2 * © Portions copyright (c) 2006-2007 Nokia Corporation. All rights reserved.
4 * Silicon Graphics Computer Systems, Inc.
9 * This material is provided "as is", with absolutely no warranty expressed
10 * or implied. Any use is at your own risk.
12 * Permission to use or copy this software for any purpose is hereby granted
13 * without fee, provided the above notices are retained on all copies.
14 * Permission to modify the code and to distribute modified code is granted,
15 * provided the above notices are retained, and a notice that the code was
16 * modified is included with the above copyright notice.
20 #ifndef _STLP_SSTREAM_C
21 #define _STLP_SSTREAM_C
23 #ifndef _STLP_SSTREAM_H
24 # include <stl/_sstream.h>
25 #include <stl/_stdio_file.h>
28 # if defined (_STLP_EXPOSE_STREAM_IMPLEMENTATION)
30 # if defined ( _STLP_NESTED_TYPE_PARAM_BUG )
31 // no wint_t is supported for this mode
32 # define __BSB_int_type__ int
33 # define __BSB_pos_type__ streampos
35 # define __BSB_int_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_stringbuf<_CharT, _Traits, _Alloc>::int_type
36 # define __BSB_pos_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type
41 //----------------------------------------------------------------------
42 // Non-inline stringbuf member functions.
44 // Constructors. Note that the base class constructor sets all of the
45 // get and area pointers to null.
47 template <class _CharT, class _Traits, class _Alloc>
48 _STLP_EXP_DECLSPEC basic_stringbuf<_CharT, _Traits, _Alloc>
49 ::basic_stringbuf(ios_base::openmode __mode)
50 : basic_streambuf<_CharT, _Traits>(), _M_mode(__mode), _M_str()
53 if (_M_mode & ios_base::out) {
54 if (_M_mode & (ios_base::app | ios_base::ate))
55 //increment the streampos to reflect the current streampos while writing
56 _M_str._M_stream_pos += _M_str.size();
61 template <class _CharT, class _Traits, class _Alloc>
62 _STLP_EXP_DECLSPEC basic_stringbuf<_CharT, _Traits, _Alloc>
63 ::basic_stringbuf(const basic_string<_CharT, _Traits, _Alloc>& __s, ios_base::openmode __mode)
64 : basic_streambuf<_CharT, _Traits>(), _M_mode(__mode), _M_str(__s)
67 if (_M_mode & ios_base::out) {
68 if (_M_mode & (ios_base::app | ios_base::ate))
69 //increment the streampos to reflect the current streampos while writing
70 _M_str._M_stream_pos += _M_str.size();
76 template <class _CharT, class _Traits, class _Alloc>
77 _STLP_EXP_DECLSPEC basic_stringbuf<_CharT, _Traits, _Alloc>::~basic_stringbuf()
80 // Set the underlying string to a new value.
81 template <class _CharT, class _Traits, class _Alloc>
82 _STLP_EXP_DECLSPEC void
83 basic_stringbuf<_CharT, _Traits, _Alloc>::str(const basic_string<_CharT, _Traits, _Alloc>& __s)
89 template <class _CharT, class _Traits, class _Alloc>
91 basic_stringbuf<_CharT, _Traits, _Alloc>::_M_set_ptrs() {
92 _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
93 _CharT* __data_end = __data_ptr + _M_str.size();
94 // The initial read position is the beginning of the string.
95 if (_M_mode & ios_base::in) {
96 if (_M_mode & ios_base::ate)
97 this->setg(__data_ptr, __data_end, __data_end);
99 this->setg(__data_ptr, __data_ptr, __data_end);
102 // The initial write position is the beginning of the string.
103 if (_M_mode & ios_base::out) {
104 if (_M_mode & (ios_base::app | ios_base::ate))
105 this->setp(__data_end, __data_end);
107 this->setp(__data_ptr, __data_end);
111 // Precondition: gptr() >= egptr(). Returns a character, if one is available.
112 template <class _CharT, class _Traits, class _Alloc>
113 _STLP_EXP_DECLSPEC __BSB_int_type__
114 basic_stringbuf<_CharT, _Traits, _Alloc>::underflow()
116 return this->gptr() != this->egptr()
117 ? _Traits::to_int_type(*this->gptr())
121 // Precondition: gptr() >= egptr().
122 template <class _CharT, class _Traits, class _Alloc>
123 _STLP_EXP_DECLSPEC __BSB_int_type__
124 basic_stringbuf<_CharT, _Traits, _Alloc>::uflow()
126 if (this->gptr() != this->egptr()) {
127 int_type __c = _Traits::to_int_type(*this->gptr());
132 return _Traits::eof();
135 template <class _CharT, class _Traits, class _Alloc>
136 _STLP_EXP_DECLSPEC __BSB_int_type__
137 basic_stringbuf<_CharT, _Traits, _Alloc>::pbackfail(int_type __c)
139 if (this->gptr() != this->eback()) {
140 if (!_Traits::eq_int_type(__c, _Traits::eof())) {
142 if (_Traits::eq(_Traits::to_char_type(__c), this->gptr()[-1])
143 || _M_mode == (ios_base::in | ios_base::out)) {
145 *this->gptr() = _Traits::to_char_type(__c);
146 return _Traits::not_eof(__c);
149 return _Traits::eof();
154 return _Traits::not_eof(__c);
158 return _Traits::eof();
161 template <class _CharT, class _Traits, class _Alloc>
162 _STLP_EXP_DECLSPEC __BSB_int_type__
163 basic_stringbuf<_CharT, _Traits, _Alloc>::overflow(int_type __c)
165 // fbp : reverse order of "ifs" to pass Dietmar's test.
166 // Apparently, standard allows overflow with eof even for read-only streams.
167 if (!_Traits::eq_int_type(__c, _Traits::eof())) {
168 if (_M_mode & ios_base::out) {
169 if (!(_M_mode & ios_base::in)) {
170 // It's a write-only streambuf, so we can use special append buffer.
171 if (this->pptr() == this->epptr())
172 this->_M_append_buffer();
174 if (this->pptr() != this->epptr()) {
175 *this->pptr() = _Traits::to_char_type(__c);
180 return _Traits::eof();
184 // We're not using a special append buffer, just the string itself.
185 if (this->pptr() == this->epptr()) {
186 ptrdiff_t __offset = this->gptr() - this->eback();
187 _M_str.push_back(_Traits::to_char_type(__c));
189 _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
190 size_t __data_size = _M_str.size();
192 this->setg(__data_ptr, __data_ptr + __offset, __data_ptr+__data_size);
193 this->setp(__data_ptr, __data_ptr + __data_size);
194 this->pbump((int)__data_size);
198 *this->pptr() = _Traits::to_char_type(__c);
204 else // Overflow always fails if it's read-only
205 return _Traits::eof();
207 else // __c is EOF, so we don't have to do anything
208 return _Traits::not_eof(__c);
211 template <class _CharT, class _Traits, class _Alloc>
212 _STLP_EXP_DECLSPEC streamsize
213 basic_stringbuf<_CharT, _Traits, _Alloc>::xsputn(const char_type* __s,
216 streamsize __nwritten = 0;
218 if ((_M_mode & ios_base::out) && __n > 0) {
219 // If the put pointer is somewhere in the middle of the string,
220 // then overwrite instead of append.
221 if (this->pbase() == _M_str.data() ) {
222 ptrdiff_t __avail = _M_str.data() + _M_str.size() - this->pptr();
224 _Traits::copy(this->pptr(), __s, __n);
225 this->pbump((int)__n);
227 // _M_str._M_stream_pos += __n; //increment streampos to number of characters in stream
232 _Traits::copy(this->pptr(), __s, __avail);
233 __nwritten += __avail;
237 // _M_str._M_stream_pos += __avail;//increment streampos to number of characters in stream
239 this->setp(_M_Buf, _M_Buf + __STATIC_CAST(int,_S_BufSiz));
243 // At this point we know we're appending.
244 if (_M_mode & ios_base::in) {
245 ptrdiff_t __get_offset = this->gptr() - this->eback();
246 _M_str.append(__s, __s + __n);
248 _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
249 size_t __data_size = _M_str.size();
251 this->setg(__data_ptr, __data_ptr + __get_offset, __data_ptr+__data_size);
252 this->setp(__data_ptr, __data_ptr + __data_size);
253 this->pbump((int)__data_size);
258 if (_M_str._M_stream_pos >= 0
259 && (_M_str._M_stream_pos < _M_str.size())) {
260 if((_M_str.size() - _M_str._M_stream_pos) >= __n)
261 _M_str.replace(_M_str._M_stream_pos, __n, __s);
264 _M_str.replace(_M_str._M_stream_pos, (_M_str.size() - _M_str._M_stream_pos), __s);
265 _M_str.append(__s + (__n - (_M_str.size() - _M_str._M_stream_pos)), __s + __n);
268 _M_str.append(__s, __s + __n);
270 _M_str._M_stream_pos += __n;
271 #else //__SYMBIAN32__
272 _M_str.append(__s, __s + __n);
273 #endif // __SYMBIAN32__
281 template <class _CharT, class _Traits, class _Alloc>
283 basic_stringbuf<_CharT, _Traits, _Alloc>::_M_xsputnc(char_type __c,
286 streamsize __nwritten = 0;
288 if ((_M_mode & ios_base::out) && __n > 0) {
289 // If the put pointer is somewhere in the middle of the string,
290 // then overwrite instead of append.
291 if (this->pbase() == _M_str.data()) {
292 ptrdiff_t __avail = _M_str.data() + _M_str.size() - this->pptr();
294 _Traits::assign(this->pptr(), __n, __c);
295 this->pbump((int)__n);
299 _Traits::assign(this->pptr(), __avail, __c);
300 __nwritten += __avail;
302 this->setp(_M_Buf, _M_Buf + __STATIC_CAST(int,_S_BufSiz));
306 // At this point we know we're appending.
307 if (this->_M_mode & ios_base::in) {
308 ptrdiff_t __get_offset = this->gptr() - this->eback();
309 _M_str.append(__n, __c);
311 _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
312 size_t __data_size = _M_str.size();
314 this->setg(__data_ptr, __data_ptr + __get_offset, __data_ptr+__data_size);
315 this->setp(__data_ptr, __data_ptr + __data_size);
316 this->pbump((int)__data_size);
321 // _M_str.append(__n, __c);
323 if (_M_str._M_stream_pos >= 0
324 && (_M_str._M_stream_pos < _M_str.size())) {
325 if((_M_str.size() - _M_str._M_stream_pos) >= __n)
326 _M_str.replace(_M_str._M_stream_pos,__n, __n, __c);
329 _M_str.replace(_M_str._M_stream_pos, (_M_str.size() - _M_str._M_stream_pos), (_M_str.size() - _M_str._M_stream_pos), __c);
330 _M_str.append(__n, __c);
333 _M_str.append(__n, __c);
335 _M_str._M_stream_pos += __n;
336 #else //__SYMBIAN32__
337 _M_str.append(__n, __c);
338 #endif // __SYMBIAN32__
347 // According to the C++ standard the effects of setbuf are implementation
348 // defined, except that setbuf(0, 0) has no effect. In this implementation,
349 // setbuf(<anything>, n), for n > 0, calls reserve(n) on the underlying
351 template <class _CharT, class _Traits, class _Alloc>
352 _STLP_EXP_DECLSPEC basic_streambuf<_CharT, _Traits>*
354 basic_stringbuf<_CharT, _Traits, _Alloc>::setbuf(_CharT* __s, streamsize __n)
356 basic_stringbuf<_CharT, _Traits, _Alloc>::setbuf(_CharT*, streamsize __n)
357 #endif //__SYMBIAN32__
360 bool __do_get_area = false;
361 bool __do_put_area = false;
362 ptrdiff_t __offg = 0;
363 ptrdiff_t __offp = 0;
365 if (this->pbase() == _M_str.data()) {
366 __do_put_area = true;
367 __offp = this->pptr() - this->pbase();
370 if (this->eback() == _M_str.data()) {
371 __do_get_area = true;
372 __offg = this->gptr() - this->eback();
375 if ((_M_mode & ios_base::out) && !(_M_mode & ios_base::in))
380 _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
382 size_t __data_size = __n;
383 memmove(__data_ptr, __s, __n*sizeof(_CharT));
384 _M_str._M_start = __data_ptr;
385 _M_str._M_finish = __data_ptr+__n;
387 size_t __data_size = _M_str.size();
388 #endif //__SYMBIAN32__
392 this->setg(__data_ptr, __data_ptr, __data_ptr+__data_size);
394 this->setg(__data_ptr, __data_ptr + __offg, __data_ptr+__data_size);
395 #endif //__SYMBIAN32__
399 this->setp(__data_ptr, __data_ptr+__data_size);
400 #ifndef __SYMBIAN32__
401 this->pbump((int)__offp);
402 #endif //__SYMBIAN32__
409 template <class _CharT, class _Traits, class _Alloc>
410 _STLP_EXP_DECLSPEC __BSB_pos_type__
411 basic_stringbuf<_CharT, _Traits, _Alloc>::seekoff(off_type __off,
412 ios_base::seekdir __dir,
413 ios_base::openmode __mode)
415 bool __stl_in = false;
416 bool __stl_out = false;
418 if ((__mode & (ios_base::in | ios_base::out)) == (ios_base::in | ios_base::out) ) {
419 if (__dir == ios_base::beg || __dir == ios_base::end)
420 __stl_in = __stl_out = true;
422 else if (__mode & ios_base::in)
424 else if (__mode & ios_base::out)
427 if (!__stl_in && !__stl_out)
428 return pos_type(off_type(-1));
429 else if ((__stl_in && (!(_M_mode & ios_base::in) || this->gptr() == 0)) ||
430 (__stl_out && (!(_M_mode & ios_base::out) || this->pptr() == 0)))
431 return pos_type(off_type(-1));
434 if (_M_mode & ios_base::out)
436 if ((_M_mode & ios_base::out) && !(_M_mode & ios_base::in))
446 __newoff = _M_str.size();
449 __newoff = __stl_in ? this->gptr() - this->eback()
451 : ((this->pbase() != this->_M_str) ? _M_str._M_stream_pos
452 : this->pptr() - this->pbase());
454 : this->pptr() - this->pbase();
455 #endif //__SYMBIAN32__
458 return pos_type(off_type(-1));
464 ptrdiff_t __n = this->egptr() - this->eback();
466 if (__off < 0 || __off > __n)
467 return pos_type(off_type(-1));
469 this->setg(this->eback(), this->eback() + __off, this->eback() + __n);
475 //if (this->pbase() != this->_M_str) {
476 void* __data_ptr1 = reinterpret_cast<void*>(this->pbase());
477 _CharT* __data_ptr2 = __CONST_CAST(_CharT*,this->_M_str.data());
479 if (__data_ptr1 != __data_ptr2) {
482 #endif // __SYMBIAN32__
483 __n = this->epptr() - this->pbase();
486 #endif //__SYMBIAN32__
487 if (__off < 0 || __off > __n)
488 return pos_type(off_type(-1));
491 void* __data_ptr1 = reinterpret_cast<void*>(this->pbase());
492 _CharT* __data_ptr2 = __CONST_CAST(_CharT*,this->_M_str.data());
494 if (__data_ptr1 != __data_ptr2) {
495 _M_str._M_stream_pos = __off;
497 #endif //__SYMBIAN32__
498 this->setp(this->pbase(), this->pbase() + __n);
499 this->pbump((int)__off);
502 #endif // __SYMBIAN32__
506 return pos_type(__off);
509 template <class _CharT, class _Traits, class _Alloc>
510 _STLP_EXP_DECLSPEC __BSB_pos_type__
511 basic_stringbuf<_CharT, _Traits, _Alloc>
512 ::seekpos(pos_type __pos, ios_base::openmode __mode)
514 bool __stl_in = (__mode & ios_base::in) != 0;
515 bool __stl_out = (__mode & ios_base::out) != 0;
517 if ((__stl_in && (!(_M_mode & ios_base::in) || this->gptr() == 0)) ||
518 (__stl_out && (!(_M_mode & ios_base::out) || this->pptr() == 0)) ||
519 (!__stl_in && !__stl_out))
520 return pos_type(off_type(-1));
522 const off_type __n = __pos - pos_type(off_type(0));
523 if ((_M_mode & ios_base::out) && !(_M_mode & ios_base::in))
527 if (__n < 0 || __n > this->egptr() - this->eback())
528 return pos_type(off_type(-1));
529 this->setg(this->eback(), this->eback() + __n, this->egptr());
533 if (__n < 0 || size_t(__n) > _M_str.size())
534 return pos_type(off_type(-1));
536 _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
537 size_t __data_size = _M_str.size();
539 this->setp(__data_ptr, __data_ptr+__data_size);
540 this->pbump((int)__n);
546 // This is declared as a const member function because it is
547 // called by basic_stringbuf<>::str(). Precondition: this is a
548 // write-only stringbuf. We can't use an output buffer for read-
549 // write stringbufs. Postcondition: pptr is reset to the beginning
551 template <class _CharT, class _Traits, class _Alloc>
552 void basic_stringbuf<_CharT, _Traits, _Alloc>::_M_append_buffer() const
555 // Do we have a buffer to append?
556 if (this->pbase() == this->_M_Buf && this->pptr() != this->_M_Buf) {
557 basic_stringbuf<_CharT, _Traits, _Alloc>* __this = __CONST_CAST(_Self*,this);
559 size_t __n = this->pptr() - this->pbase();
560 if (__this->_M_str._M_stream_pos >= 0
561 && (__this->_M_str._M_stream_pos != __this->_M_str.size())) {
563 *(this->pptr()) = (_CharT)0;
565 __this->_M_str.replace(_M_str._M_stream_pos, __n, (const _CharT*)this->pbase(), (const _CharT*)this->pptr()-(const _CharT*)this->pbase());
567 __this->_M_str.replace(_M_str._M_stream_pos, __n, (const _CharT*)this->pbase());
572 __this->_M_str.append((const _CharT*)this->pbase(), (const _CharT*)this->pptr());
574 __this->_M_str._M_stream_pos += __n;
575 #else // __SYMBAIN32__
576 __this->_M_str.append((const _CharT*)this->pbase(), (const _CharT*)this->pptr());
577 #endif // __SYMBIAN32__
578 __this->setp(__CONST_CAST(_CharT*,_M_Buf),
579 __CONST_CAST(_CharT*,_M_Buf + __STATIC_CAST(int,_S_BufSiz)));
582 // Have we run off the end of the string?
583 else if (this->pptr() == this->epptr()) {
584 basic_stringbuf<_CharT, _Traits, _Alloc>* __this = __CONST_CAST(_Self*,this);
585 __this->setp(__CONST_CAST(_CharT*,_M_Buf),
586 __CONST_CAST(_CharT*,_M_Buf + __STATIC_CAST(int,_S_BufSiz)));
587 __this->_M_str._M_stream_pos = __this->_M_str._M_finish - __this->_M_str._M_start;
591 //----------------------------------------------------------------------
592 // Non-inline istringstream member functions.
594 template <class _CharT, class _Traits, class _Alloc>
595 basic_istringstream<_CharT, _Traits, _Alloc>
596 ::basic_istringstream(ios_base::openmode __mode)
597 : basic_istream<_CharT, _Traits>(0),
598 _M_buf(__mode | ios_base::in)
603 template <class _CharT, class _Traits, class _Alloc>
604 basic_istringstream<_CharT, _Traits, _Alloc>
605 ::basic_istringstream(const _String& __str,ios_base::openmode __mode)
606 : basic_istream<_CharT, _Traits>(0),
607 _M_buf(__str, __mode | ios_base::in)
612 template <class _CharT, class _Traits, class _Alloc>
613 basic_istringstream<_CharT, _Traits, _Alloc>::~basic_istringstream()
616 //----------------------------------------------------------------------
617 // Non-inline ostringstream member functions.
619 template <class _CharT, class _Traits, class _Alloc>
620 basic_ostringstream<_CharT, _Traits, _Alloc>
621 ::basic_ostringstream(ios_base::openmode __mode)
622 : basic_ostream<_CharT, _Traits>(0),
623 _M_buf(__mode | ios_base::out)
628 template <class _CharT, class _Traits, class _Alloc>
629 basic_ostringstream<_CharT, _Traits, _Alloc>
630 ::basic_ostringstream(const _String& __str, ios_base::openmode __mode)
631 : basic_ostream<_CharT, _Traits>(0),
632 _M_buf(__str, __mode | ios_base::out)
637 template <class _CharT, class _Traits, class _Alloc>
638 basic_ostringstream<_CharT, _Traits, _Alloc>::~basic_ostringstream()
641 //----------------------------------------------------------------------
642 // Non-inline stringstream member functions.
644 template <class _CharT, class _Traits, class _Alloc>
645 _STLP_EXP_DECLSPEC basic_stringstream<_CharT, _Traits, _Alloc>
646 ::basic_stringstream(ios_base::openmode __mode)
647 : basic_iostream<_CharT, _Traits>(0), _M_buf(__mode)
652 template <class _CharT, class _Traits, class _Alloc>
653 _STLP_EXP_DECLSPEC basic_stringstream<_CharT, _Traits, _Alloc>
654 ::basic_stringstream(const _String& __str, ios_base::openmode __mode)
655 : basic_iostream<_CharT, _Traits>(0), _M_buf(__str, __mode)
660 template <class _CharT, class _Traits, class _Alloc>
661 basic_stringstream<_CharT, _Traits, _Alloc>::~basic_stringstream()
666 # undef __BSB_int_type__
667 # undef __BSB_pos_type__
671 #endif /* _STLP_SSTREAM_C */