1 | // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) |
2 | // (C) Copyright 2004-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/iostreams/detail/buffer.hpp> |
9 | #include <boost/iostreams/device/file.hpp> |
10 | #include <boost/iostreams/filter/symmetric.hpp> |
11 | #include <boost/iostreams/filter/test.hpp> |
12 | #include <boost/test/test_tools.hpp> |
13 | #include <boost/test/unit_test.hpp> |
14 | #include "detail/closable.hpp" |
15 | #include "./detail/constants.hpp" |
16 | #include "detail/operation_sequence.hpp" |
17 | #include "./detail/temp_file.hpp" |
18 | #include "./detail/verification.hpp" |
19 | |
20 | // Must come last. |
21 | #include <boost/iostreams/detail/config/disable_warnings.hpp> |
22 | |
23 | using namespace boost::iostreams; |
24 | using namespace boost::iostreams::test; |
25 | using boost::unit_test::test_suite; |
26 | namespace io = boost::iostreams; |
27 | |
28 | // Note: The filter is given an internal buffer -- unnecessary in this simple |
29 | // case -- to stress test symmetric_filter. |
30 | struct toupper_symmetric_filter_impl { |
31 | typedef char char_type; |
32 | explicit toupper_symmetric_filter_impl( |
33 | std::streamsize buffer_size = |
34 | default_filter_buffer_size |
35 | ) |
36 | : buf_(buffer_size) |
37 | { |
38 | buf_.set(ptr: 0, end: 0); |
39 | } |
40 | bool filter( const char*& src_begin, const char* src_end, |
41 | char*& dest_begin, char* dest_end, bool /* flush */ ) |
42 | { |
43 | while ( can_read(src_begin, src_end) || |
44 | can_write(dest_begin, dest_end) ) |
45 | { |
46 | if (can_read(src_begin, src_end)) |
47 | read(src_begin, src_end); |
48 | if (can_write(dest_begin, dest_end)) |
49 | write(dest_begin, dest_end); |
50 | } |
51 | bool result = buf_.ptr() != buf_.eptr(); |
52 | return result; |
53 | } |
54 | void close() { buf_.set(ptr: 0, end: 0); } |
55 | void read(const char*& src_begin, const char* src_end) |
56 | { |
57 | std::ptrdiff_t count = |
58 | (std::min) ( a: src_end - src_begin, |
59 | b: static_cast<std::ptrdiff_t>(buf_.size()) - |
60 | (buf_.eptr() - buf_.data()) ); |
61 | while (count-- > 0) |
62 | *buf_.eptr()++ = std::toupper(c: *src_begin++); |
63 | } |
64 | void write(char*& dest_begin, char* dest_end) |
65 | { |
66 | std::ptrdiff_t count = |
67 | (std::min) ( a: dest_end - dest_begin, |
68 | b: buf_.eptr() - buf_.ptr() ); |
69 | while (count-- > 0) |
70 | *dest_begin++ = *buf_.ptr()++; |
71 | if (buf_.ptr() == buf_.eptr()) |
72 | buf_.set(ptr: 0, end: 0); |
73 | } |
74 | bool can_read(const char*& src_begin, const char* src_end) |
75 | { return src_begin != src_end && buf_.eptr() != buf_.end(); } |
76 | bool can_write(char*& dest_begin, char* dest_end) |
77 | { return dest_begin != dest_end && buf_.ptr() != buf_.eptr(); } |
78 | boost::iostreams::detail::buffer<char> buf_; |
79 | }; |
80 | |
81 | typedef symmetric_filter<toupper_symmetric_filter_impl> |
82 | toupper_symmetric_filter; |
83 | |
84 | void read_symmetric_filter() |
85 | { |
86 | test_file test; |
87 | uppercase_file upper; |
88 | BOOST_CHECK( |
89 | test_input_filter( toupper_symmetric_filter(default_filter_buffer_size), |
90 | file_source(test.name(), in_mode), |
91 | file_source(upper.name(), in_mode) ) |
92 | ); |
93 | } |
94 | |
95 | void write_symmetric_filter() |
96 | { |
97 | test_file test; |
98 | uppercase_file upper; |
99 | BOOST_CHECK( |
100 | test_output_filter( toupper_symmetric_filter(default_filter_buffer_size), |
101 | file_source(test.name(), in_mode), |
102 | file_source(upper.name(), in_mode) ) |
103 | ); |
104 | } |
105 | |
106 | void close_symmetric_filter() |
107 | { |
108 | // Test input |
109 | { |
110 | operation_sequence seq; |
111 | chain<input> ch; |
112 | ch.push( |
113 | t: io::symmetric_filter<closable_symmetric_filter> |
114 | (1, seq.new_operation(id: 2)) |
115 | ); |
116 | ch.push(t: closable_device<input>(seq.new_operation(id: 1))); |
117 | BOOST_CHECK_NO_THROW(ch.reset()); |
118 | BOOST_CHECK_OPERATION_SEQUENCE(seq); |
119 | } |
120 | |
121 | // Test output |
122 | { |
123 | operation_sequence seq; |
124 | chain<output> ch; |
125 | ch.push( |
126 | t: io::symmetric_filter<closable_symmetric_filter> |
127 | (1, seq.new_operation(id: 1)) |
128 | ); |
129 | ch.push(t: closable_device<output>(seq.new_operation(id: 2))); |
130 | BOOST_CHECK_NO_THROW(ch.reset()); |
131 | BOOST_CHECK_OPERATION_SEQUENCE(seq); |
132 | } |
133 | } |
134 | |
135 | #ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS |
136 | |
137 | struct wcopy_filter_impl { |
138 | typedef wchar_t char_type; |
139 | bool filter( const wchar_t*& src_begin, const wchar_t* src_end, |
140 | wchar_t*& dest_begin, wchar_t* dest_end, bool /* flush */ ) |
141 | { |
142 | if(src_begin != src_end && dest_begin != dest_end) { |
143 | *dest_begin++ = *src_begin++; |
144 | } |
145 | return false; |
146 | } |
147 | void close() {} |
148 | }; |
149 | |
150 | typedef symmetric_filter<wcopy_filter_impl> wcopy_filter; |
151 | |
152 | void wide_symmetric_filter() |
153 | { |
154 | { |
155 | warray_source src(wide_data(), wide_data() + data_length()); |
156 | std::wstring dest; |
157 | io::copy(src, snk: io::compose(filter: wcopy_filter(16), fod: io::back_inserter(cnt&: dest))); |
158 | BOOST_CHECK(dest == wide_data()); |
159 | } |
160 | { |
161 | warray_source src(wide_data(), wide_data() + data_length()); |
162 | std::wstring dest; |
163 | io::copy(src: io::compose(filter: wcopy_filter(16), fod: src), snk: io::back_inserter(cnt&: dest)); |
164 | BOOST_CHECK(dest == wide_data()); |
165 | } |
166 | } |
167 | |
168 | #endif |
169 | |
170 | test_suite* init_unit_test_suite(int, char* []) |
171 | { |
172 | test_suite* test = BOOST_TEST_SUITE("symmetric_filter test" ); |
173 | test->add(BOOST_TEST_CASE(&read_symmetric_filter)); |
174 | test->add(BOOST_TEST_CASE(&write_symmetric_filter)); |
175 | test->add(BOOST_TEST_CASE(&close_symmetric_filter)); |
176 | #ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS |
177 | test->add(BOOST_TEST_CASE(&wide_symmetric_filter)); |
178 | #endif |
179 | return test; |
180 | } |
181 | |
182 | #include <boost/iostreams/detail/config/enable_warnings.hpp> |
183 | |