diff options
Diffstat (limited to 'newlib/libc/string/strstr.c')
-rw-r--r-- | newlib/libc/string/strstr.c | 54 |
1 files changed, 51 insertions, 3 deletions
diff --git a/newlib/libc/string/strstr.c b/newlib/libc/string/strstr.c index dddced3b2..0480bce0a 100644 --- a/newlib/libc/string/strstr.c +++ b/newlib/libc/string/strstr.c @@ -16,14 +16,14 @@ TRAD_SYNOPSIS char *<[s2]>; DESCRIPTION - Locates the first occurence in the string pointed to by <[s1]> of + Locates the first occurrence in the string pointed to by <[s1]> of the sequence of characters in the string pointed to by <[s2]> - (excluding the terminating null character). + (excluding the terminating null character). RETURNS Returns a pointer to the located string segment, or a null pointer if the string <[s2]> is not found. If <[s2]> points to - a string with zero length, the <[s1]> is returned. + a string with zero length, <[s1]> is returned. PORTABILITY <<strstr>> is ANSI C. @@ -36,11 +36,22 @@ QUICKREF #include <string.h> +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) +# 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" +#endif + char * _DEFUN (strstr, (searchee, lookfor), _CONST char *searchee _AND _CONST char *lookfor) { +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + + /* Less code size, but quadratic performance in the worst case. */ if (*searchee == 0) { if (*lookfor) @@ -70,4 +81,41 @@ _DEFUN (strstr, (searchee, lookfor), } return (char *) NULL; + +#else /* compilation for speed */ + + /* Larger code size, but guaranteed linear performance. */ + const char *haystack = searchee; + const char *needle = lookfor; + size_t needle_len; /* Length of NEEDLE. */ + size_t haystack_len; /* Known minimum length of HAYSTACK. */ + int ok = 1; /* 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 *) searchee; + + /* Reduce the size of haystack using strchr, since it has a smaller + linear coefficient than the Two-Way algorithm. */ + needle_len = needle - lookfor; + haystack = strchr (searchee + 1, *lookfor); + if (!haystack || needle_len == 1) + return (char *) haystack; + haystack_len = (haystack > searchee + needle_len ? 1 + : needle_len + searchee - haystack); + + /* Perform the search. */ + if (needle_len < LONG_NEEDLE_THRESHOLD) + return two_way_short_needle ((const unsigned char *) haystack, + haystack_len, + (const unsigned char *) lookfor, needle_len); + return two_way_long_needle ((const unsigned char *) haystack, haystack_len, + (const unsigned char *) lookfor, needle_len); +#endif /* compilation for speed */ } |