xref: /dflybsd-src/contrib/grep/lib/strstr.c (revision 91b9ed38d3db6a8a8ac5b66da1d43e6e331e259a)
1*09d4459fSDaniel Fojt /* Copyright (C) 1991-1994, 1996-1998, 2000, 2004, 2007-2020 Free Software
2dc7c36e4SJohn Marino    Foundation, Inc.
3dc7c36e4SJohn Marino    This file is part of the GNU C Library.
4dc7c36e4SJohn Marino 
5dc7c36e4SJohn Marino    This program is free software; you can redistribute it and/or modify
6dc7c36e4SJohn Marino    it under the terms of the GNU General Public License as published by
7dc7c36e4SJohn Marino    the Free Software Foundation; either version 3, or (at your option)
8dc7c36e4SJohn Marino    any later version.
9dc7c36e4SJohn Marino 
10dc7c36e4SJohn Marino    This program is distributed in the hope that it will be useful,
11dc7c36e4SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
12dc7c36e4SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13dc7c36e4SJohn Marino    GNU General Public License for more details.
14dc7c36e4SJohn Marino 
15dc7c36e4SJohn Marino    You should have received a copy of the GNU General Public License along
16*09d4459fSDaniel Fojt    with this program; if not, see <https://www.gnu.org/licenses/>.  */
17dc7c36e4SJohn Marino 
18dc7c36e4SJohn Marino /* This particular implementation was written by Eric Blake, 2008.  */
19dc7c36e4SJohn Marino 
20dc7c36e4SJohn Marino #ifndef _LIBC
21dc7c36e4SJohn Marino # include <config.h>
22dc7c36e4SJohn Marino #endif
23dc7c36e4SJohn Marino 
24dc7c36e4SJohn Marino /* Specification of strstr.  */
25dc7c36e4SJohn Marino #include <string.h>
26dc7c36e4SJohn Marino 
27dc7c36e4SJohn Marino #include <stdbool.h>
28dc7c36e4SJohn Marino 
29dc7c36e4SJohn Marino #define RETURN_TYPE char *
30dc7c36e4SJohn Marino #define AVAILABLE(h, h_l, j, n_l)                       \
31dc7c36e4SJohn Marino   (!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l))     \
32dc7c36e4SJohn Marino    && ((h_l) = (j) + (n_l)))
33dc7c36e4SJohn Marino #include "str-two-way.h"
34dc7c36e4SJohn Marino 
35dc7c36e4SJohn Marino /* Return the first occurrence of NEEDLE in HAYSTACK.  Return HAYSTACK
36dc7c36e4SJohn Marino    if NEEDLE is empty, otherwise NULL if NEEDLE is not found in
37dc7c36e4SJohn Marino    HAYSTACK.  */
38dc7c36e4SJohn Marino char *
strstr(const char * haystack_start,const char * needle_start)39dc7c36e4SJohn Marino strstr (const char *haystack_start, const char *needle_start)
40dc7c36e4SJohn Marino {
41dc7c36e4SJohn Marino   const char *haystack = haystack_start;
42dc7c36e4SJohn Marino   const char *needle = needle_start;
43dc7c36e4SJohn Marino   size_t needle_len; /* Length of NEEDLE.  */
44dc7c36e4SJohn Marino   size_t haystack_len; /* Known minimum length of HAYSTACK.  */
45dc7c36e4SJohn Marino   bool ok = true; /* True if NEEDLE is prefix of HAYSTACK.  */
46dc7c36e4SJohn Marino 
47dc7c36e4SJohn Marino   /* Determine length of NEEDLE, and in the process, make sure
48dc7c36e4SJohn Marino      HAYSTACK is at least as long (no point processing all of a long
49dc7c36e4SJohn Marino      NEEDLE if HAYSTACK is too short).  */
50dc7c36e4SJohn Marino   while (*haystack && *needle)
51dc7c36e4SJohn Marino     ok &= *haystack++ == *needle++;
52dc7c36e4SJohn Marino   if (*needle)
53dc7c36e4SJohn Marino     return NULL;
54dc7c36e4SJohn Marino   if (ok)
55dc7c36e4SJohn Marino     return (char *) haystack_start;
56dc7c36e4SJohn Marino 
57dc7c36e4SJohn Marino   /* Reduce the size of haystack using strchr, since it has a smaller
58dc7c36e4SJohn Marino      linear coefficient than the Two-Way algorithm.  */
59dc7c36e4SJohn Marino   needle_len = needle - needle_start;
60dc7c36e4SJohn Marino   haystack = strchr (haystack_start + 1, *needle_start);
61dc7c36e4SJohn Marino   if (!haystack || __builtin_expect (needle_len == 1, 0))
62dc7c36e4SJohn Marino     return (char *) haystack;
63dc7c36e4SJohn Marino   needle -= needle_len;
64dc7c36e4SJohn Marino   haystack_len = (haystack > haystack_start + needle_len ? 1
65dc7c36e4SJohn Marino                   : needle_len + haystack_start - haystack);
66dc7c36e4SJohn Marino 
67dc7c36e4SJohn Marino   /* Perform the search.  Abstract memory is considered to be an array
68dc7c36e4SJohn Marino      of 'unsigned char' values, not an array of 'char' values.  See
69dc7c36e4SJohn Marino      ISO C 99 section 6.2.6.1.  */
70dc7c36e4SJohn Marino   if (needle_len < LONG_NEEDLE_THRESHOLD)
71dc7c36e4SJohn Marino     return two_way_short_needle ((const unsigned char *) haystack,
72dc7c36e4SJohn Marino                                  haystack_len,
73dc7c36e4SJohn Marino                                  (const unsigned char *) needle, needle_len);
74dc7c36e4SJohn Marino   return two_way_long_needle ((const unsigned char *) haystack, haystack_len,
75dc7c36e4SJohn Marino                               (const unsigned char *) needle, needle_len);
76dc7c36e4SJohn Marino }
77dc7c36e4SJohn Marino 
78dc7c36e4SJohn Marino #undef LONG_NEEDLE_THRESHOLD
79