|
|
|
@ -41,7 +41,6 @@ |
|
|
|
|
|
|
|
|
|
struct grpc_mdstr_hash_table { |
|
|
|
|
gpr_refcount refs; |
|
|
|
|
size_t num_entries; |
|
|
|
|
size_t size; |
|
|
|
|
grpc_mdstr_hash_table_entry* entries; |
|
|
|
|
}; |
|
|
|
@ -77,7 +76,6 @@ grpc_mdstr_hash_table* grpc_mdstr_hash_table_create( |
|
|
|
|
grpc_mdstr_hash_table* table = gpr_malloc(sizeof(*table)); |
|
|
|
|
memset(table, 0, sizeof(*table)); |
|
|
|
|
gpr_ref_init(&table->refs, 1); |
|
|
|
|
table->num_entries = num_entries; |
|
|
|
|
// Quadratic probing gets best performance when the table is no more
|
|
|
|
|
// than half full.
|
|
|
|
|
table->size = num_entries * 2; |
|
|
|
@ -96,7 +94,7 @@ grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table) { |
|
|
|
|
return table; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int grpc_mdstr_hash_table_unref(grpc_mdstr_hash_table* table) { |
|
|
|
|
void grpc_mdstr_hash_table_unref(grpc_mdstr_hash_table* table) { |
|
|
|
|
if (table != NULL && gpr_unref(&table->refs)) { |
|
|
|
|
for (size_t i = 0; i < table->size; ++i) { |
|
|
|
|
grpc_mdstr_hash_table_entry* entry = &table->entries[i]; |
|
|
|
@ -107,13 +105,7 @@ int grpc_mdstr_hash_table_unref(grpc_mdstr_hash_table* table) { |
|
|
|
|
} |
|
|
|
|
gpr_free(table->entries); |
|
|
|
|
gpr_free(table); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size_t grpc_mdstr_hash_table_num_entries(const grpc_mdstr_hash_table* table) { |
|
|
|
|
return table->num_entries; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table, |
|
|
|
@ -123,35 +115,3 @@ void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table, |
|
|
|
|
if (idx == table->size) return NULL; // Not found.
|
|
|
|
|
return table->entries[idx].value; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int grpc_mdstr_hash_table_cmp(const grpc_mdstr_hash_table* table1, |
|
|
|
|
const grpc_mdstr_hash_table* table2) { |
|
|
|
|
// Compare by num_entries.
|
|
|
|
|
if (table1->num_entries < table2->num_entries) return -1; |
|
|
|
|
if (table1->num_entries > table2->num_entries) return 1; |
|
|
|
|
for (size_t i = 0; i < table1->num_entries; ++i) { |
|
|
|
|
grpc_mdstr_hash_table_entry* e1 = &table1->entries[i]; |
|
|
|
|
grpc_mdstr_hash_table_entry* e2 = &table2->entries[i]; |
|
|
|
|
// Compare keys by hash value.
|
|
|
|
|
if (e1->key->hash < e2->key->hash) return -1; |
|
|
|
|
if (e1->key->hash > e2->key->hash) return 1; |
|
|
|
|
// Compare by vtable (pointer equality).
|
|
|
|
|
if (e1->vtable < e2->vtable) return -1; |
|
|
|
|
if (e1->vtable > e2->vtable) return 1; |
|
|
|
|
// Compare values via vtable.
|
|
|
|
|
const int value_result = e1->vtable->compare_value(e1->value, e2->value); |
|
|
|
|
if (value_result != 0) return value_result; |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_mdstr_hash_table_iterate( |
|
|
|
|
const grpc_mdstr_hash_table* table, |
|
|
|
|
void (*func)(const grpc_mdstr_hash_table_entry* entry, void* user_data), |
|
|
|
|
void* user_data) { |
|
|
|
|
for (size_t i = 0; i < table->size; ++i) { |
|
|
|
|
if (table->entries[i].key != NULL) { |
|
|
|
|
func(&table->entries[i], user_data); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|