From 183fa8c06c9b269f1ea323cf33981e8fb75f252f Mon Sep 17 00:00:00 2001 From: derrod Date: Wed, 8 Feb 2023 12:07:11 +0100 Subject: [PATCH] libobs: Use uthash for translation lookup --- libobs/util/text-lookup.c | 200 ++++++-------------------------------- libobs/util/text-lookup.h | 4 +- 2 files changed, 33 insertions(+), 171 deletions(-) diff --git a/libobs/util/text-lookup.c b/libobs/util/text-lookup.c index 6fc144f78..7a74fb928 100644 --- a/libobs/util/text-lookup.c +++ b/libobs/util/text-lookup.c @@ -15,166 +15,34 @@ */ #include + #include "dstr.h" #include "text-lookup.h" #include "lexer.h" #include "platform.h" +#include "uthash.h" /* ------------------------------------------------------------------------- */ -struct text_leaf { +struct text_item { char *lookup, *value; + UT_hash_handle hh; }; -static inline void text_leaf_destroy(struct text_leaf *leaf) +static inline void text_item_destroy(struct text_item *item) { - if (leaf) { - bfree(leaf->lookup); - bfree(leaf->value); - bfree(leaf); - } -} - -/* ------------------------------------------------------------------------- */ - -struct text_node { - struct dstr str; - struct text_node *first_subnode; - struct text_leaf *leaf; - - struct text_node *next; -}; - -static void text_node_destroy(struct text_node *node) -{ - struct text_node *subnode; - - if (!node) - return; - - subnode = node->first_subnode; - while (subnode) { - struct text_node *destroy_node = subnode; - - subnode = subnode->next; - text_node_destroy(destroy_node); - } - - dstr_free(&node->str); - if (node->leaf) - text_leaf_destroy(node->leaf); - bfree(node); -} - -static struct text_node *text_node_bychar(struct text_node *node, char ch) -{ - struct text_node *subnode = node->first_subnode; - - while (subnode) { - if (!dstr_is_empty(&subnode->str) && - subnode->str.array[0] == ch) - return subnode; - - subnode = subnode->next; - } - - return NULL; -} - -static struct text_node *text_node_byname(struct text_node *node, - const char *name) -{ - struct text_node *subnode = node->first_subnode; - - while (subnode) { - if (astrcmpi_n(subnode->str.array, name, subnode->str.len) == 0) - return subnode; - - subnode = subnode->next; - } - - return NULL; + bfree(item->lookup); + bfree(item->value); + bfree(item); } /* ------------------------------------------------------------------------- */ struct text_lookup { struct dstr language; - struct text_node *top; + struct text_item *items; }; -static void lookup_createsubnode(const char *lookup_val, struct text_leaf *leaf, - struct text_node *node) -{ - struct text_node *new = bzalloc(sizeof(struct text_node)); - new->leaf = leaf; - new->next = node->first_subnode; - dstr_copy(&new->str, lookup_val); - - node->first_subnode = new; -} - -static void lookup_splitnode(const char *lookup_val, size_t len, - struct text_leaf *leaf, struct text_node *node) -{ - struct text_node *split = bzalloc(sizeof(struct text_node)); - - dstr_copy(&split->str, node->str.array + len); - split->leaf = node->leaf; - split->first_subnode = node->first_subnode; - node->first_subnode = split; - - dstr_resize(&node->str, len); - - if (lookup_val[len] != 0) { - node->leaf = NULL; - lookup_createsubnode(lookup_val + len, leaf, node); - } else { - node->leaf = leaf; - } -} - -static inline void lookup_replaceleaf(struct text_node *node, - struct text_leaf *leaf) -{ - text_leaf_destroy(node->leaf); - node->leaf = leaf; -} - -static void lookup_addstring(const char *lookup_val, struct text_leaf *leaf, - struct text_node *node) -{ - struct text_node *child; - - /* value already exists, so replace */ - if (!lookup_val || !*lookup_val) { - lookup_replaceleaf(node, leaf); - return; - } - - child = text_node_bychar(node, *lookup_val); - if (child) { - size_t len; - - for (len = 0; len < child->str.len; len++) { - char val1 = child->str.array[len], - val2 = lookup_val[len]; - - if (val1 != val2) - break; - } - - if (len == child->str.len) { - lookup_addstring(lookup_val + len, leaf, child); - return; - } else { - lookup_splitnode(lookup_val, len, leaf, child); - } - } else { - lookup_createsubnode(lookup_val, leaf, node); - } -} - static void lookup_getstringtoken(struct lexer *lex, struct strref *token) { const char *temp = lex->offset; @@ -300,7 +168,8 @@ static void lookup_addfiledata(struct text_lookup *lookup, strref_clear(&value); while (lookup_gettoken(&lex, &name)) { - struct text_leaf *leaf; + struct text_item *item; + struct text_item *old; bool got_eq = false; if (*name.array == '\n') @@ -315,14 +184,14 @@ static void lookup_addfiledata(struct text_lookup *lookup, goto getval; } - leaf = bmalloc(sizeof(struct text_leaf)); - leaf->lookup = bstrdup_n(name.array, name.len); - leaf->value = convert_string(value.array, value.len); + item = bzalloc(sizeof(struct text_item)); + item->lookup = bstrdup_n(name.array, name.len); + item->value = convert_string(value.array, value.len); - for (size_t i = 0; i < name.len; i++) - leaf->lookup[i] = toupper(leaf->lookup[i]); + HASH_REPLACE_STR(lookup->items, lookup, item, old); - lookup_addstring(leaf->lookup, leaf, lookup->top); + if (old) + text_item_destroy(old); if (!lookup_goto_nextline(&lex)) break; @@ -332,27 +201,19 @@ static void lookup_addfiledata(struct text_lookup *lookup, } static inline bool lookup_getstring(const char *lookup_val, const char **out, - struct text_node *node) + struct text_lookup *lookup) { - struct text_node *child; - char ch; + struct text_item *item; - if (!node) + if (!lookup->items) return false; - child = text_node_byname(node, lookup_val); - if (!child) + HASH_FIND_STR(lookup->items, lookup_val, item); + + if (!item) return false; - lookup_val += child->str.len; - ch = *lookup_val; - if (ch) - return lookup_getstring(lookup_val, out, child); - - if (!child->leaf) - return false; - - *out = child->leaf->value; + *out = item->value; return true; } @@ -387,9 +248,6 @@ bool text_lookup_add(lookup_t *lookup, const char *path) if (!file_str.array) return false; - if (!lookup->top) - lookup->top = bzalloc(sizeof(struct text_node)); - dstr_replace(&file_str, "\r", " "); lookup_addfiledata(lookup, file_str.array); dstr_free(&file_str); @@ -400,9 +258,13 @@ bool text_lookup_add(lookup_t *lookup, const char *path) void text_lookup_destroy(lookup_t *lookup) { if (lookup) { - dstr_free(&lookup->language); - text_node_destroy(lookup->top); + struct text_item *item, *tmp; + HASH_ITER (hh, lookup->items, item, tmp) { + HASH_DELETE(hh, lookup->items, item); + text_item_destroy(item); + } + dstr_free(&lookup->language); bfree(lookup); } } @@ -411,6 +273,6 @@ bool text_lookup_getstr(lookup_t *lookup, const char *lookup_val, const char **out) { if (lookup) - return lookup_getstring(lookup_val, out, lookup->top); + return lookup_getstring(lookup_val, out, lookup); return false; } diff --git a/libobs/util/text-lookup.h b/libobs/util/text-lookup.h index f01161867..4042f75c6 100644 --- a/libobs/util/text-lookup.h +++ b/libobs/util/text-lookup.h @@ -20,8 +20,8 @@ * Text Lookup interface * * Used for storing and looking up localized strings. Stores localization - * strings in a radix/trie tree to efficiently look up associated strings via a - * unique string identifier name. + * strings in a hashmap to efficiently look up associated strings via a + * unique string identifier name. */ #include "c99defs.h"