template T& Single(Args... args) { static T o(args...); return o; } template // Workaround for GCC bug - specialization needed... T& Single() { static T o; return o; } int RegisterTypeNo__(const char *type); template int StaticTypeNo() { static int typeno = RegisterTypeNo__(typeid(T).name()); return typeno; } class Any : Moveable { struct BaseData { int typeno; virtual ~BaseData() {} }; template struct Data : BaseData { T data; template Data(Args&&... args) : data(std::forward(args)...) { typeno = StaticTypeNo(); } }; BaseData *ptr; void Chk() const { ASSERT(ptr != (void *)1); } void Pick(Any&& s) { ptr = s.ptr; const_cast(s).ptr = NULL; } public: template T& Create(Args&&... args) { Clear(); Data *x = new Data(std::forward(args)...); ptr = x; return x->data; } template bool Is() const { return ptr && ptr->typeno == StaticTypeNo(); } template T& Get() { ASSERT(Is()); Chk(); return ((Data*)ptr)->data; } template const T& Get() const { ASSERT(Is()); Chk(); return ((Data*)ptr)->data; } void Clear() { if(ptr) delete ptr; ptr = NULL; } bool IsEmpty() const { return ptr == NULL; } void operator=(Any&& s) { if(this != &s) { Clear(); Pick(pick(s)); } } Any(Any&& s) { Pick(pick(s)); } Any(const Any& s) = delete; void operator=(const Any& s) = delete; Any() { ptr = NULL; } ~Any() { Clear(); } }; class Bits : Moveable { int alloc; dword *bp; void Expand(int q); void Realloc(int nalloc); int GetLast() const; public: void Clear(); void Set(int i, bool b = true) { ASSERT(i >= 0 && alloc >= 0); int q = i >> 5; if(q >= alloc) Expand(q); i &= 31; bp[q] = (bp[q] & ~(1 << i)) | (b << i); } bool Get(int i) const { ASSERT(i >= 0 && alloc >= 0); int q = i >> 5; return q < alloc ? bp[q] & (1 << (i & 31)) : false; } bool operator[](int i) const { return Get(i); } void Set(int i, dword bits, int count); dword Get(int i, int count); void Set64(int i, uint64 bits, int count); uint64 Get64(int i, int count); void SetN(int i, bool b, int count); void SetN(int i, int count) { SetN(i, true, count); } void Reserve(int nbits); void Shrink(); String ToString() const; dword *CreateRaw(int n_dwords); const dword *Raw(int& n_dwords) const { n_dwords = alloc; return bp; } dword *Raw(int& n_dwords) { n_dwords = alloc; return bp; } void Serialize(Stream& s); Bits() { bp = NULL; alloc = 0; } ~Bits() { Clear(); } Bits(Bits&& b) { alloc = b.alloc; bp = b.bp; b.bp = NULL; } void operator=(Bits&& b) { if(this != &b) { Clear(); alloc = b.alloc; bp = b.bp; b.bp = NULL; } } Bits(const Bits&) = delete; void operator=(const Bits&) = delete; }; class PackedData { void *ptr = nullptr; template T Get(int ii, T def) const; public: void SetRawPtr(void *p) { ptr = p; } void *GetRawPtr() const { return ptr; } void SetData(int ii, const void *data, int datalen); template bool GetData(int ii, F out) const; void SetNull(int ii) { SetData(ii, NULL, 0); } void SetString(int ii, const char *s) { SetData(ii, s, (int)strlen(s)); } void SetString(int ii, const String& s) { SetData(ii, s, s.GetCount()); } String GetString(int ii) const { String r; GetData(ii, [&](const char *s, int n) { r = String(s, n); }); return r; } void SetInt(int ii, int val) { SetData(ii, &val, sizeof(int)); } int GetInt(int ii, int def) const { return Get(ii, def); } void SetDword(int ii, dword val) { SetData(ii, &val, sizeof(dword)); } int GetDword(int ii, dword def) const { return Get(ii, def); } void SetInt64(int ii, int64 val) { SetData(ii, &val, sizeof(int64)); } int64 GetInt64(int ii, int64 def) const { return Get(ii, def); } void SetPtr(int ii, void *val) { SetData(ii, &val, sizeof(void *)); } void *GetPtr(int ii) const { return Get(ii, nullptr); } void Clear(); Vector Unpack() const; size_t GetPackedSize() const; String GetPacked() const { return String((const char *)ptr, (int)GetPackedSize()); } PackedData() {} PackedData(const PackedData&) = delete; ~PackedData(); }; /* template struct Link { T *link_prev[N]; T *link_next[N]; protected: void LPN(int i) { link_prev[i]->link_next[i] = link_next[i]->link_prev[i] = (T *)this; } public: NOUBSAN T *GetPtr() { return (T *) this; } const T *GetPtr() const { return (const T *) this; } T *GetNext(int i = 0) { return link_next[i]; } T *GetPrev(int i = 0) { return link_prev[i]; } const T *GetNext(int i = 0) const { return link_next[i]; } const T *GetPrev(int i = 0) const { return link_prev[i]; } NOUBSAN void LinkSelf(int i = 0) { link_next[i] = link_prev[i] = (T *)this; } void LinkSelfAll() { for(int i = 0; i < N; i++) LinkSelf(i); } void Unlink(int i = 0) { link_next[i]->link_prev[i] = link_prev[i]; link_prev[i]->link_next[i] = link_next[i]; LinkSelf(i); } void UnlinkAll() { for(int i = 0; i < N; i++) Unlink(i); } NOUBSAN void LinkBefore(Link *n, int i = 0) { link_next[i] = (T *)n; link_prev[i] = link_next[i]->link_prev[i]; LPN(i); } NOUBSAN void LinkAfter(Link *p, int i = 0) { link_prev[i] = (T *)p; link_next[i] = link_prev[i]->link_next[i]; LPN(i); } T *InsertNext(int i = 0) { T *x = new T; x->LinkAfter(this, i); return x; } T *InsertPrev(int i = 0) { T *x = new T; x->LinkBefore(this, i); return x; } void DeleteList(int i = 0) { while(link_next[i] != GetPtr()) delete link_next[i]; } bool InList(int i = 0) const { return link_next[i] != GetPtr(); } bool IsEmpty(int i = 0) const { return !InList(i); } Link() { LinkSelfAll(); } ~Link() { UnlinkAll(); } private: Link(const Link&); void operator=(const Link&); public: #ifdef _DEBUG void Dump() { for(T *t = GetNext(); t != this; t = t->GetNext()) LOG(t); LOG("-------------------------------------"); } #endif }; */ template struct Link { Link *link_prev[N]; Link *link_next[N]; protected: void LPN(int i) { link_prev[i]->link_next[i] = link_next[i]->link_prev[i] = this; } public: Link *GetNext(int i = 0) { return link_next[i]; } Link *GetPrev(int i = 0) { return link_prev[i]; } const Link *GetNext(int i = 0) const { return link_next[i]; } const Link *GetPrev(int i = 0) const { return link_prev[i]; } void LinkSelf(int i = 0) { link_next[i] = link_prev[i] = this; } void LinkSelfAll() { for(int i = 0; i < N; i++) LinkSelf(i); } void Unlink(int i = 0) { link_next[i]->link_prev[i] = link_prev[i]; link_prev[i]->link_next[i] = link_next[i]; LinkSelf(i); } void UnlinkAll() { for(int i = 0; i < N; i++) Unlink(i); } void LinkBefore(Link *n, int i = 0) { link_next[i] = n; link_prev[i] = link_next[i]->link_prev[i]; LPN(i); } void LinkAfter(Link *p, int i = 0) { link_prev[i] = p; link_next[i] = link_prev[i]->link_next[i]; LPN(i); } bool InList(int i = 0) const { return link_next[i] != this; } bool IsEmpty(int i = 0) const { return !InList(i); } Link() { LinkSelfAll(); } ~Link() { UnlinkAll(); } private: Link(const Link&); void operator=(const Link&); public: #ifdef _DEBUG void Dump() { for(auto *t = GetNext(); t != this; t = t->GetNext()) LOG(t); LOG("-------------------------------------"); } #endif }; /* template class LinkOwner : public Link { public: ~LinkOwner() { Link::DeleteList(); } }; */ template class LRUCache { public: struct Maker { virtual K Key() const = 0; virtual int Make(T& object) const = 0; virtual ~Maker() {} }; private: struct Item : Moveable { int prev, next; int size; One data; bool flag; }; struct Key : Moveable { K key; String type; bool operator==(const Key& b) const { return key == b.key && type == b.type; } hash_t GetHashValue() const { return CombineHash(key, type); } }; Index key; Vector data; int head; int size; int count; int foundsize; int newsize; bool flag = false; const int InternalSize = 3 * (sizeof(Item) + sizeof(Key) + 24) / 2; void Unlink(int i); void LinkHead(int i); public: int GetSize() const { return size; } int GetCount() const { return count; } template void AdjustSize(P getsize); T& GetLRU(); const K& GetLRUKey(); void DropLRU(); void Shrink(int maxsize, int maxcount = 30000); void ShrinkCount(int maxcount = 30000) { Shrink(INT_MAX, maxcount); } template int Remove(P predicate); template bool RemoveOne(P predicate); template T& Get(const Maker& m, B before_make, A after_make, int& sz); template T& Get(const Maker& m, B before_make, A after_make) { int sz; return Get(m, before_make, after_make, sz); } T& Get(const Maker& m) { return Get(m, []{}, []{}); } void Clear(); void ClearCounters(); int GetFoundSize() const { return foundsize; } int GetNewSize() const { return newsize; } LRUCache() { head = -1; size = 0; count = 0; ClearCounters(); } }; #include "Other.hpp"