Allow use of KiB etc to give explicit base 10 multiplies
authorJens Axboe <jaxboe@fusionio.com>
Wed, 23 Jun 2010 20:24:07 +0000 (22:24 +0200)
committerJens Axboe <jaxboe@fusionio.com>
Wed, 23 Jun 2010 20:24:07 +0000 (22:24 +0200)
Useful for disk drives, where capacity is given in base 10 units.

Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
HOWTO
fio.1
parse.c

diff --git a/HOWTO b/HOWTO
index 3e1e62a0f4d3115fa947471febf2796150eae9f2..cafe1893656cfdff733c9b4368a92396ce9bd46c 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -226,12 +226,17 @@ time      Integer with possible time suffix. In seconds unless otherwise
 int    SI integer. A whole number value, which may contain a suffix
        describing the base of the number. Accepted suffixes are k/m/g/t/p,
        meaning kilo, mega, giga, tera, and peta. The suffix is not case
 int    SI integer. A whole number value, which may contain a suffix
        describing the base of the number. Accepted suffixes are k/m/g/t/p,
        meaning kilo, mega, giga, tera, and peta. The suffix is not case
-       sensitive. So if you want to specify 4096, you could either write
+       sensitive, and you may also include trailing 'b' (eg 'kb' is the same
+       as 'k'). So if you want to specify 4096, you could either write
        out '4096' or just give 4k. The suffixes signify base 2 values, so
        out '4096' or just give 4k. The suffixes signify base 2 values, so
-       1024 is 1k and 1024k is 1m and so on. If the option accepts an upper
-       and lower range, use a colon ':' or minus '-' to separate such values.
-       May also include a prefix to indicate numbers base. If 0x is used,
-       the number is assumed to be hexadecimal. See irange.
+       1024 is 1k and 1024k is 1m and so on, unless the suffix is explicitly
+       set to a base 10 value using 'kib', 'mib', 'gib', etc. If that is the
+       case, then 1000 is used as the multiplier. This can be handy for
+       disks, since manufacturers generally use base 10 values when listing
+       the capacity of a drive. If the option accepts an upper and lower
+       range, use a colon ':' or minus '-' to separate such values.  May also
+       include a prefix to indicate numbers base. If 0x is used, the number
+       is assumed to be hexadecimal.  See irange.
 bool   Boolean. Usually parsed as an integer, however only defined for
        true and false (1 and 0).
 irange Integer range with suffix. Allows value range to be given, such
 bool   Boolean. Usually parsed as an integer, however only defined for
        true and false (1 and 0).
 irange Integer range with suffix. Allows value range to be given, such
diff --git a/fio.1 b/fio.1
index e737906f31d2fd0d4b5457bae6f27c8d2fde0738..b94241d48c2efc5081b058ce8de464e51e357031 100644 (file)
--- a/fio.1
+++ b/fio.1
@@ -81,7 +81,11 @@ SI integer: a whole number, possibly containing a suffix denoting the base unit
 of the value.  Accepted suffixes are `k', 'M', 'G', 'T', and 'P', denoting
 kilo (1024), mega (1024^2), giga (1024^3), tera (1024^4), and peta (1024^5)
 respectively. The suffix is not case sensitive. If prefixed with '0x', the
 of the value.  Accepted suffixes are `k', 'M', 'G', 'T', and 'P', denoting
 kilo (1024), mega (1024^2), giga (1024^3), tera (1024^4), and peta (1024^5)
 respectively. The suffix is not case sensitive. If prefixed with '0x', the
-value is assumed to be base 16 (hexadecimal).
+value is assumed to be base 16 (hexadecimal). A suffix may include a trailing
+'b', for instance 'kb' is identical to 'k'. You can specify a base 10 value
+by using 'KiB', 'MiB', 'GiB', etc. This is useful for disk drives where
+values are often given in base 10 values. Specifying '30GiB' will get you
+30*1000^3 bytes.
 .TP
 .I bool
 Boolean: a true or false value. `0' denotes false, `1' denotes true.
 .TP
 .I bool
 Boolean: a true or false value. `0' denotes false, `1' denotes true.
diff --git a/parse.c b/parse.c
index 869bcdad4cf2bf43ae6dc2bf8b46a0c1362e0339..e03592d8bd4ee0b7850e2067a847f4caae814f70 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -117,35 +117,72 @@ static unsigned long get_mult_time(char c)
        }
 }
 
        }
 }
 
