1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include "units.h" |
3 | #include <inttypes.h> |
4 | #include <limits.h> |
5 | #include <stdlib.h> |
6 | #include <string.h> |
7 | #include <linux/kernel.h> |
8 | #include <linux/time64.h> |
9 | |
10 | unsigned long parse_tag_value(const char *str, struct parse_tag *tags) |
11 | { |
12 | struct parse_tag *i = tags; |
13 | |
14 | while (i->tag) { |
15 | char *s = strchr(str, i->tag); |
16 | |
17 | if (s) { |
18 | unsigned long int value; |
19 | char *endptr; |
20 | |
21 | value = strtoul(str, &endptr, 10); |
22 | if (s != endptr) |
23 | break; |
24 | |
25 | if (value > ULONG_MAX / i->mult) |
26 | break; |
27 | value *= i->mult; |
28 | return value; |
29 | } |
30 | i++; |
31 | } |
32 | |
33 | return (unsigned long) -1; |
34 | } |
35 | |
36 | double convert_unit_double(double value, char *unit) |
37 | { |
38 | *unit = ' '; |
39 | |
40 | if (value > 1000.0) { |
41 | value /= 1000.0; |
42 | *unit = 'K'; |
43 | } |
44 | |
45 | if (value > 1000.0) { |
46 | value /= 1000.0; |
47 | *unit = 'M'; |
48 | } |
49 | |
50 | if (value > 1000.0) { |
51 | value /= 1000.0; |
52 | *unit = 'G'; |
53 | } |
54 | |
55 | return value; |
56 | } |
57 | |
58 | unsigned long convert_unit(unsigned long value, char *unit) |
59 | { |
60 | double v = convert_unit_double(value: (double)value, unit); |
61 | |
62 | return (unsigned long)v; |
63 | } |
64 | |
65 | int unit_number__scnprintf(char *buf, size_t size, u64 n) |
66 | { |
67 | char unit[4] = "BKMG" ; |
68 | int i = 0; |
69 | |
70 | while (((n / 1024) > 1) && (i < 3)) { |
71 | n /= 1024; |
72 | i++; |
73 | } |
74 | |
75 | return scnprintf(buf, size, "%" PRIu64 "%c" , n, unit[i]); |
76 | } |
77 | |