1 /* c-strcasestr.c -- case insensitive substring search in C locale 2 Copyright (C) 2005-2006 Free Software Foundation, Inc. 3 Written by Bruno Haible <bruno@clisp.org>, 2005. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2, or (at your option) 8 any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software Foundation, 17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 18 19 #include <config.h> 20 21 /* Specification. */ 22 #include "c-strcasestr.h" 23 24 #include <stddef.h> 25 26 #include "c-ctype.h" 27 28 /* Find the first occurrence of NEEDLE in HAYSTACK, using case-insensitive 29 comparison. 30 Note: This function may, in multibyte locales, return success even if 31 strlen (haystack) < strlen (needle) ! */ 32 char * 33 c_strcasestr (const char *haystack, const char *needle) 34 { 35 /* Be careful not to look at the entire extent of haystack or needle 36 until needed. This is useful because of these two cases: 37 - haystack may be very long, and a match of needle found early, 38 - needle may be very long, and not even a short initial segment of 39 needle may be found in haystack. */ 40 if (*needle != '\0') 41 { 42 /* Speed up the following searches of needle by caching its first 43 character. */ 44 unsigned char b = c_tolower ((unsigned char) *needle); 45 46 needle++; 47 for (;; haystack++) 48 { 49 if (*haystack == '\0') 50 /* No match. */ 51 return NULL; 52 if (c_tolower ((unsigned char) *haystack) == b) 53 /* The first character matches. */ 54 { 55 const char *rhaystack = haystack + 1; 56 const char *rneedle = needle; 57 58 for (;; rhaystack++, rneedle++) 59 { 60 if (*rneedle == '\0') 61 /* Found a match. */ 62 return (char *) haystack; 63 if (*rhaystack == '\0') 64 /* No match. */ 65 return NULL; 66 if (c_tolower ((unsigned char) *rhaystack) 67 != c_tolower ((unsigned char) *rneedle)) 68 /* Nothing in this round. */ 69 break; 70 } 71 } 72 } 73 } 74 else 75 return (char *) haystack; 76 } 77