File indexing completed on 2025-01-18 09:38:50
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