summaryrefslogtreecommitdiffstats
path: root/m_option.c
diff options
context:
space:
mode:
authorUoti Urpala <uau@mplayer2.org>2011-07-28 11:07:47 +0300
committerUoti Urpala <uau@mplayer2.org>2011-07-29 05:50:38 +0300
commite873d703e956d3e2e68b9e18562983b029b5c7a8 (patch)
tree44a2c48ae4e94bd580ffd5833cd71a037af36043 /m_option.c
parentd8374376c0d46ffab88b96eb32b52621c34f562c (diff)
downloadmpv-e873d703e956d3e2e68b9e18562983b029b5c7a8.tar.bz2
mpv-e873d703e956d3e2e68b9e18562983b029b5c7a8.tar.xz
options: change option parsing to use bstr
Using bstr allows simpler parsing code, especially because it avoids the need to modify or copy strings just to terminate extracted substrings.
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);