Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_RUNTIME_DEX_METHOD_ITERATOR_H_
     18 #define ART_RUNTIME_DEX_METHOD_ITERATOR_H_
     19 
     20 #include <vector>
     21 
     22 #include "dex_file.h"
     23 
     24 namespace art {
     25 
     26 class DexMethodIterator {
     27  public:
     28   explicit DexMethodIterator(const std::vector<const DexFile*>& dex_files)
     29       : dex_files_(dex_files),
     30         found_next_(false),
     31         dex_file_index_(0),
     32         class_def_index_(0),
     33         class_def_(NULL),
     34         class_data_(NULL),
     35         direct_method_(false) {
     36     CHECK_NE(0U, dex_files_.size());
     37   }
     38 
     39   bool HasNext() {
     40     if (found_next_) {
     41       return true;
     42     }
     43     while (true) {
     44       // End of DexFiles, we are done.
     45       if (dex_file_index_ == dex_files_.size()) {
     46         return false;
     47       }
     48       if (class_def_index_ == GetDexFileInternal().NumClassDefs()) {
     49         // End of this DexFile, advance and retry.
     50         class_def_index_ = 0;
     51         dex_file_index_++;
     52         continue;
     53       }
     54       if (class_def_ == NULL) {
     55         class_def_ = &GetDexFileInternal().GetClassDef(class_def_index_);
     56       }
     57       if (class_data_ == NULL) {
     58         class_data_ = GetDexFileInternal().GetClassData(*class_def_);
     59         if (class_data_ == NULL) {
     60           // empty class, such as a marker interface
     61           // End of this class, advance and retry.
     62           class_def_ = NULL;
     63           class_def_index_++;
     64           continue;
     65         }
     66       }
     67       if (it_.get() == NULL) {
     68         it_.reset(new ClassDataItemIterator(GetDexFileInternal(), class_data_));
     69         // Skip fields
     70         while (GetIterator().HasNextStaticField()) {
     71           GetIterator().Next();
     72         }
     73         while (GetIterator().HasNextInstanceField()) {
     74           GetIterator().Next();
     75         }
     76         direct_method_ = true;
     77       }
     78       if (direct_method_ && GetIterator().HasNextDirectMethod()) {
     79         // Found method
     80         found_next_ = true;
     81         return true;
     82       }
     83       direct_method_ = false;
     84       if (GetIterator().HasNextVirtualMethod()) {
     85         // Found method
     86         found_next_ = true;
     87         return true;
     88       }
     89       // End of this class, advance and retry.
     90       DCHECK(!GetIterator().HasNext());
     91       it_.reset(NULL);
     92       class_data_ = NULL;
     93       class_def_ = NULL;
     94       class_def_index_++;
     95     }
     96   }
     97 
     98   void Next() {
     99     found_next_ = false;
    100     if (it_.get() != NULL) {
    101       // Advance to next method if we currently are looking at a class.
    102       GetIterator().Next();
    103     }
    104   }
    105 
    106   const DexFile& GetDexFile() {
    107     CHECK(HasNext());
    108     return GetDexFileInternal();
    109   }
    110 
    111   uint32_t GetMemberIndex() {
    112     CHECK(HasNext());
    113     return GetIterator().GetMemberIndex();
    114   }
    115 
    116   InvokeType GetInvokeType() {
    117     CHECK(HasNext());
    118     CHECK(class_def_ != NULL);
    119     return GetIterator().GetMethodInvokeType(*class_def_);
    120   }
    121 
    122  private:
    123   ClassDataItemIterator& GetIterator() const {
    124     CHECK(it_.get() != NULL);
    125     return *it_.get();
    126   }
    127 
    128   const DexFile& GetDexFileInternal() const {
    129     CHECK_LT(dex_file_index_, dex_files_.size());
    130     const DexFile* dex_file = dex_files_[dex_file_index_];
    131     CHECK(dex_file != NULL);
    132     return *dex_file;
    133   }
    134 
    135   const std::vector<const DexFile*>& dex_files_;
    136 
    137   bool found_next_;
    138 
    139   uint32_t dex_file_index_;
    140   uint32_t class_def_index_;
    141   const DexFile::ClassDef* class_def_;
    142   const byte* class_data_;
    143   UniquePtr<ClassDataItemIterator> it_;
    144   bool direct_method_;
    145 };
    146 
    147 }  // namespace art
    148 
    149 #endif  // ART_RUNTIME_DEX_METHOD_ITERATOR_H_
    150