/*
 * 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_LIBDEXFILE_DEX_TYPE_LOOKUP_TABLE_H_
#define ART_LIBDEXFILE_DEX_TYPE_LOOKUP_TABLE_H_

#include <android-base/logging.h>

#include "dex/dex_file_types.h"

namespace art {

class DexFile;

/**
 * TypeLookupTable used to find class_def_idx by class descriptor quickly.
 * Implementation of TypeLookupTable is based on hash table.
 * This class instantiated at compile time by calling Create() method and written into OAT file.
 * At runtime, the raw data is read from memory-mapped file by calling Open() method. The table
 * memory remains clean.
 */
class TypeLookupTable {
 public:
  // Method creates lookup table for dex file.
  static TypeLookupTable Create(const DexFile& dex_file);

  // Method opens lookup table from binary data. Lookups will traverse strings and other
  // data contained in dex_file as well.  Lookup table does not own raw_data or dex_file.
  static TypeLookupTable Open(const uint8_t* dex_data_pointer,
                              const uint8_t* raw_data,
                              uint32_t num_class_defs);

  // Create an invalid lookup table.
  TypeLookupTable()
      : dex_data_begin_(nullptr),
        mask_bits_(0u),
        entries_(nullptr),
        owned_entries_(nullptr) {}

  TypeLookupTable(TypeLookupTable&& src) noexcept = default;
  TypeLookupTable& operator=(TypeLookupTable&& src) noexcept = default;

  ~TypeLookupTable() {
    // Implicit deallocation by std::unique_ptr<> destructor.
  }

  // Returns whether the TypeLookupTable is valid.
  bool Valid() const {
    return entries_ != nullptr;
  }

  // Return the number of buckets in the lookup table.
  uint32_t Size() const {
    DCHECK(Valid());
    return 1u << mask_bits_;
  }

  // Method search class_def_idx by class descriptor and it's hash.
  // If no data found then the method returns dex::kDexNoIndex.
  uint32_t Lookup(const char* str, uint32_t hash) const;

  // Method returns pointer to binary data of lookup table. Used by the oat writer.
  const uint8_t* RawData() const {
    DCHECK(Valid());
    return reinterpret_cast<const uint8_t*>(entries_);
  }

  // Method returns length of binary data. Used by the oat writer.
  uint32_t RawDataLength() const {
    DCHECK(Valid());
    return Size() * sizeof(Entry);
  }

  // Method returns length of binary data for the specified number of class definitions.
  static uint32_t RawDataLength(uint32_t num_class_defs);

 private:
  /**
   * To find element we need to compare strings.
   * It is faster to compare first hashes and then strings itself.
   * But we have no full hash of element of table. But we can use 2 ideas.
   * 1. All minor bits of hash inside one bucket are equal.
   *    (TODO: We're not actually using this, are we?)
   * 2. If the dex file contains N classes and the size of the hash table is 2^n (where N <= 2^n)
   *    then we need n bits for the class def index and n bits for the next position delta.
   *    So we can encode part of element's hash into the remaining 32-2*n (n <= 16) bits which
   *    would be otherwise wasted as a padding.
   * So hash of element can be divided on three parts:
   *     XXXX XXXX XXXY YYYY YYYY YZZZ ZZZZ ZZZZ  (example with n=11)
   *     Z - a part of hash encoded implicitly in the bucket index
   *         (these bits are same for all elements in bucket)
   *     Y - a part of hash that we can write into free 32-2*n bits
   *     X - a part of hash that we can't use without increasing the size of the entry
   * So the `data` element of Entry is used to store the next position delta, class_def_index
   * and a part of hash of the entry.
   */
  class Entry {
   public:
    Entry() : str_offset_(0u), data_(0u) {}
    Entry(uint32_t str_offset, uint32_t hash, uint32_t class_def_index, uint32_t mask_bits)
        : str_offset_(str_offset),
          data_(((hash & ~GetMask(mask_bits)) | class_def_index) << mask_bits) {
      DCHECK_EQ(class_def_index & ~GetMask(mask_bits), 0u);
    }

    void SetNextPosDelta(uint32_t next_pos_delta, uint32_t mask_bits) {
      DCHECK_EQ(GetNextPosDelta(mask_bits), 0u);
      DCHECK_EQ(next_pos_delta & ~GetMask(mask_bits), 0u);
      DCHECK_NE(next_pos_delta, 0u);
      data_ |= next_pos_delta;
    }

    bool IsEmpty() const {
      return str_offset_ == 0u;
    }

    bool IsLast(uint32_t mask_bits) const {
      return GetNextPosDelta(mask_bits) == 0u;
    }

    uint32_t GetStringOffset() const {
      return str_offset_;
    }

    uint32_t GetNextPosDelta(uint32_t mask_bits) const {
      return data_ & GetMask(mask_bits);
    }

    uint32_t GetClassDefIdx(uint32_t mask_bits) const {
      return (data_ >> mask_bits) & GetMask(mask_bits);
    }

    uint32_t GetHashBits(uint32_t mask_bits) const {
      DCHECK_LE(mask_bits, 16u);
      return data_ >> (2u * mask_bits);
    }

    static uint32_t GetMask(uint32_t mask_bits) {
      DCHECK_LE(mask_bits, 16u);
      return ~(std::numeric_limits<uint32_t>::max() << mask_bits);
    }

   private:
    uint32_t str_offset_;
    uint32_t data_;
  };

  static uint32_t CalculateMaskBits(uint32_t num_class_defs);
  static bool SupportedSize(uint32_t num_class_defs);

  // Construct the TypeLookupTable.
  TypeLookupTable(const uint8_t* dex_data_pointer,
                  uint32_t mask_bits,
                  const Entry* entries,
                  std::unique_ptr<Entry[]> owned_entries);

  const char* GetStringData(const Entry& entry) const;

  const uint8_t* dex_data_begin_;
  uint32_t mask_bits_;
  const Entry* entries_;
  // `owned_entries_` is either null (not owning `entries_`) or same pointer as `entries_`.
  std::unique_ptr<Entry[]> owned_entries_;
};

}  // namespace art

#endif  // ART_LIBDEXFILE_DEX_TYPE_LOOKUP_TABLE_H_
