/*
 * Copyright (C) 2017 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.
 */

#ifndef ART_DEXLAYOUT_COMPACT_DEX_WRITER_H_
#define ART_DEXLAYOUT_COMPACT_DEX_WRITER_H_

#include <memory>  // For unique_ptr
#include <unordered_map>

#include "base/data_hash.h"
#include "dex_writer.h"

namespace art {

// Compact dex writer for a single dex.
class CompactDexWriter : public DexWriter {
 public:
  explicit CompactDexWriter(DexLayout* dex_layout);

 protected:
  class Deduper {
   public:
    static const uint32_t kDidNotDedupe = 0;

    explicit Deduper(DexContainer::Section* section);

    // Deduplicate a blob of data that has been written to mem_map.
    // Returns the offset of the deduplicated data or kDidNotDedupe did deduplication did not occur.
    uint32_t Dedupe(uint32_t data_start, uint32_t data_end, uint32_t item_offset);

    // Clear dedupe state to prevent deduplication against existing items in the future.
    void Clear() {
      dedupe_map_.clear();
    }

   private:
    class HashedMemoryRange {
     public:
      uint32_t offset_;
      uint32_t length_;

      class HashEqual {
       public:
        explicit HashEqual(DexContainer::Section* section) : section_(section) {}

        // Equal function.
        bool operator()(const HashedMemoryRange& a, const HashedMemoryRange& b) const {
          if (a.length_ != b.length_) {
            return false;
          }
          const uint8_t* data = Data();
          DCHECK_LE(a.offset_ + a.length_, section_->Size());
          DCHECK_LE(b.offset_ + b.length_, section_->Size());
          return std::equal(data + a.offset_, data + a.offset_ + a.length_, data + b.offset_);
        }

        // Hash function.
        size_t operator()(const HashedMemoryRange& range) const {
          DCHECK_LE(range.offset_ + range.length_, section_->Size());
          return HashBytes(Data() + range.offset_, range.length_);
        }

        ALWAYS_INLINE uint8_t* Data() const {
          return section_->Begin();
        }

       private:
        DexContainer::Section* const section_;
      };
    };

    // Dedupe map.
    std::unordered_map<HashedMemoryRange,
                       uint32_t,
                       HashedMemoryRange::HashEqual,
                       HashedMemoryRange::HashEqual> dedupe_map_;
  };

  // Handles alignment and deduping of a data section item.
  class ScopedDataSectionItem {
   public:
    ScopedDataSectionItem(Stream* stream, dex_ir::Item* item, size_t alignment, Deduper* deduper);
    ~ScopedDataSectionItem();
    size_t Written() const;

   private:
    Stream* const stream_;
    dex_ir::Item* const item_;
    const size_t alignment_;
    Deduper* deduper_;
    const uint32_t start_offset_;
  };

 public:
  class Container : public DexContainer {
   public:
    Section* GetMainSection() override {
      return &main_section_;
    }

    Section* GetDataSection() override {
      return &data_section_;
    }

    bool IsCompactDexContainer() const override {
      return true;
    }

   private:
    Container();

    VectorSection main_section_;
    VectorSection data_section_;
    Deduper data_item_dedupe_;

    friend class CompactDexWriter;
  };

 protected:
  // Return true if we can generate compact dex for the IR.
  bool CanGenerateCompactDex(std::string* error_msg);

  bool Write(DexContainer* output, std::string* error_msg) override;

  std::unique_ptr<DexContainer> CreateDexContainer() const override;

  void WriteHeader(Stream* stream) override;

  size_t GetHeaderSize() const override;

  uint32_t WriteDebugInfoOffsetTable(Stream* stream);

  void WriteCodeItem(Stream* stream, dex_ir::CodeItem* code_item, bool reserve_only) override;

  void WriteStringData(Stream* stream, dex_ir::StringData* string_data) override;

  void WriteDebugInfoItem(Stream* stream, dex_ir::DebugInfoItem* debug_info) override;

  void SortDebugInfosByMethodIndex();

  CompactDexLevel GetCompactDexLevel() const;

 private:
  // Position in the compact dex file for the debug info table data starts.
  uint32_t debug_info_offsets_pos_ = 0u;

  // Offset into the debug info table data where the lookup table is.
  uint32_t debug_info_offsets_table_offset_ = 0u;

  // Base offset of where debug info starts in the dex file.
  uint32_t debug_info_base_ = 0u;

  // Part of the shared data section owned by this file.
  uint32_t owned_data_begin_ = 0u;
  uint32_t owned_data_end_ = 0u;

  Deduper* data_item_dedupe_ = nullptr;

  DISALLOW_COPY_AND_ASSIGN(CompactDexWriter);
};

}  // namespace art

#endif  // ART_DEXLAYOUT_COMPACT_DEX_WRITER_H_
