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 6 // See http://www.boost.org/libs/iostreams for documentation. 7 8 #ifndef BOOST_IOSTREAMS_DETAIL_CONCEPT_ADAPTER_HPP_INCLUDED 9 #define BOOST_IOSTREAMS_DETAIL_CONCEPT_ADAPTER_HPP_INCLUDED 10 11 #include <boost/config.hpp> // SFINAE. 12 #include <boost/iostreams/concepts.hpp> 13 #include <boost/iostreams/categories.hpp> 14 #include <boost/iostreams/detail/adapter/non_blocking_adapter.hpp> 15 #include <boost/iostreams/detail/call_traits.hpp> 16 #include <boost/iostreams/detail/char_traits.hpp> 17 #include <boost/iostreams/detail/dispatch.hpp> 18 #include <boost/iostreams/detail/error.hpp> 19 #include <boost/iostreams/detail/streambuf.hpp> // pubsync. 20 #include <boost/iostreams/detail/config/unreachable_return.hpp> 21 #include <boost/iostreams/device/null.hpp> 22 #include <boost/iostreams/traits.hpp> 23 #include <boost/iostreams/operations.hpp> 24 #include <boost/mpl/if.hpp> 25 #include <boost/static_assert.hpp> 26 #include <boost/throw_exception.hpp> 27 28 // Must come last. 29 #include <boost/iostreams/detail/config/disable_warnings.hpp> // MSVC. 30 31 32 namespace boost { namespace iostreams { namespace detail { 33 34 template<typename Category> struct device_wrapper_impl; 35 template<typename Category> struct flt_wrapper_impl; 36 37 template<typename T> 38 class concept_adapter { 39 private: 40 typedef typename detail::value_type<T>::type value_type; 41 typedef typename dispatch<T, input, output>::type input_tag; 42 typedef typename dispatch<T, output, input>::type output_tag; 43 typedef typename 44 mpl::if_< 45 is_device<T>, 46 device_wrapper_impl<input_tag>, 47 flt_wrapper_impl<input_tag> 48 >::type input_impl; 49 typedef typename 50 mpl::if_< 51 is_device<T>, 52 device_wrapper_impl<output_tag>, 53 flt_wrapper_impl<output_tag> 54 >::type output_impl; 55 typedef typename 56 mpl::if_< 57 is_device<T>, 58 device_wrapper_impl<any_tag>, 59 flt_wrapper_impl<any_tag> 60 >::type any_impl; 61 public: 62 typedef typename char_type_of<T>::type char_type; 63 typedef typename category_of<T>::type category; 64 concept_adapter(const reference_wrapper<T> & ref)65 explicit concept_adapter(const reference_wrapper<T>& ref) : t_(ref.get()) 66 { BOOST_STATIC_ASSERT(is_std_io<T>::value); } concept_adapter(const T & t)67 explicit concept_adapter(const T& t) : t_(t) 68 { BOOST_STATIC_ASSERT(!is_std_io<T>::value); } 69 operator *()70 T& operator*() { return t_; } operator ->()71 T* operator->() { return &t_; } 72 read(char_type * s,std::streamsize n)73 std::streamsize read(char_type* s, std::streamsize n) 74 { return this->read(s, n, (basic_null_source<char_type>*) 0); } 75 76 template<typename Source> read(char_type * s,std::streamsize n,Source * src)77 std::streamsize read(char_type* s, std::streamsize n, Source* src) 78 { return input_impl::read(t_, src, s, n); } 79 write(const char_type * s,std::streamsize n)80 std::streamsize write(const char_type* s, std::streamsize n) 81 { return this->write(s, n, (basic_null_sink<char_type>*) 0); } 82 83 template<typename Sink> write(const char_type * s,std::streamsize n,Sink * snk)84 std::streamsize write(const char_type* s, std::streamsize n, Sink* snk) 85 { return output_impl::write(t_, snk, s, n); } 86 seek(stream_offset off,BOOST_IOS::seekdir way,BOOST_IOS::openmode which)87 std::streampos seek( stream_offset off, BOOST_IOS::seekdir way, 88 BOOST_IOS::openmode which ) 89 { 90 return this->seek( off, way, which, 91 (basic_null_device<char_type, seekable>*) 0); 92 } 93 94 template<typename Device> seek(stream_offset off,BOOST_IOS::seekdir way,BOOST_IOS::openmode which,Device * dev)95 std::streampos seek( stream_offset off, BOOST_IOS::seekdir way, 96 BOOST_IOS::openmode which, Device* dev ) 97 { return any_impl::seek(t_, dev, off, way, which); } 98 close(BOOST_IOS::openmode which)99 void close(BOOST_IOS::openmode which) 100 { this->close(which, (basic_null_device<char_type, seekable>*) 0); } 101 102 template<typename Device> close(BOOST_IOS::openmode which,Device * dev)103 void close(BOOST_IOS::openmode which, Device* dev) 104 { any_impl::close(t_, dev, which); } 105 106 template<typename Device> flush(Device * dev)107 bool flush( Device* dev ) 108 { 109 bool result = any_impl::flush(t_, dev); 110 if (dev && dev->BOOST_IOSTREAMS_PUBSYNC() == -1) 111 result = false; 112 return result; 113 } 114 115 template<typename Locale> // Avoid dependency on <locale> imbue(const Locale & loc)116 void imbue(const Locale& loc) { iostreams::imbue(t_, loc); } 117 optimal_buffer_size() const118 std::streamsize optimal_buffer_size() const 119 { return iostreams::optimal_buffer_size(t_); } 120 public: 121 concept_adapter& operator=(const concept_adapter&); 122 value_type t_; 123 }; 124 125 //------------------Specializations of device_wrapper_impl--------------------// 126 127 template<> 128 struct device_wrapper_impl<any_tag> { 129 template<typename Device, typename Dummy> 130 static std::streampos seekboost::iostreams::detail::device_wrapper_impl131 seek( Device& dev, Dummy*, stream_offset off, 132 BOOST_IOS::seekdir way, BOOST_IOS::openmode which ) 133 { 134 typedef typename category_of<Device>::type category; 135 return seek(dev, off, way, which, category()); 136 } 137 138 template<typename Device> 139 static std::streampos seekboost::iostreams::detail::device_wrapper_impl140 seek( Device&, stream_offset, BOOST_IOS::seekdir, 141 BOOST_IOS::openmode, any_tag ) 142 { 143 boost::throw_exception(cant_seek()); 144 BOOST_IOSTREAMS_UNREACHABLE_RETURN(0) 145 } 146 147 template<typename Device> 148 static std::streampos seekboost::iostreams::detail::device_wrapper_impl149 seek( Device& dev, stream_offset off, 150 BOOST_IOS::seekdir way, BOOST_IOS::openmode which, 151 random_access ) 152 { 153 return iostreams::seek(dev, off, way, which); 154 } 155 156 template<typename Device, typename Dummy> closeboost::iostreams::detail::device_wrapper_impl157 static void close(Device& dev, Dummy*, BOOST_IOS::openmode which) 158 { iostreams::close(dev, which); } 159 160 template<typename Device, typename Dummy> flushboost::iostreams::detail::device_wrapper_impl161 static bool flush(Device& dev, Dummy*) 162 { return iostreams::flush(dev); } 163 }; 164 165 166 template<> 167 struct device_wrapper_impl<input> : device_wrapper_impl<any_tag> { 168 template<typename Device, typename Dummy> 169 static std::streamsize readboost::iostreams::detail::device_wrapper_impl170 read( Device& dev, Dummy*, typename char_type_of<Device>::type* s, 171 std::streamsize n ) 172 { return iostreams::read(dev, s, n); } 173 174 template<typename Device, typename Dummy> 175 static std::streamsize writeboost::iostreams::detail::device_wrapper_impl176 write( Device&, Dummy*, const typename char_type_of<Device>::type*, 177 std::streamsize ) 178 { boost::throw_exception(cant_write()); 179 BOOST_IOSTREAMS_UNREACHABLE_RETURN(0) } 180 }; 181 182 template<> 183 struct device_wrapper_impl<output> { 184 template<typename Device, typename Dummy> 185 static std::streamsize readboost::iostreams::detail::device_wrapper_impl186 read(Device&, Dummy*, typename char_type_of<Device>::type*, std::streamsize) 187 { boost::throw_exception(cant_read()); 188 BOOST_IOSTREAMS_UNREACHABLE_RETURN(0) } 189 190 template<typename Device, typename Dummy> 191 static std::streamsize writeboost::iostreams::detail::device_wrapper_impl192 write( Device& dev, Dummy*, const typename char_type_of<Device>::type* s, 193 std::streamsize n ) 194 { return iostreams::write(dev, s, n); } 195 }; 196 197 //------------------Specializations of flt_wrapper_impl--------------------// 198 199 template<> 200 struct flt_wrapper_impl<any_tag> { 201 template<typename Filter, typename Device> 202 static std::streampos seekboost::iostreams::detail::flt_wrapper_impl203 seek( Filter& f, Device* dev, stream_offset off, 204 BOOST_IOS::seekdir way, BOOST_IOS::openmode which ) 205 { 206 typedef typename category_of<Filter>::type category; 207 return seek(f, dev, off, way, which, category()); 208 } 209 210 template<typename Filter, typename Device> 211 static std::streampos seekboost::iostreams::detail::flt_wrapper_impl212 seek( Filter&, Device*, stream_offset, 213 BOOST_IOS::seekdir, BOOST_IOS::openmode, any_tag ) 214 { boost::throw_exception(cant_seek()); 215 BOOST_IOSTREAMS_UNREACHABLE_RETURN(0) } 216 217 template<typename Filter, typename Device> 218 static std::streampos seekboost::iostreams::detail::flt_wrapper_impl219 seek( Filter& f, Device* dev, stream_offset off, 220 BOOST_IOS::seekdir way, BOOST_IOS::openmode which, 221 random_access tag ) 222 { 223 typedef typename category_of<Filter>::type category; 224 return seek(f, dev, off, way, which, tag, category()); 225 } 226 227 template<typename Filter, typename Device> 228 static std::streampos seekboost::iostreams::detail::flt_wrapper_impl229 seek( Filter& f, Device* dev, stream_offset off, 230 BOOST_IOS::seekdir way, BOOST_IOS::openmode, 231 random_access, any_tag ) 232 { return f.seek(*dev, off, way); } 233 234 template<typename Filter, typename Device> 235 static std::streampos seekboost::iostreams::detail::flt_wrapper_impl236 seek( Filter& f, Device* dev, stream_offset off, 237 BOOST_IOS::seekdir way, BOOST_IOS::openmode which, 238 random_access, two_sequence ) 239 { return f.seek(*dev, off, way, which); } 240 241 template<typename Filter, typename Device> closeboost::iostreams::detail::flt_wrapper_impl242 static void close(Filter& f, Device* dev, BOOST_IOS::openmode which) 243 { iostreams::close(f, *dev, which); } 244 245 template<typename Filter, typename Device> flushboost::iostreams::detail::flt_wrapper_impl246 static bool flush(Filter& f, Device* dev) 247 { return iostreams::flush(f, *dev); } 248 }; 249 250 template<> 251 struct flt_wrapper_impl<input> { 252 template<typename Filter, typename Source> 253 static std::streamsize readboost::iostreams::detail::flt_wrapper_impl254 read( Filter& f, Source* src, typename char_type_of<Filter>::type* s, 255 std::streamsize n ) 256 { return iostreams::read(f, *src, s, n); } 257 258 template<typename Filter, typename Sink> 259 static std::streamsize writeboost::iostreams::detail::flt_wrapper_impl260 write( Filter&, Sink*, const typename char_type_of<Filter>::type*, 261 std::streamsize ) 262 { boost::throw_exception(cant_write()); 263 BOOST_IOSTREAMS_UNREACHABLE_RETURN(0) } 264 }; 265 266 template<> 267 struct flt_wrapper_impl<output> { 268 template<typename Filter, typename Source> 269 static std::streamsize readboost::iostreams::detail::flt_wrapper_impl270 read(Filter&, Source*, typename char_type_of<Filter>::type*,std::streamsize) 271 { boost::throw_exception(cant_read()); 272 BOOST_IOSTREAMS_UNREACHABLE_RETURN(0) } 273 274 template<typename Filter, typename Sink> 275 static std::streamsize writeboost::iostreams::detail::flt_wrapper_impl276 write( Filter& f, Sink* snk, const typename char_type_of<Filter>::type* s, 277 std::streamsize n ) 278 { return iostreams::write(f, *snk, s, n); } 279 }; 280 281 //----------------------------------------------------------------------------// 282 283 } } } // End namespaces detail, iostreams, boost. 284 285 #include <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC. 286 287 #endif // #ifndef BOOST_IOSTREAMS_DETAIL_CONCEPT_ADAPTER_HPP_INCLUDED 288