X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fstrstr.c;h=265fc8533ac0d9ea7b9dd24a1230556301ecc348;hb=a731808a4ac512228e870d5f443b91557f418559;hp=77f24cbc93b7a50bbbb7419b187f2ebc0ae0143e;hpb=f49cdb3fcfccab4b4e56f08aa00b7df561951662;p=gnulib.git diff --git a/lib/strstr.c b/lib/strstr.c index 77f24cbc9..265fc8533 100644 --- a/lib/strstr.c +++ b/lib/strstr.c @@ -1,5 +1,6 @@ -/* strstr.c -- return the offset of one string within another - Copyright (C) 1989, 1990 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1992, 1993, 1994, 1996, 1997, 1998, 2000, 2004, 2007, + 2008, 2009, 2010 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 the GNU General Public License as published by @@ -11,34 +12,72 @@ 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, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* Written by Mike Rendell . */ +/* This particular implementation was written by Eric Blake, 2008. */ -/* Return the starting address of string S2 in S1; - return 0 if it is not found. */ +#ifndef _LIBC +# include +#endif +/* Specification of strstr. */ +#include + +#include + +#ifndef _LIBC +# define __builtin_expect(expr, val) (expr) +#endif + +#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 (s1, s2) - char *s1; - char *s2; +strstr (const char *haystack_start, const char *needle_start) { - int i; - char *p1; - char *p2; - char *s = s1; - - for (p2 = s2, i = 0; *s; p2 = s2, i++, s++) - { - for (p1 = s; *p1 && *p2 && *p1 == *p2; p1++, p2++) - ; - if (!*p2) - break; - } - if (!*p2) - return s1 + i; - - return 0; + 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