Blame gnulib/lib/str-two-way.h

Packit 06dd63
/* Byte-wise substring search, using the Two-Way algorithm.
Packit 06dd63
   Copyright (C) 2008-2019 Free Software Foundation, Inc.
Packit 06dd63
   This file is part of the GNU C Library.
Packit 06dd63
   Written by Eric Blake <ebb9@byu.net>, 2008.
Packit 06dd63
Packit 06dd63
   This program is free software; you can redistribute it and/or modify
Packit 06dd63
   it under the terms of the GNU Lesser General Public License as published by
Packit 06dd63
   the Free Software Foundation; either version 2.1, or (at your option)
Packit 06dd63
   any later version.
Packit 06dd63
Packit 06dd63
   This program is distributed in the hope that it will be useful,
Packit 06dd63
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 06dd63
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 06dd63
   GNU Lesser General Public License for more details.
Packit 06dd63
Packit 06dd63
   You should have received a copy of the GNU Lesser General Public License along
Packit 06dd63
   with this program; if not, see <https://www.gnu.org/licenses/>.  */
Packit 06dd63
Packit 06dd63
/* Before including this file, you need to include <config.h> and
Packit 06dd63
   <string.h>, and define:
Packit 06dd63
     RESULT_TYPE             A macro that expands to the return type.
Packit 06dd63
     AVAILABLE(h, h_l, j, n_l)
Packit 06dd63
                             A macro that returns nonzero if there are
Packit 06dd63
                             at least N_L bytes left starting at H[J].
Packit 06dd63
                             H is 'unsigned char *', H_L, J, and N_L
Packit 06dd63
                             are 'size_t'; H_L is an lvalue.  For
Packit 06dd63
                             NUL-terminated searches, H_L can be
Packit 06dd63
                             modified each iteration to avoid having
Packit 06dd63
                             to compute the end of H up front.
Packit 06dd63
Packit 06dd63
  For case-insensitivity, you may optionally define:
Packit 06dd63
     CMP_FUNC(p1, p2, l)     A macro that returns 0 iff the first L
Packit 06dd63
                             characters of P1 and P2 are equal.
Packit 06dd63
     CANON_ELEMENT(c)        A macro that canonicalizes an element right after
Packit 06dd63
                             it has been fetched from one of the two strings.
Packit 06dd63
                             The argument is an 'unsigned char'; the result
Packit 06dd63
                             must be an 'unsigned char' as well.
Packit 06dd63
Packit 06dd63
  This file undefines the macros documented above, and defines
Packit 06dd63
  LONG_NEEDLE_THRESHOLD.
Packit 06dd63
*/
Packit 06dd63
Packit 06dd63
#include <limits.h>
Packit 06dd63
#include <stdint.h>
Packit 06dd63
Packit 06dd63
/* We use the Two-Way string matching algorithm (also known as
Packit 06dd63
   Chrochemore-Perrin), which guarantees linear complexity with
Packit 06dd63
   constant space.  Additionally, for long needles, we also use a bad
Packit 06dd63
   character shift table similar to the Boyer-Moore algorithm to
Packit 06dd63
   achieve improved (potentially sub-linear) performance.
Packit 06dd63
Packit 06dd63
   See http://www-igm.univ-mlv.fr/~lecroq/string/node26.html#SECTION00260,
Packit 06dd63
   https://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm,
Packit 06dd63
   https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.34.6641&rep=rep1&type=pdf
Packit 06dd63
*/
Packit 06dd63
Packit 06dd63
/* Point at which computing a bad-byte shift table is likely to be
Packit 06dd63
   worthwhile.  Small needles should not compute a table, since it
Packit 06dd63
   adds (1 << CHAR_BIT) + NEEDLE_LEN computations of preparation for a
Packit 06dd63
   speedup no greater than a factor of NEEDLE_LEN.  The larger the
Packit 06dd63
   needle, the better the potential performance gain.  On the other
Packit 06dd63
   hand, on non-POSIX systems with CHAR_BIT larger than eight, the
Packit 06dd63
   memory required for the table is prohibitive.  */
