Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
strstream.cpp
Go to the documentation of this file.
1
29#define _RWSTD_LIB_SRC
30
31#if 3 == __GNUG__ && 3 > __GNUC_MINOR__ \
32 || 3 == __GNUC_MINOR__ && 1 >__GNUC_PATCHLEVEL__
33
34 // working around a gcc bug (PR #29570)
35# include <rw/_config.h>
36# ifndef _RWSTD_NO_EXTERN_TEMPLATE
37# define _RWSTD_NO_EXTERN_TEMPLATE
38# endif
39#endif // gcc >= 3.0 && gcc < 3.3.1
40
41#include <rw/_defs.h>
42
43#include <limits.h>
44
45#include <ios>
46#include <strstream>
47
48
50
51
52/* virtual */
53strstreambuf::~strstreambuf ()
54{
55 _RWSTD_ASSERT (_C_is_valid ());
56
57 if ( _C_buffer && _C_state & _C_allocated
58 && !(_C_state & _C_frozen)) {
59 if (_C_pfree)
60 _C_pfree (_C_buffer);
61 else
62 delete[] _C_buffer;
63 }
64}
65
66
67/* virtual */ strstreambuf::int_type
68strstreambuf::overflow (int_type c)
69{
70 _RWSTD_ASSERT (_C_is_valid ());
71
72 if (!_C_is_out () || !(_C_state & _C_dynamic))
73 return traits_type::eof ();
74
75 if (_C_is_eof (c))
76 return traits_type::not_eof (c);
77
78 // reallocate space if necessary
79 if (!(pptr () < epptr ())) {
80
81 const streamsize new_size =
82 _C_bufsize ? _C_bufsize * 2 : _C_alsize ? _C_alsize : 128;
83
84 // take care to avoid calling the overridden setbuf(), if any
85 if (!strstreambuf::setbuf (0, new_size))
86 return traits_type::eof ();
87 }
88
89 return sputc (traits_type::to_char_type (c));
90}
91
92
93/* virtual */ strstreambuf::int_type
94strstreambuf::pbackfail (int_type c)
95{
96 _RWSTD_ASSERT (_C_is_valid ());
97
98 typedef traits_type Traits;
99
100 if (eback () < gptr ()) {
101
102 // putback position is available (see 27.5.1, p3, bullet 3)
103
104 if (Traits::eq_int_type (c, Traits::eof ())) {
105
106 // D.7.1.3, p6, bullet 3
107
108 gbump (-1);
109 return Traits::not_eof (c);
110 }
111
112 if (Traits::eq_int_type (Traits::to_int_type (*(gptr () - 1)), c)) {
113
114 // D.7.1.3, p6, bullet 1
115
116 gbump (-1);
117 return c;
118 }
119
120 if (!(_C_state & _C_constant)) {
121
122 // D.7.1.3, p6, bullet 2
123
124 gbump (-1);
125 Traits::assign (*gptr (), Traits::to_char_type (c));
126 return c;
127 }
128 }
129
130 // D.7.1.3, p7
131 return Traits::eof ();
132}
133
134
135/* virtual */ strstreambuf::int_type
136strstreambuf::underflow ()
137{
138 _RWSTD_ASSERT (_C_is_valid ());
139
140 if (gptr () < egptr ()) {
141 // read position is available (see 27.5.1, p3, bullet 4)
142
143 // D.7.1.3, p9, bullet 1
144 return traits_type::to_int_type (*gptr ());
145 }
146
147 if (pptr () > egptr ()) {
148
149 // D.7.1.3, p9, bullet 2
150 if (gptr ())
151 setg (eback (), gptr (), pptr ());
152 else
153 setg (pbase (), pbase (), pptr ());
154
155 return traits_type::to_int_type (*gptr ());
156 }
157
158 // D.7.1.3, p10
159 return traits_type::eof ();
160}
161
162
163/* virtual */ strstreambuf::pos_type
164strstreambuf::seekoff (off_type off, ios::seekdir way, ios::openmode which)
165{
166 _RWSTD_ASSERT (_C_is_valid ());
167
168 // should implicitly hold as long as ios::seekdir is an enum
169 _RWSTD_ASSERT (ios::beg == way || ios::cur == way || ios::end == way);
170 _RWSTD_ASSERT (_C_is_valid ());
171
172 // determine seekable area - D.7.1, p4
173 char* const seeklo = eback ();
174 char* const seekhi = epptr () ? epptr () : egptr ();
175
176 const char* const xnext = which & ios::in ? gptr () : pptr ();
177 const char* const xbeg = which & ios::in ? eback () : pbase ();
178
179 // D.7.1.3, p13
180 if (!xnext)
181 return pos_type (off_type (-1));
182
183 off_type saved_off = off;
184
185 // compute new offset - D.7.1.3, p13, table 105
186 if (ios::cur == way)
187 off += off_type (xnext - xbeg);
188 else if (ios::end == way)
189 off += off_type (seekhi - xbeg);
190
191 // test conditions in D.7.1.3, p13, table 105, row 4
192 if (off < seeklo - xbeg || off > seekhi - xbeg)
193 off = -1; // failure
194 else if (which & ios::in) { // position input sequence
195
196 // fail if `way' is `cur', otherwise position output sequence first
197 if ( which & ios::out
198 && ( way == ios::cur
199 || pos_type (-1) == seekoff (saved_off, way, ios::out)))
200 return pos_type (off_type (-1));
201
202 // adjust input sequence as necessary to maintain invariant
203 if (off <= egptr () - eback ())
204 setg (eback (), eback () + off, egptr ());
205 else if (off <= pptr () - egptr ()) // advance egptr()
206 setg (eback (), eback () + off, pptr ());
207 else // advance egptr() even further
208 setg (eback (), eback () + off, epptr ());
209 }
210 else if (which & ios::out) { // position output sequence
211 if (seeklo + off < pbase ()) {
212 // adjust beginning of output sequence, then increment pptr()
213 setp (seeklo, epptr ());
214 pbump (off);
215 }
216 else {
217 // reset pptr() first, then increment it by offset
218 setp (pbase (), epptr ());
219 pbump (off - (pbase () - seeklo));
220 }
221 }
222 else
223 off = -1; // failure
224
225 _RWSTD_ASSERT (_C_is_valid ());
226
227 return pos_type (off);
228}
229
230
231/* virtual */ strstreambuf::pos_type
232strstreambuf::seekpos (pos_type sp, ios::openmode which)
233{
234 _RWSTD_ASSERT (_C_is_valid ());
235
236 // call seekoff() defined by strstreambuf, and
237 // not an overridden() virtual if one exists
238 return strstreambuf::seekoff (sp - pos_type (), ios::beg, which);
239}
240
241
242/* virtual */ streambuf*
243strstreambuf::setbuf (char_type* buf, streamsize bufsize)
244{
245 _RWSTD_ASSERT (_C_is_valid ());
246
247 if ( !(_C_state & _C_dynamic) || (_C_state & _C_frozen)
248 || !buf && !bufsize) {
249 // lwg issue 66
250 return 0;
251 }
252
253 // determine the existing (possibly disjoint) sequences
254 // in the (possibly two distinct) buffer(s) and copy
255 // them into the new buffer
256
257 // [.....] [.....] or [....[.]...]
258 // ^ ^ ^ ^ ^ ^
259 // | | | | | |
260 // | | | +- xend | +- xend, gap_beg, gap_end
261 // | | +------- gap_end +------------ xbeg
262 // | +---------- gap_beg
263 // +---------------- xbeg
264
265 const char_type* const xbeg =
266 eback () && eback () < pbase () ? eback () : pbase ();
267
268 const char_type* const xend =
269 epptr () && epptr () < egptr () ? egptr () : epptr ();
270
271 const char_type *gap_beg = pptr () < eback ()
272 ? pptr () : egptr () < pbase () ? egptr () : pbase ();
273
274 const char_type *gap_end = pptr () < eback ()
275 ? eback () : egptr () < pbase () ? egptr () : pbase ();
276
277 // if gap_end is before gap_beg, set both so as to make the gap zero size
278 if (gap_end <= gap_beg)
279 gap_beg = gap_end = xend;
280
281 // compute the cumulative size of both sequences minus the gap
282 const streamsize slen = streamsize ((xend - xbeg) - (gap_end - gap_beg));
283
284 if (bufsize < slen || !_C_is_out ())
285 return 0; // failure
286
287 const bool free_old_buf = _C_own_buf ();
288
289 if (!buf) {
290 _TRY {
291 // allocate a new buffer
292 buf = _C_palloc ?
293 _RWSTD_STATIC_CAST (char_type*, _C_palloc (bufsize))
294 : new char [bufsize];
295 }
296 _CATCH (...) {
297 // catch all exceptions, indicate failure by returning 0
298 }
299
300 if (!buf)
301 return 0;
302
303 _C_own_buf (true);
304 }
305 else
306 _C_own_buf (false);
307
308 // copy both sequences from the old buffer to the new buffer
309 traits_type::copy (buf, xbeg, gap_beg - xbeg);
310 traits_type::copy (buf + (gap_beg - xbeg), gap_end, xend - gap_end);
311
312 if (free_old_buf) {
313 if (_C_pfree)
314 _C_pfree (_C_buffer);
315 else
316 delete[] _C_buffer;
317 }
318
319 _C_buffer = buf;
320 _C_bufsize = bufsize;
321
322 const _RWSTD_PTRDIFF_T seq_1_size = gap_beg - xbeg;
323
324 // restore output sequence
325 const streamsize pptr_off = streamsize (pptr () - pbase ());
326
327 if (pbase () < gap_beg)
328 setp (_C_buffer, _C_buffer + _C_bufsize);
329 else
330 setp (_C_buffer + seq_1_size, _C_buffer + _C_bufsize);
331
332 pbump (pptr_off);
333
334 // restore input sequence
335 char_type* const gbeg = _C_buffer + (eback () < gap_beg ? 0 : seq_1_size);
336 setg (gbeg, gbeg + (gptr () - eback ()), gbeg + (egptr () - eback ()));
337
338 return this;
339}
340
341
342void strstreambuf::
343_C_init (streamsize alsize,
344 const void *gnext_v,
345 streamsize n,
346 const void *pbeg_v,
347 void* (*palloc)(_RWSTD_SIZE_T),
348 void (*pdealloc)(void*),
349 int state)
350{
351 _C_alsize = alsize;
352 _C_palloc = palloc;
353 _C_pfree = pdealloc;
354
355 char* const gnext =
356 _RWSTD_STATIC_CAST (char*, _RWSTD_CONST_CAST (void*, gnext_v));
357
358 char* const pbeg =
359 _RWSTD_STATIC_CAST (char*, _RWSTD_CONST_CAST (void*, pbeg_v));
360
361 // D.7.1.1, p4
362 if (n < 0)
363 n = _RWSTD_INT_MAX;
364 else if (!n && gnext)
365 n = streamsize (traits_type::length (gnext));
366
367 _C_buffer = gnext;
368 _C_state = state | ios_base::in | ios_base::out;
369
370 if (pbeg) {
371 // D.7.1.1, p6
372 setg (gnext, gnext, pbeg);
373 setp (pbeg, pbeg + n);
374 }
375 else
376 // D.7.1.1, p5
377 setg (gnext, gnext, gnext + n);
378
379 _RWSTD_ASSERT (_C_is_valid ());
380}
381
382
383} // namespace std
#define which
Definition 17.names.cpp:575
#define way
Definition 17.names.cpp:574
#define Traits
Definition 17.names.cpp:556
#define slen
Definition 17.names.cpp:545
#define buf
Definition 17.names.cpp:452
#define off
Definition 17.names.cpp:507
#define c
Definition 17.names.cpp:111
#define n
Definition 17.names.cpp:130
#define _RWSTD_STATIC_CAST(T, x)
Definition _defs.h:534
#define _TRY
Definition _defs.h:850
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
#define _RWSTD_ASSERT(ignore)
Definition _defs.h:1108
#define _CATCH(ex)
Definition _defs.h:851
#define _RWSTD_CONST_CAST(T, x)
Definition _defs.h:536
Definition json.h:5363