123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
- // (C) Copyright 2005-2007 Jonathan Turkanis
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
- // See http://www.boost.org/libs/iostreams for documentation.
- #ifndef BOOST_IOSTREAMS_FILTER_TEST_HPP_INCLUDED
- #if defined(_MSC_VER)
- # pragma once
- #endif
- #include <boost/config.hpp> // BOOST_MSVC,put size_t in std.
- #include <boost/detail/workaround.hpp>
- #include <algorithm> // min.
- #include <cstddef> // size_t.
- #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) || \
- BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
- /**/
- # include <cstdlib> // rand.
- #endif
- #include <cstring> // memcpy, strlen.
- #include <iterator>
- #include <string>
- #include <vector>
- #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \
- !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
- /**/
- # include <boost/random/linear_congruential.hpp>
- # include <boost/random/uniform_smallint.hpp>
- #endif
- #include <boost/iostreams/categories.hpp>
- #include <boost/iostreams/compose.hpp>
- #include <boost/iostreams/copy.hpp>
- #include <boost/iostreams/detail/bool_trait_def.hpp>
- #include <boost/iostreams/detail/ios.hpp>
- #include <boost/iostreams/device/array.hpp>
- #include <boost/iostreams/device/back_inserter.hpp>
- #include <boost/iostreams/operations.hpp>
- #include <boost/mpl/bool.hpp>
- #include <boost/type_traits/is_array.hpp>
- #include <boost/type_traits/is_same.hpp>
- #undef memcpy
- #undef rand
- #undef strlen
- #if defined(BOOST_NO_STDC_NAMESPACE) && !defined(__LIBCOMO__)
- namespace std {
- using ::memcpy;
- using ::strlen;
- #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) || \
- BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
- /**/
- using ::rand;
- #endif
- }
- #endif
- namespace boost { namespace iostreams {
- BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_string, std::basic_string, 3)
- const std::streamsize default_increment = 5;
- #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \
- !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
- /**/
- std::streamsize rand(std::streamsize inc)
- {
- static rand48 random_gen;
- static uniform_smallint<int> random_dist(0, static_cast<int>(inc));
- return random_dist(random_gen);
- }
- #else
- std::streamsize rand(std::streamsize inc)
- {
- return (std::rand() * inc + 1) / RAND_MAX;
- }
- #endif
- class non_blocking_source {
- public:
- typedef char char_type;
- struct category
- : source_tag,
- peekable_tag
- { };
- explicit non_blocking_source( const std::string& data,
- std::streamsize inc = default_increment )
- : data_(data), inc_(inc), pos_(0)
- { }
- std::streamsize read(char* s, std::streamsize n)
- {
- using namespace std;
- if (pos_ == static_cast<streamsize>(data_.size()))
- return -1;
- streamsize avail =
- (std::min) (n, static_cast<streamsize>(data_.size() - pos_));
- streamsize amt = (std::min) (rand(inc_), avail);
- if (amt)
- memcpy(s, data_.c_str() + pos_, static_cast<size_t>(amt));
- pos_ += amt;
- return amt;
- }
- bool putback(char c)
- {
- if (pos_ > 0) {
- data_[static_cast<std::string::size_type>(--pos_)] = c;
- return true;
- }
- return false;
- }
- private:
- std::string data_;
- std::streamsize inc_, pos_;
- };
- class non_blocking_sink : public sink {
- public:
- non_blocking_sink( std::string& dest,
- std::streamsize inc = default_increment )
- : dest_(dest), inc_(inc)
- { }
- std::streamsize write(const char* s, std::streamsize n)
- {
- std::streamsize amt = (std::min) (rand(inc_), n);
- dest_.insert(dest_.end(), s, s + amt);
- return amt;
- }
- private:
- non_blocking_sink& operator=(const non_blocking_sink&);
- std::string& dest_;
- std::streamsize inc_;
- };
-
- //--------------Definition of test_input_filter-------------------------------//
- template<typename Filter>
- bool test_input_filter( Filter filter,
- const std::string& input,
- const std::string& output,
- mpl::true_ )
- {
- for ( int inc = default_increment;
- inc < default_increment * 40;
- inc += default_increment )
- {
- non_blocking_source src(input, inc);
- std::string dest;
- iostreams::copy(compose(filter, src), iostreams::back_inserter(dest));
- if (dest != output)
- return false;
- }
- return true;
- }
- template<typename Filter, typename Source1, typename Source2>
- bool test_input_filter( Filter filter,
- const Source1& input,
- const Source2& output,
- mpl::false_ )
- {
- std::string in;
- std::string out;
- iostreams::copy(input, iostreams::back_inserter(in));
- iostreams::copy(output, iostreams::back_inserter(out));
- return test_input_filter(filter, in, out);
- }
- template<typename Filter, typename Source1, typename Source2>
- bool test_input_filter( Filter filter,
- const Source1& input,
- const Source2& output )
- {
- // Use tag dispatch to compensate for bad overload resolution.
- return test_input_filter( filter, input, output,
- is_string<Source1>() );
- }
- //--------------Definition of test_output_filter------------------------------//
- template<typename Filter>
- bool test_output_filter( Filter filter,
- const std::string& input,
- const std::string& output,
- mpl::true_ )
- {
- for ( int inc = default_increment;
- inc < default_increment * 40;
- inc += default_increment )
- {
- array_source src(input.data(), input.data() + input.size());
- std::string dest;
- iostreams::copy(src, compose(filter, non_blocking_sink(dest, inc)));
- if (dest != output )
- return false;
- }
- return true;
- }
- template<typename Filter, typename Source1, typename Source2>
- bool test_output_filter( Filter filter,
- const Source1& input,
- const Source2& output,
- mpl::false_ )
- {
- std::string in;
- std::string out;
- iostreams::copy(input, iostreams::back_inserter(in));
- iostreams::copy(output, iostreams::back_inserter(out));
- return test_output_filter(filter, in, out);
- }
- template<typename Filter, typename Source1, typename Source2>
- bool test_output_filter( Filter filter,
- const Source1& input,
- const Source2& output )
- {
- // Use tag dispatch to compensate for bad overload resolution.
- return test_output_filter( filter, input, output,
- is_string<Source1>() );
- }
- //--------------Definition of test_filter_pair--------------------------------//
- template<typename OutputFilter, typename InputFilter>
- bool test_filter_pair( OutputFilter out,
- InputFilter in,
- const std::string& data,
- mpl::true_ )
- {
- for ( int inc = default_increment;
- inc <= default_increment * 40;
- inc += default_increment )
- {
- {
- array_source src(data.data(), data.data() + data.size());
- std::string temp;
- std::string dest;
- iostreams::copy(src, compose(out, non_blocking_sink(temp, inc)));
- iostreams::copy(
- compose(in, non_blocking_source(temp, inc)),
- iostreams::back_inserter(dest)
- );
- if (dest != data)
- return false;
- }
- {
- array_source src(data.data(), data.data() + data.size());
- std::string temp;
- std::string dest;
- iostreams::copy(src, compose(out, non_blocking_sink(temp, inc)));
- // truncate the file, this should not loop, it may throw
- // std::ios_base::failure, which we swallow.
- try {
- temp.resize(temp.size() / 2);
- iostreams::copy(
- compose(in, non_blocking_source(temp, inc)),
- iostreams::back_inserter(dest)
- );
- } catch(std::ios_base::failure&) {}
- }
- {
- array_source src(data.data(), data.data() + data.size());
- std::string temp;
- std::string dest;
- iostreams::copy(compose(out, src), non_blocking_sink(temp, inc));
- iostreams::copy(
- non_blocking_source(temp, inc),
- compose(in, iostreams::back_inserter(dest))
- );
- if (dest != data)
- return false;
- }
- {
- array_source src(data.data(), data.data() + data.size());
- std::string temp;
- std::string dest;
- iostreams::copy(compose(out, src), non_blocking_sink(temp, inc));
- // truncate the file, this should not loop, it may throw
- // std::ios_base::failure, which we swallow.
- try {
- temp.resize(temp.size() / 2);
- iostreams::copy(
- non_blocking_source(temp, inc),
- compose(in, iostreams::back_inserter(dest))
- );
- } catch(std::ios_base::failure&) {}
- }
- }
- return true;
- }
- template<typename OutputFilter, typename InputFilter, typename Source>
- bool test_filter_pair( OutputFilter out,
- InputFilter in,
- const Source& data,
- mpl::false_ )
- {
- std::string str;
- iostreams::copy(data, iostreams::back_inserter(str));
- return test_filter_pair(out, in, str);
- }
- template<typename OutputFilter, typename InputFilter, typename Source>
- bool test_filter_pair( OutputFilter out,
- InputFilter in,
- const Source& data )
- {
- // Use tag dispatch to compensate for bad overload resolution.
- return test_filter_pair(out, in, data, is_string<Source>());
- }
- } } // End namespaces iostreams, boost.
- #endif // #ifndef BOOST_IOSTREAMS_FILTER_TEST_HPP_INCLUDED
|