struct IndexCommon { enum { HIBIT = 0x80000000 }; struct Hash : Moveable { int next; // also link for unlinked items... dword hash; int prev; }; int *map; Hash *hash; dword mask; int unlinked; static int empty[1]; static dword Smear(hash_t h) { return FoldHash(h) | HIBIT; } void Link(int& m, Hash& hh, int ii); void Link(int ii, dword sh); void Del(int& m, Hash& hh, int ii); void Ins(int& m, Hash& hh, int ii); void MakeMap(int count); void Remap(int count); void Reindex(int count); void GrowMap(int count); void FreeMap(); void Free(); void Set(int ii, dword h); Vector GetUnlinked() const; void Clear(); void Trim(int n, int count); void Sweep(int n); void Reserve(int n); void Shrink(); void AdjustMap(int count, int alloc); void Copy(const IndexCommon& b, int count); void Pick(IndexCommon& b); void Swap(IndexCommon& b); IndexCommon(); ~IndexCommon(); }; template class AMap; template class Index : MoveableAndDeepCopyOption>, IndexCommon { Vector key; static dword Smear(const T& k) { return IndexCommon::Smear(GetHashValue(k)); } int FindFrom(int i, dword sh, const T& k, int end) const; int FindBack(int i, dword sh, const T& k, int end) const; void ReallocHash(int n); template void GrowAdd(U&& k, dword sh); template void AddS(int& m, U&& k, dword sh); template void AddS(U&& k, dword sh); template int FindAdd(U&& k, OP add_op); template int FindPut0(U&& k, bool& put); template int Put0(U&& k, dword sh); template void Set0(int i, U&& k); template friend class AMap; void FixHash(bool makemap = true); public: void Add(const T& k) { AddS(k, Smear(k)); } void Add(T&& k) { AddS(pick(k), Smear(k)); } Index& operator<<(const T& x) { Add(x); return *this; } Index& operator<<(T&& x) { Add(pick(x)); return *this; } int Find(const T& k) const; int FindNext(int i) const; int FindLast(const T& k) const; int FindPrev(int i) const; int FindAdd(const T& k) { return FindAdd(k, []{}); } int FindAdd(T&& k) { return FindAdd(pick(k), []{}); } int Put(const T& k) { return Put0(k, Smear(k)); } int Put(T&& k) { return Put0(pick(k), Smear(k)); } int FindPut(const T& k, bool& p){ return FindPut0(k, p); } int FindPut(T&& k, bool& p) { return FindPut0(pick(k), p); } int FindPut(const T& k) { bool p; return FindPut0(k, p); } int FindPut(T&& k) { bool p; return FindPut0(pick(k), p); } void Unlink(int i); int UnlinkKey(const T& k); bool IsUnlinked(int i) const { return hash[i].hash == 0; } bool HasUnlinked() const { return unlinked >= 0; } Vector GetUnlinked() const { return IndexCommon::GetUnlinked(); } void Sweep(); void Set(int i, const T& k) { Set0(i, k); } void Set(int i, T&& k) { Set0(i, pick(k)); } const T& operator[](int i) const { return key[i]; } int GetCount() const { return key.GetCount(); } bool IsEmpty() const { return key.IsEmpty(); } void Clear() { key.Clear(); IndexCommon::Clear(); } void Trim(int n = 0) { IndexCommon::Trim(n, GetCount()); key.Trim(n); } void Drop(int n = 1) { Trim(GetCount() - 1); } const T& Top() const { return key.Top(); } T Pop() { T x = pick(Top()); Drop(); return x; } void Reserve(int n); void Shrink(); int GetAlloc() const { return key.GetAlloc(); } Vector PickKeys() { Vector r = pick(key); Clear(); return r; } const Vector& GetKeys() const { return key; } void Remove(const int *sorted_list, int count); void Remove(const Vector& sorted_list) { Remove(sorted_list, sorted_list.GetCount()); } template void RemoveIf(Pred p) { Remove(FindAlli(key, p)); } Index() {} Index(Index&& s) : key(pick(s.key)) { IndexCommon::Pick(s); } Index(const Index& s, int) : key(s.key, 0) { ReallocHash(0); IndexCommon::Copy(s, key.GetCount()); } // TODO: Unlinked! explicit Index(Vector&& s) : key(pick(s)) { FixHash(); } Index(const Vector& s, int) : key(s, 0) { FixHash(); } Index& operator=(Vector&& x) { key = pick(x); FixHash(); return *this; } Index& operator=(Index&& x) { key = pick(x.key); IndexCommon::Pick(x); return *this; } Index(std::initializer_list init) : key(init) { FixHash(); } void Serialize(Stream& s); void Xmlize(XmlIO& xio, const char *itemtag = "key"); void Jsonize(JsonIO& jio); String ToString() const; template bool operator==(const B& b) const { return IsEqualRange(*this, b); } #ifndef CPP_20 template bool operator!=(const B& b) const { return !operator==(b); } #endif template int Compare(const B& b) const { return CompareRanges(*this, b); } template bool operator<=(const B& x) const { return Compare(x) <= 0; } template bool operator>=(const B& x) const { return Compare(x) >= 0; } template bool operator<(const B& x) const { return Compare(x) < 0; } template bool operator>(const B& x) const { return Compare(x) > 0; } // Standard container interface typedef ConstIteratorOf> ConstIterator; ConstIterator begin() const { return key.begin(); } ConstIterator end() const { return key.end(); } friend void Swap(Index& a, Index& b) { a.IndexCommon::Swap(b); UPP::Swap(a.key, b.key); } // deprecated: #ifdef DEPRECATED T& Insert(int i, const T& k) { key.Insert(i, k); FixHash(); return key[i]; } void Remove(int i, int count) { key.Remove(i, count); FixHash(); } void Remove(int i) { Remove(i, 1); } int RemoveKey(const T& k) { int i = Find(k); if(i >= 0) Remove(i); return i; } unsigned GetHash(int i) const { return hash[i].hash; } Index& operator<<=(const Vector& s) { *this = clone(s); return *this; } typedef T ValueType; typedef Vector ValueContainer; ConstIterator GetIter(int pos) const { return key.GetIter(pos); } void ClearIndex() {} void Reindex(int n) {} void Reindex() {} typedef T value_type; typedef ConstIterator const_iterator; typedef const T& const_reference; typedef int size_type; typedef int difference_type; const_iterator Begin() const { return begin(); } const_iterator End() const { return end(); } void clear() { Clear(); } size_type size() const { return GetCount(); } bool empty() const { return IsEmpty(); } #endif #ifdef _DEBUG String Dump() const; #endif };