/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_H_
#define ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_H_

#include "code_item_accessors.h"
#include "dex_file.h"
#include "invoke_type.h"
#include "method_reference.h"
#include "modifiers.h"

namespace art {

class ClassIteratorData;

// Classes to access Dex data.
class ClassAccessor {
 public:
  class BaseItem {
   public:
    explicit BaseItem(const DexFile& dex_file,
                      const uint8_t* ptr_pos,
                      const uint8_t* hiddenapi_ptr_pos)
        : dex_file_(dex_file), ptr_pos_(ptr_pos), hiddenapi_ptr_pos_(hiddenapi_ptr_pos) {}

    uint32_t GetIndex() const {
      return index_;
    }

    uint32_t GetAccessFlags() const {
      return access_flags_;
    }

    uint32_t GetHiddenapiFlags() const {
      return hiddenapi_flags_;
    }

    bool IsFinal() const {
      return (GetAccessFlags() & kAccFinal) != 0;
    }

    const DexFile& GetDexFile() const {
      return dex_file_;
    }

    const uint8_t* GetDataPointer() const {
      return ptr_pos_;
    }

    bool MemberIsNative() const {
      return GetAccessFlags() & kAccNative;
    }

    bool MemberIsFinal() const {
      return GetAccessFlags() & kAccFinal;
    }

   protected:
    // Internal data pointer for reading.
    const DexFile& dex_file_;
    const uint8_t* ptr_pos_ = nullptr;
    const uint8_t* hiddenapi_ptr_pos_ = nullptr;
    uint32_t index_ = 0u;
    uint32_t access_flags_ = 0u;
    uint32_t hiddenapi_flags_ = 0u;
  };

  // A decoded version of the method of a class_data_item.
  class Method : public BaseItem {
   public:
    uint32_t GetCodeItemOffset() const {
      return code_off_;
    }

    InvokeType GetInvokeType(uint32_t class_access_flags) const {
      return is_static_or_direct_
          ? GetDirectMethodInvokeType()
          : GetVirtualMethodInvokeType(class_access_flags);
    }

    MethodReference GetReference() const {
      return MethodReference(&dex_file_, GetIndex());
    }

    CodeItemInstructionAccessor GetInstructions() const;
    CodeItemDataAccessor GetInstructionsAndData() const;

    const dex::CodeItem* GetCodeItem() const;

    bool IsStaticOrDirect() const {
      return is_static_or_direct_;
    }

   private:
    Method(const DexFile& dex_file,
           const uint8_t* ptr_pos,
           const uint8_t* hiddenapi_ptr_pos = nullptr,
           bool is_static_or_direct = true)
        : BaseItem(dex_file, ptr_pos, hiddenapi_ptr_pos),
          is_static_or_direct_(is_static_or_direct) {}

    void Read();

    InvokeType GetDirectMethodInvokeType() const {
      return (GetAccessFlags() & kAccStatic) != 0 ? kStatic : kDirect;
    }

    InvokeType GetVirtualMethodInvokeType(uint32_t class_access_flags) const {
      DCHECK_EQ(GetAccessFlags() & kAccStatic, 0U);
      if ((class_access_flags & kAccInterface) != 0) {
        return kInterface;
      } else if ((GetAccessFlags() & kAccConstructor) != 0) {
        return kSuper;
      } else {
        return kVirtual;
      }
    }

    // Move to virtual method section.
    void NextSection() {
      DCHECK(is_static_or_direct_) << "Already in the virtual methods section";
      is_static_or_direct_ = false;
      index_ = 0u;
    }

    bool is_static_or_direct_ = true;
    uint32_t code_off_ = 0u;

    friend class ClassAccessor;
    friend class DexFileVerifier;
  };

  // A decoded version of the field of a class_data_item.
  class Field : public BaseItem {
   public:
    Field(const DexFile& dex_file,
          const uint8_t* ptr_pos,
          const uint8_t* hiddenapi_ptr_pos = nullptr)
        : BaseItem(dex_file, ptr_pos, hiddenapi_ptr_pos) {}

    bool IsStatic() const {
     return is_static_;
    }

   private:
    void Read();

    // Move to instance fields section.
    void NextSection() {
      index_ = 0u;
      is_static_ = false;
    }

    bool is_static_ = true;
    friend class ClassAccessor;
    friend class DexFileVerifier;
  };

  template <typename DataType>
  class DataIterator : public std::iterator<std::forward_iterator_tag, DataType> {
   public:
    using value_type = typename std::iterator<std::forward_iterator_tag, DataType>::value_type;
    using difference_type =
        typename std::iterator<std::forward_iterator_tag, value_type>::difference_type;

    DataIterator(const DexFile& dex_file,
                 uint32_t position,
                 uint32_t partition_pos,
                 uint32_t iterator_end,
                 const uint8_t* ptr_pos,
                 const uint8_t* hiddenapi_ptr_pos)
        : data_(dex_file, ptr_pos, hiddenapi_ptr_pos),
          position_(position),
          partition_pos_(partition_pos),
          iterator_end_(iterator_end) {
      ReadData();
    }

    bool IsValid() const {
      return position_ < iterator_end_;
    }

    // Value after modification.
    DataIterator& operator++() {
      ++position_;
      ReadData();
      return *this;
    }

    const value_type& operator*() const {
      return data_;
    }

    const value_type* operator->() const {
      return &data_;
    }

    bool operator==(const DataIterator& rhs) const {
      DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files.";
      return position_ == rhs.position_;
    }

    bool operator!=(const DataIterator& rhs) const {
      return !(*this == rhs);
    }

