/*
 * Copyright (C) 2015 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_COMPILER_UTILS_TEST_DEX_FILE_BUILDER_H_
#define ART_COMPILER_UTILS_TEST_DEX_FILE_BUILDER_H_

#include <cstring>
#include <set>
#include <map>
#include <vector>
#include <zlib.h>

#include "base/bit_utils.h"
#include "base/logging.h"
#include "dex_file.h"

namespace art {

class TestDexFileBuilder {
 public:
  TestDexFileBuilder()
      : strings_(), types_(), fields_(), protos_(), dex_file_data_() {
  }

  void AddString(const std::string& str) {
    CHECK(dex_file_data_.empty());
    auto it = strings_.emplace(str, IdxAndDataOffset()).first;
    CHECK_LT(it->first.length(), 128u);  // Don't allow multi-byte length in uleb128.
  }

  void AddType(const std::string& descriptor) {
    CHECK(dex_file_data_.empty());
    AddString(descriptor);
    types_.emplace(descriptor, 0u);
  }

  void AddField(const std::string& class_descriptor, const std::string& type,
                const std::string& name) {
    CHECK(dex_file_data_.empty());
    AddType(class_descriptor);
    AddType(type);
    AddString(name);
    FieldKey key = { class_descriptor, type, name };
    fields_.emplace(key, 0u);
  }

  void AddMethod(const std::string& class_descriptor, const std::string& signature,
                 const std::string& name) {
    CHECK(dex_file_data_.empty());
    AddType(class_descriptor);
    AddString(name);

    ProtoKey proto_key = CreateProtoKey(signature);
    AddString(proto_key.shorty);
    AddType(proto_key.return_type);
    for (const auto& arg_type : proto_key.args) {
      AddType(arg_type);
    }
    auto it = protos_.emplace(proto_key, IdxAndDataOffset()).first;
    const ProtoKey* proto = &it->first;  // Valid as long as the element remains in protos_.

    MethodKey method_key = {
        class_descriptor, name, proto
    };
    methods_.emplace(method_key, 0u);
  }

  // NOTE: The builder holds the actual data, so it must live as long as the dex file.
  std::unique_ptr<const DexFile> Build(const std::string& dex_location) {
    CHECK(dex_file_data_.empty());
    union {
      uint8_t data[sizeof(DexFile::Header)];
      uint64_t force_alignment;
    } header_data;
    std::memset(header_data.data, 0, sizeof(header_data.data));
    DexFile::Header* header = reinterpret_cast<DexFile::Header*>(&header_data.data);
    std::copy_n(DexFile::kDexMagic, 4u, header->magic_);
    std::copy_n(DexFile::kDexMagicVersion, 4u, header->magic_ + 4u);
    header->header_size_ = sizeof(DexFile::Header);
    header->endian_tag_ = DexFile::kDexEndianConstant;
    header->link_size_ = 0u;  // Unused.
    header->link_off_ = 0u;  // Unused.
    header->map_off_ = 0u;  // Unused. TODO: This is wrong. Dex files created by this builder
                            //               cannot be verified. b/26808512

    uint32_t data_section_size = 0u;

    uint32_t string_ids_offset = sizeof(DexFile::Header);
    uint32_t string_idx = 0u;
    for (auto& entry : strings_) {
      entry.second.idx = string_idx;
      string_idx += 1u;
      entry.second.data_offset = data_section_size;
      data_section_size += entry.first.length() + 1u /* length */ + 1u /* null-terminator */;
    }
    header->string_ids_size_ = strings_.size();
    header->string_ids_off_ = strings_.empty() ? 0u : string_ids_offset;

    uint32_t type_ids_offset = string_ids_offset + strings_.size() * sizeof(DexFile::StringId);
    uint32_t type_idx = 0u;
    for (auto& entry : types_) {
      entry.second = type_idx;
      type_idx += 1u;
    }
    header->type_ids_size_ = types_.size();
    header->type_ids_off_ = types_.empty() ? 0u : type_ids_offset;

    uint32_t proto_ids_offset = type_ids_offset + types_.size() * sizeof(DexFile::TypeId);
    uint32_t proto_idx = 0u;
    for (auto& entry : protos_) {
      entry.second.idx = proto_idx;
      proto_idx += 1u;
      size_t num_args = entry.first.args.size();
      if (num_args != 0u) {
        entry.second.data_offset = RoundUp(data_section_size, 4u);
        data_section_size = entry.second.data_offset + 4u + num_args * sizeof(DexFile::TypeItem);
      } else {
        entry.second.data_offset = 0u;
      }
    }
    header->proto_ids_size_ = protos_.size();
    header->proto_ids_off_ = protos_.empty() ? 0u : proto_ids_offset;

    uint32_t field_ids_offset = proto_ids_offset + protos_.size() * sizeof(DexFile::ProtoId);
    uint32_t field_idx = 0u;
    for (auto& entry : fields_) {
      entry.second = field_idx;
      field_idx += 1u;
    }
    header->field_ids_size_ = fields_.size();
    header->field_ids_off_ = fields_.empty() ? 0u : field_ids_offset;

    uint32_t method_ids_offset = field_ids_offset + fields_.size() * sizeof(DexFile::FieldId);
    uint32_t method_idx = 0u;
    for (auto& entry : methods_) {
      entry.second = method_idx;
      method_idx += 1u;
    }
    header->method_ids_size_ = methods_.size();
    header->method_ids_off_ = methods_.empty() ? 0u : method_ids_offset;

    // No class defs.
    header->class_defs_size_ = 0u;
    header->class_defs_off_ = 0u;

    uint32_t data_section_offset = method_ids_offset + methods_.size() * sizeof(DexFile::MethodId);
    header->data_size_ = data_section_size;
    header->data_off_ = (data_section_size != 0u) ? data_section_offset : 0u;

    uint32_t total_size = data_section_offset + data_section_size;

    dex_file_data_.resize(total_size);

    for (const auto& entry : strings_) {
      CHECK_LT(entry.first.size(), 128u);
      uint32_t raw_offset = data_section_offset + entry.second.data_offset;
      dex_file_data_[raw_offset] = static_cast<uint8_t>(entry.first.size());
      std::memcpy(&dex_file_data_[raw_offset + 1], entry.first.c_str(), entry.first.size() + 1);
      Write32(string_ids_offset + entry.second.idx * sizeof(DexFile::StringId), raw_offset);
    }

    for (const auto& entry : types_) {
      Write32(type_ids_offset + entry.second * sizeof(DexFile::TypeId), GetStringIdx(entry.first));
      ++type_idx;
    }

    for (const auto& entry : protos_) {
      size_t num_args = entry.first.args.size();
      uint32_t type_list_offset =
          (num_args != 0u) ? data_section_offset + entry.second.data_offset : 0u;
      uint32_t raw_offset = proto_ids_offset + entry.second.idx * sizeof(DexFile::ProtoId);
      Write32(raw_offset + 0u, GetStringIdx(entry.first.shorty));
      Write16(raw_offset + 4u, GetTypeIdx(entry.first.return_type));
      Write32(raw_offset + 8u, type_list_offset);
      if (num_args != 0u) {
        CHECK_NE(entry.second.data_offset, 0u);
        Write32(type_list_offset, num_args);
        for (size_t i = 0; i != num_args; ++i) {
          Write16(type_list_offset + 4u + i * sizeof(DexFile::TypeItem),
                  GetTypeIdx(entry.first.args[i]));
        }
      }
    }

    for (const auto& entry : fields_) {
      uint32_t raw_offset = field_ids_offset + entry.second * sizeof(DexFile::FieldId);
      Write16(raw_offset + 0u, GetTypeIdx(entry.first.class_descriptor));
      Write16(raw_offset + 2u, GetTypeIdx(entry.first.type));
      Write32(raw_offset + 4u, GetStringIdx(entry.first.name));
    }

    for (const auto& entry : methods_) {
      uint32_t raw_offset = method_ids_offset + entry.second * sizeof(DexFile::MethodId);
      Write16(raw_offset + 0u, GetTypeIdx(entry.first.class_descriptor));
      auto it = protos_.find(*entry.first.proto);
      CHECK(it != protos_.end());
      Write16(raw_offset + 2u, it->second.idx);
      Write32(raw_offset + 4u, GetStringIdx(entry.first.name));
    }

    // Leave signature as zeros.

    header->file_size_ = dex_file_data_.size();

    // Write the complete header early, as part of it needs to be checksummed.
    std::memcpy(&dex_file_data_[0], header_data.data, sizeof(DexFile::Header));

    // Checksum starts after the checksum field.
    size_t skip = sizeof(header->magic_) + sizeof(header->checksum_);
    header->checksum_ = adler32(adler32(0L, Z_NULL, 0),
                                dex_file_data_.data() + skip,
                                dex_file_data_.size() - skip);

    // Write the complete header again, just simpler that way.
    std::memcpy(&dex_file_data_[0], header_data.data, sizeof(DexFile::Header));

    std::string error_msg;
    std::unique_ptr<const DexFile> dex_file(DexFile::Open(
        &dex_file_data_[0], dex_file_data_.size(), dex_location, 0u, nullptr, false, &error_msg));
    CHECK(dex_file != nullptr) << error_msg;
    return dex_file;
  }

  uint32_t GetStringIdx(const std::string& type) {
    auto it = strings_.find(type);
    CHECK(it != strings_.end());
    return it->second.idx;
  }

  uint32_t GetTypeIdx(const std::string& type) {
    auto it = types_.find(type);
    CHECK(it != types_.end());
    return it->second;
  }

  uint32_t GetFieldIdx(const std::string& class_descriptor, const std::string& type,
                       const std::string& name) {
    FieldKey key = { class_descriptor, type, name };
    auto it = fields_.find(key);
    CHECK(it != fields_.end());
    return it->second;
  }

  uint32_t GetMethodIdx(const std::string& class_descriptor, const std::string& signature,
                        const std::string& name) {
    ProtoKey proto_key = CreateProtoKey(signature);
    MethodKey method_key = { class_descriptor, name, &proto_key };
    auto it = methods_.find(method_key);
    CHECK(it != methods_.end());
    return it->second;
  }

 private:
  struct IdxAndDataOffset {
    uint32_t idx;
    uint32_t data_offset;
  };

  struct FieldKey {
    const std::string class_descriptor;
    const std::string type;
    const std::string name;
  };
  struct FieldKeyComparator {
    bool operator()(const FieldKey& lhs, const FieldKey& rhs) const {
      if (lhs.class_descriptor != rhs.class_descriptor) {
        return lhs.class_descriptor < rhs.class_descriptor;
      }
      if (lhs.name != rhs.name) {
        return lhs.name < rhs.name;
      }
      return lhs.type < rhs.type;
    }
  };

  struct ProtoKey {
    std::string shorty;
    std::string return_type;
    std::vector<std::string> args;
  };
  struct ProtoKeyComparator {
    bool operator()(const ProtoKey& lhs, const ProtoKey& rhs) const {
      if (lhs.return_type != rhs.return_type) {
        return lhs.return_type < rhs.return_type;
      }
      size_t min_args = std::min(lhs.args.size(), rhs.args.size());
      for (size_t i = 0; i != min_args; ++i) {
        if (lhs.args[i] != rhs.args[i]) {
          return lhs.args[i] < rhs.args[i];
        }
      }
      return lhs.args.size() < rhs.args.size();
    }
  };

  struct MethodKey {
    std::string class_descriptor;
    std::string name;
    const ProtoKey* proto;
  };
  struct MethodKeyComparator {
    bool operator()(const MethodKey& lhs, const MethodKey& rhs) const {
      if (lhs.class_descriptor != rhs.class_descriptor) {
        return lhs.class_descriptor < rhs.class_descriptor;
      }
      if (lhs.name != rhs.name) {
        return lhs.name < rhs.name;
      }
      return ProtoKeyComparator()(*lhs.proto, *rhs.proto);
    }
  };

  ProtoKey CreateProtoKey(const std::string& signature) {
    CHECK_EQ(signature[0], '(');
    const char* args = signature.c_str() + 1;
    const char* args_end = std::strchr(args, ')');
    CHECK(args_end != nullptr);
    const char* return_type = args_end + 1;

    ProtoKey key = {
        std::string() + ((*return_type == '[') ? 'L' : *return_type),
        return_type,
        std::vector<std::string>()
    };
    while (args != args_end) {
      key.shorty += (*args == '[') ? 'L' : *args;
      const char* arg_start = args;
      while (*args == '[') {
        ++args;
      }
      if (*args == 'L') {
        do {
          ++args;
          CHECK_NE(args, args_end);
        } while (*args != ';');
      }
      ++args;
      key.args.emplace_back(arg_start, args);
    }
    return key;
  }

  void Write32(size_t offset, uint32_t value) {
    CHECK_LE(offset + 4u, dex_file_data_.size());
    CHECK_EQ(dex_file_data_[offset + 0], 0u);
    CHECK_EQ(dex_file_data_[offset + 1], 0u);
    CHECK_EQ(dex_file_data_[offset + 2], 0u);
    CHECK_EQ(dex_file_data_[offset + 3], 0u);
    dex_file_data_[offset + 0] = static_cast<uint8_t>(value >> 0);
    dex_file_data_[offset + 1] = static_cast<uint8_t>(value >> 8);
    dex_file_data_[offset + 2] = static_cast<uint8_t>(value >> 16);
    dex_file_data_[offset + 3] = static_cast<uint8_t>(value >> 24);
  }

  void Write16(size_t offset, uint32_t value) {
    CHECK_LE(value, 0xffffu);
    CHECK_LE(offset + 2u, dex_file_data_.size());
    CHECK_EQ(dex_file_data_[offset + 0], 0u);
    CHECK_EQ(dex_file_data_[offset + 1], 0u);
    dex_file_data_[offset + 0] = static_cast<uint8_t>(value >> 0);
    dex_file_data_[offset + 1] = static_cast<uint8_t>(value >> 8);
  }

  std::map<std::string, IdxAndDataOffset> strings_;
  std::map<std::string, uint32_t> types_;
  std::map<FieldKey, uint32_t, FieldKeyComparator> fields_;
  std::map<ProtoKey, IdxAndDataOffset, ProtoKeyComparator> protos_;
  std::map<MethodKey, uint32_t, MethodKeyComparator> methods_;

  std::vector<uint8_t> dex_file_data_;
};

}  // namespace art

#endif  // ART_COMPILER_UTILS_TEST_DEX_FILE_BUILDER_H_
