]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: tools: make parse_size_err() support 32/64 bits
authorWilly Tarreau <w@1wt.eu>
Tue, 19 Nov 2024 08:15:19 +0000 (09:15 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 19 Nov 2024 09:50:42 +0000 (10:50 +0100)
parse_size_err() currently is a function working only on an uint. It's
not convenient for certain elements such as rings on large machines.

This commit addresses this by having one function for uints and one
for ullong, and making parse_size_err() a macro that automatically
calls one or the other. It also has the benefit of automatically
supporting compatible types (long, size_t etc).

include/haproxy/tools.h
src/tools.c

index aa9fd777c4e77f6ae009bc2b5dc6f16cc8df8f83..72bb5325ef849449ae9e32a00f409422fc1971a6 100644 (file)
@@ -642,7 +642,26 @@ extern time_t my_timegm(const struct tm *tm);
  * <ret> is left untouched.
  */
 extern const char *parse_time_err(const char *text, unsigned *ret, unsigned unit_flags);
-extern const char *parse_size_err(const char *text, unsigned *ret);
+extern const char *parse_size_ui(const char *text, unsigned *ret);
+extern const char *parse_size_ull(const char *text, ullong *ret);
+
+/* Parse a size from <_test> into <_ret> which must be compatible with a
+ * uint or ullong. The return value is a pointer to the first unparsable
+ * character (if any) or NULL if everything's OK.
+ */
+#define parse_size_err(_text, _ret) ({                 \
+       const char *_err;                               \
+       if (sizeof(*(_ret)) > sizeof(int)) {            \
+               unsigned long long _tmp;                \
+               _err = parse_size_ull(_text, &_tmp);    \
+               *_ret = _tmp;                           \
+       } else {                                        \
+               unsigned int _tmp;                      \
+               _err = parse_size_ui(_text, &_tmp);     \
+               *_ret = _tmp;                           \
+       }                                               \
+       _err;                                           \
+})
 
 /*
  * Parse binary string written in hexadecimal (source) and store the decoded
index d2decb69beabe4c73aba3f0ea7507836574bdc01..224c5df97a5500d85b338f42723d6d9520302e08 100644 (file)
@@ -2780,7 +2780,8 @@ const char *parse_time_err(const char *text, unsigned *ret, unsigned unit_flags)
  * stored in <ret>. If an error is detected, the pointer to the unexpected
  * character is returned. If the conversion is successful, NULL is returned.
  */
-const char *parse_size_err(const char *text, unsigned *ret) {
+const char *parse_size_ui(const char *text, unsigned *ret)
+{
        unsigned value = 0;
 
        if (!isdigit((unsigned char)*text))
@@ -2833,6 +2834,76 @@ const char *parse_size_err(const char *text, unsigned *ret) {
        return NULL;
 }
 
+/* this function converts the string starting at <text> to an ullong stored in
+ * <ret>. If an error is detected, the pointer to the unexpected character is
+ * returned. If the conversion is successful, NULL is returned.
+ */
+const char *parse_size_ull(const char *text, ullong *ret)
+{
+       ullong value = 0;
+
+       if (!isdigit((unsigned char)*text))
+               return text;
+
+       while (1) {
+               unsigned int j;
+
+               j = *text - '0';
+               if (j > 9)
+                       break;
+               if (value > ~0ULL / 10)
+                       return text;
+               value *= 10;
+               if (value > (value + j))
+                       return text;
+               value += j;
+               text++;
+       }
+
+       switch (*text) {
+       case '\0':
+               break;
+       case 'K':
+       case 'k':
+               if (value > ~0ULL >> 10)
+                       return text;
+               value = value << 10;
+               break;
+       case 'M':
+       case 'm':
+               if (value > ~0ULL >> 20)
+                       return text;
+               value = value << 20;
+               break;
+       case 'G':
+       case 'g':
+               if (value > ~0ULL >> 30)
+                       return text;
+               value = value << 30;
+               break;
+       case 'T':
+       case 't':
+               if (value > ~0ULL >> 40)
+                       return text;
+               value = value << 40;
+               break;
+       case 'P':
+       case 'p':
+               if (value > ~0ULL >> 50)
+                       return text;
+               value = value << 50;
+               break;
+       default:
+               return text;
+       }
+
+       if (*text != '\0' && *++text != '\0')
+               return text;
+
+       *ret = value;
+       return NULL;
+}
+
 /*
  * Parse binary string written in hexadecimal (source) and store the decoded
  * result into binstr and set binstrlen to the length of binstr. Memory for