1 : /* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */
2 :
3 : #ifndef USTR_SRCH_H
4 : #error " Include ustr-srch.h before this file."
5 : #endif
6 :
7 : #ifndef USTR_CONF_HAVE_MEMRCHR /* GNU extension */
8 : #ifdef __GLIBC__
9 : #define USTR_CONF_HAVE_MEMRCHR 1
10 : #else
11 : #define USTR_CONF_HAVE_MEMRCHR 0
12 : #endif
13 : #endif
14 :
15 : USTR_CONF_I_PROTO
16 : size_t ustr_srch_chr_fwd(const struct Ustr *s1, size_t off, char val)
17 921 : {
18 710 : const char *beg = ustr_cstr(s1);
19 : const char *ptr;
20 710 : size_t len = ustr_len(s1);
21 : const char *tmp;
22 :
23 458 : USTR_ASSERT(ustr_assert_valid(s1));
24 :
25 921 : USTR_ASSERT_RET(off <= len, 0);
26 921 : ptr = beg + off;
27 921 : len -= off;
28 :
29 921 : if (!(tmp = memchr(ptr, val, len))) return (0);
30 :
31 703 : len = tmp - beg;
32 703 : return (len + 1);
33 : }
34 :
35 : #if USTR_CONF_HAVE_MEMRCHR /* GNU extension */
36 : USTR_CONF_I_PROTO size_t ustr_srch_chr_rev(const struct Ustr *s1, size_t off,
37 : char val)
38 248 : {
39 201 : const char *ptr = ustr_cstr(s1);
40 201 : size_t len = ustr_len(s1);
41 : const char *tmp;
42 :
43 123 : USTR_ASSERT(ustr_assert_valid(s1));
44 :
45 248 : USTR_ASSERT_RET(off <= len, 0);
46 248 : len -= off;
47 :
48 248 : if (!(tmp = memrchr(ptr, val, len))) return (0);
49 :
50 146 : len = tmp - ptr;
51 146 : return (len + 1);
52 : }
53 : #else
54 : USTR_CONF_I_PROTO size_t ustr_srch_chr_rev(const struct Ustr *s1, size_t off,
55 : char val)
56 : { /* slow... */
57 : const char *ptr = ustr_cstr(s1);
58 : size_t len = ustr_len(s1);
59 : const char *tmp = ptr;
60 : const char *prev = 0;
61 :
62 : USTR_ASSERT(ustr_assert_valid(s1));
63 :
64 : USTR_ASSERT_RET(off <= len, 0);
65 : len -= off;
66 :
67 : while ((tmp = memchr(tmp, val, len - (tmp - ptr))))
68 : {
69 : prev = tmp;
70 : ++tmp;
71 : }
72 :
73 : if (!prev)
74 : return (0);
75 :
76 : len = prev - ptr;
77 : return (len + 1);
78 : }
79 : #endif
80 :
81 : #if ! USTR_CONF_HAVE_MEMMEM
82 : USTR_CONF_i_PROTO void *ustr__sys_memmem(const void *hs, size_t hslen,
83 : const void *nd, size_t ndlen)
84 : {
85 : const char *ptr = hs;
86 :
87 : if (ndlen == 0)
88 : return ((void *)hs);
89 :
90 : while (hslen >= ndlen)
91 : {
92 : if (!memcmp(ptr, nd, ndlen))
93 : return ((void *)ptr);
94 :
95 : --hslen;
96 : ++ptr;
97 : }
98 :
99 : return (0);
100 : }
101 : #endif
102 :
103 : USTR_CONF_I_PROTO size_t ustr_srch_buf_fwd(const struct Ustr *s1, size_t off,
104 : const void *val, size_t vlen)
105 1018 : {
106 790 : const char *beg = ustr_cstr(s1);
107 : const char *ptr;
108 790 : size_t len = ustr_len(s1);
109 1018 : char *tmp = 0;
110 :
111 506 : USTR_ASSERT(ustr_assert_valid(s1));
112 :
113 1018 : if (vlen == 1)
114 512 : return (ustr_srch_chr_fwd(s1, off, ((const char *)val)[0]));
115 :
116 506 : USTR_ASSERT_RET(off <= len, 0);
117 506 : if (vlen == 0)
118 54 : return (len ? (off + 1) : 0);
119 :
120 452 : ptr = beg + off;
121 452 : len -= off;
122 :
123 452 : if (!(tmp = USTR__SYS_MEMMEM(ptr, len, val, vlen)))
124 96 : return (0);
125 :
126 356 : len = tmp - beg;
127 356 : return (len + 1);
128 : }
129 :
130 : USTR_CONF_I_PROTO size_t ustr_srch_buf_rev(const struct Ustr *s1, size_t off,
131 : const void *val, size_t vlen)
132 288 : {
133 241 : const char *ptr = ustr_cstr(s1);
134 241 : size_t len = ustr_len(s1);
135 288 : const char *prev = 0;
136 288 : const char *tmp = 0;
137 :
138 142 : USTR_ASSERT(ustr_assert_valid(s1));
139 :
140 288 : if (vlen == 1)
141 104 : return (ustr_srch_chr_rev(s1, off, ((const char *)val)[0]));
142 :
143 184 : USTR_ASSERT_RET(off <= len, 0);
144 184 : len -= off;
145 :
146 184 : if (vlen == 0)
147 54 : return (len);
148 :
149 130 : tmp = ptr;
150 372 : while (((len - (tmp - ptr)) >= vlen) &&
151 : (tmp = USTR__SYS_MEMMEM(tmp, len - (tmp - ptr), val, vlen)))
152 : {
153 112 : prev = tmp;
154 112 : ++tmp;
155 : }
156 130 : if (!prev)
157 22 : return (0);
158 :
159 108 : len = prev - ptr;
160 108 : return (len + 1);
161 : }
162 :
163 : USTR_CONF_I_PROTO
164 : size_t ustr_srch_subustr_fwd(const struct Ustr *s1, size_t off,
165 : const struct Ustr *s2, size_t pos, size_t len)
166 62 : {
167 30 : USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2));
168 :
169 62 : if (!ustr_assert_valid_subustr(s2, pos, len))
170 2 : return (ustr_srch_buf_fwd(s1, off, "", 0));
171 :
172 60 : return (ustr_srch_buf_fwd(s1, off, ustr_cstr(s2) + --pos, len));
173 : }
174 :
175 : USTR_CONF_I_PROTO
176 : size_t ustr_srch_subustr_rev(const struct Ustr *s1, size_t off,
177 : const struct Ustr *s2, size_t pos, size_t len)
178 62 : {
179 30 : USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2));
180 :
181 62 : if (!ustr_assert_valid_subustr(s2, pos, len))
182 2 : return (ustr_srch_buf_rev(s1, off, "", 0));
183 :
184 60 : return (ustr_srch_buf_rev(s1, off, ustr_cstr(s2) + --pos, len));
185 : }
186 :
187 : USTR_CONF_i_PROTO
188 : void *ustr__memrepchr(const void *hs, size_t hslen, char nd, size_t ndlen)
189 328 : {
190 328 : const char *ptr = hs;
191 :
192 164 : USTR_ASSERT(ndlen); /* dealt with by callers */
193 :
194 584 : while (hslen >= ndlen)
195 : {
196 360 : const char *tmp = memchr(ptr, nd, hslen);
197 360 : size_t len = ndlen;
198 :
199 360 : if (!tmp)
200 28 : break;
201 332 : if (ndlen > (hslen - (tmp - ptr)))
202 20 : break;
203 :
204 312 : tmp += len;
205 1276 : while (len > 0)
206 : {
207 744 : --tmp;
208 744 : if (*tmp != nd)
209 92 : break;
210 652 : --len;
211 : }
212 312 : if (!len)
213 220 : return ((void *)tmp);
214 :
215 92 : hslen -= (tmp - ptr);
216 92 : ptr = tmp;
217 : }
218 :
219 108 : return (0);
220 : }
221 :
222 : USTR_CONF_I_PROTO size_t ustr_srch_rep_chr_fwd(const struct Ustr *s1,size_t off,
223 : char val, size_t vlen)
224 489 : {
225 367 : const char *beg = ustr_cstr(s1);
226 : const char *ptr;
227 367 : size_t len = ustr_len(s1);
228 489 : char *tmp = 0;
229 :
230 244 : USTR_ASSERT(ustr_assert_valid(s1));
231 :
232 489 : if (vlen == 1)
233 249 : return (ustr_srch_chr_fwd(s1, off, val));
234 :
235 240 : USTR_ASSERT_RET(off <= len, 0);
236 240 : if (vlen == 0)
237 8 : return (len ? (off + 1) : 0);
238 :
239 232 : ptr = beg + off;
240 232 : len -= off;
241 :
242 232 : if (!(tmp = ustr__memrepchr(ptr, len, val, vlen)))
243 80 : return (0);
244 :
245 152 : len = tmp - beg;
246 152 : return (len + 1);
247 : }
248 :
249 : USTR_CONF_I_PROTO size_t ustr_srch_rep_chr_rev(const struct Ustr *s1,size_t off,
250 : char val, size_t vlen)
251 72 : {
252 54 : const char *ptr = ustr_cstr(s1);
253 54 : size_t len = ustr_len(s1);
254 72 : const char *prev = 0;
255 72 : const char *tmp = 0;
256 :
257 36 : USTR_ASSERT(ustr_assert_valid(s1));
258 :
259 72 : if (vlen == 1)
260 20 : return (ustr_srch_chr_rev(s1, off, val));
261 :
262 52 : USTR_ASSERT_RET(off <= len, 0);
263 52 : len -= off;
264 :
265 52 : if (vlen == 0)
266 8 : return (len);
267 :
268 44 : tmp = ptr;
269 156 : while (((len - (tmp - ptr)) >= vlen) &&
270 : (tmp = ustr__memrepchr(tmp, len - (tmp - ptr), val, vlen)))
271 : {
272 68 : prev = tmp;
273 68 : ++tmp;
274 : }
275 44 : if (!prev)
276 16 : return (0);
277 :
278 28 : len = prev - ptr;
279 28 : return (len + 1);
280 : }
281 :
282 : /* ignore case */
283 : USTR_CONF_i_PROTO
284 : void *ustr__memcasechr(const void *hs, const char nd, size_t len)
285 1844 : {
286 2744 : const unsigned char *s1 = hs;
287 2744 : unsigned char c2 = nd;
288 :
289 2744 : if ((c2 >= 0x61) && (c2 <= 0x7a))
290 1280 : c2 ^= 0x20;
291 :
292 11280 : while (len)
293 : {
294 9540 : unsigned char c1 = *s1;
295 :
296 9540 : if ((c1 >= 0x61) && (c1 <= 0x7a))
297 3670 : c1 ^= 0x20;
298 :
299 9540 : if (c1 == c2)
300 2376 : return ((void *)s1);
301 :
302 7164 : --len;
303 7164 : ++s1;
304 : }
305 :
306 368 : return (0);
307 : }
308 :
309 : USTR_CONF_i_PROTO
310 : void *ustr__memcasemem(const void *hs,size_t hslen, const void *nd,size_t ndlen)
311 340 : {
312 340 : const char *ptr = hs;
313 :
314 170 : USTR_ASSERT(ndlen); /* dealt with by callers */
315 :
316 2766 : while (hslen >= ndlen)
317 : {
318 2464 : if (!ustr__memcasecmp(ptr, nd, ndlen))
319 208 : return ((void *)ptr);
320 :
321 2256 : --hslen;
322 2256 : ++ptr;
323 : }
324 :
325 132 : return (0);
326 : }
327 :
328 : USTR_CONF_i_PROTO
329 : void *ustr__memcaserepchr(const void *hs, size_t hslen, char nd, size_t ndlen)
330 1240 : {
331 1240 : const unsigned char *s1 = hs;
332 1240 : unsigned char c2 = nd;
333 :
334 620 : USTR_ASSERT(ndlen); /* dealt with by callers */
335 :
336 1240 : if ((c2 >= 0x61) && (c2 <= 0x7a))
337 612 : c2 ^= 0x20;
338 :
339 1956 : while (hslen >= ndlen)
340 : {
341 1780 : const unsigned char *tmp = ustr__memcasechr(s1, nd, hslen);
342 1336 : size_t len = ndlen;
343 :
344 1336 : if (!tmp)
345 144 : break;
346 1192 : if (ndlen > (hslen - (tmp - s1)))
347 48 : break;
348 :
349 1144 : tmp += len;
350 5800 : while (len > 0)
351 : {
352 3608 : unsigned char c1 = *--tmp;
353 :
354 3608 : if ((c1 >= 0x61) && (c1 <= 0x7a))
355 1776 : c1 ^= 0x20;
356 :
357 3608 : if (c1 != c2)
358 96 : break;
359 :
360 3512 : --len;
361 : }
362 1144 : if (!len)
363 1048 : return ((void *)tmp);
364 :
365 96 : hslen -= (tmp - s1);
366 96 : s1 = tmp;
367 : }
368 :
369 192 : return (0);
370 : }
371 :
372 :
373 : USTR_CONF_I_PROTO
374 : size_t ustr_srch_case_chr_fwd(const struct Ustr *s1, size_t off, char val)
375 208 : {
376 168 : const char *beg = ustr_cstr(s1);
377 : const char *ptr;
378 168 : size_t len = ustr_len(s1);
379 : const char *tmp;
380 :
381 104 : USTR_ASSERT(ustr_assert_valid(s1));
382 :
383 208 : USTR_ASSERT_RET(off <= len, 0);
384 208 : ptr = beg + off;
385 208 : len -= off;
386 :
387 272 : if (!(tmp = ustr__memcasechr(ptr, val, len))) return (0);
388 :
389 176 : len = tmp - beg;
390 176 : return (len + 1);
391 : }
392 :
393 : USTR_CONF_I_PROTO
394 : size_t ustr_srch_case_chr_rev(const struct Ustr *s1, size_t off, char val)
395 192 : { /* slow... */
396 156 : const char *ptr = ustr_cstr(s1);
397 156 : size_t len = ustr_len(s1);
398 192 : const char *tmp = ptr;
399 192 : const char *prev = 0;
400 :
401 96 : USTR_ASSERT(ustr_assert_valid(s1));
402 :
403 192 : USTR_ASSERT_RET(off <= len, 0);
404 192 : len -= off;
405 :
406 1784 : while ((tmp = ustr__memcasechr(tmp, val, len - (tmp - ptr))))
407 : {
408 1008 : prev = tmp;
409 1008 : ++tmp;
410 : }
411 :
412 192 : if (!prev)
413 40 : return (0);
414 :
415 152 : len = prev - ptr;
416 152 : return (len + 1);
417 : }
418 :
419 : USTR_CONF_I_PROTO
420 : size_t ustr_srch_case_buf_fwd(const struct Ustr *s1, size_t off,
421 : const void *val, size_t vlen)
422 226 : {
423 183 : const char *beg = ustr_cstr(s1);
424 : const char *ptr;
425 183 : size_t len = ustr_len(s1);
426 226 : char *tmp = 0;
427 :
428 110 : USTR_ASSERT(ustr_assert_valid(s1));
429 :
430 226 : if (vlen == 1)
431 84 : return (ustr_srch_case_chr_fwd(s1, off, ((const char *)val)[0]));
432 :
433 142 : USTR_ASSERT_RET(off <= len, 0);
434 142 : if (vlen == 0)
435 18 : return (len ? (off + 1) : 0);
436 :
437 124 : ptr = beg + off;
438 124 : len -= off;
439 :
440 124 : if (!(tmp = ustr__memcasemem(ptr, len, val, vlen)))
441 24 : return (0);
442 :
443 100 : len = tmp - beg;
444 100 : return (len + 1);
445 : }
446 :
447 : USTR_CONF_I_PROTO
448 : size_t ustr_srch_case_buf_rev(const struct Ustr *s1, size_t off,
449 : const void *val, size_t vlen)
450 198 : {
451 162 : const char *ptr = ustr_cstr(s1);
452 162 : size_t len = ustr_len(s1);
453 198 : const char *prev = 0;
454 198 : const char *tmp = 0;
455 :
456 96 : USTR_ASSERT(ustr_assert_valid(s1));
457 :
458 198 : if (vlen == 1)
459 72 : return (ustr_srch_case_chr_rev(s1, off, ((const char *)val)[0]));
460 :
461 126 : USTR_ASSERT_RET(off <= len, 0);
462 126 : len -= off;
463 :
464 126 : if (vlen == 0)
465 18 : return (len);
466 :
467 108 : tmp = ptr;
468 324 : while (((len - (tmp - ptr)) >= vlen) &&
469 : (tmp = ustr__memcasemem(tmp, len - (tmp - ptr), val, vlen)))
470 : {
471 108 : prev = tmp;
472 108 : ++tmp;
473 : }
474 108 : if (!prev)
475 24 : return (0);
476 :
477 84 : len = prev - ptr;
478 84 : return (len + 1);
479 : }
480 :
481 : USTR_CONF_I_PROTO
482 : size_t ustr_srch_case_subustr_fwd(const struct Ustr *s1, size_t off,
483 : const struct Ustr *s2, size_t pos, size_t len)
484 42 : {
485 18 : USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2));
486 :
487 42 : if (!ustr_assert_valid_subustr(s2, pos, len))
488 6 : return (ustr_srch_case_buf_fwd(s1, off, "", 0));
489 :
490 36 : return (ustr_srch_case_buf_fwd(s1, off, ustr_cstr(s2) + --pos, len));
491 : }
492 :
493 : USTR_CONF_I_PROTO
494 : size_t ustr_srch_case_subustr_rev(const struct Ustr *s1, size_t off,
495 : const struct Ustr *s2, size_t pos, size_t len)
496 42 : {
497 18 : USTR_ASSERT(ustr_assert_valid(s1) && ustr_assert_valid(s2));
498 :
499 42 : if (!ustr_assert_valid_subustr(s2, pos, len))
500 6 : return (ustr_srch_case_buf_rev(s1, off, "", 0));
501 :
502 36 : return (ustr_srch_case_buf_rev(s1, off, ustr_cstr(s2) + --pos, len));
503 : }
504 :
505 : USTR_CONF_I_PROTO
506 : size_t ustr_srch_case_rep_chr_fwd(const struct Ustr *s1, size_t off,
507 : char val, size_t vlen)
508 332 : {
509 275 : const char *beg = ustr_cstr(s1);
510 : const char *ptr;
511 275 : size_t len = ustr_len(s1);
512 332 : char *tmp = 0;
513 :
514 166 : USTR_ASSERT(ustr_assert_valid(s1));
515 :
516 332 : if (vlen == 1)
517 76 : return (ustr_srch_case_chr_fwd(s1, off, val));
518 :
519 256 : USTR_ASSERT_RET(off <= len, 0);
520 256 : if (vlen == 0)
521 24 : return (len ? (off + 1) : 0);
522 :
523 232 : ptr = beg + off;
524 232 : len -= off;
525 :
526 232 : if (!(tmp = ustr__memcaserepchr(ptr, len, val, vlen)))
527 72 : return (0);
528 :
529 160 : len = tmp - beg;
530 160 : return (len + 1);
531 : }
532 :
533 : USTR_CONF_I_PROTO
534 : size_t ustr_srch_case_rep_chr_rev(const struct Ustr *s1, size_t off,
535 : char val, size_t vlen)
536 312 : {
537 260 : const char *ptr = ustr_cstr(s1);
538 260 : size_t len = ustr_len(s1);
539 312 : const char *prev = 0;
540 312 : const char *tmp = 0;
541 :
542 156 : USTR_ASSERT(ustr_assert_valid(s1));
543 :
544 312 : if (vlen == 1)
545 72 : return (ustr_srch_case_chr_rev(s1, off, val));
546 :
547 240 : USTR_ASSERT_RET(off <= len, 0);
548 240 : len -= off;
549 :
550 240 : if (vlen == 0)
551 24 : return (len);
552 :
553 216 : tmp = ptr;
554 1320 : while (((len - (tmp - ptr)) >= vlen) &&
555 : (tmp = ustr__memcaserepchr(tmp, len - (tmp - ptr), val, vlen)))
556 : {
557 888 : prev = tmp;
558 888 : ++tmp;
559 : }
560 216 : if (!prev)
561 72 : return (0);
562 :
563 144 : len = prev - ptr;
564 144 : return (len + 1);
565 : }
566 :
|