PageRenderTime 41ms CodeModel.GetById 15ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/iostreams/filter/test.hpp

http://hadesmem.googlecode.com/
C++ Header | 322 lines | 276 code | 27 blank | 19 comment | 25 complexity | c35ce884ec414eff123300e4e68fb624 MD5 | raw file
  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) && (_MSC_VER >= 1020)
 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_MSVC, <= 1300) || \
 19    BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) || \
 20    BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
 21    /**/
 22# include <cstdlib>                       // rand.
 23#endif
 24#include <cstring>                        // memcpy, strlen.
 25#include <iterator>
 26#include <string>
 27#include <vector>
 28#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && \
 29    !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \
 30    !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
 31    /**/
 32# include <boost/random/linear_congruential.hpp>
 33# include <boost/random/uniform_smallint.hpp>
 34#endif
 35#include <boost/iostreams/categories.hpp>
 36#include <boost/iostreams/compose.hpp>
 37#include <boost/iostreams/copy.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    non_blocking_sink& operator=(const non_blocking_sink&);
138    std::string&     dest_;
139    std::streamsize  inc_;
140};
141                
142//--------------Definition of test_input_filter-------------------------------//
143
144template<typename Filter>
145bool test_input_filter( Filter filter, 
146                        const std::string& input, 
147                        const std::string& output, 
148                        mpl::true_ )
149{
150    for ( int inc = default_increment; 
151          inc < default_increment * 40; 
152          inc += default_increment )
153    {
154        non_blocking_source  src(input, inc);
155        std::string          dest;
156        iostreams::copy(compose(filter, src), iostreams::back_inserter(dest));
157        if (dest != output)
158            return false;
159    }
160    return true;
161}
162
163template<typename Filter, typename Source1, typename Source2>
164bool test_input_filter( Filter filter, 
165                        const Source1& input, 
166                        const Source2& output, 
167                        mpl::false_ )
168{
169    std::string in;
170    std::string out;
171    iostreams::copy(input, iostreams::back_inserter(in));
172    iostreams::copy(output, iostreams::back_inserter(out));
173    return test_input_filter(filter, in, out);
174}
175
176template<typename Filter, typename Source1, typename Source2>
177bool test_input_filter( Filter filter, 
178                        const Source1& input, 
179                        const Source2& output )
180{
181    // Use tag dispatch to compensate for bad overload resolution.
182    return test_input_filter( filter, input, output,    
183                              is_string<Source1>() );
184}
185
186//--------------Definition of test_output_filter------------------------------//
187
188template<typename Filter>
189bool test_output_filter( Filter filter, 
190                         const std::string& input, 
191                         const std::string& output, 
192                         mpl::true_ )
193{
194    for ( int inc = default_increment; 
195          inc < default_increment * 40; 
196          inc += default_increment )
197    {
198        array_source  src(input.data(), input.data() + input.size());
199        std::string   dest;
200        iostreams::copy(src, compose(filter, non_blocking_sink(dest, inc)));
201        if (dest != output )
202            return false;
203    }
204    return true;
205}
206
207template<typename Filter, typename Source1, typename Source2>
208bool test_output_filter( Filter filter, 
209                         const Source1& input, 
210                         const Source2& output, 
211                         mpl::false_ )
212{
213    std::string in;
214    std::string out;
215    iostreams::copy(input, iostreams::back_inserter(in));
216    iostreams::copy(output, iostreams::back_inserter(out));
217    return test_output_filter(filter, in, out);
218}
219
220template<typename Filter, typename Source1, typename Source2>
221bool test_output_filter( Filter filter, 
222                         const Source1& input, 
223                         const Source2& output )
224{
225    // Use tag dispatch to compensate for bad overload resolution.
226    return test_output_filter( filter, input, output,    
227                               is_string<Source1>() );
228}
229
230//--------------Definition of test_filter_pair--------------------------------//
231
232template<typename OutputFilter, typename InputFilter>
233bool test_filter_pair( OutputFilter out, 
234                       InputFilter in, 
235                       const std::string& data, 
236                       mpl::true_ )
237{
238    for ( int inc = default_increment; 
239          inc <= default_increment * 40; 
240          inc += default_increment )
241    {
242        {
243            array_source  src(data.data(), data.data() + data.size());
244            std::string   temp;
245            std::string   dest;
246            iostreams::copy(src, compose(out, non_blocking_sink(temp, inc)));
247            iostreams::copy( 
248                compose(in, non_blocking_source(temp, inc)),
249                iostreams::back_inserter(dest)
250            );
251            if (dest != data)
252                return false;
253        }
254        {
255            array_source  src(data.data(), data.data() + data.size());
256            std::string   temp;
257            std::string   dest;
258            iostreams::copy(src, compose(out, non_blocking_sink(temp, inc)));
259            // truncate the file, this should not loop, it may throw
260            // std::ios_base::failure, which we swallow.
261            try {
262                temp.resize(temp.size() / 2);
263                iostreams::copy( 
264                    compose(in, non_blocking_source(temp, inc)),
265                    iostreams::back_inserter(dest)
266                );
267            } catch(std::ios_base::failure&) {}
268        }
269        {
270            array_source  src(data.data(), data.data() + data.size());
271            std::string   temp;
272            std::string   dest;
273            iostreams::copy(compose(out, src), non_blocking_sink(temp, inc));
274            iostreams::copy( 
275                non_blocking_source(temp, inc),
276                compose(in, iostreams::back_inserter(dest))
277            );
278            if (dest != data)
279                return false;
280        }
281        {
282            array_source  src(data.data(), data.data() + data.size());
283            std::string   temp;
284            std::string   dest;
285            iostreams::copy(compose(out, src), non_blocking_sink(temp, inc));
286            // truncate the file, this should not loop, it may throw
287            // std::ios_base::failure, which we swallow.
288            try {
289                temp.resize(temp.size() / 2);
290                iostreams::copy( 
291                    non_blocking_source(temp, inc),
292                    compose(in, iostreams::back_inserter(dest))
293                );
294            } catch(std::ios_base::failure&) {}
295        }
296    }
297    return true;
298}
299
300template<typename OutputFilter, typename InputFilter, typename Source>
301bool test_filter_pair( OutputFilter out, 
302                       InputFilter in, 
303                       const Source& data, 
304                       mpl::false_ )
305{
306    std::string str;
307    iostreams::copy(data, iostreams::back_inserter(str));
308    return test_filter_pair(out, in, str);
309}
310
311template<typename OutputFilter, typename InputFilter, typename Source>
312bool test_filter_pair( OutputFilter out, 
313                       InputFilter in, 
314                       const Source& data )
315{
316    // Use tag dispatch to compensate for bad overload resolution.
317    return test_filter_pair(out, in, data, is_string<Source>());
318}
319
320} } // End namespaces iostreams, boost.
321
322#endif // #ifndef BOOST_IOSTREAMS_FILTER_TEST_HPP_INCLUDED