xref: /netbsd-src/external/gpl2/gettext/dist/gettext-runtime/gnulib-lib/memchr.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
1*946379e7Schristos /* Copyright (C) 1991, 1993, 1996, 1997, 1999, 2000, 2003, 2004, 2006 Free
2*946379e7Schristos    Software Foundation, Inc.
3*946379e7Schristos 
4*946379e7Schristos    Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
5*946379e7Schristos    with help from Dan Sahlin (dan@sics.se) and
6*946379e7Schristos    commentary by Jim Blandy (jimb@ai.mit.edu);
7*946379e7Schristos    adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
8*946379e7Schristos    and implemented by Roland McGrath (roland@ai.mit.edu).
9*946379e7Schristos 
10*946379e7Schristos NOTE: The canonical source of this file is maintained with the GNU C Library.
11*946379e7Schristos Bugs can be reported to bug-glibc@prep.ai.mit.edu.
12*946379e7Schristos 
13*946379e7Schristos This program is free software; you can redistribute it and/or modify it
14*946379e7Schristos under the terms of the GNU General Public License as published by the
15*946379e7Schristos Free Software Foundation; either version 2, or (at your option) any
16*946379e7Schristos later version.
17*946379e7Schristos 
18*946379e7Schristos This program is distributed in the hope that it will be useful,
19*946379e7Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
20*946379e7Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21*946379e7Schristos GNU General Public License for more details.
22*946379e7Schristos 
23*946379e7Schristos You should have received a copy of the GNU General Public License
24*946379e7Schristos along with this program; if not, write to the Free Software Foundation,
25*946379e7Schristos Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
26*946379e7Schristos 
27*946379e7Schristos #ifndef _LIBC
28*946379e7Schristos # include <config.h>
29*946379e7Schristos #endif
30*946379e7Schristos 
31*946379e7Schristos #include <string.h>
32*946379e7Schristos 
33*946379e7Schristos #include <stddef.h>
34*946379e7Schristos 
35*946379e7Schristos #if defined _LIBC
36*946379e7Schristos # include <memcopy.h>
37*946379e7Schristos #else
38*946379e7Schristos # define reg_char char
39*946379e7Schristos #endif
40*946379e7Schristos 
41*946379e7Schristos #include <limits.h>
42*946379e7Schristos 
43*946379e7Schristos #if HAVE_BP_SYM_H || defined _LIBC
44*946379e7Schristos # include <bp-sym.h>
45*946379e7Schristos #else
46*946379e7Schristos # define BP_SYM(sym) sym
47*946379e7Schristos #endif
48*946379e7Schristos 
49*946379e7Schristos #undef memchr
50*946379e7Schristos #undef __memchr
51*946379e7Schristos 
52*946379e7Schristos /* Search no more than N bytes of S for C.  */
53*946379e7Schristos void *
__memchr(void const * s,int c_in,size_t n)54*946379e7Schristos __memchr (void const *s, int c_in, size_t n)
55*946379e7Schristos {
56*946379e7Schristos   const unsigned char *char_ptr;
57*946379e7Schristos   const unsigned long int *longword_ptr;
58*946379e7Schristos   unsigned long int longword, magic_bits, charmask;
59*946379e7Schristos   unsigned reg_char c;
60*946379e7Schristos   int i;
61*946379e7Schristos 
62*946379e7Schristos   c = (unsigned char) c_in;
63*946379e7Schristos 
64*946379e7Schristos   /* Handle the first few characters by reading one character at a time.
65*946379e7Schristos      Do this until CHAR_PTR is aligned on a longword boundary.  */
66*946379e7Schristos   for (char_ptr = (const unsigned char *) s;
67*946379e7Schristos        n > 0 && (size_t) char_ptr % sizeof longword != 0;
68*946379e7Schristos        --n, ++char_ptr)
69*946379e7Schristos     if (*char_ptr == c)
70*946379e7Schristos       return (void *) char_ptr;
71*946379e7Schristos 
72*946379e7Schristos   /* All these elucidatory comments refer to 4-byte longwords,
73*946379e7Schristos      but the theory applies equally well to any size longwords.  */
74*946379e7Schristos 
75*946379e7Schristos   longword_ptr = (const unsigned long int *) char_ptr;
76*946379e7Schristos 
77*946379e7Schristos   /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
78*946379e7Schristos      the "holes."  Note that there is a hole just to the left of
79*946379e7Schristos      each byte, with an extra at the end:
80*946379e7Schristos 
81*946379e7Schristos      bits:  01111110 11111110 11111110 11111111
82*946379e7Schristos      bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
83*946379e7Schristos 
84*946379e7Schristos      The 1-bits make sure that carries propagate to the next 0-bit.
85*946379e7Schristos      The 0-bits provide holes for carries to fall into.  */
86*946379e7Schristos 
87*946379e7Schristos   /* Set MAGIC_BITS to be this pattern of 1 and 0 bits.
88*946379e7Schristos      Set CHARMASK to be a longword, each of whose bytes is C.  */
89*946379e7Schristos 
90*946379e7Schristos   magic_bits = 0xfefefefe;
91*946379e7Schristos   charmask = c | (c << 8);
92*946379e7Schristos   charmask |= charmask << 16;
93*946379e7Schristos #if 0xffffffffU < ULONG_MAX
94*946379e7Schristos   magic_bits |= magic_bits << 32;
95*946379e7Schristos   charmask |= charmask << 32;
96*946379e7Schristos   if (8 < sizeof longword)
97*946379e7Schristos     for (i = 64; i < sizeof longword * 8; i *= 2)
98*946379e7Schristos       {
99*946379e7Schristos 	magic_bits |= magic_bits << i;
100*946379e7Schristos 	charmask |= charmask << i;
101*946379e7Schristos       }
102*946379e7Schristos #endif
103*946379e7Schristos   magic_bits = (ULONG_MAX >> 1) & (magic_bits | 1);
104*946379e7Schristos 
105*946379e7Schristos   /* Instead of the traditional loop which tests each character,
106*946379e7Schristos      we will test a longword at a time.  The tricky part is testing
107*946379e7Schristos      if *any of the four* bytes in the longword in question are zero.  */
108*946379e7Schristos   while (n >= sizeof longword)
109*946379e7Schristos     {
110*946379e7Schristos       /* We tentatively exit the loop if adding MAGIC_BITS to
111*946379e7Schristos 	 LONGWORD fails to change any of the hole bits of LONGWORD.
112*946379e7Schristos 
113*946379e7Schristos 	 1) Is this safe?  Will it catch all the zero bytes?
114*946379e7Schristos 	 Suppose there is a byte with all zeros.  Any carry bits
115*946379e7Schristos 	 propagating from its left will fall into the hole at its
116*946379e7Schristos 	 least significant bit and stop.  Since there will be no
117*946379e7Schristos 	 carry from its most significant bit, the LSB of the
118*946379e7Schristos 	 byte to the left will be unchanged, and the zero will be
119*946379e7Schristos 	 detected.
120*946379e7Schristos 
121*946379e7Schristos 	 2) Is this worthwhile?  Will it ignore everything except
122*946379e7Schristos 	 zero bytes?  Suppose every byte of LONGWORD has a bit set
123*946379e7Schristos 	 somewhere.  There will be a carry into bit 8.  If bit 8
124*946379e7Schristos 	 is set, this will carry into bit 16.  If bit 8 is clear,
125*946379e7Schristos 	 one of bits 9-15 must be set, so there will be a carry
126*946379e7Schristos 	 into bit 16.  Similarly, there will be a carry into bit
127*946379e7Schristos 	 24.  If one of bits 24-30 is set, there will be a carry
128*946379e7Schristos 	 into bit 31, so all of the hole bits will be changed.
129*946379e7Schristos 
130*946379e7Schristos 	 The one misfire occurs when bits 24-30 are clear and bit
131*946379e7Schristos 	 31 is set; in this case, the hole at bit 31 is not
132*946379e7Schristos 	 changed.  If we had access to the processor carry flag,
133*946379e7Schristos 	 we could close this loophole by putting the fourth hole
134*946379e7Schristos 	 at bit 32!
135*946379e7Schristos 
136*946379e7Schristos 	 So it ignores everything except 128's, when they're aligned
137*946379e7Schristos 	 properly.
138*946379e7Schristos 
139*946379e7Schristos 	 3) But wait!  Aren't we looking for C, not zero?
140*946379e7Schristos 	 Good point.  So what we do is XOR LONGWORD with a longword,
141*946379e7Schristos 	 each of whose bytes is C.  This turns each byte that is C
142*946379e7Schristos 	 into a zero.  */
143*946379e7Schristos 
144*946379e7Schristos       longword = *longword_ptr++ ^ charmask;
145*946379e7Schristos 
146*946379e7Schristos       /* Add MAGIC_BITS to LONGWORD.  */
147*946379e7Schristos       if ((((longword + magic_bits)
148*946379e7Schristos 
149*946379e7Schristos 	    /* Set those bits that were unchanged by the addition.  */
150*946379e7Schristos 	    ^ ~longword)
151*946379e7Schristos 
152*946379e7Schristos 	   /* Look at only the hole bits.  If any of the hole bits
153*946379e7Schristos 	      are unchanged, most likely one of the bytes was a
154*946379e7Schristos 	      zero.  */
155*946379e7Schristos 	   & ~magic_bits) != 0)
156*946379e7Schristos 	{
157*946379e7Schristos 	  /* Which of the bytes was C?  If none of them were, it was
158*946379e7Schristos 	     a misfire; continue the search.  */
159*946379e7Schristos 
160*946379e7Schristos 	  const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);
161*946379e7Schristos 
162*946379e7Schristos 	  if (cp[0] == c)
163*946379e7Schristos 	    return (void *) cp;
164*946379e7Schristos 	  if (cp[1] == c)
165*946379e7Schristos 	    return (void *) &cp[1];
166*946379e7Schristos 	  if (cp[2] == c)
167*946379e7Schristos 	    return (void *) &cp[2];
168*946379e7Schristos 	  if (cp[3] == c)
169*946379e7Schristos 	    return (void *) &cp[3];
170*946379e7Schristos 	  if (4 < sizeof longword && cp[4] == c)
171*946379e7Schristos 	    return (void *) &cp[4];
172*946379e7Schristos 	  if (5 < sizeof longword && cp[5] == c)
173*946379e7Schristos 	    return (void *) &cp[5];
174*946379e7Schristos 	  if (6 < sizeof longword && cp[6] == c)
175*946379e7Schristos 	    return (void *) &cp[6];
176*946379e7Schristos 	  if (7 < sizeof longword && cp[7] == c)
177*946379e7Schristos 	    return (void *) &cp[7];
178*946379e7Schristos 	  if (8 < sizeof longword)
179*946379e7Schristos 	    for (i = 8; i < sizeof longword; i++)
180*946379e7Schristos 	      if (cp[i] == c)
181*946379e7Schristos 		return (void *) &cp[i];
182*946379e7Schristos 	}
183*946379e7Schristos 
184*946379e7Schristos       n -= sizeof longword;
185*946379e7Schristos     }
186*946379e7Schristos 
187*946379e7Schristos   char_ptr = (const unsigned char *) longword_ptr;
188*946379e7Schristos 
189*946379e7Schristos   while (n-- > 0)
190*946379e7Schristos     {
191*946379e7Schristos       if (*char_ptr == c)
192*946379e7Schristos 	return (void *) char_ptr;
193*946379e7Schristos       else
194*946379e7Schristos 	++char_ptr;
195*946379e7Schristos     }
196*946379e7Schristos 
197*946379e7Schristos   return 0;
198*946379e7Schristos }
199*946379e7Schristos #ifdef weak_alias
200*946379e7Schristos weak_alias (__memchr, BP_SYM (memchr))
201*946379e7Schristos #endif
202