|
|
|
@ -16,12 +16,6 @@ |
|
|
|
|
#define ARRAY_SIZE(x) \ |
|
|
|
|
((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) |
|
|
|
|
|
|
|
|
|
static void upb_check_alloc(upb_table *t, upb_alloc *a) { |
|
|
|
|
UPB_UNUSED(t); |
|
|
|
|
UPB_UNUSED(a); |
|
|
|
|
UPB_ASSERT_DEBUGVAR(t->alloc == a); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static const double MAX_LOAD = 0.85; |
|
|
|
|
|
|
|
|
|
/* The minimum utilization of the array part of a mixed hash/array table. This
|
|
|
|
@ -100,17 +94,12 @@ static bool isfull(upb_table *t) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2, |
|
|
|
|
upb_alloc *a) { |
|
|
|
|
static bool init(upb_table *t, uint8_t size_lg2, upb_alloc *a) { |
|
|
|
|
size_t bytes; |
|
|
|
|
|
|
|
|
|
t->count = 0; |
|
|
|
|
t->ctype = ctype; |
|
|
|
|
t->size_lg2 = size_lg2; |
|
|
|
|
t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0; |
|
|
|
|
#ifndef NDEBUG |
|
|
|
|
t->alloc = a; |
|
|
|
|
#endif |
|
|
|
|
bytes = upb_table_size(t) * sizeof(upb_tabent); |
|
|
|
|
if (bytes > 0) { |
|
|
|
|
t->entries = upb_malloc(a, bytes); |
|
|
|
@ -123,7 +112,6 @@ static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void uninit(upb_table *t, upb_alloc *a) { |
|
|
|
|
upb_check_alloc(t, a); |
|
|
|
|
upb_free(a, mutable_entries(t)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -159,7 +147,7 @@ static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v, |
|
|
|
|
const upb_tabent *e = findentry(t, key, hash, eql); |
|
|
|
|
if (e) { |
|
|
|
|
if (v) { |
|
|
|
|
_upb_value_setval(v, e->val.val, t->ctype); |
|
|
|
|
_upb_value_setval(v, e->val.val); |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
@ -175,7 +163,6 @@ static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey, |
|
|
|
|
upb_tabent *our_e; |
|
|
|
|
|
|
|
|
|
UPB_ASSERT(findentry(t, key, hash, eql) == NULL); |
|
|
|
|
UPB_ASSERT_DEBUGVAR(val.ctype == t->ctype); |
|
|
|
|
|
|
|
|
|
t->count++; |
|
|
|
|
mainpos_e = getentry_mutable(t, hash); |
|
|
|
@ -221,7 +208,7 @@ static bool rm(upb_table *t, lookupkey_t key, upb_value *val, |
|
|
|
|
if (eql(chain->key, key)) { |
|
|
|
|
/* Element to remove is at the head of its chain. */ |
|
|
|
|
t->count--; |
|
|
|
|
if (val) _upb_value_setval(val, chain->val.val, t->ctype); |
|
|
|
|
if (val) _upb_value_setval(val, chain->val.val); |
|
|
|
|
if (removed) *removed = chain->key; |
|
|
|
|
if (chain->next) { |
|
|
|
|
upb_tabent *move = (upb_tabent*)chain->next; |
|
|
|
@ -241,7 +228,7 @@ static bool rm(upb_table *t, lookupkey_t key, upb_value *val, |
|
|
|
|
/* Found element to remove. */ |
|
|
|
|
upb_tabent *rm = (upb_tabent*)chain->next; |
|
|
|
|
t->count--; |
|
|
|
|
if (val) _upb_value_setval(val, chain->next->val.val, t->ctype); |
|
|
|
|
if (val) _upb_value_setval(val, chain->next->val.val); |
|
|
|
|
if (removed) *removed = rm->key; |
|
|
|
|
rm->key = 0; /* Make the slot empty. */ |
|
|
|
|
chain->next = rm->next; |
|
|
|
@ -294,7 +281,7 @@ static bool streql(upb_tabkey k1, lookupkey_t k2) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, upb_alloc *a) { |
|
|
|
|
return init(&t->t, ctype, 2, a); |
|
|
|
|
return init(&t->t, 2, a); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) { |
|
|
|
@ -308,9 +295,7 @@ bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) { |
|
|
|
|
upb_strtable new_table; |
|
|
|
|
upb_strtable_iter i; |
|
|
|
|
|
|
|
|
|
upb_check_alloc(&t->t, a); |
|
|
|
|
|
|
|
|
|
if (!init(&new_table.t, t->t.ctype, size_lg2, a)) |
|
|
|
|
if (!init(&new_table.t, size_lg2, a)) |
|
|
|
|
return false; |
|
|
|
|
upb_strtable_begin(&i, t); |
|
|
|
|
for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) { |
|
|
|
@ -330,8 +315,6 @@ bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len, |
|
|
|
|
upb_tabkey tabkey; |
|
|
|
|
uint32_t hash; |
|
|
|
|
|
|
|
|
|
upb_check_alloc(&t->t, a); |
|
|
|
|
|
|
|
|
|
if (isfull(&t->t)) { |
|
|
|
|
/* Need to resize. New table of double the size, add old elements to it. */ |
|
|
|
|
if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) { |
|
|
|
@ -398,7 +381,7 @@ upb_strview upb_strtable_iter_key(const upb_strtable_iter *i) { |
|
|
|
|
|
|
|
|
|
upb_value upb_strtable_iter_value(const upb_strtable_iter *i) { |
|
|
|
|
UPB_ASSERT(!upb_strtable_done(i)); |
|
|
|
|
return _upb_value_val(str_tabent(i)->val.val, i->t->t.ctype); |
|
|
|
|
return _upb_value_val(str_tabent(i)->val.val); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void upb_strtable_iter_setdone(upb_strtable_iter *i) { |
|
|
|
@ -464,11 +447,11 @@ static void check(upb_inttable *t) { |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype, |
|
|
|
|
size_t asize, int hsize_lg2, upb_alloc *a) { |
|
|
|
|
bool upb_inttable_sizedinit(upb_inttable *t, size_t asize, int hsize_lg2, |
|
|
|
|
upb_alloc *a) { |
|
|
|
|
size_t array_bytes; |
|
|
|
|
|
|
|
|
|
if (!init(&t->t, ctype, hsize_lg2, a)) return false; |
|
|
|
|
if (!init(&t->t, hsize_lg2, a)) return false; |
|
|
|
|
/* Always make the array part at least 1 long, so that we know key 0
|
|
|
|
|
* won't be in the hash part, which simplifies things. */ |
|
|
|
|
t->array_size = UPB_MAX(1, asize); |
|
|
|
@ -485,7 +468,7 @@ bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) { |
|
|
|
|
return upb_inttable_sizedinit(t, ctype, 0, 4, a); |
|
|
|
|
return upb_inttable_sizedinit(t, 0, 4, a); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) { |
|
|
|
@ -499,8 +482,6 @@ bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, |
|
|
|
|
tabval.val = val.val; |
|
|
|
|
UPB_ASSERT(upb_arrhas(tabval)); /* This will reject (uint64_t)-1. Fix this. */ |
|
|
|
|
|
|
|
|
|
upb_check_alloc(&t->t, a); |
|
|
|
|
|
|
|
|
|
if (key < t->array_size) { |
|
|
|
|
UPB_ASSERT(!upb_arrhas(t->array[key])); |
|
|
|
|
t->array_count++; |
|
|
|
@ -511,7 +492,7 @@ bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, |
|
|
|
|
size_t i; |
|
|
|
|
upb_table new_table; |
|
|
|
|
|
|
|
|
|
if (!init(&new_table, t->t.ctype, t->t.size_lg2 + 1, a)) { |
|
|
|
|
if (!init(&new_table, t->t.size_lg2 + 1, a)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -520,7 +501,7 @@ bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, |
|
|
|
|
uint32_t hash; |
|
|
|
|
upb_value v; |
|
|
|
|
|
|
|
|
|
_upb_value_setval(&v, e->val.val, t->t.ctype); |
|
|
|
|
_upb_value_setval(&v, e->val.val); |
|
|
|
|
hash = upb_inthash(e->key); |
|
|
|
|
insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql); |
|
|
|
|
} |
|
|
|
@ -539,7 +520,7 @@ bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, |
|
|
|
|
bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) { |
|
|
|
|
const upb_tabval *table_v = inttable_val_const(t, key); |
|
|
|
|
if (!table_v) return false; |
|
|
|
|
if (v) _upb_value_setval(v, table_v->val, t->t.ctype); |
|
|
|
|
if (v) _upb_value_setval(v, table_v->val); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -557,7 +538,7 @@ bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) { |
|
|
|
|
upb_tabval empty = UPB_TABVALUE_EMPTY_INIT; |
|
|
|
|
t->array_count--; |
|
|
|
|
if (val) { |
|
|
|
|
_upb_value_setval(val, t->array[key].val, t->t.ctype); |
|
|
|
|
_upb_value_setval(val, t->array[key].val); |
|
|
|
|
} |
|
|
|
|
mutable_array(t)[key] = empty; |
|
|
|
|
success = true; |
|
|
|
@ -572,7 +553,6 @@ bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a) { |
|
|
|
|
upb_check_alloc(&t->t, a); |
|
|
|
|
return upb_inttable_insert2(t, upb_inttable_count(t), val, a); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -585,7 +565,6 @@ upb_value upb_inttable_pop(upb_inttable *t) { |
|
|
|
|
|
|
|
|
|
bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val, |
|
|
|
|
upb_alloc *a) { |
|
|
|
|
upb_check_alloc(&t->t, a); |
|
|
|
|
return upb_inttable_insert2(t, (uintptr_t)key, val, a); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -610,8 +589,6 @@ void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) { |
|
|
|
|
int size_lg2; |
|
|
|
|
upb_inttable new_t; |
|
|
|
|
|
|
|
|
|
upb_check_alloc(&t->t, a); |
|
|
|
|
|
|
|
|
|
upb_inttable_begin(&i, t); |
|
|
|
|
for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { |
|
|
|
|
uintptr_t key = upb_inttable_iter_key(&i); |
|
|
|
@ -644,7 +621,7 @@ void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) { |
|
|
|
|
size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0; |
|
|
|
|
int hashsize_lg2 = log2ceil(hash_size); |
|
|
|
|
|
|
|
|
|
upb_inttable_sizedinit(&new_t, t->t.ctype, arr_size, hashsize_lg2, a); |
|
|
|
|
upb_inttable_sizedinit(&new_t, arr_size, hashsize_lg2, a); |
|
|
|
|
upb_inttable_begin(&i, t); |
|
|
|
|
for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { |
|
|
|
|
uintptr_t k = upb_inttable_iter_key(&i); |
|
|
|
@ -710,8 +687,7 @@ uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) { |
|
|
|
|
upb_value upb_inttable_iter_value(const upb_inttable_iter *i) { |
|
|
|
|
UPB_ASSERT(!upb_inttable_done(i)); |
|
|
|
|
return _upb_value_val( |
|
|
|
|
i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val, |
|
|
|
|
i->t->t.ctype); |
|
|
|
|
i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void upb_inttable_iter_setdone(upb_inttable_iter *i) { |
|
|
|
|