diff options
author | wm4 <wm4@nowhere> | 2013-12-17 02:02:25 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-12-17 02:07:57 +0100 |
commit | eb15151705d47d23da844449126cc6b4879f110e (patch) | |
tree | 661866ee9e73bc893c7963660aae01db503e99aa /mpvcore/m_option.c | |
parent | 793f85945fc07db905e54390c065ae51b9eeef9b (diff) | |
download | mpv-eb15151705d47d23da844449126cc6b4879f110e.tar.bz2 mpv-eb15151705d47d23da844449126cc6b4879f110e.tar.xz |
Move options/config related files from mpvcore/ to options/
Since m_option.h and options.h are extremely often included, a lot of
files have to be changed.
Moving path.c/h to options/ is a bit questionable, but since this is
mainly about access to config files (which are also handled in
options/), it's probably ok.
Diffstat (limited to 'mpvcore/m_option.c')
-rw-r--r-- | mpvcore/m_option.c | 2477 |
1 files changed, 0 insertions, 2477 deletions
diff --git a/mpvcore/m_option.c b/mpvcore/m_option.c deleted file mode 100644 index 85ac974861..0000000000 --- a/mpvcore/m_option.c +++ /dev/null @@ -1,2477 +0,0 @@ -/* - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/// \file -/// \ingroup Options - -#include "config.h" - -#include <stdlib.h> -#include <string.h> -#include <math.h> -#include <stdio.h> -#include <stdarg.h> -#include <limits.h> -#include <inttypes.h> -#include <unistd.h> -#include <ctype.h> -#include <assert.h> - -#include <libavutil/common.h> -#include <libavutil/avstring.h> - -#include "talloc.h" -#include "mpvcore/mp_common.h" -#include "mpvcore/m_option.h" -#include "mpvcore/m_config.h" -#include "mpvcore/mp_msg.h" - -char *m_option_strerror(int code) -{ - switch (code) { - case M_OPT_UNKNOWN: - return "option not found"; - case M_OPT_MISSING_PARAM: - return "option requires parameter"; - case M_OPT_INVALID: - return "option parameter could not be parsed"; - case M_OPT_OUT_OF_RANGE: - return "parameter is outside values allowed for option"; - case M_OPT_DISALLOW_PARAM: - return "option doesn't take a parameter"; - case M_OPT_PARSER_ERR: - default: - return "parser error"; - } -} - -int m_option_required_params(const m_option_t *opt) -{ - if (((opt->flags & M_OPT_OPTIONAL_PARAM) || - (opt->type->flags & M_OPT_TYPE_OPTIONAL_PARAM))) - return 0; - return 1; -} - -static const struct m_option *m_option_list_findb(const struct m_option *list, - struct bstr name) -{ - for (int i = 0; list[i].name; i++) { - struct bstr lname = bstr0(list[i].name); - if ((list[i].type->flags & M_OPT_TYPE_ALLOW_WILDCARD) - && bstr_endswith0(lname, "*")) { - lname.len--; - if (bstrcmp(bstr_splice(name, 0, lname.len), lname) == 0) - return &list[i]; - } else if (bstrcmp(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, bstr0(name)); -} - -// Default function that just does a memcpy - -static void copy_opt(const m_option_t *opt, void *dst, const void *src) -{ - if (dst && src) - memcpy(dst, src, opt->type->size); -} - -// Flag - -#define VAL(x) (*(int *)(x)) - -static int clamp_flag(const m_option_t *opt, void *val) -{ - if (VAL(val) == opt->min || VAL(val) == opt->max) - return 0; - VAL(val) = opt->min; - return M_OPT_OUT_OF_RANGE; -} - -static int parse_flag(const m_option_t *opt, struct bstr name, - struct bstr param, void *dst) -{ - if (param.len) { - if (!bstrcmp0(param, "yes")) { - if (dst) - VAL(dst) = opt->max; - return 1; - } - if (!bstrcmp0(param, "no")) { - 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; - return 0; - } -} - -static char *print_flag(const m_option_t *opt, const void *val) -{ - if (VAL(val) == opt->min) - return talloc_strdup(NULL, "no"); - else - return talloc_strdup(NULL, "yes"); -} - -static void add_flag(const m_option_t *opt, void *val, double add, bool wrap) -{ - if (fabs(add) < 0.5) - return; - bool state = VAL(val) != opt->min; - state = wrap ? !state : add > 0; - VAL(val) = state ? opt->max : opt->min; -} - -const m_option_type_t m_option_type_flag = { - // need yes or no in config files - .name = "Flag", - .size = sizeof(int), - .flags = M_OPT_TYPE_OPTIONAL_PARAM, - .parse = parse_flag, - .print = print_flag, - .copy = copy_opt, - .add = add_flag, - .clamp = clamp_flag, -}; - -// Single-value, write-only flag - -static int parse_store(const m_option_t *opt, struct bstr name, - struct bstr param, void *dst) -{ - if (param.len == 0 || bstrcmp0(param, "yes") == 0) { - if (dst) - VAL(dst) = opt->max; - return 0; - } else { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, - "Invalid parameter for %.*s flag: %.*s\n", - BSTR_P(name), BSTR_P(param)); - return M_OPT_DISALLOW_PARAM; - } -} - -const m_option_type_t m_option_type_store = { - // can only be activated - .name = "Flag", - .size = sizeof(int), - .flags = M_OPT_TYPE_OPTIONAL_PARAM, - .parse = parse_store, - .copy = copy_opt, -}; - -// Same for float types - -#undef VAL -#define VAL(x) (*(float *)(x)) - -static int parse_store_float(const m_option_t *opt, struct bstr name, - struct bstr param, void *dst) -{ - if (param.len == 0 || bstrcmp0(param, "yes") == 0) { - if (dst) - VAL(dst) = opt->max; - return 0; - } else { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, - "Invalid parameter for %.*s flag: %.*s\n", - BSTR_P(name), BSTR_P(param)); - return M_OPT_DISALLOW_PARAM; - } -} - -const m_option_type_t m_option_type_float_store = { - // can only be activated - .name = "Flag", - .size = sizeof(float), - .flags = M_OPT_TYPE_OPTIONAL_PARAM, - .parse = parse_store_float, - .copy = copy_opt, -}; - -// Integer - -#undef VAL - -static int clamp_longlong(const m_option_t *opt, void *val) -{ - long long v = *(long long *)val; - int r = 0; - if ((opt->flags & M_OPT_MAX) && (v > opt->max)) { - v = opt->max; - r = M_OPT_OUT_OF_RANGE; - } - if ((opt->flags & M_OPT_MIN) && (v < opt->min)) { - v = opt->min; - r = M_OPT_OUT_OF_RANGE; - } - *(long long *)val = v; - return r; -} - -static int parse_longlong(const m_option_t *opt, struct bstr name, - struct bstr param, void *dst) -{ - if (param.len == 0) - return M_OPT_MISSING_PARAM; - - 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", - 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", - 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", - BSTR_P(name), (int) opt->max, BSTR_P(param)); - return M_OPT_OUT_OF_RANGE; - } - - if (dst) - *(long long *)dst = tmp_int; - - return 1; -} - -static int clamp_int(const m_option_t *opt, void *val) -{ - long long tmp = *(int *)val; - int r = clamp_longlong(opt, &tmp); - *(int *)val = tmp; - return r; -} - -static int clamp_int64(const m_option_t *opt, void *val) -{ - long long tmp = *(int64_t *)val; - int r = clamp_longlong(opt, &tmp); - *(int64_t *)val = tmp; - return r; -} - -static int parse_int(const m_option_t *opt, struct bstr name, - struct bstr param, void *dst) -{ - long long tmp; - int r = parse_longlong(opt, name, param, &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, void *dst) -{ - long long tmp; - int r = parse_longlong(opt, name, param, &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)) - return talloc_asprintf(NULL, "%"PRId64, *(const int64_t *)val); - return talloc_asprintf(NULL, "%d", *(const int *)val); -} - -static void add_int64(const m_option_t *opt, void *val, double add, bool wrap) -{ - int64_t v = *(int64_t *)val; - - v = v + add; - - bool is64 = opt->type->size == sizeof(int64_t); - int64_t nmin = is64 ? INT64_MIN : INT_MIN; - int64_t nmax = is64 ? INT64_MAX : INT_MAX; - - int64_t min = (opt->flags & M_OPT_MIN) ? opt->min : nmin; - int64_t max = (opt->flags & M_OPT_MAX) ? opt->max : nmax; - - if (v < min) - v = wrap ? max : min; - if (v > max) - v = wrap ? min : max; - - *(int64_t *)val = v; -} - -static void add_int(const m_option_t *opt, void *val, double add, bool wrap) -{ - int64_t tmp = *(int *)val; - add_int64(opt, &tmp, add, wrap); - *(int *)val = tmp; -} - -static void multiply_int64(const m_option_t *opt, void *val, double f) -{ - double v = *(int64_t *)val * f; - int64_t iv = v; - if (v < INT64_MIN) - iv = INT64_MIN; - if (v > INT64_MAX) - iv = INT64_MAX; - *(int64_t *)val = iv; - clamp_int64(opt, val); -} - -static void multiply_int(const m_option_t *opt, void *val, double f) -{ - int64_t tmp = *(int *)val; - multiply_int64(opt, &tmp, f); - *(int *)val = MPCLAMP(tmp, INT_MIN, INT_MAX); -} - -const m_option_type_t m_option_type_int = { - .name = "Integer", - .size = sizeof(int), - .parse = parse_int, - .print = print_int, - .copy = copy_opt, - .add = add_int, - .multiply = multiply_int, - .clamp = clamp_int, -}; - -const m_option_type_t m_option_type_int64 = { - .name = "Integer64", - .size = sizeof(int64_t), - .parse = parse_int64, - .print = print_int, - .copy = copy_opt, - .add = add_int64, - .multiply = multiply_int64, - .clamp = clamp_int64, -}; - -static int parse_intpair(const struct m_option *opt, struct bstr name, - struct bstr param, void *dst) -{ - if (param.len == 0) - return M_OPT_MISSING_PARAM; - - struct bstr s = param; - int end = -1; - int start = bstrtoll(s, &s, 10); - if (s.len == param.len) - goto bad; - if (s.len > 0) { - if (!bstr_startswith0(s, "-")) - goto bad; - s = bstr_cut(s, 1); - } - if (s.len > 0) - end = bstrtoll(s, &s, 10); - if (s.len > 0) - goto bad; - - if (dst) { - int *p = dst; - p[0] = start; - p[1] = end; - } - - return 1; - -bad: - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid integer range " - "specification for option %.*s: %.*s\n", - BSTR_P(name), BSTR_P(param)); - return M_OPT_INVALID; -} - -const struct m_option_type m_option_type_intpair = { - .name = "Int[-Int]", - .size = sizeof(int[2]), - .parse = parse_intpair, - .copy = copy_opt, -}; - -static int clamp_choice(const m_option_t *opt, void *val) -{ - int v = *(int *)val; - if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) { - if (v >= opt->min && v <= opt->max) - return 0; - } - ; - for (struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) { - if (alt->value == v) - return 0; - } - return M_OPT_INVALID; -} - -static int parse_choice(const struct m_option *opt, struct bstr name, - struct bstr param, void *dst) -{ - struct m_opt_choice_alternatives *alt = opt->priv; - for ( ; alt->name; alt++) - if (!bstrcmp0(param, alt->name)) - break; - if (!alt->name) { - if (param.len == 0) - return M_OPT_MISSING_PARAM; - if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) { - long long val; - if (parse_longlong(opt, name, param, &val) == 1) { - if (dst) - *(int *)dst = val; - return 1; - } - } - 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); - if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) - mp_msg(MSGT_CFGPARSER, MSGL_ERR, " %g-%g", opt->min, opt->max); - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "\n"); - return M_OPT_INVALID; - } - if (dst) - *(int *)dst = alt->value; - - return 1; -} - -static char *print_choice(const m_option_t *opt, const void *val) -{ - int v = *(int *)val; - struct m_opt_choice_alternatives *alt; - for (alt = opt->priv; alt->name; alt++) - if (alt->value == v) - return talloc_strdup(NULL, alt->name); - if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) { - if (v >= opt->min && v <= opt->max) - return talloc_asprintf(NULL, "%d", v); - } - abort(); -} - -static void choice_get_min_max(const struct m_option *opt, int *min, int *max) -{ - assert(opt->type == &m_option_type_choice); - *min = INT_MAX; - *max = INT_MIN; - for (struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) { - *min = FFMIN(*min, alt->value); - *max = FFMAX(*max, alt->value); - } - if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) { - *min = FFMIN(*min, opt->min); - *max = FFMAX(*max, opt->max); - } -} - -static void check_choice(int dir, int val, bool *found, int *best, int choice) -{ - if ((dir == -1 && (!(*found) || choice > (*best)) && choice < val) || - (dir == +1 && (!(*found) || choice < (*best)) && choice > val)) - { - *found = true; - *best = choice; - } -} - -static void add_choice(const m_option_t *opt, void *val, double add, bool wrap) -{ - assert(opt->type == &m_option_type_choice); - int dir = add > 0 ? +1 : -1; - bool found = false; - int ival = *(int *)val; - int best = 0; // init. value unused - - if (fabs(add) < 0.5) - return; - - if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) { - int newval = ival + add; - if (ival >= opt->min && ival <= opt->max && - newval >= opt->min && newval <= opt->max) - { - found = true; - best = newval; - } else { - check_choice(dir, ival, &found, &best, opt->min); - check_choice(dir, ival, &found, &best, opt->max); - } - } - - for (struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) - check_choice(dir, ival, &found, &best, alt->value); - - if (!found) { - int min, max; - choice_get_min_max(opt, &min, &max); - best = (dir == -1) ^ wrap ? min : max; - } - - *(int *)val = best; -} - -const struct m_option_type m_option_type_choice = { - .name = "String", // same as arbitrary strings in option list for now - .size = sizeof(int), - .parse = parse_choice, - .print = print_choice, - .copy = copy_opt, - .add = add_choice, - .clamp = clamp_choice, -}; - -// Float - -#undef VAL -#define VAL(x) (*(double *)(x)) - -static int clamp_double(const m_option_t *opt, void *val) -{ - double v = VAL(val); - int r = 0; - if ((opt->flags & M_OPT_MAX) && (v > opt->max)) { - v = opt->max; - r = M_OPT_OUT_OF_RANGE; - } - if ((opt->flags & M_OPT_MIN) && (v < opt->min)) { - v = opt->min; - r = M_OPT_OUT_OF_RANGE; - } - if (!isfinite(v)) { - v = opt->min; - r = M_OPT_OUT_OF_RANGE; - } - VAL(val) = v; - return r; -} - -static int parse_double(const m_option_t *opt, struct bstr name, - struct bstr param, void *dst) -{ - if (param.len == 0) - return M_OPT_MISSING_PARAM; - - struct bstr rest; - double tmp_float = bstrtod(param, &rest); - - if (bstr_eatstart0(&rest, ":") || bstr_eatstart0(&rest, "/")) - tmp_float /= bstrtod(rest, &rest); - - 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", - 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", - 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", - BSTR_P(name), opt->max, BSTR_P(param)); - return M_OPT_OUT_OF_RANGE; - } - - if (!isfinite(tmp_float)) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, - "The %.*s option must be a finite number: %.*s\n", - BSTR_P(name), BSTR_P(param)); - return M_OPT_OUT_OF_RANGE; - } - - if (dst) - VAL(dst) = tmp_float; - return 1; -} - -static char *print_double(const m_option_t *opt, const void *val) -{ - return talloc_asprintf(NULL, "%f", VAL(val)); -} - -static char *print_double_f3(const m_option_t *opt, const void *val) -{ - return talloc_asprintf(NULL, "%.3f", VAL(val)); -} - -static void add_double(const m_option_t *opt, void *val, double add, bool wrap) -{ - double v = VAL(val); - - v = v + add; - - double min = (opt->flags & M_OPT_MIN) ? opt->min : -INFINITY; - double max = (opt->flags & M_OPT_MAX) ? opt->max : +INFINITY; - - if (v < min) - v = wrap ? max : min; - if (v > max) - v = wrap ? min : max; - - VAL(val) = v; -} - -static void multiply_double(const m_option_t *opt, void *val, double f) -{ - *(double *)val *= f; - clamp_double(opt, val); -} - -const m_option_type_t m_option_type_double = { - // double precision float or ratio (numerator[:/]denominator) - .name = "Double", - .size = sizeof(double), - .parse = parse_double, - .print = print_double, - .pretty_print = print_double_f3, - .copy = copy_opt, - .clamp = clamp_double, - .add = add_double, - .multiply = multiply_double, -}; - -#undef VAL -#define VAL(x) (*(float *)(x)) - -static int clamp_float(const m_option_t *opt, void *val) -{ - double tmp = VAL(val); - int r = clamp_double(opt, &tmp); - VAL(val) = tmp; - return r; -} - -static int parse_float(const m_option_t *opt, struct bstr name, - struct bstr param, void *dst) -{ - double tmp; - int r = parse_double(opt, name, param, &tmp); - if (r == 1 && dst) - VAL(dst) = tmp; - return r; -} - -static char *print_float(const m_option_t *opt, const void *val) -{ - return talloc_asprintf(NULL, "%f", VAL(val)); -} - -static char *print_float_f3(const m_option_t *opt, const void *val) -{ - return talloc_asprintf(NULL, "%.3f", VAL(val)); -} - -static void add_float(const m_option_t *opt, void *val, double add, bool wrap) -{ - double tmp = VAL(val); - add_double(opt, &tmp, add, wrap); - VAL(val) = tmp; -} - -static void multiply_float(const m_option_t *opt, void *val, double f) -{ - double tmp = VAL(val); - multiply_double(opt, &tmp, f); - VAL(val) = tmp; -} - -const m_option_type_t m_option_type_float = { - // floating point number or ratio (numerator[:/]denominator) - .name = "Float", - .size = sizeof(float), - .parse = parse_float, - .print = print_float, - .pretty_print = print_float_f3, - .copy = copy_opt, - .add = add_float, - .multiply = multiply_float, - .clamp = clamp_float, -}; - -///////////// String - -#undef VAL -#define VAL(x) (*(char **)(x)) - -static char *unescape_string(void *talloc_ctx, bstr str) -{ - char *res = talloc_strdup(talloc_ctx, ""); - while (str.len) { - bstr rest; - bool esc = bstr_split_tok(str, "\\", &str, &rest); - res = talloc_strndup_append_buffer(res, str.start, str.len); - if (esc) { - if (!mp_parse_escape(&rest, &res)) { - talloc_free(res); - return NULL; - } - } - str = rest; - } - return res; -} - -static char *escape_string(char *str0) -{ - char *res = talloc_strdup(NULL, ""); - bstr str = bstr0(str0); - while (str.len) { - bstr rest; - bool esc = bstr_split_tok(str, "\\", &str, &rest); - res = talloc_strndup_append_buffer(res, str.start, str.len); - if (esc) - res = talloc_strdup_append_buffer(res, "\\\\"); - str = rest; - } - return res; -} - -static int clamp_str(const m_option_t *opt, void *val) -{ - char *v = VAL(val); - int len = v ? strlen(v) : 0; - if ((opt->flags & M_OPT_MIN) && (len < opt->min)) - return M_OPT_OUT_OF_RANGE; - if ((opt->flags & M_OPT_MAX) && (len > opt->max)) - return M_OPT_OUT_OF_RANGE; - return 0; -} - -static int parse_str(const m_option_t *opt, struct bstr name, - struct bstr param, void *dst) -{ - int r = 1; - void *tmp = talloc_new(NULL); - - if (param.start == NULL) { - r = M_OPT_MISSING_PARAM; - goto exit; - } - - m_opt_string_validate_fn validate = opt->priv; - if (validate) { - r = validate(opt, name, param); - if (r < 0) - goto exit; - } - - if (opt->flags & M_OPT_PARSE_ESCAPES) { - char *res = unescape_string(tmp, param); - if (!res) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, - "Parameter has broken escapes: %.*s\n", BSTR_P(param)); - r = M_OPT_INVALID; - goto exit; - } - param = bstr0(res); - } - - 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)); - r = M_OPT_OUT_OF_RANGE; - goto exit; - } - - 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)); - r = M_OPT_OUT_OF_RANGE; - goto exit; - } - - if (dst) { - talloc_free(VAL(dst)); - VAL(dst) = bstrdup0(NULL, param); - } - -exit: - talloc_free(tmp); - return r; -} - -static char *print_str(const m_option_t *opt, const void *val) -{ - bool need_escape = opt->flags & M_OPT_PARSE_ESCAPES; - char *s = val ? VAL(val) : NULL; - return s ? (need_escape ? escape_string(s) : talloc_strdup(NULL, s)) : NULL; -} - -static void copy_str(const m_option_t *opt, void *dst, const void *src) -{ - if (dst && src) { - talloc_free(VAL(dst)); - VAL(dst) = talloc_strdup(NULL, VAL(src)); - } -} - -static void free_str(void *src) -{ - if (src && VAL(src)) { - talloc_free(VAL(src)); - VAL(src) = NULL; - } -} - -const m_option_type_t m_option_type_string = { - .name = "String", - .size = sizeof(char *), - .flags = M_OPT_TYPE_DYNAMIC, - .parse = parse_str, - .print = print_str, - .copy = copy_str, - .free = free_str, - .clamp = clamp_str, -}; - -//////////// String list - -#undef VAL -#define VAL(x) (*(char ***)(x)) - -#define OP_NONE 0 -#define OP_ADD 1 -#define OP_PRE 2 -#define OP_DEL 3 -#define OP_CLR 4 -#define OP_TOGGLE 5 - -static void free_str_list(void *dst) -{ - char **d; - int i; - - if (!dst || !VAL(dst)) - return; - d = VAL(dst); - - for (i = 0; d[i] != NULL; i++) - talloc_free(d[i]); - talloc_free(d); - VAL(dst) = NULL; -} - -static int str_list_add(char **add, int n, void *dst, int pre) -{ - if (!dst) - return M_OPT_PARSER_ERR; - char **lst = VAL(dst); - - int ln; - for (ln = 0; lst && lst[ln]; ln++) - /**/; - - lst = talloc_realloc(NULL, lst, char *, n + ln + 1); - - if (pre) { - memmove(&lst[n], lst, ln * sizeof(char *)); - memcpy(lst, add, n * sizeof(char *)); - } else - memcpy(&lst[ln], add, n * sizeof(char *)); - // (re-)add NULL-termination - lst[ln + n] = NULL; - - talloc_free(add); - - VAL(dst) = lst; - - return 1; -} - -static int str_list_del(char **del, int n, void *dst) -{ - char **lst, *ep; - int i, ln, s; - long idx; - - if (!dst) - return M_OPT_PARSER_ERR; - lst = VAL(dst); - - for (ln = 0; lst && lst[ln]; ln++) - /**/; - s = ln; - - for (i = 0; del[i] != NULL; i++) { - idx = strtol(del[i], &ep, 0); - if (*ep) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid index: %s\n", del[i]); - talloc_free(del[i]); - continue; - } - talloc_free(del[i]); - if (idx < 0 || idx >= ln) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, - "Index %ld is out of range.\n", idx); - continue; - } else if (!lst[idx]) - continue; - talloc_free(lst[idx]); - lst[idx] = NULL; - s--; - } - talloc_free(del); - - if (s == 0) { - talloc_free(lst); - VAL(dst) = NULL; - return 1; - } - - // Don't bother shrinking the list allocation - for (i = 0, n = 0; i < ln; i++) { - if (!lst[i]) - continue; - lst[n] = lst[i]; - n++; - } - lst[s] = NULL; - - return 1; -} - -static struct bstr get_nextsep(struct bstr *ptr, char sep, bool modify) -{ - struct bstr str = *ptr; - struct bstr orig = str; - for (;;) { - 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; - } - } - *ptr = str; - return bstr_splice(orig, 0, str.start - orig.start); -} - -static int parse_str_list(const m_option_t *opt, struct bstr name, - struct bstr param, void *dst) -{ - char **res; - int op = OP_NONE; - int len = strlen(opt->name); - if (opt->name[len - 1] == '*' && (name.len > len - 1)) { - struct bstr suffix = bstr_cut(name, len - 1); - if (bstrcmp0(suffix, "-add") == 0) - op = OP_ADD; - else if (bstrcmp0(suffix, "-pre") == 0) - op = OP_PRE; - else if (bstrcmp0(suffix, "-del") == 0) - op = OP_DEL; - else if (bstrcmp0(suffix, "-clr") == 0) - op = OP_CLR; - else - return M_OPT_UNKNOWN; - } - - // Clear the list ?? - if (op == OP_CLR) { - if (dst) - free_str_list(dst); - return 0; - } - - // All other ops need a param - if (param.len == 0 && op != OP_NONE) - 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; - int n = 0; - struct bstr str = param; - while (str.len) { - get_nextsep(&str, separator, 0); - str = bstr_cut(str, 1); - n++; - } - if (n == 0 && op != OP_NONE) - return M_OPT_INVALID; - if (((opt->flags & M_OPT_MIN) && (n < opt->min)) || - ((opt->flags & M_OPT_MAX) && (n > opt->max))) - return M_OPT_OUT_OF_RANGE; - - if (!dst) - return 1; - - res = talloc_array(NULL, char *, n + 2); - str = bstrdup(NULL, param); - char *ptr = str.start; - n = 0; - - while (1) { - struct bstr el = get_nextsep(&str, separator, 1); - res[n] = bstrdup0(NULL, el); - n++; - if (!str.len) - break; - str = bstr_cut(str, 1); - } - res[n] = NULL; - talloc_free(ptr); - - switch (op) { - case OP_ADD: - return str_list_add(res, n, dst, 0); - case OP_PRE: - return str_list_add(res, n, dst, 1); - case OP_DEL: - return str_list_del(res, n, dst); - } - - if (VAL(dst)) - free_str_list(dst); - VAL(dst) = res; - - if (!res[0]) - free_str_list(dst); - - return 1; -} - -static void copy_str_list(const m_option_t *opt, void *dst, const void *src) -{ - int n; - char **d, **s; - - if (!(dst && src)) - return; - s = VAL(src); - - if (VAL(dst)) - free_str_list(dst); - - if (!s) { - VAL(dst) = NULL; - return; - } - - for (n = 0; s[n] != NULL; n++) - /* NOTHING */; - d = talloc_array(NULL, char *, n + 1); - for (; n >= 0; n--) - d[n] = talloc_strdup(NULL, s[n]); - - VAL(dst) = d; -} - -static char *print_str_list(const m_option_t *opt, const void *src) -{ - char **lst = NULL; - char *ret = NULL; - - if (!(src && VAL(src))) - return NULL; - lst = VAL(src); - - for (int i = 0; lst[i]; i++) { |