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

Reply via email to