Author: cazfi Date: Sun May 17 00:40:15 2015 New Revision: 29096 URL: http://svn.gna.org/viewcvs/freeciv?rev=29096&view=rev Log: Reimplemented case-insensitive string comparisons to use icu.
See patch #3930 Modified: trunk/common/fc_interface.c trunk/configure.ac trunk/utility/support.c trunk/utility/support.h Modified: trunk/common/fc_interface.c URL: http://svn.gna.org/viewcvs/freeciv/trunk/common/fc_interface.c?rev=29096&r1=29095&r2=29096&view=diff ============================================================================== --- trunk/common/fc_interface.c (original) +++ trunk/common/fc_interface.c Sun May 17 00:40:15 2015 @@ -72,4 +72,5 @@ diplrel_mess_close(); free_data_dir_names(); free_multicast_group(); + cmp_buffers_free(); } Modified: trunk/configure.ac URL: http://svn.gna.org/viewcvs/freeciv/trunk/configure.ac?rev=29096&r1=29095&r2=29096&view=diff ============================================================================== --- trunk/configure.ac (original) +++ trunk/configure.ac Sun May 17 00:40:15 2015 @@ -1181,8 +1181,8 @@ fi AC_CHECK_FUNCS([bind connect fileno flock ftime gethostbyname gethostname \ - getpwuid inet_aton select snooze strcasecmp strcasestr \ - strerror strlcat strlcpy strncasecmp strstr uname usleep \ + getpwuid inet_aton select snooze strcasestr \ + strerror strlcat strlcpy strstr uname usleep \ getline _strcoll stricoll _stricoll strcasecoll getaddrinfo \ backtrace]) Modified: trunk/utility/support.c URL: http://svn.gna.org/viewcvs/freeciv/trunk/utility/support.c?rev=29096&r1=29095&r2=29096&view=diff ============================================================================== --- trunk/utility/support.c (original) +++ trunk/utility/support.c Sun May 17 00:40:15 2015 @@ -96,6 +96,9 @@ #include <zlib.h> #endif +/* ICU */ +#include "unicode/ustring.h" + /* utility */ #include "fciconv.h" #include "fcintl.h" @@ -105,29 +108,91 @@ #include "support.h" +static int cmp_buffer_size = 0; +static UChar *cmp_buffer0 = NULL; +static UChar *cmp_buffer1 = NULL; + +/*************************************************************** + Initial allocation of string comparison buffers. +***************************************************************/ +static void cmp_buffers_initial(void) +{ + if (cmp_buffer0 == NULL) { + cmp_buffer_size = 255; + cmp_buffer0 = fc_malloc(cmp_buffer_size + 1); + cmp_buffer1 = fc_malloc(cmp_buffer_size + 1); + + /* Make sure there's zero after the buffer published with cmp_buffer_size */ + cmp_buffer0[cmp_buffer_size] = '\0'; + cmp_buffer1[cmp_buffer_size] = '\0'; + } +} + +/*************************************************************** + Make string comparison buffers bigger +***************************************************************/ +static void cmp_buffers_increase(void) +{ + cmp_buffer_size *= 1.5; + cmp_buffer0 = fc_realloc(cmp_buffer0, cmp_buffer_size + 1); + cmp_buffer1 = fc_realloc(cmp_buffer1, cmp_buffer_size + 1); + + /* Make sure there's zero after the buffer published with cmp_buffer_size */ + cmp_buffer0[cmp_buffer_size] = '\0'; + cmp_buffer1[cmp_buffer_size] = '\0'; +} + +/*************************************************************** + Free string comparison buffers. +***************************************************************/ +void cmp_buffers_free(void) +{ + if (cmp_buffer0 != NULL) { + free(cmp_buffer0); + cmp_buffer0 = NULL; + free(cmp_buffer1); + cmp_buffer1 = NULL; + cmp_buffer_size = 0; + } +} + /*************************************************************** Compare strings like strcmp(), but ignoring case. ***************************************************************/ int fc_strcasecmp(const char *str0, const char *str1) { + UErrorCode err_code = U_ZERO_ERROR; + int len0; + int len1; + bool enough_mem = FALSE; + if (str0 == NULL) { return -1; } if (str1 == NULL) { return 1; } -#ifdef HAVE_STRCASECMP - return strcasecmp (str0, str1); -#else - for (; fc_tolower(*str0) == fc_tolower(*str1); str0++, str1++) { - if (*str0 == '\0') { - return 0; - } - } - - return ((int) (unsigned char) fc_tolower(*str0)) - - ((int) (unsigned char) fc_tolower(*str1)); -#endif /* HAVE_STRCASECMP */ + + cmp_buffers_initial(); + + while (!enough_mem) { + UErrorCode err_code0 = U_ZERO_ERROR; + UErrorCode err_code1 = U_ZERO_ERROR; + + u_strFromUTF8(cmp_buffer0, cmp_buffer_size, &len0, str0, -1, &err_code0); + u_strFromUTF8(cmp_buffer1, cmp_buffer_size, &len1, str1, -1, &err_code1); + + /* No need to handle U_STRING_NOT_TERMINATED_WARNING here as there's '0' after + * the buffers we were using */ + if (err_code0 == U_BUFFER_OVERFLOW_ERROR || err_code1 == U_BUFFER_OVERFLOW_ERROR) { + cmp_buffers_increase(); + } else { + enough_mem = TRUE; + } + } + + return u_strCaseCompare(cmp_buffer0, -1, cmp_buffer1, -1, + 0, &err_code); } /*************************************************************** @@ -136,30 +201,45 @@ ***************************************************************/ int fc_strncasecmp(const char *str0, const char *str1, size_t n) { + UErrorCode err_code = U_ZERO_ERROR; + int len0; + int len1; + bool enough_mem = FALSE; + if (str0 == NULL) { return -1; } if (str1 == NULL) { return 1; } -#ifdef HAVE_STRNCASECMP - return strncasecmp (str0, str1, n); -#else - size_t i; - - for (i = 0; i < n && fc_tolower(*str0) == fc_tolower(*str1); - i++, str0++, str1++) { - if (*str0 == '\0') { - return 0; - } - } - - if (i == n) - return 0; - else - return ((int) (unsigned char) fc_tolower(*str0)) - - ((int) (unsigned char) fc_tolower(*str1)); -#endif /* HAVE_STRNCASECMP */ + + cmp_buffers_initial(); + + while (!enough_mem) { + UErrorCode err_code0 = U_ZERO_ERROR; + UErrorCode err_code1 = U_ZERO_ERROR; + + u_strFromUTF8(cmp_buffer0, cmp_buffer_size, &len0, str0, -1, &err_code0); + u_strFromUTF8(cmp_buffer1, cmp_buffer_size, &len1, str1, -1, &err_code1); + + /* No need to handle U_STRING_NOT_TERMINATED_WARNING here as there's '0' after + * the buffers we were using */ + if (err_code0 == U_BUFFER_OVERFLOW_ERROR || err_code1 == U_BUFFER_OVERFLOW_ERROR) { + cmp_buffers_increase(); + } else { + enough_mem = TRUE; + } + } + + if (len0 > n) { + len0 = n; + } + if (len1 > n) { + len1 = n; + } + + return u_strCaseCompare(cmp_buffer0, len0, cmp_buffer1, len1, + 0, &err_code); } /*************************************************************** Modified: trunk/utility/support.h URL: http://svn.gna.org/viewcvs/freeciv/trunk/utility/support.h?rev=29096&r1=29095&r2=29096&view=diff ============================================================================== --- trunk/utility/support.h (original) +++ trunk/utility/support.h Sun May 17 00:40:15 2015 @@ -110,6 +110,8 @@ int fc_strncasecmp(const char *str0, const char *str1, size_t n); int fc_strncasequotecmp(const char *str0, const char *str1, size_t n); +void cmp_buffers_free(void); + size_t effectivestrlenquote(const char *str); char *fc_strcasestr(const char *haystack, const char *needle); _______________________________________________ Freeciv-commits mailing list Freeciv-commits@gna.org https://mail.gna.org/listinfo/freeciv-commits