LCOV - code coverage report
Current view: top level - libavutil - dict.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 137 146 93.8 %
Date: 2018-05-20 11:54:08 Functions: 10 10 100.0 %

          Line data    Source code
       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 "time_internal.h"
      28             : #include "bprint.h"
      29             : 
      30             : struct AVDictionary {
      31             :     int count;
      32             :     AVDictionaryEntry *elems;
      33             : };
      34             : 
      35        8865 : int av_dict_count(const AVDictionary *m)
      36             : {
      37        8865 :     return m ? m->count : 0;
      38             : }
      39             : 
      40     3037822 : AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key,
      41             :                                const AVDictionaryEntry *prev, int flags)
      42             : {
      43             :     unsigned int i, j;
      44             : 
      45     3037822 :     if (!m)
      46     1715570 :         return NULL;
      47             : 
      48     1322252 :     if (prev)
      49      482251 :         i = prev - m->elems + 1;
      50             :     else
      51      840001 :         i = 0;
      52             : 
      53     2408817 :     for (; i < m->count; i++) {
      54     1739188 :         const char *s = m->elems[i].key;
      55     1739188 :         if (flags & AV_DICT_MATCH_CASE)
      56       38657 :             for (j = 0; s[j] == key[j] && key[j]; j++)
      57             :                 ;
      58             :         else
      59     1700531 :             for (j = 0; av_toupper(s[j]) == av_toupper(key[j]) && key[j]; j++)
      60             :                 ;
      61     1739188 :         if (key[j])
      62     1082602 :             continue;
      63      656586 :         if (s[j] && !(flags & AV_DICT_IGNORE_SUFFIX))
      64        3963 :             continue;
      65      652623 :         return &m->elems[i];
      66             :     }
      67      669629 :     return NULL;
      68             : }
      69             : 
      70     1034820 : int av_dict_set(AVDictionary **pm, const char *key, const char *value,
      71             :                 int flags)
      72             : {
      73     1034820 :     AVDictionary *m = *pm;
      74     1034820 :     AVDictionaryEntry *tag = NULL;
      75     1034820 :     char *oldval = NULL, *copy_key = NULL, *copy_value = NULL;
      76             : 
      77     1034820 :     if (!(flags & AV_DICT_MULTIKEY)) {
      78     1034820 :         tag = av_dict_get(m, key, NULL, flags);
      79             :     }
      80     1034820 :     if (flags & AV_DICT_DONT_STRDUP_KEY)
      81         373 :         copy_key = (void *)key;
      82             :     else
      83     1034447 :         copy_key = av_strdup(key);
      84     1034820 :     if (flags & AV_DICT_DONT_STRDUP_VAL)
      85        7180 :         copy_value = (void *)value;
      86     1027640 :     else if (copy_key)
      87     1027638 :         copy_value = av_strdup(value);
      88     1034820 :     if (!m)
      89      540302 :         m = *pm = av_mallocz(sizeof(*m));
      90     2069640 :     if (!m || (key && !copy_key) || (value && !copy_value))
      91             :         goto err_out;
      92             : 
      93     1034818 :     if (tag) {
      94      127830 :         if (flags & AV_DICT_DONT_OVERWRITE) {
      95          58 :             av_free(copy_key);
      96          58 :             av_free(copy_value);
      97          58 :             return 0;
      98             :         }
      99      127772 :         if (flags & AV_DICT_APPEND)
     100         234 :             oldval = tag->value;
     101             :         else
     102      127538 :             av_free(tag->value);
     103      127772 :         av_free(tag->key);
     104      127772 :         *tag = m->elems[--m->count];
     105      906988 :     } else if (copy_value) {
     106      514338 :         AVDictionaryEntry *tmp = av_realloc(m->elems,
     107      514338 :                                             (m->count + 1) * sizeof(*m->elems));
     108      514338 :         if (!tmp)
     109           0 :             goto err_out;
     110      514338 :         m->elems = tmp;
     111             :     }
     112     1034760 :     if (copy_value) {
     113      525273 :         m->elems[m->count].key = copy_key;
     114      525273 :         m->elems[m->count].value = copy_value;
     115      525273 :         if (oldval && flags & AV_DICT_APPEND) {
     116         234 :             size_t len = strlen(oldval) + strlen(copy_value) + 1;
     117         234 :             char *newval = av_mallocz(len);
     118         234 :             if (!newval)
     119           0 :                 goto err_out;
     120         234 :             av_strlcat(newval, oldval, len);
     121         234 :             av_freep(&oldval);
     122         234 :             av_strlcat(newval, copy_value, len);
     123         234 :             m->elems[m->count].value = newval;
     124         234 :             av_freep(&copy_value);
     125             :         }
     126      525273 :         m->count++;
     127             :     } else {
     128      509487 :         av_freep(&copy_key);
     129             :     }
     130     1034760 :     if (!m->count) {
     131      368842 :         av_freep(&m->elems);
     132      368842 :         av_freep(pm);
     133             :     }
     134             : 
     135     1034760 :     return 0;
     136             : 
     137           2 : err_out:
     138           2 :     if (m && !m->count) {
     139           2 :         av_freep(&m->elems);
     140           2 :         av_freep(pm);
     141             :     }
     142           2 :     av_free(copy_key);
     143           2 :     av_free(copy_value);
     144           2 :     return AVERROR(ENOMEM);
     145             : }
     146             : 
     147         795 : int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value,
     148             :                 int flags)
     149             : {
     150             :     char valuestr[22];
     151         795 :     snprintf(valuestr, sizeof(valuestr), "%"PRId64, value);
     152         795 :     flags &= ~AV_DICT_DONT_STRDUP_VAL;
     153         795 :     return av_dict_set(pm, key, valuestr, flags);
     154             : }
     155             : 
     156          76 : static int parse_key_value_pair(AVDictionary **pm, const char **buf,
     157             :                                 const char *key_val_sep, const char *pairs_sep,
     158             :                                 int flags)
     159             : {
     160          76 :     char *key = av_get_token(buf, key_val_sep);
     161          76 :     char *val = NULL;
     162             :     int ret;
     163             : 
     164          76 :     if (key && *key && strspn(*buf, key_val_sep)) {
     165          76 :         (*buf)++;
     166          76 :         val = av_get_token(buf, pairs_sep);
     167             :     }
     168             : 
     169          76 :     if (key && *key && val && *val)
     170          76 :         ret = av_dict_set(pm, key, val, flags);
     171             :     else
     172           0 :         ret = AVERROR(EINVAL);
     173             : 
     174          76 :     av_freep(&key);
     175          76 :     av_freep(&val);
     176             : 
     177          76 :     return ret;
     178             : }
     179             : 
     180          35 : int av_dict_parse_string(AVDictionary **pm, const char *str,
     181             :                          const char *key_val_sep, const char *pairs_sep,
     182             :                          int flags)
     183             : {
     184             :     int ret;
     185             : 
     186          35 :     if (!str)
     187           0 :         return 0;
     188             : 
     189             :     /* ignore STRDUP flags */
     190          35 :     flags &= ~(AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
     191             : 
     192         146 :     while (*str) {
     193          76 :         if ((ret = parse_key_value_pair(pm, &str, key_val_sep, pairs_sep, flags)) < 0)
     194           0 :             return ret;
     195             : 
     196          76 :         if (*str)
     197          41 :             str++;
     198             :     }
     199             : 
     200          35 :     return 0;
     201             : }
     202             : 
     203     3984683 : void av_dict_free(AVDictionary **pm)
     204             : {
     205     3984683 :     AVDictionary *m = *pm;
     206             : 
     207     3984683 :     if (m) {
     208      740417 :         while (m->count--) {
     209      397501 :             av_freep(&m->elems[m->count].key);
     210      397501 :             av_freep(&m->elems[m->count].value);
     211             :         }
     212      171458 :         av_freep(&m->elems);
     213             :     }
     214     3984683 :     av_freep(pm);
     215     3984683 : }
     216             : 
     217      806016 : int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
     218             : {
     219      806016 :     AVDictionaryEntry *t = NULL;
     220             : 
     221     1708521 :     while ((t = av_dict_get(src, "", t, AV_DICT_IGNORE_SUFFIX))) {
     222       96489 :         int ret = av_dict_set(dst, t->key, t->value, flags);
     223       96489 :         if (ret < 0)
     224           0 :             return ret;
     225             :     }
     226             : 
     227      806016 :     return 0;
     228             : }
     229             : 
     230           8 : int av_dict_get_string(const AVDictionary *m, char **buffer,
     231             :                        const char key_val_sep, const char pairs_sep)
     232             : {
     233           8 :     AVDictionaryEntry *t = NULL;
     234             :     AVBPrint bprint;
     235           8 :     int cnt = 0;
     236           8 :     char special_chars[] = {pairs_sep, key_val_sep, '\0'};
     237             : 
     238          16 :     if (!buffer || pairs_sep == '\0' || key_val_sep == '\0' || pairs_sep == key_val_sep ||
     239          16 :         pairs_sep == '\\' || key_val_sep == '\\')
     240           0 :         return AVERROR(EINVAL);
     241             : 
     242           8 :     if (!av_dict_count(m)) {
     243           1 :         *buffer = av_strdup("");
     244           1 :         return *buffer ? 0 : AVERROR(ENOMEM);
     245             :     }
     246             : 
     247           7 :     av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
     248          45 :     while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) {
     249          31 :         if (cnt++)
     250          24 :             av_bprint_append_data(&bprint, &pairs_sep, 1);
     251          31 :         av_bprint_escape(&bprint, t->key, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
     252          31 :         av_bprint_append_data(&bprint, &key_val_sep, 1);
     253          31 :         av_bprint_escape(&bprint, t->value, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
     254             :     }
     255           7 :     return av_bprint_finalize(&bprint, buffer);
     256             : }
     257             : 
     258         539 : int avpriv_dict_set_timestamp(AVDictionary **dict, const char *key, int64_t timestamp)
     259             : {
     260         539 :     time_t seconds = timestamp / 1000000;
     261             :     struct tm *ptm, tmbuf;
     262         539 :     ptm = gmtime_r(&seconds, &tmbuf);
     263         539 :     if (ptm) {
     264             :         char buf[32];
     265         539 :         if (!strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", ptm))
     266           0 :             return AVERROR_EXTERNAL;
     267         539 :         av_strlcatf(buf, sizeof(buf), ".%06dZ", (int)(timestamp % 1000000));
     268         539 :         return av_dict_set(dict, key, buf, 0);
     269             :     } else {
     270           0 :         return AVERROR_EXTERNAL;
     271             :     }
     272             : }

Generated by: LCOV version 1.13