// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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.

// RagneMap maps
//
//   [uint64_t, uint64_t) -> std::string, [optional other range base]
//
// where ranges must be non-overlapping.
//
// This is used to map the address space (either pointer offsets or file
// offsets).
//
// The other range base allows us to use this RangeMap to translate addresses
// from this domain to another one (like vm_addr -> file_addr or vice versa).
//
// This type is only exposed in the .h file for unit testing purposes.

#ifndef BLOATY_RANGE_MAP_H_
#define BLOATY_RANGE_MAP_H_

#include <assert.h>
#include <stdint.h>

#include <exception>
#include <map>
#include <vector>

#include "absl/strings/str_cat.h"

namespace bloaty {

class RangeMapTest;

class RangeMap {
 public:
  RangeMap() = default;
  RangeMap(RangeMap&& other) = default;
  RangeMap& operator=(RangeMap&& other) = default;
  RangeMap(RangeMap& other) = delete;
  RangeMap& operator=(RangeMap& other) = delete;

  // Adds a range to this map.
  void AddRange(uint64_t addr, uint64_t size, const std::string& val);

  // Adds a range to this map (in domain D1) that also corresponds to a
  // different range in a different map (in domain D2).  The correspondance will
  // be noted to allow us to translate into the other domain later.
  void AddDualRange(uint64_t addr, uint64_t size, uint64_t otheraddr,
                    const std::string& val);

  // Adds a range to this map (in domain D1), and also adds corresponding ranges
  // to |other| (in domain D2), using |translator| (in domain D1) to translate
  // D1->D2.  The translation is performed using information from previous
  // AddDualRange() calls on |translator|.
  //
  // Returns true if the entire range [addr, size] was present in the
  // |translator| map.  (This does not necessarily mean that every part of the
  // range was actually translated).  If the return value is false, then the
  // contents of |this| and |other| are undefined (Bloaty will bail in this
  // case).
  bool AddRangeWithTranslation(uint64_t addr, uint64_t size,
                               const std::string& val,
                               const RangeMap& translator, bool verbose,
                               RangeMap* other);

  // Returns whether this RangeMap fully covers the given range.
  bool CoversRange(uint64_t addr, uint64_t size) const;

  // Translates |addr| into the other domain, returning |true| if this was
  // successful.
  bool Translate(uint64_t addr, uint64_t *translated) const;

  // Looks for a range within this map that contains |addr|.  If found, returns
  // true and sets |label| to the corresponding label, and |offset| to the
  // offset from the beginning of this range.
  bool TryGetLabel(uint64_t addr, std::string* label, uint64_t* offset) const;

  // Looks for a range that starts exactly on |addr|.  If it exists, returns
  // true and sets |size| to its size.
  bool TryGetSize(uint64_t addr, uint64_t* size) const;

  std::string DebugString() const;

  static std::string EntryDebugString(uint64_t addr, uint64_t size,
                                      uint64_t other_start,
                                      const std::string& label) {
    std::string end =
        size == kUnknownSize ? "?" : absl::StrCat(absl::Hex(addr + size));
    std::string ret = absl::StrCat("[", absl::Hex(addr), ", ", end,
                                   "] (size=", absl::Hex(size), "): ", label);
    if (other_start != UINT64_MAX) {
      absl::StrAppend(&ret, ", other_start=", absl::Hex(other_start));
    }
    return ret;
  }

  template <class T>
  std::string EntryDebugString(T it) const {
    if (it == mappings_.end()) {
      return "[end]";
    } else {
      return EntryDebugString(it->first, it->second.size,
                              it->second.other_start, it->second.label);
    }
  }

  template <class Func>
  static void ComputeRollup(const std::vector<const RangeMap*>& range_maps,
                            Func func);

  template <class Func>
  void ForEachRange(Func func) const {
    for (auto iter = mappings_.begin(); iter != mappings_.end(); ++iter) {
      func(iter->first, RangeEnd(iter) - iter->first);
    }
  }

