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