From 7eb990d5ce5177913604fa7de8b6f49a0fa72251 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sat, 16 Feb 2008 20:50:49 +0000 Subject: [PATCH] r14212@tombo: nickm | 2008-02-16 15:29:17 -0500 Add new evutil_strtoll() function so we can apply 64-bit content-length patch from Scott Lamb in a portable way. [Backport to 1.4] svn:r642 --- ChangeLog | 1 + configure.in | 4 +++- evutil.c | 30 ++++++++++++++++++++++++++++++ evutil.h | 11 +++++++++++ test/regress.c | 28 ++++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index be4cc172..75c97da1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ Changes in 1.4.2: o devpoll and evport need reinit; tested by W.C.A Wijngaards o event_base_get_method; from Springande Ulv o Send CRLF after each chunk in HTTP output, for compliance with RFC2626. Patch from "propanbutan". Fixes bug 1894184. + o Add a int64_t parsing function, with unit tests, so we can apply Scott Lamb's fix to allow large HTTP values. Changes in 1.4.1-beta: o free minheap on event_base_free(); from Christopher Layne diff --git a/configure.in b/configure.in index d2f1f21d..c7cad49c 100644 --- a/configure.in +++ b/configure.in @@ -133,7 +133,9 @@ AC_C_INLINE AC_HEADER_TIME dnl Checks for library functions. -AC_CHECK_FUNCS(gettimeofday vasprintf fcntl clock_gettime strtok_r strsep getaddrinfo getnameinfo strlcpy inet_ntop signal sigaction) +AC_CHECK_FUNCS(gettimeofday vasprintf fcntl clock_gettime strtok_r strsep getaddrinfo getnameinfo strlcpy inet_ntop signal sigaction strtoll) + +AC_CHECK_SIZEOF(long) if test "x$ac_cv_func_clock_gettime" = "xyes"; then AC_DEFINE(DNS_USE_CPU_CLOCK_FOR_ID, 1, [Define if clock_gettime is available in libc]) diff --git a/evutil.c b/evutil.c index 47136f08..e536b120 100644 --- a/evutil.c +++ b/evutil.c @@ -46,6 +46,9 @@ #ifdef HAVE_FCNTL_H #include #endif +#ifdef HAVE_STDLIB_H +#include +#endif #include #include "evutil.h" @@ -166,3 +169,30 @@ evutil_make_socket_nonblocking(int fd) return 0; } +ev_int64_t +evutil_strtoll(const char *s, char **endptr, int base) +{ +#ifdef HAVE_STRTOLL + return (ev_int64_t)strtoll(s, endptr, base); +#elif SIZEOF_LONG == 8 + return (ev_int64_t)strtol(s, endptr, base); +#elif defined(WIN32) && defined(_MSC_VER) && _MSC_VER < 1300 + /* XXXX on old versions of MS APIs, we only support base + * 10. */ + ev_int64_t r; + if (base != 10) + return 0; + r = (ev_int64_t) _atoi64(s); + while (isspace(*s)) + ++s; + while (isdigit(*s)) + ++s; + if (endptr) + *endptr = (char*) s; + return r; +#elif defined(WIN32) + return (ev_int64_t) _strtoi64(s, endptr, base); +#else +#error "I don't know how to parse 64-bit integers." +#endif +} diff --git a/evutil.h b/evutil.h index d156e663..161ab216 100644 --- a/evutil.h +++ b/evutil.h @@ -115,13 +115,24 @@ int evutil_make_socket_nonblocking(int sock); #define ev_uint32_t uint32_t #define ev_uint16_t uint16_t #define ev_uint8_t uint8_t +#define ev_int64_t int64_t +#define ev_int32_t int32_t +#define ev_int16_t int16_t +#define ev_int8_t int8_t #elif defined(WIN32) #define ev_uint64_t __uint64_t #define ev_uint32_t unsigned int #define ev_uint16_t unsigned short #define ev_uint8_t unsigned char +#define ev_int64_t __int64_t +#define ev_int32_t signed int +#define ev_int16_t signed short +#define ev_int8_t signed char #endif +/* big-int related functions */ +ev_int64_t evutil_strtoll(const char *s, char **endptr, int base); + #ifdef __cplusplus } #endif diff --git a/test/regress.c b/test/regress.c index 383e3268..0c8d92bd 100644 --- a/test/regress.c +++ b/test/regress.c @@ -1336,6 +1336,32 @@ rpc_test(void) fprintf(stdout, "OK\n"); } +static void +test_evutil_strtoll(void) +{ + const char *s; + char *endptr; + setup_test("evutil_stroll: "); + test_ok = 0; + + if (evutil_strtoll("5000000000", NULL, 10) != ((ev_int64_t)5000000)*1000) + goto err; + if (evutil_strtoll("-5000000000", NULL, 10) != ((ev_int64_t)5000000)*-1000) + goto err; + s = " 99999stuff"; + if (evutil_strtoll(s, &endptr, 10) != (ev_int64_t)99999) + goto err; + if (endptr != s+6) + goto err; + if (evutil_strtoll("foo", NULL, 10) != 0) + goto err; + + test_ok = 1; + err: + cleanup_test(); +} + + int main (int argc, char **argv) { @@ -1354,6 +1380,8 @@ main (int argc, char **argv) /* Initalize the event library */ global_base = event_init(); + test_evutil_strtoll(); + /* use the global event base and need to be called first */ test_priorities(1); test_priorities(2);