1dc7c36e4SJohn Marino /* Byte-wise substring search, using the Two-Way algorithm.
2*09d4459fSDaniel Fojt Copyright (C) 2008-2020 Free Software Foundation, Inc.
3dc7c36e4SJohn Marino This file is part of the GNU C Library.
4dc7c36e4SJohn Marino Written by Eric Blake <ebb9@byu.net>, 2008.
5dc7c36e4SJohn Marino
6dc7c36e4SJohn Marino This program is free software; you can redistribute it and/or modify
7dc7c36e4SJohn Marino it under the terms of the GNU General Public License as published by
8dc7c36e4SJohn Marino the Free Software Foundation; either version 3, or (at your option)
9dc7c36e4SJohn Marino any later version.
10dc7c36e4SJohn Marino
11dc7c36e4SJohn Marino This program is distributed in the hope that it will be useful,
12dc7c36e4SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
13dc7c36e4SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14dc7c36e4SJohn Marino GNU General Public License for more details.
15dc7c36e4SJohn Marino
16dc7c36e4SJohn Marino You should have received a copy of the GNU General Public License along
17*09d4459fSDaniel Fojt with this program; if not, see <https://www.gnu.org/licenses/>. */
18dc7c36e4SJohn Marino
19dc7c36e4SJohn Marino /* Before including this file, you need to include <config.h> and
20dc7c36e4SJohn Marino <string.h>, and define:
21*09d4459fSDaniel Fojt RETURN_TYPE A macro that expands to the return type.
22dc7c36e4SJohn Marino AVAILABLE(h, h_l, j, n_l)
23dc7c36e4SJohn Marino A macro that returns nonzero if there are
24dc7c36e4SJohn Marino at least N_L bytes left starting at H[J].
25dc7c36e4SJohn Marino H is 'unsigned char *', H_L, J, and N_L
26dc7c36e4SJohn Marino are 'size_t'; H_L is an lvalue. For
27dc7c36e4SJohn Marino NUL-terminated searches, H_L can be
28dc7c36e4SJohn Marino modified each iteration to avoid having
29dc7c36e4SJohn Marino to compute the end of H up front.
30dc7c36e4SJohn Marino
31dc7c36e4SJohn Marino For case-insensitivity, you may optionally define:
32dc7c36e4SJohn Marino CMP_FUNC(p1, p2, l) A macro that returns 0 iff the first L
33dc7c36e4SJohn Marino characters of P1 and P2 are equal.
34dc7c36e4SJohn Marino CANON_ELEMENT(c) A macro that canonicalizes an element right after
35dc7c36e4SJohn Marino it has been fetched from one of the two strings.
36dc7c36e4SJohn Marino The argument is an 'unsigned char'; the result
37dc7c36e4SJohn Marino must be an 'unsigned char' as well.
38dc7c36e4SJohn Marino
39dc7c36e4SJohn Marino This file undefines the macros documented above, and defines
40dc7c36e4SJohn Marino LONG_NEEDLE_THRESHOLD.
41dc7c36e4SJohn Marino */
42dc7c36e4SJohn Marino
43dc7c36e4SJohn Marino #include <limits.h>
44dc7c36e4SJohn Marino #include <stdint.h>
45dc7c36e4SJohn Marino
46dc7c36e4SJohn Marino /* We use the Two-Way string matching algorithm (also known as
47dc7c36e4SJohn Marino Chrochemore-Perrin), which guarantees linear complexity with
48dc7c36e4SJohn Marino constant space. Additionally, for long needles, we also use a bad
49dc7c36e4SJohn Marino character shift table similar to the Boyer-Moore algorithm to
50dc7c36e4SJohn Marino achieve improved (potentially sub-linear) performance.
51dc7c36e4SJohn Marino
52*09d4459fSDaniel Fojt See https://www-igm.univ-mlv.fr/~lecroq/string/node26.html#SECTION00260,
53*09d4459fSDaniel Fojt https://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm,
54*09d4459fSDaniel Fojt https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.34.6641&rep=rep1&type=pdf
55dc7c36e4SJohn Marino */
56dc7c36e4SJohn Marino
57dc7c36e4SJohn Marino /* Point at which computing a bad-byte shift table is likely to be
58dc7c36e4SJohn Marino worthwhile. Small needles should not compute a table, since it
59dc7c36e4SJohn Marino adds (1 << CHAR_BIT) + NEEDLE_LEN computations of preparation for a
60dc7c36e4SJohn Marino speedup no greater than a factor of NEEDLE_LEN. The larger the
61dc7c36e4SJohn Marino needle, the better the potential performance gain. On the other
62dc7c36e4SJohn Marino hand, on non-POSIX systems with CHAR_BIT larger than eight, the
63dc7c36e4SJohn Marino memory required for the table is prohibitive. */
64dc7c36e4SJohn Marino #if CHAR_BIT < 10
65dc7c36e4SJohn Marino # define LONG_NEEDLE_THRESHOLD 32U
66dc7c36e4SJohn Marino #else
67dc7c36e4SJohn Marino # define LONG_NEEDLE_THRESHOLD SIZE_MAX
68dc7c36e4SJohn Marino #endif
69dc7c36e4SJohn Marino
70dc7c36e4SJohn Marino #ifndef MAX
71dc7c36e4SJohn Marino # define MAX(a, b) ((a < b) ? (b) : (a))
72dc7c36e4SJohn Marino #endif
73dc7c36e4SJohn Marino
74dc7c36e4SJohn Marino #ifndef CANON_ELEMENT
75dc7c36e4SJohn Marino # define CANON_ELEMENT(c) c
76dc7c36e4SJohn Marino #endif
77dc7c36e4SJohn Marino #ifndef CMP_FUNC
78dc7c36e4SJohn Marino # define CMP_FUNC memcmp
79dc7c36e4SJohn Marino #endif
80dc7c36e4SJohn Marino
81dc7c36e4SJohn Marino /* Perform a critical factorization of NEEDLE, of length NEEDLE_LEN.
82dc7c36e4SJohn Marino Return the index of the first byte in the right half, and set
83dc7c36e4SJohn Marino *PERIOD to the global period of the right half.
84dc7c36e4SJohn Marino
85dc7c36e4SJohn Marino The global period of a string is the smallest index (possibly its
86dc7c36e4SJohn Marino length) at which all remaining bytes in the string are repetitions
87dc7c36e4SJohn Marino of the prefix (the last repetition may be a subset of the prefix).
88dc7c36e4SJohn Marino
89dc7c36e4SJohn Marino When NEEDLE is factored into two halves, a local period is the
90dc7c36e4SJohn Marino length of the smallest word that shares a suffix with the left half
91dc7c36e4SJohn Marino and shares a prefix with the right half. All factorizations of a
92dc7c36e4SJohn Marino non-empty NEEDLE have a local period of at least 1 and no greater
93dc7c36e4SJohn Marino than NEEDLE_LEN.
94dc7c36e4SJohn Marino
95dc7c36e4SJohn Marino A critical factorization has the property that the local period
96dc7c36e4SJohn Marino equals the global period. All strings have at least one critical
97dc7c36e4SJohn Marino factorization with the left half smaller than the global period.
98dc7c36e4SJohn Marino And while some strings have more than one critical factorization,
99dc7c36e4SJohn Marino it is provable that with an ordered alphabet, at least one of the
100dc7c36e4SJohn Marino critical factorizations corresponds to a maximal suffix.
101dc7c36e4SJohn Marino
102dc7c36e4SJohn Marino Given an ordered alphabet, a critical factorization can be computed
103dc7c36e4SJohn Marino in linear time, with 2 * NEEDLE_LEN comparisons, by computing the
104dc7c36e4SJohn Marino shorter of two ordered maximal suffixes. The ordered maximal
105dc7c36e4SJohn Marino suffixes are determined by lexicographic comparison while tracking
106dc7c36e4SJohn Marino periodicity. */
107dc7c36e4SJohn Marino static size_t
critical_factorization(const unsigned char * needle,size_t needle_len,size_t * period)108dc7c36e4SJohn Marino critical_factorization (const unsigned char *needle, size_t needle_len,
109dc7c36e4SJohn Marino size_t *period)
110dc7c36e4SJohn Marino {
111dc7c36e4SJohn Marino /* Index of last byte of left half, or SIZE_MAX. */
112dc7c36e4SJohn Marino size_t max_suffix, max_suffix_rev;
113dc7c36e4SJohn Marino size_t j; /* Index into NEEDLE for current candidate suffix. */
114dc7c36e4SJohn Marino size_t k; /* Offset into current period. */
115dc7c36e4SJohn Marino size_t p; /* Intermediate period. */
116dc7c36e4SJohn Marino unsigned char a, b; /* Current comparison bytes. */
117dc7c36e4SJohn Marino
118dc7c36e4SJohn Marino /* Special case NEEDLE_LEN of 1 or 2 (all callers already filtered
119dc7c36e4SJohn Marino out 0-length needles. */
120dc7c36e4SJohn Marino if (needle_len < 3)
121dc7c36e4SJohn Marino {
122dc7c36e4SJohn Marino *period = 1;
123dc7c36e4SJohn Marino return needle_len - 1;
124dc7c36e4SJohn Marino }
125dc7c36e4SJohn Marino
126dc7c36e4SJohn Marino /* Invariants:
127dc7c36e4SJohn Marino 0 <= j < NEEDLE_LEN - 1
128dc7c36e4SJohn Marino -1 <= max_suffix{,_rev} < j (treating SIZE_MAX as if it were signed)
129dc7c36e4SJohn Marino min(max_suffix, max_suffix_rev) < global period of NEEDLE
130dc7c36e4SJohn Marino 1 <= p <= global period of NEEDLE
131dc7c36e4SJohn Marino p == global period of the substring NEEDLE[max_suffix{,_rev}+1...j]
132dc7c36e4SJohn Marino 1 <= k <= p
133dc7c36e4SJohn Marino */
134dc7c36e4SJohn Marino
135dc7c36e4SJohn Marino /* Perform lexicographic search. */
136dc7c36e4SJohn Marino max_suffix = SIZE_MAX;
137dc7c36e4SJohn Marino j = 0;
138dc7c36e4SJohn Marino k = p = 1;
139dc7c36e4SJohn Marino while (j + k < needle_len)
140dc7c36e4SJohn Marino {
141dc7c36e4SJohn Marino a = CANON_ELEMENT (needle[j + k]);
142dc7c36e4SJohn Marino b = CANON_ELEMENT (needle[max_suffix + k]);
143dc7c36e4SJohn Marino if (a < b)
144dc7c36e4SJohn Marino {
145dc7c36e4SJohn Marino /* Suffix is smaller, period is entire prefix so far. */
146dc7c36e4SJohn Marino j += k;
147dc7c36e4SJohn Marino k = 1;
148dc7c36e4SJohn Marino p = j - max_suffix;
149dc7c36e4SJohn Marino }
150dc7c36e4SJohn Marino else if (a == b)
151dc7c36e4SJohn Marino {
152dc7c36e4SJohn Marino /* Advance through repetition of the current period. */
153dc7c36e4SJohn Marino if (k != p)
154dc7c36e4SJohn Marino ++k;
155dc7c36e4SJohn Marino else
156dc7c36e4SJohn Marino {
157dc7c36e4SJohn Marino j += p;
158dc7c36e4SJohn Marino k = 1;
159dc7c36e4SJohn Marino }
160dc7c36e4SJohn Marino }
161dc7c36e4SJohn Marino else /* b < a */
162dc7c36e4SJohn Marino {
163dc7c36e4SJohn Marino /* Suffix is larger, start over from current location. */
164dc7c36e4SJohn Marino max_suffix = j++;
165dc7c36e4SJohn Marino k = p = 1;
166dc7c36e4SJohn Marino }
167dc7c36e4SJohn Marino }
168dc7c36e4SJohn Marino *period = p;
169dc7c36e4SJohn Marino
170dc7c36e4SJohn Marino /* Perform reverse lexicographic search. */
171dc7c36e4SJohn Marino max_suffix_rev = SIZE_MAX;
172dc7c36e4SJohn Marino j = 0;
173dc7c36e4SJohn Marino k = p = 1;
174dc7c36e4SJohn Marino while (j + k < needle_len)
175dc7c36e4SJohn Marino {
176dc7c36e4SJohn Marino a = CANON_ELEMENT (needle[j + k]);
177dc7c36e4SJohn Marino b = CANON_ELEMENT (needle[max_suffix_rev + k]);
178dc7c36e4SJohn Marino if (b < a)
179dc7c36e4SJohn Marino {
180dc7c36e4SJohn Marino /* Suffix is smaller, period is entire prefix so far. */
181dc7c36e4SJohn Marino j += k;
182dc7c36e4SJohn Marino k = 1;
183dc7c36e4SJohn Marino p = j - max_suffix_rev;
184dc7c36e4SJohn Marino }
185dc7c36e4SJohn Marino else if (a == b)
186dc7c36e4SJohn Marino {
187dc7c36e4SJohn Marino /* Advance through repetition of the current period. */
188dc7c36e4SJohn Marino if (k != p)
189dc7c36e4SJohn Marino ++k;
190dc7c36e4SJohn Marino else
191dc7c36e4SJohn Marino {
192dc7c36e4SJohn Marino j += p;
193dc7c36e4SJohn Marino k = 1;
194dc7c36e4SJohn Marino }
195dc7c36e4SJohn Marino }
196dc7c36e4SJohn Marino else /* a < b */
197dc7c36e4SJohn Marino {
198dc7c36e4SJohn Marino /* Suffix is larger, start over from current location. */
199dc7c36e4SJohn Marino max_suffix_rev = j++;
200dc7c36e4SJohn Marino k = p = 1;
201dc7c36e4SJohn Marino }
202dc7c36e4SJohn Marino }
203dc7c36e4SJohn Marino
204dc7c36e4SJohn Marino /* Choose the shorter suffix. Return the index of the first byte of
205dc7c36e4SJohn Marino the right half, rather than the last byte of the left half.
206dc7c36e4SJohn Marino
207dc7c36e4SJohn Marino For some examples, 'banana' has two critical factorizations, both
208dc7c36e4SJohn Marino exposed by the two lexicographic extreme suffixes of 'anana' and
209dc7c36e4SJohn Marino 'nana', where both suffixes have a period of 2. On the other
210dc7c36e4SJohn Marino hand, with 'aab' and 'bba', both strings have a single critical
211dc7c36e4SJohn Marino factorization of the last byte, with the suffix having a period
212dc7c36e4SJohn Marino of 1. While the maximal lexicographic suffix of 'aab' is 'b',
213dc7c36e4SJohn Marino the maximal lexicographic suffix of 'bba' is 'ba', which is not a
214dc7c36e4SJohn Marino critical factorization. Conversely, the maximal reverse
215dc7c36e4SJohn Marino lexicographic suffix of 'a' works for 'bba', but not 'ab' for
216dc7c36e4SJohn Marino 'aab'. The shorter suffix of the two will always be a critical
217dc7c36e4SJohn Marino factorization. */
218dc7c36e4SJohn Marino if (max_suffix_rev + 1 < max_suffix + 1)
219dc7c36e4SJohn Marino return max_suffix + 1;
220dc7c36e4SJohn Marino *period = p;
221dc7c36e4SJohn Marino return max_suffix_rev + 1;
222dc7c36e4SJohn Marino }
223dc7c36e4SJohn Marino
224dc7c36e4SJohn Marino /* Return the first location of non-empty NEEDLE within HAYSTACK, or
225dc7c36e4SJohn Marino NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This
226dc7c36e4SJohn Marino method is optimized for NEEDLE_LEN < LONG_NEEDLE_THRESHOLD.
227dc7c36e4SJohn Marino Performance is guaranteed to be linear, with an initialization cost
228dc7c36e4SJohn Marino of 2 * NEEDLE_LEN comparisons.
229dc7c36e4SJohn Marino
230dc7c36e4SJohn Marino If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at
231dc7c36e4SJohn Marino most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching.
232dc7c36e4SJohn Marino If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
233dc7c36e4SJohn Marino HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. */
234dc7c36e4SJohn Marino static RETURN_TYPE
two_way_short_needle(const unsigned char * haystack,size_t haystack_len,const unsigned char * needle,size_t needle_len)235dc7c36e4SJohn Marino two_way_short_needle (const unsigned char *haystack, size_t haystack_len,
236dc7c36e4SJohn Marino const unsigned char *needle, size_t needle_len)
237dc7c36e4SJohn Marino {
238dc7c36e4SJohn Marino size_t i; /* Index into current byte of NEEDLE. */
239dc7c36e4SJohn Marino size_t j; /* Index into current window of HAYSTACK. */
240dc7c36e4SJohn Marino size_t period; /* The period of the right half of needle. */
241dc7c36e4SJohn Marino size_t suffix; /* The index of the right half of needle. */
242dc7c36e4SJohn Marino
243dc7c36e4SJohn Marino /* Factor the needle into two halves, such that the left half is
244dc7c36e4SJohn Marino smaller than the global period, and the right half is
245dc7c36e4SJohn Marino periodic (with a period as large as NEEDLE_LEN - suffix). */
246dc7c36e4SJohn Marino suffix = critical_factorization (needle, needle_len, &period);
247dc7c36e4SJohn Marino
248dc7c36e4SJohn Marino /* Perform the search. Each iteration compares the right half
249dc7c36e4SJohn Marino first. */
250dc7c36e4SJohn Marino if (CMP_FUNC (needle, needle + period, suffix) == 0)
251dc7c36e4SJohn Marino {
252dc7c36e4SJohn Marino /* Entire needle is periodic; a mismatch in the left half can
253dc7c36e4SJohn Marino only advance by the period, so use memory to avoid rescanning
254dc7c36e4SJohn Marino known occurrences of the period in the right half. */
255dc7c36e4SJohn Marino size_t memory = 0;
256dc7c36e4SJohn Marino j = 0;
257dc7c36e4SJohn Marino while (AVAILABLE (haystack, haystack_len, j, needle_len))
258dc7c36e4SJohn Marino {
259dc7c36e4SJohn Marino /* Scan for matches in right half. */
260dc7c36e4SJohn Marino i = MAX (suffix, memory);
261dc7c36e4SJohn Marino while (i < needle_len && (CANON_ELEMENT (needle[i])
262dc7c36e4SJohn Marino == CANON_ELEMENT (haystack[i + j])))
263dc7c36e4SJohn Marino ++i;
264dc7c36e4SJohn Marino if (needle_len <= i)
265dc7c36e4SJohn Marino {
266dc7c36e4SJohn Marino /* Scan for matches in left half. */
267dc7c36e4SJohn Marino i = suffix - 1;
268dc7c36e4SJohn Marino while (memory < i + 1 && (CANON_ELEMENT (needle[i])
269dc7c36e4SJohn Marino == CANON_ELEMENT (haystack[i + j])))
270dc7c36e4SJohn Marino --i;
271dc7c36e4SJohn Marino if (i + 1 < memory + 1)
272dc7c36e4SJohn Marino return (RETURN_TYPE) (haystack + j);
273dc7c36e4SJohn Marino /* No match, so remember how many repetitions of period
274dc7c36e4SJohn Marino on the right half were scanned. */
275dc7c36e4SJohn Marino j += period;
276dc7c36e4SJohn Marino memory = needle_len - period;
277dc7c36e4SJohn Marino }
278dc7c36e4SJohn Marino else
279dc7c36e4SJohn Marino {
280dc7c36e4SJohn Marino j += i - suffix + 1;
281dc7c36e4SJohn Marino memory = 0;
282dc7c36e4SJohn Marino }
283dc7c36e4SJohn Marino }
284dc7c36e4SJohn Marino }
285dc7c36e4SJohn Marino else
286dc7c36e4SJohn Marino {
287dc7c36e4SJohn Marino /* The two halves of needle are distinct; no extra memory is
288dc7c36e4SJohn Marino required, and any mismatch results in a maximal shift. */
289dc7c36e4SJohn Marino period = MAX (suffix, needle_len - suffix) + 1;
290dc7c36e4SJohn Marino j = 0;
291dc7c36e4SJohn Marino while (AVAILABLE (haystack, haystack_len, j, needle_len))
292dc7c36e4SJohn Marino {
293dc7c36e4SJohn Marino /* Scan for matches in right half. */
294dc7c36e4SJohn Marino i = suffix;
295dc7c36e4SJohn Marino while (i < needle_len && (CANON_ELEMENT (needle[i])
296dc7c36e4SJohn Marino == CANON_ELEMENT (haystack[i + j])))
297dc7c36e4SJohn Marino ++i;
298dc7c36e4SJohn Marino if (needle_len <= i)
299dc7c36e4SJohn Marino {
300dc7c36e4SJohn Marino /* Scan for matches in left half. */
301dc7c36e4SJohn Marino i = suffix - 1;
302dc7c36e4SJohn Marino while (i != SIZE_MAX && (CANON_ELEMENT (needle[i])
303dc7c36e4SJohn Marino == CANON_ELEMENT (haystack[i + j])))
304dc7c36e4SJohn Marino --i;
305dc7c36e4SJohn Marino if (i == SIZE_MAX)
306dc7c36e4SJohn Marino return (RETURN_TYPE) (haystack + j);
307dc7c36e4SJohn Marino j += period;
308dc7c36e4SJohn Marino }
309dc7c36e4SJohn Marino else
310dc7c36e4SJohn Marino j += i - suffix + 1;
311dc7c36e4SJohn Marino }
312dc7c36e4SJohn Marino }
313dc7c36e4SJohn Marino return NULL;
314dc7c36e4SJohn Marino }
315dc7c36e4SJohn Marino
316dc7c36e4SJohn Marino /* Return the first location of non-empty NEEDLE within HAYSTACK, or
317dc7c36e4SJohn Marino NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This
318dc7c36e4SJohn Marino method is optimized for LONG_NEEDLE_THRESHOLD <= NEEDLE_LEN.
319dc7c36e4SJohn Marino Performance is guaranteed to be linear, with an initialization cost
320dc7c36e4SJohn Marino of 3 * NEEDLE_LEN + (1 << CHAR_BIT) operations.
321dc7c36e4SJohn Marino
322dc7c36e4SJohn Marino If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at
323dc7c36e4SJohn Marino most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching,
324dc7c36e4SJohn Marino and sublinear performance O(HAYSTACK_LEN / NEEDLE_LEN) is possible.
325dc7c36e4SJohn Marino If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
326dc7c36e4SJohn Marino HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and
327dc7c36e4SJohn Marino sublinear performance is not possible. */
328dc7c36e4SJohn Marino static RETURN_TYPE
two_way_long_needle(const unsigned char * haystack,size_t haystack_len,const unsigned char * needle,size_t needle_len)329dc7c36e4SJohn Marino two_way_long_needle (const unsigned char *haystack, size_t haystack_len,
330dc7c36e4SJohn Marino const unsigned char *needle, size_t needle_len)
331dc7c36e4SJohn Marino {
332dc7c36e4SJohn Marino size_t i; /* Index into current byte of NEEDLE. */
333dc7c36e4SJohn Marino size_t j; /* Index into current window of HAYSTACK. */
334dc7c36e4SJohn Marino size_t period; /* The period of the right half of needle. */
335dc7c36e4SJohn Marino size_t suffix; /* The index of the right half of needle. */
336dc7c36e4SJohn Marino size_t shift_table[1U << CHAR_BIT]; /* See below. */
337dc7c36e4SJohn Marino
338dc7c36e4SJohn Marino /* Factor the needle into two halves, such that the left half is
339dc7c36e4SJohn Marino smaller than the global period, and the right half is
340dc7c36e4SJohn Marino periodic (with a period as large as NEEDLE_LEN - suffix). */
341dc7c36e4SJohn Marino suffix = critical_factorization (needle, needle_len, &period);
342dc7c36e4SJohn Marino
343dc7c36e4SJohn Marino /* Populate shift_table. For each possible byte value c,
344dc7c36e4SJohn Marino shift_table[c] is the distance from the last occurrence of c to
345dc7c36e4SJohn Marino the end of NEEDLE, or NEEDLE_LEN if c is absent from the NEEDLE.
346dc7c36e4SJohn Marino shift_table[NEEDLE[NEEDLE_LEN - 1]] contains the only 0. */
347dc7c36e4SJohn Marino for (i = 0; i < 1U << CHAR_BIT; i++)
348dc7c36e4SJohn Marino shift_table[i] = needle_len;
349dc7c36e4SJohn Marino for (i = 0; i < needle_len; i++)
350dc7c36e4SJohn Marino shift_table[CANON_ELEMENT (needle[i])] = needle_len - i - 1;
351dc7c36e4SJohn Marino
352dc7c36e4SJohn Marino /* Perform the search. Each iteration compares the right half
353dc7c36e4SJohn Marino first. */
354dc7c36e4SJohn Marino if (CMP_FUNC (needle, needle + period, suffix) == 0)
355dc7c36e4SJohn Marino {
356dc7c36e4SJohn Marino /* Entire needle is periodic; a mismatch in the left half can
357dc7c36e4SJohn Marino only advance by the period, so use memory to avoid rescanning
358dc7c36e4SJohn Marino known occurrences of the period in the right half. */
359dc7c36e4SJohn Marino size_t memory = 0;
360dc7c36e4SJohn Marino size_t shift;
361dc7c36e4SJohn Marino j = 0;
362dc7c36e4SJohn Marino while (AVAILABLE (haystack, haystack_len, j, needle_len))
363dc7c36e4SJohn Marino {
364dc7c36e4SJohn Marino /* Check the last byte first; if it does not match, then
365dc7c36e4SJohn Marino shift to the next possible match location. */
366dc7c36e4SJohn Marino shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])];
367dc7c36e4SJohn Marino if (0 < shift)
368dc7c36e4SJohn Marino {
369dc7c36e4SJohn Marino if (memory && shift < period)
370dc7c36e4SJohn Marino {
371dc7c36e4SJohn Marino /* Since needle is periodic, but the last period has
372dc7c36e4SJohn Marino a byte out of place, there can be no match until
373dc7c36e4SJohn Marino after the mismatch. */
374dc7c36e4SJohn Marino shift = needle_len - period;
375dc7c36e4SJohn Marino }
376dc7c36e4SJohn Marino memory = 0;
377dc7c36e4SJohn Marino j += shift;
378dc7c36e4SJohn Marino continue;
379dc7c36e4SJohn Marino }
380dc7c36e4SJohn Marino /* Scan for matches in right half. The last byte has
381dc7c36e4SJohn Marino already been matched, by virtue of the shift table. */
382dc7c36e4SJohn Marino i = MAX (suffix, memory);
383dc7c36e4SJohn Marino while (i < needle_len - 1 && (CANON_ELEMENT (needle[i])
384dc7c36e4SJohn Marino == CANON_ELEMENT (haystack[i + j])))
385dc7c36e4SJohn Marino ++i;
386dc7c36e4SJohn Marino if (needle_len - 1 <= i)
387dc7c36e4SJohn Marino {
388dc7c36e4SJohn Marino /* Scan for matches in left half. */
389dc7c36e4SJohn Marino i = suffix - 1;
390dc7c36e4SJohn Marino while (memory < i + 1 && (CANON_ELEMENT (needle[i])
391dc7c36e4SJohn Marino == CANON_ELEMENT (haystack[i + j])))
392dc7c36e4SJohn Marino --i;
393dc7c36e4SJohn Marino if (i + 1 < memory + 1)
394dc7c36e4SJohn Marino return (RETURN_TYPE) (haystack + j);
395dc7c36e4SJohn Marino /* No match, so remember how many repetitions of period
396dc7c36e4SJohn Marino on the right half were scanned. */
397dc7c36e4SJohn Marino j += period;
398dc7c36e4SJohn Marino memory = needle_len - period;
399dc7c36e4SJohn Marino }
400dc7c36e4SJohn Marino else
401dc7c36e4SJohn Marino {
402dc7c36e4SJohn Marino j += i - suffix + 1;
403dc7c36e4SJohn Marino memory = 0;
404dc7c36e4SJohn Marino }
405dc7c36e4SJohn Marino }
406dc7c36e4SJohn Marino }
407dc7c36e4SJohn Marino else
408dc7c36e4SJohn Marino {
409dc7c36e4SJohn Marino /* The two halves of needle are distinct; no extra memory is
410dc7c36e4SJohn Marino required, and any mismatch results in a maximal shift. */
411dc7c36e4SJohn Marino size_t shift;
412dc7c36e4SJohn Marino period = MAX (suffix, needle_len - suffix) + 1;
413dc7c36e4SJohn Marino j = 0;
414dc7c36e4SJohn Marino while (AVAILABLE (haystack, haystack_len, j, needle_len))
415dc7c36e4SJohn Marino {
416dc7c36e4SJohn Marino /* Check the last byte first; if it does not match, then
417dc7c36e4SJohn Marino shift to the next possible match location. */
418dc7c36e4SJohn Marino shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])];
419dc7c36e4SJohn Marino if (0 < shift)
420dc7c36e4SJohn Marino {
421dc7c36e4SJohn Marino j += shift;
422dc7c36e4SJohn Marino continue;
423dc7c36e4SJohn Marino }
424dc7c36e4SJohn Marino /* Scan for matches in right half. The last byte has
425dc7c36e4SJohn Marino already been matched, by virtue of the shift table. */
426dc7c36e4SJohn Marino i = suffix;
427dc7c36e4SJohn Marino while (i < needle_len - 1 && (CANON_ELEMENT (needle[i])
428dc7c36e4SJohn Marino == CANON_ELEMENT (haystack[i + j])))
429dc7c36e4SJohn Marino ++i;
430dc7c36e4SJohn Marino if (needle_len - 1 <= i)
431dc7c36e4SJohn Marino {
432dc7c36e4SJohn Marino /* Scan for matches in left half. */
433dc7c36e4SJohn Marino i = suffix - 1;
434dc7c36e4SJohn Marino while (i != SIZE_MAX && (CANON_ELEMENT (needle[i])
435dc7c36e4SJohn Marino == CANON_ELEMENT (haystack[i + j])))
436dc7c36e4SJohn Marino --i;
437dc7c36e4SJohn Marino if (i == SIZE_MAX)
438dc7c36e4SJohn Marino return (RETURN_TYPE) (haystack + j);
439dc7c36e4SJohn Marino j += period;
440dc7c36e4SJohn Marino }
441dc7c36e4SJohn Marino else
442dc7c36e4SJohn Marino j += i - suffix + 1;
443dc7c36e4SJohn Marino }
444dc7c36e4SJohn Marino }
445dc7c36e4SJohn Marino return NULL;
446dc7c36e4SJohn Marino }
447dc7c36e4SJohn Marino
448dc7c36e4SJohn Marino #undef AVAILABLE
449dc7c36e4SJohn Marino #undef CANON_ELEMENT
450dc7c36e4SJohn Marino #undef CMP_FUNC
451dc7c36e4SJohn Marino #undef MAX
452dc7c36e4SJohn Marino #undef RETURN_TYPE
453