Line |
Branch |
Exec |
Source |
1 |
|
|
#include "feature.h" |
2 |
|
|
#include <string.h> |
3 |
|
|
#include "xmemmem.h" |
4 |
|
|
#include "debug.h" |
5 |
|
|
|
6 |
|
54 |
void *xmemmem(const void *haystack, size_t hlen, const void *needle, size_t nlen) |
7 |
|
|
{ |
8 |
|
54 |
BUG_ON(nlen == 0); |
9 |
|
|
|
10 |
|
|
#if HAVE_MEMMEM |
11 |
|
54 |
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 inputs. |
16 |
|
|
// A library-quality memmem(3) isn't a trivial thing to implement, |
17 |
|
|
// but fortunately almost every modern platform already has one in |
18 |
|
|
// libc and it was added to the POSIX base spec in issue 8. Therefore, |
19 |
|
|
// this code isn't likely to be used, and even when it is, it should |
20 |
|
|
// be acceptable for the uses in this codebase. |
21 |
|
|
|
22 |
|
|
const char *start = haystack; |
23 |
|
|
int first_char = ((const unsigned char*)needle)[0]; |
24 |
|
|
if (nlen == 1) { |
25 |
|
|
return memchr(start, first_char, hlen); |
26 |
|
|
} |
27 |
|
|
|
28 |
|
|
while (1) { |
29 |
|
|
char *ptr = memchr(start, first_char, hlen); |
30 |
|
|
if (!ptr) { |
31 |
|
|
return NULL; |
32 |
|
|
} |
33 |
|
|
size_t skip = (size_t)(ptr - start); |
34 |
|
|
if (skip + nlen > hlen) { |
35 |
|
|
return NULL; |
36 |
|
|
} |
37 |
|
|
if (memcmp(ptr, needle, nlen) == 0) { |
38 |
|
|
return ptr; |
39 |
|
|
} |
40 |
|
|
start = ptr + 1; |
41 |
|
|
hlen -= skip + 1; |
42 |
|
|
} |
43 |
|
|
|
44 |
|
|
BUG("unexpected loop break"); |
45 |
|
|
return NULL; |
46 |
|
|
} |
47 |
|
|
|