Sample: cleaning up Inheritance
[io/quag.git] / libs / basekit / source / SHash_inline.h
blob6eefeb1e7781fab49a166ddfd852631af2a23854
1 /*#io
2 docCopyright("Steve Dekorte", 2002)
3 docCopyright("Marc Fauconneau", 2007)
4 docLicense("BSD revised")
5 docDescription("""
6 SHash - Cuckoo Hash
7 keys and values are references (they are not copied or freed)
8 key pointers are assumed unique
10 """)
13 #ifdef SHASH_C
14 #define IO_IN_C_FILE
15 #endif
16 #include "Common_inline.h"
17 #ifdef IO_DECLARE_INLINES
19 #include <stdio.h>
21 #define SHASH_RECORDS_AT_(self, tableIndex, index) (self->records + self->tableSize*tableIndex + index)
22 #define SHASH_RECORDS_AT_HASH_(self, tableIndex, hash) \
23 (self->records + self->tableSize*tableIndex + (hash & self->mask))
25 IOINLINE unsigned int SHash_count(SHash *self)
27 return self->numKeys;
30 IOINLINE void SHashRecord_swap(SHashRecord* r1, SHashRecord* r2)
32 SHashRecord t = *r1;
33 *r1 = *r2;
34 *r2 = t;
37 IOINLINE unsigned int SHash_keysAreEqual_(SHash *self, void *key1, void *key2)
39 return key2 && self->keysEqual(key1, key2);
42 // simple hash functions, should be enough for pointers
44 IOINLINE unsigned int SHash_hash(SHash *self, void *key)
46 intptr_t k = self->hashForKey(key);
47 return k ^ (k >> 4);
50 IOINLINE unsigned int SHash_hash_more(SHash *self, unsigned int hash)
52 return hash ^ (hash >> self->log2tableSize);
55 // -----------------------------------
57 IOINLINE void SHash_clean(SHash *self)
59 memset(self->records, 0, sizeof(SHashRecord) * self->tableSize * 2);
60 self->numKeys = 0;
63 IOINLINE SHashRecord *SHash_recordAt_(SHash *self, void *key)
65 unsigned int hash;
66 SHashRecord *record;
68 // try first location
70 hash = SHash_hash(self, key);
71 record = SHASH_RECORDS_AT_HASH_(self, 0, hash);
72 if (SHash_keysAreEqual_(self, key, record->key)) { return record; }
74 // try second location
76 hash = SHash_hash_more(self, hash);
77 record = SHASH_RECORDS_AT_HASH_(self, 1, hash);
78 if (SHash_keysAreEqual_(self, key, record->key)) { return record; }
80 return &self->nullRecord;
83 IOINLINE void *SHash_at_(SHash *self, void *key)
85 return SHash_recordAt_(self, key)->value;
88 IOINLINE int SHashKey_hasKey_(SHash *self, void *key)
90 return SHash_at_(self, key) != NULL;
93 IOINLINE void SHash_at_put_(SHash *self, void *key, void *value)
95 SHashRecord thisRecord;
96 SHashRecord *record;
98 record = SHash_recordAt_(self, key);
100 // already a matching key, replace it
101 if (record != &self->nullRecord && SHash_keysAreEqual_(self, key, record->key))
103 record->value = value;
104 return;
107 thisRecord.key = key;
108 thisRecord.value = value;
110 record = SHash_cuckoo_(self, &thisRecord);
112 if (!record) // collision
114 SHash_growWithRecord(self, &thisRecord);
115 //printf("grow due to key collision: SHash_%p numKeys %i \ttableSize %i \tratio %f\n", (void *)self, self->numKeys, self->tableSize, (float) self->numKeys / (float) self->tableSize);
117 else
119 *record = thisRecord;
120 self->numKeys ++;
121 if (self->numKeys > SHash_maxKeys(self))
123 SHash_grow(self);
124 //printf("grow due to full table: SHash_%p numKeys %i \ttableSize %i \tratio %f\n", (void *)self, self->numKeys, self->tableSize, (float) self->numKeys / (float) self->tableSize);
130 IOINLINE void SHash_removeKey_(SHash *self, void *key)
132 SHashRecord *record = SHash_recordAt_(self, key);
133 void *rkey = record->key;
135 if (rkey && SHash_keysAreEqual_(self, rkey, key))
137 self->numKeys --;
138 memset(record, 0, sizeof(SHashRecord));
142 // --- enumeration --------------------------------------------------
144 #define SHASH_FOREACH(self, pkey, pvalue, code) \
146 SHash *_self = (self);\
147 unsigned int _i, _j, _size = _self->tableSize;\
148 void * pkey;\
149 void * pvalue;\
151 for (_j = 0; _j < 2; _j ++)\
152 for (_i = 0; _i < _size; _i ++)\
154 SHashRecord *_record = SHASH_RECORDS_AT_(_self, _j, _i);\
155 if (_record->key)\
157 pkey = _record->key;\
158 pvalue = _record->value;\
159 code;\
165 typedef BASEKIT_API void (SHashDoCallback)(void *);
166 IOINLINE void SHash_do_(SHash *self, SHashDoCallback *callback)
167 { SHASH_FOREACH(self, k, v, (*callback)(v)); }
169 IOINLINE void SHash_doOnKeys_(SHash *self, SHashDoCallback *callback)
170 { SHASH_FOREACH(self, k, v, (*callback)(k)); }
172 IOINLINE void SHash_doOnKeyAndValue_(SHash *self, SHashDoCallback *callback)
173 { SHASH_FOREACH(self, k, v, (*callback)(k); (*callback)(v);); }
176 #undef IO_IN_C_FILE
177 #endif