Browse code

Implement av_set_options_string().

Originally committed as revision 18832 to svn://svn.ffmpeg.org/ffmpeg/trunk

Stefano Sabatini authored on 2009/05/15 07:57:08
Showing 2 changed files
... ...
@@ -256,10 +256,108 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, void *log_ctx)
256 256
     return 0;
257 257
 }
258 258
 
259
+/**
260
+ * Stores the value in the field in ctx that is named like key.
261
+ * ctx must be an AVClass context, storing is done using AVOptions.
262
+ *
263
+ * @param buf the string to parse, buf will be updated to point at the
264
+ * separator just after the parsed key/value pair
265
+ * @param key_val_sep a 0-terminated list of characters used to
266
+ * separate key from value
267
+ * @param pairs_sep a 0-terminated list of characters used to separate
268
+ * two pairs from each other
269
+ * @return 0 if the key/value pair has been successfully parsed and
270
+ * set, or a negative value corresponding to an AVERROR code in case
271
+ * of error:
272
+ * AVERROR(EINVAL) if the key/value pair cannot be parsed,
273
+ * the error code issued by av_set_string3() if the key/value pair
274
+ * cannot be set
275
+ */
276
+static int parse_key_value_pair(void *ctx, const char **buf,
277
+                                const char *key_val_sep, const char *pairs_sep)
278
+{
279
+    char *key = av_get_token(buf, key_val_sep);
280
+    char *val;
281
+    int ret;
282
+
283
+    if (*key && strspn(*buf, key_val_sep)) {
284
+        (*buf)++;
285
+        val = av_get_token(buf, pairs_sep);
286
+    } else {
287
+        av_log(ctx, AV_LOG_ERROR, "Missing key or no key/value separator found after key '%s'\n", key);
288
+        av_free(key);
289
+        return AVERROR(EINVAL);
290
+    }
291
+
292
+    av_log(ctx, AV_LOG_DEBUG, "Setting value '%s' for key '%s'\n", val, key);
293
+
294
+    ret = av_set_string3(ctx, key, val, 1, NULL);
295
+
296
+    av_free(key);
297
+    av_free(val);
298
+    return ret;
299
+}
300
+
301
+int av_set_options_string(void *ctx, const char *opts,
302
+                          const char *key_val_sep, const char *pairs_sep)
303
+{
304
+    int ret, count = 0;
305
+
306
+    while (*opts) {
307
+        if ((ret = parse_key_value_pair(ctx, &opts, key_val_sep, pairs_sep)) < 0)
308
+            return ret;
309
+        count++;
310
+
311
+        if (*opts)
312
+            opts++;
313
+    }
314
+
315
+    return count;
316
+}
317
+
259 318
 #ifdef TEST
260 319
 
261 320
 #undef printf
262 321
 
322
+typedef struct TestContext
323
+{
324
+    const AVClass *class;
325
+    int num;
326
+    int toggle;
327
+    char *string;
328
+    int flags;
329
+    AVRational rational;
330
+} TestContext;
331
+
332
+#define OFFSET(x) offsetof(TestContext, x)
333
+
334
+#define TEST_FLAG_COOL 01
335
+#define TEST_FLAG_LAME 02
336
+#define TEST_FLAG_MU   04
337
+
338
+static const AVOption test_options[]= {
339
+{"num",      "set num",        OFFSET(num),      FF_OPT_TYPE_INT,      0,              0,        100                 },
340
+{"toggle",   "set toggle",     OFFSET(toggle),   FF_OPT_TYPE_INT,      0,              0,        1                   },
341
+{"rational", "set rational",   OFFSET(rational), FF_OPT_TYPE_RATIONAL, 0,              0,        10                  },
342
+{"string",   "set string",     OFFSET(string),   FF_OPT_TYPE_STRING,   0,              CHAR_MIN, CHAR_MAX            },
343
+{"flags",    "set flags",      OFFSET(flags),    FF_OPT_TYPE_FLAGS,    0,              0,        INT_MAX, 0, "flags" },
344
+{"cool",     "set cool flag ", 0,                FF_OPT_TYPE_CONST,    TEST_FLAG_COOL, INT_MIN,  INT_MAX, 0, "flags" },
345
+{"lame",     "set lame flag ", 0,                FF_OPT_TYPE_CONST,    TEST_FLAG_LAME, INT_MIN,  INT_MAX, 0, "flags" },
346
+{"mu",       "set mu flag ",   0,                FF_OPT_TYPE_CONST,    TEST_FLAG_MU,   INT_MIN,  INT_MAX, 0, "flags" },
347
+{NULL},
348
+};
349
+
350
+static const char *test_get_name(void *ctx)
351
+{
352
+    return "test";
353
+}
354
+
355
+static const AVClass test_class = {
356
+    "TestContext",
357
+    test_get_name,
358
+    test_options
359
+};
360
+
263 361
 int main(void)
