//===- llvm/ADT/FlatArrayMap.h - 'Normally small' pointer set ----*- C++ -*-==// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the FlatArrayMap class. // See FlatArrayMap doxygen comments for more details. // //===----------------------------------------------------------------------===// #ifndef FLATARRAYMAP_H_ #define FLATARRAYMAP_H_ #include #include #include "llvm/Support/type_traits.h" namespace llvm { template struct FlatArrayMapTypes { typedef KeyTy key_type; typedef MappedTy mapped_type; typedef typename std::pair value_type; }; template class FlatArrayMapIterator; //===--------------------------------------------------------------------===// /// FlatArrayMap presents map container interface. /// It uses flat array implementation inside: /// [ , , ... ] /// It works fast for small amount of elements. /// User should pass key type, mapped type (type of value), and maximum /// number of elements. /// After maximum number of elements is reached, map declines any farther /// attempts to insert new elements ("insert" method returns ). /// template class FlatArrayMap { public: typedef FlatArrayMapTypes Types; typedef typename Types::key_type key_type; typedef typename Types::mapped_type mapped_type; typedef typename Types::value_type value_type; typedef FlatArrayMapIterator iterator; typedef FlatArrayMapIterator const_iterator; typedef FlatArrayMap self; private: enum { BadIndex = -1U }; key_type EmptyKey; mapped_type EmptyValue; value_type Array[MaxArraySize + 1]; unsigned NumElements; unsigned findFor(const KeyTy Ptr) const { // Linear search for the item. for (const value_type *APtr = Array, *E = Array + NumElements; APtr != E; ++APtr) { if (APtr->first == Ptr) { return APtr - Array; } } return BadIndex; } bool lookupFor(const KeyTy &Ptr, const value_type*& Found) const { unsigned FoundIdx = findFor(Ptr); if (FoundIdx != BadIndex) { Found = Array + FoundIdx; return true; } return false; } bool lookupFor(const KeyTy &Ptr, value_type*& Found) { unsigned FoundIdx = findFor(Ptr); if (FoundIdx != BadIndex) { Found = Array + FoundIdx; return true; } return false; } void copyFrom(const self &RHS) { memcpy(Array, RHS.Array, sizeof(value_type) * (MaxArraySize + 1)); NumElements = RHS.NumElements; } void init () { memset(Array + MaxArraySize, 0, sizeof(value_type)); NumElements = 0; } bool insertInternal(KeyTy Ptr, MappedTy Val, value_type*& Item) { // Check to see if it is already in the set. value_type *Found; if (lookupFor(Ptr, Found)) { Item = Found; return false; } if (NumElements < MaxArraySize) { unsigned Idx = NumElements++; Array[Idx] = std::make_pair(Ptr, Val); Item = Array + Idx; return true; } Item = Array + MaxArraySize; // return end() return false; } public: // Constructors FlatArrayMap() : EmptyKey(), EmptyValue() { init(); } FlatArrayMap(const self &that) : EmptyKey(), EmptyValue() { copyFrom(that); } template FlatArrayMap(It I, It E) : EmptyKey(), EmptyValue() { init(); insert(I, E); } // Size unsigned size() const { return NumElements; } bool empty() const { return !NumElements; } // Iterators iterator begin() { return iterator(Array); } const_iterator begin() const { return const_iterator(Array); } iterator end() { return iterator(Array + NumElements); } const_iterator end() const { return const_iterator(Array + NumElements); } // Modifiers void clear() { for (unsigned i = 0; i < NumElements; ++i) { Array[i].first = EmptyKey; Array[i].second = EmptyValue; } NumElements = 0; } // The map container is extended by inserting a single new element. // The behavior is the same as the std::map::insert, except the // case when maximum number of elements is reached; // in this case map declines any farther attempts // to insert new elements ("insert" method returns ). std::pair insert(const value_type& KV) { value_type* Item; bool Res = insertInternal(KV.first, KV.second, Item); return std::make_pair(iterator(Item), Res); } template void insert(IterT I, IterT E) { for (; I != E; ++I) insert(*I); } void erase(key_type K) { unsigned Found = findFor(K); if (Found != BadIndex) { value_type *APtr = Array + Found; value_type *E = Array + NumElements; *APtr = E[-1]; E[-1].first.~key_type(); E[-1].second.~mapped_type(); --NumElements; } } void erase(iterator i) { erase(i->first); } void swap(self& RHS) { std::swap_ranges(Array, Array+MaxArraySize, RHS.Array); std::swap(this->NumElements, RHS.NumElements); } // Search operations iterator find(const key_type& K) { value_type *Found; if (lookupFor(K, Found)) return iterator(Found); return end(); } const_iterator find(const key_type& K) const { const value_type *Found; if (lookupFor(K, Found)) return const_iterator(Found); return end(); } bool count(const key_type& K) const { return find(K) != end(); } mapped_type &operator[](const key_type &Key) { std::pair res = insert(Key, mapped_type()); return res.first->second; } // Other operations self& operator=(const self& other) { clear(); copyFrom(other); return *this; } /// isPointerIntoBucketsArray - Return true if the specified pointer points /// somewhere into the map's array of buckets (i.e. either to a key or /// value). bool isPointerIntoBucketsArray(const void *Ptr) const { return Ptr >= Array && Ptr < Array + NumElements; } /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets /// array. const void *getPointerIntoBucketsArray() const { return Array; } }; template class FlatArrayMapIterator { typedef FlatArrayMapTypes Types; typedef typename conditional::type value_type; typedef value_type *pointer; typedef value_type &reference; typedef FlatArrayMapIterator self; typedef FlatArrayMapIterator non_const_self; typedef FlatArrayMapIterator const_self; friend class FlatArrayMapIterator; friend class FlatArrayMapIterator; pointer TheBucket; public: FlatArrayMapIterator() : TheBucket(0) {} explicit FlatArrayMapIterator(pointer BP) : TheBucket(BP) {} // If IsConst is true this is a converting constructor from iterator to // const_iterator and the default copy constructor is used. // Otherwise this is a copy constructor for iterator. FlatArrayMapIterator(const non_const_self& I) : TheBucket(I.TheBucket) {} bool operator==(const const_self &RHS) const { return TheBucket->first == RHS.TheBucket->first; } bool operator!=(const const_self &RHS) const { return TheBucket->first != RHS.TheBucket->first; } reference operator*() const { return *TheBucket; } pointer operator->() const { return TheBucket; } inline self& operator++() { // Preincrement ++TheBucket; return *this; } self operator++(int) { // Postincrement FlatArrayMapIterator tmp = *this; ++*this; return tmp; } }; } #endif /* FLATARRAYMAP_H_ */