mirror of
https://github.com/palera1n/palera1n.git
synced 2026-10-21 09:47:01 +02:00
60 lines
2.2 KiB
C
60 lines
2.2 KiB
C
#include <limits.h>
|
|
#include <stdlib.h>
|
|
|
|
const unsigned char *
|
|
boyermoore_horspool_memmem(const unsigned char* haystack, size_t hlen,
|
|
const unsigned char* needle, size_t nlen)
|
|
{
|
|
size_t scan = 0;
|
|
size_t bad_char_skip[UCHAR_MAX + 1]; /* Officially called:
|
|
* bad character shift */
|
|
|
|
/* Sanity checks on the parameters */
|
|
if (nlen <= 0 || !haystack || !needle)
|
|
return NULL;
|
|
|
|
/* ---- Preprocess ---- */
|
|
/* Initialize the table to default value */
|
|
/* When a character is encountered that does not occur
|
|
* in the needle, we can safely skip ahead for the whole
|
|
* length of the needle.
|
|
*/
|
|
for (scan = 0; scan <= UCHAR_MAX; scan = scan + 1)
|
|
bad_char_skip[scan] = nlen;
|
|
|
|
/* C arrays have the first byte at [0], therefore:
|
|
* [nlen - 1] is the last byte of the array. */
|
|
size_t last = nlen - 1;
|
|
|
|
/* Then populate it with the analysis of the needle */
|
|
for (scan = 0; scan < last; scan = scan + 1)
|
|
bad_char_skip[needle[scan]] = last - scan;
|
|
|
|
/* ---- Do the matching ---- */
|
|
|
|
/* Search the haystack, while the needle can still be within it. */
|
|
while (hlen >= nlen)
|
|
{
|
|
/* scan from the end of the needle */
|
|
for (scan = last; haystack[scan] == needle[scan]; scan = scan - 1)
|
|
if (scan == 0) /* If the first byte matches, we've found it. */
|
|
{
|
|
return haystack;
|
|
}
|
|
|
|
/* otherwise, we need to skip some bytes and start again.
|
|
Note that here we are getting the skip value based on the last byte
|
|
of needle, no matter where we didn't match. So if needle is: "abcd"
|
|
then we are skipping based on 'd' and that value will be 4, and
|
|
for "abcdd" we again skip on 'd' but the value will be only 1.
|
|
The alternative of pretending that the mismatched character was
|
|
the last character is slower in the normal case (E.g. finding
|
|
"abcd" in "...azcd..." gives 4 by using 'd' but only
|
|
4-2==2 using 'z'. */
|
|
hlen -= bad_char_skip[haystack[last]];
|
|
haystack += bad_char_skip[haystack[last]];
|
|
}
|
|
|
|
return NULL;
|
|
}
|