lavu/opt: parse key into a mallocated buffer.
authorNicolas George <nicolas.george@normalesup.org>
Fri, 2 Nov 2012 10:35:12 +0000 (11:35 +0100)
committerNicolas George <nicolas.george@normalesup.org>
Sun, 4 Nov 2012 09:47:52 +0000 (10:47 +0100)
It removes the hardcoded limit on the key size without making
the code much more complex, and it makes for a more versatile API.

libavutil/opt.c

index 404fbac..35475eb 100644 (file)
@@ -829,31 +829,27 @@ static int is_key_char(char c)
  * Read a key from a string.
  *
  * The key consists of is_key_char characters and must be terminated by a
- * character from the delim string; spaces are ignored. The key buffer must
- * be 4 bytes larger than the longest acceptable key. If the key is too
- * long, an ellipsis will be written at the end.
+ * character from the delim string; spaces are ignored.
  *
  * @return  0 for success (even with ellipsis), <0 for failure
  */
-static int get_key(const char **ropts, const char *delim, char *key, unsigned key_size)
+static int get_key(const char **ropts, const char *delim, char **rkey)
 {
-    unsigned key_pos = 0;
     const char *opts = *ropts;
+    const char *key_start, *key_end;
 
-    opts += strspn(opts, WHITESPACES);
-    while (is_key_char(*opts)) {
-        key[key_pos++] = *opts;
-        if (key_pos == key_size)
-            key_pos--;
-        (opts)++;
-    }
+    key_start = opts += strspn(opts, WHITESPACES);
+    while (is_key_char(*opts))
+        opts++;
+    key_end = opts;
     opts += strspn(opts, WHITESPACES);
     if (!*opts || !strchr(delim, *opts))
         return AVERROR(EINVAL);
     opts++;
-    key[key_pos++] = 0;
-    if (key_pos == key_size)
-        key[key_pos - 4] = key[key_pos - 3] = key[key_pos - 2] = '.';
+    if (!(*rkey = av_malloc(key_end - key_start + 1)))
+        return AVERROR(ENOMEM);
+    memcpy(*rkey, key_start, key_end - key_start);
+    (*rkey)[key_end - key_start] = 0;
     *ropts = opts;
     return 0;
 }
@@ -864,7 +860,7 @@ int av_opt_set_from_string(void *ctx, const char *opts,
 {
     int ret, count = 0;
     const char *dummy_shorthand = NULL;
-    char key_buf[68], *value;
+    char *parsed_key, *value;
     const char *key;
 
     if (!opts)
@@ -873,7 +869,8 @@ int av_opt_set_from_string(void *ctx, const char *opts,
         shorthand = &dummy_shorthand;
 
     while (*opts) {
-        if ((ret = get_key(&opts, key_val_sep, key_buf, sizeof(key_buf))) < 0) {
+        parsed_key = NULL; /* so we can free it anyway */
+        if ((ret = get_key(&opts, key_val_sep, &parsed_key)) < 0) {
             if (*shorthand) {
                 key = *(shorthand++);
             } else {
@@ -881,7 +878,7 @@ int av_opt_set_from_string(void *ctx, const char *opts,
                 return AVERROR(EINVAL);
             }
         } else {
-            key = key_buf;
+            key = parsed_key;
             while (*shorthand) /* discard all remaining shorthand */
                 shorthand++;
         }
@@ -896,10 +893,12 @@ int av_opt_set_from_string(void *ctx, const char *opts,
             if (ret == AVERROR_OPTION_NOT_FOUND)
                 av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key);
             av_free(value);
+            av_free(parsed_key);
             return ret;
         }
 
         av_free(value);
+        av_free(parsed_key);
         count++;
     }
     return count;