Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:44:31

0001 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
0002 // (C) Copyright 2005-2007 Jonathan Turkanis
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
0005 
0006 // See http://www.boost.org/libs/iostreams for documentation.
0007 
0008 #ifndef BOOST_IOSTREAMS_FILTER_TEST_HPP_INCLUDED
0009 
0010 #if defined(_MSC_VER)
0011 # pragma once
0012 #endif
0013 
0014 #include <boost/config.hpp>               // BOOST_MSVC,put size_t in std.
0015 #include <boost/detail/workaround.hpp>
0016 #include <algorithm>                      // min.
0017 #include <cstddef>                        // size_t.
0018 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) || \
0019     BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
0020     /**/
0021 # include <cstdlib>                       // rand.
0022 #endif
0023 #include <cstring>                        // memcpy, strlen.
0024 #include <iterator>
0025 #include <string>
0026 #include <vector>
0027 #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) && \
0028     !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
0029     /**/
0030 # include <boost/random/linear_congruential.hpp>
0031 # include <boost/random/uniform_smallint.hpp>
0032 #endif
0033 #include <boost/iostreams/categories.hpp>
0034 #include <boost/iostreams/compose.hpp>
0035 #include <boost/iostreams/copy.hpp>
0036 #include <boost/iostreams/detail/bool_trait_def.hpp>
0037 #include <boost/iostreams/detail/ios.hpp>
0038 #include <boost/iostreams/device/array.hpp>
0039 #include <boost/iostreams/device/back_inserter.hpp>
0040 #include <boost/iostreams/operations.hpp>
0041 #include <boost/mpl/bool.hpp>
0042 #include <boost/type_traits/is_array.hpp>
0043 #include <boost/type_traits/is_same.hpp>
0044 
0045 #undef memcpy
0046 #undef rand
0047 #undef strlen
0048 
0049 #if defined(BOOST_NO_STDC_NAMESPACE) && !defined(__LIBCOMO__)
0050 namespace std { 
0051     using ::memcpy; 
0052     using ::strlen; 
0053     #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) || \
0054         BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
0055         /**/
0056         using ::rand; 
0057     #endif
0058 }
0059 #endif
0060 
0061 namespace boost { namespace iostreams {
0062 
0063 BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_string, std::basic_string, 3)
0064 
0065 const std::streamsize default_increment = 5;
0066 
0067 #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) && \
0068     !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
0069     /**/
0070     std::streamsize rand(std::streamsize inc)
0071     {
0072         static rand48                random_gen;
0073         static uniform_smallint<int> random_dist(0, static_cast<int>(inc));
0074         return random_dist(random_gen);
0075     }
0076 #else
0077     std::streamsize rand(std::streamsize inc) 
0078     { 
0079         return (std::rand() * inc + 1) / RAND_MAX; 
0080     }
0081 #endif
0082 
0083 class non_blocking_source {
0084 public:
0085     typedef char char_type;
0086     struct category
0087         : source_tag,
0088           peekable_tag
0089         { };
0090     explicit non_blocking_source( const std::string& data, 
0091                                   std::streamsize inc = default_increment ) 
0092         : data_(data), inc_(inc), pos_(0)
0093         { }
0094     std::streamsize read(char* s, std::streamsize n)
0095     {
0096         using namespace std;
0097         if (pos_ == static_cast<streamsize>(data_.size()))
0098             return -1;
0099         streamsize avail = 
0100             (std::min) (n, static_cast<streamsize>(data_.size() - pos_));
0101         streamsize amt = (std::min) (rand(inc_), avail);
0102         if (amt)
0103             memcpy(s, data_.c_str() + pos_, static_cast<size_t>(amt));
0104         pos_ += amt;
0105         return amt;
0106     }
0107 
0108     bool putback(char c)
0109     {
0110         if (pos_ > 0) {
0111             data_[static_cast<std::string::size_type>(--pos_)] = c;
0112             return true;
0113         }
0114         return false;
0115     }
0116 private:
0117     std::string      data_;
0118     std::streamsize  inc_, pos_;
0119 };
0120 
0121 class non_blocking_sink : public sink {
0122 public:
0123     non_blocking_sink( std::string& dest,
0124                        std::streamsize inc = default_increment ) 
0125         : dest_(dest), inc_(inc) 
0126         { }
0127     std::streamsize write(const char* s, std::streamsize n)
0128     {
0129         std::streamsize amt = (std::min) (rand(inc_), n);
0130         dest_.insert(dest_.end(), s, s + amt);
0131         return amt;
0132     }
0133 private:
0134     non_blocking_sink& operator=(const non_blocking_sink&);
0135     std::string&     dest_;
0136     std::streamsize  inc_;
0137 };
0138                 
0139 //--------------Definition of test_input_filter-------------------------------//
0140 
0141 template<typename Filter>
0142 bool test_input_filter( Filter filter, 
0143                         const std::string& input, 
0144                         const std::string& output, 
0145                         mpl::true_ )
0146 {
0147     for ( int inc = default_increment; 
0148           inc < default_increment * 40; 
0149           inc += default_increment )
0150     {
0151         non_blocking_source  src(input, inc);
0152         std::string          dest;
0153         iostreams::copy(compose(filter, src), iostreams::back_inserter(dest));
0154         if (dest != output)
0155             return false;
0156     }
0157     return true;
0158 }
0159 
0160 template<typename Filter, typename Source1, typename Source2>
0161 bool test_input_filter( Filter filter, 
0162                         const Source1& input, 
0163                         const Source2& output, 
0164                         mpl::false_ )
0165 {
0166     std::string in;
0167     std::string out;
0168     iostreams::copy(input, iostreams::back_inserter(in));
0169     iostreams::copy(output, iostreams::back_inserter(out));
0170     return test_input_filter(filter, in, out);
0171 }
0172 
0173 template<typename Filter, typename Source1, typename Source2>
0174 bool test_input_filter( Filter filter, 
0175                         const Source1& input, 
0176                         const Source2& output )
0177 {
0178     // Use tag dispatch to compensate for bad overload resolution.
0179     return test_input_filter( filter, input, output,    
0180                               is_string<Source1>() );
0181 }
0182 
0183 //--------------Definition of test_output_filter------------------------------//
0184 
0185 template<typename Filter>
0186 bool test_output_filter( Filter filter, 
0187                          const std::string& input, 
0188                          const std::string& output, 
0189                          mpl::true_ )
0190 {
0191     for ( int inc = default_increment; 
0192           inc < default_increment * 40; 
0193           inc += default_increment )
0194     {
0195         array_source  src(input.data(), input.data() + input.size());
0196         std::string   dest;
0197         iostreams::copy(src, compose(filter, non_blocking_sink(dest, inc)));
0198         if (dest != output )
0199             return false;
0200     }
0201     return true;
0202 }
0203 
0204 template<typename Filter, typename Source1, typename Source2>
0205 bool test_output_filter( Filter filter, 
0206                          const Source1& input, 
0207                          const Source2& output, 
0208                          mpl::false_ )
0209 {
0210     std::string in;
0211     std::string out;
0212     iostreams::copy(input, iostreams::back_inserter(in));
0213     iostreams::copy(output, iostreams::back_inserter(out));
0214     return test_output_filter(filter, in, out);
0215 }
0216 
0217 template<typename Filter, typename Source1, typename Source2>
0218 bool test_output_filter( Filter filter, 
0219                          const Source1& input, 
0220                          const Source2& output )
0221 {
0222     // Use tag dispatch to compensate for bad overload resolution.
0223     return test_output_filter( filter, input, output,    
0224                                is_string<Source1>() );
0225 }
0226 
0227 //--------------Definition of test_filter_pair--------------------------------//
0228 
0229 template<typename OutputFilter, typename InputFilter>
0230 bool test_filter_pair( OutputFilter out, 
0231                        InputFilter in, 
0232                        const std::string& data, 
0233                        mpl::true_ )
0234 {
0235     for ( int inc = default_increment; 
0236           inc <= default_increment * 40; 
0237           inc += default_increment )
0238     {
0239         {
0240             array_source  src(data.data(), data.data() + data.size());
0241             std::string   temp;
0242             std::string   dest;
0243             iostreams::copy(src, compose(out, non_blocking_sink(temp, inc)));
0244             iostreams::copy( 
0245                 compose(in, non_blocking_source(temp, inc)),
0246                 iostreams::back_inserter(dest)
0247             );
0248             if (dest != data)
0249                 return false;
0250         }
0251         {
0252             array_source  src(data.data(), data.data() + data.size());
0253             std::string   temp;
0254             std::string   dest;
0255             iostreams::copy(src, compose(out, non_blocking_sink(temp, inc)));
0256             // truncate the file, this should not loop, it may throw
0257             // std::ios_base::failure, which we swallow.
0258             try {
0259                 temp.resize(temp.size() / 2);
0260                 iostreams::copy( 
0261                     compose(in, non_blocking_source(temp, inc)),
0262                     iostreams::back_inserter(dest)
0263                 );
0264             } catch(std::ios_base::failure&) {}
0265         }
0266         {
0267             array_source  src(data.data(), data.data() + data.size());
0268             std::string   temp;
0269             std::string   dest;
0270             iostreams::copy(compose(out, src), non_blocking_sink(temp, inc));
0271             iostreams::copy( 
0272                 non_blocking_source(temp, inc),
0273                 compose(in, iostreams::back_inserter(dest))
0274             );
0275             if (dest != data)
0276                 return false;
0277         }
0278         {
0279             array_source  src(data.data(), data.data() + data.size());
0280             std::string   temp;
0281             std::string   dest;
0282             iostreams::copy(compose(out, src), non_blocking_sink(temp, inc));
0283             // truncate the file, this should not loop, it may throw
0284             // std::ios_base::failure, which we swallow.
0285             try {
0286                 temp.resize(temp.size() / 2);
0287                 iostreams::copy( 
0288                     non_blocking_source(temp, inc),
0289                     compose(in, iostreams::back_inserter(dest))
0290                 );
0291             } catch(std::ios_base::failure&) {}
0292         }
0293     }
0294     return true;
0295 }
0296 
0297 template<typename OutputFilter, typename InputFilter, typename Source>
0298 bool test_filter_pair( OutputFilter out, 
0299                        InputFilter in, 
0300                        const Source& data, 
0301                        mpl::false_ )
0302 {
0303     std::string str;
0304     iostreams::copy(data, iostreams::back_inserter(str));
0305     return test_filter_pair(out, in, str);
0306 }
0307 
0308 template<typename OutputFilter, typename InputFilter, typename Source>
0309 bool test_filter_pair( OutputFilter out, 
0310                        InputFilter in, 
0311                        const Source& data )
0312 {
0313     // Use tag dispatch to compensate for bad overload resolution.
0314     return test_filter_pair(out, in, data, is_string<Source>());
0315 }
0316 
0317 } } // End namespaces iostreams, boost.
0318 
0319 #endif // #ifndef BOOST_IOSTREAMS_FILTER_TEST_HPP_INCLUDED