174 n.ptr = NULL; |
174 n.ptr = NULL; |
175 n.length = 0; |
175 n.length = 0; |
176 return n; |
176 return n; |
177 } |
177 } |
178 |
178 |
179 typedef size_t(*prefix_table_rfun)(void*,size_t); |
179 #define ptable_r(dest, useheap, ptable, index) (dest = useheap ? \ |
180 typedef void(*prefix_table_wfun)(void*,size_t,size_t); |
180 ((size_t*)ptable)[index] : (size_t) ((uint8_t*)ptable)[index]) |
181 |
181 |
182 static size_t s_prefix_table_r(void* table, size_t index) { |
182 #define ptable_w(useheap, ptable, index, src) do {\ |
183 return (size_t) ((uint8_t*)table)[index]; |
183 if (!useheap) ((uint8_t*)ptable)[index] = (uint8_t) src;\ |
184 } |
184 else ((size_t*)ptable)[index] = src;\ |
185 static void s_prefix_table_w(void* table, size_t index, size_t value) { |
185 } while (0); |
186 ((uint8_t*)table)[index] = (uint8_t) value; |
|
187 } |
|
188 static size_t h_prefix_table_r(void* table, size_t index) { |
|
189 return ((size_t*)table)[index]; |
|
190 } |
|
191 static void h_prefix_table_w(void* table, size_t index, size_t value) { |
|
192 ((size_t*)table)[index] = value; |
|
193 } |
|
194 |
186 |
195 sstr_t sstrstr(sstr_t string, sstr_t match) { |
187 sstr_t sstrstr(sstr_t string, sstr_t match) { |
196 if (match.length == 0) { |
188 if (match.length == 0) { |
197 return string; |
189 return string; |
198 } |
190 } |
210 |
202 |
211 /* static prefix table */ |
203 /* static prefix table */ |
212 static uint8_t s_prefix_table[256]; |
204 static uint8_t s_prefix_table[256]; |
213 |
205 |
214 /* check pattern length and use appropriate prefix table */ |
206 /* check pattern length and use appropriate prefix table */ |
215 register void* ptable; |
207 /* if the pattern exceeds static prefix table, allocate on the heap */ |
216 prefix_table_rfun ptable_r; |
208 register int useheap = match.length > 255; |
217 prefix_table_wfun ptable_w; |
209 register void* ptable = useheap ? |
218 if (match.length > 255) { |
210 calloc(match.length+1, sizeof(size_t)): s_prefix_table; |
219 /* pattern exceeds static prefix table, allocate on the heap */ |
|
220 ptable = calloc(match.length+1, sizeof(size_t)); |
|
221 ptable_r = h_prefix_table_r; |
|
222 ptable_w = h_prefix_table_w; |
|
223 } else { |
|
224 ptable = s_prefix_table; |
|
225 ptable_r = s_prefix_table_r; |
|
226 ptable_w = s_prefix_table_w; |
|
227 } |
|
228 |
211 |
229 /* keep counter in registers */ |
212 /* keep counter in registers */ |
230 register size_t i, j; |
213 register size_t i, j; |
231 |
214 |
232 /* fill prefix table */ |
215 /* fill prefix table */ |
233 i = 0; j = 0; |
216 i = 0; j = 0; |
234 ptable_w(ptable, i, j); |
217 ptable_w(useheap, ptable, i, j); |
235 while (i < match.length) { |
218 while (i < match.length) { |
236 while (j >= 1 && match.ptr[j-1] != match.ptr[i]) { |
219 while (j >= 1 && match.ptr[j-1] != match.ptr[i]) { |
237 j = ptable_r(ptable, j-i); |
220 ptable_r(j, useheap, ptable, j-i); |
238 } |
221 } |
239 i++; j++; |
222 i++; j++; |
240 ptable_w(ptable, i, j); |
223 ptable_w(useheap, ptable, i, j); |
241 } |
224 } |
242 |
225 |
243 /* search */ |
226 /* search */ |
244 i = 0; j = 1; |
227 i = 0; j = 1; |
245 while (i < string.length) { |
228 while (i < string.length) { |
246 while (j >= 1 && string.ptr[i] != match.ptr[j-1]) { |
229 while (j >= 1 && string.ptr[i] != match.ptr[j-1]) { |
247 j = ptable_r(ptable, j-1); |
230 ptable_r(j, useheap, ptable, j-1); |
248 } |
231 } |
249 i++; j++; |
232 i++; j++; |
250 if (j-1 == match.length) { |
233 if (j-1 == match.length) { |
251 size_t start = i - match.length; |
234 size_t start = i - match.length; |
252 result.ptr = string.ptr + start; |
235 result.ptr = string.ptr + start; |