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: DexMethodIterator(const std::vector<const DexFile * > & dex_files)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 HasNext()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 Next()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 GetDexFile()106 const DexFile& GetDexFile() { 107 CHECK(HasNext()); 108 return GetDexFileInternal(); 109 } 110 GetMemberIndex()111 uint32_t GetMemberIndex() { 112 CHECK(HasNext()); 113 return GetIterator().GetMemberIndex(); 114 } 115 GetInvokeType()116 InvokeType GetInvokeType() { 117 CHECK(HasNext()); 118 CHECK(class_def_ != NULL); 119 return GetIterator().GetMethodInvokeType(*class_def_); 120 } 121 122 private: GetIterator()123 ClassDataItemIterator& GetIterator() const { 124 CHECK(it_.get() != NULL); 125 return *it_.get(); 126 } 127 GetDexFileInternal()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