/src/wget/lib/c-strcasestr.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* c-strcasestr.c -- case insensitive substring search in C locale |
2 | | Copyright (C) 2005-2023 Free Software Foundation, Inc. |
3 | | Written by Bruno Haible <bruno@clisp.org>, 2005. |
4 | | |
5 | | This file is free software: you can redistribute it and/or modify |
6 | | it under the terms of the GNU Lesser General Public License as |
7 | | published by the Free Software Foundation; either version 2.1 of the |
8 | | License, or (at your option) any later version. |
9 | | |
10 | | This file is distributed in the hope that it will be useful, |
11 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | GNU Lesser General Public License for more details. |
14 | | |
15 | | You should have received a copy of the GNU Lesser General Public License |
16 | | along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
17 | | |
18 | | #include <config.h> |
19 | | |
20 | | /* Specification. */ |
21 | | #include "c-strcasestr.h" |
22 | | |
23 | | #include <string.h> |
24 | | |
25 | | #include "c-ctype.h" |
26 | | #include "c-strcase.h" |
27 | | |
28 | | /* Two-Way algorithm. */ |
29 | | #define RETURN_TYPE char * |
30 | | #define AVAILABLE(h, h_l, j, n_l) \ |
31 | 0 | (!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l)) \ |
32 | 0 | && ((h_l) = (j) + (n_l))) |
33 | 0 | #define CANON_ELEMENT c_tolower |
34 | | #define CMP_FUNC(p1, p2, l) \ |
35 | 0 | c_strncasecmp ((const char *) (p1), (const char *) (p2), l) |
36 | | #include "str-two-way.h" |
37 | | |
38 | | /* Find the first occurrence of NEEDLE in HAYSTACK, using case-insensitive |
39 | | comparison from the C locale, regardless of the current locale. */ |
40 | | char * |
41 | | c_strcasestr (const char *haystack_start, const char *needle_start) |
42 | 0 | { |
43 | 0 | const char *haystack = haystack_start; |
44 | 0 | const char *needle = needle_start; |
45 | 0 | size_t needle_len; /* Length of NEEDLE. */ |
46 | 0 | size_t haystack_len; /* Known minimum length of HAYSTACK. */ |
47 | 0 | bool ok = true; /* True if NEEDLE is prefix of HAYSTACK. */ |
48 | | |
49 | | /* Determine length of NEEDLE, and in the process, make sure |
50 | | HAYSTACK is at least as long (no point processing all of a long |
51 | | NEEDLE if HAYSTACK is too short). */ |
52 | 0 | while (*haystack && *needle) |
53 | 0 | ok &= (c_tolower ((unsigned char) *haystack++) |
54 | 0 | == c_tolower ((unsigned char) *needle++)); |
55 | 0 | if (*needle) |
56 | 0 | return NULL; |
57 | 0 | if (ok) |
58 | 0 | return (char *) haystack_start; |
59 | 0 | needle_len = needle - needle_start; |
60 | 0 | haystack = haystack_start + 1; |
61 | 0 | haystack_len = needle_len - 1; |
62 | | |
63 | | /* Perform the search. Abstract memory is considered to be an array |
64 | | of 'unsigned char' values, not an array of 'char' values. See |
65 | | ISO C 99 section 6.2.6.1. */ |
66 | 0 | if (needle_len < LONG_NEEDLE_THRESHOLD) |
67 | 0 | return two_way_short_needle ((const unsigned char *) haystack, |
68 | 0 | haystack_len, |
69 | 0 | (const unsigned char *) needle_start, |
70 | 0 | needle_len); |
71 | 0 | return two_way_long_needle ((const unsigned char *) haystack, haystack_len, |
72 | 0 | (const unsigned char *) needle_start, |
73 | 0 | needle_len); |
74 | 0 | } |
75 | | |
76 | | #undef LONG_NEEDLE_THRESHOLD |