Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/graphite/src/inc/Rule.h
9906 views
1
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
2
// Copyright 2011, SIL International, All rights reserved.
3
4
5
#pragma once
6
7
#include "inc/Code.h"
8
#include "inc/Slot.h"
9
10
namespace graphite2 {
11
12
struct Rule {
13
const vm::Machine::Code * constraint,
14
* action;
15
unsigned short sort;
16
byte preContext;
17
#ifndef NDEBUG
18
uint16 rule_idx;
19
#endif
20
21
Rule();
22
~Rule() {}
23
24
CLASS_NEW_DELETE;
25
26
private:
27
Rule(const Rule &);
28
Rule & operator = (const Rule &);
29
};
30
31
inline
32
Rule::Rule()
33
: constraint(0),
34
action(0),
35
sort(0),
36
preContext(0)
37
{
38
#ifndef NDEBUG
39
rule_idx = 0;
40
#endif
41
}
42
43
44
struct RuleEntry
45
{
46
const Rule * rule;
47
48
inline
49
bool operator < (const RuleEntry &r) const
50
{
51
const unsigned short lsort = rule->sort, rsort = r.rule->sort;
52
return lsort > rsort || (lsort == rsort && rule < r.rule);
53
}
54
55
inline
56
bool operator == (const RuleEntry &r) const
57
{
58
return rule == r.rule;
59
}
60
};
61
62
63
struct State
64
{
65
const RuleEntry * rules,
66
* rules_end;
67
68
bool empty() const;
69
};
70
71
inline
72
bool State::empty() const
73
{
74
return rules_end == rules;
75
}
76
77
78
class SlotMap
79
{
80
public:
81
enum {MAX_SLOTS=64};
82
SlotMap(Segment & seg, uint8 direction, size_t maxSize);
83
84
Slot * * begin();
85
Slot * * end();
86
size_t size() const;
87
unsigned short context() const;
88
void reset(Slot &, unsigned short);
89
90
Slot * const & operator[](int n) const;
91
Slot * & operator [] (int);
92
void pushSlot(Slot * const slot);
93
void collectGarbage(Slot *& aSlot);
94
95
Slot * highwater() { return m_highwater; }
96
void highwater(Slot *s) { m_highwater = s; m_highpassed = false; }
97
bool highpassed() const { return m_highpassed; }
98
void highpassed(bool v) { m_highpassed = v; }
99
100
uint8 dir() const { return m_dir; }
101
int decMax() { return --m_maxSize; }
102
103
Segment & segment;
104
private:
105
Slot * m_slot_map[MAX_SLOTS+1];
106
unsigned short m_size;
107
unsigned short m_precontext;
108
Slot * m_highwater;
109
int m_maxSize;
110
uint8 m_dir;
111
bool m_highpassed;
112
};
113
114
115
class FiniteStateMachine
116
{
117
public:
118
enum {MAX_RULES=128};
119
120
private:
121
class Rules
122
{
123
public:
124
Rules();
125
void clear();
126
const RuleEntry * begin() const;
127
const RuleEntry * end() const;
128
size_t size() const;
129
130
void accumulate_rules(const State &state);
131
132
private:
133
RuleEntry * m_begin,
134
* m_end,
135
m_rules[MAX_RULES*2];
136
};
137
138
public:
139
FiniteStateMachine(SlotMap & map, json * logger);
140
void reset(Slot * & slot, const short unsigned int max_pre_ctxt);
141
142
Rules rules;
143
SlotMap & slots;
144
json * const dbgout;
145
};
146
147
148
inline
149
FiniteStateMachine::FiniteStateMachine(SlotMap& map, json * logger)
150
: slots(map),
151
dbgout(logger)
152
{
153
}
154
155
inline
156
void FiniteStateMachine::reset(Slot * & slot, const short unsigned int max_pre_ctxt)
157
{
158
rules.clear();
159
int ctxt = 0;
160
for (; ctxt != max_pre_ctxt && slot->prev(); ++ctxt, slot = slot->prev());
161
slots.reset(*slot, ctxt);
162
}
163
164
inline
165
FiniteStateMachine::Rules::Rules()
166
: m_begin(m_rules), m_end(m_rules)
167
{
168
}
169
170
inline
171
void FiniteStateMachine::Rules::clear()
172
{
173
m_end = m_begin;
174
}
175
176
inline
177
const RuleEntry * FiniteStateMachine::Rules::begin() const
178
{
179
return m_begin;
180
}
181
182
inline
183
const RuleEntry * FiniteStateMachine::Rules::end() const
184
{
185
return m_end;
186
}
187
188
inline
189
size_t FiniteStateMachine::Rules::size() const
190
{
191
return m_end - m_begin;
192
}
193
194
inline
195
void FiniteStateMachine::Rules::accumulate_rules(const State &state)
196
{
197
// Only bother if there are rules in the State object.
198
if (state.empty()) return;
199
200
// Merge the new sorted rules list into the current sorted result set.
201
const RuleEntry * lre = begin(), * rre = state.rules;
202
RuleEntry * out = m_rules + (m_begin == m_rules)*MAX_RULES;
203
const RuleEntry * const lrend = out + MAX_RULES,
204
* const rrend = state.rules_end;
205
m_begin = out;
206
while (lre != end() && out != lrend)
207
{
208
if (*lre < *rre) *out++ = *lre++;
209
else if (*rre < *lre) { *out++ = *rre++; }
210
else { *out++ = *lre++; ++rre; }
211
212
if (rre == rrend)
213
{
214
while (lre != end() && out != lrend) { *out++ = *lre++; }
215
m_end = out;
216
return;
217
}
218
}
219
while (rre != rrend && out != lrend) { *out++ = *rre++; }
220
m_end = out;
221
}
222
223
inline
224
SlotMap::SlotMap(Segment & seg, uint8 direction, size_t maxSize)
225
: segment(seg), m_size(0), m_precontext(0), m_highwater(0),
226
m_maxSize(int(maxSize)), m_dir(direction), m_highpassed(false)
227
{
228
m_slot_map[0] = 0;
229
}
230
231
inline
232
Slot * * SlotMap::begin()
233
{
234
return &m_slot_map[1]; // allow map to go 1 before slot_map when inserting
235
// at start of segment.
236
}
237
238
inline
239
Slot * * SlotMap::end()
240
{
241
return m_slot_map + m_size + 1;
242
}
243
244
inline
245
size_t SlotMap::size() const
246
{
247
return m_size;
248
}
249
250
inline
251
short unsigned int SlotMap::context() const
252
{
253
return m_precontext;
254
}
255
256
inline
257
void SlotMap::reset(Slot & slot, short unsigned int ctxt)
258
{
259
m_size = 0;
260
m_precontext = ctxt;
261
*m_slot_map = slot.prev();
262
}
263
264
inline
265
void SlotMap::pushSlot(Slot*const slot)
266
{
267
m_slot_map[++m_size] = slot;
268
}
269
270
inline
271
Slot * const & SlotMap::operator[](int n) const
272
{
273
return m_slot_map[n + 1];
274
}
275
276
inline
277
Slot * & SlotMap::operator[](int n)
278
{
279
return m_slot_map[n + 1];
280
}
281
282
} // namespace graphite2
283
284