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 |