dovecot-2.2: strnum: Implemented many more numeric string parsin...

dovecot at dovecot.org dovecot at dovecot.org
Sat Aug 29 11:50:16 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/de73e7121676
changeset: 19037:de73e7121676
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Sat Aug 29 14:31:51 2015 +0300
description:
strnum: Implemented many more numeric string parsing functions.
Created macros for most of the implementation to avoid further code
duplication.

diffstat:

 src/lib/strnum.c |  337 +++++++++++++++++++++++++++++++++++++++---------------
 src/lib/strnum.h |  184 ++++++++++++++++++++++++++---
 2 files changed, 401 insertions(+), 120 deletions(-)

diffs (truncated from 611 to 300 lines):

diff -r f78e38c7cba2 -r de73e7121676 src/lib/strnum.c
--- a/src/lib/strnum.c	Sat Aug 29 14:30:37 2015 +0300
+++ b/src/lib/strnum.c	Sat Aug 29 14:31:51 2015 +0300
@@ -17,72 +17,44 @@
 	return TRUE;
 }
 
-int str_to_uint(const char *str, unsigned int *num_r)
-{
-	uintmax_t l;
+/* 
+ * Unsigned decimal
+ */
 
-	if (str_to_uintmax(str, &l) < 0)
-		return -1;
-
-	if (l > UINT_MAX)
-		return -1;
-	*num_r = (unsigned int)l;
-	return 0;
+#define STR_PARSE_U__TEMPLATE(name, type)                     \
+int name(const char *str, type *num_r, const char **endp_r)   \
+{                                                             \
+	uintmax_t l;                                                \
+	if (str_parse_uintmax(str, &l, endp_r) < 0 || l > (type)-1) \
+		return -1;                                                \
+	*num_r = (type)l;                                           \
+	return 0;                                                   \
 }
 
-int str_to_ulong(const char *str, unsigned long *num_r)
-{
-	uintmax_t l;
+STR_PARSE_U__TEMPLATE(str_parse_uint, unsigned int)
+STR_PARSE_U__TEMPLATE(str_parse_ulong, unsigned long)
+STR_PARSE_U__TEMPLATE(str_parse_ullong, unsigned long long)
+STR_PARSE_U__TEMPLATE(str_parse_uint32, uint32_t)
+STR_PARSE_U__TEMPLATE(str_parse_uint64, uint64_t)
 
-	if (str_to_uintmax(str, &l) < 0)
-		return -1;
-
-	if (l > (unsigned long)-1)
-		return -1;
-	*num_r = (unsigned long)l;
-	return 0;
+#define STR_TO_U__TEMPLATE(name, type)                        \
+int name(const char *str, type *num_r)                        \
+{                                                             \
+	uintmax_t l;                                                \
+	if (str_to_uintmax(str, &l) < 0 || l > (type)-1)            \
+		return -1;                                                \
+	*num_r = (type)l;                                           \
+	return 0;                                                   \
 }
 
-int str_to_ullong(const char *str, unsigned long long *num_r)
-{
-	uintmax_t l;
+STR_TO_U__TEMPLATE(str_to_uint, unsigned int)
+STR_TO_U__TEMPLATE(str_to_ulong, unsigned long)
+STR_TO_U__TEMPLATE(str_to_ullong, unsigned long long)
+STR_TO_U__TEMPLATE(str_to_uint32, uint32_t)
+STR_TO_U__TEMPLATE(str_to_uint64, uint64_t)
 
-	if (str_to_uintmax(str, &l) < 0)
-		return -1;
-
-	if (l > (unsigned long long)-1)
-		return -1;
-	*num_r = (unsigned long long)l;
-	return 0;
-}
-
-int str_to_uint32(const char *str, uint32_t *num_r)
-{
-	uintmax_t l;
-
-	if (str_to_uintmax(str, &l) < 0)
-		return -1;
-
-	if (l > (uint32_t)-1)
-		return -1;
-	*num_r = (uint32_t)l;
-	return 0;
-}
-
-int str_to_uint64(const char *str, uint64_t *num_r)
-{
-	uintmax_t l;
-
-	if (str_to_uintmax(str, &l) < 0)
-		return -1;
-
-	if (l > (uint64_t)-1)
-		return -1;
-	*num_r = (uint64_t)l;
-	return 0;
-}
-
-int str_parse_uintmax(const char *str, uintmax_t *num_r, const char **endp_r)
+int str_parse_uintmax(const char *str, uintmax_t *num_r,
+	const char **endp_r)
 {
 	uintmax_t n = 0;
 
@@ -114,58 +86,216 @@
 	return 0;
 }
 
-#define STR_TO_U__TEMPLATE(name, type)				\
-int name(const char *str, type *num_r, const char **endp_r)	\
-{								\
-	uintmax_t l;						\
-	if (str_parse_uintmax(str, &l, endp_r) < 0 || l > (type)-1)\
-		return -1;					\
-	*num_r = l;						\
-	return 0;						\
+bool str_uint_equals(const char *str, uintmax_t num)
+{
+	uintmax_t l;
+
+	if (str_to_uintmax(str, &l) < 0)
+		return FALSE;
+	return l == num;
 }
-STR_TO_U__TEMPLATE(str_parse_uoff, uoff_t)
-STR_TO_U__TEMPLATE(str_parse_uint, unsigned int)
 
-int str_to_int(const char *str, int *num_r)
+/* 
+ * Unsigned hexadecimal
+ */
+
+#define STR_PARSE_UHEX__TEMPLATE(name, type)                       \
+int name(const char *str, type *num_r, const char **endp_r)        \
+{                                                                  \
+	uintmax_t l;                                                     \
+	if (str_parse_uintmax_hex(str, &l, endp_r) < 0 || l > (type)-1)  \
+		return -1;                                                     \
+	*num_r = (type)l;                                                \
+	return 0;                                                        \
+}
+
+STR_PARSE_UHEX__TEMPLATE(str_parse_uint_hex, unsigned int)
+STR_PARSE_UHEX__TEMPLATE(str_parse_ulong_hex, unsigned long)
+STR_PARSE_UHEX__TEMPLATE(str_parse_ullong_hex, unsigned long long)
+STR_PARSE_UHEX__TEMPLATE(str_parse_uint32_hex, uint32_t)
+STR_PARSE_UHEX__TEMPLATE(str_parse_uint64_hex, uint64_t)
+
+#define STR_TO_UHEX__TEMPLATE(name, type)                          \
+int name(const char *str, type *num_r)                             \
+{                                                                  \
+	uintmax_t l;                                                     \
+	if (str_to_uintmax_hex(str, &l) < 0 || l > (type)-1)             \
+		return -1;                                                     \
+	*num_r = (type)l;                                                \
+	return 0;                                                        \
+}
+
+STR_TO_UHEX__TEMPLATE(str_to_uint_hex, unsigned int)
+STR_TO_UHEX__TEMPLATE(str_to_ulong_hex, unsigned long)
+STR_TO_UHEX__TEMPLATE(str_to_ullong_hex, unsigned long long)
+STR_TO_UHEX__TEMPLATE(str_to_uint32_hex, uint32_t)
+STR_TO_UHEX__TEMPLATE(str_to_uint64_hex, uint64_t)
+
+static inline int _str_parse_hex(const char ch,
+	unsigned int *hex_r)
 {
-	intmax_t l;
+	switch (ch) {
+	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+		*hex_r = (unsigned int)(ch - 'a' + 10);
+		return 0;
+	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+		*hex_r = (unsigned int)(ch - 'A' + 10);
+		return 0;
+	case '0': case '1': case '2': case '3': case '4':
+	case '5': case '6': case '7': case '8': case '9':
+		*hex_r = (unsigned int)(ch - '0');
+		return 0;
+	default:
+		break;
+	}
+	return -1;
+}
+int str_parse_uintmax_hex(const char *str, uintmax_t *num_r,
+	const char **endp_r)
+{
+	unsigned int hex;
+	uintmax_t n = 0;
 
-	if (str_to_intmax(str, &l) < 0)
+	if (_str_parse_hex(*str, &hex) < 0)
 		return -1;
 
-	if (l < INT_MIN || l > INT_MAX)
+	do {
+		if (n >= ((uintmax_t)-1 >> 4)) {
+			if (n > (uintmax_t)-1 >> 4)
+				return -1;
+			if ((uintmax_t)hex > ((uintmax_t)-1 & 0x0f))
+				return -1;
+		}
+		n = (n << 4) + hex;
+		str++;
+	} while (_str_parse_hex(*str, &hex) >= 0);
+	if (endp_r != NULL)
+		*endp_r = str;
+	*num_r = n;
+	return 0;
+}
+int str_to_uintmax_hex(const char *str, uintmax_t *num_r)
+{
+	const char *endp;
+	uintmax_t n;
+	int ret = str_parse_uintmax_hex(str, &n, &endp);
+	if ((ret != 0) || (*endp != '\0'))
 		return -1;
-	*num_r = (int)l;
+	*num_r = n;
 	return 0;
 }
 
-int str_to_long(const char *str, long *num_r)
+/* 
+ * Unsigned octal
+ */
+
+#define STR_PARSE_UOCT__TEMPLATE(name, type)                       \
+int name(const char *str, type *num_r, const char **endp_r)        \
+{                                                                  \
+	uintmax_t l;                                                     \
+	if (str_parse_uintmax_oct(str, &l, endp_r) < 0 || l > (type)-1)  \
+		return -1;                                                     \
+	*num_r = (type)l;                                                \
+	return 0;                                                        \
+}
+
+STR_PARSE_UOCT__TEMPLATE(str_parse_uint_oct, unsigned int)
+STR_PARSE_UOCT__TEMPLATE(str_parse_ulong_oct, unsigned long)
+STR_PARSE_UOCT__TEMPLATE(str_parse_ullong_oct, unsigned long long)
+STR_PARSE_UOCT__TEMPLATE(str_parse_uint32_oct, uint32_t)
+STR_PARSE_UOCT__TEMPLATE(str_parse_uint64_oct, uint64_t)
+
+#define STR_TO_UOCT__TEMPLATE(name, type)                          \
+int name(const char *str, type *num_r)                             \
+{                                                                  \
+	uintmax_t l;                                                     \
+	if (str_to_uintmax_oct(str, &l) < 0 || l > (type)-1)             \
+		return -1;                                                     \
+	*num_r = (type)l;                                                \
+	return 0;                                                        \
+}
+
+STR_TO_UOCT__TEMPLATE(str_to_uint_oct, unsigned int)
+STR_TO_UOCT__TEMPLATE(str_to_ulong_oct, unsigned long)
+STR_TO_UOCT__TEMPLATE(str_to_ullong_oct, unsigned long long)
+STR_TO_UOCT__TEMPLATE(str_to_uint32_oct, uint32_t)
+STR_TO_UOCT__TEMPLATE(str_to_uint64_oct, uint64_t)
+
+int str_parse_uintmax_oct(const char *str, uintmax_t *num_r,
+	const char **endp_r)
 {
-	intmax_t l;
+	uintmax_t n = 0;
 
-	if (str_to_intmax(str, &l) < 0)
+	if (*str < '0' || *str > '7')
 		return -1;
 
-	if (l < LONG_MIN || l > LONG_MAX)
+	for (; *str >= '0' && *str <= '7'; str++) {
+		if (n >= ((uintmax_t)-1 >> 3)) {
+			if (n > (uintmax_t)-1 >> 3)
+				return -1;
+			if ((uintmax_t)(*str - '0') > ((uintmax_t)-1 & 0x03))
+				return -1;
+		}
+		n = (n << 3) + (*str - '0');
+	}
+	if (endp_r != NULL)
+		*endp_r = str;
+	*num_r = n;
+	return 0;
+}
+int str_to_uintmax_oct(const char *str, uintmax_t *num_r)
+{
+	const char *endp;
+	uintmax_t n;
+	int ret = str_parse_uintmax_oct(str, &n, &endp);
+	if ((ret != 0) || (*endp != '\0'))
 		return -1;
-	*num_r = (long)l;
+	*num_r = n;
 	return 0;
 }
 
-int str_to_llong(const char *str, long long *num_r)


More information about the dovecot-cvs mailing list