xref: /dflybsd-src/contrib/cvs-1.12/lib/strcasecmp.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /* Case-insensitive string comparison function.
286d7f5d3SJohn Marino    Copyright (C) 1998, 1999, 2005 Free Software Foundation, Inc.
386d7f5d3SJohn Marino    Written by Bruno Haible <bruno@clisp.org>, 2005,
486d7f5d3SJohn Marino    based on earlier glibc code.
586d7f5d3SJohn Marino 
686d7f5d3SJohn Marino    This program is free software; you can redistribute it and/or modify
786d7f5d3SJohn Marino    it under the terms of the GNU General Public License as published by
886d7f5d3SJohn Marino    the Free Software Foundation; either version 2, or (at your option)
986d7f5d3SJohn Marino    any later version.
1086d7f5d3SJohn Marino 
1186d7f5d3SJohn Marino    This program is distributed in the hope that it will be useful,
1286d7f5d3SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
1386d7f5d3SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1486d7f5d3SJohn Marino    GNU General Public License for more details.
1586d7f5d3SJohn Marino 
1686d7f5d3SJohn Marino    You should have received a copy of the GNU General Public License
1786d7f5d3SJohn Marino    along with this program; if not, write to the Free Software Foundation,
1886d7f5d3SJohn Marino    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
1986d7f5d3SJohn Marino 
2086d7f5d3SJohn Marino #ifdef HAVE_CONFIG_H
2186d7f5d3SJohn Marino # include <config.h>
2286d7f5d3SJohn Marino #endif
2386d7f5d3SJohn Marino 
2486d7f5d3SJohn Marino /* Specification.  */
2586d7f5d3SJohn Marino #include "strcase.h"
2686d7f5d3SJohn Marino 
2786d7f5d3SJohn Marino #include <ctype.h>
2886d7f5d3SJohn Marino 
2986d7f5d3SJohn Marino #if HAVE_MBRTOWC
3086d7f5d3SJohn Marino # include "mbuiter.h"
3186d7f5d3SJohn Marino #endif
3286d7f5d3SJohn Marino 
3386d7f5d3SJohn Marino #define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
3486d7f5d3SJohn Marino 
3586d7f5d3SJohn Marino /* Compare strings S1 and S2, ignoring case, returning less than, equal to or
3686d7f5d3SJohn Marino    greater than zero if S1 is lexicographically less than, equal to or greater
3786d7f5d3SJohn Marino    than S2.
3886d7f5d3SJohn Marino    Note: This function may, in multibyte locales, return 0 for strings of
3986d7f5d3SJohn Marino    different lengths!  */
4086d7f5d3SJohn Marino int
strcasecmp(const char * s1,const char * s2)4186d7f5d3SJohn Marino strcasecmp (const char *s1, const char *s2)
4286d7f5d3SJohn Marino {
4386d7f5d3SJohn Marino   if (s1 == s2)
4486d7f5d3SJohn Marino     return 0;
4586d7f5d3SJohn Marino 
4686d7f5d3SJohn Marino   /* Be careful not to look at the entire extent of s1 or s2 until needed.
4786d7f5d3SJohn Marino      This is useful because when two strings differ, the difference is
4886d7f5d3SJohn Marino      most often already in the very few first characters.  */
4986d7f5d3SJohn Marino #if HAVE_MBRTOWC
5086d7f5d3SJohn Marino   if (MB_CUR_MAX > 1)
5186d7f5d3SJohn Marino     {
5286d7f5d3SJohn Marino       mbui_iterator_t iter1;
5386d7f5d3SJohn Marino       mbui_iterator_t iter2;
5486d7f5d3SJohn Marino 
5586d7f5d3SJohn Marino       mbui_init (iter1, s1);
5686d7f5d3SJohn Marino       mbui_init (iter2, s2);
5786d7f5d3SJohn Marino 
5886d7f5d3SJohn Marino       while (mbui_avail (iter1) && mbui_avail (iter2))
5986d7f5d3SJohn Marino 	{
6086d7f5d3SJohn Marino 	  int cmp = mb_casecmp (mbui_cur (iter1), mbui_cur (iter2));
6186d7f5d3SJohn Marino 
6286d7f5d3SJohn Marino 	  if (cmp != 0)
6386d7f5d3SJohn Marino 	    return cmp;
6486d7f5d3SJohn Marino 
6586d7f5d3SJohn Marino 	  mbui_advance (iter1);
6686d7f5d3SJohn Marino 	  mbui_advance (iter2);
6786d7f5d3SJohn Marino 	}
6886d7f5d3SJohn Marino       if (mbui_avail (iter1))
6986d7f5d3SJohn Marino 	/* s2 terminated before s1.  */
7086d7f5d3SJohn Marino 	return 1;
7186d7f5d3SJohn Marino       if (mbui_avail (iter2))
7286d7f5d3SJohn Marino 	/* s1 terminated before s2.  */
7386d7f5d3SJohn Marino 	return -1;
7486d7f5d3SJohn Marino       return 0;
7586d7f5d3SJohn Marino     }
7686d7f5d3SJohn Marino   else
7786d7f5d3SJohn Marino #endif
7886d7f5d3SJohn Marino     {
7986d7f5d3SJohn Marino       const unsigned char *p1 = (const unsigned char *) s1;
8086d7f5d3SJohn Marino       const unsigned char *p2 = (const unsigned char *) s2;
8186d7f5d3SJohn Marino       unsigned char c1, c2;
8286d7f5d3SJohn Marino 
8386d7f5d3SJohn Marino       do
8486d7f5d3SJohn Marino 	{
8586d7f5d3SJohn Marino 	  c1 = TOLOWER (*p1);
8686d7f5d3SJohn Marino 	  c2 = TOLOWER (*p2);
8786d7f5d3SJohn Marino 
8886d7f5d3SJohn Marino 	  if (c1 == '\0')
8986d7f5d3SJohn Marino 	    break;
9086d7f5d3SJohn Marino 
9186d7f5d3SJohn Marino 	  ++p1;
9286d7f5d3SJohn Marino 	  ++p2;
9386d7f5d3SJohn Marino 	}
9486d7f5d3SJohn Marino       while (c1 == c2);
9586d7f5d3SJohn Marino 
9686d7f5d3SJohn Marino       return c1 - c2;
9786d7f5d3SJohn Marino     }
9886d7f5d3SJohn Marino }
99