| Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/coreutils/src/gnulib/lib/memchr2.c |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | /* Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2004, 2006, 2008-2018 | - | ||||||||||||
| 2 | Free Software Foundation, Inc. | - | ||||||||||||
| 3 | - | |||||||||||||
| 4 | Based on strlen implementation by Torbjorn Granlund (tege@sics.se), | - | ||||||||||||
| 5 | with help from Dan Sahlin (dan@sics.se) and | - | ||||||||||||
| 6 | commentary by Jim Blandy (jimb@ai.mit.edu); | - | ||||||||||||
| 7 | adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), | - | ||||||||||||
| 8 | and implemented in glibc by Roland McGrath (roland@ai.mit.edu). | - | ||||||||||||
| 9 | Extension to memchr2 implemented by Eric Blake (ebb9@byu.net). | - | ||||||||||||
| 10 | - | |||||||||||||
| 11 | This program is free software: you can redistribute it and/or modify it | - | ||||||||||||
| 12 | under the terms of the GNU General Public License as published by the | - | ||||||||||||
| 13 | Free Software Foundation; either version 3 of the License, or any | - | ||||||||||||
| 14 | later version. | - | ||||||||||||
| 15 | - | |||||||||||||
| 16 | This program is distributed in the hope that it will be useful, | - | ||||||||||||
| 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | - | ||||||||||||
| 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | - | ||||||||||||
| 19 | GNU General Public License for more details. | - | ||||||||||||
| 20 | - | |||||||||||||
| 21 | You should have received a copy of the GNU General Public License | - | ||||||||||||
| 22 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ | - | ||||||||||||
| 23 | - | |||||||||||||
| 24 | #include <config.h> | - | ||||||||||||
| 25 | - | |||||||||||||
| 26 | #include "memchr2.h" | - | ||||||||||||
| 27 | - | |||||||||||||
| 28 | #include <limits.h> | - | ||||||||||||
| 29 | #include <stdint.h> | - | ||||||||||||
| 30 | #include <string.h> | - | ||||||||||||
| 31 | - | |||||||||||||
| 32 | /* Return the first address of either C1 or C2 (treated as unsigned | - | ||||||||||||
| 33 | char) that occurs within N bytes of the memory region S. If | - | ||||||||||||
| 34 | neither byte appears, return NULL. */ | - | ||||||||||||
| 35 | void * | - | ||||||||||||
| 36 | memchr2 (void const *s, int c1_in, int c2_in, size_t n) | - | ||||||||||||
| 37 | { | - | ||||||||||||
| 38 | /* On 32-bit hardware, choosing longword to be a 32-bit unsigned | - | ||||||||||||
| 39 | long instead of a 64-bit uintmax_t tends to give better | - | ||||||||||||
| 40 | performance. On 64-bit hardware, unsigned long is generally 64 | - | ||||||||||||
| 41 | bits already. Change this typedef to experiment with | - | ||||||||||||
| 42 | performance. */ | - | ||||||||||||
| 43 | typedef unsigned long int longword; | - | ||||||||||||
| 44 | - | |||||||||||||
| 45 | const unsigned char *char_ptr; | - | ||||||||||||
| 46 | void const *void_ptr; | - | ||||||||||||
| 47 | const longword *longword_ptr; | - | ||||||||||||
| 48 | longword repeated_one; | - | ||||||||||||
| 49 | longword repeated_c1; | - | ||||||||||||
| 50 | longword repeated_c2; | - | ||||||||||||
| 51 | unsigned char c1; | - | ||||||||||||
| 52 | unsigned char c2; | - | ||||||||||||
| 53 | - | |||||||||||||
| 54 | c1 = (unsigned char) c1_in; | - | ||||||||||||
| 55 | c2 = (unsigned char) c2_in; | - | ||||||||||||
| 56 | - | |||||||||||||
| 57 | if (c1 == c2)
| 15-95 | ||||||||||||
| 58 | return memchr (s, c1, n); executed 15 times by 1 test: return memchr (s, c1, n);Executed by:
| 15 | ||||||||||||
| 59 | - | |||||||||||||
| 60 | /* Handle the first few bytes by reading one byte at a time. | - | ||||||||||||
| 61 | Do this until VOID_PTR is aligned on a longword boundary. */ | - | ||||||||||||
| 62 | for (void_ptr = s; | - | ||||||||||||
| 63 | n > 0 && (uintptr_t) void_ptr % sizeof (longword) != 0;
| 3-119 | ||||||||||||
| 64 | --n) | - | ||||||||||||
| 65 | { | - | ||||||||||||
| 66 | char_ptr = void_ptr; | - | ||||||||||||
| 67 | if (*char_ptr == c1 || *char_ptr == c2)
| 0-27 | ||||||||||||
| 68 | return (void *) void_ptr; executed 24 times by 1 test: return (void *) void_ptr;Executed by:
| 24 | ||||||||||||
| 69 | void_ptr = char_ptr + 1; | - | ||||||||||||
| 70 | } executed 27 times by 1 test: end of blockExecuted by:
| 27 | ||||||||||||
| 71 | - | |||||||||||||
| 72 | longword_ptr = void_ptr; | - | ||||||||||||
| 73 | - | |||||||||||||
| 74 | /* All these elucidatory comments refer to 4-byte longwords, | - | ||||||||||||
| 75 | but the theory applies equally well to any size longwords. */ | - | ||||||||||||
| 76 | - | |||||||||||||
| 77 | /* Compute auxiliary longword values: | - | ||||||||||||
| 78 | repeated_one is a value which has a 1 in every byte. | - | ||||||||||||
| 79 | repeated_c1 has c1 in every byte. | - | ||||||||||||
| 80 | repeated_c2 has c2 in every byte. */ | - | ||||||||||||
| 81 | repeated_one = 0x01010101; | - | ||||||||||||
| 82 | repeated_c1 = c1 | (c1 << 8); | - | ||||||||||||
| 83 | repeated_c2 = c2 | (c2 << 8); | - | ||||||||||||
| 84 | repeated_c1 |= repeated_c1 << 16; | - | ||||||||||||
| 85 | repeated_c2 |= repeated_c2 << 16; | - | ||||||||||||
| 86 | if (0xffffffffU < (longword) -1)
| 0-71 | ||||||||||||
| 87 | { | - | ||||||||||||
| 88 | repeated_one |= repeated_one << 31 << 1; | - | ||||||||||||
| 89 | repeated_c1 |= repeated_c1 << 31 << 1; | - | ||||||||||||
| 90 | repeated_c2 |= repeated_c2 << 31 << 1; | - | ||||||||||||
| 91 | if (8 < sizeof (longword))
| 0-71 | ||||||||||||
| 92 | { | - | ||||||||||||
| 93 | size_t i; | - | ||||||||||||
| 94 | - | |||||||||||||
| 95 | for (i = 64; i < sizeof (longword) * 8; i *= 2)
| 0 | ||||||||||||
| 96 | { | - | ||||||||||||
| 97 | repeated_one |= repeated_one << i; | - | ||||||||||||
| 98 | repeated_c1 |= repeated_c1 << i; | - | ||||||||||||
| 99 | repeated_c2 |= repeated_c2 << i; | - | ||||||||||||
| 100 | } never executed: end of block | 0 | ||||||||||||
| 101 | } never executed: end of block | 0 | ||||||||||||
| 102 | } executed 71 times by 1 test: end of blockExecuted by:
| 71 | ||||||||||||
| 103 | - | |||||||||||||
| 104 | /* Instead of the traditional loop which tests each byte, we will test a | - | ||||||||||||
| 105 | longword at a time. The tricky part is testing if *any of the four* | - | ||||||||||||
| 106 | bytes in the longword in question are equal to c1 or c2. We first use | - | ||||||||||||
| 107 | an xor with repeated_c1 and repeated_c2, respectively. This reduces | - | ||||||||||||
| 108 | the task to testing whether *any of the four* bytes in longword1 or | - | ||||||||||||
| 109 | longword2 is zero. | - | ||||||||||||
| 110 | - | |||||||||||||
| 111 | Let's consider longword1. We compute tmp1 = | - | ||||||||||||
| 112 | ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7). | - | ||||||||||||
| 113 | That is, we perform the following operations: | - | ||||||||||||
| 114 | 1. Subtract repeated_one. | - | ||||||||||||
| 115 | 2. & ~longword1. | - | ||||||||||||
| 116 | 3. & a mask consisting of 0x80 in every byte. | - | ||||||||||||
| 117 | Consider what happens in each byte: | - | ||||||||||||
| 118 | - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff, | - | ||||||||||||
| 119 | and step 3 transforms it into 0x80. A carry can also be propagated | - | ||||||||||||
| 120 | to more significant bytes. | - | ||||||||||||
| 121 | - If a byte of longword1 is nonzero, let its lowest 1 bit be at | - | ||||||||||||
| 122 | position k (0 <= k <= 7); so the lowest k bits are 0. After step 1, | - | ||||||||||||
| 123 | the byte ends in a single bit of value 0 and k bits of value 1. | - | ||||||||||||
| 124 | After step 2, the result is just k bits of value 1: 2^k - 1. After | - | ||||||||||||
| 125 | step 3, the result is 0. And no carry is produced. | - | ||||||||||||
| 126 | So, if longword1 has only non-zero bytes, tmp1 is zero. | - | ||||||||||||
| 127 | Whereas if longword1 has a zero byte, call j the position of the least | - | ||||||||||||
| 128 | significant zero byte. Then the result has a zero at positions 0, ..., | - | ||||||||||||
| 129 | j-1 and a 0x80 at position j. We cannot predict the result at the more | - | ||||||||||||
| 130 | significant bytes (positions j+1..3), but it does not matter since we | - | ||||||||||||
| 131 | already have a non-zero bit at position 8*j+7. | - | ||||||||||||
| 132 | - | |||||||||||||
| 133 | Similarly, we compute tmp2 = | - | ||||||||||||
| 134 | ((longword2 - repeated_one) & ~longword2) & (repeated_one << 7). | - | ||||||||||||
| 135 | - | |||||||||||||
| 136 | The test whether any byte in longword1 or longword2 is zero is equivalent | - | ||||||||||||
| 137 | to testing whether tmp1 is nonzero or tmp2 is nonzero. We can combine | - | ||||||||||||
| 138 | this into a single test, whether (tmp1 | tmp2) is nonzero. */ | - | ||||||||||||
| 139 | - | |||||||||||||
| 140 | while (n >= sizeof (longword))
| 9-62 | ||||||||||||
| 141 | { | - | ||||||||||||
| 142 | longword longword1 = *longword_ptr ^ repeated_c1; | - | ||||||||||||
| 143 | longword longword2 = *longword_ptr ^ repeated_c2; | - | ||||||||||||
| 144 | - | |||||||||||||
| 145 | if (((((longword1 - repeated_one) & ~longword1)
| 0-9 | ||||||||||||
| 146 | | ((longword2 - repeated_one) & ~longword2))
| 0-9 | ||||||||||||
| 147 | & (repeated_one << 7)) != 0)
| 0-9 | ||||||||||||
| 148 | break; executed 9 times by 1 test: break;Executed by:
| 9 | ||||||||||||
| 149 | longword_ptr++; | - | ||||||||||||
| 150 | n -= sizeof (longword); | - | ||||||||||||
| 151 | } never executed: end of block | 0 | ||||||||||||
| 152 | - | |||||||||||||
| 153 | char_ptr = (const unsigned char *) longword_ptr; | - | ||||||||||||
| 154 | - | |||||||||||||
| 155 | /* At this point, we know that either n < sizeof (longword), or one of the | - | ||||||||||||
| 156 | sizeof (longword) bytes starting at char_ptr is == c1 or == c2. On | - | ||||||||||||
| 157 | little-endian machines, we could determine the first such byte without | - | ||||||||||||
| 158 | any further memory accesses, just by looking at the (tmp1 | tmp2) result | - | ||||||||||||
| 159 | from the last loop iteration. But this does not work on big-endian | - | ||||||||||||
| 160 | machines. Choose code that works in both cases. */ | - | ||||||||||||
| 161 | - | |||||||||||||
| 162 | for (; n > 0; --n, ++char_ptr)
| 5-122 | ||||||||||||
| 163 | { | - | ||||||||||||
| 164 | if (*char_ptr == c1 || *char_ptr == c2)
| 3-63 | ||||||||||||
| 165 | return (void *) char_ptr; executed 66 times by 1 test: return (void *) char_ptr;Executed by:
| 66 | ||||||||||||
| 166 | } executed 56 times by 1 test: end of blockExecuted by:
| 56 | ||||||||||||
| 167 | - | |||||||||||||
| 168 | return NULL; executed 5 times by 1 test: return ((void *)0) ;Executed by:
| 5 | ||||||||||||
| 169 | } | - | ||||||||||||
| Source code | Switch to Preprocessed file |