Blame gnulib/lib/memchr.c

Packit 15a5a8
/* Copyright (C) 1991, 1993, 1996, 1997, 1999, 2000, 2003, 2004, 2006 Free
Packit 15a5a8
   Software Foundation, Inc.
Packit 15a5a8
Packit 15a5a8
   Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
Packit 15a5a8
   with help from Dan Sahlin (dan@sics.se) and
Packit 15a5a8
   commentary by Jim Blandy (jimb@ai.mit.edu);
Packit 15a5a8
   adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
Packit 15a5a8
   and implemented by Roland McGrath (roland@ai.mit.edu).
Packit 15a5a8
Packit 15a5a8
NOTE: The canonical source of this file is maintained with the GNU C Library.
Packit 15a5a8
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
Packit 15a5a8
Packit 15a5a8
This program is free software; you can redistribute it and/or modify it
Packit 15a5a8
under the terms of the GNU General Public License as published by the
Packit 15a5a8
Free Software Foundation; either version 2, or (at your option) any
Packit 15a5a8
later version.
Packit 15a5a8
Packit 15a5a8
This program is distributed in the hope that it will be useful,
Packit 15a5a8
but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 15a5a8
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 15a5a8
GNU General Public License for more details.
Packit 15a5a8
Packit 15a5a8
You should have received a copy of the GNU General Public License
Packit 15a5a8
along with this program; if not, write to the Free Software Foundation,
Packit 15a5a8
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
Packit 15a5a8
Packit 15a5a8
#ifndef _LIBC
Packit 15a5a8
# include <config.h>
Packit 15a5a8
#endif
Packit 15a5a8
Packit 15a5a8
#include <string.h>
Packit 15a5a8
Packit 15a5a8
#include <stddef.h>
Packit 15a5a8
Packit 15a5a8
#if defined _LIBC
Packit 15a5a8
# include <memcopy.h>
Packit 15a5a8
#else
Packit 15a5a8
# define reg_char char
Packit 15a5a8
#endif
Packit 15a5a8
Packit 15a5a8
#include <limits.h>
Packit 15a5a8
Packit 15a5a8
#if HAVE_BP_SYM_H || defined _LIBC
Packit 15a5a8
# include <bp-sym.h>
Packit 15a5a8
#else
Packit 15a5a8
# define BP_SYM(sym) sym
Packit 15a5a8
#endif
Packit 15a5a8
Packit 15a5a8
#undef memchr
Packit 15a5a8
#undef __memchr
Packit 15a5a8
Packit 15a5a8
/* Search no more than N bytes of S for C.  */
Packit 15a5a8
void *
Packit 15a5a8
__memchr (void const *s, int c_in, size_t n)
Packit 15a5a8
{
Packit 15a5a8
  const unsigned char *char_ptr;
Packit 15a5a8
  const unsigned long int *longword_ptr;
Packit 15a5a8
  unsigned long int longword, magic_bits, charmask;
Packit 15a5a8
  unsigned reg_char c;
Packit 15a5a8
  int i;
Packit 15a5a8
Packit 15a5a8
  c = (unsigned char) c_in;
Packit 15a5a8
Packit 15a5a8
  /* Handle the first few characters by reading one character at a time.
Packit 15a5a8
     Do this until CHAR_PTR is aligned on a longword boundary.  */
Packit 15a5a8
  for (char_ptr = (const unsigned char *) s;
Packit 15a5a8
       n > 0 && (size_t) char_ptr % sizeof longword != 0;
Packit 15a5a8
       --n, ++char_ptr)
Packit 15a5a8
    if (*char_ptr == c)
Packit 15a5a8
      return (void *) char_ptr;
Packit 15a5a8
Packit 15a5a8
  /* All these elucidatory comments refer to 4-byte longwords,
Packit 15a5a8
     but the theory applies equally well to any size longwords.  */
Packit 15a5a8
Packit 15a5a8
  longword_ptr = (const unsigned long int *) char_ptr;
Packit 15a5a8
Packit 15a5a8
  /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
Packit 15a5a8
     the "holes."  Note that there is a hole just to the left of
Packit 15a5a8
     each byte, with an extra at the end:
Packit 15a5a8
Packit 15a5a8
     bits:  01111110 11111110 11111110 11111111
Packit 15a5a8
     bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
Packit 15a5a8
Packit 15a5a8
     The 1-bits make sure that carries propagate to the next 0-bit.
Packit 15a5a8
     The 0-bits provide holes for carries to fall into.  */
Packit 15a5a8
Packit 15a5a8
  /* Set MAGIC_BITS to be this pattern of 1 and 0 bits.
Packit 15a5a8
     Set CHARMASK to be a longword, each of whose bytes is C.  */
Packit 15a5a8
Packit 15a5a8
  magic_bits = 0xfefefefe;
Packit 15a5a8
  charmask = c | (c << 8);
Packit 15a5a8
  charmask |= charmask << 16;
Packit 15a5a8
#if 0xffffffffU < ULONG_MAX
Packit 15a5a8
  magic_bits |= magic_bits << 32;
Packit 15a5a8
  charmask |= charmask << 32;
Packit 15a5a8
  if (8 < sizeof longword)
Packit 15a5a8
    for (i = 64; i < sizeof longword * 8; i *= 2)
Packit 15a5a8
      {
Packit 15a5a8
	magic_bits |= magic_bits << i;
Packit 15a5a8
	charmask |= charmask << i;
Packit 15a5a8
      }
Packit 15a5a8
#endif
Packit 15a5a8
  magic_bits = (ULONG_MAX >> 1) & (magic_bits | 1);
Packit 15a5a8
Packit 15a5a8
  /* Instead of the traditional loop which tests each character,
Packit 15a5a8
     we will test a longword at a time.  The tricky part is testing
Packit 15a5a8
     if *any of the four* bytes in the longword in question are zero.  */
Packit 15a5a8
  while (n >= sizeof longword)
Packit 15a5a8
    {
Packit 15a5a8
      /* We tentatively exit the loop if adding MAGIC_BITS to
Packit 15a5a8
	 LONGWORD fails to change any of the hole bits of LONGWORD.
Packit 15a5a8
Packit 15a5a8
	 1) Is this safe?  Will it catch all the zero bytes?
Packit 15a5a8
	 Suppose there is a byte with all zeros.  Any carry bits
Packit 15a5a8
	 propagating from its left will fall into the hole at its
Packit 15a5a8
	 least significant bit and stop.  Since there will be no
Packit 15a5a8
	 carry from its most significant bit, the LSB of the
Packit 15a5a8
	 byte to the left will be unchanged, and the zero will be
Packit 15a5a8
	 detected.
Packit 15a5a8
Packit 15a5a8
	 2) Is this worthwhile?  Will it ignore everything except
Packit 15a5a8
	 zero bytes?  Suppose every byte of LONGWORD has a bit set
Packit 15a5a8
	 somewhere.  There will be a carry into bit 8.  If bit 8
Packit 15a5a8
	 is set, this will carry into bit 16.  If bit 8 is clear,
Packit 15a5a8
	 one of bits 9-15 must be set, so there will be a carry
Packit 15a5a8
	 into bit 16.  Similarly, there will be a carry into bit
Packit 15a5a8
	 24.  If one of bits 24-30 is set, there will be a carry
Packit 15a5a8
	 into bit 31, so all of the hole bits will be changed.
Packit 15a5a8
Packit 15a5a8
	 The one misfire occurs when bits 24-30 are clear and bit
Packit 15a5a8
	 31 is set; in this case, the hole at bit 31 is not
Packit 15a5a8
	 changed.  If we had access to the processor carry flag,
Packit 15a5a8
	 we could close this loophole by putting the fourth hole
Packit 15a5a8
	 at bit 32!
Packit 15a5a8
Packit 15a5a8
	 So it ignores everything except 128's, when they're aligned
Packit 15a5a8
	 properly.
Packit 15a5a8
Packit 15a5a8
	 3) But wait!  Aren't we looking for C, not zero?
Packit 15a5a8
	 Good point.  So what we do is XOR LONGWORD with a longword,
Packit 15a5a8
	 each of whose bytes is C.  This turns each byte that is C
Packit 15a5a8
	 into a zero.  */
Packit 15a5a8
Packit 15a5a8
      longword = *longword_ptr++ ^ charmask;
Packit 15a5a8
Packit 15a5a8
      /* Add MAGIC_BITS to LONGWORD.  */
Packit 15a5a8
      if ((((longword + magic_bits)
Packit 15a5a8
Packit 15a5a8
	    /* Set those bits that were unchanged by the addition.  */
Packit 15a5a8
	    ^ ~longword)
Packit 15a5a8
Packit 15a5a8
	   /* Look at only the hole bits.  If any of the hole bits
Packit 15a5a8
	      are unchanged, most likely one of the bytes was a
Packit 15a5a8
	      zero.  */
Packit 15a5a8
	   & ~magic_bits) != 0)
Packit 15a5a8
	{
Packit 15a5a8
	  /* Which of the bytes was C?  If none of them were, it was
Packit 15a5a8
	     a misfire; continue the search.  */
Packit 15a5a8
Packit 15a5a8
	  const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);
Packit 15a5a8
Packit 15a5a8
	  if (cp[0] == c)
Packit 15a5a8
	    return (void *) cp;
Packit 15a5a8
	  if (cp[1] == c)
Packit 15a5a8
	    return (void *) &cp[1];
Packit 15a5a8
	  if (cp[2] == c)
Packit 15a5a8
	    return (void *) &cp[2];
Packit 15a5a8
	  if (cp[3] == c)
Packit 15a5a8
	    return (void *) &cp[3];
Packit 15a5a8
	  if (4 < sizeof longword && cp[4] == c)
Packit 15a5a8
	    return (void *) &cp[4];
Packit 15a5a8
	  if (5 < sizeof longword && cp[5] == c)
Packit 15a5a8
	    return (void *) &cp[5];
Packit 15a5a8
	  if (6 < sizeof longword && cp[6] == c)
Packit 15a5a8
	    return (void *) &cp[6];
Packit 15a5a8
	  if (7 < sizeof longword && cp[7] == c)
Packit 15a5a8
	    return (void *) &cp[7];
Packit 15a5a8
	  if (8 < sizeof longword)
Packit 15a5a8
	    for (i = 8; i < sizeof longword; i++)
Packit 15a5a8
	      if (cp[i] == c)
Packit 15a5a8
		return (void *) &cp[i];
Packit 15a5a8
	}
Packit 15a5a8
Packit 15a5a8
      n -= sizeof longword;
Packit 15a5a8
    }
Packit 15a5a8
Packit 15a5a8
  char_ptr = (const unsigned char *) longword_ptr;
Packit 15a5a8
Packit 15a5a8
  while (n-- > 0)
Packit 15a5a8
    {
Packit 15a5a8
      if (*char_ptr == c)
Packit 15a5a8
	return (void *) char_ptr;
Packit 15a5a8
      else
Packit 15a5a8
	++char_ptr;
Packit 15a5a8
    }
Packit 15a5a8
Packit 15a5a8
  return 0;
Packit 15a5a8
}
Packit 15a5a8
#ifdef weak_alias
Packit 15a5a8
weak_alias (__memchr, BP_SYM (memchr))
Packit 15a5a8
#endif