diff --git a/evdns.c b/evdns.c index 7b76ee39..01ff0bde 100644 --- a/evdns.c +++ b/evdns.c @@ -95,7 +95,6 @@ #endif #include #include -#include #include #include @@ -107,6 +106,7 @@ #include "ipv6-internal.h" #include "util-internal.h" #ifdef WIN32 +#include #include #include #include @@ -360,9 +360,6 @@ static int strtoint(const char *const str); #define CLOSE_SOCKET(s) EVUTIL_CLOSESOCKET(s) -#define ISSPACE(c) isspace((int)(unsigned char)(c)) -#define ISDIGIT(c) isdigit((int)(unsigned char)(c)) - static const char * debug_ntoa(u32 address) { @@ -2353,10 +2350,6 @@ string_num_dots(const char *s) { return count; } -/* Helper: provide a working isalpha implementation on platforms with funny - * ideas about character types and isalpha behavior. */ -#define ISALPHA(c) isalpha((int)(unsigned char)(c)) - static struct evdns_request * request_new(struct evdns_base *base, int type, const char *name, int flags, evdns_callback_type callback, void *user_ptr) { @@ -2389,7 +2382,7 @@ request_new(struct evdns_base *base, int type, const char *name, int flags, strlcpy(namebuf, name, sizeof(namebuf)); rand_bytes_function(randbits, (name_len+7)/8); for (i = 0; i < name_len; ++i) { - if (ISALPHA(namebuf[i])) { + if (EVUTIL_ISALPHA(namebuf[i])) { if ((randbits[i >> 3] & (1<<(i & 7)))) namebuf[i] |= 0x20; else @@ -3079,10 +3072,10 @@ evdns_nameserver_ip_add_line(struct evdns_base *base, const char *ips) { char *buf; int r; while (*ips) { - while (ISSPACE(*ips) || *ips == ',' || *ips == '\t') + while (isspace(*ips) || *ips == ',' || *ips == '\t') ++ips; addr = ips; - while (ISDIGIT(*ips) || *ips == '.' || *ips == ':') + while (isdigit(*ips) || *ips == '.' || *ips == ':') ++ips; buf = mm_malloc(ips-addr+1); if (!buf) return 4; diff --git a/evrpc.c b/evrpc.c index 25e7bf78..a925ffb4 100644 --- a/evrpc.c +++ b/evrpc.c @@ -53,7 +53,6 @@ #include #include -#include "util-internal.h" #include "event2/event.h" #include "event2/event_struct.h" #include "evrpc.h" @@ -63,7 +62,8 @@ #include "event2/tag.h" #include "event2/http_struct.h" #include "event2/http_compat.h" -#include "evutil.h" +#include "event2/util.h" +#include "util-internal.h" #include "log-internal.h" #include "mm-internal.h" diff --git a/evutil.c b/evutil.c index e3ddb96a..38095592 100644 --- a/evutil.c +++ b/evutil.c @@ -50,7 +50,6 @@ #endif #include #include -#include #include #ifdef _EVENT_HAVE_ARPA_INET_H #include @@ -68,6 +67,7 @@ #endif #include "event2/util.h" +#include "util-internal.h" #include "log-internal.h" #include "strlcpy-internal.h" @@ -469,9 +469,6 @@ evutil_inet_ntop(int af, const void *src, char *dst, size_t len) #endif } -#define ISDIGIT(c) isdigit((int)(unsigned char)(c)) -#define ISXDIGIT(c) isxdigit((int)(unsigned char)(c)) - int evutil_inet_pton(int af, const char *src, void *dst) { @@ -504,7 +501,7 @@ evutil_inet_pton(int af, const char *src, void *dst) else { int byte1,byte2,byte3,byte4; char more; - for (eow = dot-1; eow >= src && ISDIGIT(*eow); --eow) + for (eow = dot-1; eow >= src && EVUTIL_ISDIGIT(*eow); --eow) ; ++eow; @@ -529,7 +526,7 @@ evutil_inet_pton(int af, const char *src, void *dst) while (src < eow) { if (i > 7) return 0; - if (ISXDIGIT(*src)) { + if (EVUTIL_ISXDIGIT(*src)) { char *next; long r = strtol(src, &next, 16); if (next > 4+src) @@ -679,3 +676,59 @@ evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int o return 0; } } + +/* Tables to implement ctypes-replacement EVUTIL_IS*() functions. Each table + * has 256 bits to look up whether a character is in some set or not. This + * fails on non-ASCII platforms, but so does every other place where we + * take a char and write it onto the network. + **/ +const ev_uint32_t EVUTIL_ISALPHA_TABLE[8] = + { 0, 0, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }; +const ev_uint32_t EVUTIL_ISALNUM_TABLE[8] = + { 0, 0x3ff0000, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }; +const ev_uint32_t EVUTIL_ISSPACE_TABLE[8] = { 0x3e00, 0x1, 0, 0, 0, 0, 0, 0 }; +const ev_uint32_t EVUTIL_ISXDIGIT_TABLE[8] = + { 0, 0x3ff0000, 0x7e, 0x7e, 0, 0, 0, 0 }; +const ev_uint32_t EVUTIL_ISDIGIT_TABLE[8] = { 0, 0x3ff0000, 0, 0, 0, 0, 0, 0 }; +const ev_uint32_t EVUTIL_ISPRINT_TABLE[8] = + { 0, 0xffffffff, 0xffffffff, 0x7fffffff, 0, 0, 0, 0x0 }; +const ev_uint32_t EVUTIL_ISUPPER_TABLE[8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 }; +const ev_uint32_t EVUTIL_ISLOWER_TABLE[8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 }; +/* Upper-casing and lowercasing tables to map characters to upper/lowercase + * equivalents. */ +const char EVUTIL_TOUPPER_TABLE[256] = { + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, + 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, + 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, + 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, + 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, + 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, + 96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, + 80,81,82,83,84,85,86,87,88,89,90,123,124,125,126,127, + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, +}; +const char EVUTIL_TOLOWER_TABLE[256] = { + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, + 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, + 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, + 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, + 64,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122,91,92,93,94,95, + 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, +}; diff --git a/http.c b/http.c index 5349c717..18984368 100644 --- a/http.c +++ b/http.c @@ -63,7 +63,6 @@ #endif #include -#include #include #include #include @@ -2125,8 +2124,8 @@ evhttp_decode_uri_internal(const char *uri, size_t length, char *ret) in_query = 1; } else if (c == '+' && in_query) { c = ' '; - } else if (c == '%' && isxdigit((unsigned char)uri[i+1]) && - isxdigit((unsigned char)uri[i+2])) { + } else if (c == '%' && EVUTIL_ISXDIGIT(uri[i+1]) && + EVUTIL_ISXDIGIT(uri[i+2])) { char tmp[] = { uri[i+1], uri[i+2], '\0' }; c = (char)strtol(tmp, NULL, 16); i += 2; @@ -2254,7 +2253,7 @@ prefix_suffix_match(const char *pattern, const char *name, int ignorecase) default: if (c != *name) { if (!ignorecase || - tolower(c) != tolower(*name)) + EVUTIL_TOLOWER(c) != EVUTIL_TOLOWER(*name)) return (0); } ++name; diff --git a/util-internal.h b/util-internal.h index 13b98e0e..b429f57e 100644 --- a/util-internal.h +++ b/util-internal.h @@ -74,6 +74,30 @@ extern "C" { #define socklen_t _EVENT_socklen_t #endif +/* Locale-independent replacements for some ctypes functions. Use these + * when you care about ASCII's notion of character types, because you are about + * to send those types onto the wire. + */ +#define DECLARE_CTYPE_FN(name) \ + static int EVUTIL_##name(char c); \ + extern const ev_uint32_t EVUTIL_##name##_TABLE[]; \ + static inline int EVUTIL_##name(char c) { \ + ev_uint8_t u = c; \ + return !!(EVUTIL_##name##_TABLE[(u >> 5) & 7] & (1 << (u & 31))); \ + } +DECLARE_CTYPE_FN(ISALPHA) +DECLARE_CTYPE_FN(ISALNUM) +DECLARE_CTYPE_FN(ISSPACE) +DECLARE_CTYPE_FN(ISDIGIT) +DECLARE_CTYPE_FN(ISXDIGIT) +DECLARE_CTYPE_FN(ISPRINT) +DECLARE_CTYPE_FN(ISLOWER) +DECLARE_CTYPE_FN(ISUPPER) +extern const char EVUTIL_TOUPPER_TABLE[]; +extern const char EVUTIL_TOLOWER_TABLE[]; +#define EVUTIL_TOLOWER(c) (EVUTIL_TOLOWER_TABLE[(ev_uint8_t)c]) +#define EVUTIL_TOUPPER(c) (EVUTIL_TOUPPER_TABLE[(ev_uint8_t)c]) + #ifdef __cplusplus } #endif