tsm: unicode: add symbol-table helpers

Add three helpers to create and manage symbol-tables. Also fix internal
default-table to use them.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
David Herrmann 2012-09-18 12:03:17 +02:00
parent da51fe1589
commit 372948af53
2 changed files with 68 additions and 47 deletions

View File

@ -100,13 +100,14 @@ const tsm_symbol_t tsm_symbol_default = 0;
static const char default_u8[] = { 0 };
struct tsm_symbol_table {
unsigned long ref;
uint32_t next_id;
struct shl_array *index;
struct shl_hashtable *symbols;
};
/* TODO: remove the default context */
static struct tsm_symbol_table tsm_symbol_table_default;
static struct tsm_symbol_table *tsm_symbol_table_default;
static unsigned int hash_ucs4(const void *key)
{
@ -146,31 +147,60 @@ static bool cmp_ucs4(const void *a, const void *b)
}
}
static int table__init(struct tsm_symbol_table *tbl)
int tsm_symbol_table_new(struct tsm_symbol_table **out)
{
static const uint32_t *val = NULL; /* we need a valid lvalue */
struct tsm_symbol_table *tbl;
int ret;
static const uint32_t *val = NULL; /* we need a valid lvalue */
if (tbl->symbols)
return 0;
if (!out)
return -EINVAL;
tbl = malloc(sizeof(*tbl));
if (!tbl)
return -ENOMEM;
memset(tbl, 0, sizeof(*tbl));
tbl->ref = 1;
tbl->next_id = TSM_UCS4_MAX + 2;
ret = shl_array_new(&tbl->index, sizeof(uint32_t*), 4);
if (ret)
return ret;
goto err_free;
/* first entry is not used so add dummy */
shl_array_push(tbl->index, &val);
ret = shl_hashtable_new(&tbl->symbols, hash_ucs4, cmp_ucs4,
free, NULL);
if (ret) {
shl_array_free(tbl->index);
return -ENOMEM;
}
if (ret)
goto err_array;
*out = tbl;
return 0;
err_array:
shl_array_free(tbl->index);
err_free:
free(tbl);
return ret;
}
void tsm_symbol_table_ref(struct tsm_symbol_table *tbl)
{
if (!tbl || !tbl->ref)
return;
++tbl->ref;
}
void tsm_symbol_table_unref(struct tsm_symbol_table *tbl)
{
if (!tbl || !tbl->ref || --tbl->ref)
return;
shl_hashtable_free(tbl->symbols);
shl_array_free(tbl->index);
free(tbl);
}
tsm_symbol_t tsm_symbol_make(uint32_t ucs4)
@ -196,9 +226,7 @@ const uint32_t *tsm_symbol_get(struct tsm_symbol_table *tbl,
tsm_symbol_t *sym, size_t *size)
{
uint32_t *ucs4;
if (!tbl)
tbl = &tsm_symbol_table_default;
int ret;
if (*sym <= TSM_UCS4_MAX) {
if (size)
@ -206,10 +234,14 @@ const uint32_t *tsm_symbol_get(struct tsm_symbol_table *tbl,
return sym;
}
if (table__init(tbl)) {
if (size)
*size = 1;
return &tsm_symbol_default;
if (!tbl) {
ret = tsm_symbol_table_new(&tbl);
if (ret) {
if (size)
*size = 1;
return &tsm_symbol_default;
}
tsm_symbol_table_default = tbl;
}
ucs4 = *SHL_ARRAY_AT(tbl->index, uint32_t*,
@ -235,53 +267,41 @@ tsm_symbol_t tsm_symbol_append(struct tsm_symbol_table *tbl,
uint32_t buf[TSM_UCS4_MAXLEN + 1], nsym, *nval;
const uint32_t *ptr;
size_t s;
tsm_symbol_t rsym;
void *tmp;
bool res;
int ret;
if (!tbl)
tbl = &tsm_symbol_table_default;
if (table__init(tbl)) {
rsym = sym;
goto unlock;
if (!tbl) {
ret = tsm_symbol_table_new(&tbl);
if (ret)
return sym;
tsm_symbol_table_default = tbl;
}
if (ucs4 > TSM_UCS4_MAX) {
rsym = sym;
goto unlock;
}
if (ucs4 > TSM_UCS4_MAX)
return sym;
ptr = tsm_symbol_get(tbl, &sym, &s);
if (s >= TSM_UCS4_MAXLEN) {
rsym = sym;
goto unlock;
}
if (s >= TSM_UCS4_MAXLEN)
return sym;
memcpy(buf, ptr, s * sizeof(uint32_t));
buf[s++] = ucs4;
buf[s++] = TSM_UCS4_MAX + 1;
res = shl_hashtable_find(tbl->symbols, &tmp, buf);
if (res) {
rsym = (uint32_t)(long)tmp;
goto unlock;
}
if (res)
return (uint32_t)(long)tmp;
nval = malloc(sizeof(uint32_t) * s);
if (!nval) {
rsym = sym;
goto unlock;
}
if (!nval)
return sym;
memcpy(nval, buf, s * sizeof(uint32_t));
nsym = tbl->next_id++;
shl_hashtable_insert(tbl->symbols, nval, (void*)(long)nsym);
shl_array_push(tbl->index, &nval);
rsym = nsym;
unlock:
return rsym;
return nsym;
}
const char *tsm_symbol_get_u8(struct tsm_symbol_table *tbl,
@ -291,9 +311,6 @@ const char *tsm_symbol_get_u8(struct tsm_symbol_table *tbl,
char *val;
size_t i, pos, len;
if (!tbl)
tbl = &tsm_symbol_table_default;
ucs4 = tsm_symbol_get(tbl, &sym, &len);
val = malloc(4 * len);
if (!val)

View File

@ -50,6 +50,10 @@ typedef uint32_t tsm_symbol_t;
extern const tsm_symbol_t tsm_symbol_default;
int tsm_symbol_table_new(struct tsm_symbol_table **out);
void tsm_symbol_table_ref(struct tsm_symbol_table *tbl);
void tsm_symbol_table_unref(struct tsm_symbol_table *tbl);
tsm_symbol_t tsm_symbol_make(uint32_t ucs4);
tsm_symbol_t tsm_symbol_append(struct tsm_symbol_table *tbl,
tsm_symbol_t sym, uint32_t ucs4);