Ugly, not-to-be-pushed sucking in of all of Boost to get windows to work.
[dyninst.git] / external / boost / iostreams / filter / test.hpp
1 // (C) Copyright Jonathan Turkanis 2005.
2 // Distributed under the Boost Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
4
5 // See http://www.boost.org/libs/iostreams for documentation.
6
7 #ifndef BOOST_IOSTREAMS_FILTER_TEST_HPP_INCLUDED
8
9 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
10 # pragma once
11 #endif
12
13 #include <boost/config.hpp>               // BOOST_MSVC,put size_t in std.
14 #include <boost/detail/workaround.hpp>
15 #include <algorithm>                      // min.
16 #include <cstddef>                        // size_t.
17 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || \
18     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(BOOST_MSVC, <= 1300) && \
28     !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \
29     !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
30     /**/
31 # include <boost/random/linear_congruential.hpp>
32 # include <boost/random/uniform_smallint.hpp>
33 #endif
34 #include <boost/iostreams/categories.hpp>
35 #include <boost/iostreams/compose.hpp>
36 #include <boost/iostreams/copy.hpp>
37 #include <boost/iostreams/detail/adapter/basic_adapter.hpp>
38 #include <boost/iostreams/detail/bool_trait_def.hpp>
39 #include <boost/iostreams/detail/ios.hpp>
40 #include <boost/iostreams/device/array.hpp>
41 #include <boost/iostreams/device/back_inserter.hpp>
42 #include <boost/iostreams/operations.hpp>
43 #include <boost/mpl/bool.hpp>
44 #include <boost/type_traits/is_array.hpp>
45 #include <boost/type_traits/is_same.hpp>
46
47 #undef memcpy
48 #undef rand
49 #undef strlen
50
51 #if defined(BOOST_NO_STDC_NAMESPACE) && !defined(__LIBCOMO__)
52 namespace std { 
53     using ::memcpy; 
54     using ::strlen; 
55     #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || \
56         BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) || \
57         BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
58         /**/
59         using ::rand; 
60     #endif
61 }
62 #endif
63
64 namespace boost { namespace iostreams {
65
66 BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_string, std::basic_string, 3)
67
68 const std::streamsize default_increment = 5;
69
70 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && \
71     !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \
72     !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
73     /**/
74     std::streamsize rand(int inc)
75     {
76         static rand48                random_gen;
77         static uniform_smallint<int> random_dist(0, inc);
78         return random_dist(random_gen);
79     }
80 #else
81     std::streamsize rand(int inc) 
82     { 
83         return (std::rand() * inc + 1) / RAND_MAX; 
84     }
85 #endif
86
87 class non_blocking_source {
88 public:
89     typedef char char_type;
90     struct category
91         : source_tag,
92           peekable_tag
93         { };
94     explicit non_blocking_source( const std::string& data, 
95                                   std::streamsize inc = default_increment ) 
96         : data_(data), inc_(inc), pos_(0)
97         { }
98     std::streamsize read(char* s, std::streamsize n)
99     {
100         if (pos_ == static_cast<std::streamsize>(data_.size()))
101             return -1;
102         std::streamsize avail = 
103             (std::min) (n, static_cast<std::streamsize>(data_.size() - pos_));
104         std::streamsize amt = (std::min) (rand(inc_), avail);
105         if (amt)
106             std::memcpy(s, data_.c_str() + pos_, amt);
107         pos_ += amt;
108         return amt;
109     }
110
111     bool putback(char c)
112     {
113         if (pos_ > 0) {
114             data_[--pos_] = c;
115             return true;
116         }
117         return false;
118     }
119 private:
120     std::string      data_;
121     std::streamsize  inc_, pos_;
122 };
123
124 class non_blocking_sink : public sink {
125 public:
126     non_blocking_sink( std::string& dest,
127                        std::streamsize inc = default_increment ) 
128         : dest_(dest), inc_(inc) 
129         { }
130     std::streamsize write(const char* s, std::streamsize n)
131     {
132         std::streamsize amt = (std::min) (rand(inc_), n);
133         dest_.insert(dest_.end(), s, s + amt);
134         return amt;
135     }
136 private:
137     std::string&     dest_;
138     std::streamsize  inc_;
139 };
140                 
141 //--------------Definition of test_input_filter-------------------------------//
142
143 template<typename Filter>
144 bool test_input_filter( Filter filter, 
145                         const std::string& input, 
146                         const std::string& output, 
147                         mpl::true_ )
148 {
149     for ( int inc = default_increment; 
150           inc < default_increment * 40; 
151           inc += default_increment )
152     {
153         non_blocking_source  src(input, inc);
154         std::string          dest;
155         iostreams::copy(compose(filter, src), iostreams::back_inserter(dest));
156         if (dest != output)
157             return false;
158     }
159     return true;
160 }
161
162 template<typename Filter, typename Source1, typename Source2>
163 bool test_input_filter( Filter filter, 
164                         const Source1& input, 
165                         const Source2& output, 
166                         mpl::false_ )
167 {
168     std::string in;
169     std::string out;
170     iostreams::copy(input, iostreams::back_inserter(in));
171     iostreams::copy(output, iostreams::back_inserter(out));
172     return test_input_filter(filter, in, out);
173 }
174
175 template<typename Filter, typename Source1, typename Source2>
176 bool test_input_filter( Filter filter, 
177                         const Source1& input, 
178                         const Source2& output )
179 {
180     // Use tag dispatch to compensate for bad overload resolution.
181     return test_input_filter( filter, input, output,    
182                               is_string<Source1>() );
183 }
184
185 //--------------Definition of test_output_filter------------------------------//
186
187 template<typename Filter>
188 bool test_output_filter( Filter filter, 
189                          const std::string& input, 
190                          const std::string& output, 
191                          mpl::true_ )
192 {
193     for ( int inc = default_increment; 
194           inc < default_increment * 40; 
195           inc += default_increment )
196     {
197         array_source  src(input.data(), input.data() + input.size());
198         std::string   dest;
199         iostreams::copy(src, compose(filter, non_blocking_sink(dest, inc)));
200         if (dest != output )
201             return false;
202     }
203     return true;
204 }
205
206 template<typename Filter, typename Source1, typename Source2>
207 bool test_output_filter( Filter filter, 
208                          const Source1& input, 
209                          const Source2& output, 
210                          mpl::false_ )
211 {
212     std::string in;
213     std::string out;
214     iostreams::copy(input, iostreams::back_inserter(in));
215     iostreams::copy(output, iostreams::back_inserter(out));
216     return test_output_filter(filter, in, out);
217 }
218
219 template<typename Filter, typename Source1, typename Source2>
220 bool test_output_filter( Filter filter, 
221                          const Source1& input, 
222                          const Source2& output )
223 {
224     // Use tag dispatch to compensate for bad overload resolution.
225     return test_output_filter( filter, input, output,    
226                                is_string<Source1>() );
227 }
228
229 //--------------Definition of test_filter_pair--------------------------------//
230
231 template<typename OutputFilter, typename InputFilter>
232 bool test_filter_pair( OutputFilter out, 
233                        InputFilter in, 
234                        const std::string& data, 
235                        mpl::true_ )
236 {
237     for ( int inc = default_increment; 
238           inc <= default_increment * 40; 
239           inc += default_increment )
240     {
241         array_source  src(data.data(), data.data() + data.size());
242         std::string   temp;
243         std::string   dest;
244         iostreams::copy(src, compose(out, non_blocking_sink(temp, inc)));
245         iostreams::copy( 
246             compose(in, non_blocking_source(temp, inc)),
247             iostreams::back_inserter(dest)
248         );
249         if (dest != data)
250             return false;
251     }
252     return true;
253 }
254
255 template<typename OutputFilter, typename InputFilter, typename Source>
256 bool test_filter_pair( OutputFilter out, 
257                        InputFilter in, 
258                        const Source& data, 
259                        mpl::false_ )
260 {
261     std::string str;
262     iostreams::copy(data, iostreams::back_inserter(str));
263     return test_filter_pair(out, in, str);
264 }
265
266 template<typename OutputFilter, typename InputFilter, typename Source>
267 bool test_filter_pair( OutputFilter out, 
268                        InputFilter in, 
269                        const Source& data )
270 {
271     // Use tag dispatch to compensate for bad overload resolution.
272     return test_filter_pair(out, in, data, is_string<Source>());
273 }
274
275 } } // End namespaces iostreams, boost.
276
277 #endif // #ifndef BOOST_IOSTREAMS_FILTER_TEST_HPP_INCLUDED