* do red-black tree search for language code lookups

This commit is contained in:
gokl 2013-10-24 16:29:57 +02:00
parent 6c9bff1179
commit 486f576c83
2 changed files with 68 additions and 7 deletions

View file

@ -495,14 +495,60 @@ const lang_code_t lang_codes[] = {
{ NULL, NULL, NULL, NULL }
};
lang_code_lookup_t* lang_codes_code2b = NULL;
lang_code_lookup_t* lang_codes_code1 = NULL;
lang_code_lookup_t* lang_codes_code2t = NULL;
/* **************************************************************************
* Functions
* *************************************************************************/
/* Compare language codes */
static int _lang_code2b_cmp ( void *a, void *b )
{
return strcmp(((lang_code_lookup_element_t*)a)->lang_code->code2b,
((lang_code_lookup_element_t*)b)->lang_code->code2b);
}
static int _lang_code1_cmp ( void *a, void *b )
{
return strcmp(((lang_code_lookup_element_t*)a)->lang_code->code1,
((lang_code_lookup_element_t*)b)->lang_code->code1);
}
static int _lang_code2t_cmp ( void *a, void *b )
{
return strcmp(((lang_code_lookup_element_t*)a)->lang_code->code2t,
((lang_code_lookup_element_t*)b)->lang_code->code2t);
}
static int _lang_code_lookup_add( lang_code_lookup_t* lookup_table, const lang_code_t *code, int (*func)(void*, void*) ) {
lang_code_lookup_element_t *element;
element = (lang_code_lookup_element_t *)calloc(1, sizeof(lang_code_lookup_element_t));
element->lang_code = code;
RB_INSERT_SORTED(lookup_table, element, link, func);
return 0;
}
static const lang_code_t *_lang_code_get ( const char *code, size_t len )
{
int i;
char tmp[4];
if (lang_codes_code2b == NULL) {
const lang_code_t *c = lang_codes;
lang_codes_code2b = (lang_code_lookup_t *)calloc(1, sizeof(lang_code_lookup_t));
lang_codes_code1 = (lang_code_lookup_t *)calloc(1, sizeof(lang_code_lookup_t));
lang_codes_code2t = (lang_code_lookup_t *)calloc(1, sizeof(lang_code_lookup_t));
while (c->code2b) {
_lang_code_lookup_add(lang_codes_code2b, c, _lang_code2b_cmp);
if (c->code1) _lang_code_lookup_add(lang_codes_code1, c, _lang_code1_cmp);
if (c->code2t) _lang_code_lookup_add(lang_codes_code2t, c, _lang_code2t_cmp);
c++;
}
}
if (code && *code && len) {
@ -527,13 +573,18 @@ static const lang_code_t *_lang_code_get ( const char *code, size_t len )
/* Search */
if (i) {
const lang_code_t *c = lang_codes;
while (c->code2b) {
if ( !strcmp(tmp, c->code2b) ) return c;
if ( c->code1 && !strcmp(tmp, c->code1) ) return c;
if ( c->code2t && !strcmp(tmp, c->code2t) ) return c;
c++;
}
lang_code_lookup_element_t sample, *element;
lang_code_t lang_code;
lang_code.code1 = tmp;
lang_code.code2b = tmp;
lang_code.code2t = tmp;
sample.lang_code = &lang_code;
element = RB_FIND(lang_codes_code2b, &sample, link, _lang_code2b_cmp);
if (element != NULL) return element->lang_code;
element = RB_FIND(lang_codes_code1, &sample, link, _lang_code1_cmp);
if (element != NULL) return element->lang_code;
element = RB_FIND(lang_codes_code2t, &sample, link, _lang_code2t_cmp);
if (element != NULL) return element->lang_code;
}
}
return &lang_codes[0];

View file

@ -19,6 +19,8 @@
#ifndef __TVH_LANG_CODES_H__
#define __TVH_LANG_CODES_H__
#include "redblack.h"
typedef struct lang_code
{
const char *code2b; ///< ISO 639-2 B
@ -38,4 +40,12 @@ const lang_code_t *lang_code_get3 ( const char *code );
const char **lang_code_split ( const char *codes );
const lang_code_t **lang_code_split2 ( const char *codes );
/* Efficient code lookup */
typedef struct lang_code_lookup_element {
RB_ENTRY(lang_code_lookup_element) link;
const lang_code_t *lang_code;
} lang_code_lookup_element_t;
typedef RB_HEAD(lang_code_lookup, lang_code_lookup_element) lang_code_lookup_t;
#endif /* __TVH_LANG_CODES_H__ */