You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
744 lines
22 KiB
744 lines
22 KiB
/*==LICENSE==* |
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools |
|
Copyright (C) 2011 Cyan Worlds, Inc. |
|
|
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
Additional permissions under GNU GPL version 3 section 7 |
|
|
|
If you modify this Program, or any covered work, by linking or |
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
(or a modified version of those libraries), |
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
licensors of this Program grant you additional |
|
permission to convey the resulting work. Corresponding Source for a |
|
non-source form of such a combination shall include the source code for |
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
work. |
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
or by snail mail at: |
|
Cyan Worlds, Inc. |
|
14617 N Newport Hwy |
|
Mead, WA 99021 |
|
|
|
*==LICENSE==*/ |
|
/***************************************************************************** |
|
* |
|
* $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtHash.h |
|
* |
|
***/ |
|
|
|
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNUTILS_PRIVATE_PNUTHASH_H |
|
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtHash.h included more than once" |
|
#endif |
|
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNUTILS_PRIVATE_PNUTHASH_H |
|
|
|
|
|
/**************************************************************************** |
|
* |
|
* Macros |
|
* |
|
***/ |
|
|
|
// Define a field inside an object that is used to link it into a hash table |
|
#define HASHLINK(object) THashLink< object > |
|
|
|
// Define a POINTER to a hash table, not a hash table |
|
#define HASHTABLE(object,key) THashTable< object, key > |
|
|
|
// Define a hash table: |
|
// - starts with kSlotMinCount rows |
|
// - can grow to kDefaultSlotMaxCount rows |
|
// (hash table grows when a row contains more than kGrowOnListSize entries |
|
#define HASHTABLEDECL(object,key,link) THashTableDecl< object, key, offsetof(object,link), 0 > |
|
|
|
// Define a hash table in situations when a forward reference prevents use of HASHTABLEDECL |
|
// - Size characteristics are identical to HASHTABLEDECL |
|
#define HASHTABLEDYN(object,key) THashTableDyn< object, key > |
|
|
|
// Define a hash table with: |
|
// - starts with <size> |
|
// - row table never grows |
|
#define HASHTABLEDECLSIZE(object,key,link,size) THashTableDecl<object, key, offsetof(object,link), size > |
|
|
|
|
|
#if defined(_MSC_VER) |
|
#define forceinline __forceinline |
|
#else |
|
#define forceinline inline |
|
#endif |
|
|
|
|
|
/**************************************************************************** |
|
* |
|
* Forward declarations |
|
* |
|
***/ |
|
|
|
template<class T> |
|
class THashLink; |
|
|
|
template<class T> |
|
class TBaseHashTable; |
|
|
|
|
|
/**************************************************************************** |
|
* |
|
* CHashValue |
|
* |
|
***/ |
|
|
|
class CHashValue { |
|
private: |
|
static const dword s_hashTable[]; |
|
|
|
dword m_result; |
|
|
|
inline void Construct () { m_result = 0x325d1eae; } |
|
|
|
public: |
|
static dword LookupHashBits (unsigned value) { ASSERT(value < 0x100); return s_hashTable[value]; } |
|
|
|
inline CHashValue () { Construct() ; } |
|
inline CHashValue (const CHashValue & source) { m_result = source.m_result; } |
|
inline CHashValue (const void * data, unsigned bytes) { Construct(); Hash(data, bytes); } |
|
inline CHashValue & operator= (const CHashValue & source) { m_result = source.m_result; return *this; } |
|
inline bool operator== (const CHashValue & source) const { return (m_result == source.m_result); } |
|
|
|
inline dword GetHash () const { return m_result; } |
|
|
|
forceinline void Hash (const void * data, unsigned bytes); |
|
forceinline void Hash8 (unsigned data); |
|
forceinline void Hash16 (unsigned data); |
|
forceinline void Hash32 (unsigned data); |
|
|
|
}; |
|
|
|
//=========================================================================== |
|
void CHashValue::Hash (const void * data, unsigned bytes) { |
|
for (const byte * curr = (const byte *)data, * term = curr + bytes; curr != term; ++curr) |
|
Hash8(*curr); |
|
} |
|
|
|
//=========================================================================== |
|
void CHashValue::Hash8 (unsigned data) { |
|
m_result += s_hashTable[m_result >> 24] ^ (m_result >> 6) ^ s_hashTable[data & 0xff]; |
|
} |
|
|
|
//=========================================================================== |
|
void CHashValue::Hash16 (unsigned data) { |
|
Hash8(data); |
|
Hash8(data >> 8); |
|
} |
|
|
|
//=========================================================================== |
|
void CHashValue::Hash32 (unsigned data) { |
|
Hash8(data); |
|
Hash8(data >> 8); |
|
Hash8(data >> 16); |
|
Hash8(data >> 24); |
|
} |
|
|
|
|
|
/**************************************************************************** |
|
* |
|
* THashLink |
|
* |
|
***/ |
|
|
|
template<class T> |
|
class THashLink { |
|
friend class TBaseHashTable<T>; |
|
|
|
private: |
|
unsigned m_hash; |
|
LINK(T) m_linkToFull; |
|
LINK(T) m_linkToSlot; |
|
|
|
public: |
|
inline bool IsLinked () const; |
|
inline T * Next (); |
|
inline const T * Next () const; |
|
inline T * Prev (); |
|
inline const T * Prev () const; |
|
inline void Unlink (); |
|
}; |
|
|
|
//=========================================================================== |
|
template<class T> |
|
bool THashLink<T>::IsLinked () const { |
|
return m_linkToFull.IsLinked(); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
T * THashLink<T>::Next () { |
|
return m_linkToFull.Next(); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
const T * THashLink<T>::Next () const { |
|
return m_linkToFull.Next(); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
T * THashLink<T>::Prev () { |
|
return m_linkToFull.Prev(); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
const T * THashLink<T>::Prev () const { |
|
return m_linkToFull.Prev(); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
void THashLink<T>::Unlink () { |
|
m_linkToFull.Unlink(); |
|
m_linkToSlot.Unlink(); |
|
} |
|
|
|
|
|
/**************************************************************************** |
|
* |
|
* TBaseHashTable |
|
* |
|
***/ |
|
|
|
template<class T> |
|
class TBaseHashTable { |
|
|
|
private: |
|
enum { kSlotMinCount = 8 }; |
|
enum { kDefaultSlotMaxCount = 1024 }; |
|
enum { kGrowOnListSize = 5 }; |
|
|
|
LIST(T) m_fullList; |
|
int m_linkOffset; |
|
FARRAYOBJ(LIST(T)) m_slotListArray; |
|
unsigned m_slotMask; // always set to a power of two minus one |
|
unsigned m_slotMaxCount; |
|
|
|
inline bool CheckGrowTable (LIST(T) * slotList); |
|
inline const THashLink<T> & GetLink (const T * object) const; |
|
inline THashLink<T> & GetLink (T * object); |
|
inline void SetSlotCount (unsigned count); |
|
|
|
protected: |
|
inline unsigned GetHash (const T * object) const; |
|
inline unsigned & GetHash (T * object); |
|
inline const LIST(T) & GetSlotList (unsigned hash) const; |
|
inline LIST(T) & GetSlotList (unsigned hash); |
|
inline void SetLinkOffset (int linkOffset, unsigned maxSize); |
|
inline void SetSlotMaxCount (unsigned count); |
|
|
|
public: |
|
inline TBaseHashTable (); |
|
inline TBaseHashTable (const TBaseHashTable<T> & source); |
|
inline TBaseHashTable<T> & operator= (const TBaseHashTable<T> & source); |
|
|
|
inline void Add (T * object, unsigned hash); |
|
inline void Clear (); |
|
inline void Delete (T * object); |
|
inline T * Head (); |
|
inline const T * Head () const; |
|
inline T * Next (const T * object); |
|
inline const T * Next (const T * object) const; |
|
inline void Order (T * linkedObject, ELinkType linkType, T * existingObject); |
|
inline T * Prev (const T * object); |
|
inline const T * Prev (const T * object) const; |
|
inline T * Tail (); |
|
inline const T * Tail () const; |
|
inline void Unlink (T * object); |
|
|
|
}; |
|
|
|
//=========================================================================== |
|
template<class T> |
|
TBaseHashTable<T>::TBaseHashTable () { |
|
m_slotMask = 0; |
|
m_slotMaxCount = kDefaultSlotMaxCount; |
|
// more initialization done during call to SetLinkOffset() |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
TBaseHashTable<T>::TBaseHashTable (const TBaseHashTable<T> & source) { |
|
#ifdef HS_DEBUGGING |
|
FATAL("No copy constructor"); |
|
#endif |
|
TBaseHashTable(); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
TBaseHashTable<T> & TBaseHashTable<T>::operator= (const TBaseHashTable<T> & source) { |
|
#ifdef HS_DEBUGGING |
|
FATAL("No assignment operator"); |
|
#endif |
|
return *this; |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
void TBaseHashTable<T>::Add (T * object, unsigned hash) { |
|
GetHash(object) = hash; |
|
|
|
LIST(T) * list = &GetSlotList(hash); |
|
if (CheckGrowTable(list)) |
|
list = &GetSlotList(hash); |
|
|
|
m_fullList.Link(object); |
|
list->Link(object); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
bool TBaseHashTable<T>::CheckGrowTable (LIST(T) * list) { |
|
|
|
unsigned nextCount = (m_slotMask + 1) * 2; |
|
if (nextCount > m_slotMaxCount) |
|
return false; |
|
|
|
unsigned listCount = 0; |
|
for (T * curr = list->Head(); curr; curr = list->Next(curr)) |
|
++listCount; |
|
|
|
if (listCount + 1 < kGrowOnListSize) |
|
return false; |
|
|
|
SetSlotCount(nextCount); |
|
|
|
return true; |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
void TBaseHashTable<T>::Clear () { |
|
m_fullList.Clear(); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
void TBaseHashTable<T>::Delete (T * object) { |
|
DEL(object); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
unsigned TBaseHashTable<T>::GetHash (const T * object) const { |
|
return GetLink(object).m_hash; |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
unsigned & TBaseHashTable<T>::GetHash (T * object) { |
|
return GetLink(object).m_hash; |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
const THashLink<T> & TBaseHashTable<T>::GetLink (const T * object) const { |
|
return *(const THashLink<T> *)((const byte *)object + m_linkOffset); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
THashLink<T> & TBaseHashTable<T>::GetLink (T * object) { |
|
return *(THashLink<T> *)((byte *)object + m_linkOffset); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
const LIST(T) & TBaseHashTable<T>::GetSlotList (unsigned hash) const { |
|
return m_slotListArray[hash & m_slotMask]; |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
LIST(T) & TBaseHashTable<T>::GetSlotList (unsigned hash) { |
|
return m_slotListArray[hash & m_slotMask]; |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
T * TBaseHashTable<T>::Head () { |
|
return m_fullList.Head(); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
const T * TBaseHashTable<T>::Head () const { |
|
return m_fullList.Head(); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
T * TBaseHashTable<T>::Next (const T * object) { |
|
return m_fullList.Next(object); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
const T * TBaseHashTable<T>::Next (const T * object) const { |
|
return m_fullList.Next(object); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
void TBaseHashTable<T>::Order (T * linkedObject, ELinkType linkType, T * existingObject) { |
|
THashLink<T> & link = GetLink(linkedObject); |
|
ASSERT(link.m_linkToFull.IsLinked()); |
|
m_fullList.Link(linkedObject, linkType, existingObject); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
T * TBaseHashTable<T>::Prev (const T * object) { |
|
return m_fullList.Prev(object); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
const T * TBaseHashTable<T>::Prev (const T * object) const { |
|
return m_fullList.Prev(object); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
void TBaseHashTable<T>::SetLinkOffset (int linkOffset, unsigned maxSize) { |
|
ASSERT(!m_fullList.Head()); |
|
ASSERT(!m_slotListArray.Count()); |
|
ASSERT(!m_slotMask); |
|
|
|
m_linkOffset = linkOffset; |
|
m_fullList.SetLinkOffset(m_linkOffset + offsetof(THashLink<T>, m_linkToFull)); |
|
|
|
if (!m_slotMask) |
|
SetSlotCount(max(kSlotMinCount, MathNextPow2(maxSize))); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
void TBaseHashTable<T>::SetSlotCount (unsigned count) { |
|
ASSERT(!(count & (count - 1))); // power of two |
|
ASSERT(count >= 2); |
|
|
|
if (count == m_slotMask + 1) |
|
return; |
|
m_slotMask = count - 1; |
|
|
|
m_slotListArray.ZeroCount(); |
|
m_slotListArray.SetCount(count); |
|
for (unsigned loop = 0; loop < count; ++loop) |
|
m_slotListArray[loop].SetLinkOffset(m_linkOffset + offsetof(THashLink<T>, m_linkToSlot)); |
|
|
|
for (T * curr = Head(); curr; curr = Next(curr)) |
|
GetSlotList(GetHash(curr)).Link(curr); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
void TBaseHashTable<T>::SetSlotMaxCount (unsigned count) { |
|
if (count) |
|
m_slotMaxCount = max(kSlotMinCount, count); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
T * TBaseHashTable<T>::Tail () { |
|
return m_fullList.Tail(); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
const T * TBaseHashTable<T>::Tail () const { |
|
return m_fullList.Tail(); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T> |
|
void TBaseHashTable<T>::Unlink (T * object) { |
|
THashLink<T> & link = GetLink(object); |
|
link.Unlink(); |
|
} |
|
|
|
|
|
/**************************************************************************** |
|
* |
|
* THashTable |
|
* |
|
***/ |
|
|
|
template<class T, class K> |
|
class THashTable : public TBaseHashTable<T> { |
|
|
|
public: |
|
inline void Add (T * object); |
|
inline void Add (T * object, unsigned hash); |
|
inline T * Find (const K & key); |
|
inline T * FindNext (const K & key, T * object); |
|
inline const T * Find (const K & key) const; |
|
inline const T * FindNext (const K & key, const T * object) const; |
|
inline T * Unduplicate (T * object, const K & key); |
|
|
|
}; |
|
|
|
//=========================================================================== |
|
template<class T, class K> |
|
inline void THashTable<T,K>::Add (T * object) { |
|
TBaseHashTable<T>::Add(object, object->GetHash()); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T, class K> |
|
inline void THashTable<T,K>::Add (T * object, unsigned hash) { |
|
TBaseHashTable<T>::Add(object, hash); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T, class K> |
|
T * THashTable<T,K>::Find (const K & key) { |
|
return (T *)((const THashTable<T,K> *)this)->Find(key); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T, class K> |
|
T * THashTable<T,K>::FindNext (const K & key, T * object) { |
|
return (T *)((const THashTable<T,K> *)this)->FindNext(key, object); |
|
} |
|
|
|
//=========================================================================== |
|
template<class T, class K> |
|
const T * THashTable<T,K>::Find (const K & key) const { |
|
unsigned hash = key.GetHash(); |
|
const LIST(T) & slotList = this->GetSlotList(hash); |
|
for (const T * curr = slotList.Head(); curr; curr = slotList.Next(curr)) |
|
if ((GetHash(curr) == hash) && (*curr == key)) |
|
return curr; |
|
return nil; |
|
} |
|
|
|
//=========================================================================== |
|
template<class T, class K> |
|
const T * THashTable<T,K>::FindNext (const K & key, const T * object) const { |
|
unsigned hash = key.GetHash(); |
|
const LIST(T) & slotList = this->GetSlotList(hash); |
|
for (const T * curr = slotList.Next(object); curr; curr = slotList.Next(curr)) |
|
if ((GetHash(curr) == hash) && (*curr == key)) |
|
return curr; |
|
return nil; |
|
} |
|
|
|
//=========================================================================== |
|
template<class T, class K> |
|
T * THashTable<T,K>::Unduplicate (T * object, const K & key) { |
|
T * existing = Find(key); |
|
if (existing) { |
|
DEL(object); |
|
return existing; |
|
} |
|
else { |
|
Add(object); |
|
return object; |
|
} |
|
} |
|
|
|
|
|
/**************************************************************************** |
|
* |
|
* THashTableDecl |
|
* |
|
***/ |
|
|
|
template<class T, class K, int linkOffset, unsigned maxSize> |
|
class THashTableDecl : public THashTable<T,K> { |
|
|
|
public: |
|
inline THashTableDecl (); |
|
|
|
}; |
|
|
|
//=========================================================================== |
|
template<class T, class K, int linkOffset, unsigned maxSize> |
|
THashTableDecl<T,K,linkOffset,maxSize>::THashTableDecl () { |
|
this->SetLinkOffset(linkOffset, maxSize); |
|
this->SetSlotMaxCount(maxSize); |
|
} |
|
|
|
|
|
/**************************************************************************** |
|
* |
|
* THashTableDyn |
|
* |
|
***/ |
|
|
|
template<class T, class K> |
|
class THashTableDyn : public THashTable<T,K> { |
|
|
|
public: |
|
void Initialize (int linkOffset, unsigned maxSize = 0); |
|
|
|
}; |
|
|
|
//=========================================================================== |
|
template<class T, class K> |
|
void THashTableDyn<T,K>::Initialize (int linkOffset, unsigned maxSize) { |
|
this->SetLinkOffset(linkOffset, maxSize); |
|
this->SetSlotMaxCount(maxSize); |
|
} |
|
|
|
|
|
/**************************************************************************** |
|
* |
|
* THashKeyVal |
|
* |
|
***/ |
|
|
|
template <class T> |
|
class THashKeyVal { |
|
public: |
|
THashKeyVal () : m_value(0) { } |
|
THashKeyVal (const T & value) : m_value(value) { } |
|
bool operator== (const THashKeyVal & rhs) const { |
|
return m_value == rhs.m_value; |
|
} |
|
unsigned GetHash () const { |
|
CHashValue hash(&m_value, sizeof(m_value)); |
|
return hash.GetHash(); |
|
} |
|
const T & GetValue () const { return m_value; } |
|
void SetValue (const T & value) { m_value = value; } |
|
|
|
protected: |
|
T m_value; |
|
}; |
|
|
|
|
|
/**************************************************************************** |
|
* |
|
* CHashKeyStrPtr / CHashKeyStrPtrI |
|
* |
|
***/ |
|
|
|
//=========================================================================== |
|
template<class C> |
|
class THashKeyStrBase { |
|
public: |
|
const C * GetString () const { |
|
return m_str; |
|
} |
|
|
|
protected: |
|
THashKeyStrBase () : m_str(nil) { } |
|
THashKeyStrBase (const C str[]) : m_str(str) { } |
|
virtual ~THashKeyStrBase () { } |
|
|
|
const C * m_str; |
|
}; |
|
|
|
//=========================================================================== |
|
template<class C> |
|
class THashKeyStrCmp : public THashKeyStrBase<C> { |
|
public: |
|
bool operator== (const THashKeyStrCmp & rhs) const { |
|
return StrCmp(this->m_str, rhs.m_str) == 0; |
|
} |
|
unsigned GetHash () const { |
|
return StrHash(this->m_str); |
|
} |
|
|
|
protected: |
|
THashKeyStrCmp () { } |
|
THashKeyStrCmp (const C str[]) : THashKeyStrBase<C>(str) { } |
|
}; |
|
|
|
//=========================================================================== |
|
template<class C> |
|
class THashKeyStrCmpI : public THashKeyStrBase<C> { |
|
public: |
|
bool operator== (const THashKeyStrCmpI & rhs) const { |
|
return StrCmpI(this->m_str, rhs.m_str) == 0; |
|
} |
|
unsigned GetHash () const { |
|
return StrHashI(this->m_str); |
|
} |
|
protected: |
|
|
|
THashKeyStrCmpI () { } |
|
THashKeyStrCmpI (const C str[]) : THashKeyStrBase<C>(str) { } |
|
}; |
|
|
|
|
|
/**************************************************************************** |
|
* |
|
* THashKeyStrPtr |
|
* |
|
***/ |
|
|
|
template <class C, class T> |
|
class THashKeyStrPtr : public T { |
|
public: |
|
THashKeyStrPtr () { } |
|
THashKeyStrPtr (const C str[]) : T(str) { } |
|
void SetString (const C str[]) { |
|
this->m_str = str; |
|
} |
|
}; |
|
|
|
typedef THashKeyStrPtr< wchar, THashKeyStrCmp<wchar> > CHashKeyStrPtr; |
|
typedef THashKeyStrPtr< wchar, THashKeyStrCmpI<wchar> > CHashKeyStrPtrI; |
|
typedef THashKeyStrPtr< char, THashKeyStrCmp<char> > CHashKeyStrPtrChar; |
|
typedef THashKeyStrPtr< char, THashKeyStrCmpI<char> > CHashKeyStrPtrCharI; |
|
|
|
|
|
/**************************************************************************** |
|
* |
|
* THashKeyStr |
|
* |
|
***/ |
|
|
|
template <class C, class T> |
|
class THashKeyStr : public T { |
|
public: |
|
THashKeyStr () { } |
|
THashKeyStr (const C str[]) { SetString(str); } |
|
THashKeyStr (const THashKeyStr &); // intentionally unimplemented |
|
THashKeyStr & operator= (const THashKeyStr &); // intentionally unimplemented |
|
~THashKeyStr () { |
|
SetString(nil); |
|
} |
|
void SetString (const C str[]) { // deprecated |
|
if (this->m_str) |
|
FREE(const_cast<C *>(this->m_str)); |
|
if (str) |
|
this->m_str = StrDup(str); |
|
else |
|
this->m_str = nil; |
|
} |
|
}; |
|
|
|
typedef THashKeyStr< wchar, THashKeyStrCmp<wchar> > CHashKeyStr; |
|
typedef THashKeyStr< wchar, THashKeyStrCmpI<wchar> > CHashKeyStrI; |
|
typedef THashKeyStr< char, THashKeyStrCmp<char> > CHashKeyStrChar; |
|
typedef THashKeyStr< char, THashKeyStrCmpI<char> > CHashKeyStrCharI;
|
|
|