Home | History | Annotate | Line # | Download | only in gnulib-lib
      1  1.1  christos /* Searching in a string.
      2  1.1  christos    Copyright (C) 2005-2006 Free Software Foundation, Inc.
      3  1.1  christos    Written by Bruno Haible <bruno (at) clisp.org>, 2005.
      4  1.1  christos 
      5  1.1  christos    This program is free software; you can redistribute it and/or modify
      6  1.1  christos    it under the terms of the GNU General Public License as published by
      7  1.1  christos    the Free Software Foundation; either version 2, or (at your option)
      8  1.1  christos    any later version.
      9  1.1  christos 
     10  1.1  christos    This program is distributed in the hope that it will be useful,
     11  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  1.1  christos    GNU General Public License for more details.
     14  1.1  christos 
     15  1.1  christos    You should have received a copy of the GNU General Public License
     16  1.1  christos    along with this program; if not, write to the Free Software Foundation,
     17  1.1  christos    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
     18  1.1  christos 
     19  1.1  christos #include <config.h>
     20  1.1  christos 
     21  1.1  christos /* Specification.  */
     22  1.1  christos #include "strstr.h"
     23  1.1  christos 
     24  1.1  christos #include <stddef.h>  /* for NULL */
     25  1.1  christos 
     26  1.1  christos #if HAVE_MBRTOWC
     27  1.1  christos # include "mbuiter.h"
     28  1.1  christos #endif
     29  1.1  christos 
     30  1.1  christos /* Find the first occurrence of NEEDLE in HAYSTACK.  */
     31  1.1  christos char *
     32  1.1  christos strstr (const char *haystack, const char *needle)
     33  1.1  christos {
     34  1.1  christos   /* Be careful not to look at the entire extent of haystack or needle
     35  1.1  christos      until needed.  This is useful because of these two cases:
     36  1.1  christos        - haystack may be very long, and a match of needle found early,
     37  1.1  christos        - needle may be very long, and not even a short initial segment of
     38  1.1  christos          needle may be found in haystack.  */
     39  1.1  christos #if HAVE_MBRTOWC
     40  1.1  christos   if (MB_CUR_MAX > 1)
     41  1.1  christos     {
     42  1.1  christos       mbui_iterator_t iter_needle;
     43  1.1  christos 
     44  1.1  christos       mbui_init (iter_needle, needle);
     45  1.1  christos       if (mbui_avail (iter_needle))
     46  1.1  christos 	{
     47  1.1  christos 	  mbui_iterator_t iter_haystack;
     48  1.1  christos 
     49  1.1  christos 	  mbui_init (iter_haystack, haystack);
     50  1.1  christos 	  for (;; mbui_advance (iter_haystack))
     51  1.1  christos 	    {
     52  1.1  christos 	      if (!mbui_avail (iter_haystack))
     53  1.1  christos 		/* No match.  */
     54  1.1  christos 		return NULL;
     55  1.1  christos 
     56  1.1  christos 	      if (mb_equal (mbui_cur (iter_haystack), mbui_cur (iter_needle)))
     57  1.1  christos 		/* The first character matches.  */
     58  1.1  christos 		{
     59  1.1  christos 		  mbui_iterator_t rhaystack;
     60  1.1  christos 		  mbui_iterator_t rneedle;
     61  1.1  christos 
     62  1.1  christos 		  memcpy (&rhaystack, &iter_haystack, sizeof (mbui_iterator_t));
     63  1.1  christos 		  mbui_advance (rhaystack);
     64  1.1  christos 
     65  1.1  christos 		  mbui_init (rneedle, needle);
     66  1.1  christos 		  if (!mbui_avail (rneedle))
     67  1.1  christos 		    abort ();
     68  1.1  christos 		  mbui_advance (rneedle);
     69  1.1  christos 
     70  1.1  christos 		  for (;; mbui_advance (rhaystack), mbui_advance (rneedle))
     71  1.1  christos 		    {
     72  1.1  christos 		      if (!mbui_avail (rneedle))
     73  1.1  christos 			/* Found a match.  */
     74  1.1  christos 			return (char *) mbui_cur_ptr (iter_haystack);
     75  1.1  christos 		      if (!mbui_avail (rhaystack))
     76  1.1  christos 			/* No match.  */
     77  1.1  christos 			return NULL;
     78  1.1  christos 		      if (!mb_equal (mbui_cur (rhaystack), mbui_cur (rneedle)))
     79  1.1  christos 			/* Nothing in this round.  */
     80  1.1  christos 			break;
     81  1.1  christos 		    }
     82  1.1  christos 		}
     83  1.1  christos 	    }
     84  1.1  christos 	}
     85  1.1  christos       else
     86  1.1  christos 	return (char *) haystack;
     87  1.1  christos     }
     88  1.1  christos   else
     89  1.1  christos #endif
     90  1.1  christos     {
     91  1.1  christos       if (*needle != '\0')
     92  1.1  christos 	{
     93  1.1  christos 	  /* Speed up the following searches of needle by caching its first
     94  1.1  christos 	     character.  */
     95  1.1  christos 	  char b = *needle++;
     96  1.1  christos 
     97  1.1  christos 	  for (;; haystack++)
     98  1.1  christos 	    {
     99  1.1  christos 	      if (*haystack == '\0')
    100  1.1  christos 		/* No match.  */
    101  1.1  christos 		return NULL;
    102  1.1  christos 	      if (*haystack == b)
    103  1.1  christos 		/* The first character matches.  */
    104  1.1  christos 		{
    105  1.1  christos 		  const char *rhaystack = haystack + 1;
    106  1.1  christos 		  const char *rneedle = needle;
    107  1.1  christos 
    108  1.1  christos 		  for (;; rhaystack++, rneedle++)
    109  1.1  christos 		    {
    110  1.1  christos 		      if (*rneedle == '\0')
    111  1.1  christos 			/* Found a match.  */
    112  1.1  christos 			return (char *) haystack;
    113  1.1  christos 		      if (*rhaystack == '\0')
    114  1.1  christos 			/* No match.  */
    115  1.1  christos 			return NULL;
    116  1.1  christos 		      if (*rhaystack != *rneedle)
    117  1.1  christos 			/* Nothing in this round.  */
    118  1.1  christos 			break;
    119  1.1  christos 		    }
    120  1.1  christos 		}
    121  1.1  christos 	    }
    122  1.1  christos 	}
    123  1.1  christos       else
    124  1.1  christos 	return (char *) haystack;
    125  1.1  christos     }
    126  1.1  christos }
    127