Ugly, not-to-be-pushed sucking in of all of Boost to get windows to work.
[dyninst.git] / external / boost / format / alt_sstream_impl.hpp
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
16 namespace 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