Mercurial > hg > octave-kai > gnulib-hg
annotate lib/strcasestr.c @ 6164:83bee8e13391
Include a header, to define NULL.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Wed, 31 Aug 2005 11:51:18 +0000 |
parents | 199c20f568d7 |
children | 1c4ed7637c24 |
rev | line source |
---|---|
6058 | 1 /* Case-insensitive searching in a string. |
2 Copyright (C) 2005 Free Software Foundation, Inc. | |
3 Written by Bruno Haible <bruno@clisp.org>, 2005. | |
4 | |
5 This program is free software; you can redistribute it and/or modify | |
6 it under the terms of the GNU General Public License as published by | |
7 the Free Software Foundation; either version 2, or (at your option) | |
8 any later version. | |
9 | |
10 This program is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 GNU General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU General Public License | |
16 along with this program; if not, write to the Free Software Foundation, | |
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | |
18 | |
19 #ifdef HAVE_CONFIG_H | |
20 # include <config.h> | |
21 #endif | |
22 | |
23 /* Specification. */ | |
24 #include "strcasestr.h" | |
25 | |
26 #include <ctype.h> | |
6164
83bee8e13391
Include a header, to define NULL.
Bruno Haible <bruno@clisp.org>
parents:
6064
diff
changeset
|
27 #include <stddef.h> /* for NULL */ |
6058 | 28 |
29 #if HAVE_MBRTOWC | |
30 # include "mbuiter.h" | |
31 #endif | |
32 | |
33 #define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) | |
34 | |
35 /* Find the first occurrence of NEEDLE in HAYSTACK, using case-insensitive | |
36 comparison. | |
37 Note: This function may, in multibyte locales, return success even if | |
38 strlen (haystack) < strlen (needle) ! */ | |
39 char * | |
40 strcasestr (const char *haystack, const char *needle) | |
41 { | |
42 /* Be careful not to look at the entire extent of haystack or needle | |
43 until needed. This is useful because of these two cases: | |
44 - haystack may be very long, and a match of needle found early, | |
45 - needle may be very long, and not even a short initial segment of | |
46 needle may be found in haystack. */ | |
47 #if HAVE_MBRTOWC | |
48 if (MB_CUR_MAX > 1) | |
49 { | |
50 mbui_iterator_t iter_needle; | |
51 | |
52 mbui_init (iter_needle, needle); | |
53 if (mbui_avail (iter_needle)) | |
54 { | |
55 mbchar_t b; | |
56 mbui_iterator_t iter_haystack; | |
57 | |
58 mb_copy (&b, &mbui_cur (iter_needle)); | |
59 if (b.wc_valid) | |
60 b.wc = towlower (b.wc); | |
61 | |
62 mbui_init (iter_haystack, haystack); | |
63 for (;; mbui_advance (iter_haystack)) | |
64 { | |
65 mbchar_t c; | |
66 | |
67 if (!mbui_avail (iter_haystack)) | |
68 /* No match. */ | |
69 return NULL; | |
70 | |
71 mb_copy (&c, &mbui_cur (iter_haystack)); | |
72 if (c.wc_valid) | |
73 c.wc = towlower (c.wc); | |
74 if (mb_equal (c, b)) | |
75 /* The first character matches. */ | |
76 { | |
77 mbui_iterator_t rhaystack; | |
78 mbui_iterator_t rneedle; | |
79 | |
80 memcpy (&rhaystack, &iter_haystack, sizeof (mbui_iterator_t)); | |
81 mbui_advance (rhaystack); | |
82 | |
83 mbui_init (rneedle, needle); | |
84 if (!mbui_avail (rneedle)) | |
85 abort (); | |
86 mbui_advance (rneedle); | |
87 | |
88 for (;; mbui_advance (rhaystack), mbui_advance (rneedle)) | |
89 { | |
90 if (!mbui_avail (rneedle)) | |
91 /* Found a match. */ | |
6064 | 92 return (char *) mbui_cur_ptr (iter_haystack); |
6058 | 93 if (!mbui_avail (rhaystack)) |
94 /* No match. */ | |
95 return NULL; | |
96 if (!mb_caseequal (mbui_cur (rhaystack), | |
97 mbui_cur (rneedle))) | |
98 /* Nothing in this round. */ | |
99 break; | |
100 } | |
101 } | |
102 } | |
103 } | |
104 else | |
105 return (char *) haystack; | |
106 } | |
107 else | |
108 #endif | |
109 { | |
110 if (*needle != '\0') | |
111 { | |
112 /* Speed up the following searches of needle by caching its first | |
113 character. */ | |
114 unsigned char b = TOLOWER ((unsigned char) *needle); | |
115 | |
116 needle++; | |
117 for (;; haystack++) | |
118 { | |
119 if (*haystack == '\0') | |
120 /* No match. */ | |
121 return NULL; | |
122 if (TOLOWER ((unsigned char) *haystack) == b) | |
123 /* The first character matches. */ | |
124 { | |
125 const char *rhaystack = haystack + 1; | |
126 const char *rneedle = needle; | |
127 | |
128 for (;; rhaystack++, rneedle++) | |
129 { | |
130 if (*rneedle == '\0') | |
131 /* Found a match. */ | |
132 return (char *) haystack; | |
133 if (*rhaystack == '\0') | |
134 /* No match. */ | |
135 return NULL; | |
136 if (TOLOWER ((unsigned char) *rhaystack) | |
137 != TOLOWER ((unsigned char) *rneedle)) | |
138 /* Nothing in this round. */ | |
139 break; | |
140 } | |
141 } | |
142 } | |
143 } | |
144 else | |
145 return (char *) haystack; | |
146 } | |
147 } |