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
23using namespace boost::iostreams;
24using namespace boost::iostreams::test;
25using boost::unit_test::test_suite;
26namespace io = boost::iostreams;
27
28// Note: The filter is given an internal buffer -- unnecessary in this simple
29// case -- to stress test symmetric_filter.
30struct 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
81typedef symmetric_filter<toupper_symmetric_filter_impl>
82 toupper_symmetric_filter;
83
84void 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
95void 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
106void 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
137struct 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
150typedef symmetric_filter<wcopy_filter_impl> wcopy_filter;
151
152void 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
170test_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

source code of boost/libs/iostreams/test/symmetric_filter_test.cpp