///////////////////////////////////////////////// // Hash-Table-Key-Data #pragma pack(push, 1) // pack class size template <class TKey, class TDat> class THashKeyDat{ public: TInt Next; TInt HashCd; TKey Key; TDat Dat; public: THashKeyDat(): Next(-1), HashCd(-1), Key(), Dat(){} THashKeyDat(const int& _Next, const int& _HashCd, const TKey& _Key): Next(_Next), HashCd(_HashCd), Key(_Key), Dat(){} explicit THashKeyDat(TSIn& SIn): Next(SIn), HashCd(SIn), Key(SIn), Dat(SIn){} void Save(TSOut& SOut) const { Next.Save(SOut); HashCd.Save(SOut); Key.Save(SOut); Dat.Save(SOut);} void LoadXml(const PXmlTok& XmlTok, const TStr& Nm=""); void SaveXml(TSOut& SOut, const TStr& Nm) const; bool operator==(const THashKeyDat& HashKeyDat) const { if (this==&HashKeyDat || (HashCd==HashKeyDat.HashCd && Key==HashKeyDat.Key && Dat==HashKeyDat.Dat)){return true;} return false;} THashKeyDat& operator=(const THashKeyDat& HashKeyDat){ if (this!=&HashKeyDat){ Next=HashKeyDat.Next; HashCd=HashKeyDat.HashCd; Key=HashKeyDat.Key; Dat=HashKeyDat.Dat;} return *this;} }; #pragma pack(pop) ///////////////////////////////////////////////// // Hash-Table-Key-Data-Iterator template<class TKey, class TDat> class THashKeyDatI{ private: typedef THashKeyDat<TKey, TDat> TKeyDat; TKeyDat* KeyDatI; TKeyDat* EndI; public: THashKeyDatI(): KeyDatI(NULL), EndI(NULL){} THashKeyDatI(const THashKeyDatI& _HashKeyDatI): KeyDatI(_HashKeyDatI.KeyDatI), EndI(_HashKeyDatI.EndI){} THashKeyDatI(const TKeyDat* _KeyDatI, const TKeyDat* _EndI): KeyDatI((TKeyDat*)_KeyDatI), EndI((TKeyDat*)_EndI){} THashKeyDatI& operator=(const THashKeyDatI& HashKeyDatI){ KeyDatI=HashKeyDatI.KeyDatI; EndI=HashKeyDatI.EndI; return *this;} bool operator==(const THashKeyDatI& HashKeyDatI) const { return KeyDatI==HashKeyDatI.KeyDatI;} bool operator<(const THashKeyDatI& HashKeyDatI) const { return KeyDatI<HashKeyDatI.KeyDatI;} THashKeyDatI& operator++(int){ KeyDatI++; while (KeyDatI < EndI && KeyDatI->HashCd==-1) { KeyDatI++; } return *this; } THashKeyDatI& operator--(int){ do { KeyDatI--; } while (KeyDatI->HashCd==-1); return *this;} TKeyDat& operator*() const { return *KeyDatI; } TKeyDat& operator()() const { return *KeyDatI; } TKeyDat* operator->() const { return KeyDatI; } const TKey& GetKey() const {Assert((KeyDatI!=NULL)&&(KeyDatI->HashCd!=-1)); return KeyDatI->Key;} const TDat& GetDat() const {Assert((KeyDatI!=NULL)&&(KeyDatI->HashCd!=-1)); return KeyDatI->Dat;} TDat& GetDat() {Assert((KeyDatI!=NULL)&&(KeyDatI->HashCd!=-1)); return KeyDatI->Dat;} bool IsEnd() { return EndI == KeyDatI; } }; ///////////////////////////////////////////////// // Default-Hash-Function template<class TKey> class TDefaultHashFunc { public: static inline int GetPrimHashCd(const TKey& Key) { return Key.GetPrimHashCd(); } static inline int GetSecHashCd(const TKey& Key) { return Key.GetSecHashCd(); } }; ///////////////////////////////////////////////// // Hash-Table template<class TKey, class TDat, class THashFunc = TDefaultHashFunc<TKey> > class THash{ public: enum {HashPrimes=32}; static const unsigned int HashPrimeT[HashPrimes]; public: typedef THashKeyDatI<TKey, TDat> TIter; private: typedef THashKeyDat<TKey, TDat> TKeyDat; typedef TPair<TKey, TDat> TKeyDatP; TIntV PortV; TVec<TKeyDat> KeyDatV; TBool AutoSizeP; TInt FFreeKeyId, FreeKeys; private: class THashKeyDatCmp { public: const THash<TKey, TDat, THashFunc>& Hash; bool CmpKey, Asc; THashKeyDatCmp(THash<TKey, TDat, THashFunc>& _Hash, const bool& _CmpKey, const bool& _Asc) : Hash(_Hash), CmpKey(_CmpKey), Asc(_Asc) { } bool operator () (const int& KeyId1, const int& KeyId2) const { if (CmpKey) { if (Asc) { return Hash.GetKey(KeyId1) < Hash.GetKey(KeyId2); } else { return Hash.GetKey(KeyId2) < Hash.GetKey(KeyId1); } } else { if (Asc) { return Hash[KeyId1] < Hash[KeyId2]; } else { return Hash[KeyId2] < Hash[KeyId1]; } } } }; private: TKeyDat& GetHashKeyDat(const int& KeyId){ TKeyDat& KeyDat=KeyDatV[KeyId]; Assert(KeyDat.HashCd!=-1); return KeyDat;} const TKeyDat& GetHashKeyDat(const int& KeyId) const { const TKeyDat& KeyDat=KeyDatV[KeyId]; Assert(KeyDat.HashCd!=-1); return KeyDat;} uint GetNextPrime(const uint& Val) const; void Resize(); public: THash(): PortV(), KeyDatV(), AutoSizeP(true), FFreeKeyId(-1), FreeKeys(0){} THash(const THash& Hash): PortV(Hash.PortV), KeyDatV(Hash.KeyDatV), AutoSizeP(Hash.AutoSizeP), FFreeKeyId(Hash.FFreeKeyId), FreeKeys(Hash.FreeKeys){} explicit THash(const int& ExpectVals, const bool& _AutoSizeP=false); explicit THash(TSIn& SIn): PortV(SIn), KeyDatV(SIn), AutoSizeP(SIn), FFreeKeyId(SIn), FreeKeys(SIn){ SIn.LoadCs();} void Load(TSIn& SIn){ PortV.Load(SIn); KeyDatV.Load(SIn); AutoSizeP=TBool(SIn); FFreeKeyId=TInt(SIn); FreeKeys=TInt(SIn); SIn.LoadCs();} void Save(TSOut& SOut) const { PortV.Save(SOut); KeyDatV.Save(SOut); AutoSizeP.Save(SOut); FFreeKeyId.Save(SOut); FreeKeys.Save(SOut); SOut.SaveCs();} void LoadXml(const PXmlTok& XmlTok, const TStr& Nm=""); void SaveXml(TSOut& SOut, const TStr& Nm); THash& operator=(const THash& Hash){ if (this!=&Hash){ PortV=Hash.PortV; KeyDatV=Hash.KeyDatV; AutoSizeP=Hash.AutoSizeP; FFreeKeyId=Hash.FFreeKeyId; FreeKeys=Hash.FreeKeys;} return *this;} bool operator==(const THash& Hash) const; //J: zdaj tak kot je treba bool operator < (const THash& Hash) const { Fail; return true; } const TDat& operator[](const int& KeyId) const {return GetHashKeyDat(KeyId).Dat;} TDat& operator[](const int& KeyId){return GetHashKeyDat(KeyId).Dat;} TDat& operator()(const TKey& Key){return AddDat(Key);} ::TSize GetMemUsed() const { // return PortV.GetMemUsed()+KeyDatV.GetMemUsed()+sizeof(bool)+2*sizeof(int);} int64 MemUsed = sizeof(bool)+2*sizeof(int); MemUsed += int64(PortV.Reserved()) * int64(sizeof(TInt)); for (int KeyDatN = 0; KeyDatN < KeyDatV.Len(); KeyDatN++) { MemUsed += int64(2 * sizeof(TInt)); MemUsed += int64(KeyDatV[KeyDatN].Key.GetMemUsed()); MemUsed += int64(KeyDatV[KeyDatN].Dat.GetMemUsed()); } return ::TSize(MemUsed); } TIter BegI() const { if (Len()>0){ if (IsKeyIdEqKeyN()) { return TIter(KeyDatV.BegI(), KeyDatV.EndI());} int FKeyId=-1; FNextKeyId(FKeyId); return TIter(KeyDatV.BegI()+FKeyId, KeyDatV.EndI()); } return TIter(KeyDatV.EndI(), KeyDatV.EndI()); } TIter EndI() const {return TIter(KeyDatV.EndI(), KeyDatV.EndI());} //TIter GetI(const int& KeyId) const {return TIter(&KeyDatV[KeyId], KeyDatV.EndI());} TIter GetI(const TKey& Key) const {return TIter(&KeyDatV[GetKeyId(Key)], KeyDatV.EndI());} void Gen(const int& ExpectVals){ PortV.Gen(GetNextPrime(ExpectVals/2)); KeyDatV.Gen(ExpectVals, 0); FFreeKeyId=-1; FreeKeys=0; PortV.PutAll(TInt(-1));} void Clr(const bool& DoDel=true, const int& NoDelLim=-1, const bool& ResetDat=true); bool Empty() const {return Len()==0;} int Len() const {return KeyDatV.Len()-FreeKeys;} int GetPorts() const {return PortV.Len();} bool IsAutoSize() const {return AutoSizeP;} int GetMxKeyIds() const {return KeyDatV.Len();} int GetReservedKeyIds() const {return KeyDatV.Reserved();} bool IsKeyIdEqKeyN() const {return FreeKeys==0;} int AddKey(const TKey& Key); TDat& AddDatId(const TKey& Key){ int KeyId=AddKey(Key); return KeyDatV[KeyId].Dat=KeyId;} TDat& AddDat(const TKey& Key){return KeyDatV[AddKey(Key)].Dat;} TDat& AddDat(const TKey& Key, const TDat& Dat){ return KeyDatV[AddKey(Key)].Dat=Dat;} void DelKey(const TKey& Key); void DelIfKey(const TKey& Key){ int KeyId; if (IsKey(Key, KeyId)){DelKeyId(KeyId);}} void DelKeyId(const int& KeyId){DelKey(GetKey(KeyId));} void DelKeyIdV(const TIntV& KeyIdV){ for (int KeyIdN=0; KeyIdN<KeyIdV.Len(); KeyIdN++){DelKeyId(KeyIdV[KeyIdN]);}} void MarkDelKey(const TKey& Key); // marks the record as deleted - doesn't delete Dat (to avoid fragmentation) void MarkDelKeyId(const int& KeyId){MarkDelKey(GetKey(KeyId));} const TKey& GetKey(const int& KeyId) const { return GetHashKeyDat(KeyId).Key;} int GetKeyId(const TKey& Key) const; int GetRndKeyId(TRnd& Rnd) const { //IAssert((! Empty()) && IsKeyIdEqKeyN()); //return Rnd.GetUniDevInt(Len()); } IAssert(! Empty()); // J: can handle hash tables with deleted entries int KeyId = abs(Rnd.GetUniDevInt(KeyDatV.Len())); while (KeyDatV[KeyId].HashCd == -1) { KeyId = abs(Rnd.GetUniDevInt(KeyDatV.Len())); } return KeyId; } int GetRndKeyId(TRnd& Rnd, const double& EmptyFrac=0.8); bool IsKey(const TKey& Key) const {return GetKeyId(Key)!=-1;} bool IsKey(const TKey& Key, int& KeyId) const { KeyId=GetKeyId(Key); return KeyId!=-1;} bool IsKeyId(const int& KeyId) const { return (0<=KeyId)&&(KeyId<KeyDatV.Len())&&(KeyDatV[KeyId].HashCd!=-1);} const TDat& GetDat(const TKey& Key) const {return KeyDatV[GetKeyId(Key)].Dat;} TDat& GetDat(const TKey& Key){return KeyDatV[GetKeyId(Key)].Dat;} // TKeyDatP GetKeyDat(const int& KeyId) const { // TKeyDat& KeyDat=GetHashKeyDat(KeyId); // return TKeyDatP(KeyDat.Key, KeyDat.Dat);} void GetKeyDat(const int& KeyId, TKey& Key, TDat& Dat) const { const TKeyDat& KeyDat=GetHashKeyDat(KeyId); Key=KeyDat.Key; Dat=KeyDat.Dat;} bool IsKeyGetDat(const TKey& Key, TDat& Dat) const {int KeyId; if (IsKey(Key, KeyId)){Dat=GetHashKeyDat(KeyId).Dat; return true;} else {return false;}} int FFirstKeyId() const {return 0-1;} bool FNextKeyId(int& KeyId) const; void GetKeyV(TVec<TKey>& KeyV) const; void GetDatV(TVec<TDat>& DatV) const; void GetKeyDatPrV(TVec<TPair<TKey, TDat> >& KeyDatPrV) const; void GetDatKeyPrV(TVec<TPair<TDat, TKey> >& DatKeyPrV) const; void Swap(THash& Hash); void Defrag(); void Pack(){KeyDatV.Pack();} void Sort(const bool& CmpKey, const bool& Asc); void SortByKey(const bool& Asc=true) { Sort(true, Asc); } void SortByDat(const bool& Asc=true) { Sort(false, Asc); } }; template<class TKey, class TDat, class THashFunc> const unsigned int THash<TKey, TDat, THashFunc>::HashPrimeT[HashPrimes]={ 3ul, 5ul, 11ul, 23ul, 53ul, 97ul, 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul, 12289ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul }; template<class TKey, class TDat, class THashFunc> uint THash<TKey, TDat, THashFunc>::GetNextPrime(const uint& Val) const { const uint* f=(const uint*)HashPrimeT, *m, *l=(const uint*)HashPrimeT + (int)HashPrimes; int h, len = (int)HashPrimes; while (len > 0) { h = len >> 1; m = f + h; if (*m < Val) { f = m; f++; len = len - h - 1; } else len = h; } return f == l ? *(l - 1) : *f; } template<class TKey, class TDat, class THashFunc> void THash<TKey, TDat, THashFunc>::Resize(){ // resize & initialize port vector //if (PortV.Len()==0){PortV.Gen(17);} //else {PortV.Gen(2*PortV.Len()+1);} if (PortV.Len()==0){ PortV.Gen(17); } else if (AutoSizeP&&(KeyDatV.Len()>2*PortV.Len())){ PortV.Gen(GetNextPrime(PortV.Len()+1)); } else { return; } PortV.PutAll(TInt(-1)); // rehash keys for (int KeyId=0; KeyId<KeyDatV.Len(); KeyId++){ TKeyDat& KeyDat=KeyDatV[KeyId]; if (KeyDat.HashCd!=-1){ const int PortN = abs(THashFunc::GetPrimHashCd(KeyDat.Key) % PortV.Len()); KeyDat.Next=PortV[PortN]; PortV[PortN]=KeyId; } } } template<class TKey, class TDat, class THashFunc> THash<TKey, TDat, THashFunc>::THash(const int& ExpectVals, const bool& _AutoSizeP): PortV(GetNextPrime(ExpectVals/2)), KeyDatV(ExpectVals, 0), AutoSizeP(_AutoSizeP), FFreeKeyId(-1), FreeKeys(0){ PortV.PutAll(TInt(-1)); } template<class TKey, class TDat, class THashFunc> bool THash<TKey, TDat, THashFunc>::operator==(const THash& Hash) const { if (Len() != Hash.Len()) { return false; } for (int i = FFirstKeyId(); FNextKeyId(i); ) { const TKey& Key = GetKey(i); if (! Hash.IsKey(Key)) { return false; } if (GetDat(Key) != Hash.GetDat(Key)) { return false; } } return true; } template<class TKey, class TDat, class THashFunc> void THash<TKey, TDat, THashFunc>::Clr(const bool& DoDel, const int& NoDelLim, const bool& ResetDat){ if (DoDel){ PortV.Clr(); KeyDatV.Clr(); } else { PortV.PutAll(TInt(-1)); KeyDatV.Clr(DoDel, NoDelLim); if (ResetDat){KeyDatV.PutAll(TKeyDat());} } FFreeKeyId=TInt(-1); FreeKeys=TInt(0); } template<class TKey, class TDat, class THashFunc> int THash<TKey, TDat, THashFunc>::AddKey(const TKey& Key){ if ((KeyDatV.Len()>2*PortV.Len())||PortV.Empty()){Resize();} const int PortN=abs(THashFunc::GetPrimHashCd(Key)%PortV.Len()); const int HashCd=abs(THashFunc::GetSecHashCd(Key)); int PrevKeyId=-1; int KeyId=PortV[PortN]; while ((KeyId!=-1) && !((KeyDatV[KeyId].HashCd==HashCd) && (KeyDatV[KeyId].Key==Key))){ PrevKeyId=KeyId; KeyId=KeyDatV[KeyId].Next;} if (KeyId==-1){ if (FFreeKeyId==-1){ KeyId=KeyDatV.Add(TKeyDat(-1, HashCd, Key)); } else { KeyId=FFreeKeyId; FFreeKeyId=KeyDatV[FFreeKeyId].Next; FreeKeys--; //KeyDatV[KeyId]=TKeyDat(-1, HashCd, Key); // slow version KeyDatV[KeyId].Next=-1; KeyDatV[KeyId].HashCd=HashCd; KeyDatV[KeyId].Key=Key; //KeyDatV[KeyId].Dat=TDat(); // already empty } if (PrevKeyId==-1){ PortV[PortN]=KeyId; } else { KeyDatV[PrevKeyId].Next=KeyId; } } return KeyId; } template<class TKey, class TDat, class THashFunc> void THash<TKey, TDat, THashFunc>::DelKey(const TKey& Key){ IAssert(!PortV.Empty()); const int PortN=abs(THashFunc::GetPrimHashCd(Key)%PortV.Len()); const int HashCd=abs(THashFunc::GetSecHashCd(Key)); int PrevKeyId=-1; int KeyId=PortV[PortN]; while ((KeyId!=-1) && !((KeyDatV[KeyId].HashCd==HashCd) && (KeyDatV[KeyId].Key==Key))){ PrevKeyId=KeyId; KeyId=KeyDatV[KeyId].Next;} //IAssertR(KeyId!=-1, Key.GetStr()); //J: vsi razredi nimajo nujno funkcije GetStr()? IAssert(KeyId!=-1); //J: vsi razredi nimajo nujno funkcije GetStr()? if (PrevKeyId==-1){PortV[PortN]=KeyDatV[KeyId].Next;} else {KeyDatV[PrevKeyId].Next=KeyDatV[KeyId].Next;} KeyDatV[KeyId].Next=FFreeKeyId; FFreeKeyId=KeyId; FreeKeys++; KeyDatV[KeyId].HashCd=TInt(-1); KeyDatV[KeyId].Key=TKey(); KeyDatV[KeyId].Dat=TDat(); } template<class TKey, class TDat, class THashFunc> void THash<TKey, TDat, THashFunc>::MarkDelKey(const TKey& Key){ // MarkDelKey is same as Delkey expect last two lines IAssert(!PortV.Empty()); const int PortN=abs(THashFunc::GetPrimHashCd(Key)%PortV.Len()); const int HashCd=abs(THashFunc::GetSecHashCd(Key)); int PrevKeyId=-1; int KeyId=PortV[PortN]; while ((KeyId!=-1) && !((KeyDatV[KeyId].HashCd==HashCd) && (KeyDatV[KeyId].Key==Key))){ PrevKeyId=KeyId; KeyId=KeyDatV[KeyId].Next;} IAssertR(KeyId!=-1, Key.GetStr()); if (PrevKeyId==-1){PortV[PortN]=KeyDatV[KeyId].Next;} else {KeyDatV[PrevKeyId].Next=KeyDatV[KeyId].Next;} KeyDatV[KeyId].Next=FFreeKeyId; FFreeKeyId=KeyId; FreeKeys++; KeyDatV[KeyId].HashCd=TInt(-1); } // return random KeyId even if the hash table contains deleted keys // defrags the table if necessary template<class TKey, class TDat, class THashFunc> int THash<TKey, TDat, THashFunc>::GetRndKeyId(TRnd& Rnd, const double& EmptyFrac) { IAssert(! Empty()); if (FreeKeys/double(Len()+FreeKeys) > EmptyFrac) { Defrag(); } int KeyId = Rnd.GetUniDevInt(KeyDatV.Len()); while (KeyDatV[KeyId].HashCd == -1) { KeyId = Rnd.GetUniDevInt(KeyDatV.Len()); } return KeyId; } template<class TKey, class TDat, class THashFunc> int THash<TKey, TDat, THashFunc>::GetKeyId(const TKey& Key) const { if (PortV.Empty()){return -1;} const int PortN=abs(THashFunc::GetPrimHashCd(Key)%PortV.Len()); const int HashCd=abs(THashFunc::GetSecHashCd(Key)); int KeyId=PortV[PortN]; while ((KeyId!=-1) && !((KeyDatV[KeyId].HashCd==HashCd) && (KeyDatV[KeyId].Key==Key))){ KeyId=KeyDatV[KeyId].Next;} return KeyId; } template<class TKey, class TDat, class THashFunc> bool THash<TKey, TDat, THashFunc>::FNextKeyId(int& KeyId) const { do {KeyId++;} while ((KeyId<KeyDatV.Len())&&(KeyDatV[KeyId].HashCd==-1)); return KeyId<KeyDatV.Len(); } template<class TKey, class TDat, class THashFunc> void THash<TKey, TDat, THashFunc>::GetKeyV(TVec<TKey>& KeyV) const { KeyV.Gen(Len(), 0); int KeyId=FFirstKeyId(); while (FNextKeyId(KeyId)){ KeyV.Add(GetKey(KeyId));} } template<class TKey, class TDat, class THashFunc> void THash<TKey, TDat, THashFunc>::GetDatV(TVec<TDat>& DatV) const { DatV.Gen(Len(), 0); int KeyId=FFirstKeyId(); while (FNextKeyId(KeyId)){ DatV.Add(GetHashKeyDat(KeyId).Dat);} } template<class TKey, class TDat, class THashFunc> void THash<TKey, TDat, THashFunc>::GetKeyDatPrV(TVec<TPair<TKey, TDat> >& KeyDatPrV) const { KeyDatPrV.Gen(Len(), 0); TKey Key; TDat Dat; int KeyId=FFirstKeyId(); while (FNextKeyId(KeyId)){ GetKeyDat(KeyId, Key, Dat); KeyDatPrV.Add(TPair<TKey, TDat>(Key, Dat)); } } template<class TKey, class TDat, class THashFunc> void THash<TKey, TDat, THashFunc>::GetDatKeyPrV(TVec<TPair<TDat, TKey> >& DatKeyPrV) const { DatKeyPrV.Gen(Len(), 0); TKey Key; TDat Dat; int KeyId=FFirstKeyId(); while (FNextKeyId(KeyId)){ GetKeyDat(KeyId, Key, Dat); DatKeyPrV.Add(TPair<TDat, TKey>(Dat, Key)); } } template<class TKey, class TDat, class THashFunc> void THash<TKey, TDat, THashFunc>::Swap(THash& Hash) { if (this!=&Hash){ PortV.Swap(Hash.PortV); KeyDatV.Swap(Hash.KeyDatV); ::Swap(AutoSizeP, Hash.AutoSizeP); ::Swap(FFreeKeyId, Hash.FFreeKeyId); ::Swap(FreeKeys, Hash.FreeKeys); } } template<class TKey, class TDat, class THashFunc> void THash<TKey, TDat, THashFunc>::Defrag(){ if (!IsKeyIdEqKeyN()){ THash<TKey, TDat, THashFunc> Hash(PortV.Len()); int KeyId=FFirstKeyId(); TKey Key; TDat Dat; while (FNextKeyId(KeyId)){ GetKeyDat(KeyId, Key, Dat); Hash.AddDat(Key, Dat); } Pack(); operator=(Hash); IAssert(IsKeyIdEqKeyN()); } } template<class TKey, class TDat, class THashFunc> void THash<TKey, TDat, THashFunc>::Sort(const bool& CmpKey, const bool& Asc) { IAssertR(IsKeyIdEqKeyN(), "THash::Sort only works when table has no deleted keys."); TIntV TargV(Len()), MapV(Len()), StateV(Len()); for (int i = 0; i < TargV.Len(); i++) { TargV[i] = i; MapV[i] = i; StateV[i] = i; } // sort KeyIds THashKeyDatCmp HashCmp(*this, CmpKey, Asc); TargV.SortCmp(HashCmp); // now sort the update vector THashKeyDat<TKey, TDat> Tmp; for (int i = 0; i < TargV.Len()-1; i++) { const int SrcPos = MapV[TargV[i]]; const int Loc = i; // swap data Tmp = KeyDatV[SrcPos]; KeyDatV[SrcPos] = KeyDatV[Loc]; KeyDatV[Loc] = Tmp; // swap keys MapV[StateV[i]] = SrcPos; StateV.Swap(Loc, SrcPos); } for (int i = 0; i < TargV.Len(); i++) { MapV[TargV[i]] = i; } for (int p = 0; p < PortV.Len(); p++) { if (PortV[p] != -1) { PortV[p] = MapV[PortV[p]]; } } for (int i = 0; i < KeyDatV.Len(); i++) { if (KeyDatV[i].Next != -1) { KeyDatV[i].Next = MapV[KeyDatV[i].Next]; } } } ///////////////////////////////////////////////// // Common-Hash-Types typedef THash<TCh, TCh> TChChH; typedef THash<TChTr, TInt> TChTrIntH; typedef THash<TInt, TInt> TIntH; typedef THash<TUInt64, TInt> TUInt64H; typedef THash<TInt, TBool> TIntBoolH; typedef THash<TInt, TInt> TIntIntH; typedef THash<TInt, TIntFltPr> TIntIntFltPrH; typedef THash<TInt, TIntV> TIntIntVH; typedef THash<TInt, TIntH> TIntIntHH; typedef THash<TInt, TFlt> TIntFltH; typedef THash<TInt, TFltPr> TIntFltPrH; typedef THash<TInt, TFltTr> TIntFltTrH; typedef THash<TInt, TFltV> TIntFltVH; typedef THash<TInt, TStr> TIntStrH; typedef THash<TInt, TStrV> TIntStrVH; typedef THash<TInt, TIntPr> TIntIntPrH; typedef THash<TInt, TIntPrV> TIntIntPrVH; typedef THash<TIntPr, TInt> TIntPrIntH; typedef THash<TIntPr, TIntV> TIntPrIntVH; typedef THash<TIntPr, TIntPrV> TIntPrIntPrVH; typedef THash<TIntTr, TInt> TIntTrIntH; typedef THash<TIntV, TInt> TIntVIntH; typedef THash<TUInt, TUInt> TUIntH; typedef THash<TIntPr, TInt> TIntPrIntH; typedef THash<TIntPr, TIntV> TIntPrIntVH; typedef THash<TIntPr, TFlt> TIntPrFltH; typedef THash<TIntTr, TFlt> TIntTrFltH; typedef THash<TIntPr, TStr> TIntPrStrH; typedef THash<TIntPr, TStrV> TIntPrStrVH; typedef THash<TIntStrPr, TInt> TIntStrPrIntH; typedef THash<TFlt, TFlt> TFltFltH; typedef THash<TStr, TInt> TStrH; typedef THash<TStr, TBool> TStrBoolH; typedef THash<TStr, TInt> TStrIntH; typedef THash<TStr, TIntPr> TStrIntPrH; typedef THash<TStr, TIntV> TStrIntVH; typedef THash<TStr, TIntPrV> TStrIntPrVH; typedef THash<TStr, TFlt> TStrFltH; typedef THash<TStr, TFltV> TStrFltVH; typedef THash<TStr, TStr> TStrStrH; typedef THash<TStr, TStrPr> TStrStrPrH; typedef THash<TStr, TStrV> TStrStrVH; typedef THash<TStr, TStrPrV> TStrStrPrVH; typedef THash<TStr, TStrKdV> TStrStrKdVH; typedef THash<TStr, TIntFltPr> TStrIntFltPrH; typedef THash<TStr, TStrIntPrV> TStrStrIntPrVH; typedef THash<TStr, TStrIntKdV> TStrStrIntKdVH; typedef THash<TDbStr, TInt> TDbStrIntH; typedef THash<TDbStr, TStr> TDbStrStrH; typedef THash<TStrPr, TBool> TStrPrBoolH; typedef THash<TStrPr, TInt> TStrPrIntH; typedef THash<TStrPr, TFlt> TStrPrFltH; typedef THash<TStrPr, TStr> TStrPrStrH; typedef THash<TStrPr, TStrV> TStrPrStrVH; typedef THash<TStrTr, TInt> TStrTrIntH; typedef THash<TStrIntPr, TInt> TStrIntPrIntH; typedef THash<TStrV, TInt> TStrVH; typedef THash<TStrV, TInt> TStrVIntH; typedef THash<TStrV, TIntV> TStrVIntVH; typedef THash<TStrV, TStr> TStrVStrH; typedef THash<TStrV, TStrV> TStrVStrVH; ///////////////////////////////////////////////// // Hash-Pointer template <class TKey, class TDat> class PHash{ private: TCRef CRef; public: THash<TKey, TDat> H; public: PHash<TKey, TDat>(): H(){} static TPt<PHash<TKey, TDat> > New(){ return new PHash<TKey, TDat>();} PHash<TKey, TDat>(const int& MxVals, const int& Vals): H(MxVals, Vals){} static TPt<PHash<TKey, TDat> > New(const int& MxVals, const int& Vals){ return new PHash<TKey, TDat>(MxVals, Vals);} PHash<TKey, TDat>(const THash<TKey, TDat>& _V): H(_V){} static TPt<PHash<TKey, TDat> > New(const THash<TKey, TDat>& H){ return new PHash<TKey, TDat>(H);} explicit PHash<TKey, TDat>(TSIn& SIn): H(SIn){} static TPt<PHash<TKey, TDat> > Load(TSIn& SIn){return new PHash<TKey, TDat>(SIn);} void Save(TSOut& SOut) const {H.Save(SOut);} PHash<TKey, TDat>& operator=(const PHash<TKey, TDat>& Vec){ if (this!=&Vec){H=Vec.H;} return *this;} bool operator==(const PHash<TKey, TDat>& Vec) const {return H==Vec.H;} bool operator<(const PHash<TKey, TDat>& Vec) const {return H<Vec.H;} friend class TPt<PHash<TKey, TDat> >; }; ///////////////////////////////////////////////// // Big-String-Pool (holds up to 2 giga strings, storage overhead is 8(4) bytes per string) //J: have to put it here since it uses TVec (can't be in dt.h) ClassTP(TBigStrPool, PBigStrPool)//{ private: TSize MxBfL, BfL; uint GrowBy; char *Bf; TVec<TSize> IdOffV; // string ID to offset private: void Resize(TSize _MxBfL); public: TBigStrPool(TSize MxBfLen = 0, uint _GrowBy = 16*1024*1024); TBigStrPool(TSIn& SIn, bool LoadCompact = true); TBigStrPool(const TBigStrPool& Pool) : MxBfL(Pool.MxBfL), BfL(Pool.BfL), GrowBy(Pool.GrowBy) { Bf = (char *) malloc(Pool.MxBfL); IAssert(Bf); memcpy(Bf, Pool.Bf, Pool.BfL); } ~TBigStrPool() { if (Bf) free(Bf); else IAssert(MxBfL == 0); MxBfL = 0; BfL = 0; } static PBigStrPool New(TSize _MxBfLen = 0, uint _GrowBy = 16*1024*1024) { return PBigStrPool(new TBigStrPool(_MxBfLen, _GrowBy)); } static PBigStrPool New(TSIn& SIn) { return new TBigStrPool(SIn); } static PBigStrPool New(const TStr& fileName) { PSIn SIn = TFIn::New(fileName); return new TBigStrPool(*SIn); } static PBigStrPool Load(TSIn& SIn, bool LoadCompacted = true) { return PBigStrPool(new TBigStrPool(SIn, LoadCompacted)); } void Save(TSOut& SOut) const; void Save(const TStr& fileName) { TFOut FOut(fileName); Save(FOut); } int GetStrs() const { return IdOffV.Len(); } TSize Len() const { return BfL; } TSize Size() const { return MxBfL; } bool Empty() const { return ! Len(); } char* operator () () const { return Bf; } TBigStrPool& operator = (const TBigStrPool& Pool); int AddStr(const char *Str, uint Len); int AddStr(const char *Str) { return AddStr(Str, uint(strlen(Str)) + 1); } int AddStr(const TStr& Str) { return AddStr(Str.CStr(), Str.Len() + 1); } TStr GetStr(const int& StrId) const { Assert(StrId < GetStrs()); if (StrId == 0) return TStr::GetNullStr(); else return TStr(Bf + (TSize)IdOffV[StrId]); } const char *GetCStr(const int& StrId) const { Assert(StrId < GetStrs()); if (StrId == 0) return TStr::GetNullStr().CStr(); else return (Bf + (TSize)IdOffV[StrId]); } TStr GetStrFromOffset(const TSize& Offset) const { Assert(Offset < BfL); if (Offset == 0) return TStr::GetNullStr(); else return TStr(Bf + Offset); } const char *GetCStrFromOffset(const TSize& Offset) const { Assert(Offset < BfL); if (Offset == 0) return TStr::GetNullStr().CStr(); else return Bf + Offset; } void Clr(bool DoDel = false) { BfL = 0; if (DoDel && Bf) { free(Bf); Bf = 0; MxBfL = 0; } } int Cmp(const int& StrId, const char *Str) const { Assert(StrId < GetStrs()); if (StrId != 0) return strcmp(Bf + (TSize)IdOffV[StrId], Str); else return strcmp("", Str); } static int GetPrimHashCd(const char *CStr); static int GetSecHashCd(const char *CStr); int GetPrimHashCd(const int& StrId) { Assert(StrId < GetStrs()); if (StrId != 0) return GetPrimHashCd(Bf + (TSize)IdOffV[StrId]); else return GetPrimHashCd(""); } int GetSecHashCd(const int& StrId) { Assert(StrId < GetStrs()); if (StrId != 0) return GetSecHashCd(Bf + (TSize)IdOffV[StrId]); else return GetSecHashCd(""); } }; ///////////////////////////////////////////////// // String-Hash-Table template <class TDat, class TStringPool = TStrPool, class THashFunc = TDefaultHashFunc<TStr> > class TStrHash{ private: //typedef typename PStringPool::TObj TStringPool; typedef TPt<TStringPool> PStringPool; typedef THashKeyDat<TInt, TDat> TKeyDat; typedef TPair<TInt, TDat> TKeyDatP; typedef TVec<TKeyDat> TKeyDatV; TIntV PortV; TKeyDatV KeyDatV; TBool AutoSizeP; TInt FFreeKeyId, FreeKeys; PStringPool Pool; private: uint GetNextPrime(const uint& Val) const; void Resize(); const TKeyDat& GetHashKeyDat(const int& KeyId) const { const TKeyDat& KeyDat = KeyDatV[KeyId]; Assert(KeyDat.HashCd != -1); return KeyDat; } TKeyDat& GetHashKeyDat(const int& KeyId) { TKeyDat& KeyDat = KeyDatV[KeyId]; Assert(KeyDat.HashCd != -1); return KeyDat; } public: TStrHash(): PortV(), KeyDatV(), AutoSizeP(true), FFreeKeyId(-1), FreeKeys(0), Pool() { } TStrHash(const PStringPool& StrPool): PortV(), KeyDatV(), AutoSizeP(true), FFreeKeyId(-1), FreeKeys(0), Pool(StrPool) { } TStrHash(const int& Ports, const bool& _AutoSizeP = false, const PStringPool& StrPool = PStringPool()) : PortV(Ports), KeyDatV(Ports, 0), AutoSizeP(_AutoSizeP), FFreeKeyId(-1), FreeKeys(0), Pool(StrPool) { PortV.PutAll(-1); } TStrHash(const TStrHash& Hash): PortV(Hash.PortV), KeyDatV(Hash.KeyDatV), AutoSizeP(Hash.AutoSizeP), FFreeKeyId(Hash.FFreeKeyId), FreeKeys(Hash.FreeKeys), Pool() { if (! Hash.Pool.Empty()) { Pool=PStringPool(new TStringPool(*Hash.Pool)); } } TStrHash(TSIn& SIn, bool PoolToo = true): PortV(SIn), KeyDatV(SIn), AutoSizeP(SIn), FFreeKeyId(SIn), FreeKeys(SIn){ SIn.LoadCs(); if (PoolToo) Pool = PStringPool(SIn); } void Load(TSIn& SIn, bool PoolToo = true) { PortV.Load(SIn); KeyDatV.Load(SIn); AutoSizeP.Load(SIn); FFreeKeyId.Load(SIn); FreeKeys.Load(SIn); SIn.LoadCs(); if (PoolToo) Pool = PStringPool(SIn); } void Save(TSOut& SOut, bool PoolToo = true) const { PortV.Save(SOut); KeyDatV.Save(SOut); AutoSizeP.Save(SOut); FFreeKeyId.Save(SOut); FreeKeys.Save(SOut); SOut.SaveCs(); if (PoolToo) Pool.Save(SOut); } void SetPool(const PStringPool& StrPool) { IAssert(Pool.Empty() || Pool->Empty()); Pool = StrPool; } PStringPool GetPool() const { return Pool; } TStrHash& operator = (const TStrHash& Hash); bool Empty() const {return ! Len(); } int Len() const { return KeyDatV.Len() - FreeKeys; } int Reserved() const { return KeyDatV.Reserved(); } int GetPorts() const { return PortV.Len(); } bool IsAutoSize() const { return AutoSizeP; } int GetMxKeyIds() const { return KeyDatV.Len(); } bool IsKeyIdEqKeyN() const {return ! FreeKeys; } int AddKey(const char *Key); int AddKey(const TStr& Key) { return AddKey(Key.CStr()); } int AddKey(const TChA& Key) { return AddKey(Key.CStr()); } int AddDat(const char *Key, const TDat& Dat) { const int KeyId = AddKey(Key); KeyDatV[KeyId].Dat = Dat; return KeyId; } int AddDat(const TStr& Key, const TDat& Dat) { const int KeyId = AddKey(Key.CStr()); KeyDatV[KeyId].Dat = Dat; return KeyId; } int AddDat(const TChA& Key, const TDat& Dat) { const int KeyId = AddKey(Key.CStr()); KeyDatV[KeyId].Dat = Dat; return KeyId; } TDat& AddDat(const char *Key) { return KeyDatV[AddKey(Key)].Dat; } TDat& AddDat(const TStr& Key) { return KeyDatV[AddKey(Key.CStr())].Dat; } TDat& AddDat(const TChA& Key) { return KeyDatV[AddKey(Key.CStr())].Dat; } TDat& AddDatId(const char *Key) { const int KeyId = AddKey(Key); return KeyDatV[KeyId].Dat = KeyId; } TDat& AddDatId(const TStr& Key) { const int KeyId = AddKey(Key.CStr()); return KeyDatV[KeyId].Dat = KeyId; } TDat& AddDatId(const TChA& Key) { const int KeyId = AddKey(Key.CStr()); return KeyDatV[KeyId].Dat = KeyId; } const TDat& operator[](const int& KeyId) const {return GetHashKeyDat(KeyId).Dat;} TDat& operator[](const int& KeyId){return GetHashKeyDat(KeyId).Dat;} const TDat& operator () (const char *Key) const { return GetDat(Key);} //TDat& operator ()(const char *Key){return AddDat(Key);} // add if not found const TDat& GetDat(const char *Key) const { return KeyDatV[GetKeyId(Key)].Dat; } const TDat& GetDat(const TStr& Key) const { return GetDat(Key.CStr()); } TDat& GetDat(const char *Key) { return KeyDatV[GetKeyId(Key)].Dat; } const TDat& GetDat(const TStr& Key) { return GetDat(Key.CStr()); } const TDat& GetDat(const TChA& Key) { return GetDat(Key.CStr()); } TDat& GetDatId(const int& KeyId) { return KeyDatV[KeyId].Dat; } const TDat& GetDatId(const int& KeyId) const { return KeyDatV[KeyId].Dat; } void GetKeyDat(const int& KeyId, int& KeyO, TDat& Dat) const { const TKeyDat& KeyDat = GetHashKeyDat(KeyId); KeyO = KeyDat.Key; Dat = KeyDat.Dat; } void GetKeyDat(const int& KeyId, const char*& Key, TDat& Dat) const { const TKeyDat& KeyDat = GetHashKeyDat(KeyId); Key = KeyFromOfs(KeyDat.Key); Dat = KeyDat.Dat; } void GetKeyDat(const int& KeyId, TStr& Key, TDat& Dat) const { const TKeyDat& KeyDat = GetHashKeyDat(KeyId); Key = KeyFromOfs(KeyDat.Key); Dat = KeyDat.Dat;} void GetKeyDat(const int& KeyId, TChA& Key, TDat& Dat) const { const TKeyDat& KeyDat = GetHashKeyDat(KeyId); Key = KeyFromOfs(KeyDat.Key); Dat = KeyDat.Dat;} int GetKeyId(const char *Key) const; int GetKeyId(const TStr& Key) const { return GetKeyId(Key.CStr()); } const char *GetKey(const int& KeyId) const { return Pool->GetCStr(GetHashKeyDat(KeyId).Key); } int GetKeyOfs(const int& KeyId) const { return GetHashKeyDat(KeyId).Key; } // pool string id const char *KeyFromOfs(const int& KeyO) const { return Pool->GetCStr(KeyO); } bool IsKey(const char *Key) const { return GetKeyId(Key) != -1; } bool IsKey(const TStr& Key) const { return GetKeyId(Key.CStr()) != -1; } bool IsKey(const TChA& Key) const { return GetKeyId(Key.CStr()) != -1; } bool IsKey(const char *Key, int& KeyId) const { KeyId = GetKeyId(Key); return KeyId != -1; } bool IsKeyGetDat(const char *Key, TDat& Dat) const { const int KeyId = GetKeyId(Key); if (KeyId != -1) { Dat = KeyDatV[KeyId].Dat; return true; } else return false; } bool IsKeyGetDat(const TStr& Key, TDat& Dat) const { const int KeyId = GetKeyId(Key.CStr()); if (KeyId != -1) { Dat = KeyDatV[KeyId].Dat; return true; } else return false; } bool IsKeyGetDat(const TChA& Key, TDat& Dat) const { const int KeyId = GetKeyId(Key.CStr()); if (KeyId != -1) { Dat = KeyDatV[KeyId].Dat; return true; } else return false; } bool IsKeyId(const int& KeyId) const { return 0 <= KeyId && KeyId < KeyDatV.Len() && KeyDatV[KeyId].HashCd != -1; } int FFirstKeyId() const {return 0-1;} bool FNextKeyId(int& KeyId) const; void GetKeyV(TVec<TStr>& KeyV) const; void GetStrIdV(TIntV& StrIdV) const; void GetDatV(TVec<TDat>& DatV) const; void GetKeyDatPrV(TVec<TPair<TStr, TDat> >& KeyDatPrV) const; void GetDatKeyPrV(TVec<TPair<TDat, TStr> >& DatKeyPrV) const; void Pack(){KeyDatV.Pack();} }; template <class TDat, class TStringPool, class THashFunc> uint TStrHash<TDat, TStringPool, THashFunc>::GetNextPrime(const uint& Val) const { uint *f = (uint *) TIntH::HashPrimeT, *m, *l = (uint *) TIntH::HashPrimeT + (int) TIntH::HashPrimes; int h, len = (int)TIntH::HashPrimes; while (len > 0) { h = len >> 1; m = f + h; if (*m < Val) { f = m; f++; len = len - h - 1; } else len = h; } return f == l ? *(l - 1) : *f; } template <class TDat, class TStringPool, class THashFunc> void TStrHash<TDat, TStringPool, THashFunc>::Resize() { // resize & initialize port vector if (PortV.Empty()) { PortV.Gen(17); PortV.PutAll(-1); } else if (AutoSizeP && KeyDatV.Len() > 3 * PortV.Len()) { const int NxPrime = GetNextPrime(KeyDatV.Len()); //printf("%s resize PortV: %d -> %d, Len: %d\n", GetTypeNm(*this).CStr(), PortV.Len(), NxPrime, Len()); PortV.Gen(NxPrime); PortV.PutAll(-1); } else return; // rehash keys const int NPorts = PortV.Len(); for (int i = 0; i < KeyDatV.Len(); i++) { TKeyDat& KeyDat = KeyDatV[i]; if (KeyDat.HashCd != -1) { const int Port = abs(THashFunc::GetPrimHashCd(Pool->GetCStr(KeyDat.Key)) % NPorts); KeyDat.Next = PortV[Port]; PortV[Port] = i; } } } template <class TDat, class TStringPool, class THashFunc> TStrHash<TDat, TStringPool, THashFunc>& TStrHash<TDat, TStringPool, THashFunc>:: operator = (const TStrHash& Hash) { if (this != &Hash) { PortV = Hash.PortV; KeyDatV = Hash.KeyDatV; AutoSizeP = Hash.AutoSizeP; FFreeKeyId = Hash.FFreeKeyId; FreeKeys = Hash.FreeKeys; if (! Hash.Pool.Empty()) Pool = PStringPool(new TStringPool(*Hash.Pool)); else Pool = NULL; } return *this; } template <class TDat, class TStringPool, class THashFunc> int TStrHash<TDat, TStringPool, THashFunc>::AddKey(const char *Key) { if (Pool.Empty()) Pool = TStringPool::New(); if ((AutoSizeP && KeyDatV.Len() > PortV.Len()) || PortV.Empty()) Resize(); const int PortN = abs(THashFunc::GetPrimHashCd(Key) % PortV.Len()); const int HashCd = abs(THashFunc::GetSecHashCd(Key)); int PrevKeyId = -1; int KeyId = PortV[PortN]; while (KeyId != -1 && ! (KeyDatV[KeyId].HashCd == HashCd && Pool->Cmp(KeyDatV[KeyId].Key, Key) == 0)) { PrevKeyId = KeyId; KeyId = KeyDatV[KeyId].Next; } if (KeyId == -1) { const int StrId = Pool->AddStr(Key); if (FFreeKeyId == -1) { KeyId = KeyDatV.Add(TKeyDat(-1, HashCd, StrId)); } else { KeyId = FFreeKeyId; FFreeKeyId = KeyDatV[FFreeKeyId].Next; FreeKeys--; KeyDatV[KeyId] = TKeyDat(-1, HashCd, StrId); } if (PrevKeyId == -1) PortV[PortN] = KeyId; else KeyDatV[PrevKeyId].Next = KeyId; } return KeyId; } template <class TDat, class TStringPool, class THashFunc> int TStrHash<TDat, TStringPool, THashFunc>::GetKeyId(const char *Key) const { if (PortV.Empty()) return -1; const int PortN = abs(THashFunc::GetPrimHashCd(Key) % PortV.Len()); const int Hc = abs(THashFunc::GetSecHashCd(Key)); int KeyId = PortV[PortN]; while (KeyId != -1 && ! (KeyDatV[KeyId].HashCd == Hc && Pool->Cmp(KeyDatV[KeyId].Key, Key) == 0)) KeyId = KeyDatV[KeyId].Next; return KeyId; } template <class TDat, class TStringPool, class THashFunc> bool TStrHash<TDat, TStringPool, THashFunc>::FNextKeyId(int& KeyId) const { do KeyId++; while (KeyId < KeyDatV.Len() && KeyDatV[KeyId].HashCd == -1); return KeyId < KeyDatV.Len(); } template <class TDat, class TStringPool, class THashFunc> void TStrHash<TDat, TStringPool, THashFunc>::GetKeyV(TVec<TStr>& KeyV) const { KeyV.Gen(Len(), 0); int KeyId = FFirstKeyId(); while (FNextKeyId(KeyId)) KeyV.Add(GetKey(KeyId)); } template <class TDat, class TStringPool, class THashFunc> void TStrHash<TDat, TStringPool, THashFunc>::GetStrIdV(TIntV& StrIdV) const { StrIdV.Gen(Len(), 0); int KeyId = FFirstKeyId(); while (FNextKeyId(KeyId)) StrIdV.Add(GetKeyOfs(KeyId)); } template <class TDat, class TStringPool, class THashFunc> void TStrHash<TDat, TStringPool, THashFunc>::GetDatV(TVec<TDat>& DatV) const { DatV.Gen(Len(), 0); int KeyId = FFirstKeyId(); while (FNextKeyId(KeyId)) DatV.Add(GetHashKeyDat(KeyId).Dat); } template <class TDat, class TStringPool, class THashFunc> void TStrHash<TDat, TStringPool, THashFunc>::GetKeyDatPrV(TVec<TPair<TStr, TDat> >& KeyDatPrV) const { KeyDatPrV.Gen(Len(), 0); TStr Str; TDat Dat; int KeyId = FFirstKeyId(); while (FNextKeyId(KeyId)){ GetKeyDat(KeyId, Str, Dat); KeyDatPrV.Add(TPair<TStr, TDat>(Str, Dat)); } } template <class TDat, class TStringPool, class THashFunc> void TStrHash<TDat, TStringPool, THashFunc>::GetDatKeyPrV(TVec<TPair<TDat, TStr> >& DatKeyPrV) const { DatKeyPrV.Gen(Len(), 0); TStr Str; TDat Dat; int KeyId = FFirstKeyId(); while (FNextKeyId(KeyId)){ GetKeyDat(KeyId, Str, Dat); DatKeyPrV.Add(TPair<TDat, TStr>(Dat, Str)); } } ///////////////////////////////////////////////// // Common-String-Hash-Types typedef TStrHash<TInt> TStrSH; typedef TStrHash<TInt> TStrIntSH; typedef TStrHash<TIntV> TStrToIntVSH; ///////////////////////////////////////////////// // Cache template <class TKey, class TDat, class THashFunc = TDefaultHashFunc<TKey> > class TCache{ private: typedef TLst<TKey> TKeyL; typedef TLstNd<TKey>* TKeyLN; typedef TPair<TKeyLN, TDat> TKeyLNDatPr; int64 MxMemUsed; int64 CurMemUsed; THash<TKey, TKeyLNDatPr, THashFunc> KeyDatH; TKeyL TimeKeyL; void* RefToBs; void Purge(const int64& MemToPurge); public: TCache(){} TCache(const TCache&); TCache(const int64& _MxMemUsed, const int& Ports, void* _RefToBs): MxMemUsed(_MxMemUsed), CurMemUsed(0), KeyDatH(Ports), TimeKeyL(), RefToBs(_RefToBs){} TCache& operator=(const TCache&); int64 GetMemUsed() const; void RefreshMemUsed(); void Put(const TKey& Key, const TDat& Dat); bool Get(const TKey& Key, TDat& Dat); void Del(const TKey& Key, const bool& DoEventCall=true); void Flush(); void FlushAndClr(); void* FFirstKeyDat(); bool FNextKeyDat(void*& KeyDatP, TKey& Key, TDat& Dat); void PutRefToBs(void* _RefToBs){RefToBs=_RefToBs;} void* GetRefToBs(){return RefToBs;} }; template <class TKey, class TDat, class THashFunc> void TCache<TKey, TDat, THashFunc>::Purge(const int64& MemToPurge){ while (!TimeKeyL.Empty()&&(MxMemUsed-CurMemUsed<MemToPurge)){ TKey Key=TimeKeyL.Last()->GetVal(); Del(Key); } } template <class TKey, class TDat, class THashFunc> int64 TCache<TKey, TDat, THashFunc>::GetMemUsed() const { int64 MemUsed=0; int KeyId=KeyDatH.FFirstKeyId(); while (KeyDatH.FNextKeyId(KeyId)){ const TKey& Key=KeyDatH.GetKey(KeyId); const TKeyLNDatPr& KeyLNDatPr=KeyDatH[KeyId]; TDat Dat=KeyLNDatPr.Val2; MemUsed+=int64(Key.GetMemUsed()+Dat->GetMemUsed()); } return MemUsed; } template <class TKey, class TDat, class THashFunc> void TCache<TKey, TDat, THashFunc>::RefreshMemUsed(){ CurMemUsed=GetMemUsed(); if (CurMemUsed>MxMemUsed){ Purge(CurMemUsed-MxMemUsed);} } template <class TKey, class TDat, class THashFunc> void TCache<TKey, TDat, THashFunc>::Put(const TKey& Key, const TDat& Dat){ int KeyId=KeyDatH.GetKeyId(Key); if (KeyId==-1){ int64 KeyDatMem=int64(Key.GetMemUsed()+Dat->GetMemUsed()); if (CurMemUsed+KeyDatMem>MxMemUsed){Purge(KeyDatMem);} CurMemUsed+=KeyDatMem; TKeyLN KeyLN=TimeKeyL.AddFront(Key); TKeyLNDatPr KeyLNDatPr(KeyLN, Dat); KeyDatH.AddDat(Key, KeyLNDatPr); } else { TKeyLNDatPr& KeyLNDatPr=KeyDatH[KeyId]; TKeyLN KeyLN=KeyLNDatPr.Val1; KeyLNDatPr.Val2=Dat; TimeKeyL.PutFront(KeyLN); } } template <class TKey, class TDat, class THashFunc> bool TCache<TKey, TDat, THashFunc>::Get(const TKey& Key, TDat& Dat){ int KeyId=KeyDatH.GetKeyId(Key); if (KeyId==-1){ return false; } else { Dat=KeyDatH[KeyId].Val2; return true; } } template <class TKey, class TDat, class THashFunc> void TCache<TKey, TDat, THashFunc>::Del(const TKey& Key, const bool& DoEventCall){ int KeyId=KeyDatH.GetKeyId(Key); if (KeyId!=-1){ TKeyLNDatPr& KeyLNDatPr=KeyDatH[KeyId]; TKeyLN KeyLN=KeyLNDatPr.Val1; TDat& Dat=KeyLNDatPr.Val2; if (DoEventCall){ Dat->OnDelFromCache(Key, RefToBs);} CurMemUsed-=int64(Key.GetMemUsed()+Dat->GetMemUsed()); Dat=NULL; TimeKeyL.Del(KeyLN); KeyDatH.DelKeyId(KeyId); } } template <class TKey, class TDat, class THashFunc> void TCache<TKey, TDat, THashFunc>::Flush(){ int KeyId=KeyDatH.FFirstKeyId(); while (KeyDatH.FNextKeyId(KeyId)){ const TKey& Key=KeyDatH.GetKey(KeyId); TKeyLNDatPr& KeyLNDatPr=KeyDatH[KeyId]; TDat Dat=KeyLNDatPr.Val2; Dat->OnDelFromCache(Key, RefToBs); } } template <class TKey, class TDat, class THashFunc> void TCache<TKey, TDat, THashFunc>::FlushAndClr(){ Flush(); CurMemUsed=0; KeyDatH.Clr(); TimeKeyL.Clr(); } template <class TKey, class TDat, class THashFunc> void* TCache<TKey, TDat, THashFunc>::FFirstKeyDat(){ return TimeKeyL.First(); } template <class TKey, class TDat, class THashFunc> bool TCache<TKey, TDat, THashFunc>::FNextKeyDat(void*& KeyDatP, TKey& Key, TDat& Dat){ if (KeyDatP==NULL){ return false; } else { Key=TKeyLN(KeyDatP)->GetVal(); Dat=KeyDatH.GetDat(Key).Val2; KeyDatP=TKeyLN(KeyDatP)->Next(); return true; } } ///////////////////////////////////////////////// // String-Hash-Functions // Old-String-Hash-Function class TStrHashF_OldGLib { public: inline static int GetPrimHashCd(const char *p) { const int MulBy = 16; // even older version used MulBy=2 int HashCd = 0; while (*p) { HashCd = (MulBy * HashCd) + *p++; HashCd &= 0x0FFFFFFF; } return HashCd; } inline static int GetSecHashCd(const char *p) { const int MulBy = 16; // even older version used MulBy=2 int HashCd = 0; while (*p) { HashCd = (MulBy * HashCd) ^ *p++; HashCd &= 0x0FFFFFFF; } return HashCd; } inline static int GetPrimHashCd(const TStr& s) { return GetPrimHashCd(s.CStr()); } inline static int GetSecHashCd(const TStr& s) { return GetSecHashCd(s.CStr()); } }; // Md5-Hash-Function class TStrHashF_Md5 { public: static int GetPrimHashCd(const char *p); static int GetSecHashCd(const char *p); static int GetPrimHashCd(const TStr& s); static int GetSecHashCd(const TStr& s); }; // DJB-Hash-Function class TStrHashF_DJB { private: inline static unsigned int DJBHash(const char* Str, const ::TSize& Len) { unsigned int hash = 5381; for(unsigned int i = 0; i < Len; Str++, i++) { hash = ((hash << 5) + hash) + (*Str); } return hash; } public: inline static int GetPrimHashCd(const char *p) { const char *r = p; while (*r) { r++; } return (int) DJBHash((const char *) p, r - p) & 0x7fffffff; } inline static int GetSecHashCd(const char *p) { const char *r = p; while (*r) { r++; } return (int) DJBHash((const char *) p, r - p) & 0x7fffffff; } inline static int GetPrimHashCd(const TStr& s) { return GetPrimHashCd(s.CStr()); } inline static int GetSecHashCd(const TStr& s) { return GetSecHashCd(s.CStr()); } };