1 #define ANYSINT_MAX(t) ((((t) 1 << (sizeof(t) * 8 - 2)) - (t) 1) * (t) 2 + (t) 1)
2
3 static ssize_t hprint(char *buf, int64_t v)
4 {
5 static const char units[] = "\0kMGTPEZY";
6 char dec[3] = "";
7 int u, t;
8
9 for (u = 0; v >= 1024 || v <= -1024; u++)
10 t = do_div(v, 1024);
11
12 if (u && v < 10 && v > -10)
13 sprintf(dec, ".%i", t / 100);
14
15 return sprintf(buf, "%lli%s%c", v, dec, units[u]);
16 }
17
18 #define STRTO_H(name, type) \
19 static int name ## _h(const char *cp, type *res) \
20 { \
21 int u = 0; \
22 char *e; \
23 type i = simple_ ## name(cp, &e, 10); \
24 \
25 switch (tolower(*e)) { \
26 default: \
27 return -EINVAL; \
28 case 'y': \
29 case 'z': \
30 u++; \
31 case 'e': \
32 u++; \
33 case 'p': \
34 u++; \
35 case 't': \
36 u++; \
37 case 'g': \
38 u++; \
39 case 'm': \
40 u++; \
41 case 'k': \
42 u++; \
43 if (e++ == cp) \
44 return -EINVAL; \
45 case '\n': \
46 case '\0': \
47 if (*e == '\n') \
48 e++; \
49 } \
50 \
51 if (*e) \
52 return -EINVAL; \
53 \
54 while (u--) { \
55 if ((type) ~0 > 0 && \
56 (type) ~0 / 1024 <= i) \
57 return -EINVAL; \
58 if ((i > 0 && ANYSINT_MAX(type) / 1024 < i) || \
59 (i < 0 && -ANYSINT_MAX(type) / 1024 > i)) \
60 return -EINVAL; \
61 i *= 1024; \
62 } \
63 \
64 *res = i; \
65 return 0; \
66 }
67
68 STRTO_H(strtol, long)
69 STRTO_H(strtoll, long long)
70 STRTO_H(strtoul, unsigned long)
71 STRTO_H(strtoull, unsigned long long)
72
73 #define strtoi_h(cp, res) \
74 (__builtin_types_compatible_p(typeof(*res), long) \
75 ? strtol_h(cp, (void*) res) \
76 : __builtin_types_compatible_p(typeof(*res), long long) \
77 ? strtoll_h(cp, (void*) res) \
78 : __builtin_types_compatible_p(typeof(*res), unsigned long) \
79 ? strtoul_h(cp, (void*) res) \
80 : __builtin_types_compatible_p(typeof(*res), unsigned long long)\
81 ? strtoull_h(cp, (void*) res) : -EINVAL) \
82