// Copyright (C) 2006 Google Inc.
//
// 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.

// range_map.h: Range maps.
//
// A range map associates a range of addresses with a specific object.  This
// is useful when certain objects of variable size are located within an
// address space.  The range map makes it simple to determine which object is
// associated with a specific address, which may be any address within the
// range associated with an object.
//
// Author: Mark Mentovai

#ifndef PROCESSOR_RANGE_MAP_H__
#define PROCESSOR_RANGE_MAP_H__


#include <map>


namespace google_airbag {


template<typename AddressType, typename EntryType>
class RangeMap {
 public:
  RangeMap() : map_() {}

  // Inserts a range into the map.  Returns false for a parameter error,
  // or if the location of the range would conflict with a range already
  // stored in the map.
  bool StoreRange(const AddressType &base,
                  const AddressType &size,
                  const EntryType &entry);

  // Locates the range encompassing the supplied address.  If there is
  // no such range, or if there is a parameter error, returns false.
  bool RetrieveRange(const AddressType &address, EntryType *entry) const;

  // Empties the range map, restoring it to the state it was when it was
  // initially created.
  void Clear();

 private:
  class Range {
   public:
    Range(const AddressType &base, const EntryType &entry)
        : base_(base), entry_(entry) {}

    AddressType base() const { return base_; }
    EntryType entry() const { return entry_; }

   private:
    // The base address of the range.  The high address does not need to
    // be stored, because RangeMap uses it as the key to the map.
    const AddressType base_;

    // The entry corresponding to a range.
    const EntryType entry_;
  };

  // Convenience types.
  typedef std::map<AddressType, Range> AddressToRangeMap;
  typedef typename AddressToRangeMap::const_iterator const_iterator;
  typedef typename AddressToRangeMap::value_type value_type;

  // Maps the high address of each range to a EntryType.
  AddressToRangeMap map_;
};


template<typename AddressType, typename EntryType>
bool RangeMap<AddressType, EntryType>::StoreRange(const AddressType &base,
                                                  const AddressType &size,
                                                  const EntryType &entry) {
  AddressType high = base + size - 1;

  // Check for undersize or overflow.
  if (size <= 0 || high < base)
    return false;

  // Ensure that this range does not overlap with another one already in the
  // map.
  const_iterator iterator_base = map_.lower_bound(base);
  const_iterator iterator_high = map_.lower_bound(high);

  if (iterator_base != iterator_high) {
    // Some other range begins in the space used by this range.  It may be
    // contained within the space used by this range, or it may extend lower.
    // Regardless, it is an error.
    return false;
  }

  if (iterator_high != map_.end()) {
    if (iterator_high->second.base() <= high) {
      // The range above this one overlaps with this one.  It may fully
      // contain  this range, or it may begin within this range and extend
      // higher.  Regardless, it's an error.
      return false;
    }
  }

  // Store the range in the map by its high address, so that lower_bound can
  // be used to quickly locate a range by address.
  map_.insert(value_type(high, Range(base, entry)));
  return true;
}


template<typename AddressType, typename EntryType>
bool RangeMap<AddressType, EntryType>::RetrieveRange(
    const AddressType &address, EntryType *entry) const {
  if (!entry)
    return false;

  const_iterator iterator = map_.lower_bound(address);
  if (iterator == map_.end())
    return false;

  // The map is keyed by the high address of each range, so |address| is
  // guaranteed to be lower than the range's high address.  If |range| is
  // not directly preceded by another range, it's possible for address to
  // be below the range's low address, though.  When that happens, address
  // references something not within any range, so return false.
  if (address < iterator->second.base())
    return false;

  *entry = iterator->second.entry();
  return true;
}


template<typename AddressType, typename EntryType>
void RangeMap<AddressType, EntryType>::Clear() {
  map_.clear();
}


}  // namespace google_airbag


#endif  // PROCESSOR_RANGE_MAP_H__
