Move dex_file_verifier_test and dexlayout to ClassAccessor

Bug: 79758018
Test: test-art-host

Change-Id: I01d53eaf45d28fd762800c2716d6bf2dd3c9ad9e
diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc
index a04a234..a83a46b 100644
--- a/dexlayout/dex_ir_builder.cc
+++ b/dexlayout/dex_ir_builder.cc
@@ -21,6 +21,7 @@
 
 #include "dex_ir_builder.h"
 
+#include "dex/class_accessor-inl.h"
 #include "dex/code_item_accessors-inl.h"
 #include "dex/dex_file_exception_helpers.h"
 #include "dexlayout.h"
@@ -162,7 +163,7 @@
                                    const DexFile::CodeItem* disk_code_item,
                                    uint32_t offset,
                                    uint32_t dex_method_index);
-  ClassData* CreateClassData(const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset);
+  ClassData* CreateClassData(const DexFile& dex_file, const DexFile::ClassDef& class_def);
 
   void AddAnnotationsFromMapListSection(const DexFile& dex_file,
                                         uint32_t start_offset,
@@ -197,7 +198,7 @@
                         uint8_t length,
                         EncodedValue* item);
 
-  MethodItem GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii);
+  MethodItem GenerateMethodItem(const DexFile& dex_file, const ClassAccessor::Method& method);
 
   ParameterAnnotation* GenerateParameterAnnotation(
       const DexFile& dex_file,
@@ -488,8 +489,7 @@
   const uint8_t* static_data = dex_file.GetEncodedStaticFieldValuesArray(disk_class_def);
   EncodedArrayItem* static_values =
       CreateEncodedArrayItem(dex_file, static_data, disk_class_def.static_values_off_);
-  ClassData* class_data = CreateClassData(
-      dex_file, dex_file.GetClassData(disk_class_def), disk_class_def.class_data_off_);
+  ClassData* class_data = CreateClassData(dex_file, disk_class_def);
   CreateAndAddIndexedItem(header_->ClassDefs(),
                           header_->ClassDefs().GetOffset() + i * ClassDef::ItemSize(),
                           i,
@@ -894,36 +894,43 @@
   return code_item;
 }
 
-ClassData* BuilderMaps::CreateClassData(
-    const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset) {
+ClassData* BuilderMaps::CreateClassData(const DexFile& dex_file,
+                                        const DexFile::ClassDef& class_def) {
   // Read the fields and methods defined by the class, resolving the circular reference from those
   // to classes by setting class at the same time.
+  const uint32_t offset = class_def.class_data_off_;
   ClassData* class_data = class_datas_map_.GetExistingObject(offset);
-  if (class_data == nullptr && encoded_data != nullptr) {
-    ClassDataItemIterator cdii(dex_file, encoded_data);
+  if (class_data == nullptr && offset != 0u) {
+    ClassAccessor accessor(dex_file, class_def);
     // Static fields.
     FieldItemVector* static_fields = new FieldItemVector();
-    for (; cdii.HasNextStaticField(); cdii.Next()) {
-      FieldId* field_item = header_->FieldIds()[cdii.GetMemberIndex()];
-      uint32_t access_flags = cdii.GetRawMemberAccessFlags();
+    for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
+      FieldId* field_item = header_->FieldIds()[field.GetIndex()];
+      uint32_t access_flags = field.GetRawAccessFlags();
       static_fields->emplace_back(access_flags, field_item);
     }
-    // Instance fields.
     FieldItemVector* instance_fields = new FieldItemVector();
-    for (; cdii.HasNextInstanceField(); cdii.Next()) {
-      FieldId* field_item = header_->FieldIds()[cdii.GetMemberIndex()];
-      uint32_t access_flags = cdii.GetRawMemberAccessFlags();
+    for (const ClassAccessor::Field& field : accessor.GetInstanceFields()) {
+      FieldId* field_item = header_->FieldIds()[field.GetIndex()];
+      uint32_t access_flags = field.GetRawAccessFlags();
       instance_fields->emplace_back(access_flags, field_item);
     }
     // Direct methods.
     MethodItemVector* direct_methods = new MethodItemVector();
-    for (; cdii.HasNextDirectMethod(); cdii.Next()) {
-      direct_methods->push_back(GenerateMethodItem(dex_file, cdii));
+    auto direct_methods_it = accessor.GetDirectMethods();
+    for (auto it = direct_methods_it.begin(); it != direct_methods_it.end(); ++it) {
+      direct_methods->push_back(GenerateMethodItem(dex_file, *it));
     }
     // Virtual methods.
     MethodItemVector* virtual_methods = new MethodItemVector();
-    for (; cdii.HasNextVirtualMethod(); cdii.Next()) {
-      virtual_methods->push_back(GenerateMethodItem(dex_file, cdii));
+    auto virtual_methods_it = accessor.GetVirtualMethods();
+    const uint8_t* last_data_ptr;
+    for (auto it = virtual_methods_it.begin(); ; ++it) {
+      if (it == virtual_methods_it.end()) {
+        last_data_ptr = it->GetDataPointer();
+        break;
+      }
+      virtual_methods->push_back(GenerateMethodItem(dex_file, *it));
     }
     class_data = class_datas_map_.CreateAndAddItem(header_->ClassDatas(),
                                                    eagerly_assign_offsets_,
@@ -932,7 +939,7 @@
                                                    instance_fields,
                                                    direct_methods,
                                                    virtual_methods);
-    class_data->SetSize(cdii.EndDataPointer() - encoded_data);
+    class_data->SetSize(last_data_ptr - dex_file.GetClassData(class_def));
   }
   return class_data;
 }
@@ -1168,16 +1175,17 @@
   }
 }
 
-MethodItem BuilderMaps::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) {
-  MethodId* method_id = header_->MethodIds()[cdii.GetMemberIndex()];
-  uint32_t access_flags = cdii.GetRawMemberAccessFlags();
-  const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem();
+MethodItem BuilderMaps::GenerateMethodItem(const DexFile& dex_file,
+                                           const ClassAccessor::Method& method) {
+  MethodId* method_id = header_->MethodIds()[method.GetIndex()];
+  uint32_t access_flags = method.GetRawAccessFlags();
+  const DexFile::CodeItem* disk_code_item = method.GetCodeItem();
   // Temporary hack to prevent incorrectly deduping code items if they have the same offset since
   // they may have different debug info streams.
   CodeItem* code_item = DedupeOrCreateCodeItem(dex_file,
                                                disk_code_item,
-                                               cdii.GetMethodCodeItemOffset(),
-                                               cdii.GetMemberIndex());
+                                               method.GetCodeItemOffset(),
+                                               method.GetIndex());
   return MethodItem(access_flags, method_id, code_item);
 }
 
diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc
index 2b1352d..a20930b 100644
--- a/dexlayout/dexlayout_test.cc
+++ b/dexlayout/dexlayout_test.cc
@@ -26,6 +26,7 @@
 #include "common_runtime_test.h"
 #include "dex/art_dex_file_loader.h"
 #include "dex/base64_test_util.h"
+#include "dex/class_accessor-inl.h"
 #include "dex/code_item_accessors-inl.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_loader.h"
@@ -682,16 +683,9 @@
   MutateDexFile(temp_dex.GetFile(), GetTestDexFileName("ManyMethods"), [] (DexFile* dex) {
     bool mutated_successfully = false;
     // Change the dex instructions to make an opcode that spans past the end of the code item.
-    for (size_t i = 0; i < dex->NumClassDefs(); ++i) {
-      const DexFile::ClassDef& def = dex->GetClassDef(i);
-      const uint8_t* data = dex->GetClassData(def);
-      if (data == nullptr) {
-        continue;
-      }
-      ClassDataItemIterator it(*dex, data);
-      it.SkipAllFields();
-      while (it.HasNextMethod()) {
-        DexFile::CodeItem* item = const_cast<DexFile::CodeItem*>(it.GetMethodCodeItem());
+    for (ClassAccessor accessor : dex->GetClasses()) {
+      for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+        DexFile::CodeItem* item = const_cast<DexFile::CodeItem*>(method.GetCodeItem());
         if (item != nullptr) {
           CodeItemInstructionAccessor instructions(*dex, item);
           if (instructions.begin() != instructions.end()) {
@@ -714,7 +708,6 @@
             }
           }
         }
-        it.Next();
       }
     }
     CHECK(mutated_successfully)
diff --git a/libdexfile/dex/class_accessor.h b/libdexfile/dex/class_accessor.h
index 896fcad..9b9ac87 100644
--- a/libdexfile/dex/class_accessor.h
+++ b/libdexfile/dex/class_accessor.h
@@ -61,6 +61,10 @@
       return dex_file_;
     }
 
+    const uint8_t* GetDataPointer() const {
+      return ptr_pos_;
+    }
+
    protected:
     // Internal data pointer for reading.
     const DexFile& dex_file_;
diff --git a/libdexfile/dex/dex_file_verifier_test.cc b/libdexfile/dex/dex_file_verifier_test.cc
index 78b53a0..a22a457 100644
--- a/libdexfile/dex/dex_file_verifier_test.cc
+++ b/libdexfile/dex/dex_file_verifier_test.cc
@@ -25,6 +25,7 @@
 #include "base/leb128.h"
 #include "base/macros.h"
 #include "base64_test_util.h"
+#include "class_accessor-inl.h"
 #include "descriptors_names.h"
 #include "dex_file-inl.h"
 #include "dex_file_loader.h"
@@ -238,27 +239,10 @@
 static const uint8_t* FindMethodData(const DexFile* dex_file,
                                      const char* name,
                                      /*out*/ uint32_t* method_idx = nullptr) {
-  const DexFile::ClassDef& class_def = dex_file->GetClassDef(0);
-  const uint8_t* class_data = dex_file->GetClassData(class_def);
+  ClassAccessor accessor(*dex_file, dex_file->GetClassDef(0));
 
-  ClassDataItemIterator it(*dex_file, class_data);
-
-  const uint8_t* trailing = class_data;
-  // Need to manually decode the four entries. DataPointer() doesn't work for this, as the first
-  // element has already been loaded into the iterator.
-  DecodeUnsignedLeb128(&trailing);
-  DecodeUnsignedLeb128(&trailing);
-  DecodeUnsignedLeb128(&trailing);
-  DecodeUnsignedLeb128(&trailing);
-
-  // Skip all fields.
-  while (it.HasNextStaticField() || it.HasNextInstanceField()) {
-    trailing = it.DataPointer();
-    it.Next();
-  }
-
-  while (it.HasNextMethod()) {
-    uint32_t method_index = it.GetMemberIndex();
+  for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+    uint32_t method_index = method.GetIndex();
     dex::StringIndex name_index = dex_file->GetMethodId(method_index).name_idx_;
     const DexFile::StringId& string_id = dex_file->GetStringId(name_index);
     const char* str = dex_file->GetStringData(string_id);
@@ -266,12 +250,11 @@
       if (method_idx != nullptr) {
         *method_idx = method_index;
       }
-      DecodeUnsignedLeb128(&trailing);
+      // Go back 2 lebs to the access flags.
+      const uint8_t* trailing = ReverseSearchUnsignedLeb128(method.GetDataPointer());
+      trailing = ReverseSearchUnsignedLeb128(trailing);
       return trailing;
     }
-
-    trailing = it.DataPointer();
-    it.Next();
   }
 
   return nullptr;
@@ -849,31 +832,17 @@
 // is to the access flags, so that the caller doesn't have to handle the leb128-encoded method-index
 // delta.
 static const uint8_t* FindFieldData(const DexFile* dex_file, const char* name) {
-  const DexFile::ClassDef& class_def = dex_file->GetClassDef(0);
-  const uint8_t* class_data = dex_file->GetClassData(class_def);
+  ClassAccessor accessor(*dex_file, dex_file->GetClassDef(0));
 
-  ClassDataItemIterator it(*dex_file, class_data);
-
-  const uint8_t* trailing = class_data;
-  // Need to manually decode the four entries. DataPointer() doesn't work for this, as the first
-  // element has already been loaded into the iterator.
-  DecodeUnsignedLeb128(&trailing);
-  DecodeUnsignedLeb128(&trailing);
-  DecodeUnsignedLeb128(&trailing);
-  DecodeUnsignedLeb128(&trailing);
-
-  while (it.HasNextStaticField() || it.HasNextInstanceField()) {
-    uint32_t field_index = it.GetMemberIndex();
+  for (const ClassAccessor::Field& field : accessor.GetFields()) {
+    uint32_t field_index = field.GetIndex();
     dex::StringIndex name_index = dex_file->GetFieldId(field_index).name_idx_;
     const DexFile::StringId& string_id = dex_file->GetStringId(name_index);
     const char* str = dex_file->GetStringData(string_id);
     if (strcmp(name, str) == 0) {
-      DecodeUnsignedLeb128(&trailing);
-      return trailing;
+      // Go to the back of the access flags.
+      return ReverseSearchUnsignedLeb128(field.GetDataPointer());
     }
-
-    trailing = it.DataPointer();
-    it.Next();
   }
 
   return nullptr;