00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef dict_h
00023 #define dict_h
00024
00025 #include "List.h"
00026 #include "Hash.h"
00027
00028 class Dictionary;
00029 class DictEntry;
00030 class IterCookie;
00031
00032 declare(PList,DictEntry);
00033 declare(PList,IterCookie);
00034
00035
00036
00037 #define DEFAULT_DICT_SIZE 16
00038
00039
00040
00041 typedef enum { ORDERED, UNORDERED } dict_order;
00042
00043
00044 typedef void (*dict_delete_func)(void*);
00045
00046
00047 extern void generic_delete_func(void*);
00048
00049 class Dictionary {
00050 public:
00051 Dictionary(dict_order ordering = UNORDERED,
00052 int initial_size = DEFAULT_DICT_SIZE);
00053 virtual ~Dictionary();
00054
00055
00056
00057
00058
00059 void* Lookup(const HashKey* key) const
00060 { return Lookup(key->Key(), key->Size(), key->Hash()); }
00061 void* Lookup(const void* key, int key_size, hash_t hash) const;
00062
00063
00064 void* Insert(HashKey* key, void* val)
00065 {
00066 return Insert(key->TakeKey(), key->Size(), key->Hash(), val, 0);
00067 }
00068
00069
00070
00071 void* Insert(void* key, int key_size, hash_t hash, void* val,
00072 int copy_key);
00073
00074
00075
00076
00077 void* Remove(const HashKey* key)
00078 { return Remove(key->Key(), key->Size(), key->Hash()); }
00079 void* Remove(const void* key, int key_size, hash_t hash,
00080 bool dont_delete = false);
00081
00082
00083 int Length() const
00084 { return tbl2 ? num_entries + num_entries2 : num_entries; }
00085
00086
00087 int MaxLength() const
00088 {
00089 return tbl2 ?
00090 max_num_entries + max_num_entries2 : max_num_entries;
00091 }
00092
00093
00094 int IsOrdered() const { return order != 0; }
00095
00096
00097
00098
00099
00100
00101
00102 void* NthEntry(int n) const
00103 {
00104 const void* key;
00105 int key_len;
00106 return NthEntry(n, key, key_len);
00107 }
00108 void* NthEntry(int n, const void*& key, int& key_len) const;
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 IterCookie* InitForIteration() const;
00124 void* NextEntry(HashKey*& h, IterCookie*& cookie, int return_hash) const;
00125 void* NextEntry(const void*& key, int& key_len, IterCookie*& cookie)
00126 const;
00127 void StopIteration(IterCookie* cookie) const;
00128
00129 void SetDeleteFunc(dict_delete_func f) { delete_func = f; }
00130
00131
00132
00133
00134
00135
00136
00137 void MakeRobustCookie(IterCookie* cookie)
00138 { cookies.append(cookie); }
00139
00140 unsigned int MemoryAllocation() const;
00141
00142 private:
00143 void Init(int size);
00144 void Init2(int size);
00145
00146
00147 void* Insert(DictEntry* entry, int copy_key);
00148
00149 void* DoRemove(DictEntry* entry, hash_t h,
00150 PList(DictEntry)* chain, int chain_offset);
00151
00152 int NextPrime(int n) const;
00153 int IsPrime(int n) const;
00154 void StartChangeSize(int new_size);
00155 void FinishChangeSize(void);
00156 void MoveChains(void);
00157
00158
00159
00160
00161 double DensityThresh() const { return den_thresh; }
00162
00163 void SetDensityThresh(double thresh)
00164 {
00165 den_thresh = thresh;
00166 thresh_entries = int(thresh * double(num_buckets));
00167 }
00168
00169
00170 void SetDensityThresh2(double thresh)
00171 {
00172 den_thresh2 = thresh;
00173 thresh_entries2 = int(thresh * double(num_buckets2));
00174 }
00175
00176
00177
00178
00179
00180 PList(DictEntry)** tbl;
00181 int num_buckets;
00182 int num_entries;
00183 int max_num_entries;
00184 double den_thresh;
00185 int thresh_entries;
00186
00187
00188 PList(DictEntry)** tbl2;
00189 int num_buckets2;
00190 int num_entries2;
00191 int max_num_entries2;
00192 double den_thresh2;
00193 int thresh_entries2;
00194
00195 hash_t tbl_next_ind;
00196
00197 PList(DictEntry)* order;
00198 dict_delete_func delete_func;
00199
00200 PList(IterCookie) cookies;
00201 };
00202
00203
00204 #define PDict(type) type ## PDict
00205 #define PDictdeclare(type) \
00206 class PDict(type) : public Dictionary { \
00207 public: \
00208 PDict(type)(dict_order ordering = UNORDERED, \
00209 int initial_size = DEFAULT_DICT_SIZE) : \
00210 Dictionary(ordering, initial_size) {} \
00211 type* Lookup(const char* key) const \
00212 { \
00213 HashKey h(key); \
00214 return (type*) Dictionary::Lookup(&h); \
00215 } \
00216 type* Lookup(const HashKey* key) const \
00217 { return (type*) Dictionary::Lookup(key); } \
00218 type* Insert(const char* key, type* val) \
00219 { \
00220 HashKey h(key); \
00221 return (type*) Dictionary::Insert(&h, (void*) val); \
00222 } \
00223 type* Insert(HashKey* key, type* val) \
00224 { return (type*) Dictionary::Insert(key, (void*) val); }\
00225 type* NthEntry(int n) const \
00226 { return (type*) Dictionary::NthEntry(n); } \
00227 type* NthEntry(int n, const char*& key) const \
00228 { \
00229 int key_len; \
00230 return (type*) Dictionary::NthEntry(n, (const void*&) key,\
00231 key_len); \
00232 } \
00233 type* NextEntry(IterCookie*& cookie) const \
00234 { \
00235 HashKey* h; \
00236 return (type*) Dictionary::NextEntry(h, cookie, 0); \
00237 } \
00238 type* NextEntry(HashKey*& h, IterCookie*& cookie) const \
00239 { return (type*) Dictionary::NextEntry(h, cookie, 1); } \
00240 type* RemoveEntry(const HashKey* key) \
00241 { return (type*) Remove(key->Key(), key->Size(), \
00242 key->Hash()); } \
00243 }
00244
00245 #endif