-
Notifications
You must be signed in to change notification settings - Fork 1
/
ac_match.h
107 lines (96 loc) · 2.98 KB
/
ac_match.h
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#pragma once
#include "ac_comm.h"
namespace ac {
typedef enum STATE_MOVE_RESULT_ {
SM_ACCEPTED,
SM_FAIL_LINK,
SM_REACH_ROOT,
} MoveRet;
class WithCodeTable {
protected:
uint8_t code_table_[0x100];
public:
void set_code_table(const uint8_t* table) {
memcpy(code_table_, table, sizeof(code_table_));
}
uint8_t translate( uint8_t ch ) const {
return code_table_[ch];
}
};
template < typename MatchStateId, typename MatchState>
struct Machine {
MatchState get_state(MatchStateId) const;
MoveRet move_state(MatchState&, uint8_t ch) const;
bool is_final(const MatchState&) const;
MatchStateId id_of(const MatchState&) const;
};
template <typename Machine = Machine,
typename MatchStateId = typename Machine::MatchStateId,
typename MatchState = typename Machine::MatchState >
static bool match(const Machine & machine,
MatchStateId & state,
mem_bound_t & buffer,
bool verbose)
{
const uint8_t* data = buffer.data;
const uint8_t* tail = buffer.tail;
MatchState p = machine.get_state(state);
for (; data < tail; ++data) {
uint8_t b8 = *data;
uint8_t ch = machine.translate(b8);
for (;;) {
MoveRet ms = machine.move_state(p, ch);
if (ms == SM_ACCEPTED)
{
if (machine.is_final(p)) {
state = machine.id_of(p);
buffer.data = data + 1;
return true;
}
break;
}
else if (ms == SM_FAIL_LINK) {
continue;
}
else {
break;
}
}
}
state = machine.id_of(p);
buffer.data = data;
return false;
}
template <typename Machine = Machine,
typename MatchStateId = typename Machine::MatchStateId,
typename MatchState = typename Machine::MatchState >
static bool feed(const Machine & machine,
MatchStateId & state,
uint8_t uch8,
bool verbose)
{
MatchState p = machine.get_state(state);
uint8_t ch = machine.translate(uch8);
if (verbose) printf("\n");
for (;;) {
if (verbose) printf("%d ", machine.id_of(p));
MoveRet ms = machine.move_state(p, ch);
if (ms == SM_ACCEPTED)
{
if (machine.is_final(p)) {
state = machine.id_of(p);
return true;
}
break;
}
else if (ms == SM_FAIL_LINK) {
continue;
}
else {
break;
}
}
state = machine.id_of(p);
return false;
}
};