Line data Source code
1 : /* Case-insensitive string comparison function.
2 : Copyright (C) 1998-1999, 2005-2007 Free Software Foundation, Inc.
3 : Written by Bruno Haible <bruno@clisp.org>, 2005,
4 : based on earlier glibc code.
5 :
6 : This program is free software: you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 :
19 : #include <config.h>
20 :
21 : /* Specification. */
22 : #include <string.h>
23 :
24 : #include <ctype.h>
25 : #include <limits.h>
26 :
27 : #if HAVE_MBRTOWC
28 : # include "mbuiter.h"
29 : #endif
30 :
31 : #define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
32 :
33 : /* Compare the character strings S1 and S2, ignoring case, returning less than,
34 : equal to or greater than zero if S1 is lexicographically less than, equal to
35 : or greater than S2.
36 : Note: This function may, in multibyte locales, return 0 for strings of
37 : different lengths! */
38 : int
39 0 : mbscasecmp (const char *s1, const char *s2)
40 : {
41 0 : if (s1 == s2)
42 0 : return 0;
43 :
44 : /* Be careful not to look at the entire extent of s1 or s2 until needed.
45 : This is useful because when two strings differ, the difference is
46 : most often already in the very few first characters. */
47 : #if HAVE_MBRTOWC
48 0 : if (MB_CUR_MAX > 1)
49 : {
50 : mbui_iterator_t iter1;
51 : mbui_iterator_t iter2;
52 :
53 0 : mbui_init (iter1, s1);
54 0 : mbui_init (iter2, s2);
55 :
56 0 : while (mbui_avail (iter1) && mbui_avail (iter2))
57 : {
58 0 : int cmp = mb_casecmp (mbui_cur (iter1), mbui_cur (iter2));
59 :
60 0 : if (cmp != 0)
61 0 : return cmp;
62 :
63 0 : mbui_advance (iter1);
64 0 : mbui_advance (iter2);
65 : }
66 0 : if (mbui_avail (iter1))
67 : /* s2 terminated before s1. */
68 0 : return 1;
69 0 : if (mbui_avail (iter2))
70 : /* s1 terminated before s2. */
71 0 : return -1;
72 0 : return 0;
73 : }
74 : else
75 : #endif
76 : {
77 0 : const unsigned char *p1 = (const unsigned char *) s1;
78 0 : const unsigned char *p2 = (const unsigned char *) s2;
79 : unsigned char c1, c2;
80 :
81 : do
82 : {
83 0 : c1 = TOLOWER (*p1);
84 0 : c2 = TOLOWER (*p2);
85 :
86 0 : if (c1 == '\0')
87 0 : break;
88 :
89 0 : ++p1;
90 0 : ++p2;
91 : }
92 0 : while (c1 == c2);
93 :
94 : if (UCHAR_MAX <= INT_MAX)
95 0 : return c1 - c2;
96 : else
97 : /* On machines where 'char' and 'int' are types of the same size, the
98 : difference of two 'unsigned char' values - including the sign bit -
99 : doesn't fit in an 'int'. */
100 : return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
101 : }
102 : }
|