    bool operator<(const DataIterator& rhs) const {
      DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files.";
      return position_ < rhs.position_;
    }

    bool operator>(const DataIterator& rhs) const {
      return rhs < *this;
    }

    bool operator<=(const DataIterator& rhs) const {
      return !(rhs < *this);
    }

    bool operator>=(const DataIterator& rhs) const {
      return !(*this < rhs);
    }

    const uint8_t* GetDataPointer() const {
      return data_.ptr_pos_;
    }

   private:
    // Read data at current position.
    void ReadData() {
      if (IsValid()) {
        // At the end of the first section, go to the next section.
        if (position_ == partition_pos_) {
          data_.NextSection();
        }
        data_.Read();
      }
    }

    DataType data_;
    // Iterator position.
    uint32_t position_;
    // At partition_pos_, we go to the next section.
    const uint32_t partition_pos_;
    // At iterator_end_, the iterator is no longer valid.
    const uint32_t iterator_end_;

    friend class DexFileVerifier;
  };

  // Not explicit specifically for range-based loops.
  ALWAYS_INLINE ClassAccessor(const ClassIteratorData& data);  // NOLINT [runtime/explicit] [5]

  ALWAYS_INLINE ClassAccessor(const DexFile& dex_file,
                              const dex::ClassDef& class_def,
                              bool parse_hiddenapi_class_data = false);

  ALWAYS_INLINE ClassAccessor(const DexFile& dex_file, uint32_t class_def_index);

  ClassAccessor(const DexFile& dex_file,
                const uint8_t* class_data,
                uint32_t class_def_index = DexFile::kDexNoIndex32,
                bool parse_hiddenapi_class_data = false);

  // Return the code item for a method.
  const dex::CodeItem* GetCodeItem(const Method& method) const;

  // Iterator data is not very iterator friendly, use visitors to get around this.
  template <typename StaticFieldVisitor,
            typename InstanceFieldVisitor,
            typename DirectMethodVisitor,
            typename VirtualMethodVisitor>
  void VisitFieldsAndMethods(const StaticFieldVisitor& static_field_visitor,
                             const InstanceFieldVisitor& instance_field_visitor,
                             const DirectMethodVisitor& direct_method_visitor,
                             const VirtualMethodVisitor& virtual_method_visitor) const;

  template <typename DirectMethodVisitor,
            typename VirtualMethodVisitor>
  void VisitMethods(const DirectMethodVisitor& direct_method_visitor,
                    const VirtualMethodVisitor& virtual_method_visitor) const;

  template <typename StaticFieldVisitor,
            typename InstanceFieldVisitor>
  void VisitFields(const StaticFieldVisitor& static_field_visitor,
                   const InstanceFieldVisitor& instance_field_visitor) const;

  // Return the iteration range for all the fields.
  IterationRange<DataIterator<Field>> GetFields() const;

  // Return the iteration range for all the static fields.
  IterationRange<DataIterator<Field>> GetStaticFields() const;

  // Return the iteration range for all the instance fields.
  IterationRange<DataIterator<Field>> GetInstanceFields() const;

  // Return the iteration range for all the methods.
  IterationRange<DataIterator<Method>> GetMethods() const;

  // Return the iteration range for the direct methods.
  IterationRange<DataIterator<Method>> GetDirectMethods() const;

  // Return the iteration range for the virtual methods.
  IterationRange<DataIterator<Method>> GetVirtualMethods() const;

  uint32_t NumStaticFields() const {
    return num_static_fields_;
  }

  uint32_t NumInstanceFields() const {
    return num_instance_fields_;
  }

  uint32_t NumFields() const {
    return NumStaticFields() + NumInstanceFields();
  }

  uint32_t NumDirectMethods() const {
    return num_direct_methods_;
  }

  uint32_t NumVirtualMethods() const {
    return num_virtual_methods_;
  }

  uint32_t NumMethods() const {
    return NumDirectMethods() + NumVirtualMethods();
  }

  const char* GetDescriptor() const;

  dex::TypeIndex GetClassIdx() const;

  const DexFile& GetDexFile() const {
    return dex_file_;
  }

  bool HasClassData() const {
    return ptr_pos_ != nullptr;
  }

  bool HasHiddenapiClassData() const {
    return hiddenapi_ptr_pos_ != nullptr;
  }

  uint32_t GetClassDefIndex() const {
    return class_def_index_;
  }

  const dex::ClassDef& GetClassDef() const {
    return dex_file_.GetClassDef(GetClassDefIndex());
  }

 protected:
  // Template visitor to reduce copy paste for visiting elements.
  // No thread safety analysis since the visitor may require capabilities.
  template <typename DataType, typename Visitor>
  void VisitMembers(size_t count, const Visitor& visitor, DataType* data) const
      NO_THREAD_SAFETY_ANALYSIS;

  // Return an iteration range for the first <count> fields.
  IterationRange<DataIterator<Field>> GetFieldsInternal(size_t count) const;

  // Return an iteration range for the first <count> methods.
  IterationRange<DataIterator<Method>> GetMethodsInternal(size_t count) const;

  const DexFile& dex_file_;
  const uint32_t class_def_index_;
  const uint8_t* ptr_pos_ = nullptr;  // Pointer into stream of class_data_item.
  const uint8_t* hiddenapi_ptr_pos_ = nullptr;  // Pointer into stream of hiddenapi_metadata.
  const uint32_t num_static_fields_ = 0u;
  const uint32_t num_instance_fields_ = 0u;
  const uint32_t num_direct_methods_ = 0u;
  const uint32_t num_virtual_methods_ = 0u;

  friend class DexFileVerifier;
};

}  // namespace art

#endif  // ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_H_
