File: ParsingDigits.cpp

package info (click to toggle)
boost1.74 1.74.0-9
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 464,084 kB
  • sloc: cpp: 3,338,324; xml: 131,293; python: 33,088; ansic: 14,336; asm: 4,034; sh: 3,351; makefile: 1,193; perl: 1,036; yacc: 478; php: 212; ruby: 102; lisp: 24; sql: 13; csh: 6
file content (479 lines) | stat: -rw-r--r-- 17,992 bytes parent folder | download | duplicates (18)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
// Copyright 2010 Christophe Henry
// henry UNDERSCORE christophe AT hotmail DOT com
// This is an extended version of the state machine available in the boost::mpl library
// Distributed under the same license as the original.
// Copyright for the original version:
// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
// under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#define FUSION_MAX_VECTOR_SIZE 20

#include <boost/msm/back/state_machine.hpp>
#include "char_event_dispatcher.hpp"
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#include <boost/timer.hpp>

namespace msm = boost::msm;
namespace mpl = boost::mpl;
using namespace msm::front;

#include <iostream>
#ifdef WIN32
#include "windows.h"
#else
#include <sys/time.h>
#endif

// events
struct end_sub {template <class Event> end_sub(Event const&){}};
struct other_char {};
struct default_char {};
struct eos {};


namespace test_fsm // Concrete FSM implementation
{
    // Concrete FSM implementation 
    struct parsing_ : public msm::front::state_machine_def<parsing_>
    {
        // no need for exception handling or message queue
        typedef int no_exception_thrown;
        typedef int no_message_queue;

        struct Waiting : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Waiting" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Waiting" << std::endl;}
        };
        struct Digit1 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit1" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit1" << std::endl;}
        };
        struct Digit2 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit2" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit2" << std::endl;}
        };
        struct Digit3 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit3" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit3" << std::endl;}
        };
        struct Digit4 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit4" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit4" << std::endl;}
        };
        struct MinusChar1 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: MinusChar1" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: MinusChar1" << std::endl;}
        };
        struct Digit5 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit5" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit5" << std::endl;}
        };
        struct Digit6 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit6" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit6" << std::endl;}
        };
        struct Digit7 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit7" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit7" << std::endl;}
        };
        struct Digit8 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit8" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit8" << std::endl;}
        };
        struct MinusChar2 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: MinusChar2" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: MinusChar2" << std::endl;}
        };
        struct Digit9 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit9" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit9" << std::endl;}
        };
        struct Digit10 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit10" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit10" << std::endl;}
        };
        struct Digit11 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit11" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit11" << std::endl;}
        };
        struct Digit12 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit12" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit12" << std::endl;}
        };
        struct MinusChar3 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: MinusChar3" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: MinusChar3" << std::endl;}
        };
        struct Digit13 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit13" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit13" << std::endl;}
        };
        struct Digit14 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit14" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit14" << std::endl;}
        };
        struct Digit15 : public msm::front::state<>  
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit15" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit15" << std::endl;}
        };
        //struct Start : public msm::front::state<> {};
        struct Parsed : public msm::front::state<> {};
        //struct Failed : public msm::front::state<> {};

        // the initial state of the player SM. Must be defined
        typedef Waiting initial_state;
        // transition actions
        struct test_fct
        {
            template <class FSM,class EVT,class SourceState,class TargetState>
            void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
            {
                std::cout << "Parsed!" << std::endl;
            }
        };

        // guard conditions


        // Transition table for parsing_
        struct transition_table : mpl::vector<
            //    Start         Event                Next      Action                Guard
            //    +-------------+-------------------+---------+---------------------+----------------------+
              Row < Waiting     , digit             , Digit1                                                >,
              Row < Digit1      , digit             , Digit2                                                >,
              Row < Digit2      , digit             , Digit3                                                >,
              Row < Digit3      , digit             , Digit4                                                >,
              Row < Digit4      , event_char<'-'>   , MinusChar1                                            >,
              Row < MinusChar1  , digit             , Digit5                                                >,
              Row < Digit5      , digit             , Digit6                                                >,
              Row < Digit6      , digit             , Digit7                                                >,
              Row < Digit7      , digit             , Digit8                                                >,
              Row < Digit8      , event_char<'-'>   , MinusChar2                                            >,
              Row < MinusChar2  , digit             , Digit9                                                >,
              Row < Digit9      , digit             , Digit10                                               >,
              Row < Digit10     , digit             , Digit11                                               >,
              Row < Digit11     , digit             , Digit12                                               >,
              Row < Digit12     , event_char<'-'>   , MinusChar3                                            >,
              Row < MinusChar3  , digit             , Digit13                                               >,
              Row < Digit13     , digit             , Digit14                                               >,
              Row < Digit14     , digit             , Digit15                                               >,
              Row < Digit15     , eos               , Parsed                                                >,
              Row < Parsed      , eos               , Waiting                                               >
            //    +---------+-------------+---------+---------------------+----------------------+
        > {};


        // Replaces the default no-transition response.
        template <class FSM,class Event>
        void no_transition(Event const& e, FSM&,int state)
        {
            std::cout << "no transition from state " << state
                << " on event " << typeid(e).name() << std::endl;
        }
    };
    typedef msm::back::state_machine<parsing_> parsing;
}

