| OLD | NEW |
| 1 #define _GNU_SOURCE | 1 #define _GNU_SOURCE |
| 2 #include <string.h> | 2 #include <string.h> |
| 3 #include <stdint.h> | 3 #include <stdint.h> |
| 4 | 4 |
| 5 static char *twobyte_memmem(const unsigned char *h, size_t k, const unsigned cha
r *n) | 5 static char* twobyte_memmem(const unsigned char* h, |
| 6 { | 6 size_t k, |
| 7 » uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1]; | 7 const unsigned char* n) { |
| 8 » for (h++, k--; k; k--, hw = hw<<8 | *++h) | 8 uint16_t nw = n[0] << 8 | n[1], hw = h[0] << 8 | h[1]; |
| 9 » » if (hw == nw) return (char *)h-1; | 9 for (h++, k--; k; k--, hw = hw << 8 | *++h) |
| 10 » return 0; | 10 if (hw == nw) |
| 11 return (char*)h - 1; |
| 12 return 0; |
| 11 } | 13 } |
| 12 | 14 |
| 13 static char *threebyte_memmem(const unsigned char *h, size_t k, const unsigned c
har *n) | 15 static char* threebyte_memmem(const unsigned char* h, |
| 14 { | 16 size_t k, |
| 15 » uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8; | 17 const unsigned char* n) { |
| 16 » uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8; | 18 uint32_t nw = n[0] << 24 | n[1] << 16 | n[2] << 8; |
| 17 » for (h+=2, k-=2; k; k--, hw = (hw|*++h)<<8) | 19 uint32_t hw = h[0] << 24 | h[1] << 16 | h[2] << 8; |
| 18 » » if (hw == nw) return (char *)h-2; | 20 for (h += 2, k -= 2; k; k--, hw = (hw | *++h) << 8) |
| 19 » return 0; | 21 if (hw == nw) |
| 22 return (char*)h - 2; |
| 23 return 0; |
| 20 } | 24 } |
| 21 | 25 |
| 22 static char *fourbyte_memmem(const unsigned char *h, size_t k, const unsigned ch
ar *n) | 26 static char* fourbyte_memmem(const unsigned char* h, |
| 23 { | 27 size_t k, |
| 24 » uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3]; | 28 const unsigned char* n) { |
| 25 » uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3]; | 29 uint32_t nw = n[0] << 24 | n[1] << 16 | n[2] << 8 | n[3]; |
| 26 » for (h+=3, k-=3; k; k--, hw = hw<<8 | *++h) | 30 uint32_t hw = h[0] << 24 | h[1] << 16 | h[2] << 8 | h[3]; |
| 27 » » if (hw == nw) return (char *)h-3; | 31 for (h += 3, k -= 3; k; k--, hw = hw << 8 | *++h) |
| 28 » return 0; | 32 if (hw == nw) |
| 33 return (char*)h - 3; |
| 34 return 0; |
| 29 } | 35 } |
| 30 | 36 |
| 31 #define MAX(a,b) ((a)>(b)?(a):(b)) | 37 #define MAX(a, b) ((a) > (b) ? (a) : (b)) |
| 32 #define MIN(a,b) ((a)<(b)?(a):(b)) | 38 #define MIN(a, b) ((a) < (b) ? (a) : (b)) |
| 33 | 39 |
| 34 #define BITOP(a,b,op) \ | 40 #define BITOP(a, b, op) \ |
| 35 ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a)))) | 41 ((a)[(size_t)(b) / (8 * sizeof *(a))] op(size_t) 1 \ |
| 42 << ((size_t)(b) % (8 * sizeof *(a)))) |
| 36 | 43 |
| 37 static char *twoway_memmem(const unsigned char *h, const unsigned char *z, const
unsigned char *n, size_t l) | 44 static char* twoway_memmem(const unsigned char* h, |
| 38 { | 45 const unsigned char* z, |
| 39 » size_t i, ip, jp, k, p, ms, p0, mem, mem0; | 46 const unsigned char* n, |
| 40 » size_t byteset[32 / sizeof(size_t)] = { 0 }; | 47 size_t l) { |
| 41 » size_t shift[256]; | 48 size_t i, ip, jp, k, p, ms, p0, mem, mem0; |
| 49 size_t byteset[32 / sizeof(size_t)] = {0}; |
| 50 size_t shift[256]; |
| 42 | 51 |
| 43 » /* Computing length of needle and fill shift table */ | 52 /* Computing length of needle and fill shift table */ |
| 44 » for (i=0; i<l; i++) | 53 for (i = 0; i < l; i++) |
| 45 » » BITOP(byteset, n[i], |=), shift[n[i]] = i+1; | 54 BITOP(byteset, n[i], |=), shift[n[i]] = i + 1; |
| 46 | 55 |
| 47 » /* Compute maximal suffix */ | 56 /* Compute maximal suffix */ |
| 48 » ip = -1; jp = 0; k = p = 1; | 57 ip = -1; |
| 49 » while (jp+k<l) { | 58 jp = 0; |
| 50 » » if (n[ip+k] == n[jp+k]) { | 59 k = p = 1; |
| 51 » » » if (k == p) { | 60 while (jp + k < l) { |
| 52 » » » » jp += p; | 61 if (n[ip + k] == n[jp + k]) { |
| 53 » » » » k = 1; | 62 if (k == p) { |
| 54 » » » } else k++; | 63 jp += p; |
| 55 » » } else if (n[ip+k] > n[jp+k]) { | 64 k = 1; |
| 56 » » » jp += k; | 65 } else |
| 57 » » » k = 1; | 66 k++; |
| 58 » » » p = jp - ip; | 67 } else if (n[ip + k] > n[jp + k]) { |
| 59 » » } else { | 68 jp += k; |
| 60 » » » ip = jp++; | 69 k = 1; |
| 61 » » » k = p = 1; | 70 p = jp - ip; |
| 62 » » } | 71 } else { |
| 63 » } | 72 ip = jp++; |
| 64 » ms = ip; | 73 k = p = 1; |
| 65 » p0 = p; | 74 } |
| 75 } |
| 76 ms = ip; |
| 77 p0 = p; |
| 66 | 78 |
| 67 » /* And with the opposite comparison */ | 79 /* And with the opposite comparison */ |
| 68 » ip = -1; jp = 0; k = p = 1; | 80 ip = -1; |
| 69 » while (jp+k<l) { | 81 jp = 0; |
| 70 » » if (n[ip+k] == n[jp+k]) { | 82 k = p = 1; |
| 71 » » » if (k == p) { | 83 while (jp + k < l) { |
| 72 » » » » jp += p; | 84 if (n[ip + k] == n[jp + k]) { |
| 73 » » » » k = 1; | 85 if (k == p) { |
| 74 » » » } else k++; | 86 jp += p; |
| 75 » » } else if (n[ip+k] < n[jp+k]) { | 87 k = 1; |
| 76 » » » jp += k; | 88 } else |
| 77 » » » k = 1; | 89 k++; |
| 78 » » » p = jp - ip; | 90 } else if (n[ip + k] < n[jp + k]) { |
| 79 » » } else { | 91 jp += k; |
| 80 » » » ip = jp++; | 92 k = 1; |
| 81 » » » k = p = 1; | 93 p = jp - ip; |
| 82 » » } | 94 } else { |
| 83 » } | 95 ip = jp++; |
| 84 » if (ip+1 > ms+1) ms = ip; | 96 k = p = 1; |
| 85 » else p = p0; | 97 } |
| 98 } |
| 99 if (ip + 1 > ms + 1) |
| 100 ms = ip; |
| 101 else |
| 102 p = p0; |
| 86 | 103 |
| 87 » /* Periodic needle? */ | 104 /* Periodic needle? */ |
| 88 » if (memcmp(n, n+p, ms+1)) { | 105 if (memcmp(n, n + p, ms + 1)) { |
| 89 » » mem0 = 0; | 106 mem0 = 0; |
| 90 » » p = MAX(ms, l-ms-1) + 1; | 107 p = MAX(ms, l - ms - 1) + 1; |
| 91 » } else mem0 = l-p; | 108 } else |
| 92 » mem = 0; | 109 mem0 = l - p; |
| 110 mem = 0; |
| 93 | 111 |
| 94 » /* Search loop */ | 112 /* Search loop */ |
| 95 » for (;;) { | 113 for (;;) { |
| 96 » » /* If remainder of haystack is shorter than needle, done */ | 114 /* If remainder of haystack is shorter than needle, done */ |
| 97 » » if (z-h < l) return 0; | 115 if (z - h < l) |
| 116 return 0; |
| 98 | 117 |
| 99 » » /* Check last byte first; advance by shift on mismatch */ | 118 /* Check last byte first; advance by shift on mismatch */ |
| 100 » » if (BITOP(byteset, h[l-1], &)) { | 119 if (BITOP(byteset, h[l - 1], &)) { |
| 101 » » » k = l-shift[h[l-1]]; | 120 k = l - shift[h[l - 1]]; |
| 102 » » » if (k) { | 121 if (k) { |
| 103 » » » » if (mem0 && mem && k < p) k = l-p; | 122 if (mem0 && mem && k < p) |
| 104 » » » » h += k; | 123 k = l - p; |
| 105 » » » » mem = 0; | 124 h += k; |
| 106 » » » » continue; | 125 mem = 0; |
| 107 » » » } | 126 continue; |
| 108 » » } else { | 127 } |
| 109 » » » h += l; | 128 } else { |
| 110 » » » mem = 0; | 129 h += l; |
| 111 » » » continue; | 130 mem = 0; |
| 112 » » } | 131 continue; |
| 132 } |
| 113 | 133 |
| 114 » » /* Compare right half */ | 134 /* Compare right half */ |
| 115 » » for (k=MAX(ms+1,mem); k<l && n[k] == h[k]; k++); | 135 for (k = MAX(ms + 1, mem); k < l && n[k] == h[k]; k++) |
| 116 » » if (k < l) { | 136 ; |
| 117 » » » h += k-ms; | 137 if (k < l) { |
| 118 » » » mem = 0; | 138 h += k - ms; |
| 119 » » » continue; | 139 mem = 0; |
| 120 » » } | 140 continue; |
| 121 » » /* Compare left half */ | 141 } |
| 122 » » for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--); | 142 /* Compare left half */ |
| 123 » » if (k <= mem) return (char *)h; | 143 for (k = ms + 1; k > mem && n[k - 1] == h[k - 1]; k--) |
| 124 » » h += p; | 144 ; |
| 125 » » mem = mem0; | 145 if (k <= mem) |
| 126 » } | 146 return (char*)h; |
| 147 h += p; |
| 148 mem = mem0; |
| 149 } |
| 127 } | 150 } |
| 128 | 151 |
| 129 void *memmem(const void *h0, size_t k, const void *n0, size_t l) | 152 void* memmem(const void* h0, size_t k, const void* n0, size_t l) { |
| 130 { | 153 const unsigned char *h = h0, *n = n0; |
| 131 » const unsigned char *h = h0, *n = n0; | |
| 132 | 154 |
| 133 » /* Return immediately on empty needle */ | 155 /* Return immediately on empty needle */ |
| 134 » if (!l) return (void *)h; | 156 if (!l) |
| 157 return (void*)h; |
| 135 | 158 |
| 136 » /* Return immediately when needle is longer than haystack */ | 159 /* Return immediately when needle is longer than haystack */ |
| 137 » if (k<l) return 0; | 160 if (k < l) |
| 161 return 0; |
| 138 | 162 |
| 139 » /* Use faster algorithms for short needles */ | 163 /* Use faster algorithms for short needles */ |
| 140 » h = memchr(h0, *n, k); | 164 h = memchr(h0, *n, k); |
| 141 » if (!h || l==1) return (void *)h; | 165 if (!h || l == 1) |
| 142 » k -= h - (const unsigned char *)h0; | 166 return (void*)h; |
| 143 » if (l==2) return twobyte_memmem(h, k, n); | 167 k -= h - (const unsigned char*)h0; |
| 144 » if (l==3) return threebyte_memmem(h, k, n); | 168 if (l == 2) |
| 145 » if (l==4) return fourbyte_memmem(h, k, n); | 169 return twobyte_memmem(h, k, n); |
| 170 if (l == 3) |
| 171 return threebyte_memmem(h, k, n); |
| 172 if (l == 4) |
| 173 return fourbyte_memmem(h, k, n); |
| 146 | 174 |
| 147 » return twoway_memmem(h, h+k, n, l); | 175 return twoway_memmem(h, h + k, n, l); |
| 148 } | 176 } |
| OLD | NEW |