changeset 8156:4610755b157b

New module 'mbsncasecmp'.
author Bruno Haible <bruno@clisp.org>
date Thu, 15 Feb 2007 02:57:13 +0000
parents eca0a6359ada
children a5ef7abbb415
files ChangeLog MODULES.html.sh lib/mbsncasecmp.c lib/string_.h m4/mbsncasecmp.m4 m4/string_h.m4 modules/mbsncasecmp modules/string
diffstat 8 files changed, 176 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Feb 15 00:29:06 2007 +0000
+++ b/ChangeLog	Thu Feb 15 02:57:13 2007 +0000
@@ -1,3 +1,15 @@
+2007-02-11  Bruno Haible  <bruno@clisp.org>
+
+	New module mbsncasecmp.
+	* modules/mbsncasecmp: New file.
+	* lib/mbsncasecmp.c: New file.
+	* lib/string_.h (mbsncasecmp): New declaration.
+	* m4/mbsncasecmp.m4: New file.
+	* m4/string_h.m4 (gl_STRING_MODULE_INDICATOR_DEFAULTS): Initialize
+	GNULIB_MBSNCASECMP.
+	* modules/string (string.h): Also substitute GNULIB_MBSNCASECMP.
+	* MODULES.html.sh (Internationalization functions): Add mbsncasecmp.
+
 2007-02-14  Paul Eggert  <eggert@cs.ucla.edu>
 
 	* lib/exclude.c (FNM_EXTMATCH): Define if system does not.
--- a/MODULES.html.sh	Thu Feb 15 00:29:06 2007 +0000
+++ b/MODULES.html.sh	Thu Feb 15 02:57:13 2007 +0000
@@ -2166,6 +2166,7 @@
   func_module mbsrchr
   func_module mbsstr
   func_module mbscasecmp
+  func_module mbsncasecmp
   func_module mbscasestr
   func_module mbscspn
   func_module mbspbrk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mbsncasecmp.c	Thu Feb 15 02:57:13 2007 +0000
@@ -0,0 +1,104 @@
+/* Case-insensitive string comparison function.
+   Copyright (C) 1998-1999, 2005-2007 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2005,
+   based on earlier glibc code.
+
+   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>
+#include <limits.h>
+
+#if HAVE_MBRTOWC
+# include "mbuiter.h"
+#endif
+
+#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
+
+/* Compare the initial segment of the character string S1 consisting of at most
+   N characters with the initial segment of the character string S2 consisting
+   of at most N characters, ignoring case, returning less than, equal to or
+   greater than zero if the initial segment of S1 is lexicographically less
+   than, equal to or greater than the initial segment of S2.
+   Note: This function may, in multibyte locales, return 0 for initial segments
+   of different lengths!  */
+int
+mbsncasecmp (const char *s1, const char *s2, size_t n)
+{
+  if (s1 == s2 || n == 0)
+    return 0;
+
+  /* Be careful not to look at the entire extent of s1 or s2 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, s1);
+      mbui_init (iter2, s2);
+
+      while (mbui_avail (iter1) && mbui_avail (iter2))
+	{
+	  int cmp = mb_casecmp (mbui_cur (iter1), mbui_cur (iter2));
+
+	  if (cmp != 0)
+	    return cmp;
+
+	  if (--n == 0)
+	    return 0;
+
+	  mbui_advance (iter1);
+	  mbui_advance (iter2);
+	}
+      if (mbui_avail (iter1))
+	/* s2 terminated before s1 and n.  */
+	return 1;
+      if (mbui_avail (iter2))
+	/* s1 terminated before s2 and n.  */
+	return -1;
+      return 0;
+    }
+  else
+#endif
+    {
+      const unsigned char *p1 = (const unsigned char *) s1;
+      const unsigned char *p2 = (const unsigned char *) s2;
+      unsigned char c1, c2;
+
+      for (; ; p1++, p2++)
+	{
+	  c1 = TOLOWER (*p1);
+	  c2 = TOLOWER (*p2);
+
+	  if (--n == 0 || c1 == '\0' || c1 != c2)
+	    break;
+	}
+
+      if (UCHAR_MAX <= INT_MAX)
+	return c1 - c2;
+      else
+	/* On machines where 'char' and 'int' are types of the same size, the
+	   difference of two 'unsigned char' values - including the sign bit -
+	   doesn't fit in an 'int'.  */
+	return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+    }
+}
--- a/lib/string_.h	Thu Feb 15 00:29:06 2007 +0000
+++ b/lib/string_.h	Thu Feb 15 02:57:13 2007 +0000
@@ -415,6 +415,19 @@
 extern int mbscasecmp (const char *s1, const char *s2);
 #endif
 
