]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/iostreams/filter/test.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / iostreams / filter / test.hpp
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 #ifndef BOOST_IOSTREAMS_FILTER_TEST_HPP_INCLUDED
9
10 #if defined(_MSC_VER)
11 # pragma once
12 #endif
13
14 #include <boost/config.hpp> // BOOST_MSVC,put size_t in std.
15 #include <boost/detail/workaround.hpp>
16 #include <algorithm> // min.
17 #include <cstddef> // size_t.
18 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) || \
19 BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
20 /**/
21 # include <cstdlib> // rand.
22 #endif
23 #include <cstring> // memcpy, strlen.
24 #include <iterator>
25 #include <string>
26 #include <vector>
27 #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) && \
28 !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
29 /**/
30 # include <boost/random/linear_congruential.hpp>
31 # include <boost/random/uniform_smallint.hpp>
32 #endif
33 #include <boost/iostreams/categories.hpp>
34 #include <boost/iostreams/compose.hpp>
35 #include <boost/iostreams/copy.hpp>
36 #include <boost/iostreams/detail/bool_trait_def.hpp>
37 #include <boost/iostreams/detail/ios.hpp>
38 #include <boost/iostreams/device/array.hpp>
39 #include <boost/iostreams/device/back_inserter.hpp>
40 #include <boost/iostreams/operations.hpp>
41 #include <boost/mpl/bool.hpp>
42 #include <boost/type_traits/is_array.hpp>
43 #include <boost/type_traits/is_same.hpp>
44
45 #undef memcpy
46 #undef rand
47 #undef strlen
48
49 #if defined(BOOST_NO_STDC_NAMESPACE) && !defined(__LIBCOMO__)
50 namespace std {
51 using ::memcpy;
52 using ::strlen;
53 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) || \
54 BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
55 /**/
56 using ::rand;
57 #endif
58 }
59 #endif
60
61 namespace boost { namespace iostreams {
62
63 BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_string, std::basic_string, 3)
64
65 const std::streamsize default_increment = 5;
66
67 #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) && \
68 !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
69 /**/
70 std::streamsize rand(std::streamsize inc)
71 {
72 static rand48 random_gen;
73 static uniform_smallint<int> random_dist(0, static_cast<int>(inc));
74 return random_dist(random_gen);
75 }
76 #else
77 std::streamsize rand(std::streamsize inc)
78 {
79 return (std::rand() * inc + 1) / RAND_MAX;
80 }
81 #endif
82
83 class non_blocking_source {
84 public:
85 typedef char char_type;
86 struct category
87 : source_tag,
88 peekable_tag
89 { };
90 explicit non_blocking_source( const std::string& data,
91 std::streamsize inc = default_increment )
92 : data_(data), inc_(inc), pos_(0)
93 { }
94 std::streamsize read(char* s, std::streamsize n)
95 {
96 using namespace std;
97 if (pos_ == static_cast<streamsize>(data_.size()))
98 return -1;
99 streamsize avail =
100 (std::min) (n, static_cast<streamsize>(data_.size() - pos_));
101 streamsize amt = (std::min) (rand(inc_), avail);
102 if (amt)
103 memcpy(s, data_.c_str() + pos_, static_cast<size_t>(amt));
104 pos_ += amt;
105 return amt;
106 }
107
108 bool putback(char c)
109 {
110 if (pos_ > 0) {
111 data_[static_cast<std::string::size_type>(--pos_)] = c;
112 return true;
113 }
114 return false;
115 }
116 private:
117 std::string data_;
118 std::streamsize inc_, pos_;
119 };
120
121 class non_blocking_sink : public sink {
122 public:
123 non_blocking_sink( std::string& dest,
124 std::streamsize inc = default_increment )
125 : dest_(dest), inc_(inc)
126 { }
127 std::streamsize write(const char* s, std::streamsize n)
128 {
129 std::streamsize amt = (std::min) (rand(inc_), n);
130 dest_.insert(dest_.end(), s, s + amt);
131 return amt;
132 }
133 private:
134 non_blocking_sink& operator=(const non_blocking_sink&);
135 std::string& dest_;
136 std::streamsize inc_;
137 };
138
139 //--------------Definition of test_input_filter-------------------------------//
140
141 template<typename Filter>
142 bool test_input_filter( Filter filter,
143 const std::string& input,
144 const std::string& output,
145 mpl::true_ )
146 {
147 for ( int inc = default_increment;
148 inc < default_increment * 40;
149 inc += default_increment )
150 {
151 non_blocking_source src(input, inc);
152 std::string dest;
153 iostreams::copy(compose(filter, src), iostreams::back_inserter(dest));
154 if (dest != output)
155 return false;
156 }
157 return true;
158 }
159
160 template<typename Filter, typename Source1, typename Source2>
161 bool test_input_filter( Filter filter,
162 const Source1& input,
163 const Source2& output,
164 mpl::false_ )
165 {
166 std::string in;
167 std::string out;
168 iostreams::copy(input, iostreams::back_inserter(in));
169 iostreams::copy(output, iostreams::back_inserter(out));
170 return test_input_filter(filter, in, out);
171 }
172
173 template<typename Filter, typename Source1, typename Source2>
174 bool test_input_filter( Filter filter,
175 const Source1& input,
176 const Source2& output )
177 {
178 // Use tag dispatch to compensate for bad overload resolution.
179 return test_input_filter( filter, input, output,
180 is_string<Source1>() );
181 }
182
183 //--------------Definition of test_output_filter------------------------------//
184
185 template<typename Filter>
186 bool test_output_filter( Filter filter,
187 const std::string& input,
188 const std::string& output,
189 mpl::true_ )
190 {
191 for ( int inc = default_increment;
192 inc < default_increment * 40;
193 inc += default_increment )
194 {
195 array_source src(input.data(), input.data() + input.size());
196 std::string dest;
197 iostreams::copy(src, compose(filter, non_blocking_sink(dest, inc)));
198 if (dest != output )
199 return false;
200 }
201 return true;
202 }
203
204 template<typename Filter, typename Source1, typename Source2>
205 bool test_output_filter( Filter filter,
206 const Source1& input,
207 const Source2& output,
208 mpl::false_ )
209 {
210 std::string in;
211 std::string out;
212 iostreams::copy(input, iostreams::back_inserter(in));
213 iostreams::copy(output, iostreams::back_inserter(out));
214 return test_output_filter(filter, in, out);
215 }
216
217 template<typename Filter, typename Source1, typename Source2>
218 bool test_output_filter( Filter filter,
219 const Source1& input,
220 const Source2& output )
221 {
222 // Use tag dispatch to compensate for bad overload resolution.
223 return test_output_filter( filter, input, output,
224 is_string<Source1>() );
225 }
226
227 //--------------Definition of test_filter_pair--------------------------------//
228
229 template<typename OutputFilter, typename InputFilter>
230 bool test_filter_pair( OutputFilter out,
231 InputFilter in,
232 const std::string& data,
233 mpl::true_ )
234 {
235 for ( int inc = default_increment;
236 inc <= default_increment * 40;
237 inc += default_increment )
238 {
239 {
240 array_source src(data.data(), data.data() + data.size());
241 std::string temp;
242 std::string dest;
243 iostreams::copy(src, compose(out, non_blocking_sink(temp, inc)));
244 iostreams::copy(
245 compose(in, non_blocking_source(temp, inc)),
246 iostreams::back_inserter(dest)
247 );
248 if (dest != data)
249 return false;
250 }
251 {
252 array_source src(data.data(), data.data() + data.size());
253 std::string temp;
254 std::string dest;
255 iostreams::copy(src, compose(out, non_blocking_sink(temp, inc)));
256 // truncate the file, this should not loop, it may throw
257 // std::ios_base::failure, which we swallow.
258 try {
259 temp.resize(temp.size() / 2);
260 iostreams::copy(
261 compose(in, non_blocking_source(temp, inc)),
262 iostreams::back_inserter(dest)
263 );
264 } catch(std::ios_base::failure&) {}
265 }
266 {
267 array_source src(data.data(), data.data() + data.size());
268 std::string temp;
269 std::string dest;
270 iostreams::copy(compose(out, src), non_blocking_sink(temp, inc));
271 iostreams::copy(
272 non_blocking_source(temp, inc),
273 compose(in, iostreams::back_inserter(dest))
274 );
275 if (dest != data)
276 return false;
277 }
278 {
279 array_source src(data.data(), data.data() + data.size());
280 std::string temp;
281 std::string dest;
282 iostreams::copy(compose(out, src), non_blocking_sink(temp, inc));
283 // truncate the file, this should not loop, it may throw
284 // std::ios_base::failure, which we swallow.
285 try {
286 temp.resize(temp.size() / 2);
287 iostreams::copy(
288 non_blocking_source(temp, inc),
289 compose(in, iostreams::back_inserter(dest))
290 );
291 } catch(std::ios_base::failure&) {}
292 }
293 }
294 return true;
295 }
296
297 template<typename OutputFilter, typename InputFilter, typename Source>
298 bool test_filter_pair( OutputFilter out,
299 InputFilter in,
300 const Source& data,
301 mpl::false_ )
302 {
303 std::string str;
304 iostreams::copy(data, iostreams::back_inserter(str));
305 return test_filter_pair(out, in, str);
306 }
307
308 template<typename OutputFilter, typename InputFilter, typename Source>
309 bool test_filter_pair( OutputFilter out,
310 InputFilter in,
311 const Source& data )
312 {
313 // Use tag dispatch to compensate for bad overload resolution.
314 return test_filter_pair(out, in, data, is_string<Source>());
315 }
316
317 } } // End namespaces iostreams, boost.
318
319 #endif // #ifndef BOOST_IOSTREAMS_FILTER_TEST_HPP_INCLUDED