]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
lang codes: reimplement lang_code_split - the code is much faster now
authorJaroslav Kysela <perex@perex.cz>
Thu, 1 Feb 2018 15:39:50 +0000 (16:39 +0100)
committerJaroslav Kysela <perex@perex.cz>
Thu, 1 Feb 2018 15:39:50 +0000 (16:39 +0100)
src/lang_codes.c
src/lang_codes.h
src/lang_str.c
src/lang_str.h
src/muxer/muxer_mkv.c

index e9e580a47100305af54806e1f6d535151f8510ea..f51666e712bdc7c12a5dcf8d583994b4a56c9ef7 100644 (file)
@@ -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);
index 89d5457b05c174ceeb3944329b714e9dde479b97..2fcc5f1585c7cb34334f1ae207bfdacb7b7acfc1 100644 (file)
@@ -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 {
index 8d74d23d3d60e5f403f0f72ad9d681f0752f5563..f423432fd6141900a4994a168dbe4c92854aa0c8 100644 (file)
@@ -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 )
index b1b04fa4fa69b2206fe00336005cdcc6a7a169a1..1204c9b9852f86b013cb66bbaf5a8c0aeae815e2 100644 (file)
@@ -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      
index 7a5694cd8e62d130e5a6d33f138d9708729d966d..0f18692249a2ef8f1c4478f62805fc2defc252c9 100644 (file)
@@ -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));
   }