summaryrefslogtreecommitdiffstats
path: root/options/m_option.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2018-01-24 01:32:56 +0100
committerKevin Mitchell <kevmitch@gmail.com>2018-01-25 20:18:32 -0800
commit11f5713e3bbeea8449a97ecb979936e02660321e (patch)
treeea8ee4886ca914a9185b0b2bd9bee68fd011869c /options/m_option.c
parentcabfbc34b539c06ae37745a200996bd351b64cf5 (diff)
downloadmpv-11f5713e3bbeea8449a97ecb979936e02660321e.tar.bz2
mpv-11f5713e3bbeea8449a97ecb979936e02660321e.tar.xz
options: add an option type for byte sizes
And use it for 2 demuxer options. It could be used for more options later. (Though the --cache options can not use this, because they use KB as base unit.)
Diffstat (limited to 'options/m_option.c')
-rw-r--r--options/m_option.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/options/m_option.c b/options/m_option.c
index 8cdf8aee11..fe656a07ac 100644
--- a/options/m_option.c
+++ b/options/m_option.c
@@ -393,6 +393,101 @@ const m_option_type_t m_option_type_int64 = {
.get = int64_get,
};
+static int parse_byte_size(struct mp_log *log, const m_option_t *opt,
+ struct bstr name, struct bstr param, void *dst)
+{
+ if (param.len == 0)
+ return M_OPT_MISSING_PARAM;
+
+ struct bstr r;
+ long long tmp_int = bstrtoll(param, &r, 0);
+ int64_t unit = 1;
+ if (r.len) {
+ if (bstrcasecmp0(r, "kib") == 0 || bstrcasecmp0(r, "k") == 0) {
+ unit = 1024;
+ } else if (bstrcasecmp0(r, "mib") == 0 || bstrcasecmp0(r, "m") == 0) {
+ unit = 1024 * 1024;
+ } else if (bstrcasecmp0(r, "gib") == 0 || bstrcasecmp0(r, "g") == 0) {
+ unit = 1024 * 1024 * 1024;
+ } else if (bstrcasecmp0(r, "tib") == 0 || bstrcasecmp0(r, "t") == 0) {
+ unit = 1024 * 1024 * 1024 * 1024LL;
+ } else {
+ mp_err(log, "The %.*s option must be an integer: %.*s\n",
+ BSTR_P(name), BSTR_P(param));
+ mp_err(log, "The following suffixes are also allowed: "
+ "KiB, MiB, GiB, TiB, K, M, G, T.\n");
+ return M_OPT_INVALID;
+ }
+ }
+
+ if (tmp_int < 0) {
+ mp_err(log, "The %.*s option does not support negative numbers: %.*s\n",
+ BSTR_P(name), BSTR_P(param));
+ return M_OPT_OUT_OF_RANGE;
+ }
+
+ if (INT64_MAX / unit < tmp_int) {
+ mp_err(log, "The %.*s option overflows: %.*s\n",
+ BSTR_P(name), BSTR_P(param));
+ return M_OPT_OUT_OF_RANGE;
+ }
+
+ tmp_int *= unit;
+
+ if ((opt->flags & M_OPT_MIN) && (tmp_int < opt->min)) {
+ mp_err(log, "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_err(log, "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)
+ *(int64_t *)dst = tmp_int;
+
+ return 1;
+}
+
+char *format_file_size(int64_t size)
+{
+ double s = size;
+ if (size < 1024)
+ return talloc_asprintf(NULL, "%.0f", s);
+
+ if (size < (1024 * 1024))
+ return talloc_asprintf(NULL, "%.3f KiB", s / (1024.0));
+
+ if (size < (1024 * 1024 * 1024))
+ return talloc_asprintf(NULL, "%.3f MiB", s / (1024.0 * 1024.0));
+
+ if (size < (1024LL * 1024LL * 1024LL * 1024LL))
+ return talloc_asprintf(NULL, "%.3f GiB", s / (1024.0 * 1024.0 * 1024.0));
+
+ return talloc_asprintf(NULL, "%.3f TiB", s / (1024.0 * 1024.0 * 1024.0 * 1024.0));
+}
+
+static char *pretty_print_byte_size(const m_option_t *opt, const void *val)
+{
+ return format_file_size(*(int64_t *)val);
+}
+
+const m_option_type_t m_option_type_byte_size = {
+ .name = "ByteSize",
+ .size = sizeof(int64_t),
+ .parse = parse_byte_size,
+ .print = print_int,
+ .pretty_print = pretty_print_byte_size,
+ .copy = copy_opt,
+ .add = add_int64,
+ .multiply = multiply_int64,
+ .set = int64_set,
+ .get = int64_get,
+};
+
static int parse_intpair(struct mp_log *log, const struct m_option *opt,
struct bstr name, struct bstr param, void *dst)
{