From 980fe05f47b9d6dd8626b5ea021e2c16807ff5ca Mon Sep 17 00:00:00 2001 From: corvid Date: Fri, 11 Nov 2011 04:26:41 +0000 Subject: locale-independent ASCII character case handling Basically, I and i are different letters in Turkic languages, and this causes problems for str(n)casecmp and toupper/tolower in these locales when dillo is dealing with ASCII. --- dlib/dlib.c | 32 ++++++++++++++++++++++++++++++-- dlib/dlib.h | 10 +++++----- 2 files changed, 35 insertions(+), 7 deletions(-) (limited to 'dlib') diff --git a/dlib/dlib.c b/dlib/dlib.c index a3c59060..002adcdf 100644 --- a/dlib/dlib.c +++ b/dlib/dlib.c @@ -172,17 +172,22 @@ char *dStrsep(char **orig, const char *delim) return str; } +/* + * ASCII functions to avoid the case difficulties introduced by I/i in + * Turkic locales. + */ + /* * Case insensitive strstr */ -char *dStristr(const char *haystack, const char *needle) +char *dStriAsciiStr(const char *haystack, const char *needle) { int i, j; char *ret = NULL; if (haystack && needle) { for (i = 0, j = 0; haystack[i] && needle[j]; ++i) - if (tolower(haystack[i]) == tolower(needle[j])) { + if (D_ASCII_TOLOWER(haystack[i]) == D_ASCII_TOLOWER(needle[j])) { ++j; } else if (j) { i -= j; @@ -194,6 +199,29 @@ char *dStristr(const char *haystack, const char *needle) return ret; } +int dStrAsciiCasecmp(const char *s1, const char *s2) +{ + int ret = 0; + + while ((*s1 || *s2) && + !(ret = D_ASCII_TOLOWER(*s1) - D_ASCII_TOLOWER(*s2))) { + s1++; + s2++; + } + return ret; +} + +int dStrnAsciiCasecmp(const char *s1, const char *s2, size_t n) +{ + int ret = 0; + + while (n-- && (*s1 || *s2) && + !(ret = D_ASCII_TOLOWER(*s1) - D_ASCII_TOLOWER(*s2))) { + s1++; + s2++; + } + return ret; +} /* *- dStr ---------------------------------------------------------------------- diff --git a/dlib/dlib.h b/dlib/dlib.h index cd612d28..8dc324a7 100644 --- a/dlib/dlib.h +++ b/dlib/dlib.h @@ -5,7 +5,6 @@ #include /* for size_t */ #include /* for va_list */ #include /* for strerror */ -#include /* for strcasecmp, strncasecmp (POSIX 2001) */ #include "d_size.h" @@ -34,6 +33,8 @@ extern "C" { #define dIsspace(c) isspace((uchar_t)(c)) #define dIsalnum(c) isalnum((uchar_t)(c)) +#define D_ASCII_TOUPPER(c) (((c) >= 'a' && (c) <= 'z') ? (c) - 0x20 : (c)) +#define D_ASCII_TOLOWER(c) (((c) >= 'A' && (c) <= 'Z') ? (c) + 0x20 : (c)) /* *-- Casts ------------------------------------------------------------------- */ @@ -86,12 +87,11 @@ char *dStrconcat(const char *s1, ...); char *dStrstrip(char *s); char *dStrnfill(size_t len, char c); char *dStrsep(char **orig, const char *delim); -char *dStristr(const char *haystack, const char *needle); void dStrshred(char *s); +char *dStriAsciiStr(const char *haystack, const char *needle); +int dStrAsciiCasecmp(const char *s1, const char *s2); +int dStrnAsciiCasecmp(const char *s1, const char *s2, size_t n); -/* these are in POSIX 2001. Could be implemented if a port requires it */ -#define dStrcasecmp strcasecmp -#define dStrncasecmp strncasecmp #define dStrerror strerror /* -- cgit v1.2.3