X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fmemchr2.c;h=8b105b7f2783d6c83a076ce542dc560d80d47f0a;hb=c50edd6462eaaae00f8549f9bad99d4e68b94376;hp=1eb8f9bd7a4b21ae96bee3825683c57e12dc5c43;hpb=1f90f54e377196656bb9adc0655f0a830eac7d8a;p=gnulib.git diff --git a/lib/memchr2.c b/lib/memchr2.c index 1eb8f9bd7..8b105b7f2 100644 --- a/lib/memchr2.c +++ b/lib/memchr2.c @@ -1,5 +1,5 @@ -/* Copyright (C) 1991, 1993, 1996, 1997, 1999, 2000, 2003, 2004, 2006, - 2008 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2004, 2006, 2008-2013 + Free Software Foundation, Inc. Based on strlen implementation by Torbjorn Granlund (tege@sics.se), with help from Dan Sahlin (dan@sics.se) and @@ -29,8 +29,6 @@ along with this program. If not, see . */ #include #include -#include "intprops.h" - /* Return the first address of either C1 or C2 (treated as unsigned char) that occurs within N bytes of the memory region S. If neither byte appears, return NULL. */ @@ -42,9 +40,10 @@ memchr2 (void const *s, int c1_in, int c2_in, size_t n) performance. On 64-bit hardware, unsigned long is generally 64 bits already. Change this typedef to experiment with performance. */ - typedef unsigned long longword; + typedef unsigned long int longword; const unsigned char *char_ptr; + void const *void_ptr; const longword *longword_ptr; longword repeated_one; longword repeated_c1; @@ -59,14 +58,18 @@ memchr2 (void const *s, int c1_in, int c2_in, size_t n) return memchr (s, c1, n); /* Handle the first few bytes by reading one byte at a time. - Do this until CHAR_PTR is aligned on a longword boundary. */ - for (char_ptr = (const unsigned char *) s; - n > 0 && (size_t) char_ptr % sizeof (longword) != 0; - --n, ++char_ptr) - if (*char_ptr == c1 || *char_ptr == c2) - return (void *) char_ptr; + Do this until VOID_PTR is aligned on a longword boundary. */ + for (void_ptr = s; + n > 0 && (uintptr_t) void_ptr % sizeof (longword) != 0; + --n) + { + char_ptr = void_ptr; + if (*char_ptr == c1 || *char_ptr == c2) + return (void *) void_ptr; + void_ptr = char_ptr + 1; + } - longword_ptr = (const longword *) char_ptr; + longword_ptr = void_ptr; /* All these elucidatory comments refer to 4-byte longwords, but the theory applies equally well to any size longwords. */ @@ -80,22 +83,22 @@ memchr2 (void const *s, int c1_in, int c2_in, size_t n) repeated_c2 = c2 | (c2 << 8); repeated_c1 |= repeated_c1 << 16; repeated_c2 |= repeated_c2 << 16; - if (0xffffffffU < TYPE_MAXIMUM (longword)) + if (0xffffffffU < (longword) -1) { repeated_one |= repeated_one << 31 << 1; repeated_c1 |= repeated_c1 << 31 << 1; repeated_c2 |= repeated_c2 << 31 << 1; if (8 < sizeof (longword)) - { - int i; - - for (i = 64; i < sizeof (longword) * 8; i *= 2) - { - repeated_one |= repeated_one << i; - repeated_c1 |= repeated_c1 << i; - repeated_c2 |= repeated_c2 << i; - } - } + { + size_t i; + + for (i = 64; i < sizeof (longword) * 8; i *= 2) + { + repeated_one |= repeated_one << i; + repeated_c1 |= repeated_c1 << i; + repeated_c2 |= repeated_c2 << i; + } + } } /* Instead of the traditional loop which tests each byte, we will test a @@ -127,7 +130,7 @@ memchr2 (void const *s, int c1_in, int c2_in, size_t n) significant bytes (positions j+1..3), but it does not matter since we already have a non-zero bit at position 8*j+7. - Similary, we compute tmp2 = + Similarly, we compute tmp2 = ((longword2 - repeated_one) & ~longword2) & (repeated_one << 7). The test whether any byte in longword1 or longword2 is zero is equivalent @@ -140,9 +143,9 @@ memchr2 (void const *s, int c1_in, int c2_in, size_t n) longword longword2 = *longword_ptr ^ repeated_c2; if (((((longword1 - repeated_one) & ~longword1) - | ((longword2 - repeated_one) & ~longword2)) - & (repeated_one << 7)) != 0) - break; + | ((longword2 - repeated_one) & ~longword2)) + & (repeated_one << 7)) != 0) + break; longword_ptr++; n -= sizeof (longword); } @@ -159,7 +162,7 @@ memchr2 (void const *s, int c1_in, int c2_in, size_t n) for (; n > 0; --n, ++char_ptr) { if (*char_ptr == c1 || *char_ptr == c2) - return (void *) char_ptr; + return (void *) char_ptr; } return NULL;