source: NonGTP/Boost/boost/iostreams/detail/streambuf/direct_streambuf.hpp @ 857

Revision 857, 9.8 KB checked in by igarcia, 18 years ago (diff)
Line 
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_STREAMBUF_HPP_INCLUDED
8#define BOOST_IOSTREAMS_DETAIL_DIRECT_STREAMBUF_HPP_INCLUDED
9
10#if defined(_MSC_VER) && (_MSC_VER >= 1020)
11# pragma once
12#endif             
13
14#include <cassert>
15#include <cstddef>
16#include <typeinfo>
17#include <utility>                              // pair.
18#include <boost/config.hpp>                     // BOOST_DEDUCED_TYPENAME.
19#include <boost/iostreams/detail/char_traits.hpp>
20#include <boost/iostreams/detail/config/wide_streams.hpp>
21#include <boost/iostreams/detail/ios.hpp>
22#include <boost/iostreams/detail/optional.hpp>
23#include <boost/iostreams/detail/streambuf.hpp>
24#include <boost/iostreams/detail/streambuf/linked_streambuf.hpp>
25#include <boost/iostreams/detail/error.hpp>
26#include <boost/iostreams/operations.hpp>
27#include <boost/iostreams/positioning.hpp>
28#include <boost/iostreams/traits.hpp>
29
30// Must come last.
31#include <boost/iostreams/detail/config/disable_warnings.hpp> // MSVC.
32
33namespace boost { namespace iostreams {
34   
35namespace detail {
36
37template< typename T,
38          typename Tr =
39              BOOST_IOSTREAMS_CHAR_TRAITS(
40                 BOOST_DEDUCED_TYPENAME char_type_of<T>::type
41              ) >
42class direct_streambuf
43    : public linked_streambuf<BOOST_DEDUCED_TYPENAME char_type_of<T>::type, Tr>
44{
45public:
46    typedef typename char_type_of<T>::type                char_type;
47    BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr)
48private:
49    typedef linked_streambuf<char_type, traits_type>      base_type;
50    typedef typename category_of<T>::type                 category;
51    typedef BOOST_IOSTREAMS_BASIC_STREAMBUF(
52                char_type, traits_type
53            )                                             streambuf_type;
54public: // stream needs access.
55    void open(const T& t, int buffer_size, int pback_size);
56    bool is_open() const;
57    void close();
58    bool auto_close() const { return auto_close_; }
59    void set_auto_close(bool close) { auto_close_ = close; }
60    bool strict_sync() { return true; }
61
62    // Declared in linked_streambuf.
63    T* component() { return storage_.get(); }
64protected:
65#if !BOOST_WORKAROUND(__GNUC__, == 2)
66    BOOST_IOSTREAMS_USING_PROTECTED_STREAMBUF_MEMBERS(base_type)
67#endif
68    direct_streambuf();
69
70    //--------------Virtual functions-----------------------------------------//
71
72    // Declared in linked_streambuf.
73    void close(BOOST_IOS::openmode m);
74    const std::type_info& component_type() const { return typeid(T); }
75    void* component_impl() { return component(); }
76
77#ifdef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES
78    public:
79#endif
80
81    // Declared in basic_streambuf.
82    int_type underflow();
83    int_type pbackfail(int_type c);
84    int_type overflow(int_type c);
85    pos_type seekoff( off_type off, BOOST_IOS::seekdir way,
86                      BOOST_IOS::openmode which );
87    pos_type seekpos(pos_type sp, BOOST_IOS::openmode which);
88private:
89    pos_type seek_impl( stream_offset off, BOOST_IOS::seekdir way,
90                        BOOST_IOS::openmode which );
91    void init_input(any_tag) { }
92    void init_input(input);
93    void init_output(any_tag) { }
94    void init_output(output);
95    void init_get_area();
96    void init_put_area();
97    bool one_head() const;
98    bool two_head() const;
99    optional<T>  storage_;
100    char_type   *ibeg_, *iend_, *obeg_, *oend_;
101    bool         auto_close_;
102};
103                   
104//------------------Implementation of direct_streambuf------------------------//
105
106template<typename T, typename Tr>
107direct_streambuf<T, Tr>::direct_streambuf()
108    : ibeg_(0), iend_(0), obeg_(0), oend_(0), auto_close_(true)
109{ this->set_true_eof(true); }
110
111template<typename T, typename Tr>
112void direct_streambuf<T, Tr>::open(const T& t, int, int)
113{
114    storage_.reset(t);
115    init_input(category());
116    init_output(category());
117    setg(0, 0, 0);
118    setp(0, 0);
119}
120
121template<typename T, typename Tr>
122bool direct_streambuf<T, Tr>::is_open() const
123{ return ibeg_ != 0 && !obeg_ != 0; }
124
125template<typename T, typename Tr>
126void direct_streambuf<T, Tr>::close()
127{
128    using namespace std;
129    try { close(BOOST_IOS::in); } catch (std::exception&) { }
130    try { close(BOOST_IOS::out); } catch (std::exception&) { }
131    storage_.reset();
132}
133
134template<typename T, typename Tr>
135typename direct_streambuf<T, Tr>::int_type
136direct_streambuf<T, Tr>::underflow()
137{
138    if (!ibeg_)
139        throw cant_read();
140    if (!gptr())
141        init_get_area();
142    return gptr() != iend_ ?
143        traits_type::to_int_type(*gptr()) :
144        traits_type::eof();
145}
146
147template<typename T, typename Tr>
148typename direct_streambuf<T, Tr>::int_type
149direct_streambuf<T, Tr>::pbackfail(int_type c)
150{
151    using namespace std;
152    if (!ibeg_)
153        throw cant_read();
154    if (gptr() != 0 && gptr() != ibeg_) {
155        gbump(-1);
156        if (!traits_type::eq_int_type(c, traits_type::eof()))
157            *gptr() = traits_type::to_char_type(c);
158        return traits_type::not_eof(c);
159    }
160    throw bad_putback();
161}
162
163template<typename T, typename Tr>
164typename direct_streambuf<T, Tr>::int_type
165direct_streambuf<T, Tr>::overflow(int_type c)
166{
167    using namespace std;
168    if (!obeg_) throw BOOST_IOSTREAMS_FAILURE("no write access");
169    if (!pptr()) init_put_area();
170    if (!traits_type::eq_int_type(c, traits_type::eof())) {
171        if (pptr() == oend_)
172            throw BOOST_IOSTREAMS_FAILURE("write area exhausted");
173        *pptr() = traits_type::to_char_type(c);
174        pbump(1);
175        return c;
176    }
177    return traits_type::not_eof(c);
178}
179
180template<typename T, typename Tr>
181inline typename direct_streambuf<T, Tr>::pos_type
182direct_streambuf<T, Tr>::seekoff
183    (off_type off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which)
184{ return seek_impl(off, way, which); }
185
186template<typename T, typename Tr>
187inline typename direct_streambuf<T, Tr>::pos_type
188direct_streambuf<T, Tr>::seekpos
189    (pos_type sp, BOOST_IOS::openmode)
190{
191    return seek_impl( position_to_offset(sp), BOOST_IOS::beg,
192                      BOOST_IOS::in | BOOST_IOS::out );
193}
194
195template<typename T, typename Tr>
196void direct_streambuf<T, Tr>::close(BOOST_IOS::openmode which)
197{
198    if (which == BOOST_IOS::in && ibeg_ != 0) {
199        setg(0, 0, 0);
200        ibeg_ = iend_ = 0;
201    }
202    if (which == BOOST_IOS::out && obeg_ != 0) {
203        sync();
204        setp(0, 0);
205        obeg_ = oend_ = 0;
206    }
207    boost::iostreams::close(*storage_, which);
208}
209
210template<typename T, typename Tr>
211typename direct_streambuf<T, Tr>::pos_type direct_streambuf<T, Tr>::seek_impl
212    (stream_offset off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which)
213{
214    using namespace std;
215    BOOST_IOS::openmode both = BOOST_IOS::in | BOOST_IOS::out;
216    if (two_head() && (which & both) == both)
217        throw bad_seek();
218    stream_offset result = -1;
219    bool one = one_head();
220    if (one && (pptr() != 0 || gptr()== 0))
221        init_get_area(); // Switch to input mode, for code reuse.
222    if (one || (which & BOOST_IOS::in) != 0 && ibeg_ != 0) {
223        if (!gptr()) setg(ibeg_, ibeg_, iend_);
224        ptrdiff_t next = 0;
225        switch (way) {
226        case BOOST_IOS::beg: next = off; break;
227        case BOOST_IOS::cur: next = (gptr() - ibeg_) + off; break;
228        case BOOST_IOS::end: next = (iend_ - ibeg_) + off; break;
229        default: assert(0);
230        }
231        if (next < 0 || next > (iend_ - ibeg_))
232            throw bad_seek();
233        setg(ibeg_, ibeg_ + next, iend_);
234        result = next;
235    }
236    if (!one && (which & BOOST_IOS::out) != 0 && obeg_ != 0) {
237        if (!pptr()) setp(obeg_, oend_);
238        ptrdiff_t next = 0;
239        switch (way) {
240        case BOOST_IOS::beg: next = off; break;
241        case BOOST_IOS::cur: next = (pptr() - obeg_) + off; break;
242        case BOOST_IOS::end: next = (oend_ - obeg_) + off; break;
243        default: assert(0);
244        }
245        if (next < 0 || next > (oend_ - obeg_))
246            throw bad_seek();
247        pbump(static_cast<int>(next - (pptr() - obeg_)));
248        result = next;
249    }
250    return offset_to_position(result);
251}
252
253template<typename T, typename Tr>
254void direct_streambuf<T, Tr>::init_input(input)
255{
256    std::pair<char_type*, char_type*> p = input_sequence(*storage_);
257    ibeg_ = p.first;
258    iend_ = p.second;
259}
260
261template<typename T, typename Tr>
262void direct_streambuf<T, Tr>::init_output(output)
263{
264    std::pair<char_type*, char_type*> p = output_sequence(*storage_);
265    obeg_ = p.first;
266    oend_ = p.second;
267}
268
269template<typename T, typename Tr>
270void direct_streambuf<T, Tr>::init_get_area()
271{
272    setg(ibeg_, ibeg_, iend_);
273    if (one_head() && pptr()) {
274        gbump(static_cast<int>(pptr() - obeg_));
275        setp(0, 0);
276    }
277}
278
279template<typename T, typename Tr>
280void direct_streambuf<T, Tr>::init_put_area()
281{
282    setp(obeg_, oend_);
283    if (one_head() && gptr()) {
284        pbump(static_cast<int>(gptr() - ibeg_));
285        setg(0, 0, 0);
286    }
287}
288
289template<typename T, typename Tr>
290inline bool direct_streambuf<T, Tr>::one_head() const
291{ return ibeg_ && obeg_ && ibeg_ == obeg_; }
292
293template<typename T, typename Tr>
294inline bool direct_streambuf<T, Tr>::two_head() const
295{ return ibeg_ && obeg_ && ibeg_ != obeg_; }
296
297//----------------------------------------------------------------------------//
298
299} // End namespace detail.
300
301} } // End namespaces iostreams, boost.
302
303#include <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC
304
305#endif // #ifndef BOOST_IOSTREAMS_DETAIL_DIRECT_STREAMBUF_HPP_INCLUDED
Note: See TracBrowser for help on using the repository browser.