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

source code of include/boost/format/alt_sstream_impl.hpp