Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* GRAPHITE2 LICENSING
3 Copyright 2011, SIL International
4 All rights reserved.
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should also have received a copy of the GNU Lesser General Public
17 License along with this library in the file named "LICENSE".
18 If not, write to the Free Software Foundation, 51 Franklin Street,
19 Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
20 internet at http://www.fsf.org/licenses/lgpl.html.
22 Alternatively, the contents of this file may be used under the terms of the
23 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
24 License, as published by the Free Software Foundation, either version 2
25 of the License or (at your option) any later version.
26 */
28 #pragma once
30 #include "inc/Code.h"
31 #include "inc/Slot.h"
33 namespace graphite2 {
35 struct Rule {
36 const vm::Machine::Code * constraint,
37 * action;
38 unsigned short sort;
39 byte preContext;
40 #ifndef NDEBUG
41 uint16 rule_idx;
42 #endif
44 Rule() : constraint(0), action(0), sort(0), preContext(0) {}
45 ~Rule();
47 CLASS_NEW_DELETE;
49 private:
50 Rule(const Rule &);
51 Rule & operator = (const Rule &);
52 };
54 inline Rule::~Rule()
55 {
56 delete constraint;
57 delete action;
58 }
61 struct RuleEntry
62 {
63 const Rule * rule;
65 inline
66 bool operator < (const RuleEntry &r) const
67 {
68 const unsigned short lsort = rule->sort, rsort = r.rule->sort;
69 return lsort > rsort || (lsort == rsort && rule < r.rule);
70 }
72 inline
73 bool operator == (const RuleEntry &r) const
74 {
75 return rule == r.rule;
76 }
77 };
80 struct State
81 {
82 const RuleEntry * rules,
83 * rules_end;
85 bool empty() const;
86 };
88 inline
89 bool State::empty() const
90 {
91 return rules_end == rules;
92 }
95 class SlotMap
96 {
97 public:
98 enum {MAX_SLOTS=64};
99 SlotMap(Segment & seg);
101 Slot * * begin();
102 Slot * * end();
103 size_t size() const;
104 unsigned short context() const;
105 void reset(Slot &, unsigned short);
107 Slot * const & operator[](int n) const;
108 Slot * & operator [] (int);
109 void pushSlot(Slot * const slot);
110 void collectGarbage();
112 Slot * highwater() { return m_highwater; }
113 void highwater(Slot *s) { m_highwater = s; m_highpassed = false; }
114 bool highpassed() const { return m_highpassed; }
115 void highpassed(bool v) { m_highpassed = v; }
117 Segment & segment;
118 private:
119 Slot * m_slot_map[MAX_SLOTS+1];
120 unsigned short m_size;
121 unsigned short m_precontext;
122 Slot * m_highwater;
123 bool m_highpassed;
124 };
127 class FiniteStateMachine
128 {
129 public:
130 enum {MAX_RULES=128};
132 private:
133 class Rules
134 {
135 public:
136 Rules();
137 void clear();
138 const RuleEntry * begin() const;
139 const RuleEntry * end() const;
140 size_t size() const;
142 void accumulate_rules(const State &state);
144 private:
145 RuleEntry * m_begin,
146 * m_end,
147 m_rules[MAX_RULES*2];
148 };
150 public:
151 FiniteStateMachine(SlotMap & map, json * logger);
152 void reset(Slot * & slot, const short unsigned int max_pre_ctxt);
154 Rules rules;
155 SlotMap & slots;
156 json * const dbgout;
157 };
160 inline
161 FiniteStateMachine::FiniteStateMachine(SlotMap& map, json * logger)
162 : slots(map),
163 dbgout(logger)
164 {
165 }
167 inline
168 void FiniteStateMachine::reset(Slot * & slot, const short unsigned int max_pre_ctxt)
169 {
170 rules.clear();
171 int ctxt = 0;
172 for (; ctxt != max_pre_ctxt && slot->prev(); ++ctxt, slot = slot->prev());
173 slots.reset(*slot, ctxt);
174 }
176 inline
177 FiniteStateMachine::Rules::Rules()
178 : m_begin(m_rules), m_end(m_rules)
179 {
180 }
182 inline
183 void FiniteStateMachine::Rules::clear()
184 {
185 m_end = m_begin;
186 }
188 inline
189 const RuleEntry * FiniteStateMachine::Rules::begin() const
190 {
191 return m_begin;
192 }
194 inline
195 const RuleEntry * FiniteStateMachine::Rules::end() const
196 {
197 return m_end;
198 }
200 inline
201 size_t FiniteStateMachine::Rules::size() const
202 {
203 return m_end - m_begin;
204 }
206 inline
207 void FiniteStateMachine::Rules::accumulate_rules(const State &state)
208 {
209 // Only bother if there are rules in the State object.
210 if (state.empty()) return;
212 // Merge the new sorted rules list into the current sorted result set.
213 const RuleEntry * lre = begin(), * rre = state.rules;
214 RuleEntry * out = m_rules + (m_begin == m_rules)*MAX_RULES;
215 const RuleEntry * const lrend = out + MAX_RULES,
216 * const rrend = state.rules_end;
217 m_begin = out;
218 while (lre != end() && out != lrend)
219 {
220 if (*lre < *rre) *out++ = *lre++;
221 else if (*rre < *lre) { *out++ = *rre++; }
222 else { *out++ = *lre++; ++rre; }
224 if (rre == rrend)
225 {
226 while (lre != end() && out != lrend) { *out++ = *lre++; }
227 m_end = out;
228 return;
229 }
230 }
231 while (rre != rrend && out != lrend) { *out++ = *rre++; }
232 m_end = out;
233 }
235 inline
236 SlotMap::SlotMap(Segment & seg)
237 : segment(seg), m_size(0), m_precontext(0), m_highwater(0), m_highpassed(false)
238 {
239 m_slot_map[0] = 0;
240 }
242 inline
243 Slot * * SlotMap::begin()
244 {
245 return &m_slot_map[1]; // allow map to go 1 before slot_map when inserting
246 // at start of segment.
247 }
249 inline
250 Slot * * SlotMap::end()
251 {
252 return m_slot_map + m_size + 1;
253 }
255 inline
256 size_t SlotMap::size() const
257 {
258 return m_size;
259 }
261 inline
262 short unsigned int SlotMap::context() const
263 {
264 return m_precontext;
265 }
267 inline
268 void SlotMap::reset(Slot & slot, short unsigned int ctxt)
269 {
270 m_size = 0;
271 m_precontext = ctxt;
272 *m_slot_map = slot.prev();
273 }
275 inline
276 void SlotMap::pushSlot(Slot*const slot)
277 {
278 m_slot_map[++m_size] = slot;
279 }
281 inline
282 Slot * const & SlotMap::operator[](int n) const
283 {
284 return m_slot_map[n + 1];
285 }
287 inline
288 Slot * & SlotMap::operator[](int n)
289 {
290 return m_slot_map[n + 1];
291 }
293 } // namespace graphite2