summaryrefslogtreecommitdiffstats
path: root/m_option.c
diff options
context:
space:
mode:
Diffstat (limited to 'm_option.c')
-rw-r--r--m_option.c1093
1 files changed, 501 insertions, 592 deletions
diff --git a/m_option.c b/m_option.c
index a1cc139f8d..64a06d8971 100644
--- a/m_option.c
+++ b/m_option.c
@@ -28,6 +28,7 @@
#include <stdarg.h>
#include <inttypes.h>
#include <unistd.h>
+#include <assert.h>
#include "talloc.h"
#include "m_option.h"
@@ -35,22 +36,27 @@
#include "stream/url.h"
#include "libavutil/avstring.h"
-const m_option_t *m_option_list_find(const m_option_t *list, const char *name)
+static const struct m_option *m_option_list_findb(const struct m_option *list,
+ struct bstr name)
{
- int i;
-
- for (i = 0; list[i].name; i++) {
- int l = strlen(list[i].name) - 1;
+ for (int i = 0; list[i].name; i++) {
+ struct bstr lname = bstr(list[i].name);
if ((list[i].type->flags & M_OPT_TYPE_ALLOW_WILDCARD)
- && (l > 0) && (list[i].name[l] == '*')) {
- if (strncasecmp(list[i].name, name, l) == 0)
+ && bstr_endswith0(lname, "*")) {
+ lname.len--;
+ if (bstrcasecmp(bstr_splice(name, 0, lname.len), lname) == 0)
return &list[i];
- } else if (strcasecmp(list[i].name, name) == 0)
+ } else if (bstrcasecmp(lname, name) == 0)
return &list[i];
}
return NULL;
}
+const m_option_t *m_option_list_find(const m_option_t *list, const char *name)
+{
+ return m_option_list_findb(list, bstr(name));
+}
+
// Default function that just does a memcpy
static void copy_opt(const m_option_t *opt, void *dst, const void *src)
@@ -63,42 +69,32 @@ static void copy_opt(const m_option_t *opt, void *dst, const void *src)
#define VAL(x) (*(int *)(x))
-static int parse_flag(const m_option_t *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_flag(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
- if (param && !ambiguous_param) {
- if (!strcasecmp(param, "yes") || /* any other language? */
- !strcasecmp(param, "on") ||
- !strcasecmp(param, "ja") ||
- !strcasecmp(param, "si") ||
- !strcasecmp(param, "igen") ||
- !strcasecmp(param, "y") ||
- !strcasecmp(param, "j") ||
- !strcasecmp(param, "i") ||
- !strcasecmp(param, "tak") ||
- !strcasecmp(param, "ja") ||
- !strcasecmp(param, "true") ||
- !strcmp(param, "1")) {
- if (dst)
- VAL(dst) = opt->max;
- } else if (!strcasecmp(param, "no") ||
- !strcasecmp(param, "off") ||
- !strcasecmp(param, "nein") ||
- !strcasecmp(param, "nicht") ||
- !strcasecmp(param, "nem") ||
- !strcasecmp(param, "n") ||
- !strcasecmp(param, "nie") ||
- !strcasecmp(param, "nej") ||
- !strcasecmp(param, "false") ||
- !strcmp(param, "0")) {
- if (dst)
- VAL(dst) = opt->min;
- } else {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Invalid parameter for %s flag: %s\n", name, param);
- return M_OPT_INVALID;
+ if (param.len && !ambiguous_param) {
+ char * const enable[] = { "yes", "on", "ja", "si", "igen", "y", "j",
+ "i", "tak", "ja", "true", "1" };
+ for (int i = 0; i < sizeof(enable) / sizeof(enable[0]); i++) {
+ if (!bstrcasecmp0(param, enable[i])) {
+ if (dst)
+ VAL(dst) = opt->max;
+ return 1;
+ }
}
- return 1;
+ char * const disable[] = { "no", "off", "nein", "nicht", "nem", "n",
+ "nie", "nej", "false", "0" };
+ for (int i = 0; i < sizeof(disable) / sizeof(disable[0]); i++) {
+ if (!bstrcasecmp0(param, disable[i])) {
+ if (dst)
+ VAL(dst) = opt->min;
+ return 1;
+ }
+ }
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR,
+ "Invalid parameter for %.*s flag: %.*s\n",
+ BSTR_P(name), BSTR_P(param));
+ return M_OPT_INVALID;
} else {
if (dst)
VAL(dst) = opt->max;
@@ -129,48 +125,64 @@ const m_option_type_t m_option_type_flag = {
// Integer
-static int parse_int(const m_option_t *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_longlong(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
- long long tmp_int;
- char *endptr;
-
- if (param == NULL)
+ if (param.len == 0)
return M_OPT_MISSING_PARAM;
- tmp_int = strtoll(param, &endptr, 10);
- if (*endptr)
- tmp_int = strtoll(param, &endptr, 0);
- if (*endptr) {
+ struct bstr rest;
+ long long tmp_int = bstrtoll(param, &rest, 10);
+ if (rest.len)
+ tmp_int = bstrtoll(param, &rest, 0);
+ if (rest.len) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "The %s option must be an integer: %s\n", name, param);
+ "The %.*s option must be an integer: %.*s\n",
+ BSTR_P(name), BSTR_P(param));
return M_OPT_INVALID;
}
if ((opt->flags & M_OPT_MIN) && (tmp_int < opt->min)) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "The %s option must be >= %d: %s\n",
- name, (int) opt->min, param);
+ "The %.*s option must be >= %d: %.*s\n",
+ BSTR_P(name), (int) opt->min, BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
if ((opt->flags & M_OPT_MAX) && (tmp_int > opt->max)) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "The %s option must be <= %d: %s\n",
- name, (int) opt->max, param);
+ "The %.*s option must be <= %d: %.*s\n",
+ BSTR_P(name), (int) opt->max, BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
- if (dst) {
- if (opt->type->size == sizeof(int64_t))
- *(int64_t *)dst = tmp_int;
- else
- VAL(dst) = tmp_int;
- }
+ if (dst)
+ *(long long *)dst = tmp_int;
return 1;
}
+static int parse_int(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
+{
+ long long tmp;
+ int r = parse_longlong(opt, name, param, false, &tmp);
+ if (r >= 0 && dst)
+ *(int *)dst = tmp;
+ return r;
+}
+
+static int parse_int64(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
+{
+ long long tmp;
+ int r = parse_longlong(opt, name, param, false, &tmp);
+ if (r >= 0 && dst)
+ *(int64_t *)dst = tmp;
+ return r;
+}
+
+
static char *print_int(const m_option_t *opt, const void *val)
{
if (opt->type->size == sizeof(int64_t))
@@ -196,7 +208,7 @@ const m_option_type_t m_option_type_int64 = {
"",
sizeof(int64_t),
0,
- parse_int,
+ parse_int64,
print_int,
copy_opt,
copy_opt,
@@ -204,28 +216,25 @@ const m_option_type_t m_option_type_int64 = {
NULL
};
-static int parse_intpair(const struct m_option *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_intpair(const struct m_option *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
- if (param == NULL)
+ if (param.len == 0)
return M_OPT_MISSING_PARAM;
- char *s = (char *)param;
- int start = -1;
+ struct bstr s = param;
int end = -1;
- if (*s) {
- start = strtol(s, &s, 10);
- if (s == param)
- goto bad;
- }
- if (*s) {
- if (*s != '-')
+ int start = bstrtoll(s, &s, 10);
+ if (s.len == param.len)
+ goto bad;
+ if (s.len > 0) {
+ if (!bstr_startswith0(s, "-"))
goto bad;
- s++;
+ s = bstr_cut(s, 1);
}
- if (*s)
- end = strtol(s, &s, 10);
- if (*s)
+ if (s.len > 0)
+ end = bstrtoll(s, &s, 10);
+ if (s.len > 0)
goto bad;
if (dst) {
@@ -238,7 +247,8 @@ static int parse_intpair(const struct m_option *opt, const char *name,
bad:
mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid integer range "
- "specification for option %s: %s\n", name, param);
+ "specification for option %.*s: %.*s\n",
+ BSTR_P(name), BSTR_P(param));
return M_OPT_INVALID;
}
@@ -250,19 +260,20 @@ const struct m_option_type m_option_type_intpair = {
.set = copy_opt,
};
-static int parse_choice(const struct m_option *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_choice(const struct m_option *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
- if (param == NULL)
+ if (param.len == 0)
return M_OPT_MISSING_PARAM;
struct m_opt_choice_alternatives *alt;
for (alt = opt->priv; alt->name; alt++)
- if (!strcmp(param, alt->name))
+ if (!bstrcmp0(param, alt->name))
break;
if (!alt->name) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid value for option %s: %s\n",
- name, param);
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR,
+ "Invalid value for option %.*s: %.*s\n",
+ BSTR_P(name), BSTR_P(param));
mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Valid values are:");
for (alt = opt->priv; alt->name; alt++)
mp_msg(MSGT_CFGPARSER, MSGL_ERR, " %s", alt->name);
@@ -299,54 +310,54 @@ const struct m_option_type m_option_type_choice = {
#undef VAL
#define VAL(x) (*(double *)(x))
-static int parse_double(const m_option_t *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_double(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
- double tmp_float;
- char *endptr;
-
- if (param == NULL)
+ if (param.len == 0)
return M_OPT_MISSING_PARAM;
- tmp_float = strtod(param, &endptr);
+ struct bstr rest;
+ double tmp_float = bstrtod(param, &rest);
- switch (*endptr) {
+ switch (rest.len ? rest.start[0] : 0) {
case ':':
case '/':
- tmp_float /= strtod(endptr + 1, &endptr);
+ tmp_float /= bstrtod(bstr_cut(rest, 1), &rest);
break;
case '.':
case ',':
/* we also handle floats specified with
* non-locale decimal point ::atmos
*/
+ rest = bstr_cut(rest, 1);
if (tmp_float < 0)
- tmp_float -= 1.0 / pow(10, strlen(endptr + 1)) *
- strtod(endptr + 1, &endptr);
+ tmp_float -= 1.0 / pow(10, rest.len) * bstrtod(rest, &rest);
else
- tmp_float += 1.0 / pow(10, strlen(endptr + 1)) *
- strtod(endptr + 1, &endptr);
+ tmp_float += 1.0 / pow(10, rest.len) * bstrtod(rest, &rest);
break;
}
- if (*endptr) {
+ if (rest.len) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "The %s option must be a floating point number or a "
- "ratio (numerator[:/]denominator): %s\n", name, param);
+ "The %.*s option must be a floating point number or a "
+ "ratio (numerator[:/]denominator): %.*s\n",
+ BSTR_P(name), BSTR_P(param));
return M_OPT_INVALID;
}
if (opt->flags & M_OPT_MIN)
if (tmp_float < opt->min) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "The %s option must be >= %f: %s\n", name, opt->min, param);
+ "The %.*s option must be >= %f: %.*s\n",
+ BSTR_P(name), opt->min, BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
if (opt->flags & M_OPT_MAX)
if (tmp_float > opt->max) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "The %s option must be <= %f: %s\n", name, opt->max, param);
+ "The %.*s option must be <= %f: %.*s\n",
+ BSTR_P(name), opt->max, BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
@@ -377,8 +388,8 @@ const m_option_type_t m_option_type_double = {
#undef VAL
#define VAL(x) (*(float *)(x))
-static int parse_float(const m_option_t *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_float(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
double tmp;
int r = parse_double(opt, name, param, false, &tmp);
@@ -410,40 +421,14 @@ const m_option_type_t m_option_type_float = {
#undef VAL
#define VAL(x) (*(off_t *)(x))
-static int parse_position(const m_option_t *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_position(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
- off_t tmp_off;
- char dummy;
-
- if (param == NULL)
- return M_OPT_MISSING_PARAM;
- if (sscanf(param, sizeof(off_t) == sizeof(int) ?
- "%d%c" : "%"PRId64"%c", &tmp_off, &dummy) != 1) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "The %s option must be an integer: %s\n", opt->name, param);
- return M_OPT_INVALID;
- }
-
- if (opt->flags & M_OPT_MIN)
- if (tmp_off < opt->min) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "The %s option must be >= %"PRId64 ": %s\n",
- name, (int64_t) opt->min, param);
- return M_OPT_OUT_OF_RANGE;
- }
-
- if (opt->flags & M_OPT_MAX)
- if (tmp_off > opt->max) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "The %s option must be <= %"PRId64 ": %s\n",
- name, (int64_t) opt->max, param);
- return M_OPT_OUT_OF_RANGE;
- }
-
- if (dst)
- VAL(dst) = tmp_off;
- return 1;
+ long long tmp;
+ int r = parse_longlong(opt, name, param, false, &tmp);
+ if (r >= 0 && dst)
+ *(off_t *)dst = tmp;
+ return r;
}
static char *print_position(const m_option_t *opt, const void *val)
@@ -470,29 +455,26 @@ const m_option_type_t m_option_type_position = {
#undef VAL
#define VAL(x) (*(char **)(x))
-static int parse_str(const m_option_t *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_str(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
-
-
- if (param == NULL)
- return M_OPT_MISSING_PARAM;
-
- if ((opt->flags & M_OPT_MIN) && (strlen(param) < opt->min)) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Parameter must be >= %d chars: %s\n",
- (int) opt->min, param);
+ if ((opt->flags & M_OPT_MIN) && (param.len < opt->min)) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR,
+ "Parameter must be >= %d chars: %.*s\n",
+ (int) opt->min, BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
- if ((opt->flags & M_OPT_MAX) && (strlen(param) > opt->max)) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Parameter must be <= %d chars: %s\n",
- (int) opt->max, param);
+ if ((opt->flags & M_OPT_MAX) && (param.len > opt->max)) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR,
+ "Parameter must be <= %d chars: %.*s\n",
+ (int) opt->max, BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
if (dst) {
talloc_free(VAL(dst));
- VAL(dst) = talloc_strdup(NULL, param);
+ VAL(dst) = bstrdup0(NULL, param);
}
return 1;
@@ -640,39 +622,43 @@ static int str_list_del(char **del, int n, void *dst)
return 1;
}
-static char *get_nextsep(char *ptr, char sep, int modify)
+static struct bstr get_nextsep(struct bstr *ptr, char sep, bool modify)
{
- char *last_ptr = ptr;
+ struct bstr str = *ptr;
+ struct bstr orig = str;
for (;;) {
- ptr = strchr(ptr, sep);
- if (ptr && ptr > last_ptr && ptr[-1] == '\\') {
- if (modify)
- memmove(ptr - 1, ptr, strlen(ptr) + 1);
- else
- ptr++;
- } else
+ int idx = bstrchr(str, sep);
+ if (idx > 0 && str.start[idx - 1] == '\\') {
+ if (modify) {
+ memmove(str.start + idx - 1, str.start + idx, str.len - idx);
+ str.len--;
+ str = bstr_cut(str, idx);
+ } else
+ str = bstr_cut(str, idx + 1);
+ } else {
+ str = bstr_cut(str, idx < 0 ? str.len : idx);
break;
+ }
}
- return ptr;
+ *ptr = str;
+ return bstr_splice(orig, 0, str.start - orig.start);
}
-static int parse_str_list(const m_option_t *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_str_list(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
- int n = 0, len = strlen(opt->name);
- char *str;
- char *ptr = (char *)param, *last_ptr, **res;
+ char **res;
int op = OP_NONE;
-
- if (opt->name[len - 1] == '*' && ((int)strlen(name) > len - 1)) {
- const char *n = &name[len - 1];
- if (strcasecmp(n, "-add") == 0)
+ int len = strlen(opt->name);
+ if (opt->name[len - 1] == '*' && (name.len > len - 1)) {
+ struct bstr suffix = bstr_cut(name, len - 1);
+ if (bstrcasecmp0(suffix, "-add") == 0)
op = OP_ADD;
- else if (strcasecmp(n, "-pre") == 0)
+ else if (bstrcasecmp0(suffix, "-pre") == 0)
op = OP_PRE;
- else if (strcasecmp(n, "-del") == 0)
+ else if (bstrcasecmp0(suffix, "-del") == 0)
op = OP_DEL;
- else if (strcasecmp(n, "-clr") == 0)
+ else if (bstrcasecmp0(suffix, "-clr") == 0)
op = OP_CLR;
else
return M_OPT_UNKNOWN;
@@ -686,19 +672,17 @@ static int parse_str_list(const m_option_t *opt, const char *name,
}
// All other ops need a param
- if (param == NULL || strlen(param) == 0)
+ if (param.len == 0)
return M_OPT_MISSING_PARAM;
// custom type for "profile" calls this but uses ->priv for something else
char separator = opt->type == &m_option_type_string_list && opt->priv ?
*(char *)opt->priv : OPTION_LIST_SEPARATOR;
- while (ptr[0] != '\0') {
- ptr = get_nextsep(ptr, separator, 0);
- if (!ptr) {
- n++;
- break;
- }
- ptr++;
+ int n = 0;
+ struct bstr str = param;
+ while (str.len) {
+ get_nextsep(&str, separator, 0);
+ str = bstr_cut(str, 1);
n++;
}
if (n == 0)
@@ -711,24 +695,18 @@ static int parse_str_list(const m_option_t *opt, const char *name,
return 1;
res = talloc_array(NULL, char *, n + 2);
- ptr = str = talloc_strdup(NULL, param);
+ str = bstrdup(NULL, param);
+ char *ptr = str.start;
n = 0;
- while (1) {
- last_ptr = ptr;
- ptr = get_nextsep(ptr, separator, 1);
- if (!ptr) {
- res[n] = talloc_strdup(NULL, last_ptr);
- n++;
- break;
- }
- len = ptr - last_ptr;
- res[n] = talloc_strndup(NULL, last_ptr, len);
- ptr++;
+ while (str.len) {
+ struct bstr el = get_nextsep(&str, separator, 1);
+ res[n] = bstrdup0(NULL, el);
+ str = bstr_cut(str, 1);
n++;
}
res[n] = NULL;
- talloc_free(str);
+ talloc_free(ptr);
switch (op) {
case OP_ADD:
@@ -841,8 +819,8 @@ static void free_func_pf(void *src)
}
// Parser for func_param
-static int parse_func_pf(const m_option_t *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_func_pf(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
struct m_func_save *s, *p;
@@ -850,8 +828,8 @@ static int parse_func_pf(const m_option_t *opt, const char *name,
return 1;
s = talloc_zero(NULL, struct m_func_save);
- s->name = talloc_strdup(NULL, name);
- s->param = talloc_strdup(NULL, param);
+ s->name = bstrdup0(NULL, name);
+ s->param = bstrdup0(NULL, param);
p = VAL(dst);
if (p) {
@@ -924,8 +902,8 @@ const m_option_type_t m_option_type_func_param = {
#undef VAL
-static int parse_func(const m_option_t *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_func(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
return 0;
}
@@ -950,14 +928,19 @@ const m_option_type_t m_option_type_func = {
/////////////////// Print
-static int parse_print(const m_option_t *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_print(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
if (opt->type == CONF_TYPE_PRINT_INDIRECT)
mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", *(char **) opt->p);
- else if (opt->type == CONF_TYPE_PRINT_FUNC)
- return ((m_opt_func_full_t) opt->p)(opt, name, param);
- else
+ else if (opt->type == CONF_TYPE_PRINT_FUNC) {
+ char *name0 = bstrdup0(NULL, name);
+ char *param0 = bstrdup0(NULL, param);
+ int r = ((m_opt_func_full_t) opt->p)(opt, name0, param0);
+ talloc_free(name0);
+ talloc_free(param0);
+ return r;
+ } else
mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", mp_gtext(opt->p));
if (opt->priv == NULL)
@@ -1009,102 +992,84 @@ const m_option_type_t m_option_type_print_func = {
#undef VAL
#define VAL(x) (*(char ***)(x))
-static int parse_subconf(const m_option_t *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_subconf(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
- char *subparam;
- char *subopt;
- int nr = 0, i, r;
- const m_option_t *subopts;
- const char *p;
+ int nr = 0, i;
char **lst = NULL;
- if (param == NULL || strlen(param) == 0)
+ if (param.len == 0)
return M_OPT_MISSING_PARAM;
- subparam = talloc_size(NULL, strlen(param) + 1);
- subopt = talloc_size(NULL, strlen(param) + 1);
- p = param;
-
- subopts = opt->p;
-
- while (p[0]) {
- int sscanf_ret = 1;
- int optlen = strcspn(p, ":=");
- /* clear out */
- subopt[0] = subparam[0] = 0;
- av_strlcpy(subopt, p, optlen + 1);
- p = &p[optlen];
- if (p[0] == '=') {
- sscanf_ret = 2;
- p = &p[1];
- if (p[0] == '"') {
- p = &p[1];
- optlen = strcspn(p, "\"");
- av_strlcpy(subparam, p, optlen + 1);
- p = &p[optlen];
- if (p[0] != '"') {
+ struct bstr p = param;
+ const struct m_option *subopts = opt->p;
+
+ while (p.len) {
+ int optlen = bstrcspn(p, ":=");
+ struct bstr subopt = bstr_splice(p, 0, optlen);
+ struct bstr subparam = bstr(NULL);
+ p = bstr_cut(p, optlen);
+ if (bstr_startswith0(p, "=")) {
+ p = bstr_cut(p, 1);
+ if (bstr_startswith0(p, "\"")) {
+ p = bstr_cut(p, 1);
+ optlen = bstrcspn(p, "\"");
+ subparam = bstr_splice(p, 0, optlen);
+ p = bstr_cut(p, optlen);
+ if (!bstr_startswith0(p, "\"")) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Terminating '\"' missing for '%s'\n", subopt);
+ "Terminating '\"' missing for '%.*s'\n",
+ BSTR_P(subopt));
return M_OPT_INVALID;
}
- p = &p[1];
- } else if (p[0] == '%') {
- p = &p[1];
- optlen = (int)strtol(p, (char **)&p, 0);
- if (!p || p[0] != '%' || (optlen > strlen(p) - 1)) {
+ p = bstr_cut(p, 1);
+ } else if (bstr_startswith0(p, "%")) {
+ p = bstr_cut(p, 1);
+ optlen = bstrtoll(p, &p, 0);
+ if (!bstr_startswith0(p, "%") || (optlen > p.len - 1)) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Invalid length %i for '%s'\n", optlen, subopt);
+ "Invalid length %d for '%.*s'\n",
+ optlen, BSTR_P(subopt));
return M_OPT_INVALID;
}
- p = &p[1];
- av_strlcpy(subparam, p, optlen + 1);
- p = &p[optlen];
+ subparam = bstr_splice(p, 1, optlen + 1);
+ p = bstr_cut(p, optlen + 1);
} else {
- optlen = strcspn(p, ":");
- av_strlcpy(subparam, p, optlen + 1);
- p = &p[optlen];
+ optlen = bstrcspn(p, ":");
+ subparam = bstr_splice(p, 0, optlen);
+ p = bstr_cut(p, optlen);
}
}
- if (p[0] == ':')
- p = &p[1];
- else if (p[0]) {
+ if (bstr_startswith0(p, ":"))
+ p = bstr_cut(p, 1);
+ else if (p.len > 0) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Incorrect termination for '%s'\n", subopt);
+ "Incorrect termination for '%.*s'\n", BSTR_P(subopt));
return M_OPT_INVALID;
}
- switch (sscanf_ret) {
- case 1:
- subparam[0] = 0;
- case 2:
- for (i = 0; subopts[i].name; i++)
- if (!strcmp(subopts[i].name, subopt))
- break;
- if (!subopts[i].name) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Option %s: Unknown suboption %s\n", name, subopt);
- return M_OPT_UNKNOWN;
- }
- r = m_option_parse(&subopts[i], subopt,
- subparam[0] == 0 ? NULL : subparam, false,
- NULL);
- if (r < 0)
- return r;
- if (dst) {
- lst = talloc_realloc(NULL, lst, char *, 2 * (nr + 2));
- lst[2 * nr] = talloc_strdup(NULL, subopt);
- lst[2 * nr + 1] = subparam[0] == 0 ? NULL :
- talloc_strdup(NULL, subparam);
- memset(&lst[2 * (nr + 1)], 0, 2 * sizeof(char *));
- nr++;
- }
- break;
+ for (i = 0; subopts[i].name; i++)
+ if (!bstrcmp0(subopt, subopts[i].name))
+ break;
+ if (!subopts[i].name) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR,
+ "Option %.*s: Unknown suboption %.*s\n",
+ BSTR_P(name), BSTR_P(subopt));
+ return M_OPT_UNKNOWN;
+ }
+ int r = m_option_parse(&subopts[i], subopt, subparam, false, NULL);
+ if (r < 0)
+ return r;
+ if (dst) {
+ lst = talloc_realloc(NULL, lst, char *, 2 * (nr + 2));
+ lst[2 * nr] = bstrdup0(NULL, subopt);
+ lst[2 * nr + 1] = subparam.len == 0 ? NULL :
+ bstrdup0(NULL, subparam);
+ memset(&lst[2 * (nr + 1)], 0, 2 * sizeof(char *));
+ nr++;
}
}
- talloc_free(subparam);
- talloc_free(subopt);
if (dst)
VAL(dst) = lst;
@@ -1204,16 +1169,16 @@ static struct {
{ NULL, 0 }
};
-static int parse_imgfmt(const m_option_t *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_imgfmt(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
uint32_t fmt = 0;
int i;
- if (param == NULL || strlen(param) == 0)
+ if (param.len == 0)
return M_OPT_MISSING_PARAM;
- if (!strcmp(param, "help")) {
+ if (!bstrcmp0(param, "help")) {
mp_msg(MSGT_CFGPARSER, MSGL_INFO, "Available formats:");
for (i = 0; mp_imgfmt_list[i].name; i++)
mp_msg(MSGT_CFGPARSER, MSGL_INFO, " %s", mp_imgfmt_list[i].name);
@@ -1221,16 +1186,19 @@ static int parse_imgfmt(const m_option_t *opt, const char *name,
return M_OPT_EXIT - 1;
}
- if (sscanf(param, "0x%x", &fmt) != 1) {
+ if (bstr_startswith0(param, "0x"))
+ fmt = bstrtoll(param, NULL, 16);
+ else {
for (i = 0; mp_imgfmt_list[i].name; i++) {
- if (!strcasecmp(param, mp_imgfmt_list[i].name)) {
+ if (!bstrcasecmp0(param, mp_imgfmt_list[i].name)) {
fmt = mp_imgfmt_list[i].fmt;
break;
}
}
if (!mp_imgfmt_list[i].name) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Option %s: unknown format name: '%s'\n", name, param);
+ "Option %.*s: unknown format name: '%.*s'\n",
+ BSTR_P(name), BSTR_P(param));
return M_OPT_INVALID;
}
}
@@ -1296,16 +1264,16 @@ static struct {
{ NULL, 0 }
};
-static int parse_afmt(const m_option_t *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_afmt(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
uint32_t fmt = 0;
int i;
- if (param == NULL || strlen(param) == 0)
+ if (param.len == 0)
return M_OPT_MISSING_PARAM;
- if (!strcmp(param, "help")) {
+ if (!bstrcmp0(param, "help")) {
mp_msg(MSGT_CFGPARSER, MSGL_INFO, "Available formats:");
for (i = 0; mp_afmt_list[i].name; i++)
mp_msg(MSGT_CFGPARSER, MSGL_INFO, " %s", mp_afmt_list[i].name);
@@ -1313,16 +1281,19 @@ static int parse_afmt(const m_option_t *opt, const char *name,
return M_OPT_EXIT - 1;
}
- if (sscanf(param, "0x%x", &fmt) != 1) {
+ if (bstr_startswith0(param, "0x"))
+ fmt = bstrtoll(param, NULL, 16);
+ else {
for (i = 0; mp_afmt_list[i].name; i++) {
- if (!strcasecmp(param, mp_afmt_list[i].name)) {
+ if (!bstrcasecmp0(param, mp_afmt_list[i].name)) {
fmt = mp_afmt_list[i].fmt;
break;
}
}
if (!mp_afmt_list[i].name) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Option %s: unknown format name: '%s'\n", name, param);
+ "Option %.*s: unknown format name: '%.*s'\n",
+ BSTR_P(name), BSTR_P(param));
return M_OPT_INVALID;
}
}
@@ -1347,36 +1318,36 @@ const m_option_type_t m_option_type_afmt = {
};
-int parse_timestring(const char *str, double *time, char endchar)
+static int parse_timestring(struct bstr str, double *time, char endchar)
{
int a, b, len;
double d;
*time = 0; /* ensure initialization for error cases */
- if (sscanf(str, "%d:%d:%lf%n", &a, &b, &d, &len) >= 3)
+ if (bstr_sscanf(str, "%d:%d:%lf%n", &a, &b, &d, &len) >= 3)
*time = 3600 * a + 60 * b + d;
- else if (sscanf(str, "%d:%lf%n", &a, &d, &len) >= 2)
+ else if (bstr_sscanf(str, "%d:%lf%n", &a, &d, &len) >= 2)
*time = 60 * a + d;
- else if (sscanf(str, "%lf%n", &d, &len) >= 1)
+ else if (bstr_sscanf(str, "%lf%n", &d, &len) >= 1)
*time = d;
else
return 0; /* unsupported time format */
- if (str[len] && str[len] != endchar)
+ if (len < str.len && str.start[len] != endchar)
return 0; /* invalid extra characters at the end */
return len;
}
-static int parse_time(const m_option_t *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_time(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
double time;
- if (param == NULL || strlen(param) == 0)
+ if (param.len == 0)
return M_OPT_MISSING_PARAM;
if (!parse_timestring(param, &time, 0)) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid time: '%s'\n",
- name, param);
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %.*s: invalid time: '%.*s'\n",
+ BSTR_P(name), BSTR_P(param));
return M_OPT_INVALID;
}
@@ -1401,19 +1372,19 @@ const m_option_type_t m_option_type_time = {
// Time or size (-endpos)
-static int parse_time_size(const m_option_t *opt, const char *name,
- const char *param, bool ambiguous_param, void *dst)
+static int parse_time_size(const m_option_t *opt, struct bstr name,
+ struct bstr param, bool ambiguous_param, void *dst)
{
m_time_size_t ts;
char unit[4];
double end_at;
- if (param == NULL || strlen(param) == 0)
+ if (param.len == 0)
return M_OPT_MISSING_PARAM;
ts.pos = 0;
/* End at size parsing */
- if (sscanf(param, "%lf%3s", &end_at, unit) == 2) {
+ if (bstr_sscanf(param, "%lf%3s", &end_at, unit) == 2) {
ts.type = END_AT_SIZE;
if (!strcasecmp(unit, "b"))
;
@@ -1436,8 +1407,8 @@ static int parse_time_size(const m_option_t *opt, const char *name,
* even a number followed by garbage */
if (!parse_timestring(param, &end_at, 0)) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Option %s: invalid time or size: '%s'\n",
- name, param);
+ "Option %.*s: invalid time or size: '%.*s'\n",
+ BSTR_P(name), BSTR_P(param));
return M_OPT_INVALID;
}
@@ -1470,7 +1441,7 @@ cons