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) - 0x01010101) & ~(X) & 0x80808080) 85 #else 86 #if LONG_MAX == 9223372036854775807L 87 /* Nonzero if X (a long int) contains a NULL byte. */ 88 #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) 89 #else 90 #error long int is not a 32bit or 64bit type. 91 #endif 92 #endif 93 94 #ifndef DETECTNULL 95 #error long int is not a 32bit or 64bit byte 96 #endif 97 98 /* DETECTCHAR returns nonzero if (long)X contains the byte used 99 to fill (long)MASK. */ 100 #define DETECTCHAR(X, MASK) (DETECTNULL(X ^ MASK)) 101 102 _PTR 103 _DEFUN(memchr, (src_void, c, length), _CONST _PTR src_void _AND int c 104 _AND size_t length) 105 { 106 _CONST unsigned char *src = (_CONST unsigned char *)src_void; 107 unsigned char d = c; 108 109 #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) 110 unsigned long *asrc; 111 unsigned long mask; 112 int i; 113 114 while (UNALIGNED(src)) { 115 if (!length--) 116 return NULL; 117 if (*src == d) 118 return (void *)src; 119 src++; 120 } 121 122 if (!TOO_SMALL(length)) { 123 /* If we get this far, we know that length is large and src is 124 word-aligned. */ 125 /* The fast code reads the source one word at a time and only 126 performs the bytewise search on word-sized segments if they 127 contain the search character, which is detected by XORing 128 the word-sized segment with a word-sized block of the search 129 character and then detecting for the presence of NUL in the 130 result. */ 131 asrc = (unsigned long *)src; 132 mask = d << 8 | d; 133 mask = mask << 16 | mask; 134 for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) 135 mask = (mask << i) | mask; 136 137 while (length >= LBLOCKSIZE) { 138 if (DETECTCHAR(*asrc, mask)) 139 break; 140 length -= LBLOCKSIZE; 141 asrc++; 142 } 143 144 /* If there are fewer than LBLOCKSIZE characters left, 145 then we resort to the bytewise loop. */ 146 147 src = (unsigned char *)asrc; 148 } 149 #endif /* not PREFER_SIZE_OVER_SPEED */ 150 151 while (length--) { 152 if (*src == d) 153 return (void *)src; 154 src++; 155 } 156 157 return NULL; 158 } 159