Chris@16
|
1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
|
Chris@16
|
2 // (C) Copyright 2003-2007 Jonathan Turkanis
|
Chris@16
|
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
|
Chris@16
|
5 // See http://www.boost.org/libs/iostreams for documentation.
|
Chris@16
|
6
|
Chris@16
|
7 // This material is heavily indebted to the discussion and code samples in
|
Chris@16
|
8 // A. Langer and K. Kreft, "Standard C++ IOStreams and Locales",
|
Chris@16
|
9 // Addison-Wesley, 2000, pp. 228-43.
|
Chris@16
|
10
|
Chris@16
|
11 // User "GMSB" provided an optimization for small seeks.
|
Chris@16
|
12
|
Chris@16
|
13 #ifndef BOOST_IOSTREAMS_DETAIL_INDIRECT_STREAMBUF_HPP_INCLUDED
|
Chris@16
|
14 #define BOOST_IOSTREAMS_DETAIL_INDIRECT_STREAMBUF_HPP_INCLUDED
|
Chris@16
|
15
|
Chris@16
|
16 #include <algorithm> // min, max.
|
Chris@16
|
17 #include <cassert>
|
Chris@16
|
18 #include <exception>
|
Chris@16
|
19 #include <typeinfo>
|
Chris@16
|
20 #include <boost/config.hpp> // Member template friends.
|
Chris@16
|
21 #include <boost/detail/workaround.hpp>
|
Chris@16
|
22 #include <boost/iostreams/constants.hpp>
|
Chris@16
|
23 #include <boost/iostreams/detail/adapter/concept_adapter.hpp>
|
Chris@16
|
24 #include <boost/iostreams/detail/buffer.hpp>
|
Chris@16
|
25 #include <boost/iostreams/detail/config/wide_streams.hpp>
|
Chris@16
|
26 #include <boost/iostreams/detail/double_object.hpp>
|
Chris@16
|
27 #include <boost/iostreams/detail/execute.hpp>
|
Chris@16
|
28 #include <boost/iostreams/detail/functional.hpp>
|
Chris@16
|
29 #include <boost/iostreams/detail/ios.hpp>
|
Chris@16
|
30 #include <boost/iostreams/detail/optional.hpp>
|
Chris@16
|
31 #include <boost/iostreams/detail/push.hpp>
|
Chris@16
|
32 #include <boost/iostreams/detail/streambuf/linked_streambuf.hpp>
|
Chris@16
|
33 #include <boost/iostreams/operations.hpp>
|
Chris@16
|
34 #include <boost/iostreams/positioning.hpp>
|
Chris@16
|
35 #include <boost/iostreams/traits.hpp>
|
Chris@16
|
36 #include <boost/iostreams/operations.hpp>
|
Chris@16
|
37 #include <boost/mpl/if.hpp>
|
Chris@16
|
38 #include <boost/throw_exception.hpp>
|
Chris@16
|
39 #include <boost/type_traits/is_convertible.hpp>
|
Chris@16
|
40
|
Chris@16
|
41 // Must come last.
|
Chris@16
|
42 #include <boost/iostreams/detail/config/disable_warnings.hpp> // MSVC, BCC 5.x
|
Chris@16
|
43
|
Chris@16
|
44 namespace boost { namespace iostreams { namespace detail {
|
Chris@16
|
45
|
Chris@16
|
46 //
|
Chris@16
|
47 // Description: The implementation of basic_streambuf used by chains.
|
Chris@16
|
48 //
|
Chris@16
|
49 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
50 class indirect_streambuf
|
Chris@16
|
51 : public linked_streambuf<BOOST_DEDUCED_TYPENAME char_type_of<T>::type, Tr>
|
Chris@16
|
52 {
|
Chris@16
|
53 public:
|
Chris@16
|
54 typedef typename char_type_of<T>::type char_type;
|
Chris@16
|
55 BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr)
|
Chris@16
|
56 private:
|
Chris@16
|
57 typedef typename category_of<T>::type category;
|
Chris@16
|
58 typedef concept_adapter<T> wrapper;
|
Chris@16
|
59 typedef detail::basic_buffer<char_type, Alloc> buffer_type;
|
Chris@16
|
60 typedef indirect_streambuf<T, Tr, Alloc, Mode> my_type;
|
Chris@16
|
61 typedef detail::linked_streambuf<char_type, traits_type> base_type;
|
Chris@16
|
62 typedef linked_streambuf<char_type, Tr> streambuf_type;
|
Chris@16
|
63 public:
|
Chris@16
|
64 indirect_streambuf();
|
Chris@16
|
65
|
Chris@16
|
66 void open(const T& t BOOST_IOSTREAMS_PUSH_PARAMS());
|
Chris@16
|
67 bool is_open() const;
|
Chris@16
|
68 void close();
|
Chris@16
|
69 bool auto_close() const;
|
Chris@16
|
70 void set_auto_close(bool close);
|
Chris@16
|
71 bool strict_sync();
|
Chris@16
|
72
|
Chris@16
|
73 // Declared in linked_streambuf.
|
Chris@16
|
74 T* component() { return &*obj(); }
|
Chris@16
|
75 protected:
|
Chris@16
|
76 #if !BOOST_WORKAROUND(__GNUC__, == 2)
|
Chris@16
|
77 BOOST_IOSTREAMS_USING_PROTECTED_STREAMBUF_MEMBERS(base_type)
|
Chris@16
|
78 #endif
|
Chris@16
|
79
|
Chris@16
|
80 //----------virtual functions---------------------------------------------//
|
Chris@16
|
81
|
Chris@16
|
82 #ifndef BOOST_IOSTREAMS_NO_LOCALE
|
Chris@16
|
83 void imbue(const std::locale& loc);
|
Chris@16
|
84 #endif
|
Chris@16
|
85 #ifdef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES
|
Chris@16
|
86 public:
|
Chris@16
|
87 #endif
|
Chris@16
|
88 int_type underflow();
|
Chris@16
|
89 int_type pbackfail(int_type c);
|
Chris@16
|
90 int_type overflow(int_type c);
|
Chris@16
|
91 int sync();
|
Chris@16
|
92 pos_type seekoff( off_type off, BOOST_IOS::seekdir way,
|
Chris@16
|
93 BOOST_IOS::openmode which );
|
Chris@16
|
94 pos_type seekpos(pos_type sp, BOOST_IOS::openmode which);
|
Chris@16
|
95
|
Chris@16
|
96 // Declared in linked_streambuf.
|
Chris@16
|
97 void set_next(streambuf_type* next);
|
Chris@16
|
98 void close_impl(BOOST_IOS::openmode m);
|
Chris@16
|
99 const std::type_info& component_type() const { return typeid(T); }
|
Chris@16
|
100 void* component_impl() { return component(); }
|
Chris@16
|
101 private:
|
Chris@16
|
102
|
Chris@16
|
103 //----------Accessor functions--------------------------------------------//
|
Chris@16
|
104
|
Chris@16
|
105 wrapper& obj() { return *storage_; }
|
Chris@16
|
106 streambuf_type* next() const { return next_; }
|
Chris@16
|
107 buffer_type& in() { return buffer_.first(); }
|
Chris@16
|
108 buffer_type& out() { return buffer_.second(); }
|
Chris@16
|
109 bool can_read() const { return is_convertible<Mode, input>::value; }
|
Chris@16
|
110 bool can_write() const { return is_convertible<Mode, output>::value; }
|
Chris@16
|
111 bool output_buffered() const { return (flags_ & f_output_buffered) != 0; }
|
Chris@16
|
112 bool shared_buffer() const { return is_convertible<Mode, seekable>::value; }
|
Chris@16
|
113 void set_flags(int f) { flags_ = f; }
|
Chris@16
|
114
|
Chris@16
|
115 //----------State changing functions--------------------------------------//
|
Chris@16
|
116
|
Chris@16
|
117 virtual void init_get_area();
|
Chris@16
|
118 virtual void init_put_area();
|
Chris@16
|
119
|
Chris@16
|
120 //----------Utility function----------------------------------------------//
|
Chris@16
|
121
|
Chris@16
|
122 pos_type seek_impl( stream_offset off, BOOST_IOS::seekdir way,
|
Chris@16
|
123 BOOST_IOS::openmode which );
|
Chris@16
|
124 void sync_impl();
|
Chris@16
|
125
|
Chris@16
|
126 enum flag_type {
|
Chris@16
|
127 f_open = 1,
|
Chris@16
|
128 f_output_buffered = f_open << 1,
|
Chris@16
|
129 f_auto_close = f_output_buffered << 1
|
Chris@16
|
130 };
|
Chris@16
|
131
|
Chris@16
|
132 optional<wrapper> storage_;
|
Chris@16
|
133 streambuf_type* next_;
|
Chris@16
|
134 double_object<
|
Chris@16
|
135 buffer_type,
|
Chris@16
|
136 is_convertible<
|
Chris@16
|
137 Mode,
|
Chris@16
|
138 two_sequence
|
Chris@16
|
139 >
|
Chris@16
|
140 > buffer_;
|
Chris@16
|
141 std::streamsize pback_size_;
|
Chris@16
|
142 int flags_;
|
Chris@16
|
143 };
|
Chris@16
|
144
|
Chris@16
|
145 //--------------Implementation of indirect_streambuf--------------------------//
|
Chris@16
|
146
|
Chris@16
|
147 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
148 indirect_streambuf<T, Tr, Alloc, Mode>::indirect_streambuf()
|
Chris@16
|
149 : next_(0), pback_size_(0), flags_(f_auto_close) { }
|
Chris@16
|
150
|
Chris@16
|
151 //--------------Implementation of open, is_open and close---------------------//
|
Chris@16
|
152
|
Chris@16
|
153 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
154 void indirect_streambuf<T, Tr, Alloc, Mode>::open
|
Chris@16
|
155 (const T& t, std::streamsize buffer_size, std::streamsize pback_size)
|
Chris@16
|
156 {
|
Chris@16
|
157 using namespace std;
|
Chris@16
|
158
|
Chris@16
|
159 // Normalize buffer sizes.
|
Chris@16
|
160 buffer_size =
|
Chris@16
|
161 (buffer_size != -1) ?
|
Chris@16
|
162 buffer_size :
|
Chris@16
|
163 iostreams::optimal_buffer_size(t);
|
Chris@16
|
164 pback_size =
|
Chris@16
|
165 (pback_size != -1) ?
|
Chris@16
|
166 pback_size :
|
Chris@16
|
167 default_pback_buffer_size;
|
Chris@16
|
168
|
Chris@16
|
169 // Construct input buffer.
|
Chris@16
|
170 if (can_read()) {
|
Chris@16
|
171 pback_size_ = (std::max)(std::streamsize(2), pback_size); // STLPort needs 2.
|
Chris@16
|
172 std::streamsize size =
|
Chris@16
|
173 pback_size_ +
|
Chris@16
|
174 ( buffer_size ? buffer_size: 1 );
|
Chris@16
|
175 in().resize(size);
|
Chris@16
|
176 if (!shared_buffer())
|
Chris@16
|
177 init_get_area();
|
Chris@16
|
178 }
|
Chris@16
|
179
|
Chris@16
|
180 // Construct output buffer.
|
Chris@16
|
181 if (can_write() && !shared_buffer()) {
|
Chris@16
|
182 if (buffer_size != 0)
|
Chris@16
|
183 out().resize(buffer_size);
|
Chris@16
|
184 init_put_area();
|
Chris@16
|
185 }
|
Chris@16
|
186
|
Chris@16
|
187 storage_.reset(wrapper(t));
|
Chris@16
|
188 flags_ |= f_open;
|
Chris@16
|
189 if (can_write() && buffer_size > 1)
|
Chris@16
|
190 flags_ |= f_output_buffered;
|
Chris@16
|
191 this->set_true_eof(false);
|
Chris@16
|
192 this->set_needs_close();
|
Chris@16
|
193 }
|
Chris@16
|
194
|
Chris@16
|
195 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
196 inline bool indirect_streambuf<T, Tr, Alloc, Mode>::is_open() const
|
Chris@16
|
197 { return (flags_ & f_open) != 0; }
|
Chris@16
|
198
|
Chris@16
|
199 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
200 void indirect_streambuf<T, Tr, Alloc, Mode>::close()
|
Chris@16
|
201 {
|
Chris@16
|
202 using namespace std;
|
Chris@16
|
203 base_type* self = this;
|
Chris@16
|
204 detail::execute_all(
|
Chris@16
|
205 detail::call_member_close(*self, BOOST_IOS::in),
|
Chris@16
|
206 detail::call_member_close(*self, BOOST_IOS::out),
|
Chris@16
|
207 detail::call_reset(storage_),
|
Chris@16
|
208 detail::clear_flags(flags_)
|
Chris@16
|
209 );
|
Chris@16
|
210 }
|
Chris@16
|
211
|
Chris@16
|
212 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
213 bool indirect_streambuf<T, Tr, Alloc, Mode>::auto_close() const
|
Chris@16
|
214 { return (flags_ & f_auto_close) != 0; }
|
Chris@16
|
215
|
Chris@16
|
216 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
217 void indirect_streambuf<T, Tr, Alloc, Mode>::set_auto_close(bool close)
|
Chris@16
|
218 { flags_ = (flags_ & ~f_auto_close) | (close ? f_auto_close : 0); }
|
Chris@16
|
219
|
Chris@16
|
220 //--------------Implementation virtual functions------------------------------//
|
Chris@16
|
221
|
Chris@16
|
222 #ifndef BOOST_IOSTREAMS_NO_LOCALE
|
Chris@16
|
223 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
224 void indirect_streambuf<T, Tr, Alloc, Mode>::imbue(const std::locale& loc)
|
Chris@16
|
225 {
|
Chris@16
|
226 if (is_open()) {
|
Chris@16
|
227 obj().imbue(loc);
|
Chris@16
|
228 if (next_)
|
Chris@16
|
229 next_->pubimbue(loc);
|
Chris@16
|
230 }
|
Chris@16
|
231 }
|
Chris@16
|
232 #endif
|
Chris@16
|
233
|
Chris@16
|
234 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
235 typename indirect_streambuf<T, Tr, Alloc, Mode>::int_type
|
Chris@16
|
236 indirect_streambuf<T, Tr, Alloc, Mode>::underflow()
|
Chris@16
|
237 {
|
Chris@16
|
238 using namespace std;
|
Chris@16
|
239 if (!gptr()) init_get_area();
|
Chris@16
|
240 buffer_type& buf = in();
|
Chris@16
|
241 if (gptr() < egptr()) return traits_type::to_int_type(*gptr());
|
Chris@16
|
242
|
Chris@16
|
243 // Fill putback buffer.
|
Chris@16
|
244 std::streamsize keep =
|
Chris@16
|
245 (std::min)( static_cast<std::streamsize>(gptr() - eback()),
|
Chris@16
|
246 pback_size_ );
|
Chris@16
|
247 if (keep)
|
Chris@16
|
248 traits_type::move( buf.data() + (pback_size_ - keep),
|
Chris@16
|
249 gptr() - keep, keep );
|
Chris@16
|
250
|
Chris@16
|
251 // Set pointers to reasonable values in case read throws.
|
Chris@16
|
252 setg( buf.data() + pback_size_ - keep,
|
Chris@16
|
253 buf.data() + pback_size_,
|
Chris@16
|
254 buf.data() + pback_size_ );
|
Chris@16
|
255
|
Chris@16
|
256 // Read from source.
|
Chris@16
|
257 std::streamsize chars =
|
Chris@16
|
258 obj().read(buf.data() + pback_size_, buf.size() - pback_size_, next_);
|
Chris@16
|
259 if (chars == -1) {
|
Chris@16
|
260 this->set_true_eof(true);
|
Chris@16
|
261 chars = 0;
|
Chris@16
|
262 }
|
Chris@16
|
263 setg(eback(), gptr(), buf.data() + pback_size_ + chars);
|
Chris@16
|
264 return chars != 0 ?
|
Chris@16
|
265 traits_type::to_int_type(*gptr()) :
|
Chris@16
|
266 traits_type::eof();
|
Chris@16
|
267 }
|
Chris@16
|
268
|
Chris@16
|
269 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
270 typename indirect_streambuf<T, Tr, Alloc, Mode>::int_type
|
Chris@16
|
271 indirect_streambuf<T, Tr, Alloc, Mode>::pbackfail(int_type c)
|
Chris@16
|
272 {
|
Chris@16
|
273 if (gptr() != eback()) {
|
Chris@16
|
274 gbump(-1);
|
Chris@16
|
275 if (!traits_type::eq_int_type(c, traits_type::eof()))
|
Chris@16
|
276 *gptr() = traits_type::to_char_type(c);
|
Chris@16
|
277 return traits_type::not_eof(c);
|
Chris@16
|
278 } else {
|
Chris@16
|
279 boost::throw_exception(bad_putback());
|
Chris@16
|
280 }
|
Chris@16
|
281 }
|
Chris@16
|
282
|
Chris@16
|
283 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
284 typename indirect_streambuf<T, Tr, Alloc, Mode>::int_type
|
Chris@16
|
285 indirect_streambuf<T, Tr, Alloc, Mode>::overflow(int_type c)
|
Chris@16
|
286 {
|
Chris@16
|
287 if ( (output_buffered() && pptr() == 0) ||
|
Chris@16
|
288 (shared_buffer() && gptr() != 0) )
|
Chris@16
|
289 {
|
Chris@16
|
290 init_put_area();
|
Chris@16
|
291 }
|
Chris@16
|
292 if (!traits_type::eq_int_type(c, traits_type::eof())) {
|
Chris@16
|
293 if (output_buffered()) {
|
Chris@16
|
294 if (pptr() == epptr()) {
|
Chris@16
|
295 sync_impl();
|
Chris@16
|
296 if (pptr() == epptr())
|
Chris@16
|
297 return traits_type::eof();
|
Chris@16
|
298 }
|
Chris@16
|
299 *pptr() = traits_type::to_char_type(c);
|
Chris@16
|
300 pbump(1);
|
Chris@16
|
301 } else {
|
Chris@16
|
302 char_type d = traits_type::to_char_type(c);
|
Chris@16
|
303 if (obj().write(&d, 1, next_) != 1)
|
Chris@16
|
304 return traits_type::eof();
|
Chris@16
|
305 }
|
Chris@16
|
306 }
|
Chris@16
|
307 return traits_type::not_eof(c);
|
Chris@16
|
308 }
|
Chris@16
|
309
|
Chris@16
|
310 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
311 int indirect_streambuf<T, Tr, Alloc, Mode>::sync()
|
Chris@16
|
312 {
|
Chris@16
|
313 try { // sync() is no-throw.
|
Chris@16
|
314 sync_impl();
|
Chris@16
|
315 obj().flush(next_);
|
Chris@16
|
316 return 0;
|
Chris@16
|
317 } catch (...) { return -1; }
|
Chris@16
|
318 }
|
Chris@16
|
319
|
Chris@16
|
320 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
321 bool indirect_streambuf<T, Tr, Alloc, Mode>::strict_sync()
|
Chris@16
|
322 {
|
Chris@16
|
323 try { // sync() is no-throw.
|
Chris@16
|
324 sync_impl();
|
Chris@16
|
325 return obj().flush(next_);
|
Chris@16
|
326 } catch (...) { return false; }
|
Chris@16
|
327 }
|
Chris@16
|
328
|
Chris@16
|
329 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
330 inline typename indirect_streambuf<T, Tr, Alloc, Mode>::pos_type
|
Chris@16
|
331 indirect_streambuf<T, Tr, Alloc, Mode>::seekoff
|
Chris@16
|
332 (off_type off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which)
|
Chris@16
|
333 { return seek_impl(off, way, which); }
|
Chris@16
|
334
|
Chris@16
|
335 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
336 inline typename indirect_streambuf<T, Tr, Alloc, Mode>::pos_type
|
Chris@16
|
337 indirect_streambuf<T, Tr, Alloc, Mode>::seekpos
|
Chris@16
|
338 (pos_type sp, BOOST_IOS::openmode which)
|
Chris@16
|
339 {
|
Chris@16
|
340 return seek_impl(position_to_offset(sp), BOOST_IOS::beg, which);
|
Chris@16
|
341 }
|
Chris@16
|
342
|
Chris@16
|
343 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
344 typename indirect_streambuf<T, Tr, Alloc, Mode>::pos_type
|
Chris@16
|
345 indirect_streambuf<T, Tr, Alloc, Mode>::seek_impl
|
Chris@16
|
346 (stream_offset off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which)
|
Chris@16
|
347 {
|
Chris@16
|
348 if ( gptr() != 0 && way == BOOST_IOS::cur && which == BOOST_IOS::in &&
|
Chris@16
|
349 eback() - gptr() <= off && off <= egptr() - gptr() )
|
Chris@16
|
350 { // Small seek optimization
|
Chris@16
|
351 gbump(off);
|
Chris@16
|
352 return obj().seek(0, BOOST_IOS::cur, BOOST_IOS::in, next_) -
|
Chris@16
|
353 static_cast<off_type>(egptr() - gptr());
|
Chris@16
|
354 }
|
Chris@16
|
355 if (pptr() != 0)
|
Chris@16
|
356 this->BOOST_IOSTREAMS_PUBSYNC(); // sync() confuses VisualAge 6.
|
Chris@16
|
357 if (way == BOOST_IOS::cur && gptr())
|
Chris@16
|
358 off -= static_cast<off_type>(egptr() - gptr());
|
Chris@16
|
359 setg(0, 0, 0);
|
Chris@16
|
360 setp(0, 0);
|
Chris@16
|
361 return obj().seek(off, way, which, next_);
|
Chris@16
|
362 }
|
Chris@16
|
363
|
Chris@16
|
364 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
365 inline void indirect_streambuf<T, Tr, Alloc, Mode>::set_next
|
Chris@16
|
366 (streambuf_type* next)
|
Chris@16
|
367 { next_ = next; }
|
Chris@16
|
368
|
Chris@16
|
369 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
370 inline void indirect_streambuf<T, Tr, Alloc, Mode>::close_impl
|
Chris@16
|
371 (BOOST_IOS::openmode which)
|
Chris@16
|
372 {
|
Chris@16
|
373 if (which == BOOST_IOS::in && is_convertible<Mode, input>::value) {
|
Chris@16
|
374 setg(0, 0, 0);
|
Chris@16
|
375 }
|
Chris@16
|
376 if (which == BOOST_IOS::out && is_convertible<Mode, output>::value) {
|
Chris@16
|
377 sync();
|
Chris@16
|
378 setp(0, 0);
|
Chris@16
|
379 }
|
Chris@16
|
380 if ( !is_convertible<category, dual_use>::value ||
|
Chris@16
|
381 is_convertible<Mode, input>::value == (which == BOOST_IOS::in) )
|
Chris@16
|
382 {
|
Chris@16
|
383 obj().close(which, next_);
|
Chris@16
|
384 }
|
Chris@16
|
385 }
|
Chris@16
|
386
|
Chris@16
|
387 //----------State changing functions------------------------------------------//
|
Chris@16
|
388
|
Chris@16
|
389 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
390 void indirect_streambuf<T, Tr, Alloc, Mode>::sync_impl()
|
Chris@16
|
391 {
|
Chris@16
|
392 std::streamsize avail, amt;
|
Chris@16
|
393 if ((avail = static_cast<std::streamsize>(pptr() - pbase())) > 0) {
|
Chris@16
|
394 if ((amt = obj().write(pbase(), avail, next())) == avail)
|
Chris@16
|
395 setp(out().begin(), out().end());
|
Chris@16
|
396 else {
|
Chris@16
|
397 const char_type* ptr = pptr();
|
Chris@16
|
398 setp(out().begin() + amt, out().end());
|
Chris@16
|
399 pbump(ptr - pptr());
|
Chris@16
|
400 }
|
Chris@16
|
401 }
|
Chris@16
|
402 }
|
Chris@16
|
403
|
Chris@16
|
404 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
405 void indirect_streambuf<T, Tr, Alloc, Mode>::init_get_area()
|
Chris@16
|
406 {
|
Chris@16
|
407 if (shared_buffer() && pptr() != 0) {
|
Chris@16
|
408 sync_impl();
|
Chris@16
|
409 setp(0, 0);
|
Chris@16
|
410 }
|
Chris@16
|
411 setg(in().begin(), in().begin(), in().begin());
|
Chris@16
|
412 }
|
Chris@16
|
413
|
Chris@16
|
414 template<typename T, typename Tr, typename Alloc, typename Mode>
|
Chris@16
|
415 void indirect_streambuf<T, Tr, Alloc, Mode>::init_put_area()
|
Chris@16
|
416 {
|
Chris@16
|
417 using namespace std;
|
Chris@16
|
418 if (shared_buffer() && gptr() != 0)
|
Chris@16
|
419 setg(0, 0, 0);
|
Chris@16
|
420 if (output_buffered())
|
Chris@16
|
421 setp(out().begin(), out().end());
|
Chris@16
|
422 else
|
Chris@16
|
423 setp(0, 0);
|
Chris@16
|
424 }
|
Chris@16
|
425
|
Chris@16
|
426 //----------------------------------------------------------------------------//
|
Chris@16
|
427
|
Chris@16
|
428 } } } // End namespaces detail, iostreams, boost.
|
Chris@16
|
429
|
Chris@16
|
430 #include <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC, BCC 5.x
|
Chris@16
|
431
|
Chris@16
|
432 #endif // #ifndef BOOST_IOSTREAMS_DETAIL_INDIRECT_STREAMBUF_HPP_INCLUDED
|