1f4a2713aSLionel Sambuc //===--- ContinuousRangeMap.h - Map with int range as key -------*- C++ -*-===// 2f4a2713aSLionel Sambuc // 3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4f4a2713aSLionel Sambuc // 5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7f4a2713aSLionel Sambuc // 8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9f4a2713aSLionel Sambuc // 10f4a2713aSLionel Sambuc // This file defines the ContinuousRangeMap class, which is a highly 11f4a2713aSLionel Sambuc // specialized container used by serialization. 12f4a2713aSLionel Sambuc // 13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 14f4a2713aSLionel Sambuc 15*0a6a1f1dSLionel Sambuc #ifndef LLVM_CLANG_SERIALIZATION_CONTINUOUSRANGEMAP_H 16*0a6a1f1dSLionel Sambuc #define LLVM_CLANG_SERIALIZATION_CONTINUOUSRANGEMAP_H 17f4a2713aSLionel Sambuc 18f4a2713aSLionel Sambuc #include "clang/Basic/LLVM.h" 19f4a2713aSLionel Sambuc #include "llvm/ADT/SmallVector.h" 20f4a2713aSLionel Sambuc #include <algorithm> 21f4a2713aSLionel Sambuc #include <utility> 22f4a2713aSLionel Sambuc 23f4a2713aSLionel Sambuc namespace clang { 24f4a2713aSLionel Sambuc 25f4a2713aSLionel Sambuc /// \brief A map from continuous integer ranges to some value, with a very 26f4a2713aSLionel Sambuc /// specialized interface. 27f4a2713aSLionel Sambuc /// 28f4a2713aSLionel Sambuc /// CRM maps from integer ranges to values. The ranges are continuous, i.e. 29f4a2713aSLionel Sambuc /// where one ends, the next one begins. So if the map contains the stops I0-3, 30f4a2713aSLionel Sambuc /// the first range is from I0 to I1, the second from I1 to I2, the third from 31f4a2713aSLionel Sambuc /// I2 to I3 and the last from I3 to infinity. 32f4a2713aSLionel Sambuc /// 33f4a2713aSLionel Sambuc /// Ranges must be inserted in order. Inserting a new stop I4 into the map will 34f4a2713aSLionel Sambuc /// shrink the fourth range to I3 to I4 and add the new range I4 to inf. 35f4a2713aSLionel Sambuc template <typename Int, typename V, unsigned InitialCapacity> 36f4a2713aSLionel Sambuc class ContinuousRangeMap { 37f4a2713aSLionel Sambuc public: 38f4a2713aSLionel Sambuc typedef std::pair<Int, V> value_type; 39f4a2713aSLionel Sambuc typedef value_type &reference; 40f4a2713aSLionel Sambuc typedef const value_type &const_reference; 41f4a2713aSLionel Sambuc typedef value_type *pointer; 42f4a2713aSLionel Sambuc typedef const value_type *const_pointer; 43f4a2713aSLionel Sambuc 44f4a2713aSLionel Sambuc private: 45f4a2713aSLionel Sambuc typedef SmallVector<value_type, InitialCapacity> Representation; 46f4a2713aSLionel Sambuc Representation Rep; 47f4a2713aSLionel Sambuc 48f4a2713aSLionel Sambuc struct Compare { operatorCompare49f4a2713aSLionel Sambuc bool operator ()(const_reference L, Int R) const { 50f4a2713aSLionel Sambuc return L.first < R; 51f4a2713aSLionel Sambuc } operatorCompare52f4a2713aSLionel Sambuc bool operator ()(Int L, const_reference R) const { 53f4a2713aSLionel Sambuc return L < R.first; 54f4a2713aSLionel Sambuc } operatorCompare55f4a2713aSLionel Sambuc bool operator ()(Int L, Int R) const { 56f4a2713aSLionel Sambuc return L < R; 57f4a2713aSLionel Sambuc } operatorCompare58f4a2713aSLionel Sambuc bool operator ()(const_reference L, const_reference R) const { 59f4a2713aSLionel Sambuc return L.first < R.first; 60f4a2713aSLionel Sambuc } 61f4a2713aSLionel Sambuc }; 62f4a2713aSLionel Sambuc 63f4a2713aSLionel Sambuc public: insert(const value_type & Val)64f4a2713aSLionel Sambuc void insert(const value_type &Val) { 65f4a2713aSLionel Sambuc if (!Rep.empty() && Rep.back() == Val) 66f4a2713aSLionel Sambuc return; 67f4a2713aSLionel Sambuc 68f4a2713aSLionel Sambuc assert((Rep.empty() || Rep.back().first < Val.first) && 69f4a2713aSLionel Sambuc "Must insert keys in order."); 70f4a2713aSLionel Sambuc Rep.push_back(Val); 71f4a2713aSLionel Sambuc } 72f4a2713aSLionel Sambuc insertOrReplace(const value_type & Val)73f4a2713aSLionel Sambuc void insertOrReplace(const value_type &Val) { 74f4a2713aSLionel Sambuc iterator I = std::lower_bound(Rep.begin(), Rep.end(), Val, Compare()); 75f4a2713aSLionel Sambuc if (I != Rep.end() && I->first == Val.first) { 76f4a2713aSLionel Sambuc I->second = Val.second; 77f4a2713aSLionel Sambuc return; 78f4a2713aSLionel Sambuc } 79f4a2713aSLionel Sambuc 80f4a2713aSLionel Sambuc Rep.insert(I, Val); 81f4a2713aSLionel Sambuc } 82f4a2713aSLionel Sambuc 83f4a2713aSLionel Sambuc typedef typename Representation::iterator iterator; 84f4a2713aSLionel Sambuc typedef typename Representation::const_iterator const_iterator; 85f4a2713aSLionel Sambuc begin()86f4a2713aSLionel Sambuc iterator begin() { return Rep.begin(); } end()87f4a2713aSLionel Sambuc iterator end() { return Rep.end(); } begin()88f4a2713aSLionel Sambuc const_iterator begin() const { return Rep.begin(); } end()89f4a2713aSLionel Sambuc const_iterator end() const { return Rep.end(); } 90f4a2713aSLionel Sambuc find(Int K)91f4a2713aSLionel Sambuc iterator find(Int K) { 92f4a2713aSLionel Sambuc iterator I = std::upper_bound(Rep.begin(), Rep.end(), K, Compare()); 93f4a2713aSLionel Sambuc // I points to the first entry with a key > K, which is the range that 94f4a2713aSLionel Sambuc // follows the one containing K. 95f4a2713aSLionel Sambuc if (I == Rep.begin()) 96f4a2713aSLionel Sambuc return Rep.end(); 97f4a2713aSLionel Sambuc --I; 98f4a2713aSLionel Sambuc return I; 99f4a2713aSLionel Sambuc } find(Int K)100f4a2713aSLionel Sambuc const_iterator find(Int K) const { 101f4a2713aSLionel Sambuc return const_cast<ContinuousRangeMap*>(this)->find(K); 102f4a2713aSLionel Sambuc } 103f4a2713aSLionel Sambuc back()104f4a2713aSLionel Sambuc reference back() { return Rep.back(); } back()105f4a2713aSLionel Sambuc const_reference back() const { return Rep.back(); } 106f4a2713aSLionel Sambuc 107f4a2713aSLionel Sambuc /// \brief An object that helps properly build a continuous range map 108f4a2713aSLionel Sambuc /// from a set of values. 109f4a2713aSLionel Sambuc class Builder { 110f4a2713aSLionel Sambuc ContinuousRangeMap &Self; 111f4a2713aSLionel Sambuc 112f4a2713aSLionel Sambuc Builder(const Builder&) LLVM_DELETED_FUNCTION; 113f4a2713aSLionel Sambuc Builder &operator=(const Builder&) LLVM_DELETED_FUNCTION; 114f4a2713aSLionel Sambuc 115f4a2713aSLionel Sambuc public: Builder(ContinuousRangeMap & Self)116f4a2713aSLionel Sambuc explicit Builder(ContinuousRangeMap &Self) : Self(Self) { } 117f4a2713aSLionel Sambuc ~Builder()118f4a2713aSLionel Sambuc ~Builder() { 119f4a2713aSLionel Sambuc std::sort(Self.Rep.begin(), Self.Rep.end(), Compare()); 120*0a6a1f1dSLionel Sambuc std::unique(Self.Rep.begin(), Self.Rep.end(), 121*0a6a1f1dSLionel Sambuc [](const_reference A, const_reference B) { 122*0a6a1f1dSLionel Sambuc // FIXME: we should not allow any duplicate keys, but there are a lot of 123*0a6a1f1dSLionel Sambuc // duplicate 0 -> 0 mappings to remove first. 124*0a6a1f1dSLionel Sambuc assert((A == B || A.first != B.first) && 125*0a6a1f1dSLionel Sambuc "ContinuousRangeMap::Builder given non-unique keys"); 126*0a6a1f1dSLionel Sambuc return A == B; 127*0a6a1f1dSLionel Sambuc }); 128f4a2713aSLionel Sambuc } 129f4a2713aSLionel Sambuc insert(const value_type & Val)130f4a2713aSLionel Sambuc void insert(const value_type &Val) { 131f4a2713aSLionel Sambuc Self.Rep.push_back(Val); 132f4a2713aSLionel Sambuc } 133f4a2713aSLionel Sambuc }; 134f4a2713aSLionel Sambuc friend class Builder; 135f4a2713aSLionel Sambuc }; 136f4a2713aSLionel Sambuc 137f4a2713aSLionel Sambuc } 138f4a2713aSLionel Sambuc 139f4a2713aSLionel Sambuc #endif 140