00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef POINTERHASH_DEFINED
00011 #define POINTERHASH_DEFINED 1
00012
00013 #include "Common.h"
00014 #include <stddef.h>
00015 #include "PortableStdint.h"
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019 #include <assert.h>
00020
00021
00022 #ifdef __cplusplus
00023 extern "C" {
00024 #endif
00025
00026 #define POINTERHASH_MAXLOOP 10
00027
00028 #include "PointerHash_struct.h"
00029
00030 static inline BASEKIT_API PointerHash *PointerHash_new(void);
00031 static inline BASEKIT_API void PointerHash_copy_(PointerHash *self, const PointerHash *other);
00032 static inline BASEKIT_API PointerHash *PointerHash_clone(PointerHash *self);
00033 static inline BASEKIT_API void PointerHash_free(PointerHash *self);
00034
00035 static inline BASEKIT_API void PointerHash_at_put_(PointerHash *self, void *k, void *v);
00036 static inline BASEKIT_API void PointerHash_removeKey_(PointerHash *self, void *k);
00037 static inline BASEKIT_API size_t PointerHash_size(PointerHash *self);
00038
00039 static inline BASEKIT_API size_t PointerHash_memorySize(PointerHash *self);
00040 static inline BASEKIT_API void PointerHash_compact(PointerHash *self);
00041
00042
00043
00044 static inline BASEKIT_API void PointerHash_setSize_(PointerHash *self, size_t size);
00045 static inline BASEKIT_API void PointerHash_insert_(PointerHash *self, PointerHashRecord *x);
00046 static inline BASEKIT_API void PointerHash_grow(PointerHash *self);
00047 static inline BASEKIT_API void PointerHash_shrinkIfNeeded(PointerHash *self);
00048 static inline BASEKIT_API void PointerHash_shrink(PointerHash *self);
00049 static inline BASEKIT_API void PointerHash_show(PointerHash *self);
00050 static inline BASEKIT_API void PointerHash_updateMask(PointerHash *self);
00051
00052 #undef IOINLINE
00053 #define IOINLINE static inline
00054
00055
00056
00057 #define PointerHashRecords_recordAt_(records, pos) (PointerHashRecord *)(records + (pos * sizeof(PointerHashRecord)))
00058
00059
00060 IOINLINE PointerHashRecord *PointerHash_record1_(PointerHash *self, void *k)
00061 {
00062
00063 intptr_t kk = (intptr_t)k;
00064 size_t pos = ((kk^(kk>>4)) | 0x1) & self->mask;
00065 return PointerHashRecords_recordAt_(self->records, pos);
00066 }
00067
00068 IOINLINE PointerHashRecord *PointerHash_record2_(PointerHash *self, void *k)
00069 {
00070
00071 intptr_t kk = (intptr_t)k;
00072
00073 size_t pos = (kk << 1) & self->mask;
00074 return PointerHashRecords_recordAt_(self->records, pos);
00075 }
00076
00077 IOINLINE void *PointerHash_at_(PointerHash *self, void *k)
00078 {
00079 PointerHashRecord *r;
00080
00081 r = PointerHash_record1_(self, k);
00082 if(k == r->k) return r->v;
00083
00084 r = PointerHash_record2_(self, k);
00085 if(k == r->k) return r->v;
00086
00087 return 0x0;
00088 }
00089
00090 IOINLINE size_t PointerHash_count(PointerHash *self)
00091 {
00092 return self->keyCount;
00093 }
00094
00095 IOINLINE int PointerHashKey_hasKey_(PointerHash *self, void *key)
00096 {
00097 return PointerHash_at_(self, key) != NULL;
00098 }
00099
00100 IOINLINE void PointerHash_at_put_(PointerHash *self, void *k, void *v)
00101 {
00102 PointerHashRecord *r;
00103
00104 r = PointerHash_record1_(self, k);
00105
00106 if(!r->k)
00107 {
00108 r->k = k;
00109 r->v = v;
00110 self->keyCount ++;
00111 return;
00112 }
00113
00114 if(r->k == k)
00115 {
00116 r->v = v;
00117 return;
00118 }
00119
00120 r = PointerHash_record2_(self, k);
00121
00122 if(!r->k)
00123 {
00124 r->k = k;
00125 r->v = v;
00126 self->keyCount ++;
00127 return;
00128 }
00129
00130 if(r->k == k)
00131 {
00132 r->v = v;
00133 return;
00134 }
00135
00136 {
00137 PointerHashRecord x;
00138 x.k = k;
00139 x.v = v;
00140 PointerHash_insert_(self, &x);
00141 }
00142 }
00143
00144 IOINLINE void PointerHash_shrinkIfNeeded(PointerHash *self)
00145 {
00146 if(self->keyCount < self->size/8)
00147 {
00148 PointerHash_shrink(self);
00149 }
00150 }
00151
00152 IOINLINE void PointerHashRecord_swapWith_(PointerHashRecord *self, PointerHashRecord *other)
00153 {
00154 PointerHashRecord tmp = *self;
00155 *self = *other;
00156 *other = tmp;
00157 }
00158
00159 IOINLINE void PointerHash_clean(PointerHash *self)
00160 {
00161 memset(self->records, 0, sizeof(PointerHashRecord) * self->size);
00162 self->keyCount = 0;
00163 }
00164
00165
00166 IOINLINE PointerHash *PointerHash_new(void)
00167 {
00168 PointerHash *self = (PointerHash *)io_calloc(1, sizeof(PointerHash));
00169 PointerHash_setSize_(self, 8);
00170 return self;
00171 }
00172
00173 IOINLINE void PointerHash_copy_(PointerHash *self, const PointerHash *other)
00174 {
00175 io_free(self->records);
00176 memcpy(self, other, sizeof(PointerHash));
00177 self->records = (unsigned char *) malloc(self->size * sizeof(PointerHashRecord));
00178 memcpy(self->records, other->records, self->size * sizeof(PointerHashRecord));
00179 }
00180
00181 IOINLINE PointerHash *PointerHash_clone(PointerHash *self)
00182 {
00183 PointerHash *other = PointerHash_new();
00184 PointerHash_copy_(other, self);
00185 return other;
00186 }
00187
00188 IOINLINE void PointerHash_setSize_(PointerHash *self, size_t size)
00189 {
00190 self->records = (unsigned char *) realloc(self->records, size * sizeof(PointerHashRecord));
00191
00192 if(size > self->size)
00193 {
00194 memset(self->records + self->size * sizeof(PointerHashRecord),
00195 0x0, (size - self->size) * sizeof(PointerHashRecord));
00196 }
00197
00198 self->size = size;
00199
00200 PointerHash_updateMask(self);
00201 }
00202
00203 IOINLINE void PointerHash_updateMask(PointerHash *self)
00204 {
00205 self->mask = (intptr_t)(self->size - 1);
00206 }
00207
00208 IOINLINE void PointerHash_show(PointerHash *self)
00209 {
00210 size_t i;
00211
00212 printf("PointerHash records:\n");
00213 for(i = 0; i < self->size; i++)
00214 {
00215 PointerHashRecord *r = PointerHashRecords_recordAt_(self->records, i);
00216 printf(" %i: %p %p\n", (int)i, r->k, r->v);
00217 }
00218 }
00219
00220 IOINLINE void PointerHash_free(PointerHash *self)
00221 {
00222 io_free(self->records);
00223 io_free(self);
00224 }
00225
00226 IOINLINE void PointerHash_insert_(PointerHash *self, PointerHashRecord *x)
00227 {
00228 int n;
00229
00230 for (n = 0; n < POINTERHASH_MAXLOOP; n ++)
00231 {
00232 PointerHashRecord *r;
00233
00234 r = PointerHash_record1_(self, x->k);
00235 PointerHashRecord_swapWith_(x, r);
00236 if(x->k == 0x0) { self->keyCount ++; return; }
00237
00238 r = PointerHash_record2_(self, x->k);
00239 PointerHashRecord_swapWith_(x, r);
00240 if(x->k == 0x0) { self->keyCount ++; return; }
00241 }
00242
00243 PointerHash_grow(self);
00244 PointerHash_at_put_(self, x->k, x->v);
00245 }
00246
00247 IOINLINE void PointerHash_insertRecords(PointerHash *self, unsigned char *oldRecords, size_t oldSize)
00248 {
00249 size_t i;
00250
00251 for (i = 0; i < oldSize; i ++)
00252 {
00253 PointerHashRecord *r = PointerHashRecords_recordAt_(oldRecords, i);
00254
00255 if (r->k)
00256 {
00257 PointerHash_at_put_(self, r->k, r->v);
00258 }
00259 }
00260 }
00261
00262 IOINLINE void PointerHash_resizeTo_(PointerHash *self, size_t newSize)
00263 {
00264 unsigned char *oldRecords = self->records;
00265 size_t oldSize = self->size;
00266 self->size = newSize;
00267 self->records = (unsigned char *) io_calloc(1, sizeof(PointerHashRecord) * self->size);
00268 self->keyCount = 0;
00269 PointerHash_updateMask(self);
00270 PointerHash_insertRecords(self, oldRecords, oldSize);
00271 io_free(oldRecords);
00272 }
00273
00274 IOINLINE void PointerHash_grow(PointerHash *self)
00275 {
00276 PointerHash_resizeTo_(self, self->size * 2);
00277 }
00278
00279 IOINLINE void PointerHash_shrink(PointerHash *self)
00280 {
00281 PointerHash_resizeTo_(self, self->size / 2);
00282 }
00283
00284 IOINLINE void PointerHash_removeKey_(PointerHash *self, void *k)
00285 {
00286 PointerHashRecord *r;
00287
00288 r = PointerHash_record1_(self, k);
00289 if(r->k == k)
00290 {
00291 r->k = 0x0;
00292 r->v = 0x0;
00293 self->keyCount --;
00294 PointerHash_shrinkIfNeeded(self);
00295 return;
00296 }
00297
00298 r = PointerHash_record2_(self, k);
00299 if(r->k == k)
00300 {
00301 r->k = 0x0;
00302 r->v = 0x0;
00303 self->keyCount --;
00304 PointerHash_shrinkIfNeeded(self);
00305 return;
00306 }
00307 }
00308
00309 IOINLINE size_t PointerHash_size(PointerHash *self)
00310 {
00311 return self->keyCount;
00312 }
00313
00314
00315
00316 IOINLINE size_t PointerHash_memorySize(PointerHash *self)
00317 {
00318 return sizeof(PointerHash) + self->size * sizeof(PointerHashRecord);
00319 }
00320
00321 void PointerHash_compact(PointerHash *self)
00322 {
00323 }
00324
00325
00326
00327
00328 #define POINTERHASH_FOREACH(self, pkey, pvalue, code) \
00329 {\
00330 PointerHash *_self = (self);\
00331 unsigned char *_records = _self->records;\
00332 unsigned int _i, _size = _self->size;\
00333 void *pkey;\
00334 void *pvalue;\
00335 \
00336 for (_i = 0; _i < _size; _i ++)\
00337 {\
00338 PointerHashRecord *_record = PointerHashRecords_recordAt_(_records, _i);\
00339 if (_record->k)\
00340 {\
00341 pkey = _record->k;\
00342 pvalue = _record->v;\
00343 code;\
00344 }\
00345 }\
00346 }
00347
00348
00349 #define PointerHash_cleanSlots(self)
00350 #define PointerHash_hasDirtyKey_(self, k) 0
00351
00352 #ifdef __cplusplus
00353 }
00354 #endif
00355 #endif