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: 2017-12-15 02:19:58 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        8596 : int av_dict_count(const AVDictionary *m)
      36             : {
      37        8596 :     return m ? m->count : 0;
      38             : }
      39             : 
      40     2943028 : AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key,
      41             :                                const AVDictionaryEntry *prev, int flags)
      42             : {
      43             :     unsigned int i, j;
      44             : 
      45     2943028 :     if (!m)
      46     1660825 :         return NULL;
      47             : 
      48     1282203 :     if (prev)
      49      465375 :         i = prev - m->elems + 1;
      50             :     else
      51      816828 :         i = 0;
      52             : 
      53     2349230 :     for (; i < m->count; i++) {
      54     1695066 :         const char *s = m->elems[i].key;
      55     1695066 :         if (flags & AV_DICT_MATCH_CASE)
      56       38493 :             for (j = 0; s[j] == key[j] && key[j]; j++)
      57             :                 ;
      58             :         else
      59     1656573 :             for (j = 0; av_toupper(s[j]) == av_toupper(key[j]) && key[j]; j++)
      60             :                 ;
      61     1695066 :         if (key[j])
      62     1063066 :             continue;
      63      632000 :         if (s[j] && !(flags & AV_DICT_IGNORE_SUFFIX))
      64        3961 :             continue;
      65      628039 :         return &m->elems[i];
      66             :     }
      67      654164 :     return NULL;
      68             : }
      69             : 
      70      983944 : int av_dict_set(AVDictionary **pm, const char *key, const char *value,
      71             :                 int flags)
      72             : {
      73      983944 :     AVDictionary *m = *pm;
      74      983944 :     AVDictionaryEntry *tag = NULL;
      75      983944 :     char *oldval = NULL, *copy_key = NULL, *copy_value = NULL;
      76             : 
      77      983944 :     if (!(flags & AV_DICT_MULTIKEY)) {
      78      983944 :         tag = av_dict_get(m, key, NULL, flags);
      79             :     }
      80      983944 :     if (flags & AV_DICT_DONT_STRDUP_KEY)
      81         360 :         copy_key = (void *)key;
      82             :     else
      83      983584 :         copy_key = av_strdup(key);
      84      983944 :     if (flags & AV_DICT_DONT_STRDUP_VAL)
      85        7008 :         copy_value = (void *)value;
      86      976936 :     else if (copy_key)
      87      976934 :         copy_value = av_strdup(value);
      88      983944 :     if (!m)
      89      511469 :         m = *pm = av_mallocz(sizeof(*m));
      90     1967888 :     if (!m || (key && !copy_key) || (value && !copy_value))
      91             :         goto err_out;
      92             : 
      93      983942 :     if (tag) {
      94      120627 :         if (flags & AV_DICT_DONT_OVERWRITE) {
      95           3 :             av_free(copy_key);
      96           3 :             av_free(copy_value);
      97           3 :             return 0;
      98             :         }
      99      120624 :         if (flags & AV_DICT_APPEND)
     100         234 :             oldval = tag->value;
     101             :         else
     102      120390 :             av_free(tag->value);
     103      120624 :         av_free(tag->key);
     104      120624 :         *tag = m->elems[--m->count];
     105      863315 :     } else if (copy_value) {
     106      494207 :         AVDictionaryEntry *tmp = av_realloc(m->elems,
     107      494207 :                                             (m->count + 1) * sizeof(*m->elems));
     108      494207 :         if (!tmp)
     109           0 :             goto err_out;
     110      494207 :         m->elems = tmp;
     111             :     }
     112      983939 :     if (copy_value) {
     113      504796 :         m->elems[m->count].key = copy_key;
     114      504796 :         m->elems[m->count].value = copy_value;
     115      504796 :         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      504796 :         m->count++;
     127             :     } else {
     128      479143 :         av_freep(&copy_key);
     129             :     }
     130      983939 :     if (!m->count) {
     131      346076 :         av_freep(&m->elems);
     132      346076 :         av_freep(pm);
     133             :     }
     134             : 
     135      983939 :     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         779 : int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value,
     148             :                 int flags)
     149             : {
     150             :     char valuestr[22];
     151         779 :     snprintf(valuestr, sizeof(valuestr), "%"PRId64, value);
     152         779 :     flags &= ~AV_DICT_DONT_STRDUP_VAL;
     153         779 :     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     3931249 : void av_dict_free(AVDictionary **pm)
     204             : {
     205     3931249 :     AVDictionary *m = *pm;
     206             : 
     207     3931249 :     if (m) {
     208      714954 :         while (m->count--) {
     209      384172 :             av_freep(&m->elems[m->count].key);
     210      384172 :             av_freep(&m->elems[m->count].value);
     211             :         }
     212      165391 :         av_freep(&m->elems);
     213             :     }
     214     3931249 :     av_freep(pm);
     215     3931249 : }
     216             : 
     217      799236 : int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
     218             : {
     219      799236 :     AVDictionaryEntry *t = NULL;
     220             : 
     221     1691698 :     while ((t = av_dict_get(src, "", t, AV_DICT_IGNORE_SUFFIX))) {
     222       93226 :         int ret = av_dict_set(dst, t->key, t->value, flags);
     223       93226 :         if (ret < 0)
     224           0 :             return ret;
     225             :     }
     226             : 
     227      799236 :     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         525 : int avpriv_dict_set_timestamp(AVDictionary **dict, const char *key, int64_t timestamp)
     259             : {
     260         525 :     time_t seconds = timestamp / 1000000;
     261             :     struct tm *ptm, tmbuf;
     262         525 :     ptm = gmtime_r(&seconds, &tmbuf);
     263         525 :     if (ptm) {
     264             :         char buf[32];
     265         525 :         if (!strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", ptm))
     266           0 :             return AVERROR_EXTERNAL;
     267         525 :         av_strlcatf(buf, sizeof(buf), ".%06dZ", (int)(timestamp % 1000000));
     268         525 :         return av_dict_set(dict, key, buf, 0);
     269             :     } else {
     270           0 :         return AVERROR_EXTERNAL;
     271             :     }
     272             : }

Generated by: LCOV version 1.13