aboutsummaryrefslogtreecommitdiffstats
path: root/libautomata_execute_kmp_automaton.c
blob: 69ffcce9e1f40ce3579700d907999b8e68bbfe80 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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];
}