xref: /dflybsd-src/contrib/gdb-7/gdb/gnulib/import/str-two-way.h (revision de8e141f24382815c10a4012d209bbbf7abf1112)
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