Back to index

glibc  2.9
strcasestr.c
Go to the documentation of this file.
00001 /* Return the offset of one string within another.
00002    Copyright (C) 1994, 1996-2000, 2004, 2008 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 /*
00021  * My personal strstr() implementation that beats most other algorithms.
00022  * Until someone tells me otherwise, I assume that this is the
00023  * fastest implementation of strstr() in C.
00024  * I deliberately chose not to comment it.  You should have at least
00025  * as much fun trying to understand it, as I had to write it :-).
00026  *
00027  * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de       */
00028 
00029 #if HAVE_CONFIG_H
00030 # include <config.h>
00031 #endif
00032 
00033 /* Specification.  */
00034 #include <string.h>
00035 
00036 #include <ctype.h>
00037 #include <stdbool.h>
00038 #include <strings.h>
00039 
00040 #define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
00041 
00042 /* Two-Way algorithm.  */
00043 #define RETURN_TYPE char *
00044 #define AVAILABLE(h, h_l, j, n_l)                \
00045   (!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l))     \
00046    && ((h_l) = (j) + (n_l)))
00047 #define CANON_ELEMENT(c) TOLOWER (c)
00048 #define CMP_FUNC(p1, p2, l)                      \
00049   __strncasecmp ((const char *) (p1), (const char *) (p2), l)
00050 #include "str-two-way.h"
00051 
00052 #undef strcasestr
00053 #undef __strcasestr
00054 
00055 /* Find the first occurrence of NEEDLE in HAYSTACK, using
00056    case-insensitive comparison.  This function gives unspecified
00057    results in multibyte locales.  */
00058 char *
00059 __strcasestr (const char *haystack_start, const char *needle_start)
00060 {
00061   const char *haystack = haystack_start;
00062   const char *needle = needle_start;
00063   size_t needle_len; /* Length of NEEDLE.  */
00064   size_t haystack_len; /* Known minimum length of HAYSTACK.  */
00065   bool ok = true; /* True if NEEDLE is prefix of HAYSTACK.  */
00066 
00067   /* Determine length of NEEDLE, and in the process, make sure
00068      HAYSTACK is at least as long (no point processing all of a long
00069      NEEDLE if HAYSTACK is too short).  */
00070   while (*haystack && *needle)
00071     {
00072       ok &= (TOLOWER ((unsigned char) *haystack)
00073             == TOLOWER ((unsigned char) *needle));
00074       haystack++;
00075       needle++;
00076     }
00077   if (*needle)
00078     return NULL;
00079   if (ok)
00080     return (char *) haystack_start;
00081   needle_len = needle - needle_start;
00082   haystack = haystack_start + 1;
00083   haystack_len = needle_len - 1;
00084 
00085   /* Perform the search.  Abstract memory is considered to be an array
00086      of 'unsigned char' values, not an array of 'char' values.  See
00087      ISO C 99 section 6.2.6.1.  */
00088   if (needle_len < LONG_NEEDLE_THRESHOLD)
00089     return two_way_short_needle ((const unsigned char *) haystack,
00090                              haystack_len,
00091                              (const unsigned char *) needle_start,
00092                              needle_len);
00093   return two_way_long_needle ((const unsigned char *) haystack, haystack_len,
00094                            (const unsigned char *) needle_start,
00095                            needle_len);
00096 }
00097 
00098 #undef LONG_NEEDLE_THRESHOLD
00099 
00100 weak_alias (__strcasestr, strcasestr)