summaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--bstr.c49
-rw-r--r--bstr.h57
-rw-r--r--command.c3
-rw-r--r--libmenu/menu.c3
-rw-r--r--libmpcodecs/vf.c2
-rw-r--r--m_config.c75
-rw-r--r--m_config.h29
-rw-r--r--m_option.c1093
-rw-r--r--m_option.h18
-rw-r--r--m_property.c3
-rw-r--r--m_struct.c11
-rw-r--r--m_struct.h6
-rw-r--r--osdep/macosx_finder_args.c2
-rw-r--r--parser-cfg.c2
-rw-r--r--parser-mpcmd.c16
-rw-r--r--playtree.c4
-rw-r--r--stream/stream.c2
17 files changed, 685 insertions, 690 deletions
diff --git a/bstr.c b/bstr.c
index 2b40be399c..a2a49cc371 100644
--- a/bstr.c
+++ b/bstr.c
@@ -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;
+}
diff --git a/bstr.h b/bstr.h
index 1d26cb2728..1344f0d443 100644
--- a/bstr.h
+++ b/bstr.h
@@ -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
diff --git a/command.c b/command.c
index fda7c25626..4b502b3cc9 100644
--- a/command.c
+++ b/command.c
@@ -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 mus