Ugly, not-to-be-pushed sucking in of all of Boost to get windows to work.
[dyninst.git] / external / boost / iostreams / detail / adapter / range_adapter.hpp
1 // (C) Copyright Jonathan Turkanis 2003.
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_DETAIL_RANGE_ADAPTER_HPP_INCLUDED
8 #define BOOST_IOSTREAMS_DETAIL_RANGE_ADAPTER_HPP_INCLUDED
9
10 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
11 # pragma once
12 #endif              
13
14 #include <algorithm>                             // min.
15 #include <cassert>
16 #include <cstddef>                               // ptrdiff_t.
17 #include <iosfwd>                                // streamsize, streamoff.
18 #include <boost/detail/iterator.hpp>             // boost::iterator_traits.
19 #include <boost/iostreams/categories.hpp>
20 #include <boost/iostreams/detail/error.hpp>
21 #include <boost/iostreams/positioning.hpp>
22 #include <boost/mpl/if.hpp>
23 #include <boost/type_traits/is_convertible.hpp>
24 #include <boost/utility/enable_if.hpp>
25
26 // Must come last.
27 #include <boost/iostreams/detail/config/disable_warnings.hpp>  // MSVC.
28
29 namespace boost { namespace iostreams { namespace detail {
30
31 // Used for simulated tag dispatch.
32 template<typename Traversal> struct range_adapter_impl;
33
34 //
35 // Template name: range_adapter
36 // Description: Device based on an instance of boost::iterator_range.
37 // Template paramters:
38 //     Mode - A mode tag.
39 //     Range - An instance of iterator_range.
40 //
41 template<typename Mode, typename Range>
42 class range_adapter {
43 private:
44     typedef typename Range::iterator                  iterator;
45     typedef boost::detail::iterator_traits<iterator>  iter_traits;
46     typedef typename iter_traits::iterator_category   iter_cat;
47 public:
48     typedef typename Range::value_type                char_type;
49     struct category : Mode, device_tag { };
50     typedef typename
51             mpl::if_<
52                 is_convertible<
53                     iter_cat,
54                     std::random_access_iterator_tag
55                 >,
56                 std::random_access_iterator_tag,
57                 std::forward_iterator_tag
58             >::type                                   tag;
59     typedef range_adapter_impl<tag>                   impl;
60
61     explicit range_adapter(const Range& rng);
62     range_adapter(iterator first, iterator last);
63     std::streamsize read(char_type* s, std::streamsize n);
64     std::streamsize write(const char_type* s, std::streamsize n);
65     std::streampos seek(stream_offset off, BOOST_IOS::seekdir way);
66 private:
67     iterator first_, cur_, last_;
68 };
69
70 //------------------Implementation of range_adapter---------------------------//
71
72 template<typename Mode, typename Range>
73 range_adapter<Mode, Range>::range_adapter(const Range& rng)
74     : first_(rng.begin()), cur_(rng.begin()), last_(rng.end()) { }
75
76 template<typename Mode, typename Range>
77 range_adapter<Mode, Range>::range_adapter(iterator first, iterator last)
78     : first_(first), cur_(first), last_(last) { }
79
80 template<typename Mode, typename Range>
81 inline std::streamsize range_adapter<Mode, Range>::read
82     (char_type* s, std::streamsize n)
83 { return impl::read(cur_, last_, s, n); }
84
85 template<typename Mode, typename Range>
86 inline std::streamsize range_adapter<Mode, Range>::write
87     (const char_type* s, std::streamsize n)
88 { return impl::write(cur_, last_, s, n); }
89
90
91 template<typename Mode, typename Range>
92 std::streampos range_adapter<Mode, Range>::seek
93     (stream_offset off, BOOST_IOS::seekdir way)
94
95     impl::seek(first_, cur_, last_, off, way); 
96     return offset_to_position(cur_ - first_);
97 }
98
99 //------------------Implementation of range_adapter_impl----------------------//
100
101 template<>
102 struct range_adapter_impl<std::forward_iterator_tag> {
103     template<typename Iter, typename Ch>
104     static std::streamsize read
105         (Iter& cur, Iter& last, Ch* s,std::streamsize n)
106     {
107         std::streamsize rem = n; // No. of chars remaining.
108         while (cur != last && rem-- > 0) *s++ = *cur++;
109         return n - rem != 0 ? n - rem : -1;
110     }
111
112     template<typename Iter, typename Ch>
113     static std::streamsize write
114         (Iter& cur, Iter& last, const Ch* s, std::streamsize n)
115     {
116         while (cur != last && n-- > 0) *cur++ = *s++;
117         if (cur == last && n > 0)
118             throw write_area_exhausted();
119         return n;
120     }
121 };
122
123 template<>
124 struct range_adapter_impl<std::random_access_iterator_tag> {
125     template<typename Iter, typename Ch>
126     static std::streamsize read
127         (Iter& cur, Iter& last, Ch* s,std::streamsize n)
128     {
129         std::streamsize result = 
130             (std::min)(static_cast<std::streamsize>(last - cur), n);
131         if (result)
132             std::copy(cur, cur + result, s);
133         cur += result;
134         return result != 0 ? result : -1;
135     }
136
137     template<typename Iter, typename Ch>
138     static std::streamsize write
139         (Iter& cur, Iter& last, const Ch* s, std::streamsize n)
140     {
141         std::streamsize count =
142             (std::min)(static_cast<std::streamsize>(last - cur), n);
143         std::copy(s, s + count, cur);
144         cur += count;
145         if (count < n) 
146             throw write_area_exhausted();
147         return n;
148     }
149
150     template<typename Iter>
151     static void seek
152         ( Iter& first, Iter& cur, Iter& last, stream_offset off,
153           BOOST_IOS::seekdir way )
154     {
155         using namespace std;
156         switch (way) {
157         case BOOST_IOS::beg:
158             if (off > last - first || off < 0) bad_seek();
159             cur = first + off;
160             break;
161         case BOOST_IOS::cur:
162             {
163                 std::ptrdiff_t newoff = cur - first + off;
164                 if (newoff > last - first || newoff < 0) bad_seek();
165                 cur += off;
166                 break;
167             }
168         case BOOST_IOS::end:
169             if (last - first + off < 0 || off > 0) bad_seek();
170             cur = last + off;
171             break;
172         default:
173             assert(0);
174         }
175     }
176 };
177
178 } } } // End namespaces detail, iostreams, boost.
179
180 #include <boost/iostreams/detail/config/enable_warnings.hpp>  // MSVC.
181
182 #endif // #ifndef BOOST_IOSTREAMS_DETAIL_RANGE_ADAPTER_HPP_INCLUDED //---------------//