#ifndef WIN32
long mtime(struct timeval& tv1,struct timeval& tv2)
{
    return (tv2.tv_sec-tv1.tv_sec) *1000000 + ((tv2.tv_usec-tv1.tv_usec));
}
#endif

// This declares the statically-initialized char_event_dispatcher instance.
template <class Fsm>
const msm::back::char_event_dispatcher<Fsm>
msm::back::char_event_dispatcher<Fsm>::instance;

struct Parser
{
    Parser():p(){p.start();}
    void new_char(char c)
    {
        typedef msm::back::char_event_dispatcher<test_fsm::parsing> table;
        table::instance.process_event(p,c);
    }
    void finish_string(){p.process_event(eos());}
    void reinit(){p.process_event(eos());}
    test_fsm::parsing p;
};

void msm_match(const char* input)
{
    test_fsm::parsing p;
    p.start();

    int j=0;
    while(input[j])
        //for (size_t j=0;j<len;++j)
    {
        switch (input[j])
        {
        case '0':
            p.process_event(char_0());
            break;
        case '1':
            p.process_event(char_1());
            break;
        case '2':
            p.process_event(char_2());
            break;
        case '3':
            p.process_event(char_3());
            break;
        case '4':
            p.process_event(char_4());
            break;
        case '5':
            p.process_event(char_5());
            break;
        case '6':
            p.process_event(char_6());
            break;
        case '7':
            p.process_event(char_7());
            break;
        case '8':
            p.process_event(char_8());
            break;
        case '9':
            p.process_event(char_9());
            break;
        case '-':
            p.process_event(event_char<'-'>());
            break;
        default:
            p.process_event(default_char());
            break;
        }
        ++j;
    }
    p.process_event(eos());
    p.process_event(eos());
}

double time_match(const char* text)
{
    boost::timer tim;
    int iter = 1;
    int counter, repeats;
    double result = 0;
    double run;
    do
    {
        tim.restart();
        for(counter = 0; counter < iter; ++counter)
        {
            msm_match( text);
        }
        result = tim.elapsed();
        iter *= 2;
    } while(result < 0.5);
    iter /= 2;

    // repeat test and report least value for consistency:
    for(repeats = 0; repeats < 10; ++repeats)
    {
        tim.restart();
        for(counter = 0; counter < iter; ++counter)
        {
            msm_match( text);
        }
        run = tim.elapsed();
        result = (std::min)(run, result);
    }
    return result / iter;
}
int main()
{
    // for timing
#ifdef WIN32
    LARGE_INTEGER res;
    ::QueryPerformanceFrequency(&res);
    LARGE_INTEGER li,li2;
#else
    struct timeval tv1,tv2;
    gettimeofday(&tv1,NULL);
#endif

    test_fsm::parsing p;
    p.start();
    const char* input = "1234-5678-1234-456";
    size_t len = strlen(input);
    // for timing
#ifdef WIN32
    ::QueryPerformanceCounter(&li);
#else
    gettimeofday(&tv1,NULL);
#endif
    for (int i=0;i<1000;++i)
    {
        int j=0;
        while(input[j])
        //for (size_t j=0;j<len;++j)
        {
            switch (input[j])
            {
            case '0':
                p.process_event(char_0());
                break;
            case '1':
                p.process_event(char_1());
                break;
            case '2':
                p.process_event(char_2());
                break;
            case '3':
                p.process_event(char_3());
                break;
            case '4':
                p.process_event(char_4());
                break;
            case '5':
                p.process_event(char_5());
                break;
            case '6':
                p.process_event(char_6());
                break;
            case '7':
                p.process_event(char_7());
                break;
            case '8':
                p.process_event(char_8());
                break;
            case '9':
                p.process_event(char_9());
                break;
            case '-':
                p.process_event(event_char<'-'>());
                break;
            default:
                p.process_event(default_char());
                break;
            }
            ++j;
        }
        p.process_event(eos());
        p.process_event(eos());
    }
#ifdef WIN32
    ::QueryPerformanceCounter(&li2);
#else
    gettimeofday(&tv2,NULL);
#endif
#ifdef WIN32
    std::cout << "msm(1) took in s:" << (double)(li2.QuadPart-li.QuadPart)/res.QuadPart <<"\n" <<std::endl;
#else
    std::cout << "msm(1) took in us:" <<  mtime(tv1,tv2) <<"\n" <<std::endl;
#endif

    Parser parse;
    // for timing
#ifdef WIN32
    ::QueryPerformanceCounter(&li);
#else
    gettimeofday(&tv1,NULL);
#endif
    for (int i=0;i<1000;++i)
    {
        for (size_t j=0;j<len;++j)
        {
            parse.new_char(input[j]);
        }
        parse.finish_string();
        parse.reinit();
    }
#ifdef WIN32
    ::QueryPerformanceCounter(&li2);
#else
    gettimeofday(&tv2,NULL);
#endif
#ifdef WIN32
    std::cout << "msm(2) took in s:" << (double)(li2.QuadPart-li.QuadPart)/res.QuadPart <<"\n" <<std::endl;
#else
    std::cout << "msm(2) took in us:" <<  mtime(tv1,tv2) <<"\n" <<std::endl;
#endif
    std::cout << "msm(3) took in s:" << time_match(input) <<"\n" <<std::endl;
    return 0;
}