summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2007-02-15 03:07:04 +0000
committerBruno Haible <bruno@clisp.org>2007-02-15 03:07:04 +0000
commit58d5932625bc1e3b8f4438fa6c69a33c3b5f2ebb (patch)
tree7a277301e84b39bfb07a4fd3165206434db51bf3
parent39bc7a80b6719b1c7d0f8fb1b01380649cb8e358 (diff)
downloadgnulib-58d5932625bc1e3b8f4438fa6c69a33c3b5f2ebb.tar.gz
New module 'mbspcasecmp'.
-rw-r--r--ChangeLog13
-rwxr-xr-xMODULES.html.sh1
-rw-r--r--lib/mbspcasecmp.c100
-rw-r--r--lib/string_.h15
-rw-r--r--m4/mbspcasecmp.m416
-rw-r--r--m4/string_h.m41
-rw-r--r--modules/mbspcasecmp28
-rw-r--r--modules/string1
8 files changed, 174 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 57496563e6..2fd90537ea 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
2007-02-14 Bruno Haible <bruno@clisp.org>
+ New module mbspcasecmp.
+ * modules/mbspcasecmp: New file.
+ * lib/mbspcasecmp.c: New file.
+ * lib/string_.h (strncasecmp): Change warning message.
+ (mbspcasecmp): New declaration.
+ * m4/mbspcasecmp.m4: New file.
+ * m4/string_h.m4 (gl_STRING_MODULE_INDICATOR_DEFAULTS): Initialize
+ GNULIB_MBSPCASECMP.
+ * modules/string (string.h): Also substitute GNULIB_MBSPCASECMP.
+ * MODULES.html.sh (Internationalization functions): Add mbspcasecmp.
+
+2007-02-14 Bruno Haible <bruno@clisp.org>
+
* modules/mbsncasecmp-tests: New file.
* tests/test-mbsncasecmp.sh: New file.
* tests/test-mbsncasecmp.c: New file.
diff --git a/MODULES.html.sh b/MODULES.html.sh
index c47dcba945..d47088711f 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -2167,6 +2167,7 @@ func_all_modules ()
func_module mbsstr
func_module mbscasecmp
func_module mbsncasecmp
+ func_module mbspcasecmp
func_module mbscasestr
func_module mbscspn
func_module mbspbrk
diff --git a/lib/mbspcasecmp.c b/lib/mbspcasecmp.c
new file mode 100644
index 0000000000..1e452e8fdb
--- /dev/null
+++ b/lib/mbspcasecmp.c
@@ -0,0 +1,100 @@
+/* Case-insensitive string comparison function.
+ Copyright (C) 1998-1999, 2005-2007 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2007.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+#include <ctype.h>
+
+#if HAVE_MBRTOWC
+# include "mbuiter.h"
+#endif
+
+#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
+
+/* Compare the initial segment of the character string STRING consisting of
+ at most mbslen (PREFIX) characters with the character string PREFIX,
+ ignoring case, returning less than, equal to or greater than zero if this
+ initial segment is lexicographically less than, equal to or greater than
+ PREFIX.
+ Note: This function may, in multibyte locales, return 0 if STRING is of
+ smaller length than PREFIX! */
+char *
+mbspcasecmp (const char *string, const char *prefix)
+{
+ /* This is essentially the same as
+ mbsncasecmp (string, prefix, mbslen (prefix))
+ just with small optimizations. */
+ if (string == prefix)
+ return (char *) (string + strlen (string));
+
+ /* Be careful not to look at the entire extent of STRING or PREFIX until
+ needed. This is useful because when two strings differ, the difference is
+ most often already in the very few first characters. */
+#if HAVE_MBRTOWC
+ if (MB_CUR_MAX > 1)
+ {
+ mbui_iterator_t iter1;
+ mbui_iterator_t iter2;
+
+ mbui_init (iter1, string);
+ mbui_init (iter2, prefix);
+
+ while (mbui_avail (iter1) && mbui_avail (iter2))
+ {
+ int cmp = mb_casecmp (mbui_cur (iter1), mbui_cur (iter2));
+
+ if (cmp != 0)
+ return NULL;
+
+ mbui_advance (iter1);
+ mbui_advance (iter2);
+ }
+ if (!mbui_avail (iter2))
+ /* PREFIX equals STRING or is terminated before STRING. */
+ return (char *) mbui_cur_ptr (iter1);
+ else
+ /* STRING terminated before PREFIX. */
+ return NULL;
+ }
+ else
+#endif
+ {
+ const unsigned char *p1 = (const unsigned char *) string;
+ const unsigned char *p2 = (const unsigned char *) prefix;
+ unsigned char c1, c2;
+
+ for (; ; p1++, p2++)
+ {
+ c1 = TOLOWER (*p1);
+ c2 = TOLOWER (*p2);
+
+ if (c2 == '\0' || c1 != c2)
+ break;
+ }
+
+ if (c2 == '\0')
+ /* PREFIX equals STRING or is terminated before STRING. */
+ return (char *) p1;
+ else
+ /* STRING terminated before PREFIX. */
+ return NULL;
+ }
+}
diff --git a/lib/string_.h b/lib/string_.h
index ccc142b8c4..b7cc315196 100644
--- a/lib/string_.h
+++ b/lib/string_.h
@@ -152,7 +152,7 @@ extern int strncasecmp (char const *s1, char const *s2, size_t n);
as a sequence of bytes, not of characters. */
# undef strncasecmp
# define strncasecmp(a,b,n) \
- (GL_LINK_WARNING ("strncasecmp cannot work correctly on character strings in multibyte locales - don't use it if you care about internationalization; use c_strncasecmp (from gnulib module c-strcase) if you want a locale independent function"), \
+ (GL_LINK_WARNING ("strncasecmp cannot work correctly on character strings in multibyte locales - use mbsncasecmp or mbspcasecmp if you care about internationalization, or use c_strncasecmp (from gnulib module c-strcase) if you want a locale independent function"), \
strncasecmp (a, b, n))
#endif
@@ -428,6 +428,19 @@ extern int mbscasecmp (const char *s1, const char *s2);
extern int mbsncasecmp (const char *s1, const char *s2, size_t n);
#endif
+#if @GNULIB_MBSPCASECMP@
+/* Compare the initial segment of the character string STRING consisting of
+ at most mbslen (PREFIX) characters with the character string PREFIX,
+ ignoring case, returning less than, equal to or greater than zero if this
+ initial segment is lexicographically less than, equal to or greater than
+ PREFIX.
+ Note: This function may, in multibyte locales, return 0 if STRING is of
+ smaller length than PREFIX!
+ Unlike strncasecmp(), this function works correctly in multibyte
+ locales. */
+extern char * mbspcasecmp (const char *string, const char *prefix);
+#endif
+
#if @GNULIB_MBSCASESTR@
/* Find the first occurrence of the character string NEEDLE in the character
string HAYSTACK, using case-insensitive comparison.
diff --git a/m4/mbspcasecmp.m4 b/m4/mbspcasecmp.m4
new file mode 100644
index 0000000000..ce1672ffd2
--- /dev/null
+++ b/m4/mbspcasecmp.m4
@@ -0,0 +1,16 @@
+# mbspcasecmp.m4 serial 1
+dnl Copyright (C) 2007 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_MBSPCASECMP],
+[
+ gl_PREREQ_MBSPCASECMP
+])
+
+# Prerequisites of lib/mbspcasecmp.c.
+AC_DEFUN([gl_PREREQ_MBSPCASECMP], [
+ AC_REQUIRE([gl_FUNC_MBRTOWC])
+ :
+])
diff --git a/m4/string_h.m4 b/m4/string_h.m4
index 607f2e8337..4cc32ad7dc 100644
--- a/m4/string_h.m4
+++ b/m4/string_h.m4
@@ -73,6 +73,7 @@ AC_DEFUN([gl_STRING_MODULE_INDICATOR_DEFAULTS],
GNULIB_MBSSTR=0; AC_SUBST([GNULIB_MBSSTR])
GNULIB_MBSCASECMP=0; AC_SUBST([GNULIB_MBSCASECMP])
GNULIB_MBSNCASECMP=0; AC_SUBST([GNULIB_MBSNCASECMP])
+ GNULIB_MBSPCASECMP=0; AC_SUBST([GNULIB_MBSPCASECMP])
GNULIB_MBSCASESTR=0; AC_SUBST([GNULIB_MBSCASESTR])
GNULIB_MBSCSPN=0; AC_SUBST([GNULIB_MBSCSPN])
GNULIB_MBSPBRK=0; AC_SUBST([GNULIB_MBSPBRK])
diff --git a/modules/mbspcasecmp b/modules/mbspcasecmp
new file mode 100644
index 0000000000..e84a48e0d9
--- /dev/null
+++ b/modules/mbspcasecmp
@@ -0,0 +1,28 @@
+Description:
+mbspcasecmp() function: case-insensitive string prefix comparison.
+
+Files:
+lib/mbspcasecmp.c
+m4/mbspcasecmp.m4
+m4/mbrtowc.m4
+
+Depends-on:
+mbuiter
+string
+
+configure.ac:
+gl_FUNC_MBSPCASECMP
+gl_STRING_MODULE_INDICATOR([mbspcasecmp])
+
+Makefile.am:
+lib_SOURCES += mbspcasecmp.c
+
+Include:
+<string.h>
+
+License:
+LGPL
+
+Maintainer:
+Bruno Haible
+
diff --git a/modules/string b/modules/string
index b389c93db6..7b11e5dd83 100644
--- a/modules/string
+++ b/modules/string
@@ -27,6 +27,7 @@ string.h: string_.h
-e 's|@''GNULIB_MBSSTR''@|$(GNULIB_MBSSTR)|g' \
-e 's|@''GNULIB_MBSCASECMP''@|$(GNULIB_MBSCASECMP)|g' \
-e 's|@''GNULIB_MBSNCASECMP''@|$(GNULIB_MBSNCASECMP)|g' \
+ -e 's|@''GNULIB_MBSPCASECMP''@|$(GNULIB_MBSPCASECMP)|g' \
-e 's|@''GNULIB_MBSCASESTR''@|$(GNULIB_MBSCASESTR)|g' \
-e 's|@''GNULIB_MBSCSPN''@|$(GNULIB_MBSCSPN)|g' \
-e 's|@''GNULIB_MBSPBRK''@|$(GNULIB_MBSPBRK)|g' \