mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-03-02 02:30:58 +00:00
opt: implement av_opt_set_from_string().
It is similar to av_set_options_string() but accepts a list of options that can be in shorthand: if the key is omitted on the first fields, the keys from the shorthand list are assumed, in order.
This commit is contained in:
parent
5f1c3c785c
commit
438978fb4b
116
libavutil/opt.c
116
libavutil/opt.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -393,6 +393,36 @@ void av_opt_set_defaults2(void *s, int mask, int flags);
|
||||
int av_set_options_string(void *ctx, const char *opts,
|
||||
const char *key_val_sep, const char *pairs_sep);
|
||||
|
||||
/**
|
||||
* Parse the key=value pairs list in opts. For each key=value pair found,
|
||||
* set the value of the corresponding option in ctx.
|
||||
*
|
||||
* @param ctx the AVClass object to set options on
|
||||
* @param opts the options string, key-value pairs separated by a
|
||||
* delimiter
|
||||
* @param shorthand a NULL-terminated array of options names for shorthand
|
||||
* notation: if the first field in opts has no key part,
|
||||
* the key is taken from the first element of shorthand;
|
||||
* then again for the second, etc., until either opts is
|
||||
* finished, shorthand is finished or a named option is
|
||||
* found; after that, all options must be named
|
||||
* @param key_val_sep a 0-terminated list of characters used to separate
|
||||
* key from value, for example '='
|
||||
* @param pairs_sep a 0-terminated list of characters used to separate
|
||||
* two pairs from each other, for example ':' or ','
|
||||
* @return the number of successfully set key=value pairs, or a negative
|
||||
* value corresponding to an AVERROR code in case of error:
|
||||
* AVERROR(EINVAL) if opts cannot be parsed,
|
||||
* the error code issued by av_set_string3() if a key/value pair
|
||||
* cannot be set
|
||||
*
|
||||
* Options names must use only the following characters: a-z A-Z 0-9 - . / _
|
||||
* Separators must use characters distinct from from options and from each
|
||||
* other.
|
||||
*/
|
||||
int av_opt_set_from_string(void *ctx, const char *opts,
|
||||
const char *const *shorthand,
|
||||
const char *key_val_sep, const char *pairs_sep);
|
||||
/**
|
||||
* Free all string and binary options in obj.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user