AVOptions: split av_set_string3 into opt type-specific functions
authorAnton Khirnov <anton@khirnov.net>
Tue, 23 Aug 2011 08:23:57 +0000 (10:23 +0200)
committerAnton Khirnov <anton@khirnov.net>
Mon, 10 Oct 2011 18:27:30 +0000 (20:27 +0200)
Also stop attempting to honor the alloc parameter, as things break
horribly in that case.
It will be removed in upcoming successor to av_set_string3.

libavutil/opt.c
libavutil/opt.h

index 1dec9a6..876ea4c 100644 (file)
@@ -116,10 +116,98 @@ static int hexchar2int(char c) {
     return -1;
 }
 
+static int set_string_binary(void *obj, const AVOption *o, const char *val, uint8_t **dst)
+{
+    int *lendst = (int *)(dst + 1);
+    uint8_t *bin, *ptr;
+    int len = strlen(val);
+
+    av_freep(dst);
+    *lendst = 0;
+
+    if (len & 1)
+        return AVERROR(EINVAL);
+    len /= 2;
+
+    ptr = bin = av_malloc(len);
+    while (*val) {
+        int a = hexchar2int(*val++);
+        int b = hexchar2int(*val++);
+        if (a < 0 || b < 0) {
+            av_free(bin);
+            return AVERROR(EINVAL);
+        }
+        *ptr++ = (a << 4) | b;
+    }
+    *dst = bin;
+    *lendst = len;
+
+    return 0;
+}
+
+static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **dst)
+{
+    av_freep(dst);
+    *dst = av_strdup(val);
+    return 0;
+}
+
+static int set_string_number(void *obj, const AVOption *o, const char *val, void *dst)
+{
+    int ret = 0, notfirst = 0;
+    for (;;) {
+        int i;
+        char buf[256];
+        int cmd = 0;
+        double d;
+
+        if (*val == '+' || *val == '-')
+            cmd = *(val++);
+
+        for (i = 0; i < sizeof(buf) - 1 && val[i] && val[i] != '+' && val[i] != '-'; i++)
+            buf[i] = val[i];
+        buf[i] = 0;
+
+        {
+            const AVOption *o_named = av_opt_find(obj, buf, o->unit, 0, 0);
+            if (o_named && o_named->type == FF_OPT_TYPE_CONST)
+                d = o_named->default_val.dbl;
+            else if (!strcmp(buf, "default")) d = o->default_val.dbl;
+            else if (!strcmp(buf, "max"    )) d = o->max;
+            else if (!strcmp(buf, "min"    )) d = o->min;
+            else if (!strcmp(buf, "none"   )) d = 0;
+            else if (!strcmp(buf, "all"    )) d = ~0;
+            else {
+                int res = av_expr_parse_and_eval(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
+                if (res < 0) {
+                    av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
+                    return res;
+                }
+            }
+        }
+        if (o->type == FF_OPT_TYPE_FLAGS) {
+            if      (cmd == '+') d = av_get_int(obj, o->name, NULL) | (int64_t)d;
+            else if (cmd == '-') d = av_get_int(obj, o->name, NULL) &~(int64_t)d;
+        } else {
+            if      (cmd == '+') d = notfirst*av_get_double(obj, o->name, NULL) + d;
+            else if (cmd == '-') d = notfirst*av_get_double(obj, o->name, NULL) - d;
+        }
+
+        if ((ret = av_set_number2(obj, o->name, d, 1, 1, NULL)) < 0)
+            return ret;
+        val += i;
+        if (!*val)
+            return 0;
+        notfirst = 1;
+    }
+
+    return 0;
+}
+
 int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out)
 {
-    int ret;
     const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
+    void *dst;
     if (o_out)
         *o_out = o;
     if (!o)
@@ -127,85 +215,20 @@ int av_set_string3(void *obj, const char *name, const char *val, int alloc, cons
     if (!val)
         return AVERROR(EINVAL);
 
-    if (o->type == FF_OPT_TYPE_BINARY) {
-        uint8_t **dst = (uint8_t **)(((uint8_t*)obj) + o->offset);
-        int *lendst = (int *)(dst + 1);
-        uint8_t *bin, *ptr;
-        int len = strlen(val);
-        av_freep(dst);
-        *lendst = 0;
-        if (len & 1) return AVERROR(EINVAL);
-        len /= 2;
-        ptr = bin = av_malloc(len);
-        while (*val) {
-            int a = hexchar2int(*val++);
-            int b = hexchar2int(*val++);
-            if (a < 0 || b < 0) {
-                av_free(bin);
-                return AVERROR(EINVAL);
-            }
-            *ptr++ = (a << 4) | b;
-        }
-        *dst = bin;
-        *lendst = len;
-        return 0;
-    }
-    if (o->type != FF_OPT_TYPE_STRING) {
-        int notfirst=0;
-        for (;;) {
-            int i;
-            char buf[256];
-            int cmd=0;
-            double d;
-
-            if (*val == '+' || *val == '-')
-                cmd= *(val++);
-
-            for (i=0; i<sizeof(buf)-1 && val[i] && val[i]!='+' && val[i]!='-'; i++)
-                buf[i]= val[i];
-            buf[i]=0;
-
-            {
-                const AVOption *o_named = av_opt_find(obj, buf, o->unit, 0, 0);
-                if (o_named && o_named->type == FF_OPT_TYPE_CONST)
-                    d= o_named->default_val.dbl;
-                else if (!strcmp(buf, "default")) d= o->default_val.dbl;
-                else if (!strcmp(buf, "max"    )) d= o->max;
-                else if (!strcmp(buf, "min"    )) d= o->min;
-                else if (!strcmp(buf, "none"   )) d= 0;
-                else if (!strcmp(buf, "all"    )) d= ~0;
-                else {
-                    int res = av_expr_parse_and_eval(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
-                    if (res < 0) {
-                        av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
-                        return res;
-                    }
-                }
-            }
-            if (o->type == FF_OPT_TYPE_FLAGS) {
-                if      (cmd=='+') d= av_get_int(obj, name, NULL) | (int64_t)d;
-                else if (cmd=='-') d= av_get_int(obj, name, NULL) &~(int64_t)d;
-            } else {
-                if      (cmd=='+') d= notfirst*av_get_double(obj, name, NULL) + d;
-                else if (cmd=='-') d= notfirst*av_get_double(obj, name, NULL) - d;
-            }
-
-            if ((ret = av_set_number2(obj, name, d, 1, 1, o_out)) < 0)
-                return ret;
-            val+= i;
-            if (!*val)
-                return 0;
-            notfirst=1;
-        }
-    }
-
-    if (alloc) {
-        av_free(*(void**)(((uint8_t*)obj) + o->offset));
-        val= av_strdup(val);
+    dst = ((uint8_t*)obj) + o->offset;
+    switch (o->type) {
+    case FF_OPT_TYPE_STRING:   return set_string(obj, o, val, dst);
+    case FF_OPT_TYPE_BINARY:   return set_string_binary(obj, o, val, dst);
+    case FF_OPT_TYPE_FLAGS:
+    case FF_OPT_TYPE_INT:
+    case FF_OPT_TYPE_INT64:
+    case FF_OPT_TYPE_FLOAT:
+    case FF_OPT_TYPE_DOUBLE:
+    case FF_OPT_TYPE_RATIONAL: return set_string_number(obj, o, val, dst);
     }
 
-    memcpy(((uint8_t*)obj) + o->offset, &val, sizeof(val));
-    return 0;
+    av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");
+    return AVERROR(EINVAL);
 }
 
 const AVOption *av_set_double(void *obj, const char *name, double n)
index c6a5919..50c0a33 100644 (file)
@@ -129,9 +129,7 @@ const AVOption *av_find_opt(void *obj, const char *name, const char *unit, int m
  * similarly, '-' unsets a flag.
  * @param[out] o_out if non-NULL put here a pointer to the AVOption
  * found
- * @param alloc when 1 then the old value will be av_freed() and the
- *                     new av_strduped()
- *              when 0 then no av_free() nor av_strdup() will be used
+ * @param alloc this parameter is currently ignored
  * @return 0 if the value has been set, or an AVERROR code in case of
  * error:
  * AVERROR_OPTION_NOT_FOUND if no matching option exists