]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/iostreams/include/boost/iostreams/filter/test.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / iostreams / include / boost / iostreams / filter / test.hpp
CommitLineData
7c673cae
FG
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(__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(__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__)
50namespace std {
51 using ::memcpy;
52 using ::strlen;
53 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) || \
54 BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
55 /**/
56 using ::rand;
57 #endif
58}
59#endif
60
61namespace boost { namespace iostreams {
62
63BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_string, std::basic_string, 3)
64
65const std::streamsize default_increment = 5;
66
67#if !BOOST_WORKAROUND(__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
83class non_blocking_source {
84public:
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 }
116private:
117 std::string data_;
118 std::streamsize inc_, pos_;
119};
120
121class non_blocking_sink : public sink {
122public:
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 }
133private:
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
141template<typename Filter>
142bool 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
160template<typename Filter, typename Source1, typename Source2>
161bool 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
173template<typename Filter, typename Source1, typename Source2>
174bool 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
185template<typename Filter>
186bool 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
204template<typename Filter, typename Source1, typename Source2>
205bool 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
217template<typename Filter, typename Source1, typename Source2>
218bool 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
229template<typename OutputFilter, typename InputFilter>
230bool 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
297template<typename OutputFilter, typename InputFilter, typename Source>
298bool 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
308template<typename OutputFilter, typename InputFilter, typename Source>
309bool 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