/* * Return value of first occurrence of symbol, or -1 if symbol is not * present */ int32_t stbl_find(stbl_t *sym_table, const char *symbol) { uint32_t mask, i, h; stbl_rec_t *r; mask = sym_table->size - 1; h = jenkins_hash_string(symbol); i = h & mask; for (r = sym_table->data[i]; r != NULL; r = r->next) { if (r->hash == h && strcmp(symbol, r->string) == 0) { return r->value; } } return -1; }
/* * Add new mapping for symbol. */ void stbl_add(stbl_t *sym_table, char *symbol, int32_t value) { uint32_t mask, i, h; stbl_rec_t *r; assert(value >= 0); mask = sym_table->size - 1; h = jenkins_hash_string(symbol); i = h & mask; r = stbl_alloc_record(sym_table); stbl_init_record(r, h, value, symbol); r->next = sym_table->data[i]; sym_table->data[i] = r; sym_table->nelems ++; }
/* * Find or create record with the given key * - set is_new to true if that's a new record * - set is_new to false otherwise */ strmap_rec_t *strmap_get(strmap_t *hmap, const char *key, bool *is_new) { uint32_t mask, i, h; strmap_rec_t *d, *aux; char *clone; assert(is_power_of_two(hmap->size) && hmap->nelems + hmap->ndeleted < hmap->size); mask = hmap->size - 1; h = jenkins_hash_string(key); i = h & mask; for (;;) { d = hmap->data + i; if (! valid_key(d->key)) break; if (d->hash == h && strcmp(d->key, key) == 0) goto found; i ++; i &= mask; } aux = d; // this is where the new record will go if needed while(d->key != NULL) { i ++; i &= mask; if (d->key != DELETED_KEY && d->hash == h && strcmp(d->key, key) == 0) goto found; } // not found: add a new record hmap->nelems ++; clone = clone_string(key); string_incref(clone); if (hmap->nelems + hmap->ndeleted > hmap->resize_threshold) { // resize: we can't use the current aux strmap_extend(hmap); aux = strmap_get_clean(hmap, h); } aux->key = clone; aux->hash = h; aux->val = 0; *is_new = true; return aux; found: *is_new = false; return d; }
/* * Return value of first occurrence of symbol, or -1 if symbol is not * present. * - update the cost */ int32_t stbl_find(stbl_t *sym_table, const char *symbol) { uint32_t mask, i, h, steps; int32_t result; stbl_rec_t *r; result = -1; steps = 0; mask = sym_table->size - 1; h = jenkins_hash_string(symbol); i = h & mask; for (r = sym_table->data[i]; r != NULL; r = r->next) { steps ++; if (r->hash == h && strcmp(symbol, r->string) == 0) { result = r->value; break; } } /* * Check whether the list contains many duplicates and move r to the * front if possible. If the list has duplicates, we reduce steps to 1, * since resizing won't help much. */ if (steps > STBL_MAXVISITS && list_has_duplicates(sym_table, i, r)) { steps = 1; } /* * Update cost and counter. Resize if the last NLOOKUPS have a * high total cost. */ assert(sym_table->lctr > 0); sym_table->cost += steps; sym_table->lctr --; if (sym_table->lctr == 0) { if (sym_table->cost > STBL_RESIZE_THRESHOLD && sym_table->size <= (MAX_STBL_SIZE/2)) { stbl_extend(sym_table); } sym_table->cost = 0; sym_table->lctr = STBL_NLOOKUPS; } return result; }
/* * Search for record with the given key * - return NULL if not found */ strmap_rec_t *strmap_find(strmap_t *hmap, const char *key) { uint32_t mask, i, h; strmap_rec_t *d; assert(is_power_of_two(hmap->size) && hmap->nelems + hmap->ndeleted < hmap->size); mask = hmap->size - 1; h = jenkins_hash_string(key); i = h & mask; for (;;) { d = hmap->data + i; if (d->key == NULL) return NULL; if (d->key != DELETED_KEY && d->hash == h && strcmp(d->key, key) == 0) { return d; } i ++; i &= mask; } }
/* * Remove the first occurrence of (symbol, value). * No effect if it's not present. */ void stbl_delete_mapping(stbl_t *sym_table, const char *symbol, int32_t val) { uint32_t h, mask, i; stbl_rec_t *r, *p; mask = sym_table->size - 1; h = jenkins_hash_string(symbol); i = h & mask; p = NULL; for (r = sym_table->data[i]; r != NULL; r = r->next) { if (r->hash == h && r->value == val && strcmp(symbol, r->string) == 0) { if (p == NULL) { sym_table->data[i] = r->next; } else { p->next = r->next; } sym_table->finalize(r); stbl_free_record(sym_table, r); return; } p = r; } }