Blame lib/str-two-way.h

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