2 docCopyright("Steve Dekorte", 2002)
3 docCopyright("Marc Fauconneau", 2007)
4 docLicense("BSD revised")
14 void SHash_print(SHash
* self
)
16 printf("self->log2tableSize = %d\n", self
->log2tableSize
);
17 printf("self->tableSize = %d\n", self
->tableSize
);
18 printf("self->numKeys = %d\n", self
->numKeys
);
20 printf("self->mask = %d\n", self
->mask
);
21 printf("self->balance = %d\n", self
->balance
);
22 printf("self->maxLoops = %d\n", SHash_maxLoops(self
));
23 printf("self->maxKeys = %d\n", SHash_maxKeys(self
));
25 printf("self->nullRecord.key = %d\n", self
->nullRecord
.key
);
26 printf("self->nullRecord.value = %d\n", self
->nullRecord
.value
);
28 printf("\nmemory usage : %d bytes\n", SHash_memorySize(self
));
29 printf("\ndensity : %f \n", (self
->numKeys
*sizeof(SHashRecord
))/(double)SHash_memorySize(self
));
35 for (j
= 0; j
< 2; j
++)
37 for (i
= 0; i
< self
->tableSize
; i
++)
39 SHashRecord
*record
= SHASH_RECORDS_AT_(self
, j
, i
);
40 if (NULL
== record
->key
)
42 if (NULL
== record
->value
)
55 printf("balance : %d / %d [%1.3f]\n", count
[0], count
[1], (count
[0]-count
[1])/(double)(count
[0]+count
[1]) );
59 void SHash_tableInit_(SHash
* self
, int log2tableSize
)
61 if (log2tableSize
> 20)
63 self
->log2tableSize
= log2tableSize
;
64 self
->tableSize
= 1<<self
->log2tableSize
;
65 self
->records
= (SHashRecord
*)io_calloc(1, sizeof(SHashRecord
) * self
->tableSize
* 2);
66 self
->mask
= self
->tableSize
-1;
69 SHash
*SHash_new(void)
71 SHash
*self
= (SHash
*)io_calloc(1, sizeof(SHash
));
73 SHash_tableInit_(self
, 1);
78 SHash
*SHash_clone(SHash
*self
)
80 SHash
*child
= SHash_new();
81 SHash_copy_(child
, self
);
85 void SHash_free(SHash
*self
)
87 io_free(self
->records
);
91 size_t SHash_memorySize(SHash
*self
)
93 return sizeof(SHash
) + (self
->tableSize
* 2 * sizeof(SHashRecord
));
96 void SHash_compact(SHash
*self
)
98 printf("need to implement SHash_compact\n");
101 void SHash_copy_(SHash
*self
, SHash
*other
)
103 SHashRecord
*records
= self
->records
;
104 memcpy(self
, other
, sizeof(SHash
));
105 self
->records
= (SHashRecord
*)io_realloc(records
, sizeof(SHashRecord
) * self
->tableSize
* 2);
106 memcpy(self
->records
, other
->records
, sizeof(SHashRecord
) * self
->tableSize
* 2);
109 /* this is where our cuckoo acts :
110 it kicks records out of nests until it finds an empty nest or gets tired
111 returns the empty nest if found, or NULL if it is too tired
113 SHashRecord
*SHash_cuckoo_(SHash
*self
, SHashRecord
* thisRecord
)
117 record
= SHash_recordAt_(self
, thisRecord
->key
);
119 if (record
!= &self
->nullRecord
&& NULL
== record
->key
)
123 if (SHash_keysAreEqual_(self
, thisRecord
->key
, record
->key
))
135 hash
= SHash_hash_more(self
, SHash_hash(self
, thisRecord
->key
));
136 record
= SHASH_RECORDS_AT_HASH_(self
, 1, hash
);
137 if (NULL
== record
->key
)
140 SHashRecord_swap(record
, thisRecord
);
142 if (SHash_keysAreEqual_(self
, thisRecord
->key
, record
->key
))
147 for (i
= 0; i
< SHash_maxLoops(self
); i
++)
149 hash
= SHash_hash(self
, thisRecord
->key
);
150 record
= SHASH_RECORDS_AT_HASH_(self
, 0, hash
);
151 if (NULL
== record
->key
)
154 SHashRecord_swap(record
, thisRecord
);
156 if (SHash_keysAreEqual_(self
, thisRecord
->key
, record
->key
))
159 hash
= SHash_hash_more(self
, SHash_hash(self
, thisRecord
->key
));
160 record
= SHASH_RECORDS_AT_HASH_(self
, 1, hash
);
161 if (NULL
== record
->key
)
164 SHashRecord_swap(record
, thisRecord
);
166 if (SHash_keysAreEqual_(self
, thisRecord
->key
, record
->key
))
170 // the cuckoo is tired ^^
178 void SHash_grow(SHash
*self
)
180 unsigned int oldTableSize
= self
->tableSize
;
181 SHashRecord
* oldRecords
= self
->records
;
183 self
->records
= NULL
;
184 while (self
->records
== NULL
)
188 SHash_tableInit_(self
, self
->log2tableSize
+ 1);
190 // enumerate old records
193 while (i
< oldTableSize
*2)
195 SHashRecord thisRecord
= oldRecords
[i
];
200 SHashRecord
*record
= SHash_cuckoo_(self
, &thisRecord
);
201 if (!record
) // collision
203 io_free(self
->records
);
204 self
->records
= NULL
;
205 break; // grow & rehash
207 *record
= thisRecord
;
214 void SHash_growWithRecord(SHash
*self
, SHashRecord
* thisRecord
)
216 // put the value anywhere, SHash_grow will rehash
219 for (j
= 0; j
< 2; j
++)
220 for (i
= 0; i
< self
->tableSize
; i
++)
222 SHashRecord
*record
= SHASH_RECORDS_AT_(self
, j
, i
);
224 if (record
!= &self
->nullRecord
&& NULL
== record
->key
)
226 *record
= *thisRecord
;
233 // we can never be there
237 void SHash_removeValue_(SHash
*self
, void *value
)
242 while (index
< self
->tableSize
*2)
244 record
= self
->records
+ index
;
247 if (record
->key
&& record
->value
== value
)
250 memset(record
, 0, sizeof(SHashRecord
));
256 void *SHash_firstKeyForValue_(SHash
*self
, void *v
)
260 for (j
= 0; j
< 2; j
++)
261 for (i
= 0; i
< self
->tableSize
; i
++)
263 SHashRecord
*record
= SHASH_RECORDS_AT_(self
, j
, i
);
265 if (record
->key
&& record
->value
== v
)