-static unsigned long long get_mult_bytes(char c, void *data)
+static unsigned long long __get_mult_bytes(const char *p, void *data)
 {
        unsigned int kb_base = fio_get_kb_base(data);
        unsigned long long ret = 1;
 {
        unsigned int kb_base = fio_get_kb_base(data);
        unsigned long long ret = 1;
+       unsigned int i, pow = 0, mult = kb_base;
+       char *c;
 
 
-       switch (c) {
-       default:
-               break;
-       case 'p':
-       case 'P':
-               ret *= (unsigned long long) kb_base;
-       case 't':
-       case 'T':
-               ret *= (unsigned long long) kb_base;
-       case 'g':
-       case 'G':
-               ret *= (unsigned long long) kb_base;
-       case 'm':
-       case 'M':
-               ret *= (unsigned long long) kb_base;
-       case 'k':
-       case 'K':
-               ret *= (unsigned long long) kb_base;
-               break;
-       }
+       if (!p)
+               return 1;
 
 
+       c = strdup(p);
+
+       for (i = 0; i < strlen(c); i++)
+               c[i] = tolower(c[i]);
+
+       if (!strcmp("pib", c)) {
+               pow = 5;
+               mult = 1000;
+       } else if (!strcmp("tib", c)) {
+               pow = 4;
+               mult = 1000;
+       } else if (!strcmp("gib", c)) {
+               pow = 3;
+               mult = 1000;
+       } else if (!strcmp("mib", c)) {
+               pow = 2;
+               mult = 1000;
+       } else if (!strcmp("kib", c)) {
+               pow = 1;
+               mult = 1000;
+       } else if (!strcmp("p", c) || !strcmp("pb", c))
+               pow = 5;
+       else if (!strcmp("t", c) || !strcmp("tb", c))
+               pow = 4;
+       else if (!strcmp("g", c) || !strcmp("gb", c))
+               pow = 3;
+       else if (!strcmp("m", c) || !strcmp("mb", c))
+               pow = 2;
+       else if (!strcmp("k", c) || !strcmp("kb", c))
+               pow = 1;
+
+       while (pow--)
+               ret *= (unsigned long long) mult;
+
+       free(c);
        return ret;
 }
 
        return ret;
 }
 
+static unsigned long long get_mult_bytes(const char *str, int len, void *data)
+{
+       const char *p;
+
+       /*
+        * if the last char is 'b' or 'B', the user likely used
+        * "1gb" instead of just "1g". If the second to last is also
+        * a letter, adjust.
+        */
+       p = str + len - 1;
+       while (isalpha(*(p - 1)))
+               p--;
+       if (!isalpha(*p))
+               p = NULL;
+
+       return __get_mult_bytes(p, data);
+}
+
 /*
  * convert string into decimal value, noting any size suffix
  */
 /*
  * convert string into decimal value, noting any size suffix
  */
@@ -166,19 +203,9 @@ int str_to_decimal(const char *str, long long *val, int kilo, void *data)
        if (*val == LONG_MAX && errno == ERANGE)
                return 1;
 
        if (*val == LONG_MAX && errno == ERANGE)
                return 1;
 
-       if (kilo) {
-               const char *p;
-               /*
-                * if the last char is 'b' or 'B', the user likely used
-                * "1gb" instead of just "1g". If the second to last is also
-                * a letter, adjust.
-                */
-               p = str + len - 1;
-               if ((*p == 'b' || *p == 'B') && isalpha(*(p - 1)))
-                       --p;
-
-               *val *= get_mult_bytes(*p, data);
-       } else
+       if (kilo)
+               *val *= get_mult_bytes(str, len, data);
+       else
                *val *= get_mult_time(str[len - 1]);
 
        return 0;
                *val *= get_mult_time(str[len - 1]);
 
        return 0;
@@ -226,19 +253,13 @@ void strip_blank_end(char *p)
 
 static int check_range_bytes(const char *str, long *val, void *data)
 {
 
 static int check_range_bytes(const char *str, long *val, void *data)
 {
-       char suffix;
-
-       if (!strlen(str))
-               return 1;
+       long long __val;
 
 
-       if (sscanf(str, "%lu%c", val, &suffix) == 2) {
-               *val *= get_mult_bytes(suffix, data);
+       if (!str_to_decimal(str, &__val, 1, data)) {
+               *val = __val;
                return 0;
        }
 
                return 0;
        }
 
-       if (sscanf(str, "%lu", val) == 1)
-               return 0;
-
        return 1;
 }
 
        return 1;
 }