/Src/Dependencies/Boost/boost/iostreams/detail/adapter/direct_adapter.hpp

http://hadesmem.googlecode.com/ · C++ Header · 281 lines · 231 code · 35 blank · 15 comment · 25 complexity · 0ecd5660c3d144b5350665ae9d8bd7b9 MD5 · raw file

  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. #ifndef BOOST_IOSTREAMS_DETAIL_DIRECT_ADAPTER_HPP_INCLUDED
  7. #define BOOST_IOSTREAMS_DETAIL_DIRECT_ADAPTER_HPP_INCLUDED
  8. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  9. # pragma once
  10. #endif
  11. #include <boost/config.hpp> // SFINAE, MSVC, put ptrdiff_t in std.
  12. #include <algorithm> // copy, min.
  13. #include <cstddef> // ptrdiff_t.
  14. #include <boost/detail/workaround.hpp>
  15. #include <boost/iostreams/categories.hpp>
  16. #include <boost/iostreams/detail/config/limits.hpp> // forwarding.
  17. #include <boost/iostreams/detail/config/wide_streams.hpp> // locale.
  18. #include <boost/iostreams/detail/double_object.hpp>
  19. #include <boost/iostreams/detail/error.hpp>
  20. #include <boost/iostreams/detail/ios.hpp> // openmode, seekdir, int types.
  21. #include <boost/iostreams/traits.hpp> // mode_of, is_direct.
  22. #include <boost/iostreams/operations.hpp>
  23. #include <boost/mpl/bool.hpp>
  24. #include <boost/mpl/or.hpp>
  25. #include <boost/preprocessor/iteration/local.hpp>
  26. #include <boost/preprocessor/repetition/enum_binary_params.hpp>
  27. #include <boost/preprocessor/repetition/enum_params.hpp>
  28. #include <boost/static_assert.hpp>
  29. #include <boost/throw_exception.hpp>
  30. #include <boost/type_traits/is_convertible.hpp>
  31. // Must come last.
  32. #include <boost/iostreams/detail/config/disable_warnings.hpp> // VC7.1
  33. namespace boost { namespace iostreams { namespace detail {
  34. //------------------Definition of direct_adapter_base-------------------------//
  35. // Put all initialization in base class to faciliate forwarding.
  36. template<typename Direct>
  37. class direct_adapter_base {
  38. public:
  39. typedef typename char_type_of<Direct>::type char_type;
  40. typedef typename mode_of<Direct>::type mode_type;
  41. struct category
  42. : mode_type,
  43. device_tag,
  44. closable_tag
  45. #ifndef BOOST_IOSTREAMS_NO_LOCALE
  46. , localizable_tag
  47. #endif
  48. { };
  49. protected:
  50. explicit direct_adapter_base(const Direct& d);
  51. typedef is_convertible<category, two_sequence> is_double;
  52. struct pointers {
  53. char_type *beg, *ptr, *end;
  54. };
  55. void init_input(mpl::true_);
  56. void init_input(mpl::false_) { }
  57. void init_output(mpl::true_);
  58. void init_output(mpl::false_) { }
  59. double_object<pointers, is_double> ptrs_;
  60. Direct d_;
  61. };
  62. template<typename Direct>
  63. class direct_adapter : private direct_adapter_base<Direct> {
  64. private:
  65. typedef direct_adapter_base<Direct> base_type;
  66. typedef typename base_type::pointers pointers;
  67. typedef typename base_type::is_double is_double;
  68. using base_type::ptrs_;
  69. using base_type::d_;
  70. public:
  71. typedef typename base_type::char_type char_type;
  72. typedef typename base_type::category category;
  73. // Constructors
  74. #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
  75. direct_adapter(const Direct& d) : base_type(d) { }
  76. direct_adapter(const direct_adapter& d) : base_type(d) { }
  77. # define BOOST_PP_LOCAL_LIMITS (1, BOOST_IOSTREAMS_MAX_FORWARDING_ARITY)
  78. #else
  79. template<typename U>
  80. struct is_direct
  81. : mpl::or_<
  82. is_same<U, direct_adapter<Direct> >,
  83. is_same<U, Direct>
  84. >
  85. { };
  86. template<typename U>
  87. direct_adapter(const U& u)
  88. : base_type(forward(u, is_direct<U>()))
  89. { }
  90. # define BOOST_PP_LOCAL_LIMITS (2, BOOST_IOSTREAMS_MAX_FORWARDING_ARITY)
  91. #endif
  92. #define BOOST_PP_LOCAL_MACRO(n) \
  93. template<BOOST_PP_ENUM_PARAMS(n, typename P)> \
  94. direct_adapter(BOOST_PP_ENUM_BINARY_PARAMS(n, const P, &p)) \
  95. : base_type(Direct(BOOST_PP_ENUM_PARAMS(n, p))) \
  96. { } \
  97. /**/
  98. #include BOOST_PP_LOCAL_ITERATE()
  99. #undef BOOST_PP_LOCAL_MACRO
  100. // Device interface.
  101. std::streamsize read(char_type* s, std::streamsize n);
  102. std::streamsize write(const char_type* s, std::streamsize n);
  103. std::streampos seek( stream_offset, BOOST_IOS::seekdir,
  104. BOOST_IOS::openmode = BOOST_IOS::in | BOOST_IOS::out );
  105. void close();
  106. void close(BOOST_IOS::openmode which);
  107. #ifndef BOOST_IOSTREAMS_NO_LOCALE
  108. void imbue(const std::locale&);
  109. #endif
  110. // Direct device access.
  111. Direct& operator*() { return d_; }
  112. Direct* operator->() { return &d_; }
  113. #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
  114. private:
  115. template<typename U>
  116. static Direct forward(const U& u, mpl::true_) { return u; }
  117. template<typename U>
  118. static Direct forward(const U& u, mpl::false_) { return Direct(u); }
  119. #endif
  120. };
  121. //--------------Definition of wrap_direct and unwrap_direct-------------------//
  122. template<typename Device>
  123. struct wrap_direct_traits
  124. : mpl::if_<
  125. is_direct<Device>,
  126. direct_adapter<Device>,
  127. Device
  128. >
  129. { };
  130. template<typename Device>
  131. typename wrap_direct_traits<Device>::type
  132. inline wrap_direct(Device dev)
  133. {
  134. typedef typename wrap_direct_traits<Device>::type type;
  135. return type(dev);
  136. }
  137. template<typename Device>
  138. inline Device& unwrap_direct(Device& d) { return d; }
  139. template<typename Device>
  140. inline Device& unwrap_direct(direct_adapter<Device>& d) { return *d; }
  141. //--------------Implementation of direct_adapter_base-------------------------//
  142. template<typename Direct>
  143. direct_adapter_base<Direct>::direct_adapter_base(const Direct& d) : d_(d)
  144. {
  145. init_input(is_convertible<category, input>());
  146. init_output(is_convertible<category, output>());
  147. }
  148. template<typename Direct>
  149. void direct_adapter_base<Direct>::init_input(mpl::true_)
  150. {
  151. std::pair<char_type*, char_type*> seq = iostreams::input_sequence(d_);
  152. ptrs_.first().beg = seq.first;
  153. ptrs_.first().ptr = seq.first;
  154. ptrs_.first().end = seq.second;
  155. }
  156. template<typename Direct>
  157. void direct_adapter_base<Direct>::init_output(mpl::true_)
  158. {
  159. std::pair<char_type*, char_type*> seq = iostreams::output_sequence(d_);
  160. ptrs_.second().beg = seq.first;
  161. ptrs_.second().ptr = seq.first;
  162. ptrs_.second().end = seq.second;
  163. }
  164. //--------------Implementation of direct_adapter------------------------------//
  165. template<typename Direct>
  166. inline std::streamsize direct_adapter<Direct>::read
  167. (char_type* s, std::streamsize n)
  168. {
  169. using namespace std;
  170. pointers& get = ptrs_.first();
  171. std::streamsize avail =
  172. static_cast<std::streamsize>(get.end - get.ptr);
  173. std::streamsize result = (std::min)(n, avail);
  174. std::copy(get.ptr, get.ptr + result, s);
  175. get.ptr += result;
  176. return result != 0 ? result : -1;
  177. }
  178. template<typename Direct>
  179. inline std::streamsize direct_adapter<Direct>::write
  180. (const char_type* s, std::streamsize n)
  181. {
  182. using namespace std;
  183. pointers& put = ptrs_.second();
  184. if (n > static_cast<std::streamsize>(put.end - put.ptr))
  185. boost::throw_exception(write_area_exhausted());
  186. std::copy(s, s + n, put.ptr);
  187. put.ptr += n;
  188. return n;
  189. }
  190. template<typename Direct>
  191. inline std::streampos direct_adapter<Direct>::seek
  192. ( stream_offset off, BOOST_IOS::seekdir way,
  193. BOOST_IOS::openmode which )
  194. {
  195. using namespace std;
  196. pointers& get = ptrs_.first();
  197. pointers& put = ptrs_.second();
  198. if (way == BOOST_IOS::cur && get.ptr != put.ptr)
  199. boost::throw_exception(bad_seek());
  200. ptrdiff_t next = 0;
  201. if ((which & BOOST_IOS::in) || !is_double::value) {
  202. if (way == BOOST_IOS::beg)
  203. next = off;
  204. else if (way == BOOST_IOS::cur)
  205. next = get.ptr - get.beg + off;
  206. else
  207. next = get.end - get.beg + off;
  208. if (next >= 0 && next <= get.end - get.beg)
  209. get.ptr = get.beg + next;
  210. else
  211. boost::throw_exception(bad_seek());
  212. }
  213. if ((which & BOOST_IOS::out) && is_double::value) {
  214. if (way == BOOST_IOS::beg)
  215. next = off;
  216. else if (way == BOOST_IOS::cur)
  217. next = put.ptr - put.beg + off;
  218. else
  219. next = put.end - put.beg + off;
  220. if (next >= 0 && next <= put.end - put.beg)
  221. put.ptr = put.beg + next;
  222. else
  223. boost::throw_exception(bad_seek());
  224. }
  225. return offset_to_position(next);
  226. }
  227. template<typename Direct>
  228. void direct_adapter<Direct>::close()
  229. {
  230. BOOST_STATIC_ASSERT((!is_convertible<category, two_sequence>::value));
  231. detail::close_all(d_);
  232. }
  233. template<typename Direct>
  234. void direct_adapter<Direct>::close(BOOST_IOS::openmode which)
  235. {
  236. BOOST_STATIC_ASSERT((is_convertible<category, two_sequence>::value));
  237. boost::iostreams::close(d_, which);
  238. }
  239. #ifndef BOOST_IOSTREAMS_NO_LOCALE
  240. template<typename Direct>
  241. void direct_adapter<Direct>::imbue(const std::locale& loc)
  242. { boost::iostreams::imbue(d_, loc); }
  243. #endif
  244. } } } // End namespaces detail, iostreams, boost.
  245. #include <boost/iostreams/detail/config/enable_warnings.hpp>
  246. #endif // #ifndef BOOST_IOSTREAMS_DETAIL_DIRECT_ADAPTER_HPP_INCLUDED