Blame lib/strcasestr.c

Packit 1ac44c
/* Case-insensitive searching in a string.
Packit 1ac44c
   Copyright (C) 2005-2018 Free Software Foundation, Inc.
Packit 1ac44c
   Written by Bruno Haible <bruno@clisp.org>, 2005.
Packit 1ac44c
Packit 1ac44c
   This program is free software; you can redistribute it and/or modify
Packit 1ac44c
   it under the terms of the GNU General Public License as published by
Packit 1ac44c
   the Free Software Foundation; either version 3, or (at your option)
Packit 1ac44c
   any later version.
Packit 1ac44c
Packit 1ac44c
   This program is distributed in the hope that it will be useful,
Packit 1ac44c
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 1ac44c
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 1ac44c
   GNU General Public License for more details.
Packit 1ac44c
Packit 1ac44c
   You should have received a copy of the GNU General Public License
Packit 1ac44c
   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
Packit 1ac44c
Packit 1ac44c
#include <config.h>
Packit 1ac44c
Packit 1ac44c
/* Specification.  */
Packit 1ac44c
#include <string.h>
Packit 1ac44c
Packit 1ac44c
#include <ctype.h>
Packit 1ac44c
#include <stdbool.h>
Packit 1ac44c
#include <strings.h>
Packit 1ac44c
Packit 1ac44c
#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
Packit 1ac44c
Packit 1ac44c
/* Two-Way algorithm.  */
Packit 1ac44c
#define RETURN_TYPE char *
Packit 1ac44c
#define AVAILABLE(h, h_l, j, n_l)                       \
Packit 1ac44c
  (!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l))     \
Packit 1ac44c
   && ((h_l) = (j) + (n_l)))
Packit 1ac44c
#define CANON_ELEMENT(c) TOLOWER (c)
Packit 1ac44c
#define CMP_FUNC(p1, p2, l)                             \
Packit 1ac44c
  strncasecmp ((const char *) (p1), (const char *) (p2), l)
Packit 1ac44c
#include "str-two-way.h"
Packit 1ac44c
Packit 1ac44c
/* Find the first occurrence of NEEDLE in HAYSTACK, using
Packit 1ac44c
   case-insensitive comparison.  This function gives unspecified
Packit 1ac44c
   results in multibyte locales.  */
Packit 1ac44c
char *
Packit 1ac44c
strcasestr (const char *haystack_start, const char *needle_start)
Packit 1ac44c
{
Packit 1ac44c
  const char *haystack = haystack_start;
Packit 1ac44c
  const char *needle = needle_start;
Packit 1ac44c
  size_t needle_len; /* Length of NEEDLE.  */
Packit 1ac44c
  size_t haystack_len; /* Known minimum length of HAYSTACK.  */
Packit 1ac44c
  bool ok = true; /* True if NEEDLE is prefix of HAYSTACK.  */
Packit 1ac44c
Packit 1ac44c
  /* Determine length of NEEDLE, and in the process, make sure
Packit 1ac44c
     HAYSTACK is at least as long (no point processing all of a long
Packit 1ac44c
     NEEDLE if HAYSTACK is too short).  */
Packit 1ac44c
  while (*haystack && *needle)
Packit 1ac44c
    {
Packit 1ac44c
      ok &= (TOLOWER ((unsigned char) *haystack)
Packit 1ac44c
             == TOLOWER ((unsigned char) *needle));
Packit 1ac44c
      haystack++;
Packit 1ac44c
      needle++;
Packit 1ac44c
    }
Packit 1ac44c
  if (*needle)
Packit 1ac44c
    return NULL;
Packit 1ac44c
  if (ok)
Packit 1ac44c
    return (char *) haystack_start;
Packit 1ac44c
  needle_len = needle - needle_start;
Packit 1ac44c
  haystack = haystack_start + 1;
Packit 1ac44c
  haystack_len = needle_len - 1;
Packit 1ac44c
Packit 1ac44c
  /* Perform the search.  Abstract memory is considered to be an array
Packit 1ac44c
     of 'unsigned char' values, not an array of 'char' values.  See
Packit 1ac44c
     ISO C 99 section 6.2.6.1.  */
Packit 1ac44c
  if (needle_len < LONG_NEEDLE_THRESHOLD)
Packit 1ac44c
    return two_way_short_needle ((const unsigned char *) haystack,
Packit 1ac44c
                                 haystack_len,
Packit 1ac44c
                                 (const unsigned char *) needle_start,
Packit 1ac44c
                                 needle_len);
Packit 1ac44c
  return two_way_long_needle ((const unsigned char *) haystack, haystack_len,
Packit 1ac44c
                              (const unsigned char *) needle_start,
Packit 1ac44c
                              needle_len);
Packit 1ac44c
}
Packit 1ac44c
Packit 1ac44c
#undef LONG_NEEDLE_THRESHOLD