add string_table to manage container STAB data
This commit is contained in:
110
src/string-table.c
Normal file
110
src/string-table.c
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#include "string-table.h"
|
||||||
|
|
||||||
|
#include <blue/core/hash.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
17
src/string-table.h
Normal file
17
src/string-table.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef STRING_TABLE_H_
|
||||||
|
#define STRING_TABLE_H_
|
||||||
|
|
||||||
|
#include <blue/core/btree.h>
|
||||||
|
|
||||||
|
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
|
||||||
Reference in New Issue
Block a user