simplefsa_impl.hpp
2.32 KB
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
/*
* File: simplefsa_impl.hpp
* Author: mlenart
*
* Created on November 4, 2013, 1:05 PM
*/
#ifndef SIMPLEFSA_IMPL_HPP
#define SIMPLEFSA_IMPL_HPP
#include <iostream>
//#pragma pack(push, 1) /* push current alignment to stack */
struct StateData {
unsigned char transitionsNum;
bool accepting;
};
//#pragma pack(pop) /* restore original alignment from stack */
template <class T>
SimpleFSA<T>::SimpleFSA(const unsigned char* ptr, const Deserializer<T>& deserializer)
: FSA<T>(ptr, deserializer) {
}
template <class T>
SimpleFSA<T>::~SimpleFSA() {
}
static inline unsigned int decodeOffset(const unsigned char* ptr) {
unsigned int res = 0;
res = ptr[0] << 16 | ptr[1] << 8 | ptr[2];
return res;
}
static inline StateData decodeStateData(const unsigned char* ptr) {
static const unsigned char acceptingFlag = 128;
static const unsigned char transitionsNumMask = 127;
StateData res;
res.transitionsNum = (*ptr) & transitionsNumMask;
res.accepting = (*ptr) & acceptingFlag;
return res;
}
template <class T>
void SimpleFSA<T>::proceedToNext(const char c, State<T>& state) const {
const unsigned char* fromPointer = this->initialStatePtr + state.getOffset();
long transitionsTableOffset = 1;
if (state.isAccepting()) {
transitionsTableOffset += state.getValueSize();
}
StateData stateData = decodeStateData(fromPointer);
const unsigned char* foundTransition = fromPointer + transitionsTableOffset;
bool found = false;
for (unsigned int i = 0; i < stateData.transitionsNum; i++, foundTransition += 4) {
if ((char) *foundTransition == c) {
found = true;
break;
}
}
// const_cast<Counter*>(&counter)->increment(foundTransition - transitionsStart + 1);
if (!found) {
state.setNextAsSink();
} else {
unsigned int offset = decodeOffset(foundTransition + 1);
const unsigned char* nextStatePointer = this->initialStatePtr + offset;
StateData nextStateData = decodeStateData(nextStatePointer);
if (nextStateData.accepting) {
T object;
long size = this->deserializer.deserialize(nextStatePointer + 1, object);
state.setNext(offset, object, size);
} else {
state.setNext(offset);
}
}
}
#endif /* SIMPLEFSA_IMPL_HPP */