From: Jaroslav Kysela Date: Thu, 1 Feb 2018 15:39:50 +0000 (+0100) Subject: lang codes: reimplement lang_code_split - the code is much faster now X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7d3742dbcf96c50a24939a87937f30a3c436ae1e;p=thirdparty%2Ftvheadend.git lang codes: reimplement lang_code_split - the code is much faster now --- diff --git a/src/lang_codes.c b/src/lang_codes.c index e9e580a47..f51666e71 100644 --- a/src/lang_codes.c +++ b/src/lang_codes.c @@ -500,6 +500,9 @@ lang_code_lookup_t* lang_codes_code2b = NULL; lang_code_lookup_t* lang_codes_code1 = NULL; lang_code_lookup_t* lang_codes_code2t = NULL; +pthread_mutex_t lang_code_split_mutex = PTHREAD_MUTEX_INITIALIZER; +RB_HEAD(,lang_code_list) lang_code_split_tree = { NULL, NULL, NULL, 0 }; + /* ************************************************************************** * Functions * *************************************************************************/ @@ -508,22 +511,25 @@ lang_code_lookup_t* lang_codes_code2t = NULL; 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); + ((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); + ((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); + ((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*) ) { +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; @@ -606,35 +612,18 @@ const lang_code_t *lang_code_get3 ( const char *code ) return _lang_code_get(code, strlen(code ?: "")); } -const char **lang_code_split ( const char *codes ) +static int _split_cmp(const void *_a, const void *_b) { - int i = 0; - const lang_code_t **lcs = lang_code_split2(codes); - const char **ret; - - if(!lcs) return NULL; - - while(lcs[i]) - i++; - - ret = calloc(1+i, sizeof(char*)); - - i = 0; - while(lcs[i]) { - ret[i] = lcs[i]->code2b; - i++; - } - ret[i] = NULL; - free(lcs); - - return ret; + const lang_code_list_t *a = _a; + const lang_code_list_t *b = _b; + return strcmp(a->langs, b->langs); } -const lang_code_t **lang_code_split2 ( const char *codes ) +const lang_code_list_t *lang_code_split ( const char *codes ) { int n; const char *c, *p; - const lang_code_t **ret; + lang_code_list_t *ret, skel; const lang_code_t *co; /* Defaults */ @@ -643,30 +632,38 @@ const lang_code_t **lang_code_split2 ( const char *codes ) /* No config */ if (!codes) return NULL; - /* Count entries */ - n = 0; - c = codes; - while (*c) { - if (*c == ',') n++; - c++; - } - ret = calloc(2+n, sizeof(lang_code_t*)); - - /* Create list */ - n = 0; - p = c = codes; - while (*c) { - if (*c == ',') { + pthread_mutex_lock(&lang_code_split_mutex); + + skel.langs = (char *)codes; + ret = RB_FIND(&lang_code_split_tree, &skel, link, _split_cmp); + if (ret) + goto unlock; + + for (n = 1, p = codes; *p; p++) + if (*p == ',') n++; + + ret = calloc(1, sizeof(lang_code_list_t) + n * sizeof(lang_code_t *)); + if (ret) { + /* Create list */ + for (n = 0, p = c = codes; *c; c++) + if (*c == ',') { + co = lang_code_get3(p); + if(co) + ret->codes[n++] = co; + p = c + 1; + } + if (*p) { co = lang_code_get3(p); - if(co) - ret[n++] = co; - p = c + 1; + if (co) + ret->codes[n++] = co; } - c++; + ret->codeslen = n; + ret->langs = strdup(codes); + RB_INSERT_SORTED(&lang_code_split_tree, ret, link, _split_cmp); } - if (*p) ret[n++] = lang_code_get3(p); - ret[n] = NULL; +unlock: + pthread_mutex_unlock(&lang_code_split_mutex); return ret; } @@ -724,6 +721,14 @@ char *lang_code_user( const char *ucode ) void lang_code_done( void ) { + lang_code_list_t *lcs; + pthread_mutex_lock(&lang_code_split_mutex); + while ((lcs = RB_FIRST(&lang_code_split_tree)) != NULL) { + RB_REMOVE(&lang_code_split_tree, lcs, link); + free((char *)lcs->langs); + free(lcs); + } + pthread_mutex_unlock(&lang_code_split_mutex); lang_code_free(lang_codes_code2b); lang_code_free(lang_codes_code1); lang_code_free(lang_codes_code2t); diff --git a/src/lang_codes.h b/src/lang_codes.h index 89d5457b0..2fcc5f158 100644 --- a/src/lang_codes.h +++ b/src/lang_codes.h @@ -32,6 +32,14 @@ typedef struct lang_code extern const lang_code_t lang_codes[]; +typedef struct lang_code_list +{ + RB_ENTRY(lang_code_list) link; + const char *langs; + int codeslen; + const lang_code_t *codes[0]; +} lang_code_list_t; + /* Convert code to preferred internal code */ const char *lang_code_get ( const char *code ); const char *lang_code_get2 ( const char *code, size_t len ); @@ -41,8 +49,7 @@ const char *lang_code_preferred( void ); char *lang_code_user( const char *ucode ); /* Split list of codes as per HTTP Language-Accept spec */ -const char **lang_code_split ( const char *codes ); -const lang_code_t **lang_code_split2 ( const char *codes ); +const lang_code_list_t *lang_code_split ( const char *codes ); /* Efficient code lookup */ typedef struct lang_code_lookup_element { diff --git a/src/lang_str.c b/src/lang_str.c index 8d74d23d3..f423432fd 100644 --- a/src/lang_str.c +++ b/src/lang_str.c @@ -85,21 +85,18 @@ lang_str_ele_t *lang_str_get2 ( const lang_str_t *ls, const char *lang ) { int i; - const char **langs; + const lang_code_list_t *langs; lang_str_ele_t skel, *e = NULL; if (!ls) return NULL; /* Check config/requested langs */ - if ((langs = lang_code_split(lang))) { - i = 0; - while (langs[i]) { - strncpy(skel.lang, langs[i], sizeof(skel.lang)); + if ((langs = lang_code_split(lang)) != NULL) { + for (i = 0; i < langs->codeslen; i++) { + strncpy(skel.lang, langs->codes[i]->code2b, sizeof(skel.lang)); if ((e = RB_FIND(ls, &skel, link, _lang_cmp))) break; - i++; } - free(langs); } /* Use first available */ @@ -109,14 +106,6 @@ lang_str_ele_t *lang_str_get2 return e; } -/* Get string */ -const char *lang_str_get - ( const lang_str_t *ls, const char *lang ) -{ - lang_str_ele_t *e = lang_str_get2(ls, lang); - return e ? e->str : NULL; -} - /* Internal insertion routine */ static int _lang_str_add ( lang_str_t *ls, const char *str, const char *lang, int cmd ) diff --git a/src/lang_str.h b/src/lang_str.h index b1b04fa4f..1204c9b98 100644 --- a/src/lang_str.h +++ b/src/lang_str.h @@ -38,8 +38,13 @@ lang_str_t *lang_str_create2 ( const char *str, const char *lang ); lang_str_t *lang_str_copy ( const lang_str_t *ls ); /* Get elements */ -const char *lang_str_get ( const lang_str_t *ls, const char *lang ); lang_str_ele_t *lang_str_get2 ( const lang_str_t *ls, const char *lang ); +static inline const char *lang_str_get(const lang_str_t *ls, const char *lang) + { + lang_str_ele_t *e = lang_str_get2(ls, lang); + return e ? e->str : NULL; + } + /* Add/Update elements */ int lang_str_add diff --git a/src/muxer/muxer_mkv.c b/src/muxer/muxer_mkv.c index 7a5694cd8..0f1869224 100644 --- a/src/muxer/muxer_mkv.c +++ b/src/muxer/muxer_mkv.c @@ -741,7 +741,8 @@ _mk_build_metadata(const dvr_entry_t *de, const epg_broadcast_t *ebc, epg_episode_t *ee = NULL; channel_t *ch = NULL; lang_str_t *ls = NULL, *ls2 = NULL; - const char **langs, *lang; + const char *lang; + const lang_code_list_t *langs; if (ebc) ee = ebc->episode; else if (de && de->de_bcast) ee = de->de_bcast->episode; @@ -828,9 +829,8 @@ _mk_build_metadata(const dvr_entry_t *de, const epg_broadcast_t *ebc, if (comment) { lang = "eng"; - if ((langs = lang_code_split(NULL)) && langs[0]) - lang = tvh_strdupa(langs[0]); - free(langs); + if ((langs = lang_code_split(NULL)) != NULL) + lang = tvh_strdupa(langs->codes[0]->code2b); addtag(q, build_tag_string("COMMENT", comment, lang, 0, NULL)); }