1 /*=============================================================================
2     Copyright (c) 2001-2003 Daniel Nuffer
3     http://spirit.sourceforge.net/
4 
5     Use, modification and distribution is subject to the Boost Software
6     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7     http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 #include <boost/spirit/include/classic_multi_pass.hpp>
10 #include <boost/scoped_ptr.hpp>
11 #include <iterator>
12 #include <string>
13 #include <boost/detail/lightweight_test.hpp>
14 #include "impl/sstream.hpp"
15 
16 using namespace std;
17 using namespace BOOST_SPIRIT_CLASSIC_NS;
18 
19 sstream_t res;
20 
21 typedef multi_pass<istream_iterator<char> > default_multi_pass_t;
22 
23 typedef look_ahead<istream_iterator<char>, 6> fixed_multi_pass_t;
24 
25 typedef multi_pass<
26     istream_iterator<char>,
27     multi_pass_policies::input_iterator,
28     multi_pass_policies::first_owner,
29     multi_pass_policies::buf_id_check,
30     multi_pass_policies::std_deque
31 > first_owner_multi_pass_t;
32 
33 
34 // a functor to test out the functor_multi_pass
35 class my_functor
36 {
37     public:
38         typedef char result_type;
my_functor()39         my_functor()
40             : c('A')
41         {}
42 
operator ()()43         char operator()()
44         {
45             if (c == 'M')
46                 return eof;
47             else
48                 return c++;
49         }
50 
51         static result_type eof;
52     private:
53         char c;
54 };
55 
56 my_functor::result_type my_functor::eof = '\0';
57 
58 typedef multi_pass<
59     my_functor,
60     multi_pass_policies::functor_input,
61     multi_pass_policies::first_owner,
62     multi_pass_policies::no_check,
63     multi_pass_policies::std_deque
64 > functor_multi_pass_t;
65 
test_default_multi_pass()66 void test_default_multi_pass()
67 {
68     res << "-*= test_default_multi_pass =*-\n";
69     istream_iterator<char> end;
70     boost::scoped_ptr<default_multi_pass_t> mpend(new default_multi_pass_t(end));
71 
72     {
73         sstream_t ss;
74         ss << "test string";
75 
76         istream_iterator<char> a(ss);
77         boost::scoped_ptr<default_multi_pass_t> mp1(new default_multi_pass_t(a));
78 
79         while (*mp1 != *mpend)
80         {
81             res << *((*mp1)++);
82         }
83 
84         res << endl;
85     }
86 
87     {
88         sstream_t ss;
89         ss << "test string";
90         istream_iterator<char> b(ss);
91         boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(b));
92         boost::scoped_ptr<default_multi_pass_t> mp3(new default_multi_pass_t(b));
93         *mp3 = *mp2;
94 
95         for (int i = 0; i < 4; ++i)
96         {
97             res << **mp2;
98             ++*mp2;
99         }
100 
101         mp3.reset();
102 
103         while (*mp2 != *mpend)
104         {
105             res << **mp2;
106             ++*mp2;
107         }
108 
109         res << endl;
110     }
111 
112     {
113         sstream_t ss;
114         ss << "test string";
115         istream_iterator<char> a(ss);
116         boost::scoped_ptr<default_multi_pass_t> mp1(new default_multi_pass_t(a));
117         boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(*mp1));
118 
119         for (int i = 0; i < 4; ++i)
120         {
121             res << **mp1;
122             ++*mp1;
123         }
124 
125         while (*mp2 != *mpend)
126         {
127             res << **mp2;
128             ++*mp2;
129         }
130 
131         while (*mp1 != *mpend)
132         {
133             res << **mp1;
134             ++*mp1;
135         }
136 
137         res << endl;
138     }
139 
140     {
141         sstream_t ss;
142         ss << "test string";
143         istream_iterator<char> b(ss);
144         boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(b));
145         boost::scoped_ptr<default_multi_pass_t> mp3(new default_multi_pass_t(b));
146         *mp3 = *mp2;
147 
148         for (int i = 0; i < 4; ++i)
149         {
150             res << **mp2;
151             ++*mp2;
152         }
153 
154         mp3.reset();
155         ++*mp2;
156 
157         while (*mp2 != *mpend)
158         {
159             res << **mp2;
160             ++*mp2;
161         }
162 
163         res << endl;
164     }
165 
166     {
167         sstream_t ss;
168         ss << "test string";
169         istream_iterator<char> a(ss);
170         boost::scoped_ptr<default_multi_pass_t> mp1(new default_multi_pass_t(a));
171         boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(*mp1));
172 
173         BOOST_TEST(*mp1 == *mp2);
174         BOOST_TEST(*mp1 >= *mp2);
175         BOOST_TEST(*mp1 <= *mp2);
176         for (int i = 0; i < 4; ++i)
177         {
178             res << **mp1;
179             ++*mp1;
180         }
181 
182         BOOST_TEST(*mp1 != *mp2);
183         BOOST_TEST(*mp1 > *mp2);
184         BOOST_TEST(*mp1 >= *mp2);
185         BOOST_TEST(*mp2 < *mp1);
186         BOOST_TEST(*mp2 <= *mp1);
187         while (*mp2 != *mp1)
188         {
189             res << **mp2;
190             ++*mp2;
191         }
192 
193         BOOST_TEST(*mp1 == *mp2);
194         BOOST_TEST(*mp1 >= *mp2);
195         BOOST_TEST(*mp1 <= *mp2);
196         while (*mp1 != *mpend)
197         {
198             res << **mp1;
199             ++*mp1;
200         }
201 
202         BOOST_TEST(*mp1 != *mp2);
203         BOOST_TEST(*mp1 > *mp2);
204         BOOST_TEST(*mp1 >= *mp2);
205         BOOST_TEST(*mp2 < *mp1);
206         BOOST_TEST(*mp2 <= *mp1);
207         while (*mp2 != *mpend)
208         {
209             res << **mp2;
210             ++*mp2;
211         }
212 
213         BOOST_TEST(*mp1 == *mp2);
214         BOOST_TEST(*mp1 >= *mp2);
215         BOOST_TEST(*mp1 <= *mp2);
216         res << endl;
217     }
218 
219     {
220         sstream_t ss;
221         ss << "test string";
222         istream_iterator<char> a(ss);
223         boost::scoped_ptr<default_multi_pass_t> mp1(new default_multi_pass_t(a));
224         boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(a));
225         BOOST_TEST(*mp1 != *mp2);
226         ++*mp1;
227         BOOST_TEST(*mp1 != *mp2);
228 
229     }
230 
231     {
232         sstream_t ss;
233         ss << "test string";
234         istream_iterator<char> b(ss);
235         boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(b));
236         boost::scoped_ptr<default_multi_pass_t> mp3(new default_multi_pass_t(b));
237         *mp3 = *mp2;
238 
239         for (int i = 0; i < 4; ++i)
240         {
241             res << **mp2;
242             ++*mp2;
243         }
244 
245         mp2->clear_queue();
246 
247         while (*mp2 != *mpend)
248         {
249             res << **mp2;
250             ++*mp2;
251         }
252 
253         try
254         {
255             res << **mp3; // this should throw illegal_backtracking
256             BOOST_TEST(0);
257         }
258         catch (const BOOST_SPIRIT_CLASSIC_NS::multi_pass_policies::illegal_backtracking& /*e*/)
259         {
260         }
261         res << endl;
262     }
263 
264 
265 }
266 
test_fixed_multi_pass()267 void test_fixed_multi_pass()
268 {
269     res << "-*= test_fixed_multi_pass =*-\n";
270     istream_iterator<char> end;
271     boost::scoped_ptr<fixed_multi_pass_t> mpend(new fixed_multi_pass_t(end));
272 
273     {
274         sstream_t ss;
275         ss << "test string";
276 
277         istream_iterator<char> a(ss);
278         boost::scoped_ptr<fixed_multi_pass_t> mp1(new fixed_multi_pass_t(a));
279 
280         while (*mp1 != *mpend)
281         {
282             res << *((*mp1)++);
283         }
284 
285         res << endl;
286     }
287 
288     {
289         sstream_t ss;
290         ss << "test string";
291         istream_iterator<char> b(ss);
292         boost::scoped_ptr<fixed_multi_pass_t> mp2(new fixed_multi_pass_t(b));
293         boost::scoped_ptr<fixed_multi_pass_t> mp3(new fixed_multi_pass_t(*mp2));
294 
295         for (int i = 0; i < 4; ++i)
296         {
297             res << **mp2;
298             ++*mp2;
299         }
300 
301         mp3.reset();
302 
303         while (*mp2 != *mpend)
304         {
305             res << **mp2;
306             ++*mp2;
307         }
308 
309         res << endl;
310     }
311 
312     {
313         sstream_t ss;
314         ss << "test string";
315         istream_iterator<char> a(ss);
316         boost::scoped_ptr<fixed_multi_pass_t> mp1(new fixed_multi_pass_t(a));
317         boost::scoped_ptr<fixed_multi_pass_t> mp2(new fixed_multi_pass_t(*mp1));
318 
319         for (int i = 0; i < 4; ++i)
320         {
321             res << **mp1;
322             ++*mp1;
323         }
324 
325         while (*mp2 != *mpend)
326         {
327             res << **mp2;
328             ++*mp2;
329         }
330 
331         while (*mp1 != *mpend)
332         {
333             res << **mp1;
334             ++*mp1;
335         }
336 
337         res << endl;
338     }
339 
340     {
341         sstream_t ss;
342         ss << "test string";
343         istream_iterator<char> b(ss);
344         boost::scoped_ptr<fixed_multi_pass_t> mp2(new fixed_multi_pass_t(b));
345         boost::scoped_ptr<fixed_multi_pass_t> mp3(new fixed_multi_pass_t(*mp2));
346 
347         for (int i = 0; i < 4; ++i)
348         {
349             res << **mp2;
350             ++*mp2;
351         }
352 
353         mp3.reset();
354         ++*mp2;
355 
356         while (*mp2 != *mpend)
357         {
358             res << **mp2;
359             ++*mp2;
360         }
361 
362         res << endl;
363     }
364 
365     {
366         sstream_t ss;
367         ss << "test string";
368         istream_iterator<char> a(ss);
369         boost::scoped_ptr<fixed_multi_pass_t> mp1(new fixed_multi_pass_t(a));
370         boost::scoped_ptr<fixed_multi_pass_t> mp2(new fixed_multi_pass_t(*mp1));
371 
372         BOOST_TEST(*mp1 == *mp2);
373         BOOST_TEST(*mp1 >= *mp2);
374         BOOST_TEST(*mp1 <= *mp2);
375         for (int i = 0; i < 4; ++i)
376         {
377             res << **mp1;
378             ++*mp1;
379         }
380 
381         BOOST_TEST(*mp1 != *mp2);
382         BOOST_TEST(*mp1 > *mp2);
383         BOOST_TEST(*mp1 >= *mp2);
384         BOOST_TEST(*mp2 < *mp1);
385         BOOST_TEST(*mp2 <= *mp1);
386         while (*mp2 != *mp1)
387         {
388             res << **mp2;
389             ++*mp2;
390         }
391 
392         BOOST_TEST(*mp1 == *mp2);
393         BOOST_TEST(*mp1 >= *mp2);
394         BOOST_TEST(*mp1 <= *mp2);
395         while (*mp1 != *mpend)
396         {
397             res << **mp1;
398             ++*mp1;
399         }
400 
401         BOOST_TEST(*mp1 != *mp2);
402         BOOST_TEST(*mp1 > *mp2);
403         BOOST_TEST(*mp1 >= *mp2);
404         BOOST_TEST(*mp2 < *mp1);
405         BOOST_TEST(*mp2 <= *mp1);
406         while (*mp2 != *mpend)
407         {
408             res << **mp2;
409             ++*mp2;
410         }
411 
412         BOOST_TEST(*mp1 == *mp2);
413         BOOST_TEST(*mp1 >= *mp2);
414         BOOST_TEST(*mp1 <= *mp2);
415         res << endl;
416     }
417 
418     {
419         sstream_t ss;
420         ss << "test string";
421         istream_iterator<char> a(ss);
422         boost::scoped_ptr<fixed_multi_pass_t> mp1(new fixed_multi_pass_t(a));
423         boost::scoped_ptr<fixed_multi_pass_t> mp2(new fixed_multi_pass_t(a));
424         BOOST_TEST(*mp1 != *mp2);
425         ++*mp1;
426         BOOST_TEST(*mp1 != *mp2);
427 
428     }
429 
430 }
431 
test_first_owner_multi_pass()432 void test_first_owner_multi_pass()
433 {
434     res << "-*= test_first_owner_multi_pass =*-\n";
435     istream_iterator<char> end;
436     boost::scoped_ptr<first_owner_multi_pass_t> mpend(new first_owner_multi_pass_t(end));
437 
438     {
439         sstream_t ss;
440         ss << "test string";
441 
442         istream_iterator<char> a(ss);
443         boost::scoped_ptr<first_owner_multi_pass_t> mp1(new first_owner_multi_pass_t(a));
444 
445         while (*mp1 != *mpend)
446         {
447             res << *((*mp1)++);
448         }
449 
450         res << endl;
451     }
452 
453     {
454         sstream_t ss;
455         ss << "test string";
456         istream_iterator<char> b(ss);
457         boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(b));
458         boost::scoped_ptr<first_owner_multi_pass_t> mp3(new first_owner_multi_pass_t(*mp2));
459 
460         for (int i = 0; i < 4; ++i)
461         {
462             res << **mp2;
463             ++*mp2;
464         }
465 
466         mp3.reset();
467 
468         while (*mp2 != *mpend)
469         {
470             res << **mp2;
471             ++*mp2;
472         }
473 
474         res << endl;
475     }
476 
477     {
478         sstream_t ss;
479         ss << "test string";
480         istream_iterator<char> a(ss);
481         boost::scoped_ptr<first_owner_multi_pass_t> mp1(new first_owner_multi_pass_t(a));
482         boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(*mp1));
483 
484         for (int i = 0; i < 4; ++i)
485         {
486             res << **mp1;
487             ++*mp1;
488         }
489 
490         while (*mp2 != *mpend)
491         {
492             res << **mp2;
493             ++*mp2;
494         }
495 
496         while (*mp1 != *mpend)
497         {
498             res << **mp1;
499             ++*mp1;
500         }
501 
502         res << endl;
503     }
504 
505     {
506         sstream_t ss;
507         ss << "test string";
508         istream_iterator<char> b(ss);
509         boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(b));
510         boost::scoped_ptr<first_owner_multi_pass_t> mp3(new first_owner_multi_pass_t(*mp2));
511 
512         for (int i = 0; i < 4; ++i)
513         {
514             res << **mp2;
515             ++*mp2;
516         }
517 
518         mp3.reset();
519         ++*mp2;
520 
521         while (*mp2 != *mpend)
522         {
523             res << **mp2;
524             ++*mp2;
525         }
526 
527         res << endl;
528     }
529 
530     {
531         sstream_t ss;
532         ss << "test string";
533         istream_iterator<char> a(ss);
534         boost::scoped_ptr<first_owner_multi_pass_t> mp1(new first_owner_multi_pass_t(a));
535         boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(*mp1));
536 
537         BOOST_TEST(*mp1 == *mp2);
538         BOOST_TEST(*mp1 >= *mp2);
539         BOOST_TEST(*mp1 <= *mp2);
540         for (int i = 0; i < 4; ++i)
541         {
542             res << **mp1;
543             ++*mp1;
544         }
545 
546         BOOST_TEST(*mp1 != *mp2);
547         BOOST_TEST(*mp1 > *mp2);
548         BOOST_TEST(*mp1 >= *mp2);
549         BOOST_TEST(*mp2 < *mp1);
550         BOOST_TEST(*mp2 <= *mp1);
551         while (*mp2 != *mp1)
552         {
553             res << **mp2;
554             ++*mp2;
555         }
556 
557         BOOST_TEST(*mp1 == *mp2);
558         BOOST_TEST(*mp1 >= *mp2);
559         BOOST_TEST(*mp1 <= *mp2);
560         while (*mp1 != *mpend)
561         {
562             res << **mp1;
563             ++*mp1;
564         }
565 
566         BOOST_TEST(*mp1 != *mp2);
567         BOOST_TEST(*mp1 > *mp2);
568         BOOST_TEST(*mp1 >= *mp2);
569         BOOST_TEST(*mp2 < *mp1);
570         BOOST_TEST(*mp2 <= *mp1);
571         while (*mp2 != *mpend)
572         {
573             res << **mp2;
574             ++*mp2;
575         }
576 
577         BOOST_TEST(*mp1 == *mp2);
578         BOOST_TEST(*mp1 >= *mp2);
579         BOOST_TEST(*mp1 <= *mp2);
580         res << endl;
581     }
582 
583     {
584         sstream_t ss;
585         ss << "test string";
586         istream_iterator<char> a(ss);
587         boost::scoped_ptr<first_owner_multi_pass_t> mp1(new first_owner_multi_pass_t(a));
588         boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(a));
589         BOOST_TEST(*mp1 != *mp2);
590         ++*mp1;
591         BOOST_TEST(*mp1 != *mp2);
592 
593     }
594 
595     {
596         sstream_t ss;
597         ss << "test string";
598         istream_iterator<char> b(ss);
599         boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(b));
600         boost::scoped_ptr<first_owner_multi_pass_t> mp3(new first_owner_multi_pass_t(*mp2));
601 
602         for (int i = 0; i < 4; ++i)
603         {
604             res << **mp2;
605             ++*mp2;
606         }
607 
608         mp2->clear_queue();
609 
610         while (*mp2 != *mpend)
611         {
612             res << **mp2;
613             ++*mp2;
614         }
615 
616         try
617         {
618             res << **mp3; // this should throw illegal_backtracking
619             BOOST_TEST(0);
620         }
621         catch (const BOOST_SPIRIT_CLASSIC_NS::multi_pass_policies::illegal_backtracking& /*e*/)
622         {
623         }
624         res << endl;
625     }
626 
627 }
628 
629 
test_functor_multi_pass()630 void test_functor_multi_pass()
631 {
632     res << "-*= test_functor_multi_pass =*-\n";
633     functor_multi_pass_t mpend;
634 
635     {
636         functor_multi_pass_t mp1 = functor_multi_pass_t(my_functor());
637 
638         while (mp1 != mpend)
639         {
640             res << *(mp1++);
641         }
642 
643         res << endl;
644     }
645 
646     {
647         functor_multi_pass_t mp1 = functor_multi_pass_t(my_functor());
648         functor_multi_pass_t mp2 = functor_multi_pass_t(mp1);
649 
650         for (int i = 0; i < 4; ++i)
651         {
652             res << *mp1;
653             ++mp1;
654         }
655 
656         while (mp2 != mpend)
657         {
658             res << *mp2;
659             ++mp2;
660         }
661 
662         while (mp1 != mpend)
663         {
664             res << *mp1;
665             ++mp1;
666         }
667 
668         res << endl;
669     }
670 
671     {
672         functor_multi_pass_t mp1 = functor_multi_pass_t(my_functor());
673         functor_multi_pass_t mp2 = functor_multi_pass_t(mp1);
674 
675         BOOST_TEST(mp1 == mp2);
676         BOOST_TEST(mp1 >= mp2);
677         BOOST_TEST(mp1 <= mp2);
678         for (int i = 0; i < 4; ++i)
679         {
680             res << *mp1;
681             ++mp1;
682         }
683 
684         BOOST_TEST(mp1 != mp2);
685         BOOST_TEST(mp1 > mp2);
686         BOOST_TEST(mp1 >= mp2);
687         BOOST_TEST(mp2 < mp1);
688         BOOST_TEST(mp2 <= mp1);
689         while (mp2 != mp1)
690         {
691             res << *mp2;
692             ++mp2;
693         }
694 
695         BOOST_TEST(mp1 == mp2);
696         BOOST_TEST(mp1 >= mp2);
697         BOOST_TEST(mp1 <= mp2);
698         while (mp1 != mpend)
699         {
700             res << *mp1;
701             ++mp1;
702         }
703 
704         BOOST_TEST(mp1 != mp2);
705         BOOST_TEST(mp1 > mp2);
706         BOOST_TEST(mp1 >= mp2);
707         BOOST_TEST(mp2 < mp1);
708         BOOST_TEST(mp2 <= mp1);
709         while (mp2 != mpend)
710         {
711             res << *mp2;
712             ++mp2;
713         }
714 
715         BOOST_TEST(mp1 == mp2);
716         BOOST_TEST(mp1 >= mp2);
717         BOOST_TEST(mp1 <= mp2);
718         res << endl;
719     }
720 
721     {
722         functor_multi_pass_t mp1 = functor_multi_pass_t(my_functor());
723         functor_multi_pass_t mp2 = functor_multi_pass_t(my_functor());
724         BOOST_TEST(mp1 != mp2);
725         ++mp1;
726         BOOST_TEST(mp1 != mp2);
727 
728     }
729 }
730 
main(int,char **)731 int main(int, char**)
732 {
733 
734     test_default_multi_pass();
735     test_fixed_multi_pass();
736     test_first_owner_multi_pass();
737     test_functor_multi_pass();
738 
739     BOOST_TEST(getstring(res) == "-*= test_default_multi_pass =*-\n"
740             "teststring\n"
741             "teststring\n"
742             "testteststringstring\n"
743             "testtring\n"
744             "testteststringstring\n"
745             "teststring\n"
746             "-*= test_fixed_multi_pass =*-\n"
747             "teststring\n"
748             "teststring\n"
749             "testteststringstring\n"
750             "testtring\n"
751             "testteststringstring\n"
752             "-*= test_first_owner_multi_pass =*-\n"
753             "teststring\n"
754             "teststring\n"
755             "testteststringstring\n"
756             "testtring\n"
757             "testteststringstring\n"
758             "teststring\n"
759             "-*= test_functor_multi_pass =*-\n"
760             "ABCDEFGHIJKL\n"
761             "ABCDABCDEFGHIJKLEFGHIJKL\n"
762             "ABCDABCDEFGHIJKLEFGHIJKL\n");
763 
764     return boost::report_errors();
765 }
766