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