aboutsummaryrefslogtreecommitdiffstats
path: root/libautomata_execute_kmp_automaton.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libautomata_execute_kmp_automaton.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/libautomata_execute_kmp_automaton.c b/libautomata_execute_kmp_automaton.c
new file mode 100644
index 0000000..69ffcce
--- /dev/null
+++ b/libautomata_execute_kmp_automaton.c
@@ -0,0 +1,40 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+void *
+libautomata_execute_kmp_automaton(const void *haystack, size_t length, LIBAUTOMATA_KMP_AUTOMATON *automaton)
+{
+ const void *pattern = (void *)&automaton->next[automaton->length + 1U];
+ size_t i = 0;
+
+#define INTRINSIC(TYPE)\
+ (((const TYPE *)pattern)[automaton->position] == ((const TYPE *)haystack)[i])
+
+#define MEMCMP(WIDTH)\
+ (!memcmp(&((const char *)pattern)[automaton->position * automaton->elemsize],\
+ &((const char *)haystack)[i * automaton->elemsize],\
+ automaton->elemsize))
+
+#define IMPLEMENT(EQ, EQ_PARAM)\
+ while (i < length) {\
+ while (automaton->position != SIZE_MAX && !(EQ(EQ_PARAM)))\
+ automaton->position = automaton->next[automaton->position];\
+ i++;\
+ if (++automaton->position == automaton->length)\
+ goto found;\
+ }\
+ return NULL
+
+ switch (automaton->elemsize) {
+ case sizeof(uint8_t): IMPLEMENT(INTRINSIC, uint8_t);
+ case sizeof(uint16_t): IMPLEMENT(INTRINSIC, uint16_t);
+ case sizeof(uint32_t): IMPLEMENT(INTRINSIC, uint32_t);
+ case sizeof(uint64_t): IMPLEMENT(INTRINSIC, uint64_t);
+ default: IMPLEMENT(MEMCMP, elemsize);
+ }
+
+found:
+ automaton->position = automaton->next[automaton->position];
+ return &(*(char **)(void *)&haystack)[i];
+}