Flow123d  release_2.2.0-914-gf1a3a4f
finite_state_filter.hpp
Go to the documentation of this file.
1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2005-2007 Jonathan Turkanis
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
5 
6 // See http://www.boost.org/libs/iostreams for documentation.
7 
8 // Adapted from an example of James Kanze, with suggestions from Peter Dimov.
9 // See http://www.gabi-soft.fr/codebase-en.html.
10 
11 #ifndef BOOST_IOSTREAMS_FINITE_STATE_FILTER_HPP_INCLUDED
12 #define BOOST_IOSTREAMS_FINITE_STATE_FILTER_HPP_INCLUDED
13 
14 #include <cassert>
15 #include <cstdio> // EOF.
16 #include <iostream> // cin, cout.
17 #include <locale>
18 #include <string>
19 #include <boost/config.hpp> // JOIN, member template friends.
20 #include <boost/detail/workaround.hpp>
21 #include <boost/iostreams/categories.hpp>
22 #include <boost/iostreams/char_traits.hpp>
23 #include <boost/iostreams/checked_operations.hpp> // put_if.
24 #include <boost/iostreams/concepts.hpp>
25 #include <boost/iostreams/detail/ios.hpp> // openmode.
26 #include <boost/iostreams/filter/stdio.hpp>
27 #include <boost/iostreams/operations.hpp>
28 #include <boost/mpl/begin_end.hpp>
29 #include <boost/mpl/deref.hpp>
30 #include <boost/preprocessor/control/expr_if.hpp>
31 #include <boost/static_assert.hpp>
32 #include <boost/type_traits/is_base_and_derived.hpp>
33 
34 namespace boost { namespace iostreams {
35 
36 //------------------Definition of basic character classes---------------------//
37 
39 
40  static const int initial_state = 0;
41 
42  // All-inclusive character class.
43 
44  struct is_any {
45  template<typename Ch>
46  static bool test(Ch, const std::locale&) { return true; }
47  };
48 
49  // Locale-sensitive character classes.
50 
51  #define BOOST_IOSTREAMS_CHARACTER_CLASS(class) \
52  struct BOOST_JOIN(is_, class) { \
53  template<typename Ch> \
54  static bool test(Ch event, const std::locale& loc) \
55  { return std::BOOST_JOIN(is, class)(event, loc); } \
56  }; \
57  /**/
58 
70 
71  #undef BOOST_IOSTREAMS_CHARACTER_CLASS
72 };
73 
74 template<typename Ch>
76  template<Ch C>
77  struct is {
78  static bool test(Ch event, const std::locale&)
79  {
80  return event == C;
81  }
82  };
83 };
84 
85 //------------------Definition of base class for finite state filters---------//
86 
87 namespace detail {
88 
89 template<typename FiniteStateMachine>
91 
92 } // End namespace detail.
93 
94 template<typename Derived, typename Ch = char>
96 public:
97  typedef Ch char_type;
99  void imbue(const std::locale& loc) { loc_ = loc; }
100  const std::locale& getloc() const { return loc_; }
101 protected:
102  finite_state_machine() : off_(0) { }
103 
104  // Template whose instantiations make up transition table.
105 
106  template< int State,
107  typename CharacterClass,
108  int NextState,
109  void (Derived::*Action)(char_type) >
110  struct row {
111  typedef CharacterClass character_class;
112  static const int state = State;
113  static const int next_state = NextState;
114  static void execute(Derived& d, char_type event)
115  {
116  (d.*Action)(event);
117  }
118  };
119 
120  // Stack interface.
121 
122  bool empty() const
123  {
124  return off_ == buf_.size();
125  }
126  void push(char c) { buf_ += c; }
127  char_type pop()
128  {
129  char_type result = buf_[off_++];
130  if (off_ == buf_.size())
131  clear();
132  return result;
133  }
134  char_type& top() { return buf_[off_]; }
135  void clear()
136  {
137  buf_.clear();
138  off_ = 0;
139  }
140 
141  // Default event handlers.
142 
143  void on_eof() { }
144  void skip(char_type) { }
145 
146 #if BOOST_WORKAROUND(__MWERKS__, <= 0x3206)
147  template<typename Ch>
148  void _push_impl(Ch c) { push(c); }
149 #endif
150 
151 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
152  template<typename FiniteStateFilter>
154 #else
155  public:
156 #endif
157  void on_any(char_type) { }
158 private:
159  typedef std::basic_string<char_type> string_type;
160  typedef typename string_type::size_type size_type;
161  std::locale loc_;
162  string_type buf_;
163  size_type off_;
164 };
165 
166 #if !BOOST_WORKAROUND(__MWERKS__, <= 0x3206)
167 # define BOOST_IOSTREAMS_FSM(fsm) \
168  template<typename Ch> \
169  void push(Ch c) \
170  { ::boost::iostreams::finite_state_machine<fsm, Ch>::push(c); } \
171  template<typename Ch> \
172  void skip(Ch c) { (void) c; } \
173  /**/
174 #else // #ifndef __MWERKS__
175 # define BOOST_IOSTREAMS_FSM(fsm) \
176  void push(char c) { this->_push_impl(c); } \
177  void push(wchar_t c) { this->_push_impl(c); } \
178  void skip(char c) { (void) c; } \
179  void skip(wchar_t c) { (void) c; } \
180  /**/
181 #endif
182 
183 //------------------Definition of finite_state_filter_impl--------------------//
184 
185 namespace detail {
186 
187 template<typename FiniteStateMachine>
188 class finite_state_filter_impl : public FiniteStateMachine
189 {
190 private:
191  template<typename First, typename Last>
193 public:
194  typedef typename char_type_of<FiniteStateMachine>::type char_type;
195 
196  finite_state_filter_impl() : state_(FiniteStateMachine::initial_state) { }
197 
198  template<typename T0>
199  explicit finite_state_filter_impl(const T0& t0)
200  : FiniteStateMachine(t0), state_(FiniteStateMachine::initial_state)
201  { }
202 
203  template<typename T0, typename T1>
204  finite_state_filter_impl(const T0& t0, const T1& t1)
205  : FiniteStateMachine(t0, t1), state_(FiniteStateMachine::initial_state)
206  { }
207 
208  template<typename T0, typename T1, typename T2>
209  finite_state_filter_impl(const T0& t0, const T1& t1, const T2& t2)
210  : FiniteStateMachine(t0, t1, t2),
211  state_(FiniteStateMachine::initial_state)
212  { }
213 protected:
214  void process_event(char_type c)
215  {
216  typedef typename FiniteStateMachine::transition_table transitions;
217  typedef typename mpl::begin<transitions>::type first;
218  typedef typename mpl::end<transitions>::type last;
219  state_ = process_event_impl<first, last>::execute(*this, state_, c);
220  }
221  int& state() { return state_; }
222  void reset()
223  {
224  state_ = FiniteStateMachine::initial_state;
225  this->clear();
226  }
227 private:
228  template<typename First, typename Last>
229  struct process_event_impl {
230  static int execute(FiniteStateMachine& fsm, int state, char_type event)
231  {
232  typedef typename mpl::deref<First>::type rule;
233  typedef typename mpl::next<First>::type next;
234  typedef typename rule::character_class character_class;
235 
236  if ( state == rule::state &&
237  character_class::test(event, fsm.getloc()) )
238  {
239  // Rule applies.
240  rule::execute(fsm, event);
241  return rule::next_state;
242  }
243 
244  // Rule is inapplicable: try next rule.
245  return process_event_impl<next, Last>::execute(fsm, state, event);
246  }
247  };
248 
249  template<typename Last>
251  static int execute(FiniteStateMachine& fsm, int state, char_type c)
252  {
253  on_any(fsm, c);
254  return state;
255  }
256  };
257 #if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) /* Tru64 */ \
258  || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) /* CW9.4 */
259  public:
260 #endif
261  template<typename FSM>
262  static void on_any(FSM& fsm, char_type c) { fsm.on_any(c); }
263 private:
264  int state_;
265 };
266 
267 } // End namespace detail.
268 
269 //------------------Definition of finite_state_filter-------------------------//
270 
271 template<typename FiniteStateMachine>
274 {
275 private:
277 public:
278  typedef typename base_type::char_type char_type;
279  typedef char_traits<char_type> traits_type;
280  typedef typename base_type::int_type int_type;
281  struct category
282  : dual_use, filter_tag, closable_tag, localizable_tag
283  { };
284 
285  finite_state_filter() : flags_(0) { }
286 
287  template<typename T0>
288  finite_state_filter(const T0& t0)
289  : base_type(t0), flags_(0)
290  { }
291 
292  template<typename T0, typename T1>
293  finite_state_filter(const T0& t0, const T1& t1)
294  : base_type(t0, t1), flags_(0)
295  { }
296 
297  template<typename T0, typename T1, typename T2>
298  finite_state_filter(const T0& t0, const T1& t1, const T2& t2)
299  : base_type(t0, t1, t2), flags_(0)
300  { }
301 
302  template<typename Source>
303  int_type get(Source& src)
304  {
305  assert((flags_ & f_write) == 0);
306  flags_ |= f_read;
307 
308  while (true) {
309  if ((flags_ & f_eof) == 0) {
310 
311  // Read a character and process it.
312  int_type c;
313  if (traits_type::is_eof(c = iostreams::get(src))) {
314  flags_ |= f_eof;
315  this->on_eof();
316  } else if (!traits_type::would_block(c)) {
317  this->process_event(c);
318  }
319  }
320 
321  // Return a character, if available.
322  if (!this->empty())
323  return this->pop();
324  else if ((flags_ & f_eof) != 0)
325  return traits_type::eof();
326  }
327  }
328 
329  template<typename Sink>
330  bool put(Sink& dest, char_type c)
331  {
332  assert((flags_ & f_read) == 0);
333  flags_ |= f_write;
334 
335  this->process_event(c);
336  while (!this->empty() && iostreams::put(dest, this->top()))
337  this->pop();
338 
339  return true;
340  }
341 
342  template<typename Device>
343  void close(Device& dev, BOOST_IOS::openmode which)
344  {
345  if (which == BOOST_IOS::out) {
346  if (flags_ & f_write)
347  while (!this->empty())
348  iostreams::put_if(dev, this->pop());
349  this->reset();
350  flags_ = 0;
351  }
352  }
353 private:
354  enum flags {
355  f_read = 1,
356  f_write = f_read << 1,
357  f_eof = f_write << 1
358  };
359 
360  int flags_;
361 };
362 
363 } } // End namespaces iostreams, boost.
364 
365 #endif // #ifndef BOOST_IOSTREAMS_FINITE_STATE_FILTER_HPP_INCLUDED
static bool test(Ch event, const std::locale &)
void close(Device &dev, BOOST_IOS::openmode which)
FMT_API void print(std::FILE *f, CStringRef format_str, ArgList args)
Definition: format.cc:489
finite_state_filter(const T0 &t0, const T1 &t1, const T2 &t2)
detail::finite_state_filter_impl< FiniteStateMachine > base_type
finite_state_filter_impl(const T0 &t0, const T1 &t1, const T2 &t2)
char_type_of< FiniteStateMachine >::type char_type
std::basic_string< char_type > string_type
#define BOOST_IOSTREAMS_CHARACTER_CLASS(class)
finite_state_filter(const T0 &t0, const T1 &t1)
static void execute(Derived &d, char_type event)
static int execute(FiniteStateMachine &fsm, int state, char_type event)