Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
iostore.cpp
Go to the documentation of this file.
1
30#define _RWSTD_LIB_SRC
31
32#include <string.h> // memcpy(), memset()
33#include <rw/_rawiter.h> // get_temporary_buffer()
34
35#include "iosdata.h"
36
37#include <rw/_defs.h>
38
39
41
42
43// will grow an array of POD elements, never shrinks
44static void*
45__rw_realloc (void *array, _RWSTD_SIZE_T size, _RWSTD_SIZE_T &n, int inx)
46{
47 if (inx < 0)
48 return 0; // bad index
49
50 if (_RWSTD_STATIC_CAST (_RWSTD_SIZE_T, inx) < n)
51 return array; // no need to reallocate
52
53 void *tmp;
54
55 _TRY {
56 // make sure index is dereferencable (cast prevents HP aCC warnings)
57 tmp = operator new (_RWSTD_STATIC_CAST (_RWSTD_SIZE_T, ++inx) * size);
58 }
59 _CATCH (...) {
60 return 0;
61 }
62
63 _RWSTD_ASSERT (0 != tmp);
64
65 // copy elements from array to tmp
66 if (array)
67 memcpy (tmp, array, n * size);
68
69 // zero out newly allocated storage
70 memset (_RWSTD_STATIC_CAST (char*, tmp) + n * size, 0, (inx - n) * size);
71
72 // modify passed-in size
73 n = _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, inx);
74
75 operator delete (array);
76
77 return tmp;
78}
79
80
81} // namespace __rw
82
83
85
86
87/* static */ int ios_base::xalloc ()
88{
89 // outlined to hide implementation details
90
91 static int inx /* = 0 */;
92
93 return _RWSTD_ATOMIC_PREINCREMENT (inx, false) - 1;
94}
95
96
97void ios_base::_C_fire_event (event ev, bool reentrant)
98{
99 if (!_C_usr)
100 return;
101
102 _C_usr_data::_C_event_cb *cba = _C_usr->_C_cbarray;
103 _RWSTD_SIZE_T cbsize = _C_usr->_C_cbsize;
104
105 // verify consistency (either both are 0 or neither is)
106 _RWSTD_ASSERT (!!cba == !!cbsize);
107
108 if (!cba)
109 return;
110
111 // caller expected to lock if necessary
112
113 _TRY {
114 // protect `cba' from an exception (copy only necessary
115 // when `reentrant' is non-zero in which case we unlock
116 // the mutex and allow registered callbacks to call the
117 // stream member functions recursively)
118 if (reentrant) {
119 // never throws
120 cba = _GET_TEMP_BUFFER (_C_usr_data::_C_event_cb, cbsize).first;
121
122 if (!cba) {
123 // clear may throw...
124 _C_set (_C_state | badbit, _C_except | _RW::__rw_nolock,
125 _C_rdbuf);
126 return;
127 }
128
129 // verify consistency (neither must be 0 at this point)
130 _RWSTD_ASSERT (_C_usr->_C_cbarray && _C_usr->_C_cbsize);
131
132 // copy into temporary buffer
133 memcpy (cba, _C_usr->_C_cbarray, cbsize * sizeof *cba);
134
135 // unlock only if stream state allows it
136 if (!(flags () & _RW::__rw_nolock))
137 _C_unlock ();
138 }
139
140 // 27.4.2.6, p1 - call callbacks in opposite order of registration
141 for (_RWSTD_SIZE_T i = cbsize; i-- > 0; ) {
142
143 _RWSTD_ASSERT (cba && cba [i]._C_fn);
144
145 // ok if callback calls locking functions, we're unlocked
146 // and working with a local copy of callack array
147 cba [i]._C_fn (ev, *this, cba [i]._C_index);
148 }
149
150 if (reentrant) {
151 return_temporary_buffer (cba);
152
153 // lock only if stream state allows it (stream state
154 // may have been modified by one of the callbacks)
155 if (!(flags () & _RW::__rw_nolock))
156 _C_lock ();
157 }
158 }
159 _CATCH (...) {
160 if (reentrant) {
161 return_temporary_buffer (cba);
162
163 // lock only if `cba' was successfully allocated (or copied)
164 // and the stream state allows it (stream state may have been
165 // modified by one of the callbacks)
166 if (cba && !(flags () & _RW::__rw_nolock))
167 _C_lock ();
168 }
169 _RETHROW;
170 }
171}
172
173
174// succeeds irrespective of rdstate()
175void ios_base::
176_C_copyfmt (const ios_base &rhs,
177 void *dst, const void *src, _RWSTD_SIZE_T size)
178{
179 if (this == &rhs)
180 return;
181
182 typedef _C_usr_data::_C_event_cb EventCB;
183
184 // allocate sufficient storage
185 long *ia = 0;
186 void* *pa = 0;
187 EventCB *cba = 0;
188
189 _RWSTD_SIZE_T a_size [3]; // sizes of arrays above
190
191 unsigned fmtfl; // formatting flags
192 streamsize prec; // new precision
193 streamsize wide; // new width
194 unsigned except; // new exceptions
195 void* ptie; // tied ostream
196 locale loc; // new locale
197
198 char srcbuf [16]; // buffer to copy `src' to
199
200 // flags to copy from `rhs'
201 const fmtflags flagmask = ~(_RW::__rw_nolock | _RW::__rw_nolockbuf);
202
203 _TRY {
204 // lock `rhs', *this not locked yet
205 _RWSTD_MT_GUARD (rhs.flags () & _RW::__rw_nolock
206 ? 0 : &_RWSTD_CONST_CAST (ios_base&, rhs)._C_mutex);
207
208 if (rhs._C_usr) {
209
210 // copy pointer to the tied ostream, if any
211 ptie = rhs._C_usr->_C_tie;
212
213 // for convenience
214 const _C_usr_data* const rusr = rhs._C_usr;
215
216 // verify that either both are 0 or neither is
217 _RWSTD_ASSERT (!!rusr->_C_iarray == !!rusr->_C_isize);
218 _RWSTD_ASSERT (!!rusr->_C_parray == !!rusr->_C_psize);
219 _RWSTD_ASSERT (!!rusr->_C_cbarray == !!rusr->_C_cbsize);
220
221 a_size [0] = rusr->_C_isize;
222 a_size [1] = rusr->_C_psize;
223 a_size [2] = rusr->_C_cbsize;
224
225 ia = _RWSTD_STATIC_CAST (long*,
226 a_size [0] ? operator new (a_size [0] * sizeof *ia) : 0);
227
228 pa = _RWSTD_STATIC_CAST (void**,
229 a_size [1] ? operator new (a_size [1] * sizeof *pa) : 0);
230
231 cba = _RWSTD_STATIC_CAST (EventCB*,
232 a_size [2] ? operator new (a_size [2] * sizeof *cba) : 0);
233
234 // copy rhs into allocated storage and assign (27.4.4.2, p15)
235 memcpy (ia, rusr->_C_iarray, a_size [0] * sizeof *ia);
236 memcpy (pa, rusr->_C_parray, a_size [1] * sizeof *pa);
237 memcpy (cba, rusr->_C_cbarray, a_size [2] * sizeof *cba);
238 }
239 else {
240 // zero out array to prevent (bogus) gcc warnings
241 // about the variable being used uninitialized
242 memset (a_size, 0, sizeof a_size);
243
244 ptie = 0;
245 }
246
247 // copy the rest of rhs state (save for exceptions)
248 // while it's locked to guarantee atomicity
249 fmtfl = rhs._C_fmtfl;
250 prec = rhs._C_prec;
251 wide = rhs._C_wide;
252 except = rhs._C_except;
253 loc = rhs._C_loc;
254
255 // copy additional data (rhs's fill char) to the small
256 // temporary buffer only if it fits
257 if (size <= sizeof srcbuf)
258 src = memcpy (srcbuf, src, size);
259 }
260 _CATCH (...) {
261 // *this is unmodified
262 operator delete (ia);
263 operator delete (pa);
264 operator delete (cba);
265
266 _RETHROW;
267 }
268
269 // `rhs' unlocked, lock *this
270 _RWSTD_MT_GUARD (flags () & _RW::__rw_nolock ? 0 : &_C_mutex);
271
272 _TRY {
273 if (_C_usr) {
274 // fire erase events (27.4.4.2, p17) - may throw
275 if (_C_usr->_C_fire)
276 (this->*_C_usr->_C_fire)(erase_event, true /* reentrant */);
277
278 // delete existing arrays, if any; _C_usr will only be deleted
279 // if `rhs' contains no user data (see below)
280 operator delete (_C_usr->_C_iarray);
281 _C_usr->_C_iarray = 0;
282 _C_usr->_C_isize = 0;
283 operator delete (_C_usr->_C_parray);
284 _C_usr->_C_parray = 0;
285 _C_usr->_C_psize = 0;
286 operator delete (_C_usr->_C_cbarray);
287 _C_usr->_C_cbarray = 0;
288 _C_usr->_C_cbsize = 0;
289 }
290 else if (ia || pa || cba || ptie) {
291 // allocation may throw
292 _C_usr = new _C_usr_data ();
293
294#ifdef _RWSTD_NO_POD_ZERO_INIT
295
296# ifdef _RWSTD_NO_NEW_THROWS
297
298 if (!_C_usr)
299 _RW::__rw_throw (_RWSTD_ERROR_FIRST + 3 /* BAD_ALLOC */);
300
301# endif // _RWSTD_NO_NEW_THROWS
302
303 _RWSTD_ASSERT (0 != _C_usr);
304 memset (_C_usr, 0, sizeof *_C_usr);
305
306#endif // _RWSTD_NO_POD_ZERO_INIT
307
308 }
309 }
310 _CATCH (...) {
311 // *this is unmodified
312 operator delete (ia);
313 operator delete (pa);
314 operator delete (cba);
315
316 _RETHROW;
317 }
318
319 if (ia || pa || cba || ptie) {
320
321 // assing allocated and copied arrays and their sizes
322 _C_usr->_C_iarray = ia;
323 _C_usr->_C_parray = pa;
324 _C_usr->_C_cbarray = cba;
325
326 _C_usr->_C_isize = a_size [0];
327 _C_usr->_C_psize = a_size [1];
328 _C_usr->_C_cbsize = a_size [2];
329
330 _C_usr->_C_tie = ptie;
331
332 _C_usr->_C_fire = &ios_base::_C_fire_event;
333 }
334 else {
335 // `rhs' contains no user data, delete _C_usr
336 _C_usr_data::_C_dealloc (_C_usr);
337 _C_usr = 0;
338 }
339
340 // copy all but masked flags(), leave masked flags alone
341 _C_fmtfl = fmtfl & flagmask | _C_fmtfl & ~flagmask;
342 _C_prec = prec;
343 _C_wide = wide;
344 _C_loc = loc;
345
346 // copy additional data (fill character) -- will be atomic
347 // only if size is sufficiently small; since this is used
348 // for the fill character represented in derived classes
349 // as int_type this will be true for all standard iostreams
350 memcpy (dst, src, size);
351
352 if (_C_usr && _C_usr->_C_fire) {
353 _TRY {
354 // fire copy events (27.4.4.2, p17), may temporarily unlock
355 // or throw
356 (this->*_C_usr->_C_fire)(copyfmt_event, true /* reentrant */);
357 }
358 _CATCH (...) {
359 // must still assign exceptions
360 _C_except = except;
361
362 // just rethrow caught exception (don't call clear())
363 _RETHROW;
364 }
365 }
366
367 // assign exceptions last (27.4.4.2, p15, bullet 2)
368 _C_except = except;
369
370 // leave state alone but throw an exception if necessary
371 _C_set (_C_state, _C_except | _RW::__rw_nolock, _C_rdbuf);
372}
373
374
375long& ios_base::iword (int inx)
376{
377 _RWSTD_MT_GUARD (flags () & _RW::__rw_nolock ? 0 : &_C_mutex);
378
379 if (!_C_usr)
380 _C_usr = _C_usr_data::_C_alloc (&ios_base::_C_fire_event);
381
382 long* const ia = _C_usr
383 ? _RWSTD_STATIC_CAST (long*, _RW::__rw_realloc (_C_usr->_C_iarray,
384 sizeof (long),
385 _C_usr->_C_isize,
386 inx))
387 : 0;
388
389 if (ia) {
390 _RWSTD_ASSERT ( _C_usr->_C_isize
391 > _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, inx));
392
393 return (_C_usr->_C_iarray = ia)[inx];
394 }
395
396 _C_set (_C_state | badbit, _C_except | _RW::__rw_nolock, _C_rdbuf);
397
398 // returns a reference to a dummy object on failure (27.4.2.5, p3)
399 static long dummy_iword;
400
401 return dummy_iword = 0;
402}
403
404
405void*& ios_base::pword (int inx)
406{
407 _RWSTD_MT_GUARD (flags () & _RW::__rw_nolock ? 0 : &_C_mutex);
408
409 if (!_C_usr)
410 _C_usr = _C_usr_data::_C_alloc (&ios_base::_C_fire_event);
411
412 void** const pa = _C_usr
413 ? _RWSTD_STATIC_CAST (void**, _RW::__rw_realloc (_C_usr->_C_parray,
414 sizeof (void*),
415 _C_usr->_C_psize,
416 inx))
417 : 0;
418
419 if (pa) {
420 _RWSTD_ASSERT ( _C_usr->_C_psize
421 > _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, inx));
422
423 return (_C_usr->_C_parray = pa)[inx];
424 }
425
426 _C_set (_C_state | badbit, _C_except | _RW::__rw_nolock, _C_rdbuf);
427
428 // returns a reference to a dummy object on failure (27.4.2.5, p3)
429 static void *dummy_pword;
430
431 return dummy_pword = 0;
432}
433
434
435void ios_base::
436register_callback (event_callback fun, int inx)
437{
438 _RWSTD_ASSERT (0 != fun);
439
440 _RWSTD_MT_GUARD (flags () & _RW::__rw_nolock ? 0 : &_C_mutex);
441
442 if (!_C_usr)
443 _C_usr = _C_usr_data::_C_alloc (&ios_base::_C_fire_event);
444
445 typedef _C_usr_data::_C_event_cb EventCB;
446
447 _RWSTD_SIZE_T sz = 0;
448 EventCB *cba = 0;
449
450 if (_C_usr) {
451 sz = _C_usr->_C_cbsize;
452 cba = _RWSTD_STATIC_CAST (EventCB*,
453 _RW::__rw_realloc (_C_usr->_C_cbarray,
454 sizeof (EventCB),
455 _C_usr->_C_cbsize,
456 int (sz)));
457 }
458
459 if (cba) {
460 // array must have grown by at least one element
461 _RWSTD_ASSERT (sz < _C_usr->_C_cbsize);
462
463 _C_usr->_C_cbarray = cba;
464
465 _C_usr->_C_cbarray [sz]._C_index = inx;
466 _C_usr->_C_cbarray [sz]._C_fn = fun;
467 }
468 else {
469 // not required by 27.4.2.6
470 _C_set (_C_state | badbit, _C_except | _RW::__rw_nolock, _C_rdbuf);
471 }
472}
473
474
475} // namespace std
#define i
Definition 17.names.cpp:126
#define rhs
Definition 17.names.cpp:536
#define fun
Definition 17.names.cpp:471
#define loc
Definition 17.names.cpp:492
#define array
Definition 17.names.cpp:447
#define sz
Definition 17.names.cpp:550
#define tmp
Definition 17.names.cpp:553
#define n
Definition 17.names.cpp:130
#define inx
Definition 17.names.cpp:484
#define badbit
#define flags
#define _GET_TEMP_BUFFER(type, size)
Definition _defs.h:923
#define _RWSTD_ATOMIC_PREINCREMENT(x, ignore)
Definition _defs.h:699
#define _RETHROW
Definition _defs.h:853
#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_MT_GUARD(ignore)
Definition _defs.h:695
#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
#define _RWSTD_ERROR_FIRST
Definition _error.h:78
A TOML array.
Definition array.hpp:258
Definition json.h:5363