[FFmpeg-devel] [PATCH] lavu/dict: add av_dict_set_from_string() function
Stefano Sabatini
stefasab at gmail.com
Sun Apr 29 21:43:08 CEST 2012
Based on an idea by Andrei Utkin <andrey.krieger.utkin at gmail.com>.
---
libavutil/Makefile | 2 +-
libavutil/dict.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++
libavutil/dict.h | 27 ++++++++++++
3 files changed, 142 insertions(+), 1 deletions(-)
diff --git a/libavutil/Makefile b/libavutil/Makefile
index 83e6c07..eb12414 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -81,7 +81,7 @@ OBJS = adler32.o \
tree.o \
utils.o \
-TESTPROGS = adler32 aes avstring base64 bprint cpu crc des eval file fifo \
+TESTPROGS = adler32 aes avstring base64 bprint cpu crc dict des eval file fifo \
lfg lls md5 opt pca parseutils random_seed rational sha tree
TESTPROGS-$(HAVE_LZO1X_999_COMPRESS) += lzo
diff --git a/libavutil/dict.c b/libavutil/dict.c
index 6177ddd..f8d1845 100644
--- a/libavutil/dict.c
+++ b/libavutil/dict.c
@@ -118,3 +118,117 @@ void av_dict_copy(AVDictionary **dst, AVDictionary *src, int flags)
while ((t = av_dict_get(src, "", t, AV_DICT_IGNORE_SUFFIX)))
av_dict_set(dst, t->key, t->value, flags);
}
+
+typedef struct {
+ const AVClass *class;
+ int log_offset;
+ void *log_ctx;
+} DictLogContext;
+
+static const AVClass dict_class = { "DICT", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, offsetof(DictLogContext, log_offset), offsetof(DictLogContext, log_ctx) };
+
+static int set_key_value_pair(AVDictionary **dict, const char **buf, int flags,
+ const char *key_val_sep, const char *pairs_sep,
+ int log_offset, void *log_ctx)
+{
+ DictLogContext dict_log_ctx = { &dict_class, log_offset, log_ctx };
+ char *key = NULL, *val = NULL;
+ int ret;
+
+ ret = ff_parse_key_value_pair(&key, &val, buf, key_val_sep, pairs_sep);
+ if (ret < 0) {
+ av_log(&dict_log_ctx, AV_LOG_ERROR,
+ "Missing key or no key/value separator found after key in '%s'\n", key);
+ goto end;
+ }
+
+ av_log(&dict_log_ctx, AV_LOG_DEBUG,
+ "Setting entry with key '%s' to value '%s'\n", key, val);
+ ret = av_dict_set(dict, key, val, flags);
+
+end:
+ av_free(key);
+ av_free(val);
+ return ret;
+}
+
+int av_dict_set_from_string(AVDictionary **dict, const char *kv, int flags,
+ const char *key_val_sep, const char *pairs_sep,
+ int log_offset, void *log_ctx)
+{
+ int ret, count = 0;
+
+ if (!kv)
+ return 0;
+
+ while (*kv) {
+ ret = set_key_value_pair(dict, &kv, flags, key_val_sep, pairs_sep,
+ log_offset, log_ctx);
+ if (ret < 0)
+ return ret;
+ count++;
+
+ if (*kv)
+ kv++;
+ }
+
+ return count;
+}
+
+#ifdef TEST
+
+#undef printf
+
+static void log_dict(AVDictionary *dict)
+{
+ AVDictionaryEntry *e = NULL;
+ av_log(NULL, AV_LOG_INFO, "%p ", dict);
+ while (e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX))
+ av_log(NULL, AV_LOG_INFO, "%s->%s ", e->key, e->value);
+ av_log(NULL, AV_LOG_INFO, "\n");
+}
+
+int main(void)
+{
+ int i;
+
+ av_log(NULL, AV_LOG_INFO, "\nTesting av_dict_set_from_string()\n");
+ {
+ const char *entries[] = {
+ "",
+ ":",
+ "=",
+ "foo=:",
+ ":=foo",
+ "=foo",
+ "foo=",
+ "foo",
+ "foo=val",
+ "foo==val",
+ "toggle=:",
+ "string=:",
+ "toggle=1 : foo",
+ "toggle=100",
+ "toggle==1",
+ "flags=+mu-lame : num=42: toggle=0",
+ "num=42 : string=blahblah",
+ "rational=0 : rational=1/2 : rational=1/-1",
+ "rational=-1/0",
+ };
+
+ av_log_set_level(AV_LOG_DEBUG);
+
+ for (i = 0; i < FF_ARRAY_ELEMS(entries); i++) {
+ AVDictionary *dict = NULL;
+ av_log(NULL, AV_LOG_DEBUG, "Setting entries string '%s'\n", entries[i]);
+ if (av_dict_set_from_string(&dict, entries[i], 0, "=", ":", 0, NULL) < 0)
+ av_log(NULL, AV_LOG_ERROR, "Error setting string: '%s'\n", entries[i]);
+ log_dict(dict);
+ av_log(NULL, AV_LOG_INFO, "\n");
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libavutil/dict.h b/libavutil/dict.h
index 5a57224..d34b0d3 100644
--- a/libavutil/dict.h
+++ b/libavutil/dict.h
@@ -121,6 +121,33 @@ void av_dict_copy(AVDictionary **dst, AVDictionary *src, int flags);
void av_dict_free(AVDictionary **m);
/**
+ * Set an AVDictionary from a string containing a sequence of
+ * key/value pairs.
+ *
+ * @param[in][out] dict pointer to an AVDictionary. If *dict is NULL a new
+ * dictionary is created in put in the pointer, otherwise the
+ * dictionary is filled with the new entry.
+ * @param[in] kv string containing a key-value sequence to parse, may be NULL
+ * @param flags flags to use when setting entries in *dict
+ * @param[in] key_val_sep a 0-terminated list of characters used to
+ * separate key from value
+ * @param[in] pairs_sep a 0-terminated list of characters used to separate
+ * two key/value pairs each other
+ * @param[in] log_offset log level offset which is applied to the log
+ * level of log_ctx
+ * @param[in] log_ctx parent logging context
+ * @return the number of options set on success, a negative AVERROR code
+ * otherwise
+ */
+int av_dict_set_from_string(AVDictionary **dict, const char *kv, int flags,
+ const char *key_val_sep, const char *pairs_sep,
+ int log_offset, void *log_ctx);
+
+#define av_dict_set_from_string_quiet(dict, kv, flags, key_val_sep, pairs_sep) \
+ av_dict_set_from_string(dict, kv, flags, key_val_sep, pairs_sep, \
+ AV_LOG_MAX_OFFSET, NULL)
+
+/**
* @}
*/
--
1.7.5.4
More information about the ffmpeg-devel
mailing list