+#if @GNULIB_MBSNCASECMP@
+/* Compare the initial segment of the character string S1 consisting of at most
+   N characters with the initial segment of the character string S2 consisting
+   of at most N characters, ignoring case, returning less than, equal to or
+   greater than zero if the initial segment of S1 is lexicographically less
+   than, equal to or greater than the initial segment of S2.
+   Note: This function may, in multibyte locales, return 0 for initial segments
+   of different lengths!
+   Unlike strncasecmp(), this function works correctly in multibyte locales.
+   But beware that N is not a byte count but a character count!  */
+extern int mbsncasecmp (const char *s1, const char *s2, size_t n);
+#endif
+
 #if @GNULIB_MBSCASESTR@
 /* Find the first occurrence of the character string NEEDLE in the character
    string HAYSTACK, using case-insensitive comparison.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m4/mbsncasecmp.m4	Thu Feb 15 02:57:13 2007 +0000
@@ -0,0 +1,16 @@
+# mbsncasecmp.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_MBSNCASECMP],
+[
+  gl_PREREQ_MBSNCASECMP
+])
+
+# Prerequisites of lib/mbsncasecmp.c.
+AC_DEFUN([gl_PREREQ_MBSNCASECMP], [
+  AC_REQUIRE([gl_FUNC_MBRTOWC])
+  :
+])
--- a/m4/string_h.m4	Thu Feb 15 00:29:06 2007 +0000
+++ b/m4/string_h.m4	Thu Feb 15 02:57:13 2007 +0000
@@ -72,6 +72,7 @@
   GNULIB_MBSRCHR=0;     AC_SUBST([GNULIB_MBSRCHR])
   GNULIB_MBSSTR=0;      AC_SUBST([GNULIB_MBSSTR])
   GNULIB_MBSCASECMP=0;  AC_SUBST([GNULIB_MBSCASECMP])
+  GNULIB_MBSNCASECMP=0; AC_SUBST([GNULIB_MBSNCASECMP])
   GNULIB_MBSCASESTR=0;  AC_SUBST([GNULIB_MBSCASESTR])
   GNULIB_MBSCSPN=0;     AC_SUBST([GNULIB_MBSCSPN])
   GNULIB_MBSPBRK=0;     AC_SUBST([GNULIB_MBSPBRK])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/mbsncasecmp	Thu Feb 15 02:57:13 2007 +0000
@@ -0,0 +1,28 @@
+Description:
+mbsncasecmp() function: case-insensitive string prefix comparison.
+
+Files:
+lib/mbsncasecmp.c
+m4/mbsncasecmp.m4
+m4/mbrtowc.m4
+
+Depends-on:
+mbuiter
+string
+
+configure.ac:
+gl_FUNC_MBSNCASECMP
+gl_STRING_MODULE_INDICATOR([mbsncasecmp])
+
+Makefile.am:
+lib_SOURCES += mbsncasecmp.c
+
+Include:
+<string.h>
+
+License:
+LGPL
+
+Maintainer:
+Bruno Haible
+
--- a/modules/string	Thu Feb 15 00:29:06 2007 +0000
+++ b/modules/string	Thu Feb 15 02:57:13 2007 +0000
@@ -26,6 +26,7 @@
 	      -e 's|@''GNULIB_MBSRCHR''@|$(GNULIB_MBSRCHR)|g' \
 	      -e 's|@''GNULIB_MBSSTR''@|$(GNULIB_MBSSTR)|g' \
 	      -e 's|@''GNULIB_MBSCASECMP''@|$(GNULIB_MBSCASECMP)|g' \
+	      -e 's|@''GNULIB_MBSNCASECMP''@|$(GNULIB_MBSNCASECMP)|g' \
 	      -e 's|@''GNULIB_MBSCASESTR''@|$(GNULIB_MBSCASESTR)|g' \
 	      -e 's|@''GNULIB_MBSCSPN''@|$(GNULIB_MBSCSPN)|g' \
 	      -e 's|@''GNULIB_MBSPBRK''@|$(GNULIB_MBSPBRK)|g' \