Path: blob/master/thirdparty/graphite/src/inc/Rule.h
10279 views
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later1// Copyright 2011, SIL International, All rights reserved.234#pragma once56#include "inc/Code.h"7#include "inc/Slot.h"89namespace graphite2 {1011struct Rule {12const vm::Machine::Code * constraint,13* action;14unsigned short sort;15byte preContext;16#ifndef NDEBUG17uint16 rule_idx;18#endif1920Rule();21~Rule() {}2223CLASS_NEW_DELETE;2425private:26Rule(const Rule &);27Rule & operator = (const Rule &);28};2930inline31Rule::Rule()32: constraint(0),33action(0),34sort(0),35preContext(0)36{37#ifndef NDEBUG38rule_idx = 0;39#endif40}414243struct RuleEntry44{45const Rule * rule;4647inline48bool operator < (const RuleEntry &r) const49{50const unsigned short lsort = rule->sort, rsort = r.rule->sort;51return lsort > rsort || (lsort == rsort && rule < r.rule);52}5354inline55bool operator == (const RuleEntry &r) const56{57return rule == r.rule;58}59};606162struct State63{64const RuleEntry * rules,65* rules_end;6667bool empty() const;68};6970inline71bool State::empty() const72{73return rules_end == rules;74}757677class SlotMap78{79public:80enum {MAX_SLOTS=64};81SlotMap(Segment & seg, uint8 direction, size_t maxSize);8283Slot * * begin();84Slot * * end();85size_t size() const;86unsigned short context() const;87void reset(Slot &, unsigned short);8889Slot * const & operator[](int n) const;90Slot * & operator [] (int);91void pushSlot(Slot * const slot);92void collectGarbage(Slot *& aSlot);9394Slot * highwater() { return m_highwater; }95void highwater(Slot *s) { m_highwater = s; m_highpassed = false; }96bool highpassed() const { return m_highpassed; }97void highpassed(bool v) { m_highpassed = v; }9899uint8 dir() const { return m_dir; }100int decMax() { return --m_maxSize; }101102Segment & segment;103private:104Slot * m_slot_map[MAX_SLOTS+1];105unsigned short m_size;106unsigned short m_precontext;107Slot * m_highwater;108int m_maxSize;109uint8 m_dir;110bool m_highpassed;111};112113114class FiniteStateMachine115{116public:117enum {MAX_RULES=128};118119private:120class Rules121{122public:123Rules();124void clear();125const RuleEntry * begin() const;126const RuleEntry * end() const;127size_t size() const;128129void accumulate_rules(const State &state);130131private:132RuleEntry * m_begin,133* m_end,134m_rules[MAX_RULES*2];135};136137public:138FiniteStateMachine(SlotMap & map, json * logger);139void reset(Slot * & slot, const short unsigned int max_pre_ctxt);140141Rules rules;142SlotMap & slots;143json * const dbgout;144};145146147inline148FiniteStateMachine::FiniteStateMachine(SlotMap& map, json * logger)149: slots(map),150dbgout(logger)151{152}153154inline155void FiniteStateMachine::reset(Slot * & slot, const short unsigned int max_pre_ctxt)156{157rules.clear();158int ctxt = 0;159for (; ctxt != max_pre_ctxt && slot->prev(); ++ctxt, slot = slot->prev());160slots.reset(*slot, ctxt);161}162163inline164FiniteStateMachine::Rules::Rules()165: m_begin(m_rules), m_end(m_rules)166{167}168169inline170void FiniteStateMachine::Rules::clear()171{172m_end = m_begin;173}174175inline176const RuleEntry * FiniteStateMachine::Rules::begin() const177{178return m_begin;179}180181inline182const RuleEntry * FiniteStateMachine::Rules::end() const183{184return m_end;185}186187inline188size_t FiniteStateMachine::Rules::size() const189{190return m_end - m_begin;191}192193inline194void FiniteStateMachine::Rules::accumulate_rules(const State &state)195{196// Only bother if there are rules in the State object.197if (state.empty()) return;198199// Merge the new sorted rules list into the current sorted result set.200const RuleEntry * lre = begin(), * rre = state.rules;201RuleEntry * out = m_rules + (m_begin == m_rules)*MAX_RULES;202const RuleEntry * const lrend = out + MAX_RULES,203* const rrend = state.rules_end;204m_begin = out;205while (lre != end() && out != lrend)206{207if (*lre < *rre) *out++ = *lre++;208else if (*rre < *lre) { *out++ = *rre++; }209else { *out++ = *lre++; ++rre; }210211if (rre == rrend)212{213while (lre != end() && out != lrend) { *out++ = *lre++; }214m_end = out;215return;216}217}218while (rre != rrend && out != lrend) { *out++ = *rre++; }219m_end = out;220}221222inline223SlotMap::SlotMap(Segment & seg, uint8 direction, size_t maxSize)224: segment(seg), m_size(0), m_precontext(0), m_highwater(0),225m_maxSize(int(maxSize)), m_dir(direction), m_highpassed(false)226{227m_slot_map[0] = 0;228}229230inline231Slot * * SlotMap::begin()232{233return &m_slot_map[1]; // allow map to go 1 before slot_map when inserting234// at start of segment.235}236237inline238Slot * * SlotMap::end()239{240return m_slot_map + m_size + 1;241}242243inline244size_t SlotMap::size() const245{246return m_size;247}248249inline250short unsigned int SlotMap::context() const251{252return m_precontext;253}254255inline256void SlotMap::reset(Slot & slot, short unsigned int ctxt)257{258m_size = 0;259m_precontext = ctxt;260*m_slot_map = slot.prev();261}262263inline264void SlotMap::pushSlot(Slot*const slot)265{266m_slot_map[++m_size] = slot;267}268269inline270Slot * const & SlotMap::operator[](int n) const271{272return m_slot_map[n + 1];273}274275inline276Slot * & SlotMap::operator[](int n)277{278return m_slot_map[n + 1];279}280281} // namespace graphite2282283284