/*
 * Copyright (C) 2016 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.
 *
 * Header file of an in-memory representation of DEX files.
 */

#include <stdint.h>
#include <vector>

#include "dex_ir_builder.h"

namespace art {
namespace dex_ir {

static void CheckAndSetRemainingOffsets(const DexFile& dex_file, Collections* collections);

Header* DexIrBuilder(const DexFile& dex_file, bool eagerly_assign_offsets) {
  const DexFile::Header& disk_header = dex_file.GetHeader();
  Header* header = new Header(disk_header.magic_,
                              disk_header.checksum_,
                              disk_header.signature_,
                              disk_header.endian_tag_,
                              disk_header.file_size_,
                              disk_header.header_size_,
                              disk_header.link_size_,
                              disk_header.link_off_,
                              disk_header.data_size_,
                              disk_header.data_off_);
  Collections& collections = header->GetCollections();
  collections.SetEagerlyAssignOffsets(eagerly_assign_offsets);
  // Walk the rest of the header fields.
  // StringId table.
  collections.SetStringIdsOffset(disk_header.string_ids_off_);
  for (uint32_t i = 0; i < dex_file.NumStringIds(); ++i) {
    collections.CreateStringId(dex_file, i);
  }
  // TypeId table.
  collections.SetTypeIdsOffset(disk_header.type_ids_off_);
  for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) {
    collections.CreateTypeId(dex_file, i);
  }
  // ProtoId table.
  collections.SetProtoIdsOffset(disk_header.proto_ids_off_);
  for (uint32_t i = 0; i < dex_file.NumProtoIds(); ++i) {
    collections.CreateProtoId(dex_file, i);
  }
  // FieldId table.
  collections.SetFieldIdsOffset(disk_header.field_ids_off_);
  for (uint32_t i = 0; i < dex_file.NumFieldIds(); ++i) {
    collections.CreateFieldId(dex_file, i);
  }
  // MethodId table.
  collections.SetMethodIdsOffset(disk_header.method_ids_off_);
  for (uint32_t i = 0; i < dex_file.NumMethodIds(); ++i) {
    collections.CreateMethodId(dex_file, i);
  }
  // ClassDef table.
  collections.SetClassDefsOffset(disk_header.class_defs_off_);
  for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) {
    collections.CreateClassDef(dex_file, i);
  }
  // MapItem.
  collections.SetMapListOffset(disk_header.map_off_);
  // CallSiteIds and MethodHandleItems.
  collections.CreateCallSitesAndMethodHandles(dex_file);
  CheckAndSetRemainingOffsets(dex_file, &collections);

  // Sort the vectors by the map order (same order as the file).
  collections.SortVectorsByMapOrder();

  // Load the link data if it exists.
  collections.SetLinkData(std::vector<uint8_t>(
      dex_file.Begin() + dex_file.GetHeader().link_off_,
      dex_file.Begin() + dex_file.GetHeader().link_off_ + dex_file.GetHeader().link_size_));

  return header;
}

static void CheckAndSetRemainingOffsets(const DexFile& dex_file, Collections* collections) {
  const DexFile::Header& disk_header = dex_file.GetHeader();
  // Read MapItems and validate/set remaining offsets.
  const DexFile::MapList* map =
      reinterpret_cast<const DexFile::MapList*>(dex_file.Begin() + disk_header.map_off_);
  const uint32_t count = map->size_;
  for (uint32_t i = 0; i < count; ++i) {
    const DexFile::MapItem* item = map->list_ + i;
    switch (item->type_) {
      case DexFile::kDexTypeHeaderItem:
        CHECK_EQ(item->size_, 1u);
        CHECK_EQ(item->offset_, 0u);
        break;
      case DexFile::kDexTypeStringIdItem:
        CHECK_EQ(item->size_, collections->StringIdsSize());
        CHECK_EQ(item->offset_, collections->StringIdsOffset());
        break;
      case DexFile::kDexTypeTypeIdItem:
        CHECK_EQ(item->size_, collections->TypeIdsSize());
        CHECK_EQ(item->offset_, collections->TypeIdsOffset());
        break;
      case DexFile::kDexTypeProtoIdItem:
        CHECK_EQ(item->size_, collections->ProtoIdsSize());
        CHECK_EQ(item->offset_, collections->ProtoIdsOffset());
        break;
      case DexFile::kDexTypeFieldIdItem:
        CHECK_EQ(item->size_, collections->FieldIdsSize());
        CHECK_EQ(item->offset_, collections->FieldIdsOffset());
        break;
      case DexFile::kDexTypeMethodIdItem:
        CHECK_EQ(item->size_, collections->MethodIdsSize());
        CHECK_EQ(item->offset_, collections->MethodIdsOffset());
        break;
      case DexFile::kDexTypeClassDefItem:
        CHECK_EQ(item->size_, collections->ClassDefsSize());
        CHECK_EQ(item->offset_, collections->ClassDefsOffset());
        break;
      case DexFile::kDexTypeCallSiteIdItem:
        CHECK_EQ(item->size_, collections->CallSiteIdsSize());
        CHECK_EQ(item->offset_, collections->CallSiteIdsOffset());
        break;
      case DexFile::kDexTypeMethodHandleItem:
        CHECK_EQ(item->size_, collections->MethodHandleItemsSize());
        CHECK_EQ(item->offset_, collections->MethodHandleItemsOffset());
        break;
      case DexFile::kDexTypeMapList:
        CHECK_EQ(item->size_, 1u);
        CHECK_EQ(item->offset_, disk_header.map_off_);
        break;
      case DexFile::kDexTypeTypeList:
        collections->SetTypeListsOffset(item->offset_);
        break;
      case DexFile::kDexTypeAnnotationSetRefList:
        collections->SetAnnotationSetRefListsOffset(item->offset_);
        break;
      case DexFile::kDexTypeAnnotationSetItem:
        collections->SetAnnotationSetItemsOffset(item->offset_);
        break;
      case DexFile::kDexTypeClassDataItem:
        collections->SetClassDatasOffset(item->offset_);
        break;
      case DexFile::kDexTypeCodeItem:
        collections->SetCodeItemsOffset(item->offset_);
        break;
      case DexFile::kDexTypeStringDataItem:
        collections->SetStringDatasOffset(item->offset_);
        break;
      case DexFile::kDexTypeDebugInfoItem:
        collections->SetDebugInfoItemsOffset(item->offset_);
        break;
      case DexFile::kDexTypeAnnotationItem:
        collections->SetAnnotationItemsOffset(item->offset_);
        collections->AddAnnotationsFromMapListSection(dex_file, item->offset_, item->size_);
        break;
      case DexFile::kDexTypeEncodedArrayItem:
        collections->SetEncodedArrayItemsOffset(item->offset_);
        break;
      case DexFile::kDexTypeAnnotationsDirectoryItem:
        collections->SetAnnotationsDirectoryItemsOffset(item->offset_);
        break;
      default:
        LOG(ERROR) << "Unknown map list item type.";
    }
  }
}

}  // namespace dex_ir
}  // namespace art
