/*
 * Copyright (C) 2011 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_DEX_FILE_INL_H_
#define ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_

#include "dex_file.h"

#include "base/casts.h"
#include "base/iteration_range.h"
#include "base/leb128.h"
#include "base/utils.h"
#include "class_iterator.h"
#include "compact_dex_file.h"
#include "dex_instruction_iterator.h"
#include "invoke_type.h"
#include "signature.h"
#include "standard_dex_file.h"

namespace art {

inline std::string_view StringViewFromUtf16Length(const char* utf8_data, size_t utf16_length) {
  size_t utf8_length = LIKELY(utf8_data[utf16_length] == 0)  // Is ASCII?
                           ? utf16_length
                           : utf16_length + strlen(utf8_data + utf16_length);
  return std::string_view(utf8_data, utf8_length);
}

inline int32_t DexFile::GetStringLength(const dex::StringId& string_id) const {
  const uint8_t* ptr = DataBegin() + string_id.string_data_off_;
  return DecodeUnsignedLeb128(&ptr);
}

inline const char* DexFile::GetStringDataAndUtf16Length(const dex::StringId& string_id,
                                                        uint32_t* utf16_length) const {
  DCHECK(utf16_length != nullptr) << GetLocation();
  const uint8_t* ptr = DataBegin() + string_id.string_data_off_;
  *utf16_length = DecodeUnsignedLeb128(&ptr);
  return reinterpret_cast<const char*>(ptr);
}

inline const char* DexFile::GetStringData(const dex::StringId& string_id) const {
  uint32_t ignored;
  return GetStringDataAndUtf16Length(string_id, &ignored);
}

inline const char* DexFile::StringDataAndUtf16LengthByIdx(dex::StringIndex idx,
                                                          uint32_t* utf16_length) const {
  if (!idx.IsValid()) {
    *utf16_length = 0;
    return nullptr;
  }
  const dex::StringId& string_id = GetStringId(idx);
  return GetStringDataAndUtf16Length(string_id, utf16_length);
}

inline const char* DexFile::StringDataByIdx(dex::StringIndex idx) const {
  uint32_t unicode_length;
  return StringDataAndUtf16LengthByIdx(idx, &unicode_length);
}

inline std::string_view DexFile::StringViewByIdx(dex::StringIndex idx) const {
  uint32_t unicode_length;
  const char* data = StringDataAndUtf16LengthByIdx(idx, &unicode_length);
  return data != nullptr ? StringViewFromUtf16Length(data, unicode_length) : std::string_view("");
}

inline const char* DexFile::StringByTypeIdx(dex::TypeIndex idx, uint32_t* unicode_length) const {
  if (!idx.IsValid()) {
    return nullptr;
  }
  const dex::TypeId& type_id = GetTypeId(idx);
  return StringDataAndUtf16LengthByIdx(type_id.descriptor_idx_, unicode_length);
}

inline const char* DexFile::StringByTypeIdx(dex::TypeIndex idx) const {
  if (!idx.IsValid()) {
    return nullptr;
  }
  const dex::TypeId& type_id = GetTypeId(idx);
  return StringDataByIdx(type_id.descriptor_idx_);
}

inline const char* DexFile::GetTypeDescriptor(const dex::TypeId& type_id) const {
  return StringDataByIdx(type_id.descriptor_idx_);
}

inline std::string_view DexFile::GetTypeDescriptorView(const dex::TypeId& type_id) const {
  return StringViewByIdx(type_id.descriptor_idx_);
}

inline const char* DexFile::GetFieldTypeDescriptor(const dex::FieldId& field_id) const {
  const dex::TypeId& type_id = GetTypeId(field_id.type_idx_);
  return GetTypeDescriptor(type_id);
}

inline std::string_view DexFile::GetFieldTypeDescriptorView(const dex::FieldId& field_id) const {
  const dex::TypeId& type_id = GetTypeId(field_id.type_idx_);
  return GetTypeDescriptorView(type_id);
}

inline const char* DexFile::GetFieldName(const dex::FieldId& field_id) const {
  return StringDataByIdx(field_id.name_idx_);
}

inline std::string_view DexFile::GetFieldNameView(const dex::FieldId& field_id) const {
  return StringViewByIdx(field_id.name_idx_);
}

inline const char* DexFile::GetMethodDeclaringClassDescriptor(const dex::MethodId& method_id)
    const {
  const dex::TypeId& type_id = GetTypeId(method_id.class_idx_);
  return GetTypeDescriptor(type_id);
}

inline const Signature DexFile::GetMethodSignature(const dex::MethodId& method_id) const {
  return Signature(this, GetProtoId(method_id.proto_idx_));
}

inline const Signature DexFile::GetProtoSignature(const dex::ProtoId& proto_id) const {
  return Signature(this, proto_id);
}

inline const char* DexFile::GetMethodName(const dex::MethodId& method_id) const {
  return StringDataByIdx(method_id.name_idx_);
}

inline const char* DexFile::GetMethodName(const dex::MethodId& method_id, uint32_t* utf_length)
    const {
  return StringDataAndUtf16LengthByIdx(method_id.name_idx_, utf_length);
}

inline const char* DexFile::GetMethodName(uint32_t idx) const {
  return StringDataByIdx(GetMethodId(idx).name_idx_);
}

inline const char* DexFile::GetMethodName(uint32_t idx, uint32_t* utf_length) const {
  return StringDataAndUtf16LengthByIdx(GetMethodId(idx).name_idx_, utf_length);
}

inline const char* DexFile::GetMethodShorty(uint32_t idx) const {
  return StringDataByIdx(GetProtoId(GetMethodId(idx).proto_idx_).shorty_idx_);
}

inline const char* DexFile::GetMethodShorty(const dex::MethodId& method_id) const {
  return StringDataByIdx(GetProtoId(method_id.proto_idx_).shorty_idx_);
}

inline const char* DexFile::GetMethodShorty(const dex::MethodId& method_id, uint32_t* length)
    const {
  // Using the UTF16 length is safe here as shorties are guaranteed to be ASCII characters.
  return StringDataAndUtf16LengthByIdx(GetProtoId(method_id.proto_idx_).shorty_idx_, length);
}

inline const char* DexFile::GetClassDescriptor(const dex::ClassDef& class_def) const {
  return StringByTypeIdx(class_def.class_idx_);
}

inline const char* DexFile::GetReturnTypeDescriptor(const dex::ProtoId& proto_id) const {
  return StringByTypeIdx(proto_id.return_type_idx_);
}

inline const char* DexFile::GetShorty(dex::ProtoIndex proto_idx) const {
  const dex::ProtoId& proto_id = GetProtoId(proto_idx);
  return StringDataByIdx(proto_id.shorty_idx_);
}

inline const dex::TryItem* DexFile::GetTryItems(const DexInstructionIterator& code_item_end,
                                                uint32_t offset) {
  return reinterpret_cast<const dex::TryItem*>
      (RoundUp(reinterpret_cast<uintptr_t>(&code_item_end.Inst()), dex::TryItem::kAlignment)) +
          offset;
}

inline bool DexFile::StringEquals(const DexFile* df1, dex::StringIndex sidx1,
                                  const DexFile* df2, dex::StringIndex sidx2) {
  uint32_t s1_len;  // Note: utf16 length != mutf8 length.
  const char* s1_data = df1->StringDataAndUtf16LengthByIdx(sidx1, &s1_len);
  uint32_t s2_len;
  const char* s2_data = df2->StringDataAndUtf16LengthByIdx(sidx2, &s2_len);
  return (s1_len == s2_len) && (strcmp(s1_data, s2_data) == 0);
}

template<typename NewLocalCallback, typename IndexToStringData, typename TypeIndexToStringData>
bool DexFile::DecodeDebugLocalInfo(const uint8_t* stream,
                                   const std::string& location,
                                   const char* declaring_class_descriptor,
                                   const std::vector<const char*>& arg_descriptors,
                                   const std::string& method_name,
                                   bool is_static,
                                   uint16_t registers_size,
                                   uint16_t ins_size,
                                   uint16_t insns_size_in_code_units,
                                   const IndexToStringData& index_to_string_data,
                                   const TypeIndexToStringData& type_index_to_string_data,
                                   const NewLocalCallback& new_local_callback) {
  if (stream == nullptr) {
    return false;
  }
  std::vector<LocalInfo> local_in_reg(registers_size);

  uint16_t arg_reg = registers_size - ins_size;
  if (!is_static) {
    const char* descriptor = declaring_class_descriptor;
    local_in_reg[arg_reg].name_ = "this";
    local_in_reg[arg_reg].descriptor_ = descriptor;
    local_in_reg[arg_reg].signature_ = nullptr;
    local_in_reg[arg_reg].start_address_ = 0;
    local_in_reg[arg_reg].reg_ = arg_reg;
    local_in_reg[arg_reg].is_live_ = true;
    arg_reg++;
  }

  DecodeUnsignedLeb128(&stream);  // Line.
  uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
  uint32_t i;
  if (parameters_size != arg_descriptors.size()) {
    LOG(ERROR) << "invalid stream - problem with parameter iterator in " << location
               << " for method " << method_name;
    return false;
  }
  for (i = 0; i < parameters_size && i < arg_descriptors.size(); ++i) {
    if (arg_reg >= registers_size) {
      LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
                 << " >= " << registers_size << ") in " << location;
      return false;
    }
    uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
    const char* descriptor = arg_descriptors[i];
    local_in_reg[arg_reg].name_ = index_to_string_data(name_idx);
    local_in_reg[arg_reg].descriptor_ = descriptor;
    local_in_reg[arg_reg].signature_ = nullptr;
    local_in_reg[arg_reg].start_address_ = 0;
    local_in_reg[arg_reg].reg_ = arg_reg;
    local_in_reg[arg_reg].is_live_ = true;
    switch (*descriptor) {
      case 'D':
      case 'J':
        arg_reg += 2;
        break;
      default:
        arg_reg += 1;
        break;
    }
  }

  uint32_t address = 0;
  for (;;)  {
    uint8_t opcode = *stream++;
    switch (opcode) {
      case DBG_END_SEQUENCE:
        // Emit all variables which are still alive at the end of the method.
        for (uint16_t reg = 0; reg < registers_size; reg++) {
          if (local_in_reg[reg].is_live_) {
            local_in_reg[reg].end_address_ = insns_size_in_code_units;
            new_local_callback(local_in_reg[reg]);
          }
        }
        return true;
      case DBG_ADVANCE_PC:
        address += DecodeUnsignedLeb128(&stream);
        break;
      case DBG_ADVANCE_LINE:
        DecodeSignedLeb128(&stream);  // Line.
        break;
      case DBG_START_LOCAL:
      case DBG_START_LOCAL_EXTENDED: {
        uint16_t reg = DecodeUnsignedLeb128(&stream);
        if (reg >= registers_size) {
          LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= "
                     << registers_size << ") in " << location;
          return false;
        }

        uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
        uint16_t descriptor_idx = DecodeUnsignedLeb128P1(&stream);
        uint32_t signature_idx = dex::kDexNoIndex;
        if (opcode == DBG_START_LOCAL_EXTENDED) {
          signature_idx = DecodeUnsignedLeb128P1(&stream);
        }

        // Emit what was previously there, if anything
        if (local_in_reg[reg].is_live_) {
          local_in_reg[reg].end_address_ = address;
          new_local_callback(local_in_reg[reg]);
        }

        local_in_reg[reg].name_ = index_to_string_data(name_idx);
        local_in_reg[reg].descriptor_ = type_index_to_string_data(descriptor_idx);;
        local_in_reg[reg].signature_ = index_to_string_data(signature_idx);
        local_in_reg[reg].start_address_ = address;
        local_in_reg[reg].reg_ = reg;
        local_in_reg[reg].is_live_ = true;
        break;
      }
      case DBG_END_LOCAL: {
        uint16_t reg = DecodeUnsignedLeb128(&stream);
        if (reg >= registers_size) {
          LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= "
                     << registers_size << ") in " << location;
          return false;
        }
        // If the register is live, close it properly. Otherwise, closing an already
        // closed register is sloppy, but harmless if no further action is taken.
        if (local_in_reg[reg].is_live_) {
          local_in_reg[reg].end_address_ = address;
          new_local_callback(local_in_reg[reg]);
          local_in_reg[reg].is_live_ = false;
        }
        break;
      }
      case DBG_RESTART_LOCAL: {
        uint16_t reg = DecodeUnsignedLeb128(&stream);
        if (reg >= registers_size) {
          LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= "
                     << registers_size << ") in " << location;
          return false;
        }
        // If the register is live, the "restart" is superfluous,
        // and we don't want to mess with the existing start address.
        if (!local_in_reg[reg].is_live_) {
          local_in_reg[reg].start_address_ = address;
          local_in_reg[reg].is_live_ = true;
        }
        break;
      }
      case DBG_SET_PROLOGUE_END:
      case DBG_SET_EPILOGUE_BEGIN:
        break;
      case DBG_SET_FILE:
        DecodeUnsignedLeb128P1(&stream);  // name.
        break;
      default:
        address += (opcode - DBG_FIRST_SPECIAL) / DBG_LINE_RANGE;
        break;
    }
  }
}

template<typename NewLocalCallback>
bool DexFile::DecodeDebugLocalInfo(uint32_t registers_size,
                                   uint32_t ins_size,
                                   uint32_t insns_size_in_code_units,
                                   uint32_t debug_info_offset,
                                   bool is_static,
                                   uint32_t method_idx,
                                   const NewLocalCallback& new_local_callback) const {
  const uint8_t* const stream = GetDebugInfoStream(debug_info_offset);
  if (stream == nullptr) {
    return false;
  }
  std::vector<const char*> arg_descriptors;
  DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx)));
  for (; it.HasNext(); it.Next()) {
    arg_descriptors.push_back(it.GetDescriptor());
  }
  return DecodeDebugLocalInfo(stream,
                              GetLocation(),
                              GetMethodDeclaringClassDescriptor(GetMethodId(method_idx)),
                              arg_descriptors,
                              this->PrettyMethod(method_idx),
                              is_static,
                              registers_size,
                              ins_size,
                              insns_size_in_code_units,
                              [this](uint32_t idx) {
                                return StringDataByIdx(dex::StringIndex(idx));
                              },
                              [this](uint32_t idx) {
                                return StringByTypeIdx(dex::TypeIndex(
                                    dchecked_integral_cast<uint16_t>(idx)));
                              },
                              new_local_callback);
}

template<typename DexDebugNewPosition, typename IndexToStringData>
bool DexFile::DecodeDebugPositionInfo(const uint8_t* stream,
                                      const IndexToStringData& index_to_string_data,
                                      const DexDebugNewPosition& position_functor) {
  if (stream == nullptr) {
    return false;
  }

  PositionInfo entry;
  entry.line_ = DecodeDebugInfoParameterNames(&stream, VoidFunctor());

  for (;;)  {
    uint8_t opcode = *stream++;
    switch (opcode) {
      case DBG_END_SEQUENCE:
        return true;  // end of stream.
      case DBG_ADVANCE_PC:
        entry.address_ += DecodeUnsignedLeb128(&stream);
        break;
      case DBG_ADVANCE_LINE:
        entry.line_ += DecodeSignedLeb128(&stream);
        break;
      case DBG_START_LOCAL:
        DecodeUnsignedLeb128(&stream);  // reg.
        DecodeUnsignedLeb128P1(&stream);  // name.
        DecodeUnsignedLeb128P1(&stream);  // descriptor.
        break;
      case DBG_START_LOCAL_EXTENDED:
        DecodeUnsignedLeb128(&stream);  // reg.
        DecodeUnsignedLeb128P1(&stream);  // name.
        DecodeUnsignedLeb128P1(&stream);  // descriptor.
        DecodeUnsignedLeb128P1(&stream);  // signature.
        break;
      case DBG_END_LOCAL:
      case DBG_RESTART_LOCAL:
        DecodeUnsignedLeb128(&stream);  // reg.
        break;
      case DBG_SET_PROLOGUE_END:
        entry.prologue_end_ = true;
        break;
      case DBG_SET_EPILOGUE_BEGIN:
        entry.epilogue_begin_ = true;
        break;
      case DBG_SET_FILE: {
        uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
        entry.source_file_ = index_to_string_data(name_idx);
        break;
      }
      default: {
        int adjopcode = opcode - DBG_FIRST_SPECIAL;
        entry.address_ += adjopcode / DBG_LINE_RANGE;
        entry.line_ += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
        if (position_functor(entry)) {
          return true;  // early exit.
        }
        entry.prologue_end_ = false;
        entry.epilogue_begin_ = false;
        break;
      }
    }
  }
}

inline const CompactDexFile* DexFile::AsCompactDexFile() const {
  DCHECK(IsCompactDexFile());
  return down_cast<const CompactDexFile*>(this);
}

inline const StandardDexFile* DexFile::AsStandardDexFile() const {
  DCHECK(IsStandardDexFile());
  return down_cast<const StandardDexFile*>(this);
}

// Get the base of the encoded data for the given DexCode.
inline const uint8_t* DexFile::GetCatchHandlerData(const DexInstructionIterator& code_item_end,
                                                   uint32_t tries_size,
                                                   uint32_t offset) {
  const uint8_t* handler_data =
      reinterpret_cast<const uint8_t*>(GetTryItems(code_item_end, tries_size));
  return handler_data + offset;
}

inline IterationRange<ClassIterator> DexFile::GetClasses() const {
  return { ClassIterator(*this, 0u), ClassIterator(*this, NumClassDefs()) };
}

// Returns the line number
template <typename Visitor>
inline uint32_t DexFile::DecodeDebugInfoParameterNames(const uint8_t** debug_info,
                                                       const Visitor& visitor) {
  uint32_t line = DecodeUnsignedLeb128(debug_info);
  const uint32_t parameters_size = DecodeUnsignedLeb128(debug_info);
  for (uint32_t i = 0; i < parameters_size; ++i) {
    visitor(dex::StringIndex(DecodeUnsignedLeb128P1(debug_info)));
  }
  return line;
}

}  // namespace art

#endif  // ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_
