source: NonGTP/Boost/boost/format/alt_sstream_impl.hpp @ 857

Revision 857, 12.9 KB checked in by igarcia, 18 years ago (diff)
Line 
1// ----------------------------------------------------------------------------
2//  alt_sstream_impl.hpp : alternative stringstream, templates implementation
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#ifndef BOOST_SK_ALT_SSTREAM_IMPL_HPP
14#define BOOST_SK_ALT_SSTREAM_IMPL_HPP
15
16namespace boost {
17    namespace io {
18// --- Implementation  ------------------------------------------------------//
19
20        template<class Ch, class Tr, class Alloc>
21        void basic_altstringbuf<Ch, Tr, Alloc>::
22        clear_buffer () {
23            const Ch * p = pptr();
24            const Ch * b = pbase();
25            if(p != NULL && p != b) {
26                seekpos(0, ::std::ios_base::out);
27            }
28            p = gptr();
29            b = eback();
30            if(p != NULL && p != b) {
31                seekpos(0, ::std::ios_base::in);
32            }
33        }
34
35        template<class Ch, class Tr, class Alloc>
36        void basic_altstringbuf<Ch, Tr, Alloc>::
37        str (const string_type& s) {
38            size_type sz=s.size();
39            if(sz != 0 && mode_ & (::std::ios_base::in | ::std::ios_base::out) ) {
40                Ch *new_ptr = alloc_.allocate(sz, is_allocated_? eback() : 0);
41                // if this didnt throw, we're safe, update the buffer
42                dealloc();
43                sz = s.copy(new_ptr, sz);
44                putend_ = new_ptr + sz;
45                if(mode_ & ::std::ios_base::in)
46                    streambuf_t::setg(new_ptr, new_ptr, new_ptr + sz);
47                if(mode_ & ::std::ios_base::out) {
48                    streambuf_t::setp(new_ptr, new_ptr + sz);
49                    if(mode_ & (::std::ios_base::app | ::std::ios_base::ate))
50                        streambuf_t::pbump(static_cast<int>(sz));
51                    if(gptr() == NULL)
52                        streambuf_t::setg(new_ptr, NULL, new_ptr);
53                }
54                is_allocated_ = true;
55            }
56            else
57                dealloc();
58        }
59        template<class Ch, class Tr, class Alloc>
60        Ch*   basic_altstringbuf<Ch, Tr, Alloc>::
61        begin () const {
62            if(mode_ & ::std::ios_base::out && pptr() != NULL)
63                return pbase();
64            else if(mode_ & ::std::ios_base::in && gptr() != NULL)
65                return eback();
66            return NULL;
67        }
68
69        template<class Ch, class Tr, class Alloc>
70        typename std::basic_string<Ch,Tr,Alloc>::size_type
71        basic_altstringbuf<Ch, Tr, Alloc>::
72        size () const {
73            if(mode_ & ::std::ios_base::out && pptr())
74                return static_cast<size_type>(pend() - pbase());
75            else if(mode_ & ::std::ios_base::in && gptr())
76                return static_cast<size_type>(egptr() - eback());
77            else
78                return 0;
79        }
80
81        template<class Ch, class Tr, class Alloc>
82        typename std::basic_string<Ch,Tr,Alloc>::size_type
83        basic_altstringbuf<Ch, Tr, Alloc>::
84        cur_size () const {
85            if(mode_ & ::std::ios_base::out && pptr())
86                return static_cast<streamsize>( pptr() - pbase());
87            else if(mode_ & ::std::ios_base::in && gptr())
88                return static_cast<streamsize>( gptr() - eback());
89            else
90                return 0;
91        }
92
93        template<class Ch, class Tr, class Alloc>
94        typename basic_altstringbuf<Ch, Tr, Alloc>::pos_type 
95        basic_altstringbuf<Ch, Tr, Alloc>::
96        seekoff (off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) {
97            if(pptr() != NULL && putend_ < pptr())
98                putend_ = pptr();
99            if(which & ::std::ios_base::in && gptr() != NULL) {
100                // get area
101                if(way == ::std::ios_base::end)
102                    off += static_cast<off_type>(putend_ - gptr());
103                else if(way == ::std::ios_base::beg)
104                    off += static_cast<off_type>(eback() - gptr());
105                else if(way != ::std::ios_base::cur || (which & ::std::ios_base::out) )
106                    // (altering in&out is only supported if way is beg or end, not cur)
107                    return pos_type(off_type(-1));
108                if(eback() <= off+gptr() && off+gptr() <= putend_ ) {
109                    // set gptr
110                    streambuf_t::gbump(off);
111                    if(which & ::std::ios_base::out && pptr() != NULL)
112                        // update pptr to match gptr
113                        streambuf_t::pbump(static_cast<int>(gptr()-pptr()));
114                }
115                else
116                    off = off_type(-1);
117            }
118            else if(which & ::std::ios_base::out && pptr() != NULL) {
119                // put area
120                if(way == ::std::ios_base::end)
121                    off += static_cast<off_type>(putend_ - pptr());
122                else if(way == ::std::ios_base::beg)
123                    off += static_cast<off_type>(pbase() - pptr());
124                else if(way != ::std::ios_base::beg)
125                    return pos_type(off_type(-1));                   
126                if(pbase() <= off+pptr() && off+pptr() <= putend_)
127                    // set pptr
128                    streambuf_t::pbump(off);
129                else
130                    off = off_type(-1);
131            }
132            else // neither in nor out
133                off = off_type(-1);
134            return (pos_type(off));
135        }
136        //- end seekoff(..)
137
138       
139        template<class Ch, class Tr, class Alloc>
140        typename basic_altstringbuf<Ch, Tr, Alloc>::pos_type
141        basic_altstringbuf<Ch, Tr, Alloc>::
142        seekpos (pos_type pos, ::std::ios_base::openmode which) {
143            off_type off = off_type(pos); // operation guaranteed by §27.4.3.2 table 88
144            if(pptr() != NULL && putend_ < pptr())
145                putend_ = pptr();
146            if(off != off_type(-1)) {
147                if(which & ::std::ios_base::in && gptr() != NULL) {
148                    // get area
149                    if(0 <= off && off <= putend_ - eback()) {
150                        streambuf_t::gbump(static_cast<int>(eback() - gptr() + off));
151                        if(which & ::std::ios_base::out && pptr() != NULL) {
152                            // update pptr to match gptr
153                            streambuf_t::pbump(static_cast<int>(gptr()-pptr()));
154                        }
155                    }
156                    else
157                        off = off_type(-1);
158                }
159                else if(which & ::std::ios_base::out && pptr() != NULL) {
160                    // put area
161                    if(0 <= off && off <= putend_ - eback())
162                        streambuf_t::pbump(static_cast<int>(eback() - pptr() + off));
163                    else
164                        off = off_type(-1);
165                }
166                else // neither in nor out
167                    off = off_type(-1);
168                return (pos_type(off));
169            }
170            else {
171                BOOST_ASSERT(0); // §27.4.3.2 allows undefined-behaviour here
172                return pos_type(off_type(-1));
173            }
174        }
175        // -end seekpos(..)
176
177
178        template<class Ch, class Tr, class Alloc>
179        typename basic_altstringbuf<Ch, Tr, Alloc>::int_type
180        basic_altstringbuf<Ch, Tr, Alloc>::
181        underflow () {
182            if(gptr() == NULL) // no get area -> nothing to get.
183                return (compat_traits_type::eof());
184            else if(gptr() < egptr())  // ok, in buffer
185                return (compat_traits_type::to_int_type(*gptr()));
186            else if(mode_ & ::std::ios_base::in && pptr() != NULL
187                    && (gptr() < pptr() || gptr() < putend_) )
188                {  // expand get area
189                    if(putend_ < pptr())
190                        putend_ = pptr(); // remember pptr reached this far
191                    streambuf_t::setg(eback(), gptr(), putend_);
192                    return (compat_traits_type::to_int_type(*gptr()));
193                }
194            else // couldnt get anything. EOF.
195                return (compat_traits_type::eof());
196        }
197        // -end underflow(..)
198
199
200        template<class Ch, class Tr, class Alloc>
201        typename basic_altstringbuf<Ch, Tr, Alloc>::int_type
202        basic_altstringbuf<Ch, Tr, Alloc>::
203        pbackfail (int_type meta) {
204            if(gptr() != NULL  &&  (eback() < gptr())
205               && (mode_ & (::std::ios_base::out)
206                   || compat_traits_type::eq_int_type(compat_traits_type::eof(), meta)
207                   || compat_traits_type::eq(compat_traits_type::to_char_type(meta), gptr()[-1]) ) ) {
208                streambuf_t::gbump(-1); // back one character
209                if(!compat_traits_type::eq_int_type(compat_traits_type::eof(), meta))
210                    //  put-back meta into get area
211                    *gptr() = compat_traits_type::to_char_type(meta);
212                return (compat_traits_type::not_eof(meta));
213            }
214            else
215                return (compat_traits_type::eof());  // failed putback
216        }
217        // -end pbackfail(..)
218
219
220        template<class Ch, class Tr, class Alloc>
221        typename basic_altstringbuf<Ch, Tr, Alloc>::int_type
222        basic_altstringbuf<Ch, Tr, Alloc>::
223        overflow (int_type meta) {
224            if(compat_traits_type::eq_int_type(compat_traits_type::eof(), meta))
225                return compat_traits_type::not_eof(meta); // nothing to do
226            else if(pptr() != NULL && pptr() < epptr()) {
227                streambuf_t::sputc(compat_traits_type::to_char_type(meta));
228                return meta;
229            }
230            else if(! (mode_ & ::std::ios_base::out))
231                // no write position, and cant make one
232                return compat_traits_type::eof();
233            else { // make a write position available
234                std::size_t prev_size = pptr() == NULL ? 0 : epptr() - eback();
235                std::size_t new_size = prev_size;
236                // exponential growth : size *= 1.5
237                std::size_t add_size = new_size / 2;
238                if(add_size < alloc_min)
239                    add_size = alloc_min;
240                Ch * newptr = NULL,  *oldptr = eback();
241
242                // make sure adding add_size wont overflow size_t
243                while (0 < add_size && ((std::numeric_limits<std::size_t>::max)()
244                                        - add_size < new_size) )
245                    add_size /= 2;
246                if(0 < add_size) {
247                    new_size += add_size;
248                    newptr = alloc_.allocate(new_size, is_allocated_? oldptr : 0);
249                }
250
251                if(0 < prev_size)
252                    compat_traits_type::copy(newptr, oldptr, prev_size);
253                if(is_allocated_)
254                    alloc_.deallocate(oldptr, prev_size);
255                is_allocated_=true;
256
257                if(prev_size == 0) { // first allocation
258                    putend_ = newptr;
259                    streambuf_t::setp(newptr, newptr + new_size);
260                    if(mode_ & ::std::ios_base::in)
261                        streambuf_t::setg(newptr, newptr, newptr + 1);
262                    else
263                        streambuf_t::setg(newptr, 0, newptr);
264                }
265                else { // update pointers
266                    putend_ = putend_ - oldptr + newptr;
267                    int pptr_count = static_cast<int>(pptr()-pbase());
268                    int gptr_count = static_cast<int>(gptr()-eback());
269                    streambuf_t::setp(pbase() - oldptr + newptr, newptr + new_size);
270                    streambuf_t::pbump(pptr_count);
271                    if(mode_ & ::std::ios_base::in)
272                        streambuf_t::setg(newptr, newptr + gptr_count, pptr() + 1);
273                    else
274                        streambuf_t::setg(newptr, 0, newptr);
275                }
276                streambuf_t::sputc(compat_traits_type::to_char_type(meta));
277                return meta;
278            }
279        }
280        // -end overflow(..)
281
282        template<class Ch, class Tr, class Alloc>
283        void basic_altstringbuf<Ch, Tr, Alloc>:: dealloc() {
284            if(is_allocated_)
285                alloc_.deallocate(eback(), (pptr() != NULL ? epptr() : egptr()) - eback());
286            is_allocated_ = false;
287            streambuf_t::setg(0, 0, 0);
288            streambuf_t::setp(0, 0);
289            putend_ = NULL;
290        }
291
292    }// N.S. io
293} // N.S. boost
294
295#endif // include guard
296
Note: See TracBrowser for help on using the repository browser.