/*
 * Copyright (C) 2013 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_RUNTIME_MAPPING_TABLE_H_
#define ART_RUNTIME_MAPPING_TABLE_H_

#include "base/leb128.h"
#include "base/logging.h"

namespace art {

// A utility for processing the raw uleb128 encoded mapping table created by the quick compiler.
class MappingTable {
 public:
  explicit MappingTable(const uint8_t* encoded_map) : encoded_table_(encoded_map) {
  }

  uint32_t TotalSize() const PURE {
    const uint8_t* table = encoded_table_;
    if (table == nullptr) {
      return 0;
    } else {
      return DecodeUnsignedLeb128(&table);
    }
  }

  uint32_t DexToPcSize() const PURE {
    const uint8_t* table = encoded_table_;
    if (table == nullptr) {
      return 0;
    } else {
      uint32_t total_size = DecodeUnsignedLeb128(&table);
      uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table);
      return total_size - pc_to_dex_size;
    }
  }

  const uint8_t* FirstDexToPcPtr() const {
    const uint8_t* table = encoded_table_;
    if (table != nullptr) {
      uint32_t total_size = DecodeUnsignedLeb128(&table);
      uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table);
      // We must have dex to pc entries or else the loop will go beyond the end of the table.
      DCHECK_GT(total_size, pc_to_dex_size);
      for (uint32_t i = 0; i < pc_to_dex_size; ++i) {
        DecodeUnsignedLeb128(&table);  // Move ptr past native PC delta.
        DecodeSignedLeb128(&table);  // Move ptr past dex PC delta.
      }
    }
    return table;
  }

  class DexToPcIterator {
   public:
    DexToPcIterator(const MappingTable* table, uint32_t element) :
        table_(table), element_(element), end_(table_->DexToPcSize()), encoded_table_ptr_(nullptr),
        native_pc_offset_(0), dex_pc_(0) {
      if (element == 0) {  // An iterator wanted from the start.
        if (end_ > 0) {
          encoded_table_ptr_ = table_->FirstDexToPcPtr();
          native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
          // First delta is always positive.
          dex_pc_ = static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_));
        }
      } else {  // An iterator wanted from the end.
        DCHECK_EQ(table_->DexToPcSize(), element);
      }
    }
    uint32_t NativePcOffset() const {
      return native_pc_offset_;
    }
    uint32_t DexPc() const {
      return dex_pc_;
    }
    void operator++() {
      ++element_;
      if (element_ != end_) {  // Avoid reading beyond the end of the table.
        native_pc_offset_ += DecodeUnsignedLeb128(&encoded_table_ptr_);
        // For negative delta, unsigned overflow after static_cast does exactly what we need.
        dex_pc_ += static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_));
      }
    }
    bool operator==(const DexToPcIterator& rhs) const {
      CHECK(table_ == rhs.table_);
      return element_ == rhs.element_;
    }
    bool operator!=(const DexToPcIterator& rhs) const {
      CHECK(table_ == rhs.table_);
      return element_ != rhs.element_;
    }

   private:
    const MappingTable* const table_;  // The original table.
    uint32_t element_;  // A value in the range 0 to end_.
    const uint32_t end_;  // Equal to table_->DexToPcSize().
    const uint8_t* encoded_table_ptr_;  // Either null or points to encoded data after this entry.
    uint32_t native_pc_offset_;  // The current value of native pc offset.
    uint32_t dex_pc_;  // The current value of dex pc.
  };

  DexToPcIterator DexToPcBegin() const {
    return DexToPcIterator(this, 0);
  }

  DexToPcIterator DexToPcEnd() const {
    uint32_t size = DexToPcSize();
    return DexToPcIterator(this, size);
  }

  uint32_t PcToDexSize() const PURE {
    const uint8_t* table = encoded_table_;
    if (table == nullptr) {
      return 0;
    } else {
      DecodeUnsignedLeb128(&table);  // Total_size, unused.
      uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table);
      return pc_to_dex_size;
    }
  }

  const uint8_t* FirstPcToDexPtr() const {
    const uint8_t* table = encoded_table_;
    if (table != nullptr) {
      DecodeUnsignedLeb128(&table);  // Total_size, unused.
      DecodeUnsignedLeb128(&table);  // PC to Dex size, unused.
    }
    return table;
  }

  class PcToDexIterator {
   public:
    PcToDexIterator(const MappingTable* table, uint32_t element) :
        table_(table), element_(element), end_(table_->PcToDexSize()), encoded_table_ptr_(nullptr),
        native_pc_offset_(0), dex_pc_(0) {
      if (element == 0) {  // An iterator wanted from the start.
        if (end_ > 0) {
          encoded_table_ptr_ = table_->FirstPcToDexPtr();
          native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
          // First delta is always positive.
          dex_pc_ = static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_));
        }
      } else {  // An iterator wanted from the end.
        DCHECK_EQ(table_->PcToDexSize(), element);
      }
    }
    uint32_t NativePcOffset() const {
      return native_pc_offset_;
    }
    uint32_t DexPc() const {
      return dex_pc_;
    }
    void operator++() {
      ++element_;
      if (element_ != end_) {  // Avoid reading beyond the end of the table.
        native_pc_offset_ += DecodeUnsignedLeb128(&encoded_table_ptr_);
        // For negative delta, unsigned overflow after static_cast does exactly what we need.
        dex_pc_ += static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_));
      }
    }
    bool operator==(const PcToDexIterator& rhs) const {
      CHECK(table_ == rhs.table_);
      return element_ == rhs.element_;
    }
    bool operator!=(const PcToDexIterator& rhs) const {
      CHECK(table_ == rhs.table_);
      return element_ != rhs.element_;
    }

   private:
    const MappingTable* const table_;  // The original table.
    uint32_t element_;  // A value in the range 0 to PcToDexSize.
    const uint32_t end_;  // Equal to table_->PcToDexSize().
    const uint8_t* encoded_table_ptr_;  // Either null or points to encoded data after this entry.
    uint32_t native_pc_offset_;  // The current value of native pc offset.
    uint32_t dex_pc_;  // The current value of dex pc.
  };

  PcToDexIterator PcToDexBegin() const {
    return PcToDexIterator(this, 0);
  }

  PcToDexIterator PcToDexEnd() const {
    uint32_t size = PcToDexSize();
    return PcToDexIterator(this, size);
  }

 private:
  const uint8_t* const encoded_table_;
};

}  // namespace art

#endif  // ART_RUNTIME_MAPPING_TABLE_H_
