Blame lib/str-two-way.h

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