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