diff options
Diffstat (limited to 'gfx/graphite2/src/inc/Rule.h')
-rw-r--r-- | gfx/graphite2/src/inc/Rule.h | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/gfx/graphite2/src/inc/Rule.h b/gfx/graphite2/src/inc/Rule.h new file mode 100644 index 0000000000..5964e003a6 --- /dev/null +++ b/gfx/graphite2/src/inc/Rule.h @@ -0,0 +1,305 @@ +/* GRAPHITE2 LICENSING + + Copyright 2011, SIL International + All rights reserved. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should also have received a copy of the GNU Lesser General Public + License along with this library in the file named "LICENSE". + If not, write to the Free Software Foundation, 51 Franklin Street, + Suite 500, Boston, MA 02110-1335, USA or visit their web page on the + internet at http://www.fsf.org/licenses/lgpl.html. + +Alternatively, the contents of this file may be used under the terms of the +Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public +License, as published by the Free Software Foundation, either version 2 +of the License or (at your option) any later version. +*/ + +#pragma once + +#include "inc/Code.h" +#include "inc/Slot.h" + +namespace graphite2 { + +struct Rule { + const vm::Machine::Code * constraint, + * action; + unsigned short sort; + byte preContext; +#ifndef NDEBUG + uint16 rule_idx; +#endif + + Rule(); + ~Rule() {} + + CLASS_NEW_DELETE; + +private: + Rule(const Rule &); + Rule & operator = (const Rule &); +}; + +inline +Rule::Rule() +: constraint(0), + action(0), + sort(0), + preContext(0) +{ +#ifndef NDEBUG + rule_idx = 0; +#endif +} + + +struct RuleEntry +{ + const Rule * rule; + + inline + bool operator < (const RuleEntry &r) const + { + const unsigned short lsort = rule->sort, rsort = r.rule->sort; + return lsort > rsort || (lsort == rsort && rule < r.rule); + } + + inline + bool operator == (const RuleEntry &r) const + { + return rule == r.rule; + } +}; + + +struct State +{ + const RuleEntry * rules, + * rules_end; + + bool empty() const; +}; + +inline +bool State::empty() const +{ + return rules_end == rules; +} + + +class SlotMap +{ +public: + enum {MAX_SLOTS=64}; + SlotMap(Segment & seg, uint8 direction, size_t maxSize); + + Slot * * begin(); + Slot * * end(); + size_t size() const; + unsigned short context() const; + void reset(Slot &, unsigned short); + + Slot * const & operator[](int n) const; + Slot * & operator [] (int); + void pushSlot(Slot * const slot); + void collectGarbage(Slot *& aSlot); + + Slot * highwater() { return m_highwater; } + void highwater(Slot *s) { m_highwater = s; m_highpassed = false; } + bool highpassed() const { return m_highpassed; } + void highpassed(bool v) { m_highpassed = v; } + + uint8 dir() const { return m_dir; } + int decMax() { return --m_maxSize; } + + Segment & segment; +private: + Slot * m_slot_map[MAX_SLOTS+1]; + unsigned short m_size; + unsigned short m_precontext; + Slot * m_highwater; + int m_maxSize; + uint8 m_dir; + bool m_highpassed; +}; + + +class FiniteStateMachine +{ +public: + enum {MAX_RULES=128}; + +private: + class Rules + { + public: + Rules(); + void clear(); + const RuleEntry * begin() const; + const RuleEntry * end() const; + size_t size() const; + + void accumulate_rules(const State &state); + + private: + RuleEntry * m_begin, + * m_end, + m_rules[MAX_RULES*2]; + }; + +public: + FiniteStateMachine(SlotMap & map, json * logger); + void reset(Slot * & slot, const short unsigned int max_pre_ctxt); + + Rules rules; + SlotMap & slots; + json * const dbgout; +}; + + +inline +FiniteStateMachine::FiniteStateMachine(SlotMap& map, json * logger) +: slots(map), + dbgout(logger) +{ +} + +inline +void FiniteStateMachine::reset(Slot * & slot, const short unsigned int max_pre_ctxt) +{ + rules.clear(); + int ctxt = 0; + for (; ctxt != max_pre_ctxt && slot->prev(); ++ctxt, slot = slot->prev()); + slots.reset(*slot, ctxt); +} + +inline +FiniteStateMachine::Rules::Rules() + : m_begin(m_rules), m_end(m_rules) +{ +} + +inline +void FiniteStateMachine::Rules::clear() +{ + m_end = m_begin; +} + +inline +const RuleEntry * FiniteStateMachine::Rules::begin() const +{ + return m_begin; +} + +inline +const RuleEntry * FiniteStateMachine::Rules::end() const +{ + return m_end; +} + +inline +size_t FiniteStateMachine::Rules::size() const +{ + return m_end - m_begin; +} + +inline +void FiniteStateMachine::Rules::accumulate_rules(const State &state) +{ + // Only bother if there are rules in the State object. + if (state.empty()) return; + + // Merge the new sorted rules list into the current sorted result set. + const RuleEntry * lre = begin(), * rre = state.rules; + RuleEntry * out = m_rules + (m_begin == m_rules)*MAX_RULES; + const RuleEntry * const lrend = out + MAX_RULES, + * const rrend = state.rules_end; + m_begin = out; + while (lre != end() && out != lrend) + { + if (*lre < *rre) *out++ = *lre++; + else if (*rre < *lre) { *out++ = *rre++; } + else { *out++ = *lre++; ++rre; } + + if (rre == rrend) + { + while (lre != end() && out != lrend) { *out++ = *lre++; } + m_end = out; + return; + } + } + while (rre != rrend && out != lrend) { *out++ = *rre++; } + m_end = out; +} + +inline +SlotMap::SlotMap(Segment & seg, uint8 direction, size_t maxSize) +: segment(seg), m_size(0), m_precontext(0), m_highwater(0), + m_maxSize(int(maxSize)), m_dir(direction), m_highpassed(false) +{ + m_slot_map[0] = 0; +} + +inline +Slot * * SlotMap::begin() +{ + return &m_slot_map[1]; // allow map to go 1 before slot_map when inserting + // at start of segment. +} + +inline +Slot * * SlotMap::end() +{ + return m_slot_map + m_size + 1; +} + +inline +size_t SlotMap::size() const +{ + return m_size; +} + +inline +short unsigned int SlotMap::context() const +{ + return m_precontext; +} + +inline +void SlotMap::reset(Slot & slot, short unsigned int ctxt) +{ + m_size = 0; + m_precontext = ctxt; + *m_slot_map = slot.prev(); +} + +inline +void SlotMap::pushSlot(Slot*const slot) +{ + m_slot_map[++m_size] = slot; +} + +inline +Slot * const & SlotMap::operator[](int n) const +{ + return m_slot_map[n + 1]; +} + +inline +Slot * & SlotMap::operator[](int n) +{ + return m_slot_map[n + 1]; +} + +} // namespace graphite2 |