/* * 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; }
/* * 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 ++; if (sym_table->nelems > sym_table->size) { stbl_extend(sym_table); } }