Blame gl/str-two-way.h

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