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