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 "PointerSetHash_struct.h"
00029
00030 static inline BASEKIT_API PointerSetHash *PointerSetHash_new(void);
00031 static inline BASEKIT_API void PointerSetHash_copy_(PointerSetHash *self, const PointerSetHash *other);
00032 static inline BASEKIT_API PointerSetHash *PointerSetHash_clone(PointerSetHash *self);
00033 static inline BASEKIT_API void PointerSetHash_free(PointerSetHash *self);
00034
00035 static inline BASEKIT_API void PointerSetHash_at_put_(PointerSetHash *self, void *k);
00036 static inline BASEKIT_API void PointerSetHash_removeKey_(PointerSetHash *self, void *k);
00037 static inline BASEKIT_API size_t PointerSetHash_size(PointerSetHash *self);
00038
00039 static inline BASEKIT_API size_t PointerSetHash_memorySize(PointerSetHash *self);
00040 static inline BASEKIT_API void PointerSetHash_compact(PointerSetHash *self);
00041
00042
00043
00044 static inline BASEKIT_API void PointerSetHash_setSize_(PointerSetHash *self, size_t size);
00045 static inline BASEKIT_API void PointerSetHash_insert_(PointerSetHash *self, PointerSetHashRecord *x);
00046 static inline BASEKIT_API void PointerSetHash_grow(PointerSetHash *self);
00047 static inline BASEKIT_API void PointerSetHash_shrinkIfNeeded(PointerSetHash *self);
00048 static inline BASEKIT_API void PointerSetHash_shrink(PointerSetHash *self);
00049 static inline BASEKIT_API void PointerSetHash_show(PointerSetHash *self);
00050 static inline BASEKIT_API void PointerSetHash_updateMask(PointerSetHash *self);
00051
00052 #undef IOINLINE
00053 #define IOINLINE static inline
00054
00055
00056
00057 #define PointerSetHashRecords_recordAt_(records, pos) (PointerSetHashRecord *)(records + (pos * sizeof(PointerSetHashRecord)))
00058
00059
00060 IOINLINE PointerSetHashRecord *PointerSetHash_record1_(PointerSetHash *self, void *k)
00061 {
00062
00063 intptr_t kk = (intptr_t)k;
00064 size_t pos = ((kk^(kk>>4)) | 0x1) & self->mask;
00065 return PointerSetHashRecords_recordAt_(self->records, pos);
00066 }
00067
00068 IOINLINE PointerSetHashRecord *PointerSetHash_record2_(PointerSetHash *self, void *k)
00069 {
00070
00071 intptr_t kk = (intptr_t)k;
00072
00073 size_t pos = (kk << 1) & self->mask;
00074 return PointerSetHashRecords_recordAt_(self->records, pos);
00075 }
00076
00077 IOINLINE void *PointerSetHash_at_(PointerSetHash *self, void *k)
00078 {
00079 PointerSetHashRecord *r;
00080
00081 r = PointerSetHash_record1_(self, k);
00082 if(k == r->k) return 1;
00083
00084 r = PointerSetHash_record2_(self, k);
00085 if(k == r->k) return 1;
00086
00087 return 0x0;
00088 }
00089
00090 IOINLINE size_t PointerSetHash_count(PointerSetHash *self)
00091 {
00092 return self->keyCount;
00093 }
00094
00095 IOINLINE int PointerSetHashKey_hasKey_(PointerSetHash *self, void *key)
00096 {
00097 return PointerSetHash_at_(self, key) != NULL;
00098 }
00099
00100 IOINLINE void PointerSetHash_at_put_(PointerSetHash *self, void *k)
00101 {
00102 PointerSetHashRecord *r;
00103
00104 r = PointerSetHash_record1_(self, k);
00105
00106 if(!r->k)
00107 {
00108 r->k = k;
00109 self->keyCount ++;
00110 return;
00111 }
00112
00113 if(r->k == k)
00114 {
00115 return;
00116 }
00117
00118 r = PointerSetHash_record2_(self, k);
00119
00120 if(!r->k)
00121 {
00122 r->k = k;
00123 self->keyCount ++;
00124 return;
00125 }
00126
00127 if(r->k == k)
00128 {
00129 return;
00130 }
00131
00132 {
00133 PointerSetHashRecord x;
00134 x.k = k;
00135 PointerSetHash_insert_(self, &x);
00136 }
00137 }
00138
00139 IOINLINE void PointerSetHash_shrinkIfNeeded(PointerSetHash *self)
00140 {
00141 if(self->keyCount < self->size/8)
00142 {
00143 PointerSetHash_shrink(self);
00144 }
00145 }
00146
00147 IOINLINE void PointerSetHashRecord_swapWith_(PointerSetHashRecord *self, PointerSetHashRecord *other)
00148 {
00149 PointerSetHashRecord tmp = *self;
00150 *self = *other;
00151 *other = tmp;
00152 }
00153
00154 IOINLINE void PointerSetHash_clean(PointerSetHash *self)
00155 {
00156 memset(self->records, 0, sizeof(PointerSetHashRecord) * self->size);
00157 self->keyCount = 0;
00158 }
00159
00160
00161
00162 #define POINTERHASH_FOREACH(self, pkey, code) \
00163 {\
00164 PointerSetHash *_self = (self);\
00165 unsigned char *_records = _self->records;\
00166 unsigned int _i, _size = _self->size;\
00167 void *pkey;\
00168 void *pvalue;\
00169 \
00170 for (_i = 0; _i < _size; _i ++)\
00171 {\
00172 PointerSetHashRecord *_record = PointerSetHashRecords_recordAt_(_records, _i);\
00173 if (_record->k)\
00174 {\
00175 pkey = _record->k;\
00176 code;\
00177 }\
00178 }\
00179 }
00180
00181
00182
00183 IOINLINE PointerSetHash *PointerSetHash_new(void)
00184 {
00185 PointerSetHash *self = (PointerSetHash *)io_calloc(1, sizeof(PointerSetHash));
00186 PointerSetHash_setSize_(self, 8);
00187 return self;
00188 }
00189
00190 IOINLINE void PointerSetHash_copy_(PointerSetHash *self, const PointerSetHash *other)
00191 {
00192 io_free(self->records);
00193 memcpy(self, other, sizeof(PointerSetHash));
00194 self->records = malloc(self->size * sizeof(PointerSetHashRecord));
00195 memcpy(self->records, other->records, self->size * sizeof(PointerSetHashRecord));
00196 }
00197
00198 IOINLINE PointerSetHash *PointerSetHash_clone(PointerSetHash *self)
00199 {
00200 PointerSetHash *other = PointerSetHash_new();
00201 PointerSetHash_copy_(other, self);
00202 return other;
00203 }
00204
00205 IOINLINE void PointerSetHash_setSize_(PointerSetHash *self, size_t size)
00206 {
00207 self->records = realloc(self->records, size * sizeof(PointerSetHashRecord));
00208
00209 if(size > self->size)
00210 {
00211 memset(self->records + self->size * sizeof(PointerSetHashRecord),
00212 0x0, (size - self->size) * sizeof(PointerSetHashRecord));
00213 }
00214
00215 self->size = size;
00216
00217 PointerSetHash_updateMask(self);
00218 }
00219
00220 IOINLINE void PointerSetHash_updateMask(PointerSetHash *self)
00221 {
00222 self->mask = (intptr_t)(self->size - 1);
00223 }
00224
00225 IOINLINE void PointerSetHash_show(PointerSetHash *self)
00226 {
00227 size_t i;
00228
00229 printf("PointerSetHash records:\n");
00230 for(i = 0; i < self->size; i++)
00231 {
00232 PointerSetHashRecord *r = PointerSetHashRecords_recordAt_(self->records, i);
00233 printf(" %i: %p\n", (int)i, r->k);
00234 }
00235 }
00236
00237 IOINLINE void PointerSetHash_free(PointerSetHash *self)
00238 {
00239 io_free(self->records);
00240 io_free(self);
00241 }
00242
00243 IOINLINE void PointerSetHash_insert_(PointerSetHash *self, PointerSetHashRecord *x)
00244 {
00245 int n;
00246
00247 for (n = 0; n < POINTERHASH_MAXLOOP; n ++)
00248 {
00249 PointerSetHashRecord *r;
00250
00251 r = PointerSetHash_record1_(self, x->k);
00252 PointerSetHashRecord_swapWith_(x, r);
00253 if(x->k == 0x0) { self->keyCount ++; return; }
00254
00255 r = PointerSetHash_record2_(self, x->k);
00256 PointerSetHashRecord_swapWith_(x, r);
00257 if(x->k == 0x0) { self->keyCount ++; return; }
00258 }
00259
00260 PointerSetHash_grow(self);
00261 PointerSetHash_at_put_(self, x->k);
00262 }
00263
00264 IOINLINE void PointerSetHash_insertRecords(PointerSetHash *self, unsigned char *oldRecords, size_t oldSize)
00265 {
00266 size_t i;
00267
00268 for (i = 0; i < oldSize; i ++)
00269 {
00270 PointerSetHashRecord *r = PointerSetHashRecords_recordAt_(oldRecords, i);
00271
00272 if (r->k)
00273 {
00274 PointerSetHash_at_put_(self, r->k);
00275 }
00276 }
00277 }
00278
00279 IOINLINE void PointerSetHash_resizeTo_(PointerSetHash *self, size_t newSize)
00280 {
00281 unsigned char *oldRecords = self->records;
00282 size_t oldSize = self->size;
00283 self->size = newSize;
00284 self->records = io_calloc(1, sizeof(PointerSetHashRecord) * self->size);
00285 self->keyCount = 0;
00286 PointerSetHash_updateMask(self);
00287 PointerSetHash_insertRecords(self, oldRecords, oldSize);
00288 io_free(oldRecords);
00289 }
00290
00291 IOINLINE void PointerSetHash_grow(PointerSetHash *self)
00292 {
00293 PointerSetHash_resizeTo_(self, self->size * 2);
00294 }
00295
00296 void PointerSetHash_shrink(PointerSetHash *self)
00297 {
00298 PointerSetHash_resizeTo_(self, self->size / 2);
00299 }
00300
00301 IOINLINE void PointerSetHash_removeKey_(PointerSetHash *self, void *k)
00302 {
00303 PointerSetHashRecord *r;
00304
00305 r = PointerSetHash_record1_(self, k);
00306 if(r->k == k)
00307 {
00308 r->k = 0x0;
00309 self->keyCount --;
00310 PointerSetHash_shrinkIfNeeded(self);
00311 return;
00312 }
00313
00314 r = PointerSetHash_record2_(self, k);
00315 if(r->k == k)
00316 {
00317 r->k = 0x0;
00318 self->keyCount --;
00319 PointerSetHash_shrinkIfNeeded(self);
00320 return;
00321 }
00322 }
00323
00324 IOINLINE size_t PointerSetHash_size(PointerSetHash *self)
00325 {
00326 return self->keyCount;
00327 }
00328
00329
00330
00331 IOINLINE size_t PointerSetHash_memorySize(PointerSetHash *self)
00332 {
00333 return sizeof(PointerSetHash) + self->size * sizeof(PointerSetHashRecord);
00334 }
00335
00336 IOINLINE void PointerSetHash_compact(PointerSetHash *self)
00337 {
00338 }
00339
00340
00341 #define PointerSetHash_cleanSlots(self)
00342 #define PointerSetHash_hasDirtyKey_(self, k) 0
00343
00344 #ifdef __cplusplus
00345 }
00346 #endif
00347 #endif