summaryrefslogtreecommitdiff
path: root/src/shared/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/util.c')
-rw-r--r--src/shared/util.c53
1 files changed, 46 insertions, 7 deletions
diff --git a/src/shared/util.c b/src/shared/util.c
index b33f1203e6..5cb598c4c5 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -2135,11 +2135,28 @@ ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
return n;
}
-int parse_bytes(const char *t, off_t *bytes) {
- static const struct {
+int parse_size(const char *t, off_t base, off_t *size) {
+
+ /* Soo, sometimes we want to parse IEC binary suffxies, and
+ * sometimes SI decimal suffixes. This function can parse
+ * both. Which one is the right way depends on the
+ * context. Wikipedia suggests that SI is customary for
+ * hardrware metrics and network speeds, while IEC is
+ * customary for most data sizes used by software and volatile
+ * (RAM) memory. Hence be careful which one you pick!
+ *
+ * In either case we use just K, M, G as suffix, and not Ki,
+ * Mi, Gi or so (as IEC would suggest). That's because that's
+ * frickin' ugly. But this means you really need to make sure
+ * to document which base you are parsing when you use this
+ * call. */
+
+ struct table {
const char *suffix;
unsigned long long factor;
- } table[] = {
+ };
+
+ static const struct table iec[] = {
{ "B", 1 },
{ "K", 1024ULL },
{ "M", 1024ULL*1024ULL },
@@ -2150,11 +2167,33 @@ int parse_bytes(const char *t, off_t *bytes) {
{ "", 1 },
};
+ static const struct table si[] = {
+ { "B", 1 },
+ { "K", 1000ULL },
+ { "M", 1000ULL*1000ULL },
+ { "G", 1000ULL*1000ULL*1000ULL },
+ { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
+ { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
+ { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
+ { "", 1 },
+ };
+
+ const struct table *table;
const char *p;
unsigned long long r = 0;
+ unsigned n_entries;
assert(t);
- assert(bytes);
+ assert(base == 1000 || base == 1024);
+ assert(size);
+
+ if (base == 1000) {
+ table = si;
+ n_entries = ELEMENTSOF(si);
+ } else {
+ table = iec;
+ n_entries = ELEMENTSOF(iec);
+ }
p = t;
do {
@@ -2176,7 +2215,7 @@ int parse_bytes(const char *t, off_t *bytes) {
e += strspn(e, WHITESPACE);
- for (i = 0; i < ELEMENTSOF(table); i++)
+ for (i = 0; i < n_entries; i++)
if (startswith(e, table[i].suffix)) {
unsigned long long tmp;
if ((unsigned long long) l > ULLONG_MAX / table[i].factor)
@@ -2193,12 +2232,12 @@ int parse_bytes(const char *t, off_t *bytes) {
break;
}
- if (i >= ELEMENTSOF(table))
+ if (i >= n_entries)
return -EINVAL;
} while (*p);
- *bytes = r;
+ *size = r;
return 0;
}