forked from OSchip/llvm-project
Add ImmutableMapRef and ImmutableSetRef, which consolidate Immutable[Map,Set] and its Factory. This may eventually replace Immtuable[Map,Set].
llvm-svn: 139967
This commit is contained in:
parent
d0c435c23c
commit
502848ceda
|
@ -256,6 +256,159 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// NOTE: This will possibly become the new implementation of ImmutableMap some day.
|
||||||
|
template <typename KeyT, typename ValT,
|
||||||
|
typename ValInfo = ImutKeyValueInfo<KeyT,ValT> >
|
||||||
|
class ImmutableMapRef {
|
||||||
|
public:
|
||||||
|
typedef typename ValInfo::value_type value_type;
|
||||||
|
typedef typename ValInfo::value_type_ref value_type_ref;
|
||||||
|
typedef typename ValInfo::key_type key_type;
|
||||||
|
typedef typename ValInfo::key_type_ref key_type_ref;
|
||||||
|
typedef typename ValInfo::data_type data_type;
|
||||||
|
typedef typename ValInfo::data_type_ref data_type_ref;
|
||||||
|
typedef ImutAVLTree<ValInfo> TreeTy;
|
||||||
|
typedef typename TreeTy::Factory FactoryTy;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
TreeTy *Root;
|
||||||
|
FactoryTy *Factory;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Constructs a map from a pointer to a tree root. In general one
|
||||||
|
/// should use a Factory object to create maps instead of directly
|
||||||
|
/// invoking the constructor, but there are cases where make this
|
||||||
|
/// constructor public is useful.
|
||||||
|
explicit ImmutableMapRef(const TreeTy* R, FactoryTy *F)
|
||||||
|
: Root(const_cast<TreeTy*>(R)),
|
||||||
|
Factory(F) {
|
||||||
|
if (Root) { Root->retain(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableMapRef(const ImmutableMapRef &X)
|
||||||
|
: Root(X.Root),
|
||||||
|
Factory(X.Factory) {
|
||||||
|
if (Root) { Root->retain(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableMapRef &operator=(const ImmutableMapRef &X) {
|
||||||
|
if (Root != X.Root) {
|
||||||
|
if (X.Root)
|
||||||
|
X.Root->retain();
|
||||||
|
|
||||||
|
if (Root)
|
||||||
|
Root->release();
|
||||||
|
|
||||||
|
Root = X.Root;
|
||||||
|
Factory = X.Factory;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ImmutableMapRef() {
|
||||||
|
if (Root)
|
||||||
|
Root->release();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline ImmutableMapRef getEmptyMap(FactoryTy *F) {
|
||||||
|
return ImmutableMapRef(0, F);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableMapRef add(key_type_ref K, data_type_ref D) {
|
||||||
|
TreeTy *NewT = Factory->add(Root, std::pair<key_type, data_type>(K, D));
|
||||||
|
return ImmutableMapRef(NewT, Factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableMapRef remove(key_type_ref K) {
|
||||||
|
TreeTy *NewT = Factory->remove(Root, K);
|
||||||
|
return ImmutableMapRef(NewT, Factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(key_type_ref K) const {
|
||||||
|
return Root ? Root->contains(K) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableMap<KeyT, ValT> asImmutableMap() const {
|
||||||
|
return ImmutableMap<KeyT, ValT>(Factory->getCanonicalTree(Root));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const ImmutableMapRef &RHS) const {
|
||||||
|
return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const ImmutableMapRef &RHS) const {
|
||||||
|
return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEmpty() const { return !Root; }
|
||||||
|
|
||||||
|
//===--------------------------------------------------===//
|
||||||
|
// For testing.
|
||||||
|
//===--------------------------------------------------===//
|
||||||
|
|
||||||
|
void verify() const { if (Root) Root->verify(); }
|
||||||
|
|
||||||
|
//===--------------------------------------------------===//
|
||||||
|
// Iterators.
|
||||||
|
//===--------------------------------------------------===//
|
||||||
|
|
||||||
|
class iterator {
|
||||||
|
typename TreeTy::iterator itr;
|
||||||
|
|
||||||
|
iterator() {}
|
||||||
|
iterator(TreeTy* t) : itr(t) {}
|
||||||
|
friend class ImmutableMapRef;
|
||||||
|
|
||||||
|
public:
|
||||||
|
value_type_ref operator*() const { return itr->getValue(); }
|
||||||
|
value_type* operator->() const { return &itr->getValue(); }
|
||||||
|
|
||||||
|
key_type_ref getKey() const { return itr->getValue().first; }
|
||||||
|
data_type_ref getData() const { return itr->getValue().second; }
|
||||||
|
|
||||||
|
|
||||||
|
iterator& operator++() { ++itr; return *this; }
|
||||||
|
iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
|
||||||
|
iterator& operator--() { --itr; return *this; }
|
||||||
|
iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
|
||||||
|
bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
|
||||||
|
bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
iterator begin() const { return iterator(Root); }
|
||||||
|
iterator end() const { return iterator(); }
|
||||||
|
|
||||||
|
data_type* lookup(key_type_ref K) const {
|
||||||
|
if (Root) {
|
||||||
|
TreeTy* T = Root->find(K);
|
||||||
|
if (T) return &T->getValue().second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getMaxElement - Returns the <key,value> pair in the ImmutableMap for
|
||||||
|
/// which key is the highest in the ordering of keys in the map. This
|
||||||
|
/// method returns NULL if the map is empty.
|
||||||
|
value_type* getMaxElement() const {
|
||||||
|
return Root ? &(Root->getMaxElement()->getValue()) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===--------------------------------------------------===//
|
||||||
|
// Utility methods.
|
||||||
|
//===--------------------------------------------------===//
|
||||||
|
|
||||||
|
unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
|
||||||
|
|
||||||
|
static inline void Profile(FoldingSetNodeID& ID, const ImmutableMapRef &M) {
|
||||||
|
ID.AddPointer(M.Root);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Profile(FoldingSetNodeID& ID) const {
|
||||||
|
return Profile(ID, *this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -997,6 +997,10 @@ public:
|
||||||
|
|
||||||
BumpPtrAllocator& getAllocator() { return F.getAllocator(); }
|
BumpPtrAllocator& getAllocator() { return F.getAllocator(); }
|
||||||
|
|
||||||
|
typename TreeTy::Factory *getTreeFactory() const {
|
||||||
|
return const_cast<typename TreeTy::Factory *>(&F);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Factory(const Factory& RHS); // DO NOT IMPLEMENT
|
Factory(const Factory& RHS); // DO NOT IMPLEMENT
|
||||||
void operator=(const Factory& RHS); // DO NOT IMPLEMENT
|
void operator=(const Factory& RHS); // DO NOT IMPLEMENT
|
||||||
|
@ -1021,6 +1025,10 @@ public:
|
||||||
if (Root) { Root->retain(); }
|
if (Root) { Root->retain(); }
|
||||||
return Root;
|
return Root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TreeTy *getRootWithoutRetain() const {
|
||||||
|
return Root;
|
||||||
|
}
|
||||||
|
|
||||||
/// isEmpty - Return true if the set contains no elements.
|
/// isEmpty - Return true if the set contains no elements.
|
||||||
bool isEmpty() const { return !Root; }
|
bool isEmpty() const { return !Root; }
|
||||||
|
@ -1078,6 +1086,131 @@ public:
|
||||||
|
|
||||||
void validateTree() const { if (Root) Root->validateTree(); }
|
void validateTree() const { if (Root) Root->validateTree(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// NOTE: This may some day replace the current ImmutableSet.
|
||||||
|
template <typename ValT, typename ValInfo = ImutContainerInfo<ValT> >
|
||||||
|
class ImmutableSetRef {
|
||||||
|
public:
|
||||||
|
typedef typename ValInfo::value_type value_type;
|
||||||
|
typedef typename ValInfo::value_type_ref value_type_ref;
|
||||||
|
typedef ImutAVLTree<ValInfo> TreeTy;
|
||||||
|
typedef typename TreeTy::Factory FactoryTy;
|
||||||
|
|
||||||
|
private:
|
||||||
|
TreeTy *Root;
|
||||||
|
FactoryTy *Factory;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Constructs a set from a pointer to a tree root. In general one
|
||||||
|
/// should use a Factory object to create sets instead of directly
|
||||||
|
/// invoking the constructor, but there are cases where make this
|
||||||
|
/// constructor public is useful.
|
||||||
|
explicit ImmutableSetRef(TreeTy* R, FactoryTy *F)
|
||||||
|
: Root(R),
|
||||||
|
Factory(F) {
|
||||||
|
if (Root) { Root->retain(); }
|
||||||
|
}
|
||||||
|
ImmutableSetRef(const ImmutableSetRef &X)
|
||||||
|
: Root(X.Root),
|
||||||
|
Factory(X.Factory) {
|
||||||
|
if (Root) { Root->retain(); }
|
||||||
|
}
|
||||||
|
ImmutableSetRef &operator=(const ImmutableSetRef &X) {
|
||||||
|
if (Root != X.Root) {
|
||||||
|
if (X.Root) { X.Root->retain(); }
|
||||||
|
if (Root) { Root->release(); }
|
||||||
|
Root = X.Root;
|
||||||
|
Factory = X.Factory;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
~ImmutableSetRef() {
|
||||||
|
if (Root) { Root->release(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline ImmutableSetRef getEmptySet(FactoryTy *F) {
|
||||||
|
return ImmutableSetRef(0, F);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableSetRef add(value_type_ref V) {
|
||||||
|
return ImmutableSetRef(Factory->add(Root, V), Factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableSetRef remove(value_type_ref V) {
|
||||||
|
return ImmutableSetRef(Factory->remove(Root, V), Factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if the set contains the specified value.
|
||||||
|
bool contains(value_type_ref V) const {
|
||||||
|
return Root ? Root->contains(V) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableSet<ValT> asImmutableSet() const {
|
||||||
|
return ImmutableSet<ValT>(Factory->getCanonicalTree(Root));
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeTy *getRootWithoutRetain() const {
|
||||||
|
return Root;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const ImmutableSetRef &RHS) const {
|
||||||
|
return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const ImmutableSetRef &RHS) const {
|
||||||
|
return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// isEmpty - Return true if the set contains no elements.
|
||||||
|
bool isEmpty() const { return !Root; }
|
||||||
|
|
||||||
|
/// isSingleton - Return true if the set contains exactly one element.
|
||||||
|
/// This method runs in constant time.
|
||||||
|
bool isSingleton() const { return getHeight() == 1; }
|
||||||
|
|
||||||
|
//===--------------------------------------------------===//
|
||||||
|
// Iterators.
|
||||||
|
//===--------------------------------------------------===//
|
||||||
|
|
||||||
|
class iterator {
|
||||||
|
typename TreeTy::iterator itr;
|
||||||
|
iterator(TreeTy* t) : itr(t) {}
|
||||||
|
friend class ImmutableSetRef<ValT,ValInfo>;
|
||||||
|
public:
|
||||||
|
iterator() {}
|
||||||
|
inline value_type_ref operator*() const { return itr->getValue(); }
|
||||||
|
inline iterator& operator++() { ++itr; return *this; }
|
||||||
|
inline iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
|
||||||
|
inline iterator& operator--() { --itr; return *this; }
|
||||||
|
inline iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
|
||||||
|
inline bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
|
||||||
|
inline bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
|
||||||
|
inline value_type *operator->() const { return &(operator*()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
iterator begin() const { return iterator(Root); }
|
||||||
|
iterator end() const { return iterator(); }
|
||||||
|
|
||||||
|
//===--------------------------------------------------===//
|
||||||
|
// Utility methods.
|
||||||
|
//===--------------------------------------------------===//
|
||||||
|
|
||||||
|
unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
|
||||||
|
|
||||||
|
static inline void Profile(FoldingSetNodeID& ID, const ImmutableSetRef& S) {
|
||||||
|
ID.AddPointer(S.Root);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Profile(FoldingSetNodeID& ID) const {
|
||||||
|
return Profile(ID,*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//===--------------------------------------------------===//
|
||||||
|
// For testing.
|
||||||
|
//===--------------------------------------------------===//
|
||||||
|
|
||||||
|
void validateTree() const { if (Root) Root->validateTree(); }
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue