Blame gl/str-two-way.h

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