  template <class Func>
  void ForEachRangeWithStart(uint64_t start, Func func) const {
    for (auto iter = FindContaining(start); iter != mappings_.end(); ++iter) {
      if (!func(iter->second.label, iter->first,
                RangeEnd(iter) - iter->first)) {
        return;
      }
    }
  }

  static const uint64_t kUnknownSize = UINT64_MAX;

 private:
  friend class RangeMapTest;
  static const uint64_t kNoTranslation = UINT64_MAX;

  struct Entry {
    Entry(const std::string& label_, uint64_t size_, uint64_t other_)
        : label(label_), size(size_), other_start(other_) {}
    std::string label;
    uint64_t size;
    uint64_t other_start;  // kNoTranslation if there is no mapping.

    bool HasTranslation() const { return other_start != kNoTranslation; }
  };

  typedef std::map<uint64_t, Entry> Map;
  Map mappings_;

  template <class T>
  void CheckConsistency(T iter) const {
    assert(iter->first + iter->second.size > iter->first);
    assert(iter == mappings_.begin() ||
           RangeEnd(std::prev(iter)) <= iter->first);
    assert(std::next(iter) == mappings_.end() ||
           RangeEnd(iter) <= std::next(iter)->first);
  }

  template <class T>
  bool EntryContains(T iter, uint64_t addr) const {
    return addr >= iter->first && addr < RangeEnd(iter);
  }

  template <class T>
  bool EntryContainsStrict(T iter, uint64_t addr) const {
    if (iter->second.size == kUnknownSize) {
      return iter->first == addr;
    } else {
      return addr >= iter->first && addr < RangeEnd(iter);
    }
  }

  template <class T>
  void MaybeSetLabel(T iter, const std::string& label, uint64_t addr,
                     uint64_t end);

  // When the size is unknown return |unknown| for the end.
  uint64_t RangeEndUnknownLimit(Map::const_iterator iter,
                                uint64_t unknown) const {
    if (iter->second.size == kUnknownSize) {
      Map::const_iterator next = std::next(iter);
      if (IterIsEnd(next) || next->first > unknown) {
        return unknown;
      } else {
        return next->first;
      }
    } else {
      uint64_t ret = iter->first + iter->second.size;
      assert(ret > iter->first);
      return ret;
    }
  }

  uint64_t RangeEnd(Map::const_iterator iter) const {
    return RangeEndUnknownLimit(iter, UINT64_MAX);
  }

  bool IterIsEnd(Map::const_iterator iter) const {
    return iter == mappings_.end();
  }

  template <class T>
  uint64_t TranslateWithEntry(T iter, uint64_t addr) const;

  template <class T>
  bool TranslateAndTrimRangeWithEntry(T iter, uint64_t addr, uint64_t size,
                                      uint64_t* trimmed_addr,
                                      uint64_t* translated_addr,
                                      uint64_t* trimmed_size) const;

  // Finds the entry that contains |addr|.  If no such mapping exists, returns
  // mappings_.end().
  Map::const_iterator FindContaining(uint64_t addr) const;

