dovecot-2.0: Added str_to_*() for converting strings to numbers,...

dovecot at dovecot.org dovecot at dovecot.org
Wed Apr 7 01:49:34 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/b262aad23e59
changeset: 11085:b262aad23e59
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Apr 07 01:48:03 2010 +0300
description:
Added str_to_*() for converting strings to numbers, plus a few helper functions.
The str_to_*() return failure also if integer is too large or too small to
fit into destination.

diffstat:

 src/lib/Makefile.am |    2 +
 src/lib/lib.h       |    1 +
 src/lib/strnum.c    |  253 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lib/strnum.h    |   36 +++++++
 4 files changed, 292 insertions(+), 0 deletions(-)

diffs (truncated from 327 to 300 lines):

diff -r 88a7e034ebc1 -r b262aad23e59 src/lib/Makefile.am
--- a/src/lib/Makefile.am	Wed Apr 07 00:45:00 2010 +0300
+++ b/src/lib/Makefile.am	Wed Apr 07 01:48:03 2010 +0300
@@ -104,6 +104,7 @@
 	str-sanitize.c \
 	strescape.c \
 	strfuncs.c \
+	strnum.c \
 	time-util.c \
 	unix-socket-create.c \
 	unlink-directory.c \
@@ -198,6 +199,7 @@
 	str-sanitize.h \
 	strescape.h \
 	strfuncs.h \
+	strnum.h \
 	time-util.h \
 	unix-socket-create.h \
 	unlink-directory.h \
diff -r 88a7e034ebc1 -r b262aad23e59 src/lib/lib.h
--- a/src/lib/lib.h	Wed Apr 07 00:45:00 2010 +0300
+++ b/src/lib/lib.h	Wed Apr 07 01:48:03 2010 +0300
@@ -37,6 +37,7 @@
 
 #include "array-decl.h" /* ARRAY_DEFINE()s may exist in any header */
 #include "strfuncs.h"
+#include "strnum.h"
 
 size_t nearest_power(size_t num) ATTR_CONST;
 
