symmetric_filter_test.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
  2. // (C) Copyright 2004-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. #include <boost/iostreams/detail/buffer.hpp>
  7. #include <boost/iostreams/device/file.hpp>
  8. #include <boost/iostreams/filter/symmetric.hpp>
  9. #include <boost/iostreams/filter/test.hpp>
  10. #include <boost/test/test_tools.hpp>
  11. #include <boost/test/unit_test.hpp>
  12. #include "detail/closable.hpp"
  13. #include "./detail/constants.hpp"
  14. #include "detail/operation_sequence.hpp"
  15. #include "./detail/temp_file.hpp"
  16. #include "./detail/verification.hpp"
  17. // Must come last.
  18. #include <boost/iostreams/detail/config/disable_warnings.hpp>
  19. using namespace boost::iostreams;
  20. using namespace boost::iostreams::test;
  21. using boost::unit_test::test_suite;
  22. namespace io = boost::iostreams;
  23. // Note: The filter is given an internal buffer -- unnecessary in this simple
  24. // case -- to stress test symmetric_filter.
  25. struct toupper_symmetric_filter_impl {
  26. typedef char char_type;
  27. explicit toupper_symmetric_filter_impl(
  28. std::streamsize buffer_size =
  29. default_filter_buffer_size
  30. )
  31. : buf_(buffer_size)
  32. {
  33. buf_.set(0, 0);
  34. }
  35. bool filter( const char*& src_begin, const char* src_end,
  36. char*& dest_begin, char* dest_end, bool /* flush */ )
  37. {
  38. while ( can_read(src_begin, src_end) ||
  39. can_write(dest_begin, dest_end) )
  40. {
  41. if (can_read(src_begin, src_end))
  42. read(src_begin, src_end);
  43. if (can_write(dest_begin, dest_end))
  44. write(dest_begin, dest_end);
  45. }
  46. bool result = buf_.ptr() != buf_.eptr();
  47. return result;
  48. }
  49. void close() { buf_.set(0, 0); }
  50. void read(const char*& src_begin, const char* src_end)
  51. {
  52. std::ptrdiff_t count =
  53. (std::min) ( src_end - src_begin,
  54. static_cast<std::ptrdiff_t>(buf_.size()) -
  55. (buf_.eptr() - buf_.data()) );
  56. while (count-- > 0)
  57. *buf_.eptr()++ = std::toupper(*src_begin++);
  58. }
  59. void write(char*& dest_begin, char* dest_end)
  60. {
  61. std::ptrdiff_t count =
  62. (std::min) ( dest_end - dest_begin,
  63. buf_.eptr() - buf_.ptr() );
  64. while (count-- > 0)
  65. *dest_begin++ = *buf_.ptr()++;
  66. if (buf_.ptr() == buf_.eptr())
  67. buf_.set(0, 0);
  68. }
  69. bool can_read(const char*& src_begin, const char* src_end)
  70. { return src_begin != src_end && buf_.eptr() != buf_.end(); }
  71. bool can_write(char*& dest_begin, char* dest_end)
  72. { return dest_begin != dest_end && buf_.ptr() != buf_.eptr(); }
  73. boost::iostreams::detail::buffer<char> buf_;
  74. };
  75. typedef symmetric_filter<toupper_symmetric_filter_impl>
  76. toupper_symmetric_filter;
  77. void read_symmetric_filter()
  78. {
  79. test_file test;
  80. uppercase_file upper;
  81. BOOST_CHECK(
  82. test_input_filter( toupper_symmetric_filter(default_filter_buffer_size),
  83. file_source(test.name(), in_mode),
  84. file_source(upper.name(), in_mode) )
  85. );
  86. }
  87. void write_symmetric_filter()
  88. {
  89. test_file test;
  90. uppercase_file upper;
  91. BOOST_CHECK(
  92. test_output_filter( toupper_symmetric_filter(default_filter_buffer_size),
  93. file_source(test.name(), in_mode),
  94. file_source(upper.name(), in_mode) )
  95. );
  96. }
  97. void close_symmetric_filter()
  98. {
  99. // Test input
  100. {
  101. operation_sequence seq;
  102. chain<input> ch;
  103. ch.push(
  104. io::symmetric_filter<closable_symmetric_filter>
  105. (1, seq.new_operation(2))
  106. );
  107. ch.push(closable_device<input>(seq.new_operation(1)));
  108. BOOST_CHECK_NO_THROW(ch.reset());
  109. BOOST_CHECK_OPERATION_SEQUENCE(seq);
  110. }
  111. // Test output
  112. {
  113. operation_sequence seq;
  114. chain<output> ch;
  115. ch.push(
  116. io::symmetric_filter<closable_symmetric_filter>
  117. (1, seq.new_operation(1))
  118. );
  119. ch.push(closable_device<output>(seq.new_operation(2)));
  120. BOOST_CHECK_NO_THROW(ch.reset());
  121. BOOST_CHECK_OPERATION_SEQUENCE(seq);
  122. }
  123. }
  124. #ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS
  125. struct wcopy_filter_impl {
  126. typedef wchar_t char_type;
  127. bool filter( const wchar_t*& src_begin, const wchar_t* src_end,
  128. wchar_t*& dest_begin, wchar_t* dest_end, bool /* flush */ )
  129. {
  130. if(src_begin != src_end && dest_begin != dest_end) {
  131. *dest_begin++ = *src_begin++;
  132. }
  133. return false;
  134. }
  135. void close() {}
  136. };
  137. typedef symmetric_filter<wcopy_filter_impl> wcopy_filter;
  138. void wide_symmetric_filter()
  139. {
  140. {
  141. warray_source src(wide_data(), wide_data() + data_length());
  142. std::wstring dest;
  143. io::copy(src, io::compose(wcopy_filter(16), io::back_inserter(dest)));
  144. BOOST_CHECK(dest == wide_data());
  145. }
  146. {
  147. warray_source src(wide_data(), wide_data() + data_length());
  148. std::wstring dest;
  149. io::copy(io::compose(wcopy_filter(16), src), io::back_inserter(dest));
  150. BOOST_CHECK(dest == wide_data());
  151. }
  152. }
  153. #endif
  154. test_suite* init_unit_test_suite(int, char* [])
  155. {
  156. test_suite* test = BOOST_TEST_SUITE("symmetric_filter test");
  157. test->add(BOOST_TEST_CASE(&read_symmetric_filter));
  158. test->add(BOOST_TEST_CASE(&write_symmetric_filter));
  159. test->add(BOOST_TEST_CASE(&close_symmetric_filter));
  160. #ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS
  161. test->add(BOOST_TEST_CASE(&wide_symmetric_filter));
  162. #endif
  163. return test;
  164. }
  165. #include <boost/iostreams/detail/config/enable_warnings.hpp>