strstr.c revision 1.1.1.1 1 1.1 christos /* Searching in a string.
2 1.1 christos Copyright (C) 2005-2006 Free Software Foundation, Inc.
3 1.1 christos Written by Bruno Haible <bruno (at) clisp.org>, 2005.
4 1.1 christos
5 1.1 christos This program is free software; you can redistribute it and/or modify
6 1.1 christos it under the terms of the GNU General Public License as published by
7 1.1 christos the Free Software Foundation; either version 2, or (at your option)
8 1.1 christos any later version.
9 1.1 christos
10 1.1 christos This program is distributed in the hope that it will be useful,
11 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
12 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 1.1 christos GNU General Public License for more details.
14 1.1 christos
15 1.1 christos You should have received a copy of the GNU General Public License
16 1.1 christos along with this program; if not, write to the Free Software Foundation,
17 1.1 christos Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18 1.1 christos
19 1.1 christos #include <config.h>
20 1.1 christos
21 1.1 christos /* Specification. */
22 1.1 christos #include "strstr.h"
23 1.1 christos
24 1.1 christos #include <stddef.h> /* for NULL */
25 1.1 christos
26 1.1 christos #if HAVE_MBRTOWC
27 1.1 christos # include "mbuiter.h"
28 1.1 christos #endif
29 1.1 christos
30 1.1 christos /* Find the first occurrence of NEEDLE in HAYSTACK. */
31 1.1 christos char *
32 1.1 christos strstr (const char *haystack, const char *needle)
33 1.1 christos {
34 1.1 christos /* Be careful not to look at the entire extent of haystack or needle
35 1.1 christos until needed. This is useful because of these two cases:
36 1.1 christos - haystack may be very long, and a match of needle found early,
37 1.1 christos - needle may be very long, and not even a short initial segment of
38 1.1 christos needle may be found in haystack. */
39 1.1 christos #if HAVE_MBRTOWC
40 1.1 christos if (MB_CUR_MAX > 1)
41 1.1 christos {
42 1.1 christos mbui_iterator_t iter_needle;
43 1.1 christos
44 1.1 christos mbui_init (iter_needle, needle);
45 1.1 christos if (mbui_avail (iter_needle))
46 1.1 christos {
47 1.1 christos mbui_iterator_t iter_haystack;
48 1.1 christos
49 1.1 christos mbui_init (iter_haystack, haystack);
50 1.1 christos for (;; mbui_advance (iter_haystack))
51 1.1 christos {
52 1.1 christos if (!mbui_avail (iter_haystack))
53 1.1 christos /* No match. */
54 1.1 christos return NULL;
55 1.1 christos
56 1.1 christos if (mb_equal (mbui_cur (iter_haystack), mbui_cur (iter_needle)))
57 1.1 christos /* The first character matches. */
58 1.1 christos {
59 1.1 christos mbui_iterator_t rhaystack;
60 1.1 christos mbui_iterator_t rneedle;
61 1.1 christos
62 1.1 christos memcpy (&rhaystack, &iter_haystack, sizeof (mbui_iterator_t));
63 1.1 christos mbui_advance (rhaystack);
64 1.1 christos
65 1.1 christos mbui_init (rneedle, needle);
66 1.1 christos if (!mbui_avail (rneedle))
67 1.1 christos abort ();
68 1.1 christos mbui_advance (rneedle);
69 1.1 christos
70 1.1 christos for (;; mbui_advance (rhaystack), mbui_advance (rneedle))
71 1.1 christos {
72 1.1 christos if (!mbui_avail (rneedle))
73 1.1 christos /* Found a match. */
74 1.1 christos return (char *) mbui_cur_ptr (iter_haystack);
75 1.1 christos if (!mbui_avail (rhaystack))
76 1.1 christos /* No match. */
77 1.1 christos return NULL;
78 1.1 christos if (!mb_equal (mbui_cur (rhaystack), mbui_cur (rneedle)))
79 1.1 christos /* Nothing in this round. */
80 1.1 christos break;
81 1.1 christos }
82 1.1 christos }
83 1.1 christos }
84 1.1 christos }
85 1.1 christos else
86 1.1 christos return (char *) haystack;
87 1.1 christos }
88 1.1 christos else
89 1.1 christos #endif
90 1.1 christos {
91 1.1 christos if (*needle != '\0')
92 1.1 christos {
93 1.1 christos /* Speed up the following searches of needle by caching its first
94 1.1 christos character. */
95 1.1 christos char b = *needle++;
96 1.1 christos
97 1.1 christos for (;; haystack++)
98 1.1 christos {
99 1.1 christos if (*haystack == '\0')
100 1.1 christos /* No match. */
101 1.1 christos return NULL;
102 1.1 christos if (*haystack == b)
103 1.1 christos /* The first character matches. */
104 1.1 christos {
105 1.1 christos const char *rhaystack = haystack + 1;
106 1.1 christos const char *rneedle = needle;
107 1.1 christos
108 1.1 christos for (;; rhaystack++, rneedle++)
109 1.1 christos {
110 1.1 christos if (*rneedle == '\0')
111 1.1 christos /* Found a match. */
112 1.1 christos return (char *) haystack;
113 1.1 christos if (*rhaystack == '\0')
114 1.1 christos /* No match. */
115 1.1 christos return NULL;
116 1.1 christos if (*rhaystack != *rneedle)
117 1.1 christos /* Nothing in this round. */
118 1.1 christos break;
119 1.1 christos }
120 1.1 christos }
121 1.1 christos }
122 1.1 christos }
123 1.1 christos else
124 1.1 christos return (char *) haystack;
125 1.1 christos }
126 1.1 christos }
127