summaryrefslogtreecommitdiff
path: root/src/tsm_unicode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tsm_unicode.c')
-rw-r--r--src/tsm_unicode.c50
1 files changed, 30 insertions, 20 deletions
diff --git a/src/tsm_unicode.c b/src/tsm_unicode.c
index eb061a2..874915c 100644
--- a/src/tsm_unicode.c
+++ b/src/tsm_unicode.c
@@ -61,7 +61,7 @@
#include "libtsm.h"
#include "libtsm_int.h"
#include "shl_array.h"
-#include "shl_hashtable.h"
+#include "shl_htable.h"
/*
* Unicode Symbol Handling
@@ -103,13 +103,12 @@ struct tsm_symbol_table {
unsigned long ref;
uint32_t next_id;
struct shl_array *index;
- struct shl_hashtable *symbols;
+ struct shl_htable symbols;
};
-static unsigned int hash_ucs4(const void *key)
+static size_t hash_ucs4(const void *key, void *priv)
{
- unsigned int val = 5381;
- size_t i;
+ size_t i, val = 5381;
const uint32_t *ucs4 = key;
for (i = 0; ucs4[i] <= TSM_UCS4_MAX; ++i)
@@ -134,6 +133,14 @@ static bool cmp_ucs4(const void *a, const void *b)
}
}
+static void free_ucs4(void *elem, void *priv)
+{
+ uint32_t *v = elem;
+
+ /* key is prefix with actual value so pass correct pointer */
+ free(--v);
+}
+
int tsm_symbol_table_new(struct tsm_symbol_table **out)
{
struct tsm_symbol_table *tbl;
@@ -149,6 +156,7 @@ int tsm_symbol_table_new(struct tsm_symbol_table **out)
memset(tbl, 0, sizeof(*tbl));
tbl->ref = 1;
tbl->next_id = TSM_UCS4_MAX + 2;
+ shl_htable_init(&tbl->symbols, cmp_ucs4, hash_ucs4, NULL);
ret = shl_array_new(&tbl->index, sizeof(uint32_t*), 4);
if (ret)
@@ -157,16 +165,9 @@ int tsm_symbol_table_new(struct tsm_symbol_table **out)
/* 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)
- goto err_array;
-
*out = tbl;
return 0;
-err_array:
- shl_array_free(tbl->index);
err_free:
free(tbl);
return ret;
@@ -185,7 +186,7 @@ void tsm_symbol_table_unref(struct tsm_symbol_table *tbl)
if (!tbl || !tbl->ref || --tbl->ref)
return;
- shl_hashtable_free(tbl->symbols);
+ shl_htable_clear(&tbl->symbols, free_ucs4, NULL);
shl_array_free(tbl->index);
free(tbl);
}
@@ -250,7 +251,6 @@ 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;
- void *tmp;
bool res;
int ret;
@@ -268,22 +268,32 @@ tsm_symbol_t tsm_symbol_append(struct tsm_symbol_table *tbl,
buf[s++] = ucs4;
buf[s++] = TSM_UCS4_MAX + 1;
- res = shl_hashtable_find(tbl->symbols, &tmp, buf);
- if (res)
- return (uint32_t)(long)tmp;
+ res = shl_htable_lookup(&tbl->symbols, buf, hash_ucs4(buf, NULL),
+ (void**)&nval);
+ if (res) {
+ /* key is prefixed with actual value */
+ return *--nval;
+ }
- nval = malloc(sizeof(uint32_t) * s);
+ /* We save the key in nval and prefix it with the new ID. Note that
+ * the prefix is hidden, we actually store "++nval" in the htable. */
+ nval = malloc(sizeof(uint32_t) * (s + 1));
if (!nval)
return sym;
+ ++nval;
memcpy(nval, buf, s * sizeof(uint32_t));
+
nsym = tbl->next_id + 1;
/* Out of IDs; we actually have 2 Billion IDs so this seems
* very unlikely but lets be safe here */
if (nsym <= tbl->next_id++)
goto err_id;
- ret = shl_hashtable_insert(tbl->symbols, nval, (void*)(long)nsym);
+ /* store ID hidden before the key */
+ *(nval - 1) = nsym;
+
+ ret = shl_htable_insert(&tbl->symbols, nval, hash_ucs4(nval, NULL));
if (ret)
goto err_id;
@@ -294,7 +304,7 @@ tsm_symbol_t tsm_symbol_append(struct tsm_symbol_table *tbl,
return nsym;
err_symbol:
- shl_hashtable_remove(tbl->symbols, nval);
+ shl_htable_remove(&tbl->symbols, nval, hash_ucs4(nval, NULL), NULL);
err_id:
--tbl->next_id;
free(nval);