1 /*
2 FUNCTION
3 <<strstr>>---find string segment
4
5 INDEX
6 strstr
7
8 ANSI_SYNOPSIS
9 #include <string.h>
10 char *strstr(const char *<[s1]>, const char *<[s2]>);
11
12 TRAD_SYNOPSIS
13 #include <string.h>
14 char *strstr(<[s1]>, <[s2]>)
15 char *<[s1]>;
16 char *<[s2]>;
17
18 DESCRIPTION
19 Locates the first occurrence in the string pointed to by <[s1]> of
20 the sequence of characters in the string pointed to by <[s2]>
21 (excluding the terminating null character).
22
23 RETURNS
24 Returns a pointer to the located string segment, or a null
25 pointer if the string <[s2]> is not found. If <[s2]> points to
26 a string with zero length, <[s1]> is returned.
27
28 PORTABILITY
29 <<strstr>> is ANSI C.
30
31 <<strstr>> requires no supporting OS subroutines.
32
33 QUICKREF
34 strstr ansi pure
35 */
36
37 #include <section_config.h>
38 #include <basic_types.h>
39
40 #include <string.h>
41
42 extern char * _strchr(const char *s1 , int i);
43
44 #if !defined(PREFER_SIZE_OVER_SPEED)
45 # define RETURN_TYPE char *
46 # define AVAILABLE(h, h_l, j, n_l) \
47 (! _memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l)) \
48 && ((h_l) = (j) + (n_l)))
49 # include "str-two-way.h"
50 #endif
51
52 LIBC_ROM_TEXT_SECTION
53 _LONG_CALL_
_strstr(const char * searchee,const char * lookfor)54 char * _strstr(const char *searchee , const char *lookfor)
55 {
56 #if defined(PREFER_SIZE_OVER_SPEED)
57
58 /* Less code size, but quadratic performance in the worst case. */
59 if (*searchee == 0)
60 {
61 if (*lookfor)
62 return (char *) NULL;
63 return (char *) searchee;
64 }
65
66 while (*searchee)
67 {
68 size_t i;
69 i = 0;
70
71 while (1)
72 {
73 if (lookfor[i] == 0)
74 {
75 return (char *) searchee;
76 }
77
78 if (lookfor[i] != searchee[i])
79 {
80 break;
81 }
82 i++;
83 }
84 searchee++;
85 }
86
87 return (char *) NULL;
88
89 #else /* compilation for speed */
90
91 /* Larger code size, but guaranteed linear performance. */
92 const char *haystack = searchee;
93 const char *needle = lookfor;
94 size_t needle_len; /* Length of NEEDLE. */
95 size_t haystack_len; /* Known minimum length of HAYSTACK. */
96 int ok = 1; /* True if NEEDLE is prefix of HAYSTACK. */
97
98 /* Determine length of NEEDLE, and in the process, make sure
99 HAYSTACK is at least as long (no point processing all of a long
100 NEEDLE if HAYSTACK is too short). */
101 while (*haystack && *needle)
102 ok &= *haystack++ == *needle++;
103 if (*needle)
104 return NULL;
105 if (ok)
106 return (char *) searchee;
107
108 /* Reduce the size of haystack using strchr, since it has a smaller
109 linear coefficient than the Two-Way algorithm. */
110 needle_len = needle - lookfor;
111 haystack = _strchr (searchee + 1, *lookfor);
112 if (!haystack || needle_len == 1)
113 return (char *) haystack;
114 haystack_len = (haystack > searchee + needle_len ? 1
115 : needle_len + searchee - haystack);
116
117 /* Perform the search. */
118 if (needle_len < LONG_NEEDLE_THRESHOLD)
119 return __rtl_two_way_short_needle ((const unsigned char *) haystack,
120 haystack_len,
121 (const unsigned char *) lookfor, needle_len);
122 return __rtl_two_way_long_needle ((const unsigned char *) haystack, haystack_len,
123 (const unsigned char *) lookfor, needle_len);
124 #endif /* compilation for speed */
125 }
126