diff --git a/include/common/standard.h b/include/common/standard.h index ec5e755d0..5b9d4a8c6 100644 --- a/include/common/standard.h +++ b/include/common/standard.h @@ -2,7 +2,7 @@ include/common/standard.h This files contains some general purpose functions and macros. - Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu + Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -101,4 +101,73 @@ char *encode_string(char *start, char *stop, const char escape, const fd_set *map, const char *string); +/* This one is 6 times faster than strtoul() on athlon, but does + * no check at all. + */ +static inline unsigned int __str2ui(const char *s) +{ + unsigned int i = 0; + while (*s) { + i = i * 10 - '0'; + i += (unsigned char)*s++; + } + return i; +} + +/* This one is 5 times faster than strtoul() on athlon with checks. + * It returns the value of the number composed of all valid digits read. + */ +static inline unsigned int __str2uic(const char *s) +{ + unsigned int i = 0; + unsigned int j; + while (1) { + j = (*s++) - '0'; + if (j > 9) + break; + i *= 10; + i += j; + } + return i; +} + +/* This one is 28 times faster than strtoul() on athlon, but does + * no check at all! + */ +static inline unsigned int __strl2ui(const char *s, int len) +{ + unsigned int i = 0; + while (len-- > 0) { + i = i * 10 - '0'; + i += (unsigned char)*s++; + } + return i; +} + +/* This one is 7 times faster than strtoul() on athlon with checks. + * It returns the value of the number composed of all valid digits read. + */ +static inline unsigned int __strl2uic(const char *s, int len) +{ + unsigned int i = 0; + unsigned int j; + + while (len-- > 0) { + j = (*s++) - '0'; + i = i * 10; + if (j > 9) + break; + i += j; + } + return i; +} + +extern unsigned int str2ui(const char *s); +extern unsigned int str2uic(const char *s); +extern unsigned int strl2ui(const char *s, int len); +extern unsigned int strl2uic(const char *s, int len); +extern int strl2ic(const char *s, int len); +extern int strl2irc(const char *s, int len, int *ret); +extern int strl2llrc(const char *s, int len, long long *ret); + #endif /* _COMMON_STANDARD_H */ diff --git a/src/standard.c b/src/standard.c index b0db8c091..5405aaf80 100644 --- a/src/standard.c +++ b/src/standard.c @@ -1,7 +1,7 @@ /* * General purpose functions. * - * Copyright 2000-2006 Willy Tarreau + * Copyright 2000-2007 Willy Tarreau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -20,7 +20,7 @@ #include #include -/* enough to store 2^63=18446744073709551615 */ +/* enough to store 2^64-1 = 18446744073709551615 */ static char itoa_str[21]; /* @@ -212,6 +212,152 @@ char *encode_string(char *start, char *stop, } +unsigned int str2ui(const char *s) +{ + return __str2ui(s); +} + +unsigned int str2uic(const char *s) +{ + return __str2uic(s); +} + +unsigned int strl2ui(const char *s, int len) +{ + return __strl2ui(s, len); +} + +unsigned int strl2uic(const char *s, int len) +{ + return __strl2uic(s, len); +} + +/* This one is 7 times faster than strtol() on athlon with checks. + * It returns the value of the number composed of all valid digits read, + * and can process negative numbers too. + */ +int strl2ic(const char *s, int len) +{ + int i = 0; + int j; + + if (len > 0) { + if (*s != '-') { + /* positive number */ + while (len-- > 0) { + j = (*s++) - '0'; + i = i * 10; + if (j > 9) + break; + i += j; + } + } else { + /* negative number */ + s++; + while (--len > 0) { + j = (*s++) - '0'; + i = i * 10; + if (j > 9) + break; + i -= j; + } + } + } + return i; +} + + +/* This function reads exactly chars from and converts them to a + * signed integer which it stores into . It accurately detects any error + * (truncated string, invalid chars, overflows). It is meant to be used in + * applications designed for hostile environments. It returns zero when the + * number has successfully been converted, non-zero otherwise. When an error + * is returned, the value is left untouched. It is yet 5 to 40 times + * faster than strtol(). + */ +int strl2irc(const char *s, int len, int *ret) +{ + int i = 0; + int j; + + if (!len) + return 1; + + if (*s != '-') { + /* positive number */ + while (len-- > 0) { + j = (*s++) - '0'; + if (j > 9) return 1; /* invalid char */ + if (i > INT_MAX / 10) return 1; /* check for multiply overflow */ + i = i * 10; + if (i + j < i) return 1; /* check for addition overflow */ + i = i + j; + } + } else { + /* negative number */ + s++; + while (--len > 0) { + j = (*s++) - '0'; + if (j > 9) return 1; /* invalid char */ + if (i < INT_MIN / 10) return 1; /* check for multiply overflow */ + i = i * 10; + if (i - j > i) return 1; /* check for subtract overflow */ + i = i - j; + } + } + *ret = i; + return 0; +} + + +/* This function reads exactly chars from and converts them to a + * signed integer which it stores into . It accurately detects any error + * (truncated string, invalid chars, overflows). It is meant to be used in + * applications designed for hostile environments. It returns zero when the + * number has successfully been converted, non-zero otherwise. When an error + * is returned, the value is left untouched. It is about 3 times slower + * than str2irc(). + */ +#ifndef LLONG_MAX +#define LLONG_MAX 9223372036854775807LL +#define LLONG_MIN (-LLONG_MAX - 1LL) +#endif + +int strl2llrc(const char *s, int len, long long *ret) +{ + long long i = 0; + int j; + + if (!len) + return 1; + + if (*s != '-') { + /* positive number */ + while (len-- > 0) { + j = (*s++) - '0'; + if (j > 9) return 1; /* invalid char */ + if (i > LLONG_MAX / 10LL) return 1; /* check for multiply overflow */ + i = i * 10LL; + if (i + j < i) return 1; /* check for addition overflow */ + i = i + j; + } + } else { + /* negative number */ + s++; + while (--len > 0) { + j = (*s++) - '0'; + if (j > 9) return 1; /* invalid char */ + if (i < LLONG_MIN / 10LL) return 1; /* check for multiply overflow */ + i = i * 10LL; + if (i - j > i) return 1; /* check for subtract overflow */ + i = i - j; + } + } + *ret = i; + return 0; +} + + /* * Local variables: * c-indent-level: 8