Blame lib/strstr.c

Packit Service a2489d
/* Copyright (C) 1991-1994, 1996-1998, 2000, 2004, 2007-2018 Free Software
Packit Service a2489d
   Foundation, Inc.
Packit Service a2489d
   This file is part of the GNU C Library.
Packit Service a2489d
Packit Service a2489d
   This program is free software; you can redistribute it and/or modify
Packit Service a2489d
   it under the terms of the GNU General Public License as published by
Packit Service a2489d
   the Free Software Foundation; either version 3, or (at your option)
Packit Service a2489d
   any later version.
Packit Service a2489d
Packit Service a2489d
   This program is distributed in the hope that it will be useful,
Packit Service a2489d
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service a2489d
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service a2489d
   GNU General Public License for more details.
Packit Service a2489d
Packit Service a2489d
   You should have received a copy of the GNU General Public License along
Packit Service a2489d
   with this program; if not, see <https://www.gnu.org/licenses/>.  */
Packit Service a2489d
Packit Service a2489d
/* This particular implementation was written by Eric Blake, 2008.  */
Packit Service a2489d
Packit Service a2489d
#ifndef _LIBC
Packit Service a2489d
# include <config.h>
Packit Service a2489d
#endif
Packit Service a2489d
Packit Service a2489d
/* Specification of strstr.  */
Packit Service a2489d
#include <string.h>
Packit Service a2489d
Packit Service a2489d
#include <stdbool.h>
Packit Service a2489d
Packit Service a2489d
#define RETURN_TYPE char *
Packit Service a2489d
#define AVAILABLE(h, h_l, j, n_l)                       \
Packit Service a2489d
  (!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l))     \
Packit Service a2489d
   && ((h_l) = (j) + (n_l)))
Packit Service a2489d
#include "str-two-way.h"
Packit Service a2489d
Packit Service a2489d
/* Return the first occurrence of NEEDLE in HAYSTACK.  Return HAYSTACK
Packit Service a2489d
   if NEEDLE is empty, otherwise NULL if NEEDLE is not found in
Packit Service a2489d
   HAYSTACK.  */
Packit Service a2489d
char *
Packit Service a2489d
strstr (const char *haystack_start, const char *needle_start)
Packit Service a2489d
{
Packit Service a2489d
  const char *haystack = haystack_start;
Packit Service a2489d
  const char *needle = needle_start;
Packit Service a2489d
  size_t needle_len; /* Length of NEEDLE.  */
Packit Service a2489d
  size_t haystack_len; /* Known minimum length of HAYSTACK.  */
Packit Service a2489d
  bool ok = true; /* True if NEEDLE is prefix of HAYSTACK.  */
Packit Service a2489d
Packit Service a2489d
  /* Determine length of NEEDLE, and in the process, make sure
Packit Service a2489d
     HAYSTACK is at least as long (no point processing all of a long
Packit Service a2489d
     NEEDLE if HAYSTACK is too short).  */
Packit Service a2489d
  while (*haystack && *needle)
Packit Service a2489d
    ok &= *haystack++ == *needle++;
Packit Service a2489d
  if (*needle)
Packit Service a2489d
    return NULL;
Packit Service a2489d
  if (ok)
Packit Service a2489d
    return (char *) haystack_start;
Packit Service a2489d
Packit Service a2489d
  /* Reduce the size of haystack using strchr, since it has a smaller
Packit Service a2489d
     linear coefficient than the Two-Way algorithm.  */
Packit Service a2489d
  needle_len = needle - needle_start;
Packit Service a2489d
  haystack = strchr (haystack_start + 1, *needle_start);
Packit Service a2489d
  if (!haystack || __builtin_expect (needle_len == 1, 0))
Packit Service a2489d
    return (char *) haystack;
Packit Service a2489d
  needle -= needle_len;
Packit Service a2489d
  haystack_len = (haystack > haystack_start + needle_len ? 1
Packit Service a2489d
                  : needle_len + haystack_start - haystack);
Packit Service a2489d
Packit Service a2489d
  /* Perform the search.  Abstract memory is considered to be an array
Packit Service a2489d
     of 'unsigned char' values, not an array of 'char' values.  See
Packit Service a2489d
     ISO C 99 section 6.2.6.1.  */
Packit Service a2489d
  if (needle_len < LONG_NEEDLE_THRESHOLD)
Packit Service a2489d
    return two_way_short_needle ((const unsigned char *) haystack,
Packit Service a2489d
                                 haystack_len,
Packit Service a2489d
                                 (const unsigned char *) needle, needle_len);
Packit Service a2489d
  return two_way_long_needle ((const unsigned char *) haystack, haystack_len,
Packit Service a2489d
                              (const unsigned char *) needle, needle_len);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
#undef LONG_NEEDLE_THRESHOLD