File indexing completed on 2025-01-30 09:44:31
0001
0002
0003
0004
0005
0006
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
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
0179 return test_input_filter( filter, input, output,
0180 is_string<Source1>() );
0181 }
0182
0183
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
0223 return test_output_filter( filter, input, output,
0224 is_string<Source1>() );
0225 }
0226
0227
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
0257
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
0284
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
0314 return test_filter_pair(out, in, data, is_string<Source>());
0315 }
0316
0317 } }
0318
0319 #endif