Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * copyright (c) 2009 Michael Niedermayer
  3.  *
  4.  * This file is part of FFmpeg.
  5.  *
  6.  * FFmpeg is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2.1 of the License, or (at your option) any later version.
  10.  *
  11.  * FFmpeg is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Lesser General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with FFmpeg; if not, write to the Free Software
  18.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19.  */
  20.  
  21. #include <string.h>
  22.  
  23. #include "avstring.h"
  24. #include "dict.h"
  25. #include "internal.h"
  26. #include "mem.h"
  27. #include "bprint.h"
  28.  
  29. struct AVDictionary {
  30.     int count;
  31.     AVDictionaryEntry *elems;
  32. };
  33.  
  34. int av_dict_count(const AVDictionary *m)
  35. {
  36.     return m ? m->count : 0;
  37. }
  38.  
  39. AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key,
  40.                                const AVDictionaryEntry *prev, int flags)
  41. {
  42.     unsigned int i, j;
  43.  
  44.     if (!m)
  45.         return NULL;
  46.  
  47.     if (prev)
  48.         i = prev - m->elems + 1;
  49.     else
  50.         i = 0;
  51.  
  52.     for (; i < m->count; i++) {
  53.         const char *s = m->elems[i].key;
  54.         if (flags & AV_DICT_MATCH_CASE)
  55.             for (j = 0; s[j] == key[j] && key[j]; j++)
  56.                 ;
  57.         else
  58.             for (j = 0; av_toupper(s[j]) == av_toupper(key[j]) && key[j]; j++)
  59.                 ;
  60.         if (key[j])
  61.             continue;
  62.         if (s[j] && !(flags & AV_DICT_IGNORE_SUFFIX))
  63.             continue;
  64.         return &m->elems[i];
  65.     }
  66.     return NULL;
  67. }
  68.  
  69. int av_dict_set(AVDictionary **pm, const char *key, const char *value,
  70.                 int flags)
  71. {
  72.     AVDictionary *m = *pm;
  73.     AVDictionaryEntry *tag = av_dict_get(m, key, NULL, flags);
  74.     char *oldval = NULL, *copy_key = NULL, *copy_value = NULL;
  75.  
  76.     if (flags & AV_DICT_DONT_STRDUP_KEY)
  77.         copy_key = (void *)key;
  78.     else
  79.         copy_key = av_strdup(key);
  80.     if (flags & AV_DICT_DONT_STRDUP_VAL)
  81.         copy_value = (void *)value;
  82.     else if (copy_key)
  83.         copy_value = av_strdup(value);
  84.     if (!m)
  85.         m = *pm = av_mallocz(sizeof(*m));
  86.     if (!m || (key && !copy_key) || (value && !copy_value))
  87.         goto err_out;
  88.  
  89.     if (tag) {
  90.         if (flags & AV_DICT_DONT_OVERWRITE) {
  91.             av_free(copy_key);
  92.             av_free(copy_value);
  93.             return 0;
  94.         }
  95.         if (flags & AV_DICT_APPEND)
  96.             oldval = tag->value;
  97.         else
  98.             av_free(tag->value);
  99.         av_free(tag->key);
  100.         *tag = m->elems[--m->count];
  101.     } else {
  102.         AVDictionaryEntry *tmp = av_realloc(m->elems,
  103.                                             (m->count + 1) * sizeof(*m->elems));
  104.         if (!tmp)
  105.             goto err_out;
  106.         m->elems = tmp;
  107.     }
  108.     if (copy_value) {
  109.         m->elems[m->count].key = copy_key;
  110.         m->elems[m->count].value = copy_value;
  111.         if (oldval && flags & AV_DICT_APPEND) {
  112.             size_t len = strlen(oldval) + strlen(copy_value) + 1;
  113.             char *newval = av_mallocz(len);
  114.             if (!newval)
  115.                 goto err_out;
  116.             av_strlcat(newval, oldval, len);
  117.             av_freep(&oldval);
  118.             av_strlcat(newval, copy_value, len);
  119.             m->elems[m->count].value = newval;
  120.             av_freep(&copy_value);
  121.         }
  122.         m->count++;
  123.     } else {
  124.         av_freep(&copy_key);
  125.     }
  126.     if (!m->count) {
  127.         av_freep(&m->elems);
  128.         av_freep(pm);
  129.     }
  130.  
  131.     return 0;
  132.  
  133. err_out:
  134.     if (m && !m->count) {
  135.         av_freep(&m->elems);
  136.         av_freep(pm);
  137.     }
  138.     av_free(copy_key);
  139.     av_free(copy_value);
  140.     return AVERROR(ENOMEM);
  141. }
  142.  
  143. int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value,
  144.                 int flags)
  145. {
  146.     char valuestr[22];
  147.     snprintf(valuestr, sizeof(valuestr), "%"PRId64, value);
  148.     flags &= ~AV_DICT_DONT_STRDUP_VAL;
  149.     return av_dict_set(pm, key, valuestr, flags);
  150. }
  151.  
  152. static int parse_key_value_pair(AVDictionary **pm, const char **buf,
  153.                                 const char *key_val_sep, const char *pairs_sep,
  154.                                 int flags)
  155. {
  156.     char *key = av_get_token(buf, key_val_sep);
  157.     char *val = NULL;
  158.     int ret;
  159.  
  160.     if (key && *key && strspn(*buf, key_val_sep)) {
  161.         (*buf)++;
  162.         val = av_get_token(buf, pairs_sep);
  163.     }
  164.  
  165.     if (key && *key && val && *val)
  166.         ret = av_dict_set(pm, key, val, flags);
  167.     else
  168.         ret = AVERROR(EINVAL);
  169.  
  170.     av_freep(&key);
  171.     av_freep(&val);
  172.  
  173.     return ret;
  174. }
  175.  
  176. int av_dict_parse_string(AVDictionary **pm, const char *str,
  177.                          const char *key_val_sep, const char *pairs_sep,
  178.                          int flags)
  179. {
  180.     int ret;
  181.  
  182.     if (!str)
  183.         return 0;
  184.  
  185.     /* ignore STRDUP flags */
  186.     flags &= ~(AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
  187.  
  188.     while (*str) {
  189.         if ((ret = parse_key_value_pair(pm, &str, key_val_sep, pairs_sep, flags)) < 0)
  190.             return ret;
  191.  
  192.         if (*str)
  193.             str++;
  194.     }
  195.  
  196.     return 0;
  197. }
  198.  
  199. void av_dict_free(AVDictionary **pm)
  200. {
  201.     AVDictionary *m = *pm;
  202.  
  203.     if (m) {
  204.         while (m->count--) {
  205.             av_freep(&m->elems[m->count].key);
  206.             av_freep(&m->elems[m->count].value);
  207.         }
  208.         av_freep(&m->elems);
  209.     }
  210.     av_freep(pm);
  211. }
  212.  
  213. void av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
  214. {
  215.     AVDictionaryEntry *t = NULL;
  216.  
  217.     while ((t = av_dict_get(src, "", t, AV_DICT_IGNORE_SUFFIX)))
  218.         av_dict_set(dst, t->key, t->value, flags);
  219. }
  220.  
  221. int av_dict_get_string(const AVDictionary *m, char **buffer,
  222.                        const char key_val_sep, const char pairs_sep)
  223. {
  224.     AVDictionaryEntry *t = NULL;
  225.     AVBPrint bprint;
  226.     int cnt = 0;
  227.     char special_chars[] = {pairs_sep, key_val_sep, '\0'};
  228.  
  229.     if (!buffer || pairs_sep == '\0' || key_val_sep == '\0' || pairs_sep == key_val_sep ||
  230.         pairs_sep == '\\' || key_val_sep == '\\')
  231.         return AVERROR(EINVAL);
  232.  
  233.     if (!av_dict_count(m)) {
  234.         *buffer = av_strdup("");
  235.         return *buffer ? 0 : AVERROR(ENOMEM);
  236.     }
  237.  
  238.     av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
  239.     while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) {
  240.         if (cnt++)
  241.             av_bprint_append_data(&bprint, &pairs_sep, 1);
  242.         av_bprint_escape(&bprint, t->key, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
  243.         av_bprint_append_data(&bprint, &key_val_sep, 1);
  244.         av_bprint_escape(&bprint, t->value, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
  245.     }
  246.     return av_bprint_finalize(&bprint, buffer);
  247. }
  248.  
  249. #ifdef TEST
  250. static void print_dict(const AVDictionary *m)
  251. {
  252.     AVDictionaryEntry *t = NULL;
  253.     while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX)))
  254.         printf("%s %s   ", t->key, t->value);
  255.     printf("\n");
  256. }
  257.  
  258. static void test_separators(const AVDictionary *m, const char pair, const char val)
  259. {
  260.     AVDictionary *dict = NULL;
  261.     char pairs[] = {pair , '\0'};
  262.     char vals[]  = {val, '\0'};
  263.  
  264.     char *buffer = NULL;
  265.     av_dict_copy(&dict, m, 0);
  266.     print_dict(dict);
  267.     av_dict_get_string(dict, &buffer, val, pair);
  268.     printf("%s\n", buffer);
  269.     av_dict_free(&dict);
  270.     av_dict_parse_string(&dict, buffer, vals, pairs, 0);
  271.     av_freep(&buffer);
  272.     print_dict(dict);
  273.     av_dict_free(&dict);
  274. }
  275.  
  276. int main(void)
  277. {
  278.     AVDictionary *dict = NULL;
  279.     AVDictionaryEntry *e;
  280.     char *buffer = NULL;
  281.  
  282.     printf("Testing av_dict_get_string() and av_dict_parse_string()\n");
  283.     av_dict_get_string(dict, &buffer, '=', ',');
  284.     printf("%s\n", buffer);
  285.     av_freep(&buffer);
  286.     av_dict_set(&dict, "aaa", "aaa", 0);
  287.     av_dict_set(&dict, "b,b", "bbb", 0);
  288.     av_dict_set(&dict, "c=c", "ccc", 0);
  289.     av_dict_set(&dict, "ddd", "d,d", 0);
  290.     av_dict_set(&dict, "eee", "e=e", 0);
  291.     av_dict_set(&dict, "f,f", "f=f", 0);
  292.     av_dict_set(&dict, "g=g", "g,g", 0);
  293.     test_separators(dict, ',', '=');
  294.     av_dict_free(&dict);
  295.     av_dict_set(&dict, "aaa", "aaa", 0);
  296.     av_dict_set(&dict, "bbb", "bbb", 0);
  297.     av_dict_set(&dict, "ccc", "ccc", 0);
  298.     av_dict_set(&dict, "\\,=\'\"", "\\,=\'\"", 0);
  299.     test_separators(dict, '"',  '=');
  300.     test_separators(dict, '\'', '=');
  301.     test_separators(dict, ',', '"');
  302.     test_separators(dict, ',', '\'');
  303.     test_separators(dict, '\'', '"');
  304.     test_separators(dict, '"', '\'');
  305.     av_dict_free(&dict);
  306.  
  307.     printf("\nTesting av_dict_set()\n");
  308.     av_dict_set(&dict, "a", "a", 0);
  309.     av_dict_set(&dict, "b", av_strdup("b"), AV_DICT_DONT_STRDUP_VAL);
  310.     av_dict_set(&dict, av_strdup("c"), "c", AV_DICT_DONT_STRDUP_KEY);
  311.     av_dict_set(&dict, av_strdup("d"), av_strdup("d"), AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
  312.     av_dict_set(&dict, "e", "e", AV_DICT_DONT_OVERWRITE);
  313.     av_dict_set(&dict, "e", "f", AV_DICT_DONT_OVERWRITE);
  314.     av_dict_set(&dict, "f", "f", 0);
  315.     av_dict_set(&dict, "f", NULL, 0);
  316.     av_dict_set(&dict, "ff", "f", 0);
  317.     av_dict_set(&dict, "ff", "f", AV_DICT_APPEND);
  318.     e = NULL;
  319.     while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX)))
  320.         printf("%s %s\n", e->key, e->value);
  321.     av_dict_free(&dict);
  322.  
  323.     av_dict_set(&dict, NULL, "a", 0);
  324.     av_dict_set(&dict, NULL, "b", 0);
  325.     av_dict_get(dict, NULL, NULL, 0);
  326.     e = NULL;
  327.     while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX)))
  328.         printf("'%s' '%s'\n", e->key, e->value);
  329.     av_dict_free(&dict);
  330.  
  331.  
  332.     //valgrind sensible test
  333.     printf("\nTesting av_dict_set_int()\n");
  334.     av_dict_set_int(&dict, "1", 1, AV_DICT_DONT_STRDUP_VAL);
  335.     av_dict_set_int(&dict, av_strdup("2"), 2, AV_DICT_DONT_STRDUP_KEY);
  336.     av_dict_set_int(&dict, av_strdup("3"), 3, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
  337.     av_dict_set_int(&dict, "4", 4, 0);
  338.     av_dict_set_int(&dict, "5", 5, AV_DICT_DONT_OVERWRITE);
  339.     av_dict_set_int(&dict, "5", 6, AV_DICT_DONT_OVERWRITE);
  340.     av_dict_set_int(&dict, "12", 1, 0);
  341.     av_dict_set_int(&dict, "12", 2, AV_DICT_APPEND);
  342.     e = NULL;
  343.     while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX)))
  344.         printf("%s %s\n", e->key, e->value);
  345.     av_dict_free(&dict);
  346.  
  347.     //valgrind sensible test
  348.     printf("\nTesting av_dict_set() with existing AVDictionaryEntry.key as key\n");
  349.     av_dict_set(&dict, "key", "old", 0);
  350.     e = av_dict_get(dict, "key", NULL, 0);
  351.     av_dict_set(&dict, e->key, "new val OK", 0);
  352.     e = av_dict_get(dict, "key", NULL, 0);
  353.     printf("%s\n", e->value);
  354.     av_dict_set(&dict, e->key, e->value, 0);
  355.     e = av_dict_get(dict, "key", NULL, 0);
  356.     printf("%s\n", e->value);
  357.     av_dict_free(&dict);
  358.  
  359.     return 0;
  360. }
  361. #endif
  362.