2 //metadoc SHash copyright Steve Dekorte 2002, Marc Fauconneau 2007
3 //metadoc SHash license BSD revised
12 void SHash_print(SHash
* self
)
14 printf("self->log2tableSize = %d\n", self
->log2tableSize
);
15 printf("self->tableSize = %d\n", self
->tableSize
);
16 printf("self->numKeys = %d\n", self
->numKeys
);
18 printf("self->mask = %d\n", self
->mask
);
19 printf("self->balance = %d\n", self
->balance
);
20 printf("self->maxLoops = %d\n", SHash_maxLoops(self
));
21 printf("self->maxKeys = %d\n", SHash_maxKeys(self
));
23 printf("self->nullRecord.key = %d\n", self
->nullRecord
.key
);
24 printf("self->nullRecord.value = %d\n", self
->nullRecord
.value
);
26 printf("\nmemory usage : %d bytes\n", SHash_memorySize(self
));
27 printf("\ndensity : %f \n", (self
->numKeys
*sizeof(SHashRecord
))/(double)SHash_memorySize(self
));
33 for (j
= 0; j
< 2; j
++)
35 for (i
= 0; i
< self
->tableSize
; i
++)
37 SHashRecord
*record
= SHASH_RECORDS_AT_(self
, j
, i
);
38 if (NULL
== record
->key
)
40 if (NULL
== record
->value
)
53 printf("balance : %d / %d [%1.3f]\n", count
[0], count
[1], (count
[0]-count
[1])/(double)(count
[0]+count
[1]) );
57 void SHash_tableInit_(SHash
* self
, int log2tableSize
)
59 if (log2tableSize
> 20)
61 self
->log2tableSize
= log2tableSize
;
62 self
->tableSize
= 1<<self
->log2tableSize
;
63 self
->records
= (SHashRecord
*)io_calloc(1, sizeof(SHashRecord
) * self
->tableSize
* 2);
64 self
->mask
= self
->tableSize
-1;
67 SHash
*SHash_new(void)
69 SHash
*self
= (SHash
*)io_calloc(1, sizeof(SHash
));
71 SHash_tableInit_(self
, 1);
76 SHash
*SHash_clone(SHash
*self
)
78 SHash
*child
= SHash_new();
79 SHash_copy_(child
, self
);
83 void SHash_free(SHash
*self
)
85 io_free(self
->records
);
89 size_t SHash_memorySize(SHash
*self
)
91 return sizeof(SHash
) + (self
->tableSize
* 2 * sizeof(SHashRecord
));
94 void SHash_compact(SHash
*self
)
96 printf("need to implement SHash_compact\n");
99 void SHash_copy_(SHash
*self
, SHash
*other
)
101 SHashRecord
*records
= self
->records
;
102 memcpy(self
, other
, sizeof(SHash
));
103 self
->records
= (SHashRecord
*)io_realloc(records
, sizeof(SHashRecord
) * self
->tableSize
* 2);
104 memcpy(self
->records
, other
->records
, sizeof(SHashRecord
) * self
->tableSize
* 2);
107 /* this is where our cuckoo acts :
108 it kicks records out of nests until it finds an empty nest or gets tired
109 returns the empty nest if found, or NULL if it is too tired
111 SHashRecord
*SHash_cuckoo_(SHash
*self
, SHashRecord
* thisRecord
)
115 record
= SHash_recordAt_(self
, thisRecord
->key
);
117 if (record
!= &self
->nullRecord
&& NULL
== record
->key
)
121 if (SHash_keysAreEqual_(self
, thisRecord
->key
, record
->key
))
133 hash
= SHash_hash_more(self
, SHash_hash(self
, thisRecord
->key
));
134 record
= SHASH_RECORDS_AT_HASH_(self
, 1, hash
);
135 if (NULL
== record
->key
)
138 SHashRecord_swap(record
, thisRecord
);
140 if (SHash_keysAreEqual_(self
, thisRecord
->key
, record
->key
))
145 for (i
= 0; i
< SHash_maxLoops(self
); i
++)
147 hash
= SHash_hash(self
, thisRecord
->key
);
148 record
= SHASH_RECORDS_AT_HASH_(self
, 0, hash
);
149 if (NULL
== record
->key
)
152 SHashRecord_swap(record
, thisRecord
);
154 if (SHash_keysAreEqual_(self
, thisRecord
->key
, record
->key
))
157 hash
= SHash_hash_more(self
, SHash_hash(self
, thisRecord
->key
));
158 record
= SHASH_RECORDS_AT_HASH_(self
, 1, hash
);
159 if (NULL
== record
->key
)
162 SHashRecord_swap(record
, thisRecord
);
164 if (SHash_keysAreEqual_(self
, thisRecord
->key
, record
->key
))
168 // the cuckoo is tired ^^
176 void SHash_grow(SHash
*self
)
178 unsigned int oldTableSize
= self
->tableSize
;
179 SHashRecord
* oldRecords
= self
->records
;
181 self
->records
= NULL
;
182 while (self
->records
== NULL
)
186 SHash_tableInit_(self
, self
->log2tableSize
+ 1);
188 // enumerate old records
191 while (i
< oldTableSize
*2)
193 SHashRecord thisRecord
= oldRecords
[i
];
198 SHashRecord
*record
= SHash_cuckoo_(self
, &thisRecord
);
199 if (!record
) // collision
201 io_free(self
->records
);
202 self
->records
= NULL
;
203 break; // grow & rehash
205 *record
= thisRecord
;
212 void SHash_growWithRecord(SHash
*self
, SHashRecord
* thisRecord
)
214 // put the value anywhere, SHash_grow will rehash
217 for (j
= 0; j
< 2; j
++)
218 for (i
= 0; i
< self
->tableSize
; i
++)
220 SHashRecord
*record
= SHASH_RECORDS_AT_(self
, j
, i
);
222 if (record
!= &self
->nullRecord
&& NULL
== record
->key
)
224 *record
= *thisRecord
;
231 // we can never be there
235 void SHash_removeValue_(SHash
*self
, void *value
)
240 while (index
< self
->tableSize
*2)
242 record
= self
->records
+ index
;
245 if (record
->key
&& record
->value
== value
)
248 memset(record
, 0, sizeof(SHashRecord
));
254 void *SHash_firstKeyForValue_(SHash
*self
, void *v
)
258 for (j
= 0; j
< 2; j
++)
259 for (i
= 0; i
< self
->tableSize
; i
++)
261 SHashRecord
*record
= SHASH_RECORDS_AT_(self
, j
, i
);
263 if (record
->key
&& record
->value
== v
)