Expand or create the hash table, * when malloc_failed is non-NULL, it'll avoid panic if malloc fails (in which case it'll be set to 1). * Returns DICT_OK if expand was performed, and DICT_ERR if skipped. */
| 187 | * when malloc_failed is non-NULL, it'll avoid panic if malloc fails (in which case it'll be set to 1). |
| 188 | * Returns DICT_OK if expand was performed, and DICT_ERR if skipped. */ |
| 189 | int _HashTableExpand |
| 190 | ( |
| 191 | dict *d, |
| 192 | unsigned long size, |
| 193 | int* malloc_failed |
| 194 | ) { |
| 195 | //printf("_HashTableExpand size: %lu\n", size); |
| 196 | if (malloc_failed) *malloc_failed = 0; |
| 197 | |
| 198 | /* the size is invalid if it is smaller than the number of |
| 199 | * elements already inside the hash table */ |
| 200 | if (dictIsRehashing(d) || d->ht_used[0] > size) |
| 201 | return DICT_ERR; |
| 202 | |
| 203 | /* the new hash table */ |
| 204 | dictEntry **new_ht_table; |
| 205 | unsigned long new_ht_used; |
| 206 | signed char new_ht_size_exp = _dictNextExp(size); |
| 207 | |
| 208 | /* Detect overflows */ |
| 209 | size_t newsize = 1ul<<new_ht_size_exp; |
| 210 | //printf("_HashTableExpand newsize: %zu\n", newsize); |
| 211 | if (newsize < size || newsize * sizeof(dictEntry*) < newsize) |
| 212 | return DICT_ERR; |
| 213 | |
| 214 | /* Rehashing to the same table size is not useful. */ |
| 215 | if (new_ht_size_exp == d->ht_size_exp[0]) return DICT_ERR; |
| 216 | |
| 217 | /* Allocate the new hash table and initialize all pointers to NULL */ |
| 218 | if (malloc_failed) { |
| 219 | new_ht_table = calloc(1, newsize*sizeof(dictEntry*)); |
| 220 | *malloc_failed = new_ht_table == NULL; |
| 221 | if (*malloc_failed) |
| 222 | return DICT_ERR; |
| 223 | } else |
| 224 | new_ht_table = calloc(1, newsize*sizeof(dictEntry*)); |
| 225 | |
| 226 | new_ht_used = 0; |
| 227 | |
| 228 | /* Is this the first initialization? If so it's not really a rehashing |
| 229 | * we just set the first hash table so that it can accept keys. */ |
| 230 | if (d->ht_table[0] == NULL) { |
| 231 | d->ht_size_exp[0] = new_ht_size_exp; |
| 232 | d->ht_used[0] = new_ht_used; |
| 233 | d->ht_table[0] = new_ht_table; |
| 234 | return DICT_OK; |
| 235 | } |
| 236 | |
| 237 | /* Prepare a second hash table for incremental rehashing */ |
| 238 | d->ht_size_exp[1] = new_ht_size_exp; |
| 239 | d->ht_used[1] = new_ht_used; |
| 240 | d->ht_table[1] = new_ht_table; |
| 241 | d->rehashidx = 0; |
| 242 | return DICT_OK; |
| 243 | } |
| 244 | |
| 245 | /* return DICT_ERR if expand was not performed */ |
| 246 | int HashTableExpand |
no test coverage detected