1 /* Searching in a string. 2 Copyright (C) 2005 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 #include <sys/cdefs.h> 19 __RCSID("$NetBSD: strstr.c,v 1.2 2016/05/17 14:00:09 christos Exp $"); 20 21 22 #ifdef HAVE_CONFIG_H 23 # include <config.h> 24 #endif 25 26 /* Specification. */ 27 #include "strstr.h" 28 29 #include <stddef.h> /* for NULL */ 30 31 #if HAVE_MBRTOWC 32 # include "mbuiter.h" 33 #endif 34 35 /* Find the first occurrence of NEEDLE in HAYSTACK. */ 36 char * 37 strstr (const char *haystack, const char *needle) 38 { 39 /* Be careful not to look at the entire extent of haystack or needle 40 until needed. This is useful because of these two cases: 41 - haystack may be very long, and a match of needle found early, 42 - needle may be very long, and not even a short initial segment of 43 needle may be found in haystack. */ 44 #if HAVE_MBRTOWC 45 if (MB_CUR_MAX > 1) 46 { 47 mbui_iterator_t iter_needle; 48 49 mbui_init (iter_needle, needle); 50 if (mbui_avail (iter_needle)) 51 { 52 mbui_iterator_t iter_haystack; 53 54 mbui_init (iter_haystack, haystack); 55 for (;; mbui_advance (iter_haystack)) 56 { 57 if (!mbui_avail (iter_haystack)) 58 /* No match. */ 59 return NULL; 60 61 if (mb_equal (mbui_cur (iter_haystack), mbui_cur (iter_needle))) 62 /* The first character matches. */ 63 { 64 mbui_iterator_t rhaystack; 65 mbui_iterator_t rneedle; 66 67 memcpy (&rhaystack, &iter_haystack, sizeof (mbui_iterator_t)); 68 mbui_advance (rhaystack); 69 70 mbui_init (rneedle, needle); 71 if (!mbui_avail (rneedle)) 72 abort (); 73 mbui_advance (rneedle); 74 75 for (;; mbui_advance (rhaystack), mbui_advance (rneedle)) 76 { 77 if (!mbui_avail (rneedle)) 78 /* Found a match. */ 79 return (char *) mbui_cur_ptr (iter_haystack); 80 if (!mbui_avail (rhaystack)) 81 /* No match. */ 82 return NULL; 83 if (!mb_equal (mbui_cur (rhaystack), mbui_cur (rneedle))) 84 /* Nothing in this round. */ 85 break; 86 } 87 } 88 } 89 } 90 else 91 return (char *) haystack; 92 } 93 else 94 #endif 95 { 96 if (*needle != '\0') 97 { 98 /* Speed up the following searches of needle by caching its first 99 character. */ 100 char b = *needle++; 101 102 for (;; haystack++) 103 { 104 if (*haystack == '\0') 105 /* No match. */ 106 return NULL; 107 if (*haystack == b) 108 /* The first character matches. */ 109 { 110 const char *rhaystack = haystack + 1; 111 const char *rneedle = needle; 112 113 for (;; rhaystack++, rneedle++) 114 { 115 if (*rneedle == '\0') 116 /* Found a match. */ 117 return (char *) haystack; 118 if (*rhaystack == '\0') 119 /* No match. */ 120 return NULL; 121 if (*rhaystack != *rneedle) 122 /* Nothing in this round. */ 123 break; 124 } 125 } 126 } 127 } 128 else 129 return (char *) haystack; 130 } 131 } 132