gfx/graphite2/src/inc/Rule.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/graphite2/src/inc/Rule.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,293 @@
     1.4 +/*  GRAPHITE2 LICENSING
     1.5 +
     1.6 +    Copyright 2011, SIL International
     1.7 +    All rights reserved.
     1.8 +
     1.9 +    This library is free software; you can redistribute it and/or modify
    1.10 +    it under the terms of the GNU Lesser General Public License as published
    1.11 +    by the Free Software Foundation; either version 2.1 of License, or
    1.12 +    (at your option) any later version.
    1.13 +
    1.14 +    This program is distributed in the hope that it will be useful,
    1.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.17 +    Lesser General Public License for more details.
    1.18 +
    1.19 +    You should also have received a copy of the GNU Lesser General Public
    1.20 +    License along with this library in the file named "LICENSE".
    1.21 +    If not, write to the Free Software Foundation, 51 Franklin Street, 
    1.22 +    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
    1.23 +    internet at http://www.fsf.org/licenses/lgpl.html.
    1.24 +
    1.25 +Alternatively, the contents of this file may be used under the terms of the
    1.26 +Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
    1.27 +License, as published by the Free Software Foundation, either version 2
    1.28 +of the License or (at your option) any later version.
    1.29 +*/
    1.30 +
    1.31 +#pragma once
    1.32 +
    1.33 +#include "inc/Code.h"
    1.34 +#include "inc/Slot.h"
    1.35 +
    1.36 +namespace graphite2 {
    1.37 +
    1.38 +struct Rule {
    1.39 +  const vm::Machine::Code * constraint, 
    1.40 +                 * action;
    1.41 +  unsigned short   sort;
    1.42 +  byte             preContext;
    1.43 +#ifndef NDEBUG
    1.44 +  uint16           rule_idx;
    1.45 +#endif
    1.46 +
    1.47 +  Rule() : constraint(0), action(0), sort(0), preContext(0) {}
    1.48 +  ~Rule();
    1.49 +
    1.50 +  CLASS_NEW_DELETE;
    1.51 +
    1.52 +private:
    1.53 +  Rule(const Rule &);
    1.54 +  Rule & operator = (const Rule &);
    1.55 +};
    1.56 +
    1.57 +inline Rule::~Rule()
    1.58 +{
    1.59 +  delete constraint;
    1.60 +  delete action;
    1.61 +}
    1.62 +
    1.63 +
    1.64 +struct RuleEntry
    1.65 +{
    1.66 +  const Rule   * rule;
    1.67 +
    1.68 +  inline
    1.69 +  bool operator < (const RuleEntry &r) const
    1.70 +  {
    1.71 +    const unsigned short lsort = rule->sort, rsort = r.rule->sort;
    1.72 +    return lsort > rsort || (lsort == rsort && rule < r.rule);
    1.73 +  }
    1.74 +
    1.75 +  inline
    1.76 +  bool operator == (const RuleEntry &r) const
    1.77 +  {
    1.78 +    return rule == r.rule;
    1.79 +  }
    1.80 +};
    1.81 +
    1.82 +
    1.83 +struct State
    1.84 +{
    1.85 +  const RuleEntry     * rules,
    1.86 +                      * rules_end;
    1.87 +  
    1.88 +  bool   empty() const;
    1.89 +};
    1.90 +
    1.91 +inline
    1.92 +bool State::empty() const
    1.93 +{
    1.94 +    return rules_end == rules;
    1.95 +}
    1.96 +
    1.97 +
    1.98 +class SlotMap
    1.99 +{
   1.100 +public:
   1.101 +  enum {MAX_SLOTS=64};
   1.102 +  SlotMap(Segment & seg);
   1.103 +  
   1.104 +  Slot       * * begin();
   1.105 +  Slot       * * end();
   1.106 +  size_t         size() const;
   1.107 +  unsigned short context() const;
   1.108 +  void           reset(Slot &, unsigned short);
   1.109 +  
   1.110 +  Slot * const & operator[](int n) const;
   1.111 +  Slot       * & operator [] (int);
   1.112 +  void           pushSlot(Slot * const slot);
   1.113 +  void           collectGarbage();
   1.114 +
   1.115 +  Slot         * highwater() { return m_highwater; }
   1.116 +  void           highwater(Slot *s) { m_highwater = s; m_highpassed = false; }
   1.117 +  bool           highpassed() const { return m_highpassed; }
   1.118 +  void           highpassed(bool v) { m_highpassed = v; }
   1.119 +
   1.120 +  Segment &    segment;
   1.121 +private:
   1.122 +  Slot         * m_slot_map[MAX_SLOTS+1];
   1.123 +  unsigned short m_size;
   1.124 +  unsigned short m_precontext;
   1.125 +  Slot         * m_highwater;
   1.126 +  bool           m_highpassed;
   1.127 +};
   1.128 +
   1.129 +
   1.130 +class FiniteStateMachine
   1.131 +{
   1.132 +public:
   1.133 +  enum {MAX_RULES=128};
   1.134 +
   1.135 +private:
   1.136 +  class Rules
   1.137 +  {
   1.138 +  public:
   1.139 +      Rules();
   1.140 +      void              clear();
   1.141 +      const RuleEntry * begin() const;
   1.142 +      const RuleEntry * end() const;
   1.143 +      size_t            size() const;
   1.144 +      
   1.145 +      void accumulate_rules(const State &state);
   1.146 +
   1.147 +  private:
   1.148 +      RuleEntry * m_begin, 
   1.149 +                * m_end,
   1.150 +                  m_rules[MAX_RULES*2];
   1.151 +  };
   1.152 +
   1.153 +public:
   1.154 +  FiniteStateMachine(SlotMap & map, json * logger);
   1.155 +  void      reset(Slot * & slot, const short unsigned int max_pre_ctxt);
   1.156 +
   1.157 +  Rules     rules;
   1.158 +  SlotMap   & slots;
   1.159 +  json    * const dbgout;
   1.160 +};
   1.161 +
   1.162 +
   1.163 +inline
   1.164 +FiniteStateMachine::FiniteStateMachine(SlotMap& map, json * logger)
   1.165 +: slots(map),
   1.166 +  dbgout(logger)
   1.167 +{
   1.168 +}
   1.169 +
   1.170 +inline
   1.171 +void FiniteStateMachine::reset(Slot * & slot, const short unsigned int max_pre_ctxt)
   1.172 +{
   1.173 +  rules.clear();
   1.174 +  int ctxt = 0;
   1.175 +  for (; ctxt != max_pre_ctxt && slot->prev(); ++ctxt, slot = slot->prev());
   1.176 +  slots.reset(*slot, ctxt);
   1.177 +}
   1.178 +
   1.179 +inline
   1.180 +FiniteStateMachine::Rules::Rules()
   1.181 +  : m_begin(m_rules), m_end(m_rules)
   1.182 +{
   1.183 +}
   1.184 +
   1.185 +inline
   1.186 +void FiniteStateMachine::Rules::clear()
   1.187 +{
   1.188 +  m_end = m_begin;
   1.189 +}
   1.190 +
   1.191 +inline
   1.192 +const RuleEntry * FiniteStateMachine::Rules::begin() const
   1.193 +{
   1.194 +  return m_begin;
   1.195 +}
   1.196 +
   1.197 +inline
   1.198 +const RuleEntry * FiniteStateMachine::Rules::end() const
   1.199 +{
   1.200 +  return m_end;
   1.201 +}
   1.202 +
   1.203 +inline
   1.204 +size_t FiniteStateMachine::Rules::size() const
   1.205 +{
   1.206 +  return m_end - m_begin;
   1.207 +}
   1.208 +
   1.209 +inline
   1.210 +void FiniteStateMachine::Rules::accumulate_rules(const State &state)
   1.211 +{
   1.212 +  // Only bother if there are rules in the State object.
   1.213 +  if (state.empty()) return;
   1.214 +  
   1.215 +  // Merge the new sorted rules list into the current sorted result set.
   1.216 +  const RuleEntry * lre = begin(), * rre = state.rules;
   1.217 +  RuleEntry * out = m_rules + (m_begin == m_rules)*MAX_RULES;    
   1.218 +  const RuleEntry * const lrend = out + MAX_RULES,
   1.219 +                  * const rrend = state.rules_end;
   1.220 +  m_begin = out; 
   1.221 +  while (lre != end() && out != lrend)
   1.222 +  {
   1.223 +    if (*lre < *rre)      *out++ = *lre++;
   1.224 +    else if (*rre < *lre) { *out++ = *rre++; }
   1.225 +    else                { *out++ = *lre++; ++rre; }
   1.226 +
   1.227 +    if (rre == rrend)
   1.228 +    { 
   1.229 +      while (lre != end() && out != lrend) { *out++ = *lre++; }
   1.230 +      m_end = out;
   1.231 +      return;
   1.232 +    }
   1.233 +  }
   1.234 +  while (rre != rrend && out != lrend) { *out++ = *rre++; }
   1.235 +  m_end = out;
   1.236 +}
   1.237 +
   1.238 +inline
   1.239 +SlotMap::SlotMap(Segment & seg)
   1.240 +: segment(seg), m_size(0), m_precontext(0), m_highwater(0), m_highpassed(false)
   1.241 +{
   1.242 +    m_slot_map[0] = 0;
   1.243 +}
   1.244 +
   1.245 +inline
   1.246 +Slot * * SlotMap::begin()
   1.247 +{
   1.248 +  return &m_slot_map[1]; // allow map to go 1 before slot_map when inserting
   1.249 +                         // at start of segment.
   1.250 +}
   1.251 +
   1.252 +inline
   1.253 +Slot * * SlotMap::end()
   1.254 +{
   1.255 +  return m_slot_map + m_size + 1;
   1.256 +}
   1.257 +
   1.258 +inline
   1.259 +size_t SlotMap::size() const
   1.260 +{
   1.261 +  return m_size;
   1.262 +}
   1.263 +
   1.264 +inline
   1.265 +short unsigned int SlotMap::context() const
   1.266 +{
   1.267 +  return m_precontext;
   1.268 +}
   1.269 +
   1.270 +inline
   1.271 +void SlotMap::reset(Slot & slot, short unsigned int ctxt)
   1.272 +{
   1.273 +  m_size = 0;
   1.274 +  m_precontext = ctxt;
   1.275 +  *m_slot_map = slot.prev();
   1.276 +}
   1.277 +
   1.278 +inline
   1.279 +void SlotMap::pushSlot(Slot*const slot)
   1.280 +{
   1.281 +  m_slot_map[++m_size] = slot;
   1.282 +}
   1.283 +
   1.284 +inline
   1.285 +Slot * const & SlotMap::operator[](int n) const
   1.286 +{
   1.287 +  return m_slot_map[n + 1];
   1.288 +}
   1.289 +
   1.290 +inline
   1.291 +Slot * & SlotMap::operator[](int n)
   1.292 +{
   1.293 +  return m_slot_map[n + 1];
   1.294 +}
   1.295 +
   1.296 +} // namespace graphite2

mercurial