diff options
Diffstat (limited to 'libavutil/dict.c')
-rw-r--r-- | libavutil/dict.c | 150 |
1 files changed, 111 insertions, 39 deletions
diff --git a/libavutil/dict.c b/libavutil/dict.c index 7213bf2519..0ea71386e5 100644 --- a/libavutil/dict.c +++ b/libavutil/dict.c @@ -1,20 +1,20 @@ /* * copyright (c) 2009 Michael Niedermayer * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -24,6 +24,8 @@ #include "dict.h" #include "internal.h" #include "mem.h" +#include "time_internal.h" +#include "bprint.h" struct AVDictionary { int count; @@ -69,19 +71,29 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags) { AVDictionary *m = *pm; - AVDictionaryEntry *tag = av_dict_get(m, key, NULL, flags); - char *oldval = NULL; - int allocated = !!m; + AVDictionaryEntry *tag = NULL; + char *oldval = NULL, *copy_key = NULL, *copy_value = NULL; + if (!(flags & AV_DICT_MULTIKEY)) { + tag = av_dict_get(m, key, NULL, flags); + } + if (flags & AV_DICT_DONT_STRDUP_KEY) + copy_key = (void *)key; + else + copy_key = av_strdup(key); + if (flags & AV_DICT_DONT_STRDUP_VAL) + copy_value = (void *)value; + else if (copy_key) + copy_value = av_strdup(value); if (!m) m = *pm = av_mallocz(sizeof(*m)); - if (!m) - return AVERROR(ENOMEM); + if (!m || (key && !copy_key) || (value && !copy_value)) + goto err_out; if (tag) { if (flags & AV_DICT_DONT_OVERWRITE) { - if (flags & AV_DICT_DONT_STRDUP_KEY) av_free(key); - if (flags & AV_DICT_DONT_STRDUP_VAL) av_free(value); + av_free(copy_key); + av_free(copy_value); return 0; } if (flags & AV_DICT_APPEND) @@ -90,39 +102,55 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value, av_free(tag->value); av_free(tag->key); *tag = m->elems[--m->count]; - } else { - int ret = av_reallocp_array(&m->elems, - m->count + 1, sizeof(*m->elems)); - if (ret < 0) { - if (allocated) - av_freep(pm); - - return ret; - } + } else if (copy_value) { + AVDictionaryEntry *tmp = av_realloc(m->elems, + (m->count + 1) * sizeof(*m->elems)); + if (!tmp) + goto err_out; + m->elems = tmp; } - if (value) { - if (flags & AV_DICT_DONT_STRDUP_KEY) - m->elems[m->count].key = key; - else - m->elems[m->count].key = av_strdup(key); - if (flags & AV_DICT_DONT_STRDUP_VAL) { - m->elems[m->count].value = value; - } else if (oldval && flags & AV_DICT_APPEND) { - int len = strlen(oldval) + strlen(value) + 1; - if (!(oldval = av_realloc(oldval, len))) - return AVERROR(ENOMEM); - av_strlcat(oldval, value, len); - m->elems[m->count].value = oldval; - } else - m->elems[m->count].value = av_strdup(value); + if (copy_value) { + m->elems[m->count].key = copy_key; + m->elems[m->count].value = copy_value; + if (oldval && flags & AV_DICT_APPEND) { + size_t len = strlen(oldval) + strlen(copy_value) + 1; + char *newval = av_mallocz(len); + if (!newval) + goto err_out; + av_strlcat(newval, oldval, len); + av_freep(&oldval); + av_strlcat(newval, copy_value, len); + m->elems[m->count].value = newval; + av_freep(©_value); + } m->count++; + } else { + av_freep(©_key); } if (!m->count) { - av_free(m->elems); + av_freep(&m->elems); av_freep(pm); } return 0; + +err_out: + if (m && !m->count) { + av_freep(&m->elems); + av_freep(pm); + } + av_free(copy_key); + av_free(copy_value); + return AVERROR(ENOMEM); +} + +int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, + int flags) +{ + char valuestr[22]; + snprintf(valuestr, sizeof(valuestr), "%"PRId64, value); + flags &= ~AV_DICT_DONT_STRDUP_VAL; + return av_dict_set(pm, key, valuestr, flags); } static int parse_key_value_pair(AVDictionary **pm, const char **buf, @@ -178,10 +206,10 @@ void av_dict_free(AVDictionary **pm) if (m) { while (m->count--) { - av_free(m->elems[m->count].key); - av_free(m->elems[m->count].value); + av_freep(&m->elems[m->count].key); + av_freep(&m->elems[m->count].value); } - av_free(m->elems); + av_freep(&m->elems); } av_freep(pm); } @@ -198,3 +226,47 @@ int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags) return 0; } + +int av_dict_get_string(const AVDictionary *m, char **buffer, + const char key_val_sep, const char pairs_sep) +{ + AVDictionaryEntry *t = NULL; + AVBPrint bprint; + int cnt = 0; + char special_chars[] = {pairs_sep, key_val_sep, '\0'}; + + if (!buffer || pairs_sep == '\0' || key_val_sep == '\0' || pairs_sep == key_val_sep || + pairs_sep == '\\' || key_val_sep == '\\') + return AVERROR(EINVAL); + + if (!av_dict_count(m)) { + *buffer = av_strdup(""); + return *buffer ? 0 : AVERROR(ENOMEM); + } + + av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED); + while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) { + if (cnt++) + av_bprint_append_data(&bprint, &pairs_sep, 1); + av_bprint_escape(&bprint, t->key, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0); + av_bprint_append_data(&bprint, &key_val_sep, 1); + av_bprint_escape(&bprint, t->value, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0); + } + return av_bprint_finalize(&bprint, buffer); +} + +int avpriv_dict_set_timestamp(AVDictionary **dict, const char *key, int64_t timestamp) +{ + time_t seconds = timestamp / 1000000; + struct tm *ptm, tmbuf; + ptm = gmtime_r(&seconds, &tmbuf); + if (ptm) { + char buf[32]; + if (!strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", ptm)) + return AVERROR_EXTERNAL; + av_strlcatf(buf, sizeof(buf), ".%06dZ", (int)(timestamp % 1000000)); + return av_dict_set(dict, key, buf, 0); + } else { + return AVERROR_EXTERNAL; + } +} |