]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
parse-util: also parse integers prefixed with 0b and 0o
authorLennart Poettering <lennart@poettering.net>
Mon, 1 Jun 2020 15:31:51 +0000 (17:31 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 5 Jun 2020 13:56:32 +0000 (15:56 +0200)
Let's adopt Python 3 style 0b and 0x syntaxes, because it makes a ton of
sense, in particular in bitmask settings.

src/basic/parse-util.c

index 0f6d24f59031b05342469a942209e9dabf3b21f8..44f0438cf468f7ec12ac427a9f5560048d638da1 100644 (file)
@@ -352,6 +352,32 @@ int parse_syscall_and_errno(const char *in, char **name, int *error) {
         return 0;
 }
 
+static const char *mangle_base(const char *s, unsigned *base) {
+        const char *k;
+
+        assert(s);
+        assert(base);
+
+        /* Base already explicitly specified, then don't do anything. */
+        if (SAFE_ATO_MASK_FLAGS(*base) != 0)
+                return s;
+
+        /* Support Python 3 style "0b" and 0x" prefixes, because they truly make sense, much more than C's "0" prefix for octal. */
+        k = STARTSWITH_SET(s, "0b", "0B");
+        if (k) {
+                *base = 2 | (*base & SAFE_ATO_ALL_FLAGS);
+                return k;
+        }
+
+        k = STARTSWITH_SET(s, "0o", "0O");
+        if (k) {
+                *base = 8 | (*base & SAFE_ATO_ALL_FLAGS);
+                return k;
+        }
+
+        return s;
+}
+
 int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
         char *x = NULL;
         unsigned long l;
@@ -383,6 +409,8 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
                 return -EINVAL; /* This is particularly useful to avoid ambiguities between C's octal
                                  * notation and assumed-to-be-decimal integers with a leading zero. */
 
+        s = mangle_base(s, &base);
+
         errno = 0;
         l = strtoul(s, &x, SAFE_ATO_MASK_FLAGS(base) /* Let's mask off the flags bits so that only the actual
                                                       * base is left */);
@@ -402,13 +430,17 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
 }
 
 int safe_atoi(const char *s, int *ret_i) {
+        unsigned base = 0;
         char *x = NULL;
         long l;
 
         assert(s);
 
+        s += strspn(s, WHITESPACE);
+        s = mangle_base(s, &base);
+
         errno = 0;
-        l = strtol(s, &x, 0);
+        l = strtol(s, &x, base);
         if (errno > 0)
                 return -errno;
         if (!x || x == s || *x != 0)
@@ -443,6 +475,8 @@ int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu)
             s[0] == '0' && s[1] != 0)
                 return -EINVAL;
 
+        s = mangle_base(s, &base);
+
         errno = 0;
         l = strtoull(s, &x, SAFE_ATO_MASK_FLAGS(base));
         if (errno > 0)
@@ -459,13 +493,17 @@ int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu)
 }
 
 int safe_atolli(const char *s, long long int *ret_lli) {
+        unsigned base = 0;
         char *x = NULL;
         long long l;
 
         assert(s);
 
+        s += strspn(s, WHITESPACE);
+        s = mangle_base(s, &base);
+
         errno = 0;
-        l = strtoll(s, &x, 0);
+        l = strtoll(s, &x, base);
         if (errno > 0)
                 return -errno;
         if (!x || x == s || *x != 0)
@@ -478,15 +516,17 @@ int safe_atolli(const char *s, long long int *ret_lli) {
 }
 
 int safe_atou8(const char *s, uint8_t *ret) {
-        char *x = NULL;
+        unsigned base = 0;
         unsigned long l;
+        char *x = NULL;
 
         assert(s);
 
         s += strspn(s, WHITESPACE);
+        s = mangle_base(s, &base);
 
         errno = 0;
-        l = strtoul(s, &x, 0);
+        l = strtoul(s, &x, base);
         if (errno > 0)
                 return -errno;
         if (!x || x == s || *x != 0)
@@ -522,6 +562,8 @@ int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
             s[0] == '0' && s[1] != 0)
                 return -EINVAL;
 
+        s = mangle_base(s, &base);
+
         errno = 0;
         l = strtoul(s, &x, SAFE_ATO_MASK_FLAGS(base));
         if (errno > 0)
@@ -540,13 +582,17 @@ int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
 }
 
 int safe_atoi16(const char *s, int16_t *ret) {
+        unsigned base = 0;
         char *x = NULL;
         long l;
 
         assert(s);
 
+        s += strspn(s, WHITESPACE);
+        s = mangle_base(s, &base);
+
         errno = 0;
-        l = strtol(s, &x, 0);
+        l = strtol(s, &x, base);
         if (errno > 0)
                 return -errno;
         if (!x || x == s || *x != 0)