Line |
Branch |
Exec |
Source |
1 |
|
|
#include "feature.h" |
2 |
|
|
#include <string.h> |
3 |
|
|
#include "xmemmem.h" |
4 |
|
|
#include "debug.h" |
5 |
|
|
|
6 |
|
53 |
void *xmemmem(const void *haystack, size_t hlen, const void *needle, size_t nlen) |
7 |
|
|
{ |
8 |
|
53 |
BUG_ON(nlen == 0); |
9 |
|
|
|
10 |
|
|
#if HAVE_MEMMEM |
11 |
|
53 |
return memmem(haystack, hlen, needle, nlen); |
12 |
|
|
#endif |
13 |
|
|
|
14 |
|
|
// Note: this fallback implementation isn't well suited to general |
15 |
|
|
// purpose use and can exhibit poor performance under certain |
16 |
|
|
// inputs. A library-quality memmem(3) is not a trivial thing to |
17 |
|
|
// implement, but fortunately almost every modern platform already |
18 |
|
|
// has one in libc and it's been added to the POSIX base spec in |
19 |
|
|
// issue 8[1]. Therefore, this code isn't likely to be used, and |
20 |
|
|
// even when it is, it should be acceptable for the uses in this |
21 |
|
|
// codebase. |
22 |
|
|
// [1]: https://www.austingroupbugs.net/view.php?id=1061 |
23 |
|
|
|
24 |
|
|
const char *start = haystack; |
25 |
|
|
int first_char = ((const unsigned char*)needle)[0]; |
26 |
|
|
if (nlen == 1) { |
27 |
|
|
return memchr(start, first_char, hlen); |
28 |
|
|
} |
29 |
|
|
|
30 |
|
|
while (1) { |
31 |
|
|
char *ptr = memchr(start, first_char, hlen); |
32 |
|
|
if (!ptr) { |
33 |
|
|
return NULL; |
34 |
|
|
} |
35 |
|
|
size_t skip = (size_t)(ptr - start); |
36 |
|
|
if (skip + nlen > hlen) { |
37 |
|
|
return NULL; |
38 |
|
|
} |
39 |
|
|
if (memcmp(ptr, needle, nlen) == 0) { |
40 |
|
|
return ptr; |
41 |
|
|
} |
42 |
|
|
start = ptr + 1; |
43 |
|
|
hlen -= skip + 1; |
44 |
|
|
} |
45 |
|
|
|
46 |
|
|
BUG("unexpected loop break"); |
47 |
|
|
return NULL; |
48 |
|
|
} |
49 |
|
|
|