unistr/u8-strstr, unistr/u16-strstr: Optimize the one-character case.
[gnulib.git] / lib / unistr / u-strstr.h
1 /* Substring test for UTF-8/UTF-16/UTF-32 strings.
2    Copyright (C) 1999, 2002, 2006, 2010 Free Software Foundation, Inc.
3    Written by Bruno Haible <bruno@clisp.org>, 2002.
4
5    This program is free software: you can redistribute it and/or modify it
6    under the terms of the GNU Lesser General Public License as published
7    by the Free Software Foundation; either version 3 of the License, or
8    (at your option) 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 GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 UNIT *
19 FUNC (const UNIT *haystack, const UNIT *needle)
20 {
21   UNIT first = needle[0];
22
23   /* Is needle empty?  */
24   if (first == 0)
25     return (UNIT *) haystack;
26
27   /* Is needle nearly empty (only one unit)?  */
28   if (needle[1] == 0)
29     return U_STRCHR (haystack, first);
30
31 #ifdef U_STRMBTOUC
32   /* Is needle nearly empty (only one character)?  */
33   {
34     ucs4_t first_uc;
35     int count = U_STRMBTOUC (&first_uc, needle);
36     if (count > 0 && needle[count] == 0)
37       return U_STRCHR (haystack, first_uc);
38   }
39 #endif
40
41   /* Search for needle's first unit.  */
42   for (; *haystack != 0; haystack++)
43     if (*haystack == first)
44       {
45         /* Compare with needle's remaining units.  */
46         const UNIT *hptr = haystack + 1;
47         const UNIT *nptr = needle + 1;
48         for (;;)
49           {
50             if (*hptr != *nptr)
51               break;
52             hptr++; nptr++;
53             if (*nptr == 0)
54               return (UNIT *) haystack;
55           }
56       }
57
58   return NULL;
59 }