1 //===- llvm/ADT/FlatArrayMap.h - 'Normally small' pointer set ----*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the FlatArrayMap class.
11 // See FlatArrayMap doxygen comments for more details.
13 //===----------------------------------------------------------------------===//
15 #ifndef FLATARRAYMAP_H_
16 #define FLATARRAYMAP_H_
20 #include "llvm/Support/type_traits.h"
24 template <typename KeyTy, typename MappedTy>
25 struct FlatArrayMapTypes {
26 typedef KeyTy key_type;
27 typedef MappedTy mapped_type;
28 typedef typename std::pair<key_type, mapped_type> value_type;
31 template<typename KeyTy, typename MappedTy, bool IsConst = false>
32 class FlatArrayMapIterator;
34 //===--------------------------------------------------------------------===//
35 /// FlatArrayMap presents map container interface.
36 /// It uses flat array implementation inside:
37 /// [ <key0, value0>, <key1, value1>, ... <keyN, valueN> ]
38 /// It works fast for small amount of elements.
39 /// User should pass key type, mapped type (type of value), and maximum
40 /// number of elements.
41 /// After maximum number of elements is reached, map declines any farther
42 /// attempts to insert new elements ("insert" method returns <end(),false>).
44 template <typename KeyTy, typename MappedTy, unsigned MaxArraySize>
47 typedef FlatArrayMapTypes<KeyTy, MappedTy> Types;
49 typedef typename Types::key_type key_type;
50 typedef typename Types::mapped_type mapped_type;
51 typedef typename Types::value_type value_type;
53 typedef FlatArrayMapIterator<KeyTy, MappedTy> iterator;
54 typedef FlatArrayMapIterator<KeyTy, MappedTy, true> const_iterator;
56 typedef FlatArrayMap<KeyTy, MappedTy, MaxArraySize> self;
60 enum { BadIndex = -1U };
63 mapped_type EmptyValue;
65 value_type Array[MaxArraySize + 1];
68 unsigned findFor(const KeyTy Ptr) const {
69 // Linear search for the item.
70 for (const value_type *APtr = Array, *E = Array + NumElements;
72 if (APtr->first == Ptr) {
79 bool lookupFor(const KeyTy &Ptr, const value_type*& Found) const {
80 unsigned FoundIdx = findFor(Ptr);
81 if (FoundIdx != BadIndex) {
82 Found = Array + FoundIdx;
88 bool lookupFor(const KeyTy &Ptr, value_type*& Found) {
89 unsigned FoundIdx = findFor(Ptr);
90 if (FoundIdx != BadIndex) {
91 Found = Array + FoundIdx;
98 void copyFrom(const self &RHS) {
99 std::copy(RHS.Array, RHS.Array + MaxArraySize + 1, Array);
100 NumElements = RHS.NumElements;
104 // Even if Array contains non POD, use memset for last element,
105 // since it is used as end() iterator only.
106 memset(Array + MaxArraySize, 0, sizeof(value_type));
110 bool insertInternal(KeyTy Ptr, MappedTy Val, value_type*& Item) {
111 // Check to see if it is already in the set.
113 if (lookupFor(Ptr, Found)) {
117 if (NumElements < MaxArraySize) {
118 unsigned Idx = NumElements++;
119 Array[Idx] = std::make_pair(Ptr, Val);
123 Item = Array + MaxArraySize; // return end()
131 FlatArrayMap() : EmptyKey(), EmptyValue() {
135 FlatArrayMap(const self &that) :
136 EmptyKey(), EmptyValue() {
140 template<typename It>
141 FlatArrayMap(It I, It E) :
142 EmptyKey(), EmptyValue() {
149 unsigned size() const {
160 return iterator(Array);
162 const_iterator begin() const {
163 return const_iterator(Array);
167 return iterator(Array + NumElements);
169 const_iterator end() const {
170 return const_iterator(Array + NumElements);
176 for (unsigned i = 0; i < NumElements; ++i) {
177 Array[i].first = EmptyKey;
178 Array[i].second = EmptyValue;
183 // The map container is extended by inserting a single new element.
184 // The behavior is the same as the std::map::insert, except the
185 // case when maximum number of elements is reached;
186 // in this case map declines any farther attempts
187 // to insert new elements ("insert" method returns <end(),false>).
188 std::pair<iterator, bool> insert(const value_type& KV) {
190 bool Res = insertInternal(KV.first, KV.second, Item);
191 return std::make_pair(iterator(Item), Res);
194 template <typename IterT>
195 void insert(IterT I, IterT E) {
200 void erase(key_type K) {
201 unsigned Found = findFor(K);
202 if (Found != BadIndex) {
203 value_type *APtr = Array + Found;
204 value_type *E = Array + NumElements;
206 E[-1].first.~key_type();
207 E[-1].second.~mapped_type();
212 void erase(iterator i) {
216 void swap(self& RHS) {
217 std::swap_ranges(Array, Array+MaxArraySize, RHS.Array);
218 std::swap(this->NumElements, RHS.NumElements);
223 iterator find(const key_type& K) {
225 if (lookupFor(K, Found))
226 return iterator(Found);
230 const_iterator find(const key_type& K) const {
231 const value_type *Found;
232 if (lookupFor(K, Found))
233 return const_iterator(Found);
237 bool count(const key_type& K) const {
238 return find(K) != end();
241 mapped_type &operator[](const key_type &Key) {
242 std::pair<iterator, bool> res = insert(Key, mapped_type());
243 return res.first->second;
248 self& operator=(const self& other) {
254 /// isPointerIntoBucketsArray - Return true if the specified pointer points
255 /// somewhere into the map's array of buckets (i.e. either to a key or
257 bool isPointerIntoBucketsArray(const void *Ptr) const {
258 return Ptr >= Array && Ptr < Array + NumElements;
261 /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets
263 const void *getPointerIntoBucketsArray() const { return Array; }
266 template<typename KeyTy, typename MappedTy, bool IsConst>
267 class FlatArrayMapIterator {
269 typedef FlatArrayMapTypes<KeyTy, MappedTy> Types;
271 typedef typename conditional<IsConst,
272 const typename Types::value_type,
273 typename Types::value_type>::type value_type;
274 typedef value_type *pointer;
275 typedef value_type &reference;
277 typedef FlatArrayMapIterator<KeyTy, MappedTy, IsConst> self;
278 typedef FlatArrayMapIterator<KeyTy, MappedTy, false> non_const_self;
279 typedef FlatArrayMapIterator<KeyTy, MappedTy, true> const_self;
281 friend class FlatArrayMapIterator<KeyTy, MappedTy, false>;
282 friend class FlatArrayMapIterator<KeyTy, MappedTy, true>;
288 FlatArrayMapIterator() : TheBucket(0) {}
290 explicit FlatArrayMapIterator(pointer BP) :
293 // If IsConst is true this is a converting constructor from iterator to
294 // const_iterator and the default copy constructor is used.
295 // Otherwise this is a copy constructor for iterator.
296 FlatArrayMapIterator(const non_const_self& I)
297 : TheBucket(I.TheBucket) {}
299 bool operator==(const const_self &RHS) const {
300 return TheBucket->first == RHS.TheBucket->first;
302 bool operator!=(const const_self &RHS) const {
303 return TheBucket->first != RHS.TheBucket->first;
306 reference operator*() const {
310 pointer operator->() const {
314 inline self& operator++() { // Preincrement
319 self operator++(int) { // Postincrement
320 FlatArrayMapIterator tmp = *this; ++*this; return tmp;
325 #endif /* FLATARRAYMAP_H_ */