| 1 | ///////////////////////////////////////////////////////////////////////////// |
| 2 | // Name: wx/hash.h |
| 3 | // Purpose: wxHashTable class |
| 4 | // Author: Julian Smart |
| 5 | // Modified by: VZ at 25.02.00: type safe hashes with WX_DECLARE_HASH() |
| 6 | // Created: 01/02/97 |
| 7 | // RCS-ID: $Id$ |
| 8 | // Copyright: (c) |
| 9 | // Licence: wxWindows licence |
| 10 | ///////////////////////////////////////////////////////////////////////////// |
| 11 | |
| 12 | #ifndef _WX_HASH_H__ |
| 13 | #define _WX_HASH_H__ |
| 14 | |
| 15 | #ifdef __GNUG__ |
| 16 | #pragma interface "hash.h" |
| 17 | #endif |
| 18 | |
| 19 | #include "wx/list.h" |
| 20 | #include "wx/dynarray.h" |
| 21 | |
| 22 | // the default size of the hash |
| 23 | #define wxHASH_SIZE_DEFAULT (1000) |
| 24 | |
| 25 | /* |
| 26 | * A hash table is an array of user-definable size with lists |
| 27 | * of data items hanging off the array positions. Usually there'll |
| 28 | * be a hit, so no search is required; otherwise we'll have to run down |
| 29 | * the list to find the desired item. |
| 30 | */ |
| 31 | |
| 32 | // ---------------------------------------------------------------------------- |
| 33 | // this is the base class for object hashes: hash tables which contain |
| 34 | // pointers to objects |
| 35 | // ---------------------------------------------------------------------------- |
| 36 | |
| 37 | class WXDLLEXPORT wxHashTableBase : public wxObject |
| 38 | { |
| 39 | public: |
| 40 | wxHashTableBase(); |
| 41 | |
| 42 | void Create(wxKeyType keyType = wxKEY_INTEGER, |
| 43 | size_t size = wxHASH_SIZE_DEFAULT); |
| 44 | void Destroy(); |
| 45 | |
| 46 | size_t GetSize() const { return m_hashSize; } |
| 47 | size_t GetCount() const { return m_count; } |
| 48 | |
| 49 | void DeleteContents(bool flag); |
| 50 | |
| 51 | protected: |
| 52 | // find the node for (key, value) |
| 53 | wxNodeBase *GetNode(long key, long value) const; |
| 54 | |
| 55 | // the array of lists in which we store the values for given key hash |
| 56 | wxListBase **m_hashTable; |
| 57 | |
| 58 | // the size of m_lists array |
| 59 | size_t m_hashSize; |
| 60 | |
| 61 | // the type of indexing we use |
| 62 | wxKeyType m_keyType; |
| 63 | |
| 64 | // the total number of elements in the hash |
| 65 | size_t m_count; |
| 66 | |
| 67 | // should we delete our data? |
| 68 | bool m_deleteContents; |
| 69 | |
| 70 | private: |
| 71 | // no copy ctor/assignment operator (yet) |
| 72 | DECLARE_NO_COPY_CLASS(wxHashTableBase) |
| 73 | }; |
| 74 | |
| 75 | // ---------------------------------------------------------------------------- |
| 76 | // a hash table which stores longs |
| 77 | // ---------------------------------------------------------------------------- |
| 78 | |
| 79 | class WXDLLEXPORT wxHashTableLong : public wxObject |
| 80 | { |
| 81 | public: |
| 82 | wxHashTableLong(size_t size = wxHASH_SIZE_DEFAULT) { Init(size); } |
| 83 | virtual ~wxHashTableLong(); |
| 84 | |
| 85 | void Create(size_t size = wxHASH_SIZE_DEFAULT); |
| 86 | void Destroy(); |
| 87 | |
| 88 | size_t GetSize() const { return m_hashSize; } |
| 89 | size_t GetCount() const { return m_count; } |
| 90 | |
| 91 | void Put(long key, long value); |
| 92 | long Get(long key) const; |
| 93 | long Delete(long key); |
| 94 | |
| 95 | protected: |
| 96 | void Init(size_t size); |
| 97 | |
| 98 | private: |
| 99 | wxArrayLong **m_values, |
| 100 | **m_keys; |
| 101 | |
| 102 | // the size of array above |
| 103 | size_t m_hashSize; |
| 104 | |
| 105 | // the total number of elements in the hash |
| 106 | size_t m_count; |
| 107 | |
| 108 | // not implemented yet |
| 109 | DECLARE_NO_COPY_CLASS(wxHashTableLong) |
| 110 | }; |
| 111 | |
| 112 | // ---------------------------------------------------------------------------- |
| 113 | // wxStringHashTable: a hash table which indexes strings with longs |
| 114 | // ---------------------------------------------------------------------------- |
| 115 | |
| 116 | class WXDLLEXPORT wxStringHashTable : public wxObject |
| 117 | { |
| 118 | public: |
| 119 | wxStringHashTable(size_t sizeTable = wxHASH_SIZE_DEFAULT); |
| 120 | virtual ~wxStringHashTable(); |
| 121 | |
| 122 | // add a string associated with this key to the table |
| 123 | void Put(long key, const wxString& value); |
| 124 | |
| 125 | // get the string from the key: if not found, an empty string is returned |
| 126 | // and the wasFound is set to FALSE if not NULL |
| 127 | wxString Get(long key, bool *wasFound = NULL) const; |
| 128 | |
| 129 | // clean up |
| 130 | void Destroy(); |
| 131 | |
| 132 | private: |
| 133 | wxArrayLong **m_keys; |
| 134 | wxArrayString **m_values; |
| 135 | |
| 136 | // the size of array above |
| 137 | size_t m_hashSize; |
| 138 | |
| 139 | DECLARE_NO_COPY_CLASS(wxStringHashTable) |
| 140 | }; |
| 141 | |
| 142 | // ---------------------------------------------------------------------------- |
| 143 | // for compatibility only |
| 144 | // ---------------------------------------------------------------------------- |
| 145 | |
| 146 | class WXDLLEXPORT wxHashTable : public wxObject |
| 147 | { |
| 148 | public: |
| 149 | int n; |
| 150 | int current_position; |
| 151 | wxNode *current_node; |
| 152 | |
| 153 | unsigned int key_type; |
| 154 | wxList **hash_table; |
| 155 | |
| 156 | wxHashTable(int the_key_type = wxKEY_INTEGER, |
| 157 | int size = wxHASH_SIZE_DEFAULT); |
| 158 | ~wxHashTable(); |
| 159 | |
| 160 | // copy ctor and assignment operator |
| 161 | wxHashTable(const wxHashTable& table) : wxObject() { DoCopy(table); } |
| 162 | wxHashTable& operator=(const wxHashTable& table) |
| 163 | { Clear(); DoCopy(table); return *this; } |
| 164 | |
| 165 | void DoCopy(const wxHashTable& table); |
| 166 | |
| 167 | void Destroy(); |
| 168 | |
| 169 | bool Create(int the_key_type = wxKEY_INTEGER, |
| 170 | int size = wxHASH_SIZE_DEFAULT); |
| 171 | |
| 172 | // Note that there are 2 forms of Put, Get. |
| 173 | // With a key and a value, the *value* will be checked |
| 174 | // when a collision is detected. Otherwise, if there are |
| 175 | // 2 items with a different value but the same key, |
| 176 | // we'll retrieve the WRONG ONE. So where possible, |
| 177 | // supply the required value along with the key. |
| 178 | // In fact, the value-only versions make a key, and still store |
| 179 | // the value. The use of an explicit key might be required |
| 180 | // e.g. when combining several values into one key. |
| 181 | // When doing that, it's highly likely we'll get a collision, |
| 182 | // e.g. 1 + 2 = 3, 2 + 1 = 3. |
| 183 | |
| 184 | // key and value are NOT necessarily the same |
| 185 | void Put(long key, long value, wxObject *object); |
| 186 | void Put(long key, const wxChar *value, wxObject *object); |
| 187 | |
| 188 | // key and value are the same |
| 189 | void Put(long value, wxObject *object); |
| 190 | void Put(const wxChar *value, wxObject *object); |
| 191 | |
| 192 | // key and value not the same |
| 193 | wxObject *Get(long key, long value) const; |
| 194 | wxObject *Get(long key, const wxChar *value) const; |
| 195 | |
| 196 | // key and value are the same |
| 197 | wxObject *Get(long value) const; |
| 198 | wxObject *Get(const wxChar *value) const; |
| 199 | |
| 200 | // Deletes entry and returns data if found |
| 201 | wxObject *Delete(long key); |
| 202 | wxObject *Delete(const wxChar *key); |
| 203 | |
| 204 | wxObject *Delete(long key, int value); |
| 205 | wxObject *Delete(long key, const wxChar *value); |
| 206 | |
| 207 | // Construct your own integer key from a string, e.g. in case |
| 208 | // you need to combine it with something |
| 209 | long MakeKey(const wxChar *string) const; |
| 210 | |
| 211 | // Way of iterating through whole hash table (e.g. to delete everything) |
| 212 | // Not necessary, of course, if you're only storing pointers to |
| 213 | // objects maintained separately |
| 214 | |
| 215 | void BeginFind(); |
| 216 | wxNode *Next(); |
| 217 | |
| 218 | void DeleteContents(bool flag); |
| 219 | void Clear(); |
| 220 | |
| 221 | // Returns number of nodes |
| 222 | size_t GetCount() const { return m_count; } |
| 223 | |
| 224 | private: |
| 225 | size_t m_count; // number of elements in the hashtable |
| 226 | bool m_deleteContents; |
| 227 | |
| 228 | DECLARE_DYNAMIC_CLASS(wxHashTable) |
| 229 | }; |
| 230 | |
| 231 | // defines a new type safe hash table which stores the elements of type eltype |
| 232 | // in lists of class listclass |
| 233 | #define _WX_DECLARE_HASH(eltype, listclass, hashclass, classexp) \ |
| 234 | classexp hashclass : public wxHashTableBase \ |
| 235 | { \ |
| 236 | public: \ |
| 237 | hashclass(wxKeyType keyType = wxKEY_INTEGER, \ |
| 238 | size_t size = wxHASH_SIZE_DEFAULT) \ |
| 239 | { Create(keyType, size); } \ |
| 240 | \ |
| 241 | ~hashclass() { Destroy(); } \ |
| 242 | \ |
| 243 | void Put(long key, long val, eltype *data) { DoPut(key, val, data); } \ |
| 244 | void Put(long key, eltype *data) { DoPut(key, key, data); } \ |
| 245 | \ |
| 246 | eltype *Get(long key, long value) const \ |
| 247 | { \ |
| 248 | wxNodeBase *node = GetNode(key, value); \ |
| 249 | return node ? ((listclass::Node *)node)->GetData() : (eltype *)0; \ |
| 250 | } \ |
| 251 | eltype *Get(long key) const { return Get(key, key); } \ |
| 252 | \ |
| 253 | eltype *Delete(long key, long value) \ |
| 254 | { \ |
| 255 | eltype *data; \ |
| 256 | \ |
| 257 | wxNodeBase *node = GetNode(key, value); \ |
| 258 | if ( node ) \ |
| 259 | { \ |
| 260 | data = ((listclass::Node *)node)->GetData(); \ |
| 261 | \ |
| 262 | delete node; \ |
| 263 | m_count--; \ |
| 264 | } \ |
| 265 | else \ |
| 266 | { \ |
| 267 | data = (eltype *)0; \ |
| 268 | } \ |
| 269 | \ |
| 270 | return data; \ |
| 271 | } \ |
| 272 | eltype *Delete(long key) { return Delete(key, key); } \ |
| 273 | \ |
| 274 | protected: \ |
| 275 | void DoPut(long key, long value, eltype *data) \ |
| 276 | { \ |
| 277 | size_t slot = (size_t)abs((int)(key % (long)m_hashSize)); \ |
| 278 | \ |
| 279 | if ( !m_hashTable[slot] ) \ |
| 280 | { \ |
| 281 | m_hashTable[slot] = new listclass(m_keyType); \ |
| 282 | if ( m_deleteContents ) \ |
| 283 | m_hashTable[slot]->DeleteContents(TRUE); \ |
| 284 | } \ |
| 285 | \ |
| 286 | ((listclass *)m_hashTable[slot])->Append(value, data); \ |
| 287 | m_count++; \ |
| 288 | } \ |
| 289 | } |
| 290 | |
| 291 | // this macro is to be used in the user code |
| 292 | #define WX_DECLARE_HASH(el, list, hash) \ |
| 293 | _WX_DECLARE_HASH(el, list, hash, class) |
| 294 | |
| 295 | // and this one does exactly the same thing but should be used inside the |
| 296 | // library |
| 297 | #define WX_DECLARE_EXPORTED_HASH(el, list, hash) \ |
| 298 | _WX_DECLARE_HASH(el, list, hash, class WXDLLEXPORT) |
| 299 | |
| 300 | #define WX_DECLARE_USER_EXPORTED_HASH(el, list, hash, usergoo) \ |
| 301 | _WX_DECLARE_HASH(el, list, hash, class usergoo) |
| 302 | |
| 303 | #endif |
| 304 | // _WX_HASH_H__ |