Explorar o código

libobs: Use uthash for translation lookup

derrod %!s(int64=2) %!d(string=hai) anos
pai
achega
183fa8c06c
Modificáronse 2 ficheiros con 32 adicións e 170 borrados
  1. 30 168
      libobs/util/text-lookup.c
  2. 2 2
      libobs/util/text-lookup.h

+ 30 - 168
libobs/util/text-lookup.c

@@ -15,166 +15,34 @@
  */
 
 #include <ctype.h>
+
 #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)
-{
-	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)
+static inline void text_item_destroy(struct text_item *item)
 {
-	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;
-
-	if (!node)
-		return false;
+	struct text_item *item;
 
-	child = text_node_byname(node, lookup_val);
-	if (!child)
+	if (!lookup->items)
 		return false;
 
-	lookup_val += child->str.len;
-	ch = *lookup_val;
-	if (ch)
-		return lookup_getstring(lookup_val, out, child);
+	HASH_FIND_STR(lookup->items, lookup_val, item);
 
-	if (!child->leaf)
+	if (!item)
 		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;
 }

+ 2 - 2
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"