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