1 // ----------------------------------------------------------------------------
2 // alt_sstream_impl.hpp : alternative stringstream, templates implementation
3 // ----------------------------------------------------------------------------
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)
9 // See http://www.boost.org/libs/format for library home page
11 // ----------------------------------------------------------------------------
13 #ifndef BOOST_SK_ALT_SSTREAM_IMPL_HPP
14 #define BOOST_SK_ALT_SSTREAM_IMPL_HPP
18 // --- Implementation ------------------------------------------------------//
20 template<class Ch, class Tr, class Alloc>
21 void basic_altstringbuf<Ch, Tr, Alloc>::
23 const Ch * p = pptr();
24 const Ch * b = pbase();
25 if(p != NULL && p != b) {
26 seekpos(0, ::std::ios_base::out);
30 if(p != NULL && p != b) {
31 seekpos(0, ::std::ios_base::in);
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 = alloc_.allocate(sz, is_allocated_? eback() : 0);
42 Ch *new_ptr = static_cast<Ch *>(vd_ptr);
44 Ch *new_ptr = alloc_.allocate(sz, is_allocated_? eback() : 0);
46 // if this didnt throw, we're safe, update the buffer
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));
57 streambuf_t::setg(new_ptr, NULL, new_ptr);
64 template<class Ch, class Tr, class Alloc>
65 Ch* basic_altstringbuf<Ch, Tr, Alloc>::
67 if(mode_ & ::std::ios_base::out && pptr() != NULL)
69 else if(mode_ & ::std::ios_base::in && gptr() != NULL)
74 template<class Ch, class Tr, class Alloc>
75 typename std::basic_string<Ch,Tr,Alloc>::size_type
76 basic_altstringbuf<Ch, Tr, Alloc>::
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());
86 template<class Ch, class Tr, class Alloc>
87 typename std::basic_string<Ch,Tr,Alloc>::size_type
88 basic_altstringbuf<Ch, Tr, Alloc>::
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());
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())
104 if(which & ::std::ios_base::in && gptr() != NULL) {
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_ ) {
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()));
123 else if(which & ::std::ios_base::out && pptr() != NULL) {
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_)
133 streambuf_t::pbump(static_cast<int>(off));
137 else // neither in nor out
139 return (pos_type(off));
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 27.4.3.2 table 88
149 if(pptr() != NULL && putend_ < pptr())
151 if(off != off_type(-1)) {
152 if(which & ::std::ios_base::in && gptr() != NULL) {
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()));
164 else if(which & ::std::ios_base::out && pptr() != NULL) {
166 if(0 <= off && off <= putend_ - eback())
167 streambuf_t::pbump(static_cast<int>(eback() - pptr() + off));
171 else // neither in nor out
173 return (pos_type(off));
176 BOOST_ASSERT(0); // ยง27.4.3.2 allows undefined-behaviour here
177 return pos_type(off_type(-1));
183 template<class Ch, class Tr, class Alloc>
184 typename basic_altstringbuf<Ch, Tr, Alloc>::int_type
185 basic_altstringbuf<Ch, Tr, Alloc>::
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_) )
195 putend_ = pptr(); // remember pptr reached this far
196 streambuf_t::setg(eback(), gptr(), putend_);
197 return (compat_traits_type::to_int_type(*gptr()));
199 else // couldnt get anything. EOF.
200 return (compat_traits_type::eof());
202 // -end underflow(..)
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));
220 return (compat_traits_type::eof()); // failed putback
222 // -end pbackfail(..)
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) {
230 #pragma warning(push)
231 #pragma warning(disable:4996)
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));
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();
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) )
256 new_size += add_size;
257 #ifdef _RWSTD_NO_CLASS_PARTIAL_SPEC
258 void *vdptr = alloc_.allocate(new_size, is_allocated_? oldptr : 0);
259 newptr = static_cast<Ch *>(vdptr);
261 newptr = alloc_.allocate(new_size, is_allocated_? oldptr : 0);
266 compat_traits_type::copy(newptr, oldptr, prev_size);
268 alloc_.deallocate(oldptr, prev_size);
271 if(prev_size == 0) { // first allocation
273 streambuf_t::setp(newptr, newptr + new_size);
274 if(mode_ & ::std::ios_base::in)
275 streambuf_t::setg(newptr, newptr, newptr + 1);
277 streambuf_t::setg(newptr, 0, newptr);
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);
288 streambuf_t::setg(newptr, 0, newptr);
290 streambuf_t::sputc(compat_traits_type::to_char_type(meta));
299 template<class Ch, class Tr, class Alloc>
300 void basic_altstringbuf<Ch, Tr, Alloc>:: dealloc() {
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);
312 #endif // include guard