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

#ifndef ART_RUNTIME_DEX_INSTRUCTION_ITERATOR_H_
#define ART_RUNTIME_DEX_INSTRUCTION_ITERATOR_H_

#include <iterator>

#include <android-base/logging.h>

#include "dex_instruction.h"
#include "base/macros.h"

namespace art {

class DexInstructionPcPair {
 public:
  ALWAYS_INLINE const Instruction& Inst() const {
    return *Instruction::At(instructions_ + DexPc());
  }

  ALWAYS_INLINE const Instruction* operator->() const {
    return &Inst();
  }

  ALWAYS_INLINE uint32_t DexPc() const {
    return dex_pc_;
  }

  ALWAYS_INLINE const uint16_t* Instructions() const {
    return instructions_;
  }

 protected:
  explicit DexInstructionPcPair(const uint16_t* instructions, uint32_t dex_pc)
      : instructions_(instructions), dex_pc_(dex_pc) {}

  const uint16_t* instructions_ = nullptr;
  uint32_t dex_pc_ = 0;

  friend class DexInstructionIteratorBase;
  friend class DexInstructionIterator;
  friend class SafeDexInstructionIterator;
};

// Base helper class to prevent duplicated comparators.
class DexInstructionIteratorBase : public
        std::iterator<std::forward_iterator_tag, DexInstructionPcPair> {
 public:
  using value_type = std::iterator<std::forward_iterator_tag, DexInstructionPcPair>::value_type;
  using difference_type = std::iterator<std::forward_iterator_tag, value_type>::difference_type;

  DexInstructionIteratorBase() = default;
  explicit DexInstructionIteratorBase(const Instruction* inst, uint32_t dex_pc)
      : data_(reinterpret_cast<const uint16_t*>(inst), dex_pc) {}

  const Instruction& Inst() const {
    return data_.Inst();
  }

  // Return the dex pc for an iterator compared to the code item begin.
  ALWAYS_INLINE uint32_t DexPc() const {
    return data_.DexPc();
  }

  // Instructions from the start of the code item.
  ALWAYS_INLINE const uint16_t* Instructions() const {
    return data_.Instructions();
  }

 protected:
  DexInstructionPcPair data_;
};

static ALWAYS_INLINE inline bool operator==(const DexInstructionIteratorBase& lhs,
                                            const DexInstructionIteratorBase& rhs) {
  DCHECK_EQ(lhs.Instructions(), rhs.Instructions()) << "Comparing different code items.";
  return lhs.DexPc() == rhs.DexPc();
}

static inline bool operator!=(const DexInstructionIteratorBase& lhs,
                              const DexInstructionIteratorBase& rhs) {
  return !(lhs == rhs);
}

static inline bool operator<(const DexInstructionIteratorBase& lhs,
                             const DexInstructionIteratorBase& rhs) {
  DCHECK_EQ(lhs.Instructions(), rhs.Instructions()) << "Comparing different code items.";
  return lhs.DexPc() < rhs.DexPc();
}

static inline bool operator>(const DexInstructionIteratorBase& lhs,
                             const DexInstructionIteratorBase& rhs) {
  return rhs < lhs;
}

static inline bool operator<=(const DexInstructionIteratorBase& lhs,
                              const DexInstructionIteratorBase& rhs) {
  return !(rhs < lhs);
}

static inline bool operator>=(const DexInstructionIteratorBase& lhs,
                              const DexInstructionIteratorBase& rhs) {
  return !(lhs < rhs);
}

// A helper class for a code_item's instructions using range based for loop syntax.
class DexInstructionIterator : public DexInstructionIteratorBase {
 public:
  using DexInstructionIteratorBase::DexInstructionIteratorBase;

  explicit DexInstructionIterator(const uint16_t* inst, uint32_t dex_pc)
      : DexInstructionIteratorBase(Instruction::At(inst), dex_pc) {}

  explicit DexInstructionIterator(const DexInstructionPcPair& pair)
      : DexInstructionIterator(pair.Instructions(), pair.DexPc()) {}

  // Value after modification.
  DexInstructionIterator& operator++() {
    data_.dex_pc_ += Inst().SizeInCodeUnits();
    return *this;
  }

  // Value before modification.
  DexInstructionIterator operator++(int) {
    DexInstructionIterator temp = *this;
    ++*this;
    return temp;
  }

  const value_type& operator*() const {
    return data_;
  }

  const Instruction* operator->() const {
    return &data_.Inst();
  }

  // Return the dex pc for the iterator.
  ALWAYS_INLINE uint32_t DexPc() const {
    return data_.DexPc();
  }
};

// A safe version of DexInstructionIterator that is guaranteed to not go past the end of the code
// item.
class SafeDexInstructionIterator : public DexInstructionIteratorBase {
 public:
  explicit SafeDexInstructionIterator(const DexInstructionIteratorBase& start,
                                      const DexInstructionIteratorBase& end)
      : DexInstructionIteratorBase(&start.Inst(), start.DexPc())
      , num_code_units_(end.DexPc()) {
    DCHECK_EQ(start.Instructions(), end.Instructions())
        << "start and end must be in the same code item.";
  }

  // Value after modification, does not read past the end of the allowed region. May increment past
  // the end of the code item though.
  SafeDexInstructionIterator& operator++() {
    AssertValid();
    const size_t size_code_units = Inst().CodeUnitsRequiredForSizeComputation();
    const size_t available = NumCodeUnits() - DexPc();
    if (UNLIKELY(size_code_units > available)) {
      error_state_ = true;
      return *this;
    }
    const size_t instruction_code_units = Inst().SizeInCodeUnits();
    if (UNLIKELY(instruction_code_units > available)) {
      error_state_ = true;
      return *this;
    }
    data_.dex_pc_ += instruction_code_units;
    return *this;
  }

  // Value before modification.
  SafeDexInstructionIterator operator++(int) {
    SafeDexInstructionIterator temp = *this;
    ++*this;
    return temp;
  }

  const value_type& operator*() const {
    AssertValid();
    return data_;
  }

  const Instruction* operator->() const {
    AssertValid();
    return &data_.Inst();
  }

  // Return the current instruction of the iterator.
  ALWAYS_INLINE const Instruction& Inst() const {
    return data_.Inst();
  }

  const uint16_t* Instructions() const {
    return data_.Instructions();
  }

  // Returns true if the iterator is in an error state. This occurs when an instruction couldn't
  // have its size computed without reading past the end iterator.
  bool IsErrorState() const {
    return error_state_;
  }

 private:
  ALWAYS_INLINE void AssertValid() const {
    DCHECK(!IsErrorState());
    DCHECK_LT(DexPc(), NumCodeUnits());
  }

  ALWAYS_INLINE uint32_t NumCodeUnits() const {
    return num_code_units_;
  }

  const uint32_t num_code_units_ = 0;
  bool error_state_ = false;
};

}  // namespace art

#endif  // ART_RUNTIME_DEX_INSTRUCTION_ITERATOR_H_
