annotate DEPENDENCIES/generic/include/boost/iostreams/detail/adapter/direct_adapter.hpp @ 133:4acb5d8d80b6 tip

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