From e61e7afaff8ff0aa72cbb5335837739ab14c2e6d Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 16 Feb 2025 08:42:02 +0000 Subject: [PATCH] add string_table to manage container STAB data --- src/string-table.c | 110 +++++++++++++++++++++++++++++++++++++++++++++ src/string-table.h | 17 +++++++ 2 files changed, 127 insertions(+) create mode 100644 src/string-table.c create mode 100644 src/string-table.h diff --git a/src/string-table.c b/src/string-table.c new file mode 100644 index 0000000..103fa54 --- /dev/null +++ b/src/string-table.c @@ -0,0 +1,110 @@ +#include "string-table.h" + +#include +#include +#include + +struct string_table_entry { + b_btree_node e_hash_node; + b_btree_node e_offset_node; + size_t e_hash; + size_t e_offset; + char e_str[]; +}; + +B_BTREE_DEFINE_SIMPLE_INSERT( + struct string_table_entry, + e_hash_node, + e_hash, + put_string_by_hash) + +B_BTREE_DEFINE_SIMPLE_INSERT( + struct string_table_entry, + e_offset_node, + e_offset, + put_string_by_offset) + +struct string_table_entry *get_string(const b_btree *hash_tree, const char *s) +{ + size_t key = b_hash_string(s); + + b_btree_node *cur = hash_tree->b_root; + while (cur) { + struct string_table_entry *cur_node + = b_unbox(struct string_table_entry, cur, e_hash_node); + + if (key == cur_node->e_hash && !strcmp(s, cur_node->e_str)) { + return cur_node; + } + + if (key >= cur_node->e_hash) { + cur = b_btree_right(cur); + } else { + cur = b_btree_left(cur); + } + } + + return NULL; +} + +static struct string_table_entry *create_entry(const char *s) +{ + struct string_table_entry *out = NULL; + + size_t s_len = strlen(s); + size_t entry_len = s_len + 1 + sizeof *out; + + out = malloc(entry_len); + + if (!out) { + return NULL; + } + + memset(out, 0x0, entry_len); + memcpy(out->e_str, s, s_len); + + out->e_hash = b_hash_string(s); + + return out; +} + +void string_table_init(struct string_table *out) +{ + memset(out, 0x0, sizeof *out); +} + +void string_table_finish(struct string_table *tab) +{ + b_btree_iterator it; + b_btree_iterator_begin(&tab->s_hash_tree, &it); + + while (b_btree_iterator_is_valid(&it)) { + struct string_table_entry *entry = b_unbox( + struct string_table_entry, + it.node, + e_hash_node); + b_btree_iterator_erase(&it); + free(entry); + } + + free(tab); +} + +size_t string_table_get(struct string_table *tab, const char *s) +{ + struct string_table_entry *entry = get_string(&tab->s_hash_tree, s); + if (entry) { + return entry->e_offset; + } + + entry = create_entry(s); + + entry->e_offset = tab->s_next_offset; + + tab->s_next_offset += strlen(s) + 1; + + put_string_by_hash(&tab->s_hash_tree, entry); + put_string_by_offset(&tab->s_offset_tree, entry); + + return entry->e_offset; +} diff --git a/src/string-table.h b/src/string-table.h new file mode 100644 index 0000000..1d5a0ad --- /dev/null +++ b/src/string-table.h @@ -0,0 +1,17 @@ +#ifndef STRING_TABLE_H_ +#define STRING_TABLE_H_ + +#include + +struct string_table { + b_btree s_hash_tree; + b_btree s_offset_tree; + size_t s_next_offset; +}; + +extern void string_table_init(struct string_table *out); +extern void string_table_finish(struct string_table *tab); + +extern size_t string_table_get(struct string_table *tab, const char *s); + +#endif