Packit 06dd63
#if CHAR_BIT < 10
Packit 06dd63
# define LONG_NEEDLE_THRESHOLD 32U
Packit 06dd63
#else
Packit 06dd63
# define LONG_NEEDLE_THRESHOLD SIZE_MAX
Packit 06dd63
#endif
Packit 06dd63
Packit 06dd63
#ifndef MAX
Packit 06dd63
# define MAX(a, b) ((a < b) ? (b) : (a))
Packit 06dd63
#endif
Packit 06dd63
Packit 06dd63
#ifndef CANON_ELEMENT
Packit 06dd63
# define CANON_ELEMENT(c) c
Packit 06dd63
#endif
Packit 06dd63
#ifndef CMP_FUNC
Packit 06dd63
# define CMP_FUNC memcmp
Packit 06dd63
#endif
Packit 06dd63
Packit 06dd63
/* Perform a critical factorization of NEEDLE, of length NEEDLE_LEN.
Packit 06dd63
   Return the index of the first byte in the right half, and set
Packit 06dd63
   *PERIOD to the global period of the right half.
Packit 06dd63
Packit 06dd63
   The global period of a string is the smallest index (possibly its
Packit 06dd63
   length) at which all remaining bytes in the string are repetitions
Packit 06dd63
   of the prefix (the last repetition may be a subset of the prefix).
Packit 06dd63
Packit 06dd63
   When NEEDLE is factored into two halves, a local period is the
Packit 06dd63
   length of the smallest word that shares a suffix with the left half
Packit 06dd63
   and shares a prefix with the right half.  All factorizations of a
Packit 06dd63
   non-empty NEEDLE have a local period of at least 1 and no greater
Packit 06dd63
   than NEEDLE_LEN.
Packit 06dd63
Packit 06dd63
   A critical factorization has the property that the local period
Packit 06dd63
   equals the global period.  All strings have at least one critical
Packit 06dd63
   factorization with the left half smaller than the global period.
Packit 06dd63
   And while some strings have more than one critical factorization,
Packit 06dd63
   it is provable that with an ordered alphabet, at least one of the
Packit 06dd63
   critical factorizations corresponds to a maximal suffix.
Packit 06dd63
Packit 06dd63
   Given an ordered alphabet, a critical factorization can be computed
Packit 06dd63
   in linear time, with 2 * NEEDLE_LEN comparisons, by computing the
Packit 06dd63
   shorter of two ordered maximal suffixes.  The ordered maximal
Packit 06dd63
   suffixes are determined by lexicographic comparison while tracking
Packit 06dd63
   periodicity.  */
Packit 06dd63
static size_t
Packit 06dd63
critical_factorization (const unsigned char *needle, size_t needle_len,
Packit 06dd63
                        size_t *period)
