/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. // See http://www.boost.org/libs/iostreams for documentation.
  6. #ifndef BOOST_IOSTREAMS_FILTER_TEST_HPP_INCLUDED
  7. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  8. # pragma once
  9. #endif
  10. #include <boost/config.hpp> // BOOST_MSVC,put size_t in std.
  11. #include <boost/detail/workaround.hpp>
  12. #include <algorithm> // min.
  13. #include <cstddef> // size_t.
  14. #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || \
  15. BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) || \
  16. BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
  17. /**/
  18. # include <cstdlib> // rand.
  19. #endif
  20. #include <cstring> // memcpy, strlen.
  21. #include <iterator>
  22. #include <string>
  23. #include <vector>
  24. #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && \
  25. !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \
  26. !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
  27. /**/
  28. # include <boost/random/linear_congruential.hpp>
  29. # include <boost/random/uniform_smallint.hpp>
  30. #endif
  31. #include <boost/iostreams/categories.hpp>
  32. #include <boost/iostreams/compose.hpp>
  33. #include <boost/iostreams/copy.hpp>
  34. #include <boost/iostreams/detail/bool_trait_def.hpp>
  35. #include <boost/iostreams/detail/ios.hpp>
  36. #include <boost/iostreams/device/array.hpp>
  37. #include <boost/iostreams/device/back_inserter.hpp>
  38. #include <boost/iostreams/operations.hpp>
  39. #include <boost/mpl/bool.hpp>
  40. #include <boost/type_traits/is_array.hpp>
  41. #include <boost/type_traits/is_same.hpp>
  42. #undef memcpy
  43. #undef rand
  44. #undef strlen
  45. #if defined(BOOST_NO_STDC_NAMESPACE) && !defined(__LIBCOMO__)
  46. namespace std {
  47. using ::memcpy;
  48. using ::strlen;
  49. #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || \
  50. BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) || \
  51. BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
  52. /**/
  53. using ::rand;
  54. #endif
  55. }
  56. #endif
  57. namespace boost { namespace iostreams {
  58. BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_string, std::basic_string, 3)
  59. const std::streamsize default_increment = 5;
  60. #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && \
  61. !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \
  62. !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
  63. /**/
  64. std::streamsize rand(int inc)
  65. {
  66. static rand48 random_gen;
  67. static uniform_smallint<int> random_dist(0, inc);
  68. return random_dist(random_gen);
  69. }
  70. #else
  71. std::streamsize rand(int inc)
  72. {
  73. return (std::rand() * inc + 1) / RAND_MAX;
  74. }
  75. #endif
  76. class non_blocking_source {
  77. public:
  78. typedef char char_type;
  79. struct category
  80. : source_tag,
  81. peekable_tag
  82. { };
  83. explicit non_blocking_source( const std::string& data,
  84. std::streamsize inc = default_increment )
  85. : data_(data), inc_(inc), pos_(0)
  86. { }
  87. std::streamsize read(char* s, std::streamsize n)
  88. {
  89. if (pos_ == static_cast<std::streamsize>(data_.size()))
  90. return -1;
  91. std::streamsize avail =
  92. (std::min) (n, static_cast<std::streamsize>(data_.size() - pos_));
  93. std::streamsize amt = (std::min) (rand(inc_), avail);
  94. if (amt)
  95. std::memcpy(s, data_.c_str() + pos_, amt);
  96. pos_ += amt;
  97. return amt;
  98. }
  99. bool putback(char c)
  100. {
  101. if (pos_ > 0) {
  102. data_[--pos_] = c;
  103. return true;
  104. }
  105. return false;
  106. }
  107. private:
  108. std::string data_;
  109. std::streamsize inc_, pos_;
  110. };
  111. class non_blocking_sink : public sink {
  112. public:
  113. non_blocking_sink( std::string& dest,
  114. std::streamsize inc = default_increment )
  115. : dest_(dest), inc_(inc)
  116. { }
  117. std::streamsize write(const char* s, std::streamsize n)
  118. {
  119. std::streamsize amt = (std::min) (rand(inc_), n);
  120. dest_.insert(dest_.end(), s, s + amt);
  121. return amt;
  122. }
  123. private:
  124. non_blocking_sink& operator=(const non_blocking_sink&);
  125. std::string& dest_;
  126. std::streamsize inc_;
  127. };
  128. //--------------Definition of test_input_filter-------------------------------//
  129. template<typename Filter>
  130. bool test_input_filter( Filter filter,
  131. const std::string& input,
  132. const std::string& output,
  133. mpl::true_ )
  134. {
  135. for ( int inc = default_increment;
  136. inc < default_increment * 40;
  137. inc += default_increment )
  138. {
  139. non_blocking_source src(input, inc);
  140. std::string dest;
  141. iostreams::copy(compose(filter, src), iostreams::back_inserter(dest));
  142. if (dest != output)
  143. return false;
  144. }
  145. return true;
  146. }
  147. template<typename Filter, typename Source1, typename Source2>
  148. bool test_input_filter( Filter filter,
  149. const Source1& input,
  150. const Source2& output,
  151. mpl::false_ )
  152. {
  153. std::string in;
  154. std::string out;
  155. iostreams::copy(input, iostreams::back_inserter(in));
  156. iostreams::copy(output, iostreams::back_inserter(out));
  157. return test_input_filter(filter, in, out);
  158. }
  159. template<typename Filter, typename Source1, typename Source2>
  160. bool test_input_filter( Filter filter,
  161. const Source1& input,
  162. const Source2& output )
  163. {
  164. // Use tag dispatch to compensate for bad overload resolution.
  165. return test_input_filter( filter, input, output,
  166. is_string<Source1>() );
  167. }
  168. //--------------Definition of test_output_filter------------------------------//
  169. template<typename Filter>
  170. bool test_output_filter( Filter filter,
  171. const std::string& input,
  172. const std::string& output,
  173. mpl::true_ )
  174. {
  175. for ( int inc = default_increment;
  176. inc < default_increment * 40;
  177. inc += default_increment )
  178. {
  179. array_source src(input.data(), input.data() + input.size());
  180. std::string dest;
  181. iostreams::copy(src, compose(filter, non_blocking_sink(dest, inc)));
  182. if (dest != output )
  183. return false;
  184. }
  185. return true;
  186. }
  187. template<typename Filter, typename Source1, typename Source2>
  188. bool test_output_filter( Filter filter,
  189. const Source1& input,
  190. const Source2& output,
  191. mpl::false_ )
  192. {
  193. std::string in;
  194. std::string out;
  195. iostreams::copy(input, iostreams::back_inserter(in));
  196. iostreams::copy(output, iostreams::back_inserter(out));
  197. return test_output_filter(filter, in, out);
  198. }
  199. template<typename Filter, typename Source1, typename Source2>
  200. bool test_output_filter( Filter filter,
  201. const Source1& input,
  202. const Source2& output )
  203. {
  204. // Use tag dispatch to compensate for bad overload resolution.
  205. return test_output_filter( filter, input, output,
  206. is_string<Source1>() );
  207. }
  208. //--------------Definition of test_filter_pair--------------------------------//
  209. template<typename OutputFilter, typename InputFilter>
  210. bool test_filter_pair( OutputFilter out,
  211. InputFilter in,
  212. const std::string& data,
  213. mpl::true_ )
  214. {
  215. for ( int inc = default_increment;
  216. inc <= default_increment * 40;
  217. inc += default_increment )
  218. {
  219. {
  220. array_source src(data.data(), data.data() + data.size());
  221. std::string temp;
  222. std::string dest;
  223. iostreams::copy(src, compose(out, non_blocking_sink(temp, inc)));
  224. iostreams::copy(
  225. compose(in, non_blocking_source(temp, inc)),
  226. iostreams::back_inserter(dest)
  227. );
  228. if (dest != data)
  229. return false;
  230. }
  231. {
  232. array_source src(data.data(), data.data() + data.size());
  233. std::string temp;
  234. std::string dest;
  235. iostreams::copy(src, compose(out, non_blocking_sink(temp, inc)));
  236. // truncate the file, this should not loop, it may throw
  237. // std::ios_base::failure, which we swallow.
  238. try {
  239. temp.resize(temp.size() / 2);
  240. iostreams::copy(
  241. compose(in, non_blocking_source(temp, inc)),
  242. iostreams::back_inserter(dest)
  243. );
  244. } catch(std::ios_base::failure&) {}
  245. }
  246. {
  247. array_source src(data.data(), data.data() + data.size());
  248. std::string temp;
  249. std::string dest;
  250. iostreams::copy(compose(out, src), non_blocking_sink(temp, inc));
  251. iostreams::copy(
  252. non_blocking_source(temp, inc),
  253. compose(in, iostreams::back_inserter(dest))
  254. );
  255. if (dest != data)
  256. return false;
  257. }
  258. {
  259. array_source src(data.data(), data.data() + data.size());
  260. std::string temp;
  261. std::string dest;
  262. iostreams::copy(compose(out, src), non_blocking_sink(temp, inc));
  263. // truncate the file, this should not loop, it may throw
  264. // std::ios_base::failure, which we swallow.
  265. try {
  266. temp.resize(temp.size() / 2);
  267. iostreams::copy(
  268. non_blocking_source(temp, inc),
  269. compose(in, iostreams::back_inserter(dest))
  270. );
  271. } catch(std::ios_base::failure&) {}
  272. }
  273. }
  274. return true;
  275. }
  276. template<typename OutputFilter, typename InputFilter, typename Source>
  277. bool test_filter_pair( OutputFilter out,
  278. InputFilter in,
  279. const Source& data,
  280. mpl::false_ )
  281. {
  282. std::string str;
  283. iostreams::copy(data, iostreams::back_inserter(str));
  284. return test_filter_pair(out, in, str);
  285. }
  286. template<typename OutputFilter, typename InputFilter, typename Source>
  287. bool test_filter_pair( OutputFilter out,
  288. InputFilter in,
  289. const Source& data )
  290. {
  291. // Use tag dispatch to compensate for bad overload resolution.
  292. return test_filter_pair(out, in, data, is_string<Source>());
  293. }
  294. } } // End namespaces iostreams, boost.
  295. #endif // #ifndef BOOST_IOSTREAMS_FILTER_TEST_HPP_INCLUDED