|
|
|
@@ -790,6 +790,91 @@ int av_set_options_string(void *ctx, const char *opts, |
|
|
|
return count; |
|
|
|
} |
|
|
|
|
|
|
|
#define WHITESPACES " \n\t" |
|
|
|
|
|
|
|
static int is_key_char(char c) |
|
|
|
{ |
|
|
|
return (unsigned)((c | 32) - 'a') < 26 || |
|
|
|
(unsigned)(c - '0') < 10 || |
|
|
|
c == '-' || c == '_' || c == '/' || 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. @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) |
|
|
|
{ |
|
|
|
unsigned key_pos = 0; |
|
|
|
const char *opts = *ropts; |
|
|
|
|
|
|
|
opts += strspn(opts, WHITESPACES); |
|
|
|
while (is_key_char(*opts)) { |
|
|
|
key[key_pos++] = *opts; |
|
|
|
if (key_pos == key_size) |
|
|
|
key_pos--; |
|
|
|
(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] = '.'; |
|
|
|
*ropts = opts; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
int av_opt_set_from_string(void *ctx, const char *opts, |
|
|
|
const char *const *shorthand, |
|
|
|
const char *key_val_sep, const char *pairs_sep) |
|
|
|
{ |
|
|
|
int ret, count = 0; |
|
|
|
const char *dummy_shorthand = NULL; |
|
|
|
char key_buf[68], *value; |
|
|
|
const char *key; |
|
|
|
|
|
|
|
if (!opts) |
|
|
|
return 0; |
|
|
|
if (!shorthand) |
|
|
|
shorthand = &dummy_shorthand; |
|
|
|
|
|
|
|
while (*opts) { |
|
|
|
if ((ret = get_key(&opts, key_val_sep, key_buf, sizeof(key_buf))) < 0) { |
|
|
|
if (*shorthand) { |
|
|
|
key = *(shorthand++); |
|
|
|
} else { |
|
|
|
av_log(ctx, AV_LOG_ERROR, "No option name near '%s'\n", opts); |
|
|
|
return AVERROR(EINVAL); |
|
|
|
} |
|
|
|
} else { |
|
|
|
key = key_buf; |
|
|
|
while (*shorthand) /* discard all remaining shorthand */ |
|
|
|
shorthand++; |
|
|
|
} |
|
|
|
|
|
|
|
if (!(value = av_get_token(&opts, pairs_sep))) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
if (*opts && strchr(pairs_sep, *opts)) |
|
|
|
opts++; |
|
|
|
|
|
|
|
av_log(ctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value); |
|
|
|
if ((ret = av_opt_set(ctx, key, value, 0)) < 0) { |
|
|
|
if (ret == AVERROR_OPTION_NOT_FOUND) |
|
|
|
av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
av_free(value); |
|
|
|
count++; |
|
|
|
} |
|
|
|
return count; |
|
|
|
} |
|
|
|
|
|
|
|
void av_opt_free(void *obj) |
|
|
|
{ |
|
|
|
const AVOption *o = NULL; |
|
|
|
@@ -986,6 +1071,37 @@ int main(void) |
|
|
|
av_freep(&test_ctx.string); |
|
|
|
} |
|
|
|
|
|
|
|
printf("\nTesting av_opt_set_from_string()\n"); |
|
|
|
{ |
|
|
|
TestContext test_ctx = { 0 }; |
|
|
|
const char *options[] = { |
|
|
|
"", |
|
|
|
"5", |
|
|
|
"5:hello", |
|
|
|
"5:hello:size=pal", |
|
|
|
"5:size=pal:hello", |
|
|
|
":", |
|
|
|
"=", |
|
|
|
" 5 : hello : size = pal ", |
|
|
|
"a_very_long_option_name_that_will_need_to_be_ellipsized_around_here=42" |
|
|
|
}; |
|
|
|
const char *shorthand[] = { "num", "string", NULL }; |
|
|
|
|
|
|
|
test_ctx.class = &test_class; |
|
|
|
av_opt_set_defaults(&test_ctx); |
|
|
|
test_ctx.string = av_strdup("default"); |
|
|
|
|
|
|
|
av_log_set_level(AV_LOG_DEBUG); |
|
|
|
|
|
|
|
for (i=0; i < FF_ARRAY_ELEMS(options); i++) { |
|
|
|
av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]); |
|
|
|
if (av_opt_set_from_string(&test_ctx, options[i], shorthand, "=", ":") < 0) |
|
|
|
av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]); |
|
|
|
printf("\n"); |
|
|
|
} |
|
|
|
av_freep(&test_ctx.string); |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
|