]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/msm/doc/PDF/examples/ParsingDigits.cpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / msm / doc / PDF / examples / ParsingDigits.cpp
1 // Copyright 2010 Christophe Henry
2 // henry UNDERSCORE christophe AT hotmail DOT com
3 // This is an extended version of the state machine available in the boost::mpl library
4 // Distributed under the same license as the original.
5 // Copyright for the original version:
6 // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
7 // under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10
11 #define FUSION_MAX_VECTOR_SIZE 20
12
13 #include <boost/msm/back/state_machine.hpp>
14 #include "char_event_dispatcher.hpp"
15 #include <boost/msm/front/state_machine_def.hpp>
16 #include <boost/msm/front/functor_row.hpp>
17 #include <boost/timer.hpp>
18
19 namespace msm = boost::msm;
20 namespace mpl = boost::mpl;
21 using namespace msm::front;
22
23 #include <iostream>
24 #ifdef WIN32
25 #include "windows.h"
26 #else
27 #include <sys/time.h>
28 #endif
29
30 // events
31 struct end_sub {template <class Event> end_sub(Event const&){}};
32 struct other_char {};
33 struct default_char {};
34 struct eos {};
35
36
37 namespace test_fsm // Concrete FSM implementation
38 {
39 // Concrete FSM implementation
40 struct parsing_ : public msm::front::state_machine_def<parsing_>
41 {
42 // no need for exception handling or message queue
43 typedef int no_exception_thrown;
44 typedef int no_message_queue;
45
46 struct Waiting : public msm::front::state<>
47 {
48 // optional entry/exit methods
49 //template <class Event,class FSM>
50 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Waiting" << std::endl;}
51 //template <class Event,class FSM>
52 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Waiting" << std::endl;}
53 };
54 struct Digit1 : public msm::front::state<>
55 {
56 // optional entry/exit methods
57 //template <class Event,class FSM>
58 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit1" << std::endl;}
59 //template <class Event,class FSM>
60 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit1" << std::endl;}
61 };
62 struct Digit2 : public msm::front::state<>
63 {
64 // optional entry/exit methods
65 //template <class Event,class FSM>
66 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit2" << std::endl;}
67 //template <class Event,class FSM>
68 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit2" << std::endl;}
69 };
70 struct Digit3 : public msm::front::state<>
71 {
72 // optional entry/exit methods
73 //template <class Event,class FSM>
74 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit3" << std::endl;}
75 //template <class Event,class FSM>
76 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit3" << std::endl;}
77 };
78 struct Digit4 : public msm::front::state<>
79 {
80 // optional entry/exit methods
81 //template <class Event,class FSM>
82 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit4" << std::endl;}
83 //template <class Event,class FSM>
84 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit4" << std::endl;}
85 };
86 struct MinusChar1 : public msm::front::state<>
87 {
88 // optional entry/exit methods
89 //template <class Event,class FSM>
90 //void on_entry(Event const&,FSM& ) {std::cout << "entering: MinusChar1" << std::endl;}
91 //template <class Event,class FSM>
92 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: MinusChar1" << std::endl;}
93 };
94 struct Digit5 : public msm::front::state<>
95 {
96 // optional entry/exit methods
97 //template <class Event,class FSM>
98 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit5" << std::endl;}
99 //template <class Event,class FSM>
100 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit5" << std::endl;}
101 };
102 struct Digit6 : public msm::front::state<>
103 {
104 // optional entry/exit methods
105 //template <class Event,class FSM>
106 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit6" << std::endl;}
107 //template <class Event,class FSM>
108 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit6" << std::endl;}
109 };
110 struct Digit7 : public msm::front::state<>
111 {
112 // optional entry/exit methods
113 //template <class Event,class FSM>
114 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit7" << std::endl;}
115 //template <class Event,class FSM>
116 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit7" << std::endl;}
117 };
118 struct Digit8 : public msm::front::state<>
119 {
120 // optional entry/exit methods
121 //template <class Event,class FSM>
122 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit8" << std::endl;}
123 //template <class Event,class FSM>
124 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit8" << std::endl;}
125 };
126 struct MinusChar2 : public msm::front::state<>
127 {
128 // optional entry/exit methods
129 //template <class Event,class FSM>
130 //void on_entry(Event const&,FSM& ) {std::cout << "entering: MinusChar2" << std::endl;}
131 //template <class Event,class FSM>
132 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: MinusChar2" << std::endl;}
133 };
134 struct Digit9 : public msm::front::state<>
135 {
136 // optional entry/exit methods
137 //template <class Event,class FSM>
138 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit9" << std::endl;}
139 //template <class Event,class FSM>
140 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit9" << std::endl;}
141 };
142 struct Digit10 : public msm::front::state<>
143 {
144 // optional entry/exit methods
145 //template <class Event,class FSM>
146 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit10" << std::endl;}
147 //template <class Event,class FSM>
148 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit10" << std::endl;}
149 };
150 struct Digit11 : public msm::front::state<>
151 {
152 // optional entry/exit methods
153 //template <class Event,class FSM>
154 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit11" << std::endl;}
155 //template <class Event,class FSM>
156 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit11" << std::endl;}
157 };
158 struct Digit12 : public msm::front::state<>
159 {
160 // optional entry/exit methods
161 //template <class Event,class FSM>
162 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit12" << std::endl;}
163 //template <class Event,class FSM>
164 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit12" << std::endl;}
165 };
166 struct MinusChar3 : public msm::front::state<>
167 {
168 // optional entry/exit methods
169 //template <class Event,class FSM>
170 //void on_entry(Event const&,FSM& ) {std::cout << "entering: MinusChar3" << std::endl;}
171 //template <class Event,class FSM>
172 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: MinusChar3" << std::endl;}
173 };
174 struct Digit13 : public msm::front::state<>
175 {
176 // optional entry/exit methods
177 //template <class Event,class FSM>
178 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit13" << std::endl;}
179 //template <class Event,class FSM>
180 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit13" << std::endl;}
181 };
182 struct Digit14 : public msm::front::state<>
183 {
184 // optional entry/exit methods
185 //template <class Event,class FSM>
186 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit14" << std::endl;}
187 //template <class Event,class FSM>
188 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit14" << std::endl;}
189 };
190 struct Digit15 : public msm::front::state<>
191 {
192 // optional entry/exit methods
193 //template <class Event,class FSM>
194 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit15" << std::endl;}
195 //template <class Event,class FSM>
196 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit15" << std::endl;}
197 };
198 //struct Start : public msm::front::state<> {};
199 struct Parsed : public msm::front::state<> {};
200 //struct Failed : public msm::front::state<> {};
201
202 // the initial state of the player SM. Must be defined
203 typedef Waiting initial_state;
204 // transition actions
205 struct test_fct
206 {
207 template <class FSM,class EVT,class SourceState,class TargetState>
208 void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
209 {
210 std::cout << "Parsed!" << std::endl;
211 }
212 };
213
214 // guard conditions
215
216
217 // Transition table for parsing_
218 struct transition_table : mpl::vector<
219 // Start Event Next Action Guard
220 // +-------------+-------------------+---------+---------------------+----------------------+
221 Row < Waiting , digit , Digit1 >,
222 Row < Digit1 , digit , Digit2 >,
223 Row < Digit2 , digit , Digit3 >,
224 Row < Digit3 , digit , Digit4 >,
225 Row < Digit4 , event_char<'-'> , MinusChar1 >,
226 Row < MinusChar1 , digit , Digit5 >,
227 Row < Digit5 , digit , Digit6 >,
228 Row < Digit6 , digit , Digit7 >,
229 Row < Digit7 , digit , Digit8 >,
230 Row < Digit8 , event_char<'-'> , MinusChar2 >,
231 Row < MinusChar2 , digit , Digit9 >,
232 Row < Digit9 , digit , Digit10 >,
233 Row < Digit10 , digit , Digit11 >,
234 Row < Digit11 , digit , Digit12 >,
235 Row < Digit12 , event_char<'-'> , MinusChar3 >,
236 Row < MinusChar3 , digit , Digit13 >,
237 Row < Digit13 , digit , Digit14 >,
238 Row < Digit14 , digit , Digit15 >,
239 Row < Digit15 , eos , Parsed >,
240 Row < Parsed , eos , Waiting >
241 // +---------+-------------+---------+---------------------+----------------------+
242 > {};
243
244
245 // Replaces the default no-transition response.
246 template <class FSM,class Event>
247 void no_transition(Event const& e, FSM&,int state)
248 {
249 std::cout << "no transition from state " << state
250 << " on event " << typeid(e).name() << std::endl;
251 }
252 };
253 typedef msm::back::state_machine<parsing_> parsing;
254 }
255
256 #ifndef WIN32
257 long mtime(struct timeval& tv1,struct timeval& tv2)
258 {
259 return (tv2.tv_sec-tv1.tv_sec) *1000000 + ((tv2.tv_usec-tv1.tv_usec));
260 }
261 #endif
262
263 // This declares the statically-initialized char_event_dispatcher instance.
264 template <class Fsm>
265 const msm::back::char_event_dispatcher<Fsm>
266 msm::back::char_event_dispatcher<Fsm>::instance;
267
268 struct Parser
269 {
270 Parser():p(){p.start();}
271 void new_char(char c)
272 {
273 typedef msm::back::char_event_dispatcher<test_fsm::parsing> table;
274 table::instance.process_event(p,c);
275 }
276 void finish_string(){p.process_event(eos());}
277 void reinit(){p.process_event(eos());}
278 test_fsm::parsing p;
279 };
280
281 void msm_match(const char* input)
282 {
283 test_fsm::parsing p;
284 p.start();
285
286 int j=0;
287 while(input[j])
288 //for (size_t j=0;j<len;++j)
289 {
290 switch (input[j])
291 {
292 case '0':
293 p.process_event(char_0());
294 break;
295 case '1':
296 p.process_event(char_1());
297 break;
298 case '2':
299 p.process_event(char_2());
300 break;
301 case '3':
302 p.process_event(char_3());
303 break;
304 case '4':
305 p.process_event(char_4());
306 break;
307 case '5':
308 p.process_event(char_5());
309 break;
310 case '6':
311 p.process_event(char_6());
312 break;
313 case '7':
314 p.process_event(char_7());
315 break;
316 case '8':
317 p.process_event(char_8());
318 break;
319 case '9':
320 p.process_event(char_9());
321 break;
322 case '-':
323 p.process_event(event_char<'-'>());
324 break;
325 default:
326 p.process_event(default_char());
327 break;
328 }
329 ++j;
330 }
331 p.process_event(eos());
332 p.process_event(eos());
333 }
334
335 double time_match(const char* text)
336 {
337 boost::timer tim;
338 int iter = 1;
339 int counter, repeats;
340 double result = 0;
341 double run;
342 do
343 {
344 tim.restart();
345 for(counter = 0; counter < iter; ++counter)
346 {
347 msm_match( text);
348 }
349 result = tim.elapsed();
350 iter *= 2;
351 } while(result < 0.5);
352 iter /= 2;
353
354 // repeat test and report least value for consistency:
355 for(repeats = 0; repeats < 10; ++repeats)
356 {
357 tim.restart();
358 for(counter = 0; counter < iter; ++counter)
359 {
360 msm_match( text);
361 }
362 run = tim.elapsed();
363 result = (std::min)(run, result);
364 }
365 return result / iter;
366 }
367 int main()
368 {
369 // for timing
370 #ifdef WIN32
371 LARGE_INTEGER res;
372 ::QueryPerformanceFrequency(&res);
373 LARGE_INTEGER li,li2;
374 #else
375 struct timeval tv1,tv2;
376 gettimeofday(&tv1,NULL);
377 #endif
378
379 test_fsm::parsing p;
380 p.start();
381 const char* input = "1234-5678-1234-456";
382 size_t len = strlen(input);
383 // for timing
384 #ifdef WIN32
385 ::QueryPerformanceCounter(&li);
386 #else
387 gettimeofday(&tv1,NULL);
388 #endif
389 for (int i=0;i<1000;++i)
390 {
391 int j=0;
392 while(input[j])
393 //for (size_t j=0;j<len;++j)
394 {
395 switch (input[j])
396 {
397 case '0':
398 p.process_event(char_0());
399 break;
400 case '1':
401 p.process_event(char_1());
402 break;
403 case '2':
404 p.process_event(char_2());
405 break;
406 case '3':
407 p.process_event(char_3());
408 break;
409 case '4':
410 p.process_event(char_4());
411 break;
412 case '5':
413 p.process_event(char_5());
414 break;
415 case '6':
416 p.process_event(char_6());
417 break;
418 case '7':
419 p.process_event(char_7());
420 break;
421 case '8':
422 p.process_event(char_8());
423 break;
424 case '9':
425 p.process_event(char_9());
426 break;
427 case '-':
428 p.process_event(event_char<'-'>());
429 break;
430 default:
431 p.process_event(default_char());
432 break;
433 }
434 ++j;
435 }
436 p.process_event(eos());
437 p.process_event(eos());
438 }
439 #ifdef WIN32
440 ::QueryPerformanceCounter(&li2);
441 #else
442 gettimeofday(&tv2,NULL);
443 #endif
444 #ifdef WIN32
445 std::cout << "msm(1) took in s:" << (double)(li2.QuadPart-li.QuadPart)/res.QuadPart <<"\n" <<std::endl;
446 #else
447 std::cout << "msm(1) took in us:" << mtime(tv1,tv2) <<"\n" <<std::endl;
448 #endif
449
450 Parser parse;
451 // for timing
452 #ifdef WIN32
453 ::QueryPerformanceCounter(&li);
454 #else
455 gettimeofday(&tv1,NULL);
456 #endif
457 for (int i=0;i<1000;++i)
458 {
459 for (size_t j=0;j<len;++j)
460 {
461 parse.new_char(input[j]);
462 }
463 parse.finish_string();
464 parse.reinit();
465 }
466 #ifdef WIN32
467 ::QueryPerformanceCounter(&li2);
468 #else
469 gettimeofday(&tv2,NULL);
470 #endif
471 #ifdef WIN32
472 std::cout << "msm(2) took in s:" << (double)(li2.QuadPart-li.QuadPart)/res.QuadPart <<"\n" <<std::endl;
473 #else
474 std::cout << "msm(2) took in us:" << mtime(tv1,tv2) <<"\n" <<std::endl;
475 #endif
476 std::cout << "msm(3) took in s:" << time_match(input) <<"\n" <<std::endl;
477 return 0;
478 }
479