Warning, file /include/boost/iostreams/detail/restrict_impl.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #if !defined(BOOST_IOSTREAMS_RESTRICT_IMPL_HPP_INCLUDED) && \
0024 !defined(BOOST_IOSTREAMS_RESTRICT)
0025 # define BOOST_IOSTREAMS_RESTRICT_IMPL_HPP_INCLUDED
0026
0027
0028
0029 # include <algorithm> // min.
0030 # include <utility> // pair.
0031 # include <boost/cstdint.hpp> // intmax_t.
0032 # include <boost/config.hpp> // DEDUCED_TYPENAME.
0033 # include <boost/iostreams/categories.hpp>
0034 # include <boost/iostreams/char_traits.hpp>
0035 # include <boost/iostreams/detail/adapter/device_adapter.hpp>
0036 # include <boost/iostreams/detail/adapter/filter_adapter.hpp>
0037 # include <boost/iostreams/detail/call_traits.hpp>
0038 # include <boost/iostreams/detail/enable_if_stream.hpp>
0039 # include <boost/iostreams/detail/error.hpp>
0040 # include <boost/iostreams/detail/ios.hpp> // failure.
0041 # include <boost/iostreams/detail/select.hpp>
0042 # include <boost/iostreams/operations.hpp>
0043 # include <boost/iostreams/skip.hpp>
0044 # include <boost/iostreams/traits.hpp> // mode_of, is_direct.
0045 # include <boost/mpl/bool.hpp>
0046 # include <boost/static_assert.hpp>
0047 # include <boost/throw_exception.hpp>
0048 # include <boost/type_traits/is_convertible.hpp>
0049
0050 # include <boost/iostreams/detail/config/disable_warnings.hpp>
0051
0052 namespace boost { namespace iostreams {
0053
0054 namespace detail {
0055
0056
0057
0058
0059
0060
0061
0062
0063 template<typename Device>
0064 class restricted_indirect_device : public device_adapter<Device> {
0065 private:
0066 typedef typename detail::param_type<Device>::type param_type;
0067 public:
0068 typedef typename char_type_of<Device>::type char_type;
0069 typedef typename mode_of<Device>::type mode;
0070 BOOST_STATIC_ASSERT(!(is_convertible<mode, detail::two_sequence>::value));
0071 struct category
0072 : mode,
0073 device_tag,
0074 closable_tag,
0075 flushable_tag,
0076 localizable_tag,
0077 optimally_buffered_tag
0078 { };
0079 restricted_indirect_device( param_type dev, stream_offset off,
0080 stream_offset len = -1 );
0081 std::streamsize read(char_type* s, std::streamsize n);
0082 std::streamsize write(const char_type* s, std::streamsize n);
0083 std::streampos seek(stream_offset off, BOOST_IOS::seekdir way);
0084 private:
0085 stream_offset beg_, pos_, end_;
0086 };
0087
0088
0089
0090
0091
0092
0093
0094 template<typename Device>
0095 class restricted_direct_device : public device_adapter<Device> {
0096 public:
0097 typedef typename char_type_of<Device>::type char_type;
0098 typedef std::pair<char_type*, char_type*> pair_type;
0099 typedef typename mode_of<Device>::type mode;
0100 BOOST_STATIC_ASSERT(!(is_convertible<mode, detail::two_sequence>::value));
0101 struct category
0102 : mode_of<Device>::type,
0103 device_tag,
0104 direct_tag,
0105 closable_tag,
0106 localizable_tag
0107 { };
0108 restricted_direct_device( const Device& dev, stream_offset off,
0109 stream_offset len = -1 );
0110 pair_type input_sequence();
0111 pair_type output_sequence();
0112 private:
0113 pair_type sequence(mpl::true_);
0114 pair_type sequence(mpl::false_);
0115 char_type *beg_, *end_;
0116 };
0117
0118
0119
0120
0121
0122
0123
0124 template<typename Filter>
0125 class restricted_filter : public filter_adapter<Filter> {
0126 public:
0127 typedef typename char_type_of<Filter>::type char_type;
0128 typedef typename mode_of<Filter>::type mode;
0129 BOOST_STATIC_ASSERT(!(is_convertible<mode, detail::two_sequence>::value));
0130 struct category
0131 : mode,
0132 filter_tag,
0133 multichar_tag,
0134 closable_tag,
0135 localizable_tag,
0136 optimally_buffered_tag
0137 { };
0138 restricted_filter( const Filter& flt, stream_offset off,
0139 stream_offset len = -1 );
0140
0141 template<typename Source>
0142 std::streamsize read(Source& src, char_type* s, std::streamsize n)
0143 {
0144 using namespace std;
0145 if (!open_)
0146 open(src, BOOST_IOS::in);
0147 std::streamsize amt =
0148 end_ != -1 ?
0149 (std::min) (n, static_cast<std::streamsize>(end_ - pos_)) :
0150 n;
0151 std::streamsize result =
0152 iostreams::read(this->component(), src, s, amt);
0153 if (result != -1)
0154 pos_ += result;
0155 return result;
0156 }
0157
0158 template<typename Sink>
0159 std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
0160 {
0161 if (!open_)
0162 open(snk, BOOST_IOS::out);
0163 if (end_ != -1 && pos_ + n >= end_) {
0164 if(pos_ < end_)
0165 pos_ += iostreams::write(this->component(),
0166 snk, s, end_ - pos_);
0167 boost::throw_exception(bad_write());
0168 }
0169 std::streamsize result =
0170 iostreams::write(this->component(), snk, s, n);
0171 pos_ += result;
0172 return result;
0173 }
0174
0175 template<typename Device>
0176 std::streampos seek(Device& dev, stream_offset off, BOOST_IOS::seekdir way)
0177 {
0178 stream_offset next;
0179 if (way == BOOST_IOS::beg) {
0180 next = beg_ + off;
0181 } else if (way == BOOST_IOS::cur) {
0182 next = pos_ + off;
0183 } else if (end_ != -1) {
0184 next = end_ + off;
0185 } else {
0186
0187 pos_ = this->component().seek(dev, off, BOOST_IOS::end);
0188 if (pos_ < beg_)
0189 boost::throw_exception(bad_seek());
0190 return offset_to_position(pos_ - beg_);
0191 }
0192 if (next < beg_ || (end_ != -1 && next >= end_))
0193 boost::throw_exception(bad_seek());
0194 pos_ = this->component().seek(dev, next, BOOST_IOS::cur);
0195 return offset_to_position(pos_ - beg_);
0196 }
0197
0198 template<typename Device>
0199 void close(Device& dev)
0200 {
0201 open_ = false;
0202 detail::close_all(this->component(), dev);
0203 }
0204
0205 template<typename Device>
0206 void close(Device& dev, BOOST_IOS::openmode which)
0207 {
0208 open_ = false;
0209 iostreams::close(this->component(), dev, which);
0210 }
0211 private:
0212 template<typename Device>
0213 void open(Device& dev, BOOST_IOS::openmode which)
0214 {
0215 typedef typename is_convertible<mode, dual_use>::type is_dual_use;
0216 open_ = true;
0217 which = is_dual_use() ? which : (BOOST_IOS::in | BOOST_IOS::out);
0218 iostreams::skip(this->component(), dev, beg_, which);
0219 }
0220
0221 stream_offset beg_, pos_, end_;
0222 bool open_;
0223 };
0224
0225 template<typename T>
0226 struct restriction_traits
0227 : iostreams::select<
0228 is_filter<T>, restricted_filter<T>,
0229 is_direct<T>, restricted_direct_device<T>,
0230 else_, restricted_indirect_device<T>
0231 >
0232 { };
0233
0234 }
0235
0236 template<typename T>
0237 struct restriction : public detail::restriction_traits<T>::type {
0238 typedef typename detail::param_type<T>::type param_type;
0239 typedef typename detail::restriction_traits<T>::type base_type;
0240 restriction(param_type t, stream_offset off, stream_offset len = -1)
0241 : base_type(t, off, len)
0242 { }
0243 };
0244
0245 namespace detail {
0246
0247
0248
0249 template<typename Device>
0250 restricted_indirect_device<Device>::restricted_indirect_device
0251 (param_type dev, stream_offset off, stream_offset len)
0252 : device_adapter<Device>(dev), beg_(off), pos_(off),
0253 end_(len != -1 ? off + len : -1)
0254 {
0255 if (len < -1 || off < 0)
0256 boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad offset"));
0257 iostreams::skip(this->component(), off);
0258 }
0259
0260 template<typename Device>
0261 inline std::streamsize restricted_indirect_device<Device>::read
0262 (char_type* s, std::streamsize n)
0263 {
0264 using namespace std;
0265 std::streamsize amt =
0266 end_ != -1 ?
0267 (std::min) (n, static_cast<std::streamsize>(end_ - pos_)) :
0268 n;
0269 std::streamsize result = iostreams::read(this->component(), s, amt);
0270 if (result != -1)
0271 pos_ += result;
0272 return result;
0273 }
0274
0275 template<typename Device>
0276 inline std::streamsize restricted_indirect_device<Device>::write
0277 (const char_type* s, std::streamsize n)
0278 {
0279 if (end_ != -1 && pos_ + n >= end_) {
0280 if(pos_ < end_)
0281 pos_ += iostreams::write(this->component(), s, end_ - pos_);
0282 boost::throw_exception(bad_write());
0283 }
0284 std::streamsize result = iostreams::write(this->component(), s, n);
0285 pos_ += result;
0286 return result;
0287 }
0288
0289 template<typename Device>
0290 std::streampos restricted_indirect_device<Device>::seek
0291 (stream_offset off, BOOST_IOS::seekdir way)
0292 {
0293 stream_offset next;
0294 if (way == BOOST_IOS::beg) {
0295 next = beg_ + off;
0296 } else if (way == BOOST_IOS::cur) {
0297 next = pos_ + off;
0298 } else if (end_ != -1) {
0299 next = end_ + off;
0300 } else {
0301
0302 pos_ = iostreams::seek(this->component(), off, BOOST_IOS::end);
0303 if (pos_ < beg_)
0304 boost::throw_exception(bad_seek());
0305 return offset_to_position(pos_ - beg_);
0306 }
0307 if (next < beg_ || (end_ != -1 && next > end_))
0308 boost::throw_exception(bad_seek());
0309 pos_ = iostreams::seek(this->component(), next - pos_, BOOST_IOS::cur);
0310 return offset_to_position(pos_ - beg_);
0311 }
0312
0313
0314
0315 template<typename Device>
0316 restricted_direct_device<Device>::restricted_direct_device
0317 (const Device& dev, stream_offset off, stream_offset len)
0318 : device_adapter<Device>(dev), beg_(0), end_(0)
0319 {
0320 std::pair<char_type*, char_type*> seq =
0321 sequence(is_convertible<category, input>());
0322 if ( off < 0 || len < -1 ||
0323 (len != -1 && off + len > seq.second - seq.first) )
0324 {
0325 boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad offset"));
0326 }
0327 beg_ = seq.first + off;
0328 end_ = len != -1 ?
0329 seq.first + off + len :
0330 seq.second;
0331 }
0332
0333 template<typename Device>
0334 typename restricted_direct_device<Device>::pair_type
0335 restricted_direct_device<Device>::input_sequence()
0336 {
0337 BOOST_STATIC_ASSERT((is_convertible<category, input>::value));
0338 return std::make_pair(beg_, end_);
0339 }
0340
0341 template<typename Device>
0342 typename restricted_direct_device<Device>::pair_type
0343 restricted_direct_device<Device>::output_sequence()
0344 {
0345 BOOST_STATIC_ASSERT((is_convertible<category, output>::value));
0346 return std::make_pair(beg_, end_);
0347 }
0348
0349 template<typename Device>
0350 typename restricted_direct_device<Device>::pair_type
0351 restricted_direct_device<Device>::sequence(mpl::true_)
0352 { return iostreams::input_sequence(this->component()); }
0353
0354 template<typename Device>
0355 typename restricted_direct_device<Device>::pair_type
0356 restricted_direct_device<Device>::sequence(mpl::false_)
0357 { return iostreams::output_sequence(this->component()); }
0358
0359
0360
0361 template<typename Filter>
0362 restricted_filter<Filter>::restricted_filter
0363 (const Filter& flt, stream_offset off, stream_offset len)
0364 : filter_adapter<Filter>(flt), beg_(off),
0365 pos_(off), end_(len != -1 ? off + len : -1), open_(false)
0366 {
0367 if (len < -1 || off < 0)
0368 boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad offset"));
0369 }
0370
0371 }
0372
0373 } }
0374
0375 #elif defined(BOOST_IOSTREAMS_RESTRICT)
0376
0377 namespace boost { namespace iostreams {
0378
0379
0380
0381
0382
0383
0384 # ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION
0385 # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES
0386
0387 template<typename T>
0388 restriction<T>
0389 BOOST_IOSTREAMS_RESTRICT( const T& t, stream_offset off, stream_offset len = -1
0390 BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) )
0391 { return restriction<T>(t, off, len); }
0392
0393 template<typename Ch, typename Tr>
0394 restriction< std::basic_streambuf<Ch, Tr> >
0395 BOOST_IOSTREAMS_RESTRICT( std::basic_streambuf<Ch, Tr>& sb, stream_offset off,
0396 stream_offset len = -1 )
0397 { return restriction< std::basic_streambuf<Ch, Tr> >(sb, off, len); }
0398
0399 template<typename Ch, typename Tr>
0400 restriction< std::basic_istream<Ch, Tr> >
0401 BOOST_IOSTREAMS_RESTRICT
0402 (std::basic_istream<Ch, Tr>& is, stream_offset off, stream_offset len = -1)
0403 { return restriction< std::basic_istream<Ch, Tr> >(is, off, len); }
0404
0405 template<typename Ch, typename Tr>
0406 restriction< std::basic_ostream<Ch, Tr> >
0407 BOOST_IOSTREAMS_RESTRICT
0408 (std::basic_ostream<Ch, Tr>& os, stream_offset off, stream_offset len = -1)
0409 { return restriction< std::basic_ostream<Ch, Tr> >(os, off, len); }
0410
0411 template<typename Ch, typename Tr>
0412 restriction< std::basic_iostream<Ch, Tr> >
0413 BOOST_IOSTREAMS_RESTRICT
0414 (std::basic_iostream<Ch, Tr>& io, stream_offset off, stream_offset len = -1)
0415 { return restriction< std::basic_iostream<Ch, Tr> >(io, off, len); }
0416
0417 # else
0418
0419 template<typename T>
0420 restriction<T>
0421 BOOST_IOSTREAMS_RESTRICT( const T& t, stream_offset off, stream_offset len = -1
0422 BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) )
0423 { return restriction<T>(t, off, len); }
0424
0425 restriction<std::streambuf>
0426 BOOST_IOSTREAMS_RESTRICT
0427 (std::streambuf& sb, stream_offset off, stream_offset len = -1)
0428 { return restriction<std::streambuf>(sb, off, len); }
0429
0430 restriction<std::istream>
0431 BOOST_IOSTREAMS_RESTRICT
0432 (std::istream<Ch, Tr>& is, stream_offset off, stream_offset len = -1)
0433 { return restriction<std::istream>(is, off, len); }
0434
0435 restriction<std::ostream>
0436 BOOST_IOSTREAMS_RESTRICT
0437 (std::ostream<Ch, Tr>& os, stream_offset off, stream_offset len = -1)
0438 { return restriction<std::ostream>(os, off, len); }
0439
0440 restriction<std::iostream>
0441 BOOST_IOSTREAMS_RESTRICT
0442 (std::iostream<Ch, Tr>& io, stream_offset off, stream_offset len = -1)
0443 { return restriction<std::iostream>(io, off, len); }
0444
0445 # endif
0446 # else
0447
0448 template<typename T>
0449 restriction<T>
0450 BOOST_IOSTREAMS_RESTRICT
0451 (const T& t, stream_offset off, stream_offset len, mpl::true_)
0452 {
0453 return restriction<T>(const_cast<T&>(t, off, len));
0454 }
0455
0456 template<typename T>
0457 restriction<T>
0458 BOOST_IOSTREAMS_RESTRICT
0459 (const T& t, stream_offset off, stream_offset len, mpl::false_)
0460 { return restriction<T>(t, off, len); }
0461
0462 template<typename T>
0463 restriction<T>
0464 BOOST_IOSTREAMS_RESTRICT( const T& t, stream_offset off, stream_offset len = -1
0465 BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) )
0466 { return BOOST_IOSTREAMS_RESTRICT(t, off, len, is_std_io<T>()); }
0467
0468 # if !BOOST_WORKAROUND(BOOST_BORLANDC, < 0x600) && \
0469 !defined(__GNUC__)
0470
0471 template<typename T>
0472 restriction<T>
0473 BOOST_IOSTREAMS_RESTRICT(T& t, stream_offset off, stream_offset len = -1)
0474 { return restriction<T>(t, off, len); }
0475
0476 # endif
0477 # endif
0478
0479 } }
0480
0481 # include <boost/iostreams/detail/config/enable_warnings.hpp>
0482
0483 #endif