Packit 06dd63
{
Packit 06dd63
  /* Index of last byte of left half, or SIZE_MAX.  */
Packit 06dd63
  size_t max_suffix, max_suffix_rev;
Packit 06dd63
  size_t j; /* Index into NEEDLE for current candidate suffix.  */
Packit 06dd63
  size_t k; /* Offset into current period.  */
Packit 06dd63
  size_t p; /* Intermediate period.  */
Packit 06dd63
  unsigned char a, b; /* Current comparison bytes.  */
Packit 06dd63
Packit 06dd63
  /* Special case NEEDLE_LEN of 1 or 2 (all callers already filtered
Packit 06dd63
     out 0-length needles.  */
Packit 06dd63
  if (needle_len < 3)
Packit 06dd63
    {
Packit 06dd63
      *period = 1;
Packit 06dd63
      return needle_len - 1;
Packit 06dd63
    }
Packit 06dd63
Packit 06dd63
  /* Invariants:
Packit 06dd63
     0 <= j < NEEDLE_LEN - 1
Packit 06dd63
     -1 <= max_suffix{,_rev} < j (treating SIZE_MAX as if it were signed)
Packit 06dd63
     min(max_suffix, max_suffix_rev) < global period of NEEDLE
Packit 06dd63
     1 <= p <= global period of NEEDLE
Packit 06dd63
     p == global period of the substring NEEDLE[max_suffix{,_rev}+1...j]
Packit 06dd63
     1 <= k <= p
Packit 06dd63
  */
Packit 06dd63
Packit 06dd63
  /* Perform lexicographic search.  */
Packit 06dd63
  max_suffix = SIZE_MAX;
Packit 06dd63
  j = 0;
Packit 06dd63
  k = p = 1;
Packit 06dd63
  while (j + k < needle_len)
Packit 06dd63
    {
Packit 06dd63
      a = CANON_ELEMENT (needle[j + k]);
Packit 06dd63
      b = CANON_ELEMENT (needle[max_suffix + k]);
Packit 06dd63
      if (a < b)
Packit 06dd63
        {
Packit 06dd63
          /* Suffix is smaller, period is entire prefix so far.  */
Packit 06dd63
          j += k;
Packit 06dd63
          k = 1;
Packit 06dd63
          p = j - max_suffix;
Packit 06dd63
        }
Packit 06dd63
      else if (a == b)
Packit 06dd63
        {
Packit 06dd63
          /* Advance through repetition of the current period.  */
Packit 06dd63
          if (k != p)
Packit 06dd63
            ++k;
Packit 06dd63
          else
Packit 06dd63
            {
Packit 06dd63
              j += p;
Packit 06dd63
              k = 1;
Packit 06dd63
            }
Packit 06dd63
        }
Packit 06dd63
      else /* b < a */
Packit 06dd63
        {
Packit 06dd63
          /* Suffix is larger, start over from current location.  */
Packit 06dd63
          max_suffix = j++;
Packit 06dd63
          k = p = 1;
Packit 06dd63
        }
Packit 06dd63
    }
Packit 06dd63
  *period = p;
Packit 06dd63
Packit 06dd63
  /* Perform reverse lexicographic search.  */
Packit 06dd63
  max_suffix_rev = SIZE_MAX;
Packit 06dd63
  j = 0;
Packit 06dd63
  k = p = 1;
Packit 06dd63
  while (j + k < needle_len)
Packit 06dd63
    {
Packit 06dd63
      a = CANON_ELEMENT (needle[j + k]);
Packit 06dd63
      b = CANON_ELEMENT (needle[max_suffix_rev + k]);
Packit 06dd63
      if (b < a)
Packit 06dd63
        {
Packit 06dd63
          /* Suffix is smaller, period is entire prefix so far.  */
Packit 06dd63
          j += k;
Packit 06dd63
          k = 1;
Packit 06dd63
          p = j - max_suffix_rev;
Packit 06dd63
        }
Packit 06dd63
      else if (a == b)
Packit 06dd63
        {
Packit 06dd63
          /* Advance through repetition of the current period.  */
Packit 06dd63
          if (k != p)
Packit 06dd63
            ++k;
Packit 06dd63
          else
Packit 06dd63
            {
Packit 06dd63
              j += p;
Packit 06dd63
              k = 1;
Packit 06dd63
            }
Packit 06dd63
        }
Packit 06dd63
      else /* a < b */
Packit 06dd63
        {
Packit 06dd63
          /* Suffix is larger, start over from current location.  */
Packit 06dd63
          max_suffix_rev = j++;
Packit 06dd63
          k = p = 1;
Packit 06dd63
        }
Packit 06dd63
    }
Packit 06dd63
Packit 06dd63
  /* Choose the shorter suffix.  Return the index of the first byte of
Packit 06dd63
     the right half, rather than the last byte of the left half.
Packit 06dd63
Packit 06dd63
     For some examples, 'banana' has two critical factorizations, both
Packit 06dd63
     exposed by the two lexicographic extreme suffixes of 'anana' and
Packit 06dd63
     'nana', where both suffixes have a period of 2.  On the other
Packit 06dd63
     hand, with 'aab' and 'bba', both strings have a single critical
Packit 06dd63
     factorization of the last byte, with the suffix having a period
Packit 06dd63
     of 1.  While the maximal lexicographic suffix of 'aab' is 'b',
Packit 06dd63
     the maximal lexicographic suffix of 'bba' is 'ba', which is not a
Packit 06dd63
     critical factorization.  Conversely, the maximal reverse
Packit 06dd63
     lexicographic suffix of 'a' works for 'bba', but not 'ab' for
Packit 06dd63
     'aab'.  The shorter suffix of the two will always be a critical
Packit 06dd63
     factorization.  */
Packit 06dd63
  if (max_suffix_rev + 1 < max_suffix + 1)
Packit 06dd63
    return max_suffix + 1;
Packit 06dd63
  *period = p;
Packit 06dd63
  return max_suffix_rev + 1;
Packit 06dd63
}
Packit 06dd63
Packit 06dd63
/* Return the first location of non-empty NEEDLE within HAYSTACK, or
Packit 06dd63
   NULL.  HAYSTACK_LEN is the minimum known length of HAYSTACK.  This
Packit 06dd63
   method is optimized for NEEDLE_LEN < LONG_NEEDLE_THRESHOLD.
Packit 06dd63
   Performance is guaranteed to be linear, with an initialization cost
Packit 06dd63
   of 2 * NEEDLE_LEN comparisons.
Packit 06dd63
Packit 06dd63
   If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at
Packit 06dd63
   most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching.
Packit 06dd63
   If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
Packit 06dd63
   HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching.  */
