aboutsummaryrefslogtreecommitdiffstats
path: root/libautomata_compile_mp_automaton.c
blob: b9e8739f48b39d477d1b419abee70eba0dc9c032 (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
41
42
43
44
/* See LICENSE file for copyright and license details. */
#include "common.h"


LIBAUTOMATA_MP_AUTOMATON *
libautomata_compile_mp_automaton(const void *pattern, size_t length, size_t elemsize)
{
	size_t i = 0, j = SIZE_MAX;
	size_t size = sizeof_mp_automaton(length, elemsize);
	LIBAUTOMATA_MP_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++;\
	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);
	}
}