1 // ----------------------------------------------------------------------------
2 //  alt_sstream.hpp : alternative stringstream
3 // ----------------------------------------------------------------------------
4 
5 //  Copyright Samuel Krempp 2003. Use, modification, and distribution are
6 //  subject to the Boost Software License, Version 1.0. (See accompanying
7 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 
9 //  See http://www.boost.org/libs/format for library home page
10 
11 // ----------------------------------------------------------------------------
12 
13 
14 
15 #ifndef BOOST_SK_ALT_SSTREAM_HPP
16 #define BOOST_SK_ALT_SSTREAM_HPP
17 
18 #include <string>
19 #include <boost/format/detail/compat_workarounds.hpp>
20 #include <boost/utility/base_from_member.hpp>
21 #include <boost/shared_ptr.hpp>
22 #include <boost/assert.hpp>
23 
24 namespace boost {
25     namespace io {
26 
27         template<class Ch, class Tr=::std::char_traits<Ch>,
28                  class Alloc=::std::allocator<Ch> >
29         class basic_altstringbuf;
30 
31         template<class Ch, class Tr =::std::char_traits<Ch>,
32                  class Alloc=::std::allocator<Ch> >
33         class basic_oaltstringstream;
34 
35 
36         template<class Ch, class Tr, class Alloc>
37         class basic_altstringbuf
38             : public ::std::basic_streambuf<Ch, Tr>
39         {
40             typedef ::std::basic_streambuf<Ch, Tr>  streambuf_t;
41             typedef typename CompatAlloc<Alloc>::compatible_type compat_allocator_type;
42             typedef typename CompatTraits<Tr>::compatible_type   compat_traits_type;
43         public:
44             typedef Ch     char_type;
45             typedef Tr     traits_type;
46             typedef typename compat_traits_type::int_type     int_type;
47             typedef typename compat_traits_type::pos_type     pos_type;
48             typedef typename compat_traits_type::off_type     off_type;
49             typedef Alloc                     allocator_type;
50             typedef ::std::basic_string<Ch, Tr, Alloc> string_type;
51             typedef typename string_type::size_type    size_type;
52 
53             typedef ::std::streamsize streamsize;
54 
55 
basic_altstringbuf(std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)56             explicit basic_altstringbuf(std::ios_base::openmode mode
57                                         = std::ios_base::in | std::ios_base::out)
58                 : putend_(NULL), is_allocated_(false), mode_(mode)
59                 {}
basic_altstringbuf(const string_type & s,::std::ios_base::openmode mode=::std::ios_base::in|::std::ios_base::out)60             explicit basic_altstringbuf(const string_type& s,
61                                         ::std::ios_base::openmode mode
62                                         = ::std::ios_base::in | ::std::ios_base::out)
63                 : putend_(NULL), is_allocated_(false), mode_(mode)
64                 { dealloc(); str(s); }
~basic_altstringbuf()65             virtual ~basic_altstringbuf()
66                 { dealloc(); }
67             using streambuf_t::pbase;
68             using streambuf_t::pptr;
69             using streambuf_t::epptr;
70             using streambuf_t::eback;
71             using streambuf_t::gptr;
72             using streambuf_t::egptr;
73 
74             void clear_buffer();
75             void str(const string_type& s);
76 
77             // 0-copy access :
78             Ch * begin() const;
79             size_type size() const;
80             size_type cur_size() const; // stop at current pointer
pend() const81             Ch * pend() const // the highest position reached by pptr() since creation
82                 { return ((putend_ < pptr()) ? pptr() : putend_); }
pcount() const83             size_type pcount() const
84                 { return static_cast<size_type>( pptr() - pbase()) ;}
85 
86             // copy buffer to string :
str() const87             string_type str() const
88                 { return string_type(begin(), size()); }
cur_str() const89             string_type cur_str() const
90                 { return string_type(begin(), cur_size()); }
91         protected:
basic_altstringbuf(basic_altstringbuf * s,::std::ios_base::openmode mode=::std::ios_base::in|::std::ios_base::out)92             explicit basic_altstringbuf (basic_altstringbuf * s,
93                                          ::std::ios_base::openmode mode
94                                          = ::std::ios_base::in | ::std::ios_base::out)
95                 : putend_(NULL), is_allocated_(false), mode_(mode)
96                 { dealloc(); str(s); }
97 
98             virtual pos_type seekoff(off_type off, ::std::ios_base::seekdir way,
99                                      ::std::ios_base::openmode which
100                                      = ::std::ios_base::in | ::std::ios_base::out);
101             virtual pos_type seekpos (pos_type pos,
102                                       ::std::ios_base::openmode which
103                                       = ::std::ios_base::in | ::std::ios_base::out);
104             virtual int_type underflow();
105             virtual int_type pbackfail(int_type meta = compat_traits_type::eof());
106             virtual int_type overflow(int_type meta = compat_traits_type::eof());
107             void dealloc();
108         private:
109             enum { alloc_min = 256}; // minimum size of allocations
110 
111             Ch *putend_;  // remembers (over seeks) the highest value of pptr()
112             bool is_allocated_;
113             ::std::ios_base::openmode mode_;
114             compat_allocator_type alloc_;  // the allocator object
115         };
116 
117 
118 // ---   class basic_oaltstringstream ----------------------------------------
119         template <class Ch, class Tr, class Alloc>
120         class basic_oaltstringstream
121             : private base_from_member< shared_ptr< basic_altstringbuf< Ch, Tr, Alloc> > >,
122               public ::std::basic_ostream<Ch, Tr>
123         {
124             class No_Op {
125                 // used as no-op deleter for (not-owner) shared_pointers
126             public:
127                 template<class T>
operator ()(const T & arg)128                 const T & operator()(const T & arg) { return arg; }
129             };
130             typedef ::std::basic_ostream<Ch, Tr> stream_t;
131             typedef boost::base_from_member<boost::shared_ptr<
132                 basic_altstringbuf<Ch,Tr, Alloc> > >
133                 pbase_type;
134             typedef ::std::basic_string<Ch, Tr, Alloc>  string_type;
135             typedef typename string_type::size_type     size_type;
136             typedef basic_altstringbuf<Ch, Tr, Alloc>   stringbuf_t;
137         public:
138             typedef Alloc  allocator_type;
basic_oaltstringstream()139             basic_oaltstringstream()
140                 : pbase_type(new stringbuf_t), stream_t(rdbuf())
141                 { }
basic_oaltstringstream(::boost::shared_ptr<stringbuf_t> buf)142             basic_oaltstringstream(::boost::shared_ptr<stringbuf_t> buf)
143                 : pbase_type(buf), stream_t(rdbuf())
144                 { }
basic_oaltstringstream(stringbuf_t * buf)145             basic_oaltstringstream(stringbuf_t * buf)
146                 : pbase_type(buf, No_Op() ), stream_t(rdbuf())
147                 { }
rdbuf() const148             stringbuf_t * rdbuf() const
149                 { return pbase_type::member.get(); }
clear_buffer()150             void clear_buffer()
151                 { rdbuf()->clear_buffer(); }
152 
153             // 0-copy access :
begin() const154             Ch * begin() const
155                 { return rdbuf()->begin(); }
size() const156             size_type size() const
157                 { return rdbuf()->size(); }
cur_size() const158             size_type cur_size() const // stops at current position
159                 { return rdbuf()->cur_size(); }
160 
161             // copy buffer to string :
str() const162             string_type str()     const   // [pbase, epptr[
163                 { return rdbuf()->str(); }
cur_str() const164             string_type cur_str() const   // [pbase, pptr[
165                 { return rdbuf()->cur_str(); }
str(const string_type & s)166             void str(const string_type& s)
167                 { rdbuf()->str(s); }
168         };
169 
170     } // N.S. io
171 } // N.S. boost
172 
173 #include <boost/format/alt_sstream_impl.hpp>
174 
175 #endif // include guard
176 
177