New doc system done for core
[io.git] / libs / basekit / source / PHash_inline.h
blob781bee43d3161200fcf952ce230711a92dad744b
1 //metadoc PHash copyright Steve Dekorte 2002, Marc Fauconneau 2007
2 //metadoc PHash license BSD revised
3 /*metadoc PHash description
4 PHash - Cuckoo Hash
5 keys and values are references (they are not copied or freed)
6 key pointers are assumed unique
7 */
9 #ifdef PHASH_C
10 #define IO_IN_C_FILE
11 #endif
12 #include "Common_inline.h"
13 #ifdef IO_DECLARE_INLINES
15 #include <stdio.h>
17 #define PHASH_RECORDS_AT_(self, tableIndex, index) (self->records + self->tableSize*tableIndex + index)
18 #define PHASH_RECORDS_AT_HASH_(self, tableIndex, hash) \
19 (self->records + self->tableSize*tableIndex + (hash & self->mask))
21 IOINLINE unsigned int PHash_count(PHash *self)
23 return self->numKeys;
26 IOINLINE void PHashRecord_swap(PHashRecord* r1, PHashRecord* r2)
28 PHashRecord t = *r1;
29 *r1 = *r2;
30 *r2 = t;
33 #define PHashKey_value(k) k
36 IOINLINE void *PHashKey_value(void *key)
38 return key;
42 IOINLINE unsigned int PHashKey_isEqual_(void *key1, void *key2)
44 // return key2 && (PHashKey_value(key1) == PHashKey_value(key2));
45 return key1 == key2;
48 // simple hash functions, should be enough for pointers
49 IOINLINE unsigned int PHash_hash(PHash *self, void *key)
51 intptr_t k = (intptr_t)PHashKey_value(key);
52 return k^(k>>4);
55 IOINLINE unsigned int PHash_hash_more(PHash *self, unsigned int hash)
57 return hash ^ (hash >> self->log2tableSize);
60 // -----------------------------------
62 IOINLINE void PHash_clean(PHash *self)
64 memset(self->records, 0, sizeof(PHashRecord) * self->tableSize * 2);
65 self->numKeys = 0;
68 IOINLINE PHashRecord *PHash_recordAt_(PHash *self, void *key)
70 unsigned int hash;
71 PHashRecord *record;
73 hash = PHash_hash(self, key);
74 record = PHASH_RECORDS_AT_HASH_(self, 0, hash);
76 // we try the second location
77 hash = PHash_hash_more(self, hash);
78 record = (key == record->key) ? record : PHASH_RECORDS_AT_HASH_(self, 1, hash);
80 return (key == record->key) ? record : &self->nullRecord;
83 IOINLINE void *PHash_at_(PHash *self, void *key)
85 return PHash_recordAt_(self, key)->value;
88 IOINLINE unsigned char PHash_at_update_(PHash *self, void *key, void *value)
90 PHashRecord *record = PHash_recordAt_(self, key);
92 if (record->key)
94 // already a matching key, replace it
95 if (PHashKey_isEqual_(key, record->key))
97 if (record->value == value)
99 return 0; // return 0 if no change
102 record->value = value;
103 return 1;
107 return 0;
110 IOINLINE void PHash_at_put_(PHash *self, void *key, void *value)
112 PHashRecord thisRecord;
113 PHashRecord *record;
115 record = PHash_recordAt_(self, key);
117 // already a matching key, replace it
118 if (record != &self->nullRecord && PHashKey_isEqual_(key, record->key))
120 record->value = value;
121 return;
124 thisRecord.key = key;
125 thisRecord.value = value;
127 record = PHash_cuckoo_(self, &thisRecord);
129 if (!record) // collision
131 PHash_growWithRecord(self, &thisRecord);
133 else
135 *record = thisRecord;
136 self->numKeys ++;
137 if (self->numKeys > PHash_maxKeys(self))
138 PHash_grow(self);
142 IOINLINE void PHash_removeKey_(PHash *self, void *key)
144 PHashRecord *record = PHash_recordAt_(self, key);
145 void *rkey = record->key;
147 if (rkey && PHashKey_value(rkey) == PHashKey_value(key))
149 self->numKeys --;
150 memset(record, 0, sizeof(PHashRecord));
154 // --- enumeration --------------------------------------------------
156 #define PHASH_FOREACH(self, pkey, pvalue, code) \
158 PHash *_self = (self);\
159 unsigned int _i, _j, _size = _self->tableSize;\
160 void * pkey;\
161 void * pvalue;\
163 for (_j = 0; _j < 2; _j ++)\
164 for (_i = 0; _i < _size; _i ++)\
166 PHashRecord *_record = PHASH_RECORDS_AT_(_self, _j, _i);\
167 if (_record->key)\
169 pkey = _record->key;\
170 pvalue = _record->value;\
171 code;\
177 typedef BASEKIT_API void (PHashDoCallback)(void *);
179 IOINLINE void PHash_do_(PHash *self, PHashDoCallback *callback)
180 { PHASH_FOREACH(self, k, v, (*callback)(v)); }
182 IOINLINE void *PHash_detect_(PHash *self, PHashDetectCallback *callback)
183 { PHASH_FOREACH(self, k, v, if ((*callback)(v)) return k; ); return NULL; }
185 IOINLINE void PHash_doOnKeys_(PHash *self, PHashDoCallback *callback)
186 { PHASH_FOREACH(self, k, v, (*callback)(k)); }
188 IOINLINE void PHash_doOnKeyAndValue_(PHash *self, PHashDoCallback *callback)
189 { PHASH_FOREACH(self, k, v, (*callback)(k); (*callback)(v);); }
192 #undef IO_IN_C_FILE
193 #endif