source: NonGTP/Boost/boost/iostreams/filter/test.hpp @ 857

Revision 857, 8.9 KB checked in by igarcia, 18 years ago (diff)
Line 
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__)
52namespace 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
64namespace boost { namespace iostreams {
65
66BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_string, std::basic_string, 3)
67
68const 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
87class non_blocking_source {
88public:
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    }
119private:
120    std::string      data_;
121    std::streamsize  inc_, pos_;
122};
123
124class non_blocking_sink : public sink {
125public:
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    }
136private:
137    std::string&     dest_;
138    std::streamsize  inc_;
139};
140               
141//--------------Definition of test_input_filter-------------------------------//
142
143template<typename Filter>
144bool 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
162template<typename Filter, typename Source1, typename Source2>
163bool 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
175template<typename Filter, typename Source1, typename Source2>
176bool 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
187template<typename Filter>
188bool 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
206template<typename Filter, typename Source1, typename Source2>
207bool 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
219template<typename Filter, typename Source1, typename Source2>
220bool 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
231template<typename OutputFilter, typename InputFilter>
232bool 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
255template<typename OutputFilter, typename InputFilter, typename Source>
256bool 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
266template<typename OutputFilter, typename InputFilter, typename Source>
267bool 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
Note: See TracBrowser for help on using the repository browser.