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