  // Finds the entry that contains |addr|, or the very next entry (which may be
  // mappings_.end()).
  Map::iterator FindContainingOrAfter(uint64_t addr);
  Map::const_iterator FindContainingOrAfter(uint64_t addr) const;
};

template <class Func>
void RangeMap::ComputeRollup(const std::vector<const RangeMap*>& range_maps,
                             Func func) {
  assert(range_maps.size() > 0);
  std::vector<Map::const_iterator> iters;

  if (range_maps[0]->mappings_.empty()) {
    for (int i = 0; i < range_maps.size(); i++) {
      const RangeMap* range_map = range_maps[i];
      if (!range_map->mappings_.empty()) {
        printf(
            "Error, range (%s) exists at index %d, but base map is empty\n",
            range_map->EntryDebugString(range_map->mappings_.begin()).c_str(),
            i);
        assert(false);
        throw std::runtime_error("Range extends beyond base map.");
      }
    }
    return;
  }

  for (auto range_map : range_maps) {
    iters.push_back(range_map->mappings_.begin());
  }

  // Iterate over all ranges in parallel to perform this transformation:
  //
  //   -----  -----  -----             ---------------
  //     |      |      1                    A,X,1
  //     |      X    -----             ---------------
  //     |      |      |                    A,X,2
  //     A    -----    |               ---------------
  //     |      |      |                      |
  //     |      |      2      ----->          |
  //     |      Y      |                    A,Y,2
  //     |      |      |                      |
  //   -----    |      |               ---------------
  //     B      |      |                    B,Y,2
  //   -----  -----  -----             ---------------
  //
  //
  //   -----  -----  -----             ---------------
  //     C      Z      3                    C,Z,3
  //   -----  -----  -----             ---------------
  //
  // All input maps must cover exactly the same domain.

  // Outer loop: once per continuous (gapless) region.
  while (true) {
    std::vector<std::string> keys;
    uint64_t current = 0;

    if (range_maps[0]->IterIsEnd(iters[0])) {
      // Termination condition: all iterators must be at end.
      for (int i = 0; i < range_maps.size(); i++) {
        if (!range_maps[i]->IterIsEnd(iters[i])) {
          printf(
              "Error, range (%s) extends beyond final base map range "
              "(%s)\n",
              range_maps[i]->EntryDebugString(iters[i]).c_str(),
              range_maps[0]->EntryDebugString(std::prev(iters[0])).c_str());
          assert(false);
          throw std::runtime_error("Range extends beyond base map.");
        }
      }
      return;
    } else {
      // Starting a new continuous range: all iterators must start at the same
      // place.
      current = iters[0]->first;
      for (int i = 0; i < range_maps.size(); i++)  {
        if (range_maps[i]->IterIsEnd(iters[i])) {
          printf(
              "Error, no more ranges for index %d but we need one "
              "to match (%s)\n",
              i, range_maps[0]->EntryDebugString(iters[0]).c_str());
          assert(false);
          throw std::runtime_error("No more ranges.");
        } else if (iters[i]->first != current) {
          printf(
              "Error, range (%s) doesn't match the beginning of base range "
              "(%s)\n",
              range_maps[i]->EntryDebugString(iters[i]).c_str(),
              range_maps[0]->EntryDebugString(iters[0]).c_str());
          assert(false);
          throw std::runtime_error("No more ranges.");
        }
        keys.push_back(iters[i]->second.label);
      }
    }

    bool continuous = true;

    // Inner loop: once per range within the continuous region.
    while (continuous) {
      uint64_t next_break = UINT64_MAX;

      for (int i = 0; i < iters.size(); i++) {
        next_break = std::min(next_break, range_maps[i]->RangeEnd(iters[i]));
      }

      func(keys, current, next_break);

      // Advance all iterators with ranges ending at next_break.
      for (int i = 0; i < iters.size(); i++) {
        const RangeMap& map = *range_maps[i];
        Map::const_iterator& iter = iters[i];
        uint64_t end = continuous ? map.RangeEnd(iter)
                                  : map.RangeEndUnknownLimit(iter, next_break);

        if (end != next_break) {
          continue;
        }
        ++iter;

        // Test for discontinuity.
        if (map.IterIsEnd(iter) || iter->first != next_break) {
          if (i > 0 && continuous) {
            printf(
                "Error, gap between ranges (%s) and (%s) fails to cover base "
                "range (%s)\n",
                map.EntryDebugString(std::prev(iter)).c_str(),
                map.EntryDebugString(iter).c_str(),
                range_maps[0]->EntryDebugString(iters[0]).c_str());
            assert(false);
            throw std::runtime_error("Entry range extends beyond base range");
          }
          assert(i == 0 || !continuous);
          continuous = false;
        } else {
          assert(continuous);
          keys[i] = iter->second.label;
        }
      }
      current = next_break;
    }
  }
}


}  // namespace bloaty

#endif  // BLOATY_RANGE_MAP_H_