Packit 06dd63
static RETURN_TYPE
Packit 06dd63
two_way_short_needle (const unsigned char *haystack, size_t haystack_len,
Packit 06dd63
                      const unsigned char *needle, size_t needle_len)
Packit 06dd63
{
Packit 06dd63
  size_t i; /* Index into current byte of NEEDLE.  */
Packit 06dd63
  size_t j; /* Index into current window of HAYSTACK.  */
Packit 06dd63
  size_t period; /* The period of the right half of needle.  */
Packit 06dd63
  size_t suffix; /* The index of the right half of needle.  */
Packit 06dd63
Packit 06dd63
  /* Factor the needle into two halves, such that the left half is
Packit 06dd63
     smaller than the global period, and the right half is
Packit 06dd63
     periodic (with a period as large as NEEDLE_LEN - suffix).  */
Packit 06dd63
  suffix = critical_factorization (needle, needle_len, &period);
Packit 06dd63
Packit 06dd63
  /* Perform the search.  Each iteration compares the right half
Packit 06dd63
     first.  */
Packit 06dd63
  if (CMP_FUNC (needle, needle + period, suffix) == 0)
Packit 06dd63
    {
Packit 06dd63
      /* Entire needle is periodic; a mismatch in the left half can
Packit 06dd63
         only advance by the period, so use memory to avoid rescanning
Packit 06dd63
         known occurrences of the period in the right half.  */
Packit 06dd63
      size_t memory = 0;
Packit 06dd63
      j = 0;
Packit 06dd63
      while (AVAILABLE (haystack, haystack_len, j, needle_len))
Packit 06dd63
        {
Packit 06dd63
          /* Scan for matches in right half.  */
Packit 06dd63
          i = MAX (suffix, memory);
Packit 06dd63
          while (i < needle_len && (CANON_ELEMENT (needle[i])
Packit 06dd63
                                    == CANON_ELEMENT (haystack[i + j])))
Packit 06dd63
            ++i;
Packit 06dd63
          if (needle_len <= i)
Packit 06dd63
            {
Packit 06dd63
              /* Scan for matches in left half.  */
Packit 06dd63
              i = suffix - 1;
Packit 06dd63
              while (memory < i + 1 && (CANON_ELEMENT (needle[i])
Packit 06dd63
                                        == CANON_ELEMENT (haystack[i + j])))
Packit 06dd63
                --i;
Packit 06dd63
              if (i + 1 < memory + 1)
Packit 06dd63
                return (RETURN_TYPE) (haystack + j);
Packit 06dd63
              /* No match, so remember how many repetitions of period
Packit 06dd63
                 on the right half were scanned.  */
Packit 06dd63
              j += period;
Packit 06dd63
              memory = needle_len - period;
Packit 06dd63
            }
Packit 06dd63
          else
Packit 06dd63
            {
Packit 06dd63
              j += i - suffix + 1;
Packit 06dd63
              memory = 0;
Packit 06dd63
            }
Packit 06dd63
        }
Packit 06dd63
    }
Packit 06dd63
  else
Packit 06dd63
    {
Packit 06dd63
      /* The two halves of needle are distinct; no extra memory is
Packit 06dd63
         required, and any mismatch results in a maximal shift.  */
Packit 06dd63
      period = MAX (suffix, needle_len - suffix) + 1;
Packit 06dd63
      j = 0;
Packit 06dd63
      while (AVAILABLE (haystack, haystack_len, j, needle_len))
Packit 06dd63
        {
Packit 06dd63
          /* Scan for matches in right half.  */
Packit 06dd63
          i = suffix;
Packit 06dd63
          while (i < needle_len && (CANON_ELEMENT (needle[i])
Packit 06dd63
                                    == CANON_ELEMENT (haystack[i + j])))
Packit 06dd63
            ++i;
Packit 06dd63
          if (needle_len <= i)
Packit 06dd63
            {
Packit 06dd63
              /* Scan for matches in left half.  */
Packit 06dd63
              i = suffix - 1;
Packit 06dd63
              while (i != SIZE_MAX && (CANON_ELEMENT (needle[i])
Packit 06dd63
                                       == CANON_ELEMENT (haystack[i + j])))
Packit 06dd63
                --i;
Packit 06dd63
              if (i == SIZE_MAX)
Packit 06dd63
                return (RETURN_TYPE) (haystack + j);
Packit 06dd63
              j += period;
Packit 06dd63
            }
Packit 06dd63
          else
Packit 06dd63
            j += i - suffix + 1;
Packit 06dd63
        }
Packit 06dd63
    }
Packit 06dd63
  return NULL;
Packit 06dd63
}
Packit 06dd63
Packit 06dd63
/* Return the first location of non-empty NEEDLE within HAYSTACK, or
Packit 06dd63
   NULL.  HAYSTACK_LEN is the minimum known length of HAYSTACK.  This
Packit 06dd63
   method is optimized for LONG_NEEDLE_THRESHOLD <= NEEDLE_LEN.
Packit 06dd63
   Performance is guaranteed to be linear, with an initialization cost
Packit 06dd63
   of 3 * NEEDLE_LEN + (1 << CHAR_BIT) operations.
Packit 06dd63
Packit 06dd63
   If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at
Packit 06dd63
   most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching,
Packit 06dd63
   and sublinear performance O(HAYSTACK_LEN / NEEDLE_LEN) is possible.
Packit 06dd63
   If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
Packit 06dd63
   HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and
Packit 06dd63
   sublinear performance is not possible.  */
