gfx/graphite2/src/inc/Rule.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial