Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
sstream.cc
Go to the documentation of this file.
1
31
32
33template<class _CharT, class _Traits, class _Allocator>
34basic_stringbuf<_CharT, _Traits, _Allocator>::
35basic_stringbuf (const _C_string_type& __str, ios_base::openmode __mode)
36 : basic_streambuf<_CharT, _Traits>(__mode)
37{
38 str (__str);
39}
40
41
42// extension
43template<class _CharT, class _Traits, class _Allocator>
44basic_stringbuf<_CharT, _Traits, _Allocator>::
45basic_stringbuf (const char_type *__s, ios_base::openmode __mode)
46 : basic_streambuf<_CharT, _Traits>(__mode)
47{
48 _RWSTD_ASSERT (0 != __s);
49
50 str (__s, traits_type::length (__s));
51}
52
53
54template <class _CharT, class _Traits, class _Allocator>
55/* virtual */
56basic_stringbuf<_CharT, _Traits, _Allocator>::
57~basic_stringbuf ()
58{
59 typedef _RWSTD_ALLOC_TYPE (allocator_type, char_type) _ValueAlloc;
60
61 if (this->_C_own_buf ())
62 _ValueAlloc ().deallocate (this->_C_buffer, this->_C_bufsize);
63}
64
65
66// extension
67template<class _CharT, class _Traits, class _Allocator>
68void
69basic_stringbuf<_CharT, _Traits, _Allocator>::
70str (const char_type *__s, _RWSTD_SIZE_T __slen)
71{
72 _RWSTD_ASSERT (this->_C_is_valid ());
73
74 typedef _RWSTD_ALLOC_TYPE (allocator_type, char_type) _ValueAlloc;
75
76 typedef _RWSTD_STREAMSIZE _Streamsize;
77
78 // compute the lenth if not specified
79 if (_RWSTD_SIZE_MAX == __slen)
80 __slen = traits_type::length (__s);
81
82 _ValueAlloc __alloc;
83
84 // new buffer and size
85 char_type *__buf;
86 _RWSTD_SIZE_T __bufsize = __slen;
87 // saved offset of pptr
88 _RWSTD_STREAMSIZE __off = -1;
89
90 if (__s == this->_C_buffer) {
91 // special case: str(_C_buffer, _C_bufsize + N) called
92 // to increase the capacity of buffer
93
94 _C_catchup (this->eback ());
95
96 // set `slen' to the number of initialized characters
97 // in the buffer
98 __slen = this->egptr () - this->pbase ();
99 // save the offset of pptr
100 __off = this->pptr () - this->pbase ();
101 }
102
103 if (this->_C_bufsize < __bufsize) {
104 // requested capacity is greater than the current capacity
105 // allocate a new buffer of sufficient size
106 const _RWSTD_STREAMSIZE __ratio =
109
110 const _RWSTD_SIZE_T __cap =
111 this->_C_bufsize ?
112 (this->_C_bufsize >> 10) * __ratio
113 + (((this->_C_bufsize & 0x3ff) * __ratio) >> 10)
115
116 __bufsize = __cap < __bufsize ? __bufsize : __cap;
117
118 if (__s != this->_C_buffer && this->_C_own_buf ()) {
119 // deallocate the existing buffer here only if the string
120 // is not the same as the buffer itself; otherwise, copy
121 // it to the newly allocated buffer first and deallocate
122 // it later
123 __alloc.deallocate (this->_C_buffer, this->_C_bufsize);
124 this->_C_buffer = 0;
125 }
126
127 __buf = __alloc.allocate (__bufsize);
128 }
129 else if (0 < __bufsize) {
130 // requested capacity is the same or less than the current one
131 __buf = this->_C_buffer;
132 __bufsize = this->_C_bufsize;
133 }
134 else {
135 // zero size and capacity, deallocate and reset all pointers
136 __buf = 0;
137 __bufsize = 0;
138
139 _RWSTD_ASSERT (0 == __slen);
140 }
141
142 // compute the "high mark" (see lwg issue 432)
143 char_type* const __egptr = __buf + __slen;
144
145 if (__s != __buf) {
146 // copy the provided string to buffer
147 traits_type::copy (__buf, __s, __slen);
148
149 if (this->_C_buffer != __buf) {
150 if (this->_C_buffer && this->_C_own_buf ())
151 __alloc.deallocate (this->_C_buffer, this->_C_bufsize);
152
153 // take ownership of the allocated buffer
154 this->_C_own_buf (true);
155
156 this->_C_buffer = __buf;
157 this->_C_bufsize = __bufsize;
158 }
159 }
160
161 if (this->_C_is_in ())
162 this->setg (this->_C_buffer, this->_C_buffer, __egptr);
163 else {
164 // when not in in mode set all get pointers to the same
165 // value and use egptr() as the "high mark" (see lwg
166 // issue 432)
167 this->setg (__egptr, __egptr, __egptr);
168 }
169
170 if (this->_C_is_out ()) {
171 this->setp (this->_C_buffer, this->_C_buffer + this->_C_bufsize);
172
173 if (0 <= __off) {
174 // restore the pptr
175 this->pbump (__off);
176 }
177 else if ( this->_C_state & ios_base::in
178 || this->_C_state & (ios_base::app | ios_base::ate)) {
179 // in input or append/ate modes seek to end
180 // (see also lwg issue 562 for clarification)
181 this->pbump (__slen);
182 }
183 }
184
185 _RWSTD_ASSERT (this->_C_is_valid ());
186}
187
188
189template <class _CharT, class _Traits, class _Allocator>
190streamsize
191basic_stringbuf<_CharT, _Traits, _Allocator>::
192xsputn (const char_type* __s, streamsize __n)
193{
194 _RWSTD_ASSERT (0 != __s || 0 == __n);
195 _RWSTD_ASSERT (this->_C_is_valid ());
196
197 if (__n <= 0 || !this->_C_is_out ())
198 return 0;
199
200 if (this->epptr () - this->pptr () < __n) {
201
202 // compute the total amount of space necessary
203 const _RWSTD_SIZE_T __bufsize =
204 __n + (this->pptr () - this->pbase ());
205
206 _RWSTD_PTRDIFF_T __off = -1;
207
208 if (this->pbase () <= __s && this->pptr () > __s) {
209 // __s is a part of the buffer
210 _RWSTD_ASSERT (this->epptr () >= __s + __n);
211 // save the offset from pbase()
212 __off = this->pbase () - __s;
213 }
214
215 // grow the buffer if necessary to accommodate the whole
216 // string plus the contents of the buffer up to pptr()
217 str (this->_C_buffer, __bufsize);
218
219 _RWSTD_ASSERT (__n <= this->epptr () - this->pptr ());
220
221 if (0 <= __off) {
222 // correct __s after the buffer reallocation
223 __s = this->pbase () + __off;
224 }
225 }
226
227 // copy the whole string
228 traits_type::copy (this->pptr (), __s, __n);
229
230 this->pbump (__n);
231
232 _C_catchup (this->eback ());
233
234 return __n;
235}
236
237
238template <class _CharT, class _Traits, class _Allocator>
239/* virtual */ streamsize
240basic_stringbuf<_CharT, _Traits, _Allocator>::
241showmanyc ()
242{
243 _RWSTD_ASSERT (this->_C_is_valid ());
244
245 // get egptr() caught up with pptr()
246 _C_catchup (this->eback ());
247
248 return streamsize (this->egptr () - this->gptr ());
249}
250
251
252template <class _CharT, class _Traits, class _Allocator>
253/* virtual */ typename basic_stringbuf<_CharT, _Traits, _Allocator>::int_type
254basic_stringbuf<_CharT, _Traits, _Allocator>::
255underflow ()
256{
257 _RWSTD_ASSERT (this->_C_is_valid ());
258
259 if (this->gptr () < this->egptr ()) {
260
261 _RWSTD_ASSERT (0 != this->gptr ());
262
263 return traits_type::to_int_type (*this->gptr ());
264 }
265 else if (this->gptr () < this->pptr ()) {
266
267 // get egptr() caught up with pptr()
268 _C_catchup (this->eback ());
269
270 if (this->gptr () < this->egptr ())
271 return traits_type::to_int_type (*this->gptr ());
272 }
273
274 return traits_type::eof ();
275}
276
277
278template<class _CharT, class _Traits, class _Allocator>
279typename basic_stringbuf<_CharT, _Traits, _Allocator>::int_type
280basic_stringbuf<_CharT, _Traits, _Allocator>::
281overflow (int_type __c)
282{
283 _RWSTD_ASSERT (this->_C_is_valid ());
284
285 // 27.7.1.3, p5, bullet 2 of C++ '03: when (c == eof)
286 // indicate success even when not in out mode
287 if (this->_C_is_eof (__c))
288 return traits_type::not_eof (__c);
289
290 if (!this->_C_is_out ())
291 return traits_type::eof ();
292
293 char_type* const __bufend = this->_C_buffer + this->_C_bufsize;
294
295 if (this->pptr () == this->epptr ()) {
296 // reallocate buffer
297 str (this->_C_buffer, this->_C_bufsize + 1);
298 }
299 else if (this->epptr () < __bufend) {
300 // bump up epptr() keeping pbase() and pptr() unchanged
301
302 const _RWSTD_STREAMSIZE __off = this->pptr () - this->pbase ();
303 this->setp (this->pbase (), __bufend);
304 this->pbump (__off);
305 }
306
307 const int_type __retval = this->sputc (traits_type::to_char_type (__c));
308
309 // get egptr() caught up with the value of pptr() after the call
310 _C_catchup (this->_C_buffer);
311
312 return __retval;
313}
314
315
316template<class _CharT, class _Traits, class _Allocator>
317/* virtual */ typename basic_stringbuf<_CharT, _Traits, _Allocator>::int_type
318basic_stringbuf<_CharT, _Traits, _Allocator>::
319pbackfail (int_type __c)
320{
321 _RWSTD_ASSERT (this->_C_is_valid ());
322
323 if (!this->_C_putback_avail ())
324 return traits_type::eof ();
325
326 int_type __retval;
327
328 const char_type __ch = traits_type::to_char_type (__c);
329
330 if (traits_type::eq (__ch, *(this->gptr () - 1)) || this->_C_is_eof (__c)) {
331 // "put back" original value
332 this->gbump (-1);
333 __retval = traits_type::not_eof (__c);
334 }
335 else if (this->_C_is_out ()) {
336 // overwrite existing value with new value
337 this->gbump (-1);
338 traits_type::assign (*this->gptr (), __ch);
339 __retval = __c;
340 }
341 else
342 __retval = traits_type::eof ();
343
344 return __retval;
345}
346
347
348template<class _CharT, class _Traits, class _Allocator>
349/* virtual */ basic_streambuf<_CharT, _Traits>*
350basic_stringbuf<_CharT, _Traits, _Allocator>::
351setbuf (char_type* __buf, _RWSTD_STREAMSIZE __n)
352{
353 _RWSTD_ASSERT (this->_C_is_valid ());
354
355 if (!__buf && !__n) // 27.7.1.3, p16
356 return this;
357
358 const _RWSTD_STREAMSIZE __slen = (this->egptr () < this->pptr () ?
359 this->pptr () : this->egptr ()) - this->pbase ();
360
361 if (__n < __slen || !this->_C_is_out())
362 return 0; // failure
363
364 // compute the gptr and pptr offsets so the pointers can be restored
365 const _RWSTD_STREAMSIZE __goff = this->gptr () - this->eback ();
366 const _RWSTD_STREAMSIZE __poff = this->pptr () - this->pbase ();
367
368 const bool __own_old_buf = this->_C_own_buf ();
369
370 typedef _RWSTD_ALLOC_TYPE (allocator_type, char_type) _ValueAlloc;
371
372 if (0 == __buf) {
373 // allocate a new buffer of the specified size
374 __buf = _ValueAlloc ().allocate (__n);
375 this->_C_own_buf (true);
376 }
377 else
378 this->_C_own_buf (false);
379
380 // copy the contents of the existing buffer to the new one
381 traits_type::copy (__buf, this->_C_buffer, __slen);
382
383 if (__own_old_buf)
384 _ValueAlloc ().deallocate (this->_C_buffer, this->_C_bufsize);
385
386 this->_C_buffer = __buf;
387 this->_C_bufsize = __n;
388
389 // reset the output and input sequences within the new buffer
390 this->setp (this->_C_buffer, this->_C_buffer + this->_C_bufsize);
391 this->pbump (__poff); // ... and restore it
392
393 char_type* const __egptr = this->_C_buffer + __slen;
394
395 if (this->_C_is_in ())
396 this->setg (this->_C_buffer, this->_C_buffer + __goff, __egptr);
397 else {
398 // use egptr as the "high mark" (see lwg issue 432)
399 this->setg (__egptr, __egptr, __egptr);
400 }
401
402 return this;
403}
404
405
406template<class _CharT, class _Traits, class _Allocator>
407/* virtual */ typename basic_stringbuf<_CharT, _Traits, _Allocator>::pos_type
408basic_stringbuf<_CharT, _Traits, _Allocator>::
409seekoff (off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
410{
411 _RWSTD_ASSERT (this->_C_is_valid ());
412
413 // should implicitly hold as long as ios::seekdir is an enum
414 _RWSTD_ASSERT ( ios_base::beg == __way
415 || ios_base::cur == __way
416 || ios_base::end == __way);
417
418 _RWSTD_STREAMSIZE __newoff = -1;
419
420 // get egptr() caught up with pptr()
421 _C_catchup (this->eback ());
422
423 if (__which & ios_base::in) {
424
425 // LWG issue 453: the operation fails if either gptr() or pptr()
426 // is a null pointer and the new offset newoff is nonzero
427 if (!this->_C_is_in () || __off && !this->gptr ())
428 return pos_type (off_type (-1));
429
430 // do the checks for in|out mode here
431 if ( __which & ios_base::out
432 && (ios_base::cur == __way || !this->_C_is_out ()))
433 return pos_type (off_type (-1));
434
435 switch (__way) {
436 case ios_base::beg: __newoff = 0; break;
437 case ios_base::cur: __newoff = this->gptr () - this->eback (); break;
438 case ios_base::end: __newoff = this->egptr () - this->eback (); break;
439 }
440
441 __newoff += __off;
442
443 if (__newoff < 0 || this->egptr () - this->eback () < __newoff)
444 return pos_type (off_type (-1));
445
446 this->setg (this->eback (), this->eback () + __newoff, this->egptr ());
447 }
448
449 if (__which & ios_base::out) {
450
451 // LWG issue 453: the operation fails if either gptr() or pptr()
452 // is a null pointer and the new offset newoff is nonzero
453 if (!this->_C_is_out () || __off && !this->pptr ())
454 return pos_type (off_type (-1));
455
456 // egptr() is used as the "high mark" even when not in "in" mode
457 _RWSTD_ASSERT (0 == this->pbase () || 0 != this->egptr ());
458
459 // compute the number of initialized characters in the buffer
460 // (see LWG issue 432)
461 const _RWSTD_STREAMSIZE __high = this->egptr () - this->pbase ();
462 const _RWSTD_STREAMSIZE __cur = this->pptr () - this->pbase ();
463
464 switch (__way) {
465 case ios_base::beg: __newoff = 0; break;
466 case ios_base::cur: __newoff = __cur; break;
467 case ios_base::end: __newoff = __high; break;
468 }
469
470 __newoff += __off;
471
472 if (__newoff < 0 || __high < __newoff)
473 return pos_type (off_type (-1));
474
475 // bump pptr up (or down) to the new position
476 this->pbump (__newoff - __cur);
477 }
478
479 _RWSTD_ASSERT (this->_C_is_valid ());
480
481 return __newoff < 0 ? pos_type (off_type (-1)) : pos_type (__newoff);
482}
483
484
485template<class _CharT, class _Traits, class _Allocator>
486/* virtual */ typename basic_stringbuf<_CharT, _Traits, _Allocator>::pos_type
487basic_stringbuf<_CharT, _Traits, _Allocator>::
488seekpos (pos_type __pos, ios_base::openmode __which)
489{
490 _RWSTD_ASSERT (this->_C_is_valid ());
491
492 // typedef helps HP aCC 3.27
493 typedef basic_stringbuf _StringBuf;
494
495 return pos_type (_StringBuf::seekoff (__pos, ios_base::beg, __which));
496}
497
498
499} // namespace std
#define _RWSTD_MINIMUM_STRINGBUF_CAPACITY
Definition _defs.h:457
#define _RWSTD_ALLOC_TYPE(Allocator, ignore)
Definition _defs.h:891
#define _RWSTD_NEW_CAPACITY_RATIO
Definition _defs.h:445
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
#define _RWSTD_STREAMSIZE
Definition _defs.h:762
#define _RWSTD_ASSERT(ignore)
Definition _defs.h:1108
#define _RWSTD_RATIO_DIVIDER
Definition _defs.h:435
const char * str
Definition exec.cpp:170
Definition json.h:5363