1 |
/* strcasecmp.c -- case insensitive string comparator |
/* Case-insensitive string comparison function. |
2 |
Copyright (C) 1998, 1999 Free Software Foundation, Inc. |
Copyright (C) 1998, 1999, 2005 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 |
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 |
it under the terms of the GNU General Public License as published by |
17 |
along with this program; if not, write to the Free Software Foundation, |
along with this program; if not, write to the Free Software Foundation, |
18 |
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ |
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ |
19 |
|
|
20 |
#if HAVE_CONFIG_H |
#ifdef HAVE_CONFIG_H |
21 |
# include <config.h> |
# include <config.h> |
22 |
#endif |
#endif |
23 |
|
|
24 |
#ifdef LENGTH_LIMIT |
/* Specification. */ |
25 |
# define STRXCASECMP_FUNCTION strncasecmp |
#include "strcase.h" |
|
# define STRXCASECMP_DECLARE_N , size_t n |
|
|
# define LENGTH_LIMIT_EXPR(Expr) Expr |
|
|
#else |
|
|
# define STRXCASECMP_FUNCTION strcasecmp |
|
|
# define STRXCASECMP_DECLARE_N /* empty */ |
|
|
# define LENGTH_LIMIT_EXPR(Expr) 0 |
|
|
#endif |
|
26 |
|
|
|
#include <stddef.h> |
|
27 |
#include <ctype.h> |
#include <ctype.h> |
28 |
|
#include <limits.h> |
29 |
|
|
30 |
#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) |
#if HAVE_MBRTOWC |
31 |
|
# include "mbuiter.h" |
32 |
|
#endif |
33 |
|
|
34 |
/* Compare {{no more than N characters of }}strings S1 and S2, |
#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) |
|
ignoring case, returning less than, equal to or |
|
|
greater than zero if S1 is lexicographically less |
|
|
than, equal to or greater than S2. */ |
|
35 |
|
|
36 |
|
/* Compare strings S1 and S2, ignoring case, returning less than, equal to or |
37 |
|
greater than zero if S1 is lexicographically less than, equal to or greater |
38 |
|
than S2. |
39 |
|
Note: This function may, in multibyte locales, return 0 for strings of |
40 |
|
different lengths! */ |
41 |
int |
int |
42 |
STRXCASECMP_FUNCTION (const char *s1, const char *s2 STRXCASECMP_DECLARE_N) |
strcasecmp (const char *s1, const char *s2) |
43 |
{ |
{ |
44 |
register const unsigned char *p1 = (const unsigned char *) s1; |
if (s1 == s2) |
|
register const unsigned char *p2 = (const unsigned char *) s2; |
|
|
unsigned char c1, c2; |
|
|
|
|
|
if (p1 == p2 || LENGTH_LIMIT_EXPR (n == 0)) |
|
45 |
return 0; |
return 0; |
46 |
|
|
47 |
do |
/* Be careful not to look at the entire extent of s1 or s2 until needed. |
48 |
|
This is useful because when two strings differ, the difference is |
49 |
|
most often already in the very few first characters. */ |
50 |
|
#if HAVE_MBRTOWC |
51 |
|
if (MB_CUR_MAX > 1) |
52 |
{ |
{ |
53 |
c1 = TOLOWER (*p1); |
mbui_iterator_t iter1; |
54 |
c2 = TOLOWER (*p2); |
mbui_iterator_t iter2; |
55 |
|
|
56 |
if (LENGTH_LIMIT_EXPR (--n == 0) || c1 == '\0') |
mbui_init (iter1, s1); |
57 |
break; |
mbui_init (iter2, s2); |
58 |
|
|
59 |
++p1; |
while (mbui_avail (iter1) && mbui_avail (iter2)) |
60 |
++p2; |
{ |
61 |
|
int cmp = mb_casecmp (mbui_cur (iter1), mbui_cur (iter2)); |
62 |
|
|
63 |
|
if (cmp != 0) |
64 |
|
return cmp; |
65 |
|
|
66 |
|
mbui_advance (iter1); |
67 |
|
mbui_advance (iter2); |
68 |
|
} |
69 |
|
if (mbui_avail (iter1)) |
70 |
|
/* s2 terminated before s1. */ |
71 |
|
return 1; |
72 |
|
if (mbui_avail (iter2)) |
73 |
|
/* s1 terminated before s2. */ |
74 |
|
return -1; |
75 |
|
return 0; |
76 |
|
} |
77 |
|
else |
78 |
|
#endif |
79 |
|
{ |
80 |
|
const unsigned char *p1 = (const unsigned char *) s1; |
81 |
|
const unsigned char *p2 = (const unsigned char *) s2; |
82 |
|
unsigned char c1, c2; |
83 |
|
|
84 |
|
do |
85 |
|
{ |
86 |
|
c1 = TOLOWER (*p1); |
87 |
|
c2 = TOLOWER (*p2); |
88 |
|
|
89 |
|
if (c1 == '\0') |
90 |
|
break; |
91 |
|
|
92 |
|
++p1; |
93 |
|
++p2; |
94 |
|
} |
95 |
|
while (c1 == c2); |
96 |
|
|
97 |
|
if (UCHAR_MAX <= INT_MAX) |
98 |
|
return c1 - c2; |
99 |
|
else |
100 |
|
/* On machines where 'char' and 'int' are types of the same size, the |
101 |
|
difference of two 'unsigned char' values - including the sign bit - |
102 |
|
doesn't fit in an 'int'. */ |
103 |
|
return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); |
104 |
} |
} |
|
while (c1 == c2); |
|
|
|
|
|
return c1 - c2; |
|
105 |
} |
} |