diff options
author | Uoti Urpala <uau@mplayer2.org> | 2011-07-28 11:07:47 +0300 |
---|---|---|
committer | Uoti Urpala <uau@mplayer2.org> | 2011-07-29 05:50:38 +0300 |
commit | e873d703e956d3e2e68b9e18562983b029b5c7a8 (patch) | |
tree | 44a2c48ae4e94bd580ffd5833cd71a037af36043 | |
parent | d8374376c0d46ffab88b96eb32b52621c34f562c (diff) | |
download | mpv-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.
-rw-r--r-- | bstr.c | 49 | ||||
-rw-r--r-- | bstr.h | 57 | ||||
-rw-r--r-- | command.c | 3 | ||||
-rw-r--r-- | libmenu/menu.c | 3 | ||||
-rw-r--r-- | libmpcodecs/vf.c | 2 | ||||
-rw-r--r-- | m_config.c | 75 | ||||
-rw-r--r-- | m_config.h | 29 | ||||
-rw-r--r-- | m_option.c | 1093 | ||||
-rw-r--r-- | m_option.h | 18 | ||||
-rw-r--r-- | m_property.c | 3 | ||||
-rw-r--r-- | m_struct.c | 11 | ||||
-rw-r--r-- | m_struct.h | 6 | ||||
-rw-r--r-- | osdep/macosx_finder_args.c | 2 | ||||
-rw-r--r-- | parser-cfg.c | 2 | ||||
-rw-r--r-- | parser-mpcmd.c | 16 | ||||
-rw-r--r-- | playtree.c | 4 | ||||
-rw-r--r-- | stream/stream.c | 2 |
17 files changed, 685 insertions, 690 deletions
@@ -20,6 +20,7 @@ #include <libavutil/avutil.h> #include <assert.h> #include <ctype.h> +#include <stdarg.h> #include "talloc.h" @@ -71,6 +72,15 @@ int bstrrchr(struct bstr str, int c) return -1; } +int bstrcspn(struct bstr str, const char *reject) +{ + int i; + for (i = 0; i < str.len; i++) + if (strchr(reject, str.start[i])) + break; + return i; +} + int bstr_find(struct bstr haystack, struct bstr needle) { for (int i = 0; i < haystack.len; i++) @@ -96,21 +106,18 @@ struct bstr bstr_strip(struct bstr str) return str; } -struct bstr bstr_split(struct bstr str, char *sep, struct bstr *rest) +struct bstr bstr_split(struct bstr str, const char *sep, struct bstr *rest) { - int start, end; + int start; for (start = 0; start < str.len; start++) if (!strchr(sep, str.start[start])) break; - for (end = start; end < str.len; end++) - if (strchr(sep, str.start[end])) - break; + str = bstr_cut(str, start); + int end = bstrcspn(str, sep); if (rest) { *rest = bstr_cut(str, end); } - str.start += start; - str.len = end - start; - return str; + return bstr_splice(str, 0, end); } @@ -131,6 +138,7 @@ struct bstr bstr_splice(struct bstr str, int start, int end) long long bstrtoll(struct bstr str, struct bstr *rest, int base) { + str = bstr_lstrip(str); char buf[51]; int len = FFMIN(str.len, 50); memcpy(buf, str.start, len); @@ -142,6 +150,20 @@ long long bstrtoll(struct bstr str, struct bstr *rest, int base) return r; } +double bstrtod(struct bstr str, struct bstr *rest) +{ + str = bstr_lstrip(str); + char buf[101]; + int len = FFMIN(str.len, 100); + memcpy(buf, str.start, len); + buf[len] = 0; + char *endptr; + double r = strtod(buf, &endptr); + if (rest) + *rest = bstr_cut(str, endptr - buf); + return r; +} + struct bstr *bstr_splitlines(void *talloc_ctx, struct bstr str) { if (str.len == 0) @@ -169,3 +191,14 @@ void bstr_lower(struct bstr str) for (int i = 0; i < str.len; i++) str.start[i] = tolower(str.start[i]); } + +int bstr_sscanf(struct bstr str, const char *format, ...) +{ + char *ptr = bstrdup0(NULL, str); + va_list va; + va_start(va, format); + int ret = vsscanf(ptr, format, va); + va_end(va); + talloc_free(ptr); + return ret; +} @@ -34,22 +34,45 @@ struct bstr { size_t len; }; +// demux_rtp.cpp (live555) C++ compilation workaround +#ifndef __cplusplus +static inline char *bstrdup0(void *talloc_ctx, struct bstr str) +{ + return talloc_strndup(talloc_ctx, (char *)str.start, str.len); +} + +static inline struct bstr bstrdup(void *talloc_ctx, struct bstr str) +{ + struct bstr r = { talloc_strndup(talloc_ctx, str.start, str.len), str.len }; + return r; +} + +static inline struct bstr bstr(const unsigned char *s) +{ + return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0}; +} + int bstrcmp(struct bstr str1, struct bstr str2); int bstrcasecmp(struct bstr str1, struct bstr str2); int bstrchr(struct bstr str, int c); int bstrrchr(struct bstr str, int c); +int bstrcspn(struct bstr str, const char *reject); int bstr_find(struct bstr haystack, struct bstr needle); struct bstr *bstr_splitlines(void *talloc_ctx, struct bstr str); struct bstr bstr_lstrip(struct bstr str); struct bstr bstr_strip(struct bstr str); -struct bstr bstr_split(struct bstr str, char *sep, struct bstr *rest); +struct bstr bstr_split(struct bstr str, const char *sep, struct bstr *rest); struct bstr bstr_splice(struct bstr str, int start, int end); long long bstrtoll(struct bstr str, struct bstr *rest, int base); +double bstrtod(struct bstr str, struct bstr *rest); void bstr_lower(struct bstr str); +int bstr_sscanf(struct bstr str, const char *format, ...); static inline struct bstr bstr_cut(struct bstr str, int n) { + if (n > str.len) + n = str.len; return (struct bstr){str.start + n, str.len - n}; } @@ -60,22 +83,36 @@ static inline bool bstr_startswith(struct bstr str, struct bstr prefix) return !memcmp(str.start, prefix.start, prefix.len); } -// demux_rtp.cpp (live555) C++ compilation workaround -#ifndef __cplusplus -static inline char *bstrdup0(void *talloc_ctx, struct bstr str) +static inline bool bstr_startswith0(struct bstr str, const char *prefix) { - return talloc_strndup(talloc_ctx, (char *)str.start, str.len); + return bstr_startswith(str, bstr(prefix)); } -static inline struct bstr bstrdup(void *talloc_ctx, struct bstr str) +static inline bool bstr_endswith(struct bstr str, struct bstr suffix) { - struct bstr r = { talloc_strndup(talloc_ctx, str.start, str.len), str.len }; - return r; + if (str.len < suffix.len) + return false; + return !memcmp(str.start + str.len - suffix.len, suffix.start, suffix.len); } -static inline struct bstr bstr(const unsigned char *s) +static inline bool bstr_endswith0(struct bstr str, const char *suffix) { - return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0}; + return bstr_endswith(str, bstr(suffix)); +} + +static inline int bstrcmp0(struct bstr str1, const char *str2) +{ + return bstrcmp(str1, bstr(str2)); +} + +static inline int bstrcasecmp0(struct bstr str1, const char *str2) +{ + return bstrcasecmp(str1, bstr(str2)); +} + +static inline int bstr_find0(struct bstr haystack, const char *needle) +{ + return bstr_find(haystack, bstr(needle)); } #endif @@ -232,7 +232,8 @@ static int mp_property_generic_option(struct m_option *prop, int action, void *arg, MPContext *mpctx) { char *optname = prop->priv; - const struct m_option *opt = m_config_get_option(mpctx->mconfig, optname); + const struct m_option *opt = m_config_get_option(mpctx->mconfig, + bstr(optname)); void *valptr = m_option_get_ptr(opt, &mpctx->opts); switch (action) { diff --git a/libmenu/menu.c b/libmenu/menu.c index 0f920825b0..3e003900ce 100644 --- a/libmenu/menu.c +++ b/libmenu/menu.c @@ -208,7 +208,8 @@ static int menu_parse_config(char* buffer, struct m_config *mconfig) // Setup the attribs for(i = 0 ; attribs[2*i] ; i++) { if(strcasecmp(attribs[2*i],"name") == 0) continue; - if(!m_struct_set(&minfo->priv_st,menu_list[menu_count].cfg,attribs[2*i], attribs[2*i+1])) + if (!m_struct_set(&minfo->priv_st, menu_list[menu_count].cfg, + attribs[2*i], bstr(attribs[2*i+1]))) mp_tmsg(MSGT_GLOBAL,MSGL_WARN,"[MENU] bad attribute %s=%s in menu '%s' at line %d\n",attribs[2*i],attribs[2*i+1], name,parser->line); } diff --git a/libmpcodecs/vf.c b/libmpcodecs/vf.c index bb9ebff7b4..7c84a49ef0 100644 --- a/libmpcodecs/vf.c +++ b/libmpcodecs/vf.c @@ -455,7 +455,7 @@ struct vf_instance *vf_open_plugin_noerr(struct MPOpts *opts, void* vf_priv = m_struct_alloc(st); int n; for(n = 0 ; args && args[2*n] ; n++) - m_struct_set(st,vf_priv,args[2*n],args[2*n+1]); + m_struct_set(st, vf_priv, args[2*n], bstr(args[2*n+1])); vf->priv = vf_priv; args = NULL; } else // Otherwise we should have the '_oldargs_' diff --git a/m_config.c b/m_config.c index b278877c3c..3cf8c721ac 100644 --- a/m_config.c +++ b/m_config.c @@ -36,13 +36,13 @@ #define MAX_PROFILE_DEPTH 20 -static int parse_profile(const struct m_option *opt, const char *name, - const char *param, bool ambiguous_param, void *dst) +static int parse_profile(const struct m_option *opt, struct bstr name, + struct bstr param, bool ambiguous_param, void *dst) { struct m_config *config = opt->priv; char **list = NULL; int i, r; - if (param && !strcmp(param, "help")) { + if (!bstrcmp0(param, "help")) { struct m_profile *p; if (!config->profiles) { mp_tmsg(MSGT_CFGPARSER, MSGL_INFO, @@ -387,36 +387,37 @@ int m_config_register_options(struct m_config *config, } static struct m_config_option *m_config_get_co(const struct m_config *config, - char *arg) + struct bstr name) { struct m_config_option *co; for (co = config->opts; co; co = co->next) { - int l = strlen(co->name) - 1; - if ((co->opt->type->flags & M_OPT_TYPE_ALLOW_WILDCARD) && - (co->name[l] == '*')) { - if (strncasecmp(co->name, arg, l) == 0) + struct bstr coname = bstr(co->name); + if ((co->opt->type->flags & M_OPT_TYPE_ALLOW_WILDCARD) + && bstr_endswith0(coname, "*")) { + coname.len--; + if (bstrcasecmp(bstr_splice(name, 0, coname.len), coname) == 0) return co; - } else if (strcasecmp(co->name, arg) == 0) + } else if (bstrcasecmp(coname, name) == 0) return co; } return NULL; } -static int m_config_parse_option(const struct m_config *config, char *arg, - char *param, bool ambiguous_param, bool set) +static int m_config_parse_option(const struct m_config *config, + struct bstr name, struct bstr param, + bool ambiguous_param, bool set) { struct m_config_option *co; int r = 0; assert(config != NULL); assert(config->lvl > 0); - assert(arg != NULL); + assert(name.len != 0); - co = m_config_get_co(config, arg); - if (!co) { + co = m_config_get_co(config, name); + if (!co) return M_OPT_UNKNOWN; - } // This is the only mandatory function assert(co->opt->type->parse); @@ -424,12 +425,14 @@ static int m_config_parse_option(const struct m_config *config, char *arg, // Check if this option isn't forbidden in the current mode if ((config->mode == M_CONFIG_FILE) && (co->opt->flags & M_OPT_NOCFG)) { mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, - "The %s option can't be used in a config file.\n", arg); + "The %.*s option can't be used in a config file.\n", + BSTR_P(name)); return M_OPT_INVALID; } if ((config->mode == M_COMMAND_LINE) && (co->opt->flags & M_OPT_NOCMD)) { mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, - "The %s option can't be used on the command line.\n", arg); + "The %.*s option can't be used on the command line.\n", + BSTR_P(name)); return M_OPT_INVALID; } // During command line preparse set only pre-parse options @@ -445,7 +448,7 @@ static int m_config_parse_option(const struct m_config *config, char *arg, char **lst = NULL; int i, sr; // Parse the child options - r = m_option_parse(co->opt, arg, param, false, &lst); + r = m_option_parse(co->opt, name, param, false, &lst); // Set them now if (r >= 0) for (i = 0; lst && lst[2 * i]; i++) { @@ -454,8 +457,9 @@ static int m_config_parse_option(const struct m_config *config, char *arg, // Build the full name char n[l]; sprintf(n, "%s:%s", co->name, lst[2 * i]); - sr = m_config_parse_option(config, n, lst[2 * i + 1], - false, set); + sr = m_config_parse_option(config, bstr(n), + bstr(lst[2 * i + 1]), false, + set); if (sr < 0) { if (sr == M_OPT_UNKNOWN) { mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, @@ -476,7 +480,7 @@ static int m_config_parse_option(const struct m_config *config, char *arg, } talloc_free(lst); } else - r = m_option_parse(co->opt, arg, param, ambiguous_param, + r = m_option_parse(co->opt, name, param, ambiguous_param, set ? co->slots->data : NULL); // Parsing failed ? @@ -491,22 +495,24 @@ static int m_config_parse_option(const struct m_config *config, char *arg, return r; } -int m_config_set_option(struct m_config *config, char *arg, - char *param, bool ambiguous_param) +int m_config_set_option(struct m_config *config, struct bstr name, + struct bstr param, bool ambiguous_param) { - mp_msg(MSGT_CFGPARSER, MSGL_DBG2, "Setting %s=%s\n", arg, param); - return m_config_parse_option(config, arg, param, ambiguous_param, 1); + mp_msg(MSGT_CFGPARSER, MSGL_DBG2, "Setting %.*s=%.*s\n", BSTR_P(name), + BSTR_P(param)); + return m_config_parse_option(config, name, param, ambiguous_param, 1); } -int m_config_check_option(const struct m_config *config, char *arg, - char *param, bool ambiguous_param) +int m_config_check_option(const struct m_config *config, struct bstr name, + struct bstr param, bool ambiguous_param) { int r; - mp_msg(MSGT_CFGPARSER, MSGL_DBG2, "Checking %s=%s\n", arg, param); - r = m_config_parse_option(config, arg, param, ambiguous_param, 0); + mp_msg(MSGT_CFGPARSER, MSGL_DBG2, "Checking %.*s=%.*s\n", BSTR_P(name), + BSTR_P(param)); + r = m_config_parse_option(config, name, param, ambiguous_param, 0); if (r == M_OPT_MISSING_PARAM) { mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, - "Error: option '%s' must have a parameter!\n", arg); + "Error: option '%.*s' must have a parameter!\n", BSTR_P(name)); return M_OPT_INVALID; } return r; @@ -514,15 +520,14 @@ int m_config_check_option(const struct m_config *config, char *arg, const struct m_option *m_config_get_option(const struct m_config *config, - char *arg) + struct bstr name) { struct m_config_option *co; assert(config != NULL); assert(config->lvl > 0); - assert(arg != NULL); - co = m_config_get_co(config, arg); + co = m_config_get_co(config, name); if (co) return co->opt; else @@ -597,7 +602,7 @@ void m_profile_set_desc(struct m_profile *p, char *desc) int m_config_set_profile_option(struct m_config *config, struct m_profile *p, char *name, char *val) { - int i = m_config_check_option(config, name, val, false); + int i = m_config_check_option0(config, name, val, false); if (i < 0) return i; p->opts = talloc_realloc(p, p->opts, char *, 2 * (p->num_opts + 2)); @@ -620,7 +625,7 @@ void m_config_set_profile(struct m_config *config, struct m_profile *p) config->mode = M_CONFIG_FILE; config->profile_depth++; for (i = 0; i < p->num_opts; i++) - m_config_set_option(config, p->opts[2 * i], p->opts[2 * i + 1], false); + m_config_set_option0(config, p->opts[2 * i], p->opts[2 * i + 1], false); config->profile_depth--; config->mode = prev_mode; } diff --git a/m_config.h b/m_config.h index d2c3b9ee4e..75dd85ac14 100644 --- a/m_config.h +++ b/m_config.h @@ -21,6 +21,7 @@ #include <stdbool.h> +#include "bstr.h" // m_config provides an API to manipulate the config variables in MPlayer. // It makes use of the Options API to provide a context stack that @@ -129,28 +130,42 @@ int m_config_register_options(struct m_config *config, /* Set an option. * \param config The config object. - * \param arg The option's name. + * \param name The option's name. * \param param The value of the option, can be NULL. * \param ambiguous_param: old style cmdline option, "param" may be a parameter to this option or something entirely unrelated * \return See \ref OptionParserReturn. */ -int m_config_set_option(struct m_config *config, char *arg, - char *param, bool ambiguous_param); +int m_config_set_option(struct m_config *config, struct bstr name, + struct bstr param, bool ambiguous_param); + +static inline int m_config_set_option0(struct m_config *config, + const char *name, const char *param, + bool ambiguous) +{ + return m_config_set_option(config, bstr(name), bstr(param), ambiguous); +} /* Check if an option setting is valid. * Same as above m_config_set_option() but doesn't actually set anything. */ -int m_config_check_option(const struct m_config *config, char *arg, - char *param, bool ambiguous_param); +int m_config_check_option(const struct m_config *config, struct bstr name, + struct bstr param, bool ambiguous_param); + +static inline int m_config_check_option0(struct m_config *config, + const char *name, const char *param, + bool ambiguous) +{ + return m_config_check_option(config, bstr(name), bstr(param), ambiguous); +} /* Get the option matching the given name. * \param config The config object. - * \param arg The option's name. + * \param name The option's name. */ const struct m_option *m_config_get_option(const struct m_config *config, - char *arg); + struct bstr name); /* Print a list of all registered options. * \param config The config object. 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)) |