00001
00002
00003
00004
00005 #define CHASH_C
00006 #include "CHash.h"
00007 #undef CHASH_C
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <string.h>
00011 #include <assert.h>
00012
00013 CHash *CHash_new(void)
00014 {
00015 CHash *self = (CHash *)io_calloc(1, sizeof(CHash));
00016 CHash_setSize_(self, 8);
00017 return self;
00018 }
00019
00020 void CHash_copy_(CHash *self, const CHash *other)
00021 {
00022 io_free(self->records);
00023 memcpy(self, other, sizeof(CHash));
00024 self->records = malloc(self->size * sizeof(CHashRecord));
00025 memcpy(self->records, other->records, self->size * sizeof(CHashRecord));
00026 }
00027
00028 CHash *CHash_clone(CHash *self)
00029 {
00030 CHash *other = CHash_new();
00031 CHash_copy_(other, self);
00032 return other;
00033 }
00034
00035 void CHash_setSize_(CHash *self, size_t size)
00036 {
00037 self->records = realloc(self->records, size * sizeof(CHashRecord));
00038
00039 if(size > self->size)
00040 {
00041 memset(self->records + self->size * sizeof(CHashRecord),
00042 0x0, (size - self->size) * sizeof(CHashRecord));
00043 }
00044
00045 self->size = size;
00046
00047 CHash_updateMask(self);
00048
00049 }
00050
00051 void CHash_updateMask(CHash *self)
00052 {
00053 self->mask = (intptr_t)(self->size - 1);
00054 }
00055
00056 void CHash_show(CHash *self)
00057 {
00058 size_t i;
00059
00060 printf("CHash records:\n");
00061 for(i = 0; i < self->size; i++)
00062 {
00063 CHashRecord *r = CRecords_recordAt_(self->records, i);
00064 printf(" %i: %p %p\n", (int)i, r->k, r->v);
00065 }
00066 }
00067
00068 void CHash_free(CHash *self)
00069 {
00070 io_free(self->records);
00071 io_free(self);
00072 }
00073
00074 void CHash_setHash1Func_(CHash *self, CHashHashFunc *f)
00075 {
00076 self->hash1 = f;
00077 }
00078
00079 void CHash_setHash2Func_(CHash *self, CHashHashFunc *f)
00080 {
00081 self->hash2 = f;
00082 }
00083
00084 void CHash_setEqualFunc_(CHash *self, CHashEqualFunc *f)
00085 {
00086 self->equals = f;
00087 }
00088
00089 int CHash_insert_(CHash *self, CHashRecord *x)
00090 {
00091 int n;
00092
00093 for (n = 0; n < CHASH_MAXLOOP; n ++)
00094 {
00095 CHashRecord *r;
00096
00097
00098
00099 r = CHash_record1_(self, x->k);
00100 CHashRecord_swapWith_(x, r);
00101 if(x->k == 0x0) { self->keyCount ++; return 0; }
00102
00103
00104
00105 r = CHash_record2_(self, x->k);
00106 CHashRecord_swapWith_(x, r);
00107 if(x->k == 0x0) { self->keyCount ++; return 0; }
00108 }
00109
00110 if(self->isResizing)
00111 {
00112 return -1;
00113 }
00114
00115 CHash_grow(self);
00116 CHash_at_put_(self, x->k, x->v);
00117 return 0;
00118 }
00119
00120 int CHash_insertRecords(CHash *self, unsigned char *oldRecords, size_t oldSize)
00121 {
00122 size_t i;
00123
00124 for (i = 0; i < oldSize; i ++)
00125 {
00126 CHashRecord *r = CRecords_recordAt_(oldRecords, i);
00127
00128 if (r->k)
00129 {
00130 if(CHash_at_put_(self, r->k, r->v)) return 1;
00131 }
00132 }
00133 return 0;
00134 }
00135
00136 int CHash_resizeTo_(CHash *self, size_t newSize)
00137 {
00138 unsigned char *oldRecords = self->records;
00139 size_t oldSize = self->size;
00140
00141 self->isResizing = 1;
00142
00143
00144
00145 do
00146 {
00147 self->size = newSize;
00148 self->records = io_calloc(1, sizeof(CHashRecord) * self->size);
00149 self->keyCount = 0;
00150 CHash_updateMask(self);
00151 if(CHash_insertRecords(self, oldRecords, oldSize) == 0)
00152 {
00153 self->isResizing = 0;
00154 }
00155 else
00156 {
00157
00158 newSize *= 2;
00159 io_free(self->records);
00160 }
00161 } while(self->isResizing);
00162
00163 io_free(oldRecords);
00164 return 0;
00165 }
00166
00167 void CHash_grow(CHash *self)
00168 {
00169 CHash_resizeTo_(self, self->size * 2);
00170 }
00171
00172 void CHash_shrink(CHash *self)
00173 {
00174
00175
00176 }
00177
00178 void CHash_removeKey_(CHash *self, void *k)
00179 {
00180 CHashRecord *r1 = CHash_record1_(self, k);
00181 CHashRecord *r2;
00182
00183 if(r1->k && self->equals(k, r1->k))
00184 {
00185 r1->k = 0x0;
00186 r1->v = 0x0;
00187 self->keyCount --;
00188 CHash_shrinkIfNeeded(self);
00189 return;
00190 }
00191
00192 r2 = CHash_record2_(self, k);
00193
00194 if(r2->k && self->equals(k, r2->k))
00195 {
00196 r2->k = 0x0;
00197 r2->v = 0x0;
00198 self->keyCount --;
00199 CHash_shrinkIfNeeded(self);
00200 return;
00201 }
00202 }
00203
00204 void CHash_clear(CHash *self)
00205 {
00206 memset(self->records, 0x0, self->size * sizeof(CHashRecord));
00207 self->keyCount = 0;
00208 CHash_shrinkIfNeeded(self);
00209 }
00210
00211 size_t CHash_size(CHash *self)
00212 {
00213 return self->keyCount;
00214 }
00215
00216
00217
00218 size_t CHash_memorySize(CHash *self)
00219 {
00220 return sizeof(CHash) + self->size * sizeof(CHashRecord);
00221 }
00222
00223 void CHash_compact(CHash *self)
00224 {
00225 }
00226
00227 float CHash_density(CHash *self)
00228 {
00229 float kc = (float)self->keyCount;
00230 float size = (float)self->size;
00231 return kc/size;
00232 }
00233