Packit 06dd63
static RETURN_TYPE
Packit 06dd63
two_way_long_needle (const unsigned char *haystack, size_t haystack_len,
Packit 06dd63
                     const unsigned char *needle, size_t needle_len)
Packit 06dd63
{
Packit 06dd63
  size_t i; /* Index into current byte of NEEDLE.  */
Packit 06dd63
  size_t j; /* Index into current window of HAYSTACK.  */
Packit 06dd63
  size_t period; /* The period of the right half of needle.  */
Packit 06dd63
  size_t suffix; /* The index of the right half of needle.  */
Packit 06dd63
  size_t shift_table[1U << CHAR_BIT]; /* See below.  */
Packit 06dd63
Packit 06dd63
  /* Factor the needle into two halves, such that the left half is
Packit 06dd63
     smaller than the global period, and the right half is
Packit 06dd63
     periodic (with a period as large as NEEDLE_LEN - suffix).  */
Packit 06dd63
  suffix = critical_factorization (needle, needle_len, &period);
Packit 06dd63
Packit 06dd63
  /* Populate shift_table.  For each possible byte value c,
Packit 06dd63
     shift_table[c] is the distance from the last occurrence of c to
Packit 06dd63
     the end of NEEDLE, or NEEDLE_LEN if c is absent from the NEEDLE.
Packit 06dd63
     shift_table[NEEDLE[NEEDLE_LEN - 1]] contains the only 0.  */
Packit 06dd63
  for (i = 0; i < 1U << CHAR_BIT; i++)
Packit 06dd63
    shift_table[i] = needle_len;
Packit 06dd63
  for (i = 0; i < needle_len; i++)
Packit 06dd63
    shift_table[CANON_ELEMENT (needle[i])] = needle_len - i - 1;
Packit 06dd63
Packit 06dd63
  /* Perform the search.  Each iteration compares the right half
Packit 06dd63
     first.  */
Packit 06dd63
  if (CMP_FUNC (needle, needle + period, suffix) == 0)
Packit 06dd63
    {
Packit 06dd63
      /* Entire needle is periodic; a mismatch in the left half can
Packit 06dd63
         only advance by the period, so use memory to avoid rescanning
Packit 06dd63
         known occurrences of the period in the right half.  */
Packit 06dd63
      size_t memory = 0;
Packit 06dd63
      size_t shift;
Packit 06dd63
      j = 0;
Packit 06dd63
      while (AVAILABLE (haystack, haystack_len, j, needle_len))
Packit 06dd63
        {
Packit 06dd63
          /* Check the last byte first; if it does not match, then
Packit 06dd63
             shift to the next possible match location.  */
Packit 06dd63
          shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])];
Packit 06dd63
          if (0 < shift)
