tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

dict.c (7873B)


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