diff -r 88a7e034ebc1 -r b262aad23e59 src/lib/strnum.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/strnum.c	Wed Apr 07 01:48:03 2010 +0300
@@ -0,0 +1,253 @@
+/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "strnum.h"
+
+bool str_is_numeric(const char *str, char end_char)
+{
+	if (*str == '\0' || *str == end_char)
+		return FALSE;
+
+	while (*str != '\0' && *str != end_char) {
+		if (*str < '0' || *str > '9')
+			return FALSE;
+		str++;
+	}
+
+	return TRUE;
+}
+
+int str_to_uint(const char *str, unsigned int *num_r)
+{
+	uintmax_t l;
+
+	if (str_to_uintmax(str, &l) < 0)
+		return -1;
+
+	if (l > (unsigned int)-1)
+		return -1;
+	*num_r = (unsigned int)l;
+	return 0;
+}
+
+int str_to_ulong(const char *str, unsigned long *num_r)
+{
+	uintmax_t l;
+
+	if (str_to_uintmax(str, &l) < 0)
+		return -1;
+
+	if (l > (unsigned long)-1)
+		return -1;
+	*num_r = (unsigned long)l;
+	return 0;
+}
+
+int str_to_ullong(const char *str, unsigned long long *num_r)
+{
+	uintmax_t l;
+
+	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_to_uintmax(const char *str, uintmax_t *num_r)
+{
+	uintmax_t next, n = 0;
+
+	if (*str < '0' || *str > '9')
+		return -1;
+
+	for (; *str >= '0' && *str <= '9'; str++) {
+		next = n*10;
+		if (next < n) {
+			/* overflow */
+			return -1;
+		}
+		n = next + (*str - '0');
+	}
+	if (str != '\0')
+		return -1;
+	*num_r = n;
+	return 0;
+}
+
+int str_to_int(const char *str, int *num_r)
+{
+	intmax_t l;
+
+	if (str_to_intmax(str, &l) < 0)
+		return -1;
+
+	if (l < INT_MIN || l > INT_MAX)
+		return -1;
+	*num_r = (int)l;
+	return 0;
+}
+
+int str_to_long(const char *str, long *num_r)
+{
+	intmax_t l;
+
+	if (str_to_intmax(str, &l) < 0)
+		return -1;
+
+	if (l < LONG_MIN || l > LONG_MAX)
+		return -1;
+	*num_r = (long)l;
+	return 0;
+}
+
+int str_to_llong(const char *str, long long *num_r)
+{
+	intmax_t l;
+
+	if (str_to_intmax(str, &l) < 0)
+		return -1;
+
+	if (l < LLONG_MIN || l > LLONG_MAX)
+		return -1;
+	*num_r = (long long)l;
+	return 0;
+}
+
+int str_to_intmax(const char *str, intmax_t *num_r)
+{
+	bool neg = FALSE;
+	uintmax_t l;
+
+	if (*str == '-') {
+		neg = TRUE;
+		str++;
+	}
+	if (str_to_uintmax(str, &l) < 0)
+		return -1;
+
+	if (!neg) {
+		if (l > INTMAX_MAX)
+			return -1;
+		*num_r = (intmax_t)l;
+	} else {
+		if (l > UINTMAX_MAX - (UINTMAX_MAX + INTMAX_MIN))
+			return -1;
+		*num_r = (intmax_t)-l;
+	}
+	return 0;
+}
+
+static int verify_xid(uintmax_t l, unsigned int result_size)
+{
+	unsigned int result_bits;
+
+	/* we assume that result is a signed type,
+	   but that it can never be negative */
+	result_bits = result_size*CHAR_BIT - 1;
+	if ((l >> result_bits) != 0)
+		return -1;
+	return 0;
+}
+
+int str_to_uid(const char *str, uid_t *num_r)
+{
+	uintmax_t l;
+
+	if (str_to_uintmax(str, &l) < 0)
+		return -1;
+
+	if (verify_xid(l, sizeof(*num_r)) < 0)
+		return -1;
+	*num_r = (uid_t)l;
+	return 0;
+}
+
+int str_to_gid(const char *str, gid_t *num_r)
+{
+	uintmax_t l;
+
+	if (str_to_uintmax(str, &l) < 0)
+		return -1;
+
+	if (verify_xid(l, sizeof(*num_r)) < 0)
+		return -1;
+	*num_r = (gid_t)l;
+	return 0;
+}
+
+int str_to_pid(const char *str, pid_t *num_r)
+{
+	uintmax_t l;
+
+	if (str_to_uintmax(str, &l) < 0)
+		return -1;
+
+	if (verify_xid(l, sizeof(*num_r)) < 0)
+		return -1;
+	*num_r = (pid_t)l;
+	return 0;
+}
+
+int str_to_uoff(const char *str, uoff_t *num_r)
+{
+	uintmax_t l;
+
+	if (str_to_uintmax(str, &l) < 0)
+		return -1;
+
+	if (l > (uoff_t)-1)
+		return -1;
+	*num_r = (uoff_t)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;
+}
+
+const char *str_num_error(const char *str)
+{
+	if (*str == '-') {
+		if (!str_is_numeric(str + 1, '\0'))
+			return "Not a valid number";
+		return "Number too small";
+	} else {
+		if (!str_is_numeric(str, '\0'))
+			return "Not a valid number";
+		return "Number too large";
+	}
+}
diff -r 88a7e034ebc1 -r b262aad23e59 src/lib/strnum.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/strnum.h	Wed Apr 07 01:48:03 2010 +0300
@@ -0,0 +1,36 @@
+#ifndef STRNUM_H
+#define STRNUM_H
+
+/* Return TRUE if all characters in string are numbers.
+   Stop when `end_char' is found from string. */
+bool str_is_numeric(const char *str, char end_char) ATTR_PURE;
+
+/* str_to_*() functions return 0 if string is valid number in valid range.
+   Otherwise -1 is returned and num_r is left untouched */


More information about the dovecot-cvs mailing list