1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-08-15 14:13:16 +02:00

lavu/opt: parse key into a mallocated buffer.

It removes the hardcoded limit on the key size without making
the code much more complex, and it makes for a more versatile API.
This commit is contained in:
Nicolas George
2012-11-02 11:35:12 +01:00
parent 4e6fa5be3c
commit e021eeb9f0

View File

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