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 #include <boost/config.hpp>
9 #ifdef BOOST_NO_STD_LOCALE
10 # error std::locale not supported on this platform
11 #else
12 
13 # include <map>
14 # include <boost/iostreams/detail/ios.hpp>  // failure.
15 # include <boost/iostreams/filter/test.hpp>
16 # include <boost/mpl/vector.hpp>
17 # include <boost/test/test_tools.hpp>
18 # include <boost/test/unit_test.hpp>
19 # include "../example/finite_state_filter.hpp"
20 
21 using boost::unit_test::test_suite;
22 namespace io = boost::iostreams;
23 
24 const std::string posix = // 'unix' is sometimes a macro.
25     "When I was one-and-twenty\n"
26     "I heard a wise man say,\n"
27     "'Give crowns and pounds and guineas\n"
28     "But not your heart away;\n"
29     "\n"
30     "Give pearls away and rubies\n"
31     "But keep your fancy free.'\n"
32     "But I was one-and-twenty,\n"
33     "No use to talk to me.\n"
34     "\n"
35     "When I was one-and-twenty\n"
36     "I heard him say again,\n"
37     "'The heart out of the bosom\n"
38     "Was never given in vain;\n"
39     "'Tis paid with sighs a plenty\n"
40     "And sold for endless rue.'\n"
41     "And I am two-and-twenty,\n"
42     "And oh, 'tis true, 'tis true.";
43 
44 const std::string dos =
45     "When I was one-and-twenty\r\n"
46     "I heard a wise man say,\r\n"
47     "'Give crowns and pounds and guineas\r\n"
48     "But not your heart away;\r\n"
49     "\r\n"
50     "Give pearls away and rubies\r\n"
51     "But keep your fancy free.'\r\n"
52     "But I was one-and-twenty,\r\n"
53     "No use to talk to me.\r\n"
54     "\r\n"
55     "When I was one-and-twenty\r\n"
56     "I heard him say again,\r\n"
57     "'The heart out of the bosom\r\n"
58     "Was never given in vain;\r\n"
59     "'Tis paid with sighs a plenty\r\n"
60     "And sold for endless rue.'\r\n"
61     "And I am two-and-twenty,\r\n"
62     "And oh, 'tis true, 'tis true.";
63 
64 const std::string comments =
65     "When I was /*one-and-twenty\n"
66     "I he*/ard a wise/ man say,\n"
67     "'Give cr//*owns *and po**/unds and guineas\n"
68     "But n*/ot yo*/ur he/*a*/rt /**/away;\n";
69 
70 const std::string no_comments =
71     "When I was "
72     "ard a wise/ man say,\n"
73     "'Give cr/unds and guineas\n"
74     "But n*/ot yo*/ur hert away;\n";
75 
76 struct identity_fsm
77     : io::finite_state_machine<identity_fsm, char>
78 {
on_anyidentity_fsm79     void on_any(char c) { push(c); }
80     typedef boost::mpl::vector0<> transition_table;
81 };
82 
83 struct dos2unix_fsm : io::finite_state_machine<dos2unix_fsm> {
84     BOOST_IOSTREAMS_FSM(dos2unix_fsm) // Define skip and push.
85     typedef dos2unix_fsm self;
86     typedef boost::mpl::vector<
87                 row<initial_state, is<'\r'>, initial_state, &self::skip>,
88                 row<initial_state, is_any,   initial_state, &self::push>
89             > transition_table;
90 };
91 
92 struct unix2dos_fsm : io::finite_state_machine<unix2dos_fsm> {
93     BOOST_IOSTREAMS_FSM(unix2dos_fsm) // Define skip and push.
94     typedef unix2dos_fsm self;
95 
on_lfunix2dos_fsm96     void on_lf(char) { push('\r'); push('\n'); }
97 
98     typedef boost::mpl::vector<
99                 row<initial_state, is<'\n'>, initial_state, &self::on_lf>,
100                 row<initial_state, is_any,   initial_state, &self::push>
101             > transition_table;
102 };
103 
104 struct uncommenting_fsm : io::finite_state_machine<uncommenting_fsm> {
105     BOOST_IOSTREAMS_FSM(uncommenting_fsm) // Define skip and push.
106     typedef uncommenting_fsm self;
107 
108     static const int no_comment   = initial_state;
109     static const int pre_comment  = no_comment + 1;
110     static const int comment      = pre_comment + 1;
111     static const int post_comment = comment + 1;
112 
push_slashuncommenting_fsm113     void push_slash(char c) { push('/'); push(c); }
114 
115     typedef boost::mpl::vector<
116                 row<no_comment,   is<'/'>, pre_comment,  &self::skip>,
117                 row<no_comment,   is_any,  no_comment,   &self::push>,
118                 row<pre_comment,  is<'*'>, comment,      &self::skip>,
119                 row<pre_comment,  is<'/'>, pre_comment,  &self::push>,
120                 row<pre_comment,  is_any,  no_comment,   &self::push_slash>,
121                 row<comment,      is<'*'>, post_comment, &self::skip>,
122                 row<comment,      is_any,  comment,      &self::skip>,
123                 row<post_comment, is<'/'>, no_comment,   &self::skip>,
124                 row<post_comment, is<'*'>, post_comment, &self::skip>,
125                 row<post_comment, is_any,  comment,      &self::skip>
126             > transition_table;
127 };
128 
finite_state_filter_test()129 void finite_state_filter_test()
130 {
131     using namespace std;
132 
133     typedef io::finite_state_filter<identity_fsm>      identity_filter;
134     typedef io::finite_state_filter<dos2unix_fsm>      dos2unix_filter;
135     typedef io::finite_state_filter<unix2dos_fsm>      unix2dos_filter;
136     typedef io::finite_state_filter<uncommenting_fsm>  uncommenting_filter;
137 
138         // Test identity_filter.
139 
140     BOOST_CHECK(
141         io::test_input_filter(identity_filter(), dos, dos)
142     );
143     BOOST_CHECK(
144         io::test_output_filter(identity_filter(), dos, dos)
145     );
146 
147         // Test dos2unix_filter.
148 
149     BOOST_CHECK(
150         io::test_input_filter(dos2unix_filter(), dos, posix)
151     );
152     BOOST_CHECK(
153         io::test_output_filter(dos2unix_filter(), dos, posix)
154     );
155 
156         // Test unix2dos_filter.
157 
158     BOOST_CHECK(
159         io::test_input_filter(unix2dos_filter(), posix, dos)
160     );
161     BOOST_CHECK(
162         io::test_output_filter(unix2dos_filter(), posix, dos)
163     );
164 
165         // Test uncommenting_filter.
166 
167     BOOST_CHECK(
168         io::test_input_filter(uncommenting_filter(), comments, no_comments)
169     );
170     BOOST_CHECK(
171         io::test_output_filter(uncommenting_filter(), comments, no_comments)
172     );
173 }
174 
init_unit_test_suite(int,char * [])175 test_suite* init_unit_test_suite(int, char* [])
176 {
177     test_suite* test = BOOST_TEST_SUITE("example test");
178     test->add(BOOST_TEST_CASE(&finite_state_filter_test));
179     return test;
180 }
181 
182 #endif // #ifdef BOOST_NO_STD_LOCALE //---------------------------------------//
183