mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-09-03 18:29:48 +00:00
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156810 91177308-0d34-0410-b5e6-96231b3b80d8
324 lines
8.5 KiB
C++
324 lines
8.5 KiB
C++
//===- 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 <algorithm>
|
|
#include <utility>
|
|
#include "llvm/Support/type_traits.h"
|
|
|
|
namespace llvm {
|
|
|
|
template <typename KeyTy, typename MappedTy>
|
|
struct FlatArrayMapTypes {
|
|
typedef KeyTy key_type;
|
|
typedef MappedTy mapped_type;
|
|
typedef typename std::pair<key_type, mapped_type> value_type;
|
|
};
|
|
|
|
template<typename KeyTy, typename MappedTy, bool IsConst = false>
|
|
class FlatArrayMapIterator;
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
/// FlatArrayMap presents map container interface.
|
|
/// It uses flat array implementation inside:
|
|
/// [ <key0, value0>, <key1, value1>, ... <keyN, valueN> ]
|
|
/// 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 <end(),false>).
|
|
///
|
|
template <typename KeyTy, typename MappedTy, unsigned MaxArraySize>
|
|
class FlatArrayMap {
|
|
public:
|
|
typedef FlatArrayMapTypes<KeyTy, MappedTy> Types;
|
|
|
|
typedef typename Types::key_type key_type;
|
|
typedef typename Types::mapped_type mapped_type;
|
|
typedef typename Types::value_type value_type;
|
|
|
|
typedef FlatArrayMapIterator<KeyTy, MappedTy> iterator;
|
|
typedef FlatArrayMapIterator<KeyTy, MappedTy, true> const_iterator;
|
|
|
|
typedef FlatArrayMap<KeyTy, MappedTy, MaxArraySize> 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<typename It>
|
|
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 <end(),false>).
|
|
std::pair<iterator, bool> insert(const value_type& KV) {
|
|
value_type* Item;
|
|
bool Res = insertInternal(KV.first, KV.second, Item);
|
|
return std::make_pair(iterator(Item), Res);
|
|
}
|
|
|
|
template <typename IterT>
|
|
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<iterator, bool> 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<typename KeyTy, typename MappedTy, bool IsConst>
|
|
class FlatArrayMapIterator {
|
|
|
|
typedef FlatArrayMapTypes<KeyTy, MappedTy> Types;
|
|
|
|
typedef typename conditional<IsConst,
|
|
const typename Types::value_type,
|
|
typename Types::value_type>::type value_type;
|
|
typedef value_type *pointer;
|
|
typedef value_type &reference;
|
|
|
|
typedef FlatArrayMapIterator<KeyTy, MappedTy, IsConst> self;
|
|
typedef FlatArrayMapIterator<KeyTy, MappedTy, false> non_const_self;
|
|
typedef FlatArrayMapIterator<KeyTy, MappedTy, true> const_self;
|
|
|
|
friend class FlatArrayMapIterator<KeyTy, MappedTy, false>;
|
|
friend class FlatArrayMapIterator<KeyTy, MappedTy, true>;
|
|
|
|
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_ */
|