FFmpeg
Loading...
Searching...
No Matches
dict.c
Go to the documentation of this file.
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 "error.h"
29#include "mem.h"
30#include "bprint.h"
31
37
39{
40 return m ? m->count : 0;
41}
42
44 const AVDictionaryEntry *prev)
45{
46 int i = 0;
47
48 if (!m)
49 return NULL;
50
51 if (prev)
52 i = prev - m->elems + 1;
53
54 av_assert2(i >= 0);
55 if (i >= m->count)
56 return NULL;
57
58 return &m->elems[i];
59}
60
62 const AVDictionaryEntry *prev, int flags)
63{
64 const AVDictionaryEntry *entry = prev;
65 unsigned int j;
66
67 if (!key)
68 return NULL;
69
70 while ((entry = av_dict_iterate(m, entry))) {
71 const char *s = entry->key;
73 for (j = 0; s[j] == key[j] && key[j]; j++)
74 ;
75 else
76 for (j = 0; av_toupper(s[j]) == av_toupper(key[j]) && key[j]; j++)
77 ;
78 if (key[j])
79 continue;
80 if (s[j] && !(flags & AV_DICT_IGNORE_SUFFIX))
81 continue;
82 return (AVDictionaryEntry *)entry;
83 }
84 return NULL;
85}
86
87int av_dict_set(AVDictionary **pm, const char *key, const char *value,
88 int flags)
89{
90 AVDictionary *m = *pm;
92 char *copy_key = NULL, *copy_value = NULL;
93 int err;
94
96 copy_value = (void *)value;
97 else if (value)
98 copy_value = av_strdup(value);
99 if (!key) {
100 err = AVERROR(EINVAL);
101 goto err_out;
102 }
104 copy_key = (void *)key;
105 else
106 copy_key = av_strdup(key);
107 if (!copy_key || (value && !copy_value))
108 goto enomem;
109
110 if (!(flags & AV_DICT_MULTIKEY)) {
111 tag = av_dict_get(m, key, NULL, flags);
112 } else if (flags & AV_DICT_DEDUP) {
113 while ((tag = av_dict_get(m, key, tag, flags))) {
114 if ((!value && !tag->value) ||
115 (value && tag->value && !strcmp(value, tag->value))) {
116 av_free(copy_key);
117 av_free(copy_value);
118 return 0;
119 }
120 }
121 }
122 if (!m)
123 m = *pm = av_mallocz(sizeof(*m));
124 if (!m)
125 goto enomem;
126
127 if (tag) {
129 av_free(copy_key);
130 av_free(copy_value);
131 return 0;
132 }
133 if (copy_value && flags & AV_DICT_APPEND) {
134 size_t oldlen = strlen(tag->value);
135 size_t new_part_len = strlen(copy_value);
136 size_t len = oldlen + new_part_len + 1;
137 char *newval = av_realloc(tag->value, len);
138 if (!newval)
139 goto enomem;
140 memcpy(newval + oldlen, copy_value, new_part_len + 1);
141 av_freep(&copy_value);
142 copy_value = newval;
143 } else
144 av_free(tag->value);
145 av_free(tag->key);
146 *tag = m->elems[--m->count];
147 } else if (copy_value) {
149 m->count + 1, sizeof(*m->elems));
150 if (!tmp)
151 goto enomem;
152 m->elems = tmp;
153 }
154 if (copy_value) {
155 m->elems[m->count].key = copy_key;
156 m->elems[m->count].value = copy_value;
157 m->count++;
159 m->duplicate_keys = 1;
160 } else {
161 err = 0;
162 goto end;
163 }
164
165 return 0;
166
167enomem:
168 err = AVERROR(ENOMEM);
169err_out:
170 av_free(copy_value);
171end:
172 if (m && !m->count) {
173 av_freep(&m->elems);
174 av_freep(pm);
175 }
176 av_free(copy_key);
177 return err;
178}
179
181 int flags)
182{
183 char valuestr[22];
184 snprintf(valuestr, sizeof(valuestr), "%"PRId64, value);
186 return av_dict_set(pm, key, valuestr, flags);
187}
188
189static int parse_key_value_pair(AVDictionary **pm, const char **buf,
190 const char *key_val_sep, const char *pairs_sep,
191 int flags)
192{
193 char *key = av_get_token(buf, key_val_sep);
194 char *val = NULL;
195 int ret;
196
197 if (key && *key && strspn(*buf, key_val_sep)) {
198 (*buf)++;
199 val = av_get_token(buf, pairs_sep);
200 }
201
202 if (key && *key && val && *val)
203 ret = av_dict_set(pm, key, val, flags);
204 else
205 ret = AVERROR(EINVAL);
206
207 av_freep(&key);
208 av_freep(&val);
209
210 return ret;
211}
212
213int av_dict_parse_string(AVDictionary **pm, const char *str,
214 const char *key_val_sep, const char *pairs_sep,
215 int flags)
216{
217 int ret;
218
219 if (!str)
220 return 0;
221
222 /* ignore STRDUP flags */
224
225 while (*str) {
226 if ((ret = parse_key_value_pair(pm, &str, key_val_sep, pairs_sep, flags)) < 0)
227 return ret;
228
229 if (*str)
230 str++;
231 }
232
233 return 0;
234}
235
237{
238 AVDictionary *m = *pm;
239
240 if (m) {
241 while (m->count--) {
242 av_freep(&m->elems[m->count].key);
243 av_freep(&m->elems[m->count].value);
244 }
245 av_freep(&m->elems);
246 }
247 av_freep(pm);
248}
249
251{
252 const AVDictionaryEntry *t = NULL;
253
254 if (!*dst && src && src->count && !src->duplicate_keys &&
256 AVDictionary *m = av_mallocz(sizeof(*m));
257 if (!m)
258 return AVERROR(ENOMEM);
259 m->elems = av_calloc(src->count, sizeof(*m->elems));
260 if (!m->elems) {
261 av_free(m);
262 return AVERROR(ENOMEM);
263 }
264 *dst = m;
265 for (int i = 0; i < src->count; i++) {
266 m->elems[i].key = av_strdup(src->elems[i].key);
267 m->elems[i].value = av_strdup(src->elems[i].value);
268 m->count++;
269 if (!m->elems[i].key || !m->elems[i].value) {
271 return AVERROR(ENOMEM);
272 }
273 }
274 return 0;
275 }
276
277 while ((t = av_dict_iterate(src, t))) {
278 int ret = av_dict_set(dst, t->key, t->value, flags);
279 if (ret < 0)
280 return ret;
281 }
282
283 return 0;
284}
285
287 const char key_val_sep, const char pairs_sep)
288{
289 const AVDictionaryEntry *t = NULL;
290 AVBPrint bprint;
291 int cnt = 0;
292 char special_chars[] = {pairs_sep, key_val_sep, '\0'};
293
294 if (!buffer || pairs_sep == '\0' || key_val_sep == '\0' || pairs_sep == key_val_sep ||
295 pairs_sep == '\\' || key_val_sep == '\\')
296 return AVERROR(EINVAL);
297
298 if (!av_dict_count(m)) {
299 *buffer = av_strdup("");
300 return *buffer ? 0 : AVERROR(ENOMEM);
301 }
302
304 while ((t = av_dict_iterate(m, t))) {
305 if (cnt++)
306 av_bprint_append_data(&bprint, &pairs_sep, 1);
307 av_bprint_escape(&bprint, t->key, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
308 av_bprint_append_data(&bprint, &key_val_sep, 1);
309 av_bprint_escape(&bprint, t->value, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
310 }
311 return av_bprint_finalize(&bprint, buffer);
312}
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:97
static double val(void *priv, double ch)
Definition aeval.c:77
#define entry
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition avassert.h:68
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition bprint.c:68
AVBPrint public header.
#define AV_BPRINT_SIZE_UNLIMITED
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static int parse_key_value_pair(AVDictionary **pm, const char **buf, const char *key_val_sep, const char *pairs_sep, int flags)
Definition dict.c:189
Public dictionary API.
error code definitions
double value
Definition eval.c:102
const char * key
void av_bprint_escape(AVBPrint *dstbuf, const char *src, const char *special_chars, enum AVEscapeMode mode, int flags)
Escape the content in src and append it to dstbuf.
Definition bprint.c:262
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition bprint.c:234
void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size)
Append data to a print buffer.
Definition bprint.c:147
#define AV_DICT_MULTIKEY
Allow to store several equal keys in the dictionary.
Definition dict.h:84
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:236
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition dict.c:61
#define AV_DICT_IGNORE_SUFFIX
Return first entry in a dictionary whose first part corresponds to the search key,...
Definition dict.h:75
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
Definition dict.c:43
int av_dict_get_string(const AVDictionary *m, char **buffer, const char key_val_sep, const char pairs_sep)
Get dictionary entries as a string.
Definition dict.c:286
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition dict.c:250
#define AV_DICT_APPEND
If the entry already exists, append to it.
Definition dict.h:82
#define AV_DICT_DONT_STRDUP_VAL
Take ownership of a value that's been allocated with av_malloc() or another memory allocation functio...
Definition dict.h:79
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition dict.c:87
#define AV_DICT_DONT_OVERWRITE
Don't overwrite existing entries.
Definition dict.h:81
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
Definition dict.c:213
#define AV_DICT_DONT_STRDUP_KEY
Take ownership of a key that's been allocated with av_malloc() or another memory allocation function.
Definition dict.h:77
int av_dict_count(const AVDictionary *m)
Get number of entries in dictionary.
Definition dict.c:38
#define AV_DICT_MATCH_CASE
Only get an entry with exact-case key match.
Definition dict.h:74
#define AV_DICT_DEDUP
If inserting a value that already exists for a key, do nothing.
Definition dict.h:85
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set() that converts the value to a string and stores it.
Definition dict.c:180
#define AVERROR(e)
Definition error.h:45
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition mem.c:318
char * av_get_token(const char **buf, const char *term)
Unescape the given string until a non escaped terminating char, and return the token corresponding to...
Definition avstring.c:143
static av_const int av_toupper(int c)
Locale-independent conversion of ASCII characters to uppercase.
Definition avstring.h:227
@ AV_ESCAPE_MODE_BACKSLASH
Use backslash escaping.
Definition avstring.h:316
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:370
Memory handling functions.
uint32_t tag
Definition movenc.c:2128
#define av_strdup(s)
Definition ops_static.c:55
#define av_realloc(p, s)
Definition ops_static.c:54
char * key
Definition dict.h:91
char * value
Definition dict.h:92
AVDictionaryEntry * elems
Definition dict.c:34
int duplicate_keys
Definition dict.c:35
int count
Definition dict.c:33
#define av_free(p)
#define av_mallocz(s)
#define av_freep(p)
static uint8_t tmp[40]
Definition aes_ctr.c:52
#define src
Definition vp8dsp.c:248
static char buffer[20]
Definition seek.c:32
int len