1 /*******************************************************************************
2 * tlx/string/parse_si_iec_units.cpp
3 *
4 * Part of tlx - http://panthema.net/tlx
5 *
6 * Copyright (C) 2016-2017 Timo Bingmann <tb@panthema.net>
7 *
8 * All rights reserved. Published under the Boost Software License, Version 1.0
9 ******************************************************************************/
10
11 #include <tlx/string/parse_si_iec_units.hpp>
12
13 #include <cstdlib>
14
15 namespace tlx {
16
parse_si_iec_units(const char * str,uint64_t * out_size,char default_unit)17 bool parse_si_iec_units(
18 const char* str, uint64_t* out_size, char default_unit) {
19
20 char* endptr;
21 *out_size = strtoul(str, &endptr, 10);
22 if (endptr == nullptr) return false; // parse failed, no number
23
24 while (*endptr == ' ') ++endptr; // skip over spaces
25
26 // multiply with base ^ power
27 unsigned int base = 1000;
28 unsigned int power = 0;
29
30 if (*endptr == 'k' || *endptr == 'K')
31 power = 1, ++endptr;
32 else if (*endptr == 'm' || *endptr == 'M')
33 power = 2, ++endptr;
34 else if (*endptr == 'g' || *endptr == 'G')
35 power = 3, ++endptr;
36 else if (*endptr == 't' || *endptr == 'T')
37 power = 4, ++endptr;
38 else if (*endptr == 'p' || *endptr == 'P')
39 power = 5, ++endptr;
40
41 // switch to power of two (only if power was set above)
42 if ((*endptr == 'i' || *endptr == 'I') && power != 0)
43 base = 1024, ++endptr;
44
45 // byte indicator
46 if (*endptr == 'b' || *endptr == 'B') {
47 ++endptr;
48 }
49 else if (power == 0)
50 {
51 // no explicit power indicator, and no 'b' or 'B' -> apply default unit
52 switch (default_unit)
53 {
54 default: break;
55 case 'k': power = 1, base = 1000;
56 break;
57 case 'm': power = 2, base = 1000;
58 break;
59 case 'g': power = 3, base = 1000;
60 break;
61 case 't': power = 4, base = 1000;
62 break;
63 case 'p': power = 5, base = 1000;
64 break;
65 case 'K': power = 1, base = 1024;
66 break;
67 case 'M': power = 2, base = 1024;
68 break;
69 case 'G': power = 3, base = 1024;
70 break;
71 case 'T': power = 4, base = 1024;
72 break;
73 case 'P': power = 5, base = 1024;
74 break;
75 }
76 }
77
78 // skip over spaces
79 while (*endptr == ' ') ++endptr;
80
81 // multiply size
82 for (unsigned int p = 0; p < power; ++p)
83 *out_size *= base;
84
85 return (*endptr == 0);
86 }
87
parse_si_iec_units(const std::string & str,uint64_t * out_size,char default_unit)88 bool parse_si_iec_units(
89 const std::string& str, uint64_t* out_size, char default_unit) {
90 return parse_si_iec_units(str.c_str(), out_size, default_unit);
91 }
92
93 } // namespace tlx
94
95 /******************************************************************************/
96