1 /* 2 * Copyright (c) 1994-2009 Red Hat, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its 16 * contributors may be used to endorse or promote products derived from this 17 * software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 FUNCTION 34 <<memchr>>---find character in memory 35 36 INDEX 37 memchr 38 39 ANSI_SYNOPSIS 40 #include <string.h> 41 void *memchr(const void *<[src]>, int <[c]>, size_t <[length]>); 42 43 TRAD_SYNOPSIS 44 #include <string.h> 45 void *memchr(<[src]>, <[c]>, <[length]>) 46 void *<[src]>; 47 void *<[c]>; 48 size_t <[length]>; 49 50 DESCRIPTION 51 This function searches memory starting at <<*<[src]>>> for the 52 character <[c]>. The search only ends with the first 53 occurrence of <[c]>, or after <[length]> characters; in 54 particular, <<NUL>> does not terminate the search. 55 56 RETURNS 57 If the character <[c]> is found within <[length]> characters 58 of <<*<[src]>>>, a pointer to the character is returned. If 59 <[c]> is not found, then <<NULL>> is returned. 60 61 PORTABILITY 62 <<memchr>> is ANSI C. 63 64 <<memchr>> requires no supporting OS subroutines. 65 66 QUICKREF 67 memchr ansi pure 68 */ 69 70 #include "_ansi.h" 71 #include <string.h> 72 #include <limits.h> 73 74 /* Nonzero if either X or Y is not aligned on a "long" boundary. */ 75 #define UNALIGNED(X) ((long)X & (sizeof(long) - 1)) 76 77 /* How many bytes are loaded each iteration of the word copy loop. */ 78 #define LBLOCKSIZE (sizeof(long)) 79 80 /* Threshhold for punting to the bytewise iterator. */ 81 #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) 82 83 #if LONG_MAX == 2147483647L 84 #define DETECTNULL(X) (((X) - 0x01010101L) & ~(X) & 0x80808080UL) 85 #else 86 #if LONG_MAX == 9223372036854775807L 87 /* Nonzero if X (a long int) contains a NULL byte. */ 88 #define DETECTNULL(X) (((X) - 0x0101010101010101L) & ~(X) & \ 89 0x8080808080808080UL) 90 #else 91 #error long int is not a 32bit or 64bit type. 92 #endif 93 #endif 94 95 #ifndef DETECTNULL 96 #error long int is not a 32bit or 64bit byte 97 #endif 98 99 /* DETECTCHAR returns nonzero if (long)X contains the byte used 100 to fill (long)MASK. */ 101 #define DETECTCHAR(X, MASK) (DETECTNULL(X ^ MASK)) 102 103 _PTR 104 _DEFUN(memchr, (src_void, c, length), _CONST _PTR src_void _AND int c 105 _AND size_t length) 106 { 107 _CONST unsigned char *src = (_CONST unsigned char *)src_void; 108 unsigned char d = c; 109 110 #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) 111 unsigned long *asrc; 112 unsigned long mask; 113 int i; 114 115 while (UNALIGNED(src)) { 116 if (!length--) 117 return NULL; 118 if (*src == d) 119 return (void *)src; 120 src++; 121 } 122 123 if (!TOO_SMALL(length)) { 124 /* If we get this far, we know that length is large and src is 125 word-aligned. */ 126 /* The fast code reads the source one word at a time and only 127 performs the bytewise search on word-sized segments if they 128 contain the search character, which is detected by XORing 129 the word-sized segment with a word-sized block of the search 130 character and then detecting for the presence of NUL in the 131 result. */ 132 asrc = (unsigned long *)src; 133 mask = d << 8 | d; 134 mask = mask << 16 | mask; 135 for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) 136 mask = (mask << i) | mask; 137 138 while (length >= LBLOCKSIZE) { 139 if (DETECTCHAR(*asrc, mask)) 140 break; 141 length -= LBLOCKSIZE; 142 asrc++; 143 } 144 145 /* If there are fewer than LBLOCKSIZE characters left, 146 then we resort to the bytewise loop. */ 147 148 src = (unsigned char *)asrc; 149 } 150 #endif /* not PREFER_SIZE_OVER_SPEED */ 151 152 while (length--) { 153 if (*src == d) 154 return (void *)src; 155 src++; 156 } 157 158 return NULL; 159 } 160