67 public: // Constructors, destructor. |
67 public: // Constructors, destructor. |
68 explicit basic_stringbuf(ios_base::openmode __mode |
68 explicit basic_stringbuf(ios_base::openmode __mode |
69 = ios_base::in | ios_base::out); |
69 = ios_base::in | ios_base::out); |
70 explicit basic_stringbuf(const _String& __s, ios_base::openmode __mode |
70 explicit basic_stringbuf(const _String& __s, ios_base::openmode __mode |
71 = ios_base::in | ios_base::out); |
71 = ios_base::in | ios_base::out); |
72 virtual ~basic_stringbuf(); |
72 virtual ~basic_stringbuf(){} |
73 |
73 |
74 public: // Get or set the string. |
74 public: // Get or set the string. |
75 _String str() const { _M_append_buffer(); return _M_str; } |
75 _String str() const { _M_append_buffer(); return _M_str; } |
76 void str(const _String& __s); |
76 void str(const _String& __s); |
77 |
77 |
78 protected: // Overridden virtual member functions. |
78 protected: // Overridden virtual member functions. |
79 virtual int_type underflow(); |
79 |
80 virtual int_type uflow(); |
80 // Precondition: gptr() >= egptr(). Returns a character, if one is available. |
81 virtual int_type pbackfail(int_type __c); |
81 virtual int_type underflow() { |
82 virtual int_type overflow(int_type __c); |
82 return this->gptr() != this->egptr() |
|
83 ? _Traits::to_int_type(*this->gptr()) |
|
84 : _Traits::eof(); |
|
85 } |
|
86 |
|
87 virtual int_type uflow() { |
|
88 if (this->gptr() != this->egptr()) { |
|
89 int_type __c = _Traits::to_int_type(*this->gptr()); |
|
90 this->gbump(1); |
|
91 return __c; |
|
92 } |
|
93 else |
|
94 return _Traits::eof(); |
|
95 } |
|
96 |
|
97 virtual int_type pbackfail(int_type __c) { |
|
98 if (this->gptr() != this->eback()) { |
|
99 if (!_Traits::eq_int_type(__c, _Traits::eof())) { |
|
100 if (_Traits::eq(_Traits::to_char_type(__c), this->gptr()[-1])) { |
|
101 this->gbump(-1); |
|
102 return __c; |
|
103 } |
|
104 else if (_M_mode & ios_base::out) { |
|
105 this->gbump(-1); |
|
106 *this->gptr() = _Traits::to_char_type(__c); |
|
107 return __c; |
|
108 } |
|
109 else |
|
110 return _Traits::eof(); |
|
111 } |
|
112 else { |
|
113 this->gbump(-1); |
|
114 return _Traits::not_eof(__c); |
|
115 } |
|
116 } |
|
117 else |
|
118 return _Traits::eof(); |
|
119 } |
|
120 |
|
121 virtual int_type overflow(int_type __c) { |
|
122 // fbp : reverse order of "ifs" to pass Dietmar's test. |
|
123 // Apparently, standard allows overflow with eof even for read-only streams. |
|
124 if (!_Traits::eq_int_type(__c, _Traits::eof())) { |
|
125 if (_M_mode & ios_base::out) { |
|
126 if (!(_M_mode & ios_base::in)) { |
|
127 // It's a write-only streambuf, so we can use special append buffer. |
|
128 if (this->pptr() == this->epptr()) |
|
129 this->_M_append_buffer(); |
|
130 |
|
131 if (this->pptr() != this->epptr()) { |
|
132 *this->pptr() = _Traits::to_char_type(__c); |
|
133 this->pbump(1); |
|
134 return __c; |
|
135 } |
|
136 else |
|
137 return _Traits::eof(); |
|
138 } |
|
139 else { |
|
140 // We're not using a special append buffer, just the string itself. |
|
141 if (this->pptr() == this->epptr()) { |
|
142 ptrdiff_t __offset = this->gptr() - this->eback(); |
|
143 _M_str.push_back(_Traits::to_char_type(__c)); |
|
144 |
|
145 _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data()); |
|
146 size_t __data_size = _M_str.size(); |
|
147 |
|
148 this->setg(__data_ptr, __data_ptr + __offset, __data_ptr+__data_size); |
|
149 this->setp(__data_ptr, __data_ptr + __data_size); |
|
150 this->pbump((int)__data_size); |
|
151 return __c; |
|
152 } |
|
153 else { |
|
154 *this->pptr() = _Traits::to_char_type(__c); |
|
155 this->pbump(1); |
|
156 return __c; |
|
157 } |
|
158 } |
|
159 } |
|
160 else // Overflow always fails if it's read-only |
|
161 return _Traits::eof(); |
|
162 } |
|
163 else // __c is EOF, so we don't have to do anything |
|
164 return _Traits::not_eof(__c); |
|
165 } |
|
166 |
83 int_type pbackfail() {return pbackfail(_Traits::eof());} |
167 int_type pbackfail() {return pbackfail(_Traits::eof());} |
84 int_type overflow() {return overflow(_Traits::eof());} |
168 int_type overflow() {return overflow(_Traits::eof());} |
85 |
169 |
86 virtual streamsize xsputn(const char_type* __s, streamsize __n); |
170 |
87 virtual streamsize _M_xsputnc(char_type __c, streamsize __n); |
171 virtual streamsize xsputn(const char_type* __s, streamsize __n) { |
88 |
172 streamsize __nwritten = 0; |
89 virtual _Base* setbuf(_CharT* __buf, streamsize __n); |
173 |
|
174 if ((_M_mode & ios_base::out) && __n > 0) { |
|
175 // If the put pointer is somewhere in the middle of the string, |
|
176 // then overwrite instead of append. |
|
177 if (this->pbase() == _M_str.data() ) { |
|
178 ptrdiff_t __avail = _M_str.data() + _M_str.size() - this->pptr(); |
|
179 if (__avail > __n) { |
|
180 _Traits::copy(this->pptr(), __s, __STATIC_CAST(size_t, __n)); |
|
181 this->pbump((int)__n); |
|
182 return __n; |
|
183 } |
|
184 else { |
|
185 _Traits::copy(this->pptr(), __s, __avail); |
|
186 __nwritten += __avail; |
|
187 __n -= __avail; |
|
188 __s += __avail; |
|
189 this->setp(_M_Buf, _M_Buf + __STATIC_CAST(int,_S_BufSiz)); |
|
190 } |
|
191 } |
|
192 |
|
193 // At this point we know we're appending. |
|
194 if (_M_mode & ios_base::in) { |
|
195 ptrdiff_t __get_offset = this->gptr() - this->eback(); |
|
196 _M_str.append(__s, __s + __STATIC_CAST(ptrdiff_t, __n)); |
|
197 |
|
198 _CharT* __data_ptr = __CONST_CAST(_CharT*, _M_str.data()); |
|
199 size_t __data_size = _M_str.size(); |
|
200 |
|
201 this->setg(__data_ptr, __data_ptr + __get_offset, __data_ptr + __data_size); |
|
202 this->setp(__data_ptr, __data_ptr + __data_size); |
|
203 this->pbump((int)__data_size); |
|
204 } |
|
205 else { |
|
206 _M_append_buffer(); |
|
207 _M_str.append(__s, __s + __STATIC_CAST(ptrdiff_t, __n)); |
|
208 } |
|
209 |
|
210 __nwritten += __n; |
|
211 } |
|
212 |
|
213 return __nwritten; |
|
214 } |
|
215 |
|
216 virtual streamsize _M_xsputnc(char_type __c, streamsize __n) { |
|
217 streamsize __nwritten = 0; |
|
218 |
|
219 if ((_M_mode & ios_base::out) && __n > 0) { |
|
220 // If the put pointer is somewhere in the middle of the string, |
|
221 // then overwrite instead of append. |
|
222 if (this->pbase() == _M_str.data()) { |
|
223 ptrdiff_t __avail = _M_str.data() + _M_str.size() - this->pptr(); |
|
224 if (__avail > __n) { |
|
225 _Traits::assign(this->pptr(), __STATIC_CAST(size_t, __n), __c); |
|
226 this->pbump(__STATIC_CAST(int, __n)); |
|
227 return __n; |
|
228 } |
|
229 else { |
|
230 _Traits::assign(this->pptr(), __avail, __c); |
|
231 __nwritten += __avail; |
|
232 __n -= __avail; |
|
233 this->setp(_M_Buf, _M_Buf + __STATIC_CAST(int,_S_BufSiz)); |
|
234 } |
|
235 } |
|
236 |
|
237 |
|
238 // At this point we know we're appending. |
|
239 size_t __app_size = sizeof(streamsize) > sizeof(size_t) ? __STATIC_CAST(size_t, (min)(__n, __STATIC_CAST(streamsize, _M_str.max_size()))) |
|
240 : __STATIC_CAST(size_t, __n); |
|
241 if (this->_M_mode & ios_base::in) { |
|
242 ptrdiff_t __get_offset = this->gptr() - this->eback(); |
|
243 _M_str.append(__app_size, __c); |
|
244 |
|
245 _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data()); |
|
246 size_t __data_size = _M_str.size(); |
|
247 |
|
248 this->setg(__data_ptr, __data_ptr + __get_offset, __data_ptr + __data_size); |
|
249 this->setp(__data_ptr, __data_ptr + __data_size); |
|
250 this->pbump((int)__data_size); |
|
251 } |
|
252 else { |
|
253 _M_append_buffer(); |
|
254 _M_str.append(__app_size, __c); |
|
255 } |
|
256 |
|
257 __nwritten += __app_size; |
|
258 } |
|
259 |
|
260 return __nwritten; |
|
261 } |
|
262 |
|
263 virtual _Base* setbuf(_CharT*, streamsize __n) { |
|
264 if (__n > 0) { |
|
265 bool __do_get_area = false; |
|
266 bool __do_put_area = false; |
|
267 ptrdiff_t __offg = 0; |
|
268 ptrdiff_t __offp = 0; |
|
269 |
|
270 if (this->pbase() == _M_str.data()) { |
|
271 __do_put_area = true; |
|
272 __offp = this->pptr() - this->pbase(); |
|
273 } |
|
274 |
|
275 if (this->eback() == _M_str.data()) { |
|
276 __do_get_area = true; |
|
277 __offg = this->gptr() - this->eback(); |
|
278 } |
|
279 |
|
280 if ((_M_mode & ios_base::out) && !(_M_mode & ios_base::in)) |
|
281 _M_append_buffer(); |
|
282 |
|
283 _M_str.reserve(sizeof(streamsize) > sizeof(size_t) ? __STATIC_CAST(size_t, (min)(__n, __STATIC_CAST(streamsize, _M_str.max_size()))) |
|
284 : __STATIC_CAST(size_t, __n)); |
|
285 |
|
286 _CharT* __data_ptr = __CONST_CAST(_CharT*, _M_str.data()); |
|
287 size_t __data_size = _M_str.size(); |
|
288 |
|
289 if (__do_get_area) { |
|
290 this->setg(__data_ptr, __data_ptr + __offg, __data_ptr + __data_size); |
|
291 } |
|
292 |
|
293 if (__do_put_area) { |
|
294 this->setp(__data_ptr, __data_ptr + __data_size); |
|
295 this->pbump((int)__offp); |
|
296 } |
|
297 } |
|
298 |
|
299 return this; |
|
300 } |
90 virtual pos_type seekoff(off_type __off, ios_base::seekdir __dir, |
301 virtual pos_type seekoff(off_type __off, ios_base::seekdir __dir, |
91 ios_base::openmode __mode |
302 ios_base::openmode __mode |
92 = ios_base::in | ios_base::out); |
303 = ios_base::in | ios_base::out) { |
93 virtual pos_type seekpos(pos_type __pos, ios_base::openmode __mode |
304 __mode &= _M_mode; |
94 = ios_base::in | ios_base::out); |
305 |
95 |
306 bool __imode = (__mode & ios_base::in) != 0; |
|
307 bool __omode = (__mode & ios_base::out) != 0; |
|
308 |
|
309 if ( !(__imode || __omode) ) |
|
310 return pos_type(off_type(-1)); |
|
311 |
|
312 if ( (__imode && (this->gptr() == 0)) || (__omode && (this->pptr() == 0)) ) |
|
313 return pos_type(off_type(-1)); |
|
314 |
|
315 #ifndef SYMBIAN_OE_ENHANCED_LOCALE_SUPPORT |
|
316 if ((_M_mode & ios_base::out) && !(_M_mode & ios_base::in)) |
|
317 _M_append_buffer(); |
|
318 #endif |
|
319 |
|
320 streamoff __newoff; |
|
321 switch(__dir) { |
|
322 case ios_base::beg: |
|
323 __newoff = 0; |
|
324 break; |
|
325 case ios_base::end: |
|
326 __newoff = _M_str.size(); |
|
327 break; |
|
328 case ios_base::cur: |
|
329 __newoff = __imode ? this->gptr() - this->eback() : this->pptr() - this->pbase(); |
|
330 #ifdef SYMBIAN_OE_ENHANCED_LOCALE_SUPPORT |
|
331 if ( __off == 0 ) { |
|
332 return pos_type(__newoff); |
|
333 } |
|
334 #endif |
|
335 break; |
|
336 default: |
|
337 return pos_type(off_type(-1)); |
|
338 } |
|
339 |
|
340 __off += __newoff; |
|
341 #ifdef SYMBIAN_OE_ENHANCED_LOCALE_SUPPORT |
|
342 _CharT* __data_ptr = __CONST_CAST(_CharT*, _M_str.data()); |
|
343 size_t __data_size = _M_str.size(); |
|
344 #endif |
|
345 |
|
346 if (__imode) { |
|
347 ptrdiff_t __n = this->egptr() - this->eback(); |
|
348 |
|
349 if (__off < 0 || __off > __n) |
|
350 return pos_type(off_type(-1)); |
|
351 this->setg(this->eback(), this->eback() + __STATIC_CAST(ptrdiff_t, __off), |
|
352 this->eback() + __STATIC_CAST(ptrdiff_t, __n)); |
|
353 } |
|
354 |
|
355 if (__omode) { |
|
356 ptrdiff_t __n = this->epptr() - this->pbase(); |
|
357 |
|
358 if (__off < 0 || __off > __n) |
|
359 return pos_type(off_type(-1)); |
|
360 #ifdef SYMBIAN_OE_ENHANCED_LOCALE_SUPPORT |
|
361 this->setp(__data_ptr, __data_ptr+__data_size); |
|
362 #else |
|
363 this->setp(this->pbase(), this->pbase() + __n); |
|
364 #endif |
|
365 this->pbump((int)__off); |
|
366 } |
|
367 |
|
368 return pos_type(__off); |
|
369 } |
|
370 |
|
371 virtual pos_type seekpos(pos_type __pos, ios_base::openmode __mode |
|
372 = ios_base::in | ios_base::out) { |
|
373 __mode &= _M_mode; |
|
374 |
|
375 bool __imode = (__mode & ios_base::in) != 0; |
|
376 bool __omode = (__mode & ios_base::out) != 0; |
|
377 |
|
378 if ( !(__imode || __omode) ) |
|
379 return pos_type(off_type(-1)); |
|
380 |
|
381 if ( (__imode && (this->gptr() == 0)) || (__omode && (this->pptr() == 0)) ) |
|
382 return pos_type(off_type(-1)); |
|
383 |
|
384 const off_type __n = __pos - pos_type(off_type(0)); |
|
385 if ((_M_mode & ios_base::out) && !(_M_mode & ios_base::in)) |
|
386 _M_append_buffer(); |
|
387 |
|
388 if (__imode) { |
|
389 if (__n < 0 || __n > this->egptr() - this->eback()) |
|
390 return pos_type(off_type(-1)); |
|
391 this->setg(this->eback(), this->eback() + __STATIC_CAST(ptrdiff_t, __n), this->egptr()); |
|
392 } |
|
393 |
|
394 if (__omode) { |
|
395 if (__n < 0 || size_t(__n) > _M_str.size()) |
|
396 return pos_type(off_type(-1)); |
|
397 |
|
398 _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data()); |
|
399 size_t __data_size = _M_str.size(); |
|
400 |
|
401 this->setp(__data_ptr, __data_ptr+__data_size); |
|
402 this->pbump((int)__n); |
|
403 } |
|
404 |
|
405 return __pos; |
|
406 } |
|
407 |
|
408 |
96 private: // Helper functions. |
409 private: // Helper functions. |
97 // Append the internal buffer to the string if necessary. |
410 // Append the internal buffer to the string if necessary. |
98 void _M_append_buffer() const; |
411 void _M_append_buffer() const; |
99 void _M_set_ptrs(); |
412 void _M_set_ptrs(); |
100 |
413 |