2 * copyright (c) 2009 Michael Niedermayer
4 * This file is part of FFmpeg.
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.
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.
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
31 AVDictionaryEntry
*elems
;
34 int av_dict_count(const AVDictionary
*m
)
36 return m
? m
->count
: 0;
39 AVDictionaryEntry
*av_dict_get(const AVDictionary
*m
, const char *key
,
40 const AVDictionaryEntry
*prev
, int flags
)
48 i
= prev
- m
->elems
+ 1;
52 for (; i
< m
->count
; i
++) {
53 const char *s
= m
->elems
[i
].key
;
54 if (flags
& AV_DICT_MATCH_CASE
)
55 for (j
= 0; s
[j
] == key
[j
] && key
[j
]; j
++)
58 for (j
= 0; av_toupper(s
[j
]) == av_toupper(key
[j
]) && key
[j
]; j
++)
62 if (s
[j
] && !(flags
& AV_DICT_IGNORE_SUFFIX
))
69 int av_dict_set(AVDictionary
**pm
, const char *key
, const char *value
,
72 AVDictionary
*m
= *pm
;
73 AVDictionaryEntry
*tag
= av_dict_get(m
, key
, NULL
, flags
);
77 m
= *pm
= av_mallocz(sizeof(*m
));
80 if (flags
& AV_DICT_DONT_OVERWRITE
) {
81 if (flags
& AV_DICT_DONT_STRDUP_KEY
) av_free((void*)key
);
82 if (flags
& AV_DICT_DONT_STRDUP_VAL
) av_free((void*)value
);
85 if (flags
& AV_DICT_APPEND
)
90 *tag
= m
->elems
[--m
->count
];
92 AVDictionaryEntry
*tmp
= av_realloc(m
->elems
,
93 (m
->count
+ 1) * sizeof(*m
->elems
));
99 if (flags
& AV_DICT_DONT_STRDUP_KEY
)
100 m
->elems
[m
->count
].key
= (char*)(intptr_t)key
;
102 m
->elems
[m
->count
].key
= av_strdup(key
);
103 if (flags
& AV_DICT_DONT_STRDUP_VAL
) {
104 m
->elems
[m
->count
].value
= (char*)(intptr_t)value
;
105 } else if (oldval
&& flags
& AV_DICT_APPEND
) {
106 int len
= strlen(oldval
) + strlen(value
) + 1;
107 char *newval
= av_mallocz(len
);
110 av_strlcat(newval
, oldval
, len
);
112 av_strlcat(newval
, value
, len
);
113 m
->elems
[m
->count
].value
= newval
;
115 m
->elems
[m
->count
].value
= av_strdup(value
);
130 if (flags
& AV_DICT_DONT_STRDUP_KEY
) av_free((void*)key
);
131 if (flags
& AV_DICT_DONT_STRDUP_VAL
) av_free((void*)value
);
132 return AVERROR(ENOMEM
);
135 int av_dict_set_int(AVDictionary
**pm
, const char *key
, int64_t value
,
139 snprintf(valuestr
, sizeof(valuestr
), "%"PRId64
, value
);
140 return av_dict_set(pm
, key
, valuestr
, flags
);
143 static int parse_key_value_pair(AVDictionary
**pm
, const char **buf
,
144 const char *key_val_sep
, const char *pairs_sep
,
147 char *key
= av_get_token(buf
, key_val_sep
);
151 if (key
&& *key
&& strspn(*buf
, key_val_sep
)) {
153 val
= av_get_token(buf
, pairs_sep
);
156 if (key
&& *key
&& val
&& *val
)
157 ret
= av_dict_set(pm
, key
, val
, flags
);
159 ret
= AVERROR(EINVAL
);
167 int av_dict_parse_string(AVDictionary
**pm
, const char *str
,
168 const char *key_val_sep
, const char *pairs_sep
,
176 /* ignore STRDUP flags */
177 flags
&= ~(AV_DICT_DONT_STRDUP_KEY
| AV_DICT_DONT_STRDUP_VAL
);
180 if ((ret
= parse_key_value_pair(pm
, &str
, key_val_sep
, pairs_sep
, flags
)) < 0)
190 void av_dict_free(AVDictionary
**pm
)
192 AVDictionary
*m
= *pm
;
196 av_free(m
->elems
[m
->count
].key
);
197 av_free(m
->elems
[m
->count
].value
);
204 void av_dict_copy(AVDictionary
**dst
, const AVDictionary
*src
, int flags
)
206 AVDictionaryEntry
*t
= NULL
;
208 while ((t
= av_dict_get(src
, "", t
, AV_DICT_IGNORE_SUFFIX
)))
209 av_dict_set(dst
, t
->key
, t
->value
, flags
);
212 int av_dict_get_string(const AVDictionary
*m
, char **buffer
,
213 const char key_val_sep
, const char pairs_sep
)
215 AVDictionaryEntry
*t
= NULL
;
218 char special_chars
[] = {pairs_sep
, key_val_sep
, '\0'};
220 if (!buffer
|| pairs_sep
== '\0' || key_val_sep
== '\0' || pairs_sep
== key_val_sep
||
221 pairs_sep
== '\\' || key_val_sep
== '\\')
222 return AVERROR(EINVAL
);
224 if (!av_dict_count(m
)) {
225 *buffer
= av_strdup("");
226 return *buffer
? 0 : AVERROR(ENOMEM
);
229 av_bprint_init(&bprint
, 64, AV_BPRINT_SIZE_UNLIMITED
);
230 while ((t
= av_dict_get(m
, "", t
, AV_DICT_IGNORE_SUFFIX
))) {
232 av_bprint_append_data(&bprint
, &pairs_sep
, 1);
233 av_bprint_escape(&bprint
, t
->key
, special_chars
, AV_ESCAPE_MODE_BACKSLASH
, 0);
234 av_bprint_append_data(&bprint
, &key_val_sep
, 1);
235 av_bprint_escape(&bprint
, t
->value
, special_chars
, AV_ESCAPE_MODE_BACKSLASH
, 0);
237 return av_bprint_finalize(&bprint
, buffer
);
241 static void print_dict(const AVDictionary
*m
)
243 AVDictionaryEntry
*t
= NULL
;
244 while ((t
= av_dict_get(m
, "", t
, AV_DICT_IGNORE_SUFFIX
)))
245 printf("%s %s ", t
->key
, t
->value
);
249 static void test_separators(const AVDictionary
*m
, const char pair
, const char val
)
251 AVDictionary
*dict
= NULL
;
252 char pairs
[] = {pair
, '\0'};
253 char vals
[] = {val
, '\0'};
256 av_dict_copy(&dict
, m
, 0);
258 av_dict_get_string(dict
, &buffer
, val
, pair
);
259 printf("%s\n", buffer
);
261 av_dict_parse_string(&dict
, buffer
, vals
, pairs
, 0);
269 AVDictionary
*dict
= NULL
;
272 printf("Testing av_dict_get_string() and av_dict_parse_string()\n");
273 av_dict_get_string(dict
, &buffer
, '=', ',');
274 printf("%s\n", buffer
);
276 av_dict_set(&dict
, "aaa", "aaa", 0);
277 av_dict_set(&dict
, "b,b", "bbb", 0);
278 av_dict_set(&dict
, "c=c", "ccc", 0);
279 av_dict_set(&dict
, "ddd", "d,d", 0);
280 av_dict_set(&dict
, "eee", "e=e", 0);
281 av_dict_set(&dict
, "f,f", "f=f", 0);
282 av_dict_set(&dict
, "g=g", "g,g", 0);
283 test_separators(dict
, ',', '=');
285 av_dict_set(&dict
, "aaa", "aaa", 0);
286 av_dict_set(&dict
, "bbb", "bbb", 0);
287 av_dict_set(&dict
, "ccc", "ccc", 0);
288 av_dict_set(&dict
, "\\,=\'\"", "\\,=\'\"", 0);
289 test_separators(dict
, '"', '=');
290 test_separators(dict
, '\'', '=');
291 test_separators(dict
, ',', '"');
292 test_separators(dict
, ',', '\'');
293 test_separators(dict
, '\'', '"');
294 test_separators(dict
, '"', '\'');