LCOV - code coverage report
Current view: top level - src/libavutil - dict.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 136 145 93.8 %
Date: 2017-01-21 09:32:20 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        8027 : int av_dict_count(const AVDictionary *m)
      36             : {
      37        8027 :     return m ? m->count : 0;
      38             : }
      39             : 
      40     2827494 : AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key,
      41             :                                const AVDictionaryEntry *prev, int flags)
      42             : {
      43             :     unsigned int i, j;
      44             : 
      45     2827494 :     if (!m)
      46     1576738 :         return NULL;
      47             : 
      48     1250756 :     if (prev)
      49      453012 :         i = prev - m->elems + 1;
      50             :     else
      51      797744 :         i = 0;
      52             : 
      53     2230807 :     for (; i < m->count; i++) {
      54     1591704 :         const char *s = m->elems[i].key;
      55     1591704 :         if (flags & AV_DICT_MATCH_CASE)
      56       34294 :             for (j = 0; s[j] == key[j] && key[j]; j++)
      57             :                 ;
      58             :         else
      59     1557410 :             for (j = 0; av_toupper(s[j]) == av_toupper(key[j]) && key[j]; j++)
      60             :                 ;
      61     1591704 :         if (key[j])
      62      979410 :             continue;
      63      612294 :         if (s[j] && !(flags & AV_DICT_IGNORE_SUFFIX))
      64         641 :             continue;
      65      611653 :         return &m->elems[i];
      66             :     }
      67      639103 :     return NULL;
      68             : }
      69             : 
      70      940162 : int av_dict_set(AVDictionary **pm, const char *key, const char *value,
      71             :                 int flags)
      72             : {
      73      940162 :     AVDictionary *m = *pm;
      74      940162 :     AVDictionaryEntry *tag = NULL;
      75      940162 :     char *oldval = NULL, *copy_key = NULL, *copy_value = NULL;
      76             : 
      77      940162 :     if (!(flags & AV_DICT_MULTIKEY)) {
      78      940162 :         tag = av_dict_get(m, key, NULL, flags);
      79             :     }
      80      940162 :     if (flags & AV_DICT_DONT_STRDUP_KEY)
      81         313 :         copy_key = (void *)key;
      82             :     else
      83      939849 :         copy_key = av_strdup(key);
      84      940162 :     if (flags & AV_DICT_DONT_STRDUP_VAL)
      85        6548 :         copy_value = (void *)value;
      86      933614 :     else if (copy_key)
      87      933612 :         copy_value = av_strdup(value);
      88      940162 :     if (!m)
      89      492700 :         m = *pm = av_mallocz(sizeof(*m));
      90      940162 :     if (!m || (key && !copy_key) || (value && !copy_value))
      91             :         goto err_out;
      92             : 
      93      940160 :     if (tag) {
      94      115408 :         if (flags & AV_DICT_DONT_OVERWRITE) {
      95           3 :             av_free(copy_key);
      96           3 :             av_free(copy_value);
      97           3 :             return 0;
      98             :         }
      99      115405 :         if (flags & AV_DICT_APPEND)
     100         273 :             oldval = tag->value;
     101             :         else
     102      115132 :             av_free(tag->value);
     103      115405 :         av_free(tag->key);
     104      115405 :         *tag = m->elems[--m->count];
     105      824752 :     } else if (copy_value) {
     106      475063 :         AVDictionaryEntry *tmp = av_realloc(m->elems,
     107      475063 :                                             (m->count + 1) * sizeof(*m->elems));
     108      475063 :         if (!tmp)
     109           0 :             goto err_out;
     110      475063 :         m->elems = tmp;
     111             :     }
     112      940157 :     if (copy_value) {
     113      485009 :         m->elems[m->count].key = copy_key;
     114      485009 :         m->elems[m->count].value = copy_value;
     115      485009 :         if (oldval && flags & AV_DICT_APPEND) {
     116         273 :             size_t len = strlen(oldval) + strlen(copy_value) + 1;
     117         273 :             char *newval = av_mallocz(len);
     118         273 :             if (!newval)
     119           0 :                 goto err_out;
     120         273 :             av_strlcat(newval, oldval, len);
     121         273 :             av_freep(&oldval);
     122         273 :             av_strlcat(newval, copy_value, len);
     123         273 :             m->elems[m->count].value = newval;
     124         273 :             av_freep(&copy_value);
     125             :         }
     126      485009 :         m->count++;
     127             :     } else {
     128      455148 :         av_freep(&copy_key);
     129             :     }
     130      940157 :     if (!m->count) {
     131      327845 :         av_freep(&m->elems);
     132      327845 :         av_freep(pm);
     133             :     }
     134             : 
     135      940157 :     return 0;
     136             : 
     137             : 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         747 : int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value,
     148             :                 int flags)
     149             : {
     150             :     char valuestr[22];
     151         747 :     snprintf(valuestr, sizeof(valuestr), "%"PRId64, value);
     152         747 :     flags &= ~AV_DICT_DONT_STRDUP_VAL;
     153         747 :     return av_dict_set(pm, key, valuestr, flags);
     154             : }
     155             : 
     156          79 : 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          79 :     char *key = av_get_token(buf, key_val_sep);
     161          79 :     char *val = NULL;
     162             :     int ret;
     163             : 
     164          79 :     if (key && *key && strspn(*buf, key_val_sep)) {
     165          79 :         (*buf)++;
     166          79 :         val = av_get_token(buf, pairs_sep);
     167             :     }
     168             : 
     169          79 :     if (key && *key && val && *val)
     170          79 :         ret = av_dict_set(pm, key, val, flags);
     171             :     else
     172           0 :         ret = AVERROR(EINVAL);
     173             : 
     174          79 :     av_freep(&key);
     175          79 :     av_freep(&val);
     176             : 
     177          79 :     return ret;
     178             : }
     179             : 
     180          36 : 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          36 :     if (!str)
     187           0 :         return 0;
     188             : 
     189             :     /* ignore STRDUP flags */
     190          36 :     flags &= ~(AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
     191             : 
     192         151 :     while (*str) {
     193          79 :         if ((ret = parse_key_value_pair(pm, &str, key_val_sep, pairs_sep, flags)) < 0)
     194           0 :             return ret;
     195             : 
     196          79 :         if (*str)
     197          43 :             str++;
     198             :     }
     199             : 
     200          36 :     return 0;
     201             : }
     202             : 
     203     4182389 : void av_dict_free(AVDictionary **pm)
     204             : {
     205     4182389 :     AVDictionary *m = *pm;
     206             : 
     207     4182389 :     if (m) {
     208      699310 :         while (m->count--) {
     209      369604 :             av_freep(&m->elems[m->count].key);
     210      369604 :             av_freep(&m->elems[m->count].value);
     211             :         }
     212      164853 :         av_freep(&m->elems);
     213             :     }
     214     4182389 :     av_freep(pm);
     215     4182389 : }
     216             : 
     217      774784 : int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
     218             : {
     219      774784 :     AVDictionaryEntry *t = NULL;
     220             : 
     221     1640334 :     while ((t = av_dict_get(src, "", t, AV_DICT_IGNORE_SUFFIX))) {
     222       90766 :         int ret = av_dict_set(dst, t->key, t->value, flags);
     223       90766 :         if (ret < 0)
     224           0 :             return ret;
     225             :     }
     226             : 
     227      774784 :     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         483 : int avpriv_dict_set_timestamp(AVDictionary **dict, const char *key, int64_t timestamp)
     259             : {
     260         483 :     time_t seconds = timestamp / 1000000;
     261             :     struct tm *ptm, tmbuf;
     262         483 :     ptm = gmtime_r(&seconds, &tmbuf);
     263         483 :     if (ptm) {
     264             :         char buf[32];
     265         483 :         if (!strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", ptm))
     266           0 :             return AVERROR_EXTERNAL;
     267         483 :         av_strlcatf(buf, sizeof(buf), ".%06dZ", (int)(timestamp % 1000000));
     268         483 :         return av_dict_set(dict, key, buf, 0);
     269             :     } else {
     270           0 :         return AVERROR_EXTERNAL;
     271             :     }
     272             : }

Generated by: LCOV version 1.12