Ugly, not-to-be-pushed sucking in of all of Boost to get windows to work.
[dyninst.git] / external / boost / iostreams / restrict.hpp
1 // (C) Copyright Jonathan Turkanis 2005.
2 // Distributed under the Boost Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
4
5 // See http://www.boost.org/libs/iostreams for documentation.
6
7 #ifndef BOOST_IOSTREAMS_RESTRICT_HPP_INCLUDED
8 #define BOOST_IOSTREAMS_RESTRICT_HPP_INCLUDED
9
10 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
11 # pragma once
12 #endif
13
14 #include <algorithm>          // min.
15 #include <utility>            // pair.
16 #include <boost/cstdint.hpp>  // intmax_t.
17 #include <boost/config.hpp>   // DEDUCED_TYPENAME.
18 #include <boost/iostreams/categories.hpp>
19 #include <boost/iostreams/char_traits.hpp>
20 #include <boost/iostreams/detail/adapter/basic_adapter.hpp>
21 #include <boost/iostreams/detail/call_traits.hpp>
22 #include <boost/iostreams/detail/enable_if_stream.hpp>
23 #include <boost/iostreams/detail/error.hpp>
24 #include <boost/iostreams/detail/ios.hpp>     // failure.
25 #include <boost/iostreams/detail/select.hpp>
26 #include <boost/iostreams/operations.hpp>
27 #include <boost/iostreams/skip.hpp>
28 #include <boost/iostreams/traits.hpp>         // mode_of, is_direct.
29 #include <boost/mpl/bool.hpp>
30 #include <boost/static_assert.hpp>
31 #include <boost/type_traits/is_convertible.hpp>
32
33 #include <boost/iostreams/detail/config/disable_warnings.hpp> // VC7.1 C4244.
34
35 namespace boost { namespace iostreams {
36
37 namespace detail {
38
39 //
40 // Template name: restricted_indirect_device.
41 // Description: Provides an restricted view of an indirect Device.
42 // Template paramters:
43 //      Device - An indirect model of Device that models either Source or
44 //          SeekableDevice.
45 //
46 template<typename Device>
47 class restricted_indirect_device : public basic_adapter<Device> {
48 private:
49     typedef typename detail::param_type<Device>::type  param_type;
50 public:
51     typedef typename char_type_of<Device>::type        char_type;
52     struct category
53         : mode_of<Device>::type,
54           device_tag,
55           closable_tag,
56           flushable_tag,
57           localizable_tag,
58           optimally_buffered_tag
59         { };
60     restricted_indirect_device( param_type dev, stream_offset off,
61                                 stream_offset len = -1 );
62     std::streamsize read(char_type* s, std::streamsize n);
63     std::streamsize write(const char_type* s, std::streamsize n);
64     std::streampos seek(stream_offset off, BOOST_IOS::seekdir way);
65 private:
66     stream_offset beg_, pos_, end_;
67 };
68
69 //
70 // Template name: restricted_direct_device.
71 // Description: Provides an restricted view of a Direct Device.
72 // Template paramters:
73 //      Device - A model of Direct and Device.
74 //
75 template<typename Device>
76 class restricted_direct_device : public basic_adapter<Device> {
77 public:
78     typedef typename char_type_of<Device>::type  char_type;
79     typedef std::pair<char_type*, char_type*>    pair_type;
80     struct category
81         : mode_of<Device>::type,
82           device_tag,
83           direct_tag,
84           closable_tag,
85           localizable_tag
86         { };
87     restricted_direct_device( const Device& dev, stream_offset off,
88                               stream_offset len = -1 );
89     pair_type input_sequence();
90     pair_type output_sequence();
91 private:
92     pair_type sequence(mpl::true_);
93     pair_type sequence(mpl::false_);
94     char_type *beg_, *end_;
95 };
96
97 //
98 // Template name: restricted_filter.
99 // Description: Provides an restricted view of a Filter.
100 // Template paramters:
101 //      Filter - An indirect model of Filter.
102 //
103 template<typename Filter>
104 class restricted_filter : public basic_adapter<Filter> {
105 public:
106     typedef typename char_type_of<Filter>::type char_type;
107     struct category
108         : mode_of<Filter>::type,
109           filter_tag,
110           multichar_tag,
111           closable_tag,
112           localizable_tag,
113           optimally_buffered_tag
114         { };
115     restricted_filter( const Filter& flt, stream_offset off, 
116                        stream_offset len = -1 );
117
118     template<typename Source>
119     std::streamsize read(Source& src, char_type* s, std::streamsize n)
120     {
121         using namespace std;
122         if (!open_)
123             open(src);
124         streamsize amt =
125             end_ != -1 ?
126                 (std::min) (n, static_cast<streamsize>(end_ - pos_)) :
127                 n;
128         streamsize result = iostreams::read(this->component(), src, s, amt);
129         if (result != -1)
130             pos_ += result;
131         return result;
132     }
133
134     template<typename Sink>
135     std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
136     {
137         if (!open_)
138             open(snk);
139         if (end_ != -1 && pos_ + n >= end_)
140             bad_write();
141         std::streamsize result = 
142             iostreams::write(this->component(), snk, s, n);
143         pos_ += result;
144         return result;
145     }
146
147     template<typename Device>
148     std::streampos seek(Device& dev, stream_offset off, BOOST_IOS::seekdir way)
149     {
150         stream_offset next;
151         if (way == BOOST_IOS::beg) {
152             next = beg_ + off;
153         } else if (way == BOOST_IOS::cur) {
154             next = pos_ + off;
155         } else if (end_ != -1) {
156             next = end_ + off;
157         } else {
158             // Restriction is half-open; seek relative to the actual end.
159             pos_ = this->component().seek(dev, off, BOOST_IOS::end);
160             if (pos_ < beg_)
161                 bad_seek();
162             return offset_to_position(pos_ - beg_);
163         }
164         if (next < beg_ || end_ != -1 && next >= end_)
165             bad_seek();
166         pos_ = this->component().seek(dev, next, BOOST_IOS::cur);
167         return offset_to_position(pos_ - beg_);
168     }
169 private:
170     template<typename Device>
171     void open(Device& dev)
172     {
173         open_ = true;
174         iostreams::skip(this->component(), dev, beg_);
175     }
176     stream_offset  beg_, pos_, end_;
177     bool           open_;
178 };
179
180 template<typename T>
181 struct restriction_traits
182     : iostreams::select<  // Disambiguation for Tru64.
183           is_filter<T>,  restricted_filter<T>,
184           is_direct<T>,  restricted_direct_device<T>,
185           else_,         restricted_indirect_device<T>
186       >
187     { };
188
189 } // End namespace detail.
190
191 template<typename T>
192 struct restriction : public detail::restriction_traits<T>::type {
193     typedef typename detail::param_type<T>::type          param_type;
194     typedef typename detail::restriction_traits<T>::type  base_type;
195     restriction(param_type t, stream_offset off, stream_offset len = -1)
196         : base_type(t, off, len)
197         { }
198 };
199
200 //--------------Implementation of restrict------------------------------------//
201
202 // Note: The following workarounds are patterned after resolve.hpp. It has not
203 // yet been confirmed that they are necessary.
204
205 #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //-------------------------//
206 # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //-------------------------------//
207
208 template<typename T>
209 restriction<T> restrict( const T& t, stream_offset off, stream_offset len = -1
210                          BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) )
211 { return restriction<T>(t, off, len); }
212
213 template<typename Ch, typename Tr>
214 restriction< std::basic_streambuf<Ch, Tr> >
215 restrict(std::basic_streambuf<Ch, Tr>& sb, stream_offset off, stream_offset len = -1)
216 { return restriction< std::basic_streambuf<Ch, Tr> >(sb, off, len); }
217
218 template<typename Ch, typename Tr>
219 restriction< std::basic_istream<Ch, Tr> >
220 restrict(std::basic_istream<Ch, Tr>& is, stream_offset off, stream_offset len = -1)
221 { return restriction< std::basic_istream<Ch, Tr> >(is, off, len); }
222
223 template<typename Ch, typename Tr>
224 restriction< std::basic_ostream<Ch, Tr> >
225 restrict(std::basic_ostream<Ch, Tr>& os, stream_offset off, stream_offset len = -1)
226 { return restriction< std::basic_ostream<Ch, Tr> >(os, off, len); }
227
228 template<typename Ch, typename Tr>
229 restriction< std::basic_iostream<Ch, Tr> >
230 restrict(std::basic_iostream<Ch, Tr>& io, stream_offset off, stream_offset len = -1)
231 { return restriction< std::basic_iostream<Ch, Tr> >(io, off, len); }
232
233 # else // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //---------------------//
234
235 template<typename T>
236 restriction<T> restrict( const T& t, stream_offset off, stream_offset len = -1
237                          BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) )
238 { return restriction<T>(t, off, len); }
239
240 restriction<std::streambuf> 
241 restrict(std::streambuf& sb, stream_offset off, stream_offset len = -1)
242 { return restriction<std::streambuf>(sb, off, len); }
243
244 restriction<std::istream> 
245 restrict(std::istream<Ch, Tr>& is, stream_offset off, stream_offset len = -1)
246 { return restriction<std::istream>(is, off, len); }
247
248 restriction<std::ostream> 
249 restrict(std::ostream<Ch, Tr>& os, stream_offset off, stream_offset len = -1)
250 { return restriction<std::ostream>(os, off, len); }
251
252 restriction<std::iostream> 
253 restrict(std::iostream<Ch, Tr>& io, stream_offset off, stream_offset len = -1)
254 { return restriction<std::iostream>(io, off, len); }
255
256 # endif // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //--------------------//
257 #else // #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //----------------//
258
259 template<typename T>
260 restriction<T> 
261 restrict(const T& t, stream_offset off, stream_offset len, mpl::true_)
262 {   // Bad overload resolution.
263     return restriction<T>(const_cast<T&>(t, off, len));
264 }
265
266 template<typename T>
267 restriction<T> 
268 restrict(const T& t, stream_offset off, stream_offset len, mpl::false_)
269 { return restriction<T>(t, off, len); }
270
271 template<typename T>
272 restriction<T> 
273 restrict( const T& t, stream_offset off, stream_offset len = -1
274           BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) )
275 { return restrict(t, off, len, is_std_io<T>()); }
276
277 # if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) && \
278      !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && \
279      !defined(__GNUC__) // ---------------------------------------------------//
280
281 template<typename T>
282 restriction<T>
283 restrict(T& t, stream_offset off, stream_offset len = -1)
284 { return restriction<T>(t, off, len); }
285
286 # endif // Borland 5.x, VC6-7.0 or GCC 2.9x //--------------------------------//
287 #endif // #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //---------------//
288 //----------------------------------------------------------------------------//
289
290 namespace detail {
291
292 //--------------Implementation of restricted_indirect_device------------------//
293
294 template<typename Device>
295 restricted_indirect_device<Device>::restricted_indirect_device
296     (param_type dev, stream_offset off, stream_offset len)
297     : basic_adapter<Device>(dev), beg_(off), pos_(off), 
298       end_(len != -1 ? off + len : -1)
299 {
300     if (len < -1 || off < 0)
301         throw BOOST_IOSTREAMS_FAILURE("bad offset");
302     iostreams::skip(this->component(), off);
303 }
304
305 template<typename Device>
306 inline std::streamsize restricted_indirect_device<Device>::read
307     (char_type* s, std::streamsize n)
308 {
309     using namespace std;
310     streamsize amt =
311         end_ != -1 ?
312             (std::min) (n, static_cast<streamsize>(end_ - pos_)) :
313             n;
314     streamsize result = iostreams::read(this->component(), s, amt);
315     if (result != -1)
316         pos_ += result;
317     return result;
318 }
319
320 template<typename Device>
321 inline std::streamsize restricted_indirect_device<Device>::write
322     (const char_type* s, std::streamsize n)
323 {
324     if (end_ != -1 && pos_ + n >= end_)
325         bad_write();
326     std::streamsize result = iostreams::write(this->component(), s, n);
327     pos_ += result;
328     return result;
329 }
330
331 template<typename Device>
332 std::streampos restricted_indirect_device<Device>::seek
333     (stream_offset off, BOOST_IOS::seekdir way)
334 {
335     stream_offset next;
336     if (way == BOOST_IOS::beg) {
337         next = beg_ + off;
338     } else if (way == BOOST_IOS::cur) {
339         next = pos_ + off;
340     } else if (end_ != -1) {
341         next = end_ + off;
342     } else {
343         // Restriction is half-open; seek relative to the actual end.
344         pos_ = iostreams::seek(this->component(), off, BOOST_IOS::end);
345         if (pos_ < beg_)
346             bad_seek();
347         return offset_to_position(pos_ - beg_);
348     }
349     if (next < beg_ || end_ != -1 && next >= end_)
350         bad_seek();
351     pos_ = iostreams::seek(this->component(), next - pos_, BOOST_IOS::cur);
352     return offset_to_position(pos_ - beg_);
353 }
354
355 //--------------Implementation of restricted_direct_device--------------------//
356
357 template<typename Device>
358 restricted_direct_device<Device>::restricted_direct_device
359     (const Device& dev, stream_offset off, stream_offset len)
360     : basic_adapter<Device>(dev), beg_(0), end_(0)
361 {
362     std::pair<char_type*, char_type*> seq =
363         sequence(is_convertible<category, input>());
364     if ( off < 0 || len < -1 || 
365          len != -1 && off + len > seq.second - seq.first )
366     {
367         throw BOOST_IOSTREAMS_FAILURE("bad offset");
368     }
369     beg_ = seq.first + off;
370     end_ = len != -1 ? 
371         seq.first + off + len :
372         seq.second;
373 }
374
375 template<typename Device>
376 typename restricted_direct_device<Device>::pair_type
377 restricted_direct_device<Device>::input_sequence()
378 {
379     BOOST_STATIC_ASSERT((is_convertible<category, input>::value));
380     return std::make_pair(beg_, end_);
381 }
382
383 template<typename Device>
384 typename restricted_direct_device<Device>::pair_type
385 restricted_direct_device<Device>::output_sequence()
386 {
387     BOOST_STATIC_ASSERT((is_convertible<category, output>::value));
388     return std::make_pair(beg_, end_);
389 }
390
391 template<typename Device>
392 typename restricted_direct_device<Device>::pair_type
393 restricted_direct_device<Device>::sequence(mpl::true_)
394 { return iostreams::input_sequence(this->component()); }
395
396 template<typename Device>
397 typename restricted_direct_device<Device>::pair_type
398 restricted_direct_device<Device>::sequence(mpl::false_)
399 { return iostreams::output_sequence(this->component()); }
400
401 //--------------Implementation of restricted_filter---------------------------//
402
403 template<typename Filter>
404 restricted_filter<Filter>::restricted_filter
405     (const Filter& flt, stream_offset off, stream_offset len)
406     : basic_adapter<Filter>(flt), beg_(off),
407       pos_(off), end_(len != -1 ? off + len : -1), open_(false)
408 {
409     if (len < -1 || off < 0)
410         throw BOOST_IOSTREAMS_FAILURE("bad offset");
411 }
412
413 } // End namespace detail.
414
415 } } // End namespaces iostreams, boost.
416
417
418 #endif // #ifndef BOOST_IOSTREAMS_RESTRICT_HPP_INCLUDED