Packit 06dd63
            {
Packit 06dd63
              if (memory && shift < period)
Packit 06dd63
                {
Packit 06dd63
                  /* Since needle is periodic, but the last period has
Packit 06dd63
                     a byte out of place, there can be no match until
Packit 06dd63
                     after the mismatch.  */
Packit 06dd63
                  shift = needle_len - period;
Packit 06dd63
                }
Packit 06dd63
              memory = 0;
Packit 06dd63
              j += shift;
Packit 06dd63
              continue;
Packit 06dd63
            }
Packit 06dd63
          /* Scan for matches in right half.  The last byte has
Packit 06dd63
             already been matched, by virtue of the shift table.  */
Packit 06dd63
          i = MAX (suffix, memory);
Packit 06dd63
          while (i < needle_len - 1 && (CANON_ELEMENT (needle[i])
Packit 06dd63
                                        == CANON_ELEMENT (haystack[i + j])))
Packit 06dd63
            ++i;
Packit 06dd63
          if (needle_len - 1 <= i)
Packit 06dd63
            {
Packit 06dd63
              /* Scan for matches in left half.  */
Packit 06dd63
              i = suffix - 1;
Packit 06dd63
              while (memory < i + 1 && (CANON_ELEMENT (needle[i])
Packit 06dd63
                                        == CANON_ELEMENT (haystack[i + j])))
Packit 06dd63
                --i;
Packit 06dd63
              if (i + 1 < memory + 1)
Packit 06dd63
                return (RETURN_TYPE) (haystack + j);
Packit 06dd63
              /* No match, so remember how many repetitions of period
Packit 06dd63
                 on the right half were scanned.  */
Packit 06dd63
              j += period;
Packit 06dd63
              memory = needle_len - period;
Packit 06dd63
            }
Packit 06dd63
          else
Packit 06dd63
            {
Packit 06dd63
              j += i - suffix + 1;
Packit 06dd63
              memory = 0;
Packit 06dd63
            }
Packit 06dd63
        }
Packit 06dd63
    }
Packit 06dd63
  else
Packit 06dd63
    {
Packit 06dd63
      /* The two halves of needle are distinct; no extra memory is
Packit 06dd63
         required, and any mismatch results in a maximal shift.  */
Packit 06dd63
      size_t shift;
Packit 06dd63
      period = MAX (suffix, needle_len - suffix) + 1;
Packit 06dd63
      j = 0;
Packit 06dd63
      while (AVAILABLE (haystack, haystack_len, j, needle_len))
Packit 06dd63
        {
Packit 06dd63
          /* Check the last byte first; if it does not match, then
Packit 06dd63
             shift to the next possible match location.  */
Packit 06dd63
          shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])];
Packit 06dd63
          if (0 < shift)
Packit 06dd63
            {
Packit 06dd63
              j += shift;
Packit 06dd63
              continue;
Packit 06dd63
            }
Packit 06dd63
          /* Scan for matches in right half.  The last byte has
Packit 06dd63
             already been matched, by virtue of the shift table.  */
Packit 06dd63
          i = suffix;
Packit 06dd63
          while (i < needle_len - 1 && (CANON_ELEMENT (needle[i])
Packit 06dd63
                                        == CANON_ELEMENT (haystack[i + j])))
Packit 06dd63
            ++i;
Packit 06dd63
          if (needle_len - 1 <= i)
Packit 06dd63
            {
Packit 06dd63
              /* Scan for matches in left half.  */
Packit 06dd63
              i = suffix - 1;
Packit 06dd63
              while (i != SIZE_MAX && (CANON_ELEMENT (needle[i])
Packit 06dd63
                                       == CANON_ELEMENT (haystack[i + j])))
Packit 06dd63
                --i;
Packit 06dd63
              if (i == SIZE_MAX)
Packit 06dd63
                return (RETURN_TYPE) (haystack + j);
Packit 06dd63
              j += period;
Packit 06dd63
            }
Packit 06dd63
          else
Packit 06dd63
            j += i - suffix + 1;
Packit 06dd63
        }
Packit 06dd63
    }
Packit 06dd63
  return NULL;
Packit 06dd63
}
Packit 06dd63
Packit 06dd63
#undef AVAILABLE
Packit 06dd63
#undef CANON_ELEMENT
Packit 06dd63
#undef CMP_FUNC
Packit 06dd63
#undef MAX
Packit 06dd63
#undef RETURN_TYPE