/*
 * 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.
 */

#ifndef ART_DEXLAYOUT_DEX_WRITER_H_
#define ART_DEXLAYOUT_DEX_WRITER_H_

#include <functional>

#include "base/unix_file/fd_file.h"
#include "dex/compact_dex_level.h"
#include "dex_ir.h"
#include "mem_map.h"
#include "os.h"

#include <queue>

namespace art {

class DexLayout;
class DexLayoutHotnessInfo;

struct MapItem {
  // Not using DexFile::MapItemType since compact dex and standard dex file may have different
  // sections.
  MapItem() = default;
  MapItem(uint32_t type, uint32_t size, uint32_t offset)
      : type_(type), size_(size), offset_(offset) { }

  // Sort by decreasing order since the priority_queue puts largest elements first.
  bool operator>(const MapItem& other) const {
    return offset_ > other.offset_;
  }

  uint32_t type_ = 0u;
  uint32_t size_ = 0u;
  uint32_t offset_ = 0u;
};

class MapItemQueue : public
    std::priority_queue<MapItem, std::vector<MapItem>, std::greater<MapItem>> {
 public:
  void AddIfNotEmpty(const MapItem& item);
};

class DexWriter {
 public:
  DexWriter(dex_ir::Header* header,
            MemMap* mem_map,
            DexLayout* dex_layout,
            bool compute_offsets)
      : header_(header),
        mem_map_(mem_map),
        dex_layout_(dex_layout),
        compute_offsets_(compute_offsets) {}

  static void Output(dex_ir::Header* header,
                     MemMap* mem_map,
                     DexLayout* dex_layout,
                     bool compute_offsets,
                     CompactDexLevel compact_dex_level);

  virtual ~DexWriter() {}

 protected:
  void WriteMemMap();

  size_t Write(const void* buffer, size_t length, size_t offset) WARN_UNUSED;
  size_t WriteSleb128(uint32_t value, size_t offset) WARN_UNUSED;
  size_t WriteUleb128(uint32_t value, size_t offset) WARN_UNUSED;
  size_t WriteEncodedValue(dex_ir::EncodedValue* encoded_value, size_t offset) WARN_UNUSED;
  size_t WriteEncodedValueHeader(int8_t value_type, size_t value_arg, size_t offset) WARN_UNUSED;
  size_t WriteEncodedArray(dex_ir::EncodedValueVector* values, size_t offset) WARN_UNUSED;
  size_t WriteEncodedAnnotation(dex_ir::EncodedAnnotation* annotation, size_t offset) WARN_UNUSED;
  size_t WriteEncodedFields(dex_ir::FieldItemVector* fields, size_t offset) WARN_UNUSED;
  size_t WriteEncodedMethods(dex_ir::MethodItemVector* methods, size_t offset) WARN_UNUSED;

  // Header and id section
  virtual void WriteHeader();
  virtual size_t GetHeaderSize() const;
  // reserve_only means don't write, only reserve space. This is required since the string data
  // offsets must be assigned.
  uint32_t WriteStringIds(uint32_t offset, bool reserve_only);
  uint32_t WriteTypeIds(uint32_t offset);
  uint32_t WriteProtoIds(uint32_t offset, bool reserve_only);
  uint32_t WriteFieldIds(uint32_t offset);
  uint32_t WriteMethodIds(uint32_t offset);
  uint32_t WriteClassDefs(uint32_t offset, bool reserve_only);
  uint32_t WriteCallSiteIds(uint32_t offset, bool reserve_only);

  uint32_t WriteEncodedArrays(uint32_t offset);
  uint32_t WriteAnnotations(uint32_t offset);
  uint32_t WriteAnnotationSets(uint32_t offset);
  uint32_t WriteAnnotationSetRefs(uint32_t offset);
  uint32_t WriteAnnotationsDirectories(uint32_t offset);

  // Data section.
  uint32_t WriteDebugInfoItems(uint32_t offset);
  uint32_t WriteCodeItems(uint32_t offset, bool reserve_only);
  uint32_t WriteTypeLists(uint32_t offset);
  uint32_t WriteStringDatas(uint32_t offset);
  uint32_t WriteClassDatas(uint32_t offset);
  uint32_t WriteMethodHandles(uint32_t offset);
  uint32_t WriteMapItems(uint32_t offset, MapItemQueue* queue);
  uint32_t GenerateAndWriteMapItems(uint32_t offset);

  // Process an offset, if compute_offset is set, write into the dex ir item, otherwise read the
  // existing offset and use that for writing.
  void ProcessOffset(uint32_t* const offset, dex_ir::Item* item) {
    if (compute_offsets_) {
      item->SetOffset(*offset);
    } else {
      // Not computing offsets, just use the one in the item.
      *offset = item->GetOffset();
    }
  }

  dex_ir::Header* const header_;
  MemMap* const mem_map_;
  DexLayout* const dex_layout_;
  bool compute_offsets_;

 private:
  DISALLOW_COPY_AND_ASSIGN(DexWriter);
};

}  // namespace art

#endif  // ART_DEXLAYOUT_DEX_WRITER_H_