264 362
 {
265 363
     int i;
... ...
@@ -329,6 +427,45 @@ int main(void)
329 329
         }
330 330
     }
331 331
 
332
+    printf("\nTesting av_set_options_string()\n");
333
+    {
334
+        TestContext test_ctx;
335
+        const char *options[] = {
336
+            "",
337
+            ":",
338
+            "=",
339
+            "foo=:",
340
+            ":=foo",
341
+            "=foo",
342
+            "foo=",
343
+            "foo",
344
+            "foo=val",
345
+            "foo==val",
346
+            "toggle=:",
347
+            "string=:",
348
+            "toggle=1 : foo",
349
+            "toggle=100",
350
+            "toggle==1",
351
+            "flags=+mu-lame : num=42: toggle=0",
352
+            "num=42 : string=blahblah",
353
+            "rational=0 : rational=1/2 : rational=1/-1",
354
+            "rational=-1/0",
355
+        };
356
+
357
+        test_ctx.class = &test_class;
358
+        av_opt_set_defaults2(&test_ctx, 0, 0);
359
+        test_ctx.string = av_strdup("default");
360
+
361
+        av_log_set_level(AV_LOG_DEBUG);
362
+
363
+        for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
364
+            av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
365
+            if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0)
366
+                av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]);
367
+            printf("\n");
368
+        }
369
+    }
370
+
332 371
     return 0;
333 372
 }
334 373
 
... ...
@@ -25,6 +25,8 @@
25 25
 #ifndef AVFILTER_PARSEUTILS_H
26 26
 #define AVFILTER_PARSEUTILS_H
27 27
 
28
+#include "libavcodec/opt.h"
29
+
28 30
 /**
29 31
  * Unescapes the given string until a non escaped terminating char,
30 32
  * and returns the token corresponding to the unescaped string.
... ...
@@ -51,4 +53,23 @@ char *av_get_token(const char **buf, const char *term);
51 51
  */
52 52
 int av_parse_color(uint8_t *rgba_color, const char *color_string, void *log_ctx);
53 53
 
54
+/**
55
+ * Parses the key/value pairs list in opts. For each key/value pair
56
+ * found, stores the value in the field in ctx that is named like the
57
+ * key. ctx must be an AVClass context, storing is done using
58
+ * AVOptions.
59
+ *
60
+ * @param key_val_sep a 0-terminated list of characters used to
61
+ * separate key from value
62
+ * @param pairs_sep a 0-terminated list of characters used to separate
63
+ * two pairs from each other
64
+ * @return the number of successfully set key/value pairs, or a negative
65
+ * value corresponding to an AVERROR code in case of error:
66
+ * AVERROR(EINVAL) if opts cannot be parsed,
67
+ * the error code issued by av_set_string3() if a key/value pair
68
+ * cannot be set
69
+ */
70
+int av_set_options_string(void *ctx, const char *opts,
71
+                          const char *key_val_sep, const char *pairs_sep);
72
+
54 73
 #endif  /* AVFILTER_PARSEUTILS_H */