combine.hpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
  2. // (C) Copyright 2003-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. // To do: add support for random-access.
  7. #ifndef BOOST_IOSTREAMS_COMBINE_HPP_INCLUDED
  8. #define BOOST_IOSTREAMS_COMBINE_HPP_INCLUDED
  9. #if defined(_MSC_VER)
  10. # pragma once
  11. #endif
  12. #include <boost/config.hpp> // NO_STD_LOCALE, DEDUCED_TYPENAME.
  13. #ifndef BOOST_NO_STD_LOCALE
  14. # include <locale>
  15. #endif
  16. #include <boost/iostreams/detail/ios.hpp>
  17. #include <boost/iostreams/detail/wrap_unwrap.hpp>
  18. #include <boost/iostreams/traits.hpp>
  19. #include <boost/iostreams/operations.hpp>
  20. #include <boost/mpl/if.hpp>
  21. #include <boost/static_assert.hpp>
  22. #include <boost/type_traits/is_convertible.hpp>
  23. #include <boost/type_traits/is_same.hpp>
  24. // Must come last.
  25. #include <boost/iostreams/detail/config/disable_warnings.hpp>
  26. namespace boost { namespace iostreams {
  27. namespace detail {
  28. //
  29. // Template name: combined_device.
  30. // Description: Model of Device defined in terms of a Source/Sink pair.
  31. // Template parameters:
  32. // Source - A model of Source, with the same char_type and traits_type
  33. // as Sink.
  34. // Sink - A model of Sink, with the same char_type and traits_type
  35. // as Source.
  36. //
  37. template<typename Source, typename Sink>
  38. class combined_device {
  39. private:
  40. typedef typename category_of<Source>::type in_category;
  41. typedef typename category_of<Sink>::type out_category;
  42. typedef typename char_type_of<Sink>::type sink_char_type;
  43. public:
  44. typedef typename char_type_of<Source>::type char_type;
  45. struct category
  46. : bidirectional,
  47. device_tag,
  48. closable_tag,
  49. localizable_tag
  50. { };
  51. BOOST_STATIC_ASSERT(is_device<Source>::value);
  52. BOOST_STATIC_ASSERT(is_device<Sink>::value);
  53. BOOST_STATIC_ASSERT((is_convertible<in_category, input>::value));
  54. BOOST_STATIC_ASSERT((is_convertible<out_category, output>::value));
  55. BOOST_STATIC_ASSERT((is_same<char_type, sink_char_type>::value));
  56. combined_device(const Source& src, const Sink& snk);
  57. std::streamsize read(char_type* s, std::streamsize n);
  58. std::streamsize write(const char_type* s, std::streamsize n);
  59. void close(BOOST_IOS::openmode);
  60. #ifndef BOOST_NO_STD_LOCALE
  61. void imbue(const std::locale& loc);
  62. #endif
  63. private:
  64. Source src_;
  65. Sink sink_;
  66. };
  67. //
  68. // Template name: combined_filter.
  69. // Description: Model of Device defined in terms of a Source/Sink pair.
  70. // Template parameters:
  71. // InputFilter - A model of InputFilter, with the same char_type as
  72. // OutputFilter.
  73. // OutputFilter - A model of OutputFilter, with the same char_type as
  74. // InputFilter.
  75. //
  76. template<typename InputFilter, typename OutputFilter>
  77. class combined_filter {
  78. private:
  79. typedef typename category_of<InputFilter>::type in_category;
  80. typedef typename category_of<OutputFilter>::type out_category;
  81. typedef typename char_type_of<OutputFilter>::type output_char_type;
  82. public:
  83. typedef typename char_type_of<InputFilter>::type char_type;
  84. struct category
  85. : multichar_bidirectional_filter_tag,
  86. closable_tag,
  87. localizable_tag
  88. { };
  89. BOOST_STATIC_ASSERT(is_filter<InputFilter>::value);
  90. BOOST_STATIC_ASSERT(is_filter<OutputFilter>::value);
  91. BOOST_STATIC_ASSERT((is_convertible<in_category, input>::value));
  92. BOOST_STATIC_ASSERT((is_convertible<out_category, output>::value));
  93. BOOST_STATIC_ASSERT((is_same<char_type, output_char_type>::value));
  94. combined_filter(const InputFilter& in, const OutputFilter& out);
  95. template<typename Source>
  96. std::streamsize read(Source& src, char_type* s, std::streamsize n)
  97. { return boost::iostreams::read(in_, src, s, n); }
  98. template<typename Sink>
  99. std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
  100. { return boost::iostreams::write(out_, snk, s, n); }
  101. template<typename Sink>
  102. void close(Sink& snk, BOOST_IOS::openmode which)
  103. {
  104. if (which == BOOST_IOS::in) {
  105. if (is_convertible<in_category, dual_use>::value) {
  106. iostreams::close(in_, snk, BOOST_IOS::in);
  107. } else {
  108. detail::close_all(in_, snk);
  109. }
  110. }
  111. if (which == BOOST_IOS::out) {
  112. if (is_convertible<out_category, dual_use>::value) {
  113. iostreams::close(out_, snk, BOOST_IOS::out);
  114. } else {
  115. detail::close_all(out_, snk);
  116. }
  117. }
  118. }
  119. #ifndef BOOST_NO_STD_LOCALE
  120. void imbue(const std::locale& loc);
  121. #endif
  122. private:
  123. InputFilter in_;
  124. OutputFilter out_;
  125. };
  126. template<typename In, typename Out>
  127. struct combination_traits
  128. : mpl::if_<
  129. is_device<In>,
  130. combined_device<
  131. typename wrapped_type<In>::type,
  132. typename wrapped_type<Out>::type
  133. >,
  134. combined_filter<
  135. typename wrapped_type<In>::type,
  136. typename wrapped_type<Out>::type
  137. >
  138. >
  139. { };
  140. } // End namespace detail.
  141. template<typename In, typename Out>
  142. struct combination : detail::combination_traits<In, Out>::type {
  143. typedef typename detail::combination_traits<In, Out>::type base_type;
  144. typedef typename detail::wrapped_type<In>::type in_type;
  145. typedef typename detail::wrapped_type<Out>::type out_type;
  146. combination(const in_type& in, const out_type& out)
  147. : base_type(in, out) { }
  148. };
  149. namespace detail {
  150. // Workaround for VC6 ETI bug.
  151. template<typename In, typename Out>
  152. struct combine_traits {
  153. typedef combination<
  154. BOOST_DEDUCED_TYPENAME detail::unwrapped_type<In>::type,
  155. BOOST_DEDUCED_TYPENAME detail::unwrapped_type<Out>::type
  156. > type;
  157. };
  158. } // End namespace detail.
  159. //
  160. // Template name: combine.
  161. // Description: Takes a Source/Sink pair or InputFilter/OutputFilter pair and
  162. // returns a Source or Filter which performs input using the first member
  163. // of the pair and output using the second member of the pair.
  164. // Template parameters:
  165. // In - A model of Source or InputFilter, with the same char_type as Out.
  166. // Out - A model of Sink or OutputFilter, with the same char_type as In.
  167. //
  168. template<typename In, typename Out>
  169. typename detail::combine_traits<In, Out>::type
  170. combine(const In& in, const Out& out)
  171. {
  172. typedef typename detail::combine_traits<In, Out>::type return_type;
  173. return return_type(in, out);
  174. }
  175. //----------------------------------------------------------------------------//
  176. namespace detail {
  177. //--------------Implementation of combined_device-----------------------------//
  178. template<typename Source, typename Sink>
  179. inline combined_device<Source, Sink>::combined_device
  180. (const Source& src, const Sink& snk)
  181. : src_(src), sink_(snk) { }
  182. template<typename Source, typename Sink>
  183. inline std::streamsize
  184. combined_device<Source, Sink>::read(char_type* s, std::streamsize n)
  185. { return iostreams::read(src_, s, n); }
  186. template<typename Source, typename Sink>
  187. inline std::streamsize
  188. combined_device<Source, Sink>::write(const char_type* s, std::streamsize n)
  189. { return iostreams::write(sink_, s, n); }
  190. template<typename Source, typename Sink>
  191. inline void
  192. combined_device<Source, Sink>::close(BOOST_IOS::openmode which)
  193. {
  194. if (which == BOOST_IOS::in)
  195. detail::close_all(src_);
  196. if (which == BOOST_IOS::out)
  197. detail::close_all(sink_);
  198. }
  199. #ifndef BOOST_NO_STD_LOCALE
  200. template<typename Source, typename Sink>
  201. void combined_device<Source, Sink>::imbue(const std::locale& loc)
  202. {
  203. iostreams::imbue(src_, loc);
  204. iostreams::imbue(sink_, loc);
  205. }
  206. #endif
  207. //--------------Implementation of filter_pair---------------------------------//
  208. template<typename InputFilter, typename OutputFilter>
  209. inline combined_filter<InputFilter, OutputFilter>::combined_filter
  210. (const InputFilter& in, const OutputFilter& out) : in_(in), out_(out)
  211. { }
  212. #ifndef BOOST_NO_STD_LOCALE
  213. template<typename InputFilter, typename OutputFilter>
  214. void combined_filter<InputFilter, OutputFilter>::imbue
  215. (const std::locale& loc)
  216. {
  217. iostreams::imbue(in_, loc);
  218. iostreams::imbue(out_, loc);
  219. }
  220. #endif
  221. } // End namespace detail.
  222. } } // End namespaces iostreams, boost.
  223. #include <boost/iostreams/detail/config/enable_warnings.hpp>
  224. #endif // #ifndef BOOST_IOSTREAMS_COMBINE_HPP_INCLUDED