Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
rw_streambuf.h
Go to the documentation of this file.
1
29#ifndef RW_STREAMBUF_H_INCLUDED
30#define RW_STREAMBUF_H_INCLUDED
31
32
33#include <cstring> // for memset()
34#include <streambuf> // for basic_streambuf
35
36#include <rw_testdefs.h>
37#include <rw_char.h> // for make_char()
38#include <rw_exception.h> // for rw_throw()
39
40
41enum MemFun {
42 // bitmask with a bit for each virtual member function
43 None = 0,
44 Setbuf = 0x0001,
45 Seekoff = 0x0002,
46 Seekpos = 0x0004,
47 Showmanyc = 0x0008,
48 Xsgetn = 0x0010,
49 Underflow = 0x0020,
50 Uflow = 0x0040,
51 Overflow = 0x0080,
52 Pbackfail = 0x0100,
53 Xsputn = 0x0200,
54 Sync = 0x0400,
55 // bit OR-ed with MemFun bits
56 Throw = 0x1000,
57 Failure = 0x2000
58};
59
60static const char* const streambuf_func_names[] = {
61 "setbuf", "seekoff", "seekpos", "showmanyc", "xsgetn", "underflow",
62 "uflow", "overflow", "pbackfail", "xsputn", "sync"
63};
64
65template <class charT, class Traits>
66struct MyStreambuf: std::basic_streambuf<charT, Traits>
67{
70 typedef std::basic_streambuf<char_type, traits_type> Base;
71 typedef typename Base::int_type int_type;
72 typedef typename Base::off_type off_type;
73 typedef typename Base::pos_type pos_type;
74
75 MyStreambuf (std::streamsize, int, int);
76
77 MyStreambuf (const char*, std::streamsize, int, int);
78
80 delete[] buf_;
81 }
82
83 // public interface to base class protected members
84 char_type* pubeback () const {
85 return this->eback ();
86 }
87
88 char_type* pubgptr () const {
89 return this->gptr ();
90 }
91
92 char_type* pubegptr () const {
93 return this->egptr ();
94 }
95
96 char_type* pubpbase () const {
97 return this->pbase ();
98 }
99
100 char_type* pubpptr () const {
101 return this->pptr ();
102 }
103
104 char_type* pubepptr () const {
105 return this->epptr ();
106 }
107
108 void pubsetg (charT *beg, charT *cur, charT *end) {
109 this->setg (beg, cur, end);
110 }
111
112 void pubsetp (charT *beg, charT *cur, charT *end) {
113 this->setp (beg, end);
114 this->pbump (cur - beg);
115 }
116
117private:
118
119 // overridden protected virtual functions
120 virtual Base* setbuf (char_type*, std::streamsize) {
121 return test (Setbuf) ? this : 0;
122 }
123
124 virtual pos_type
125 seekoff (off_type, std::ios_base::seekdir, std::ios_base::openmode) {
126 test (Seekoff);
127 return pos_type (off_type (-1));
128 }
129
130 virtual pos_type
131 seekpos (pos_type, std::ios_base::openmode) {
132 test (Seekpos);
133 return pos_type (off_type (-1));
134 }
135
136 virtual std::streamsize showmanyc () {
137 test (Showmanyc);
138 return 0;
139 }
140
141 virtual std::streamsize xsgetn (char_type*, std::streamsize) {
142 test (Xsgetn);
143 return 0;
144 }
145
146 virtual int_type underflow ();
147
148 virtual int_type uflow ();
149
150 virtual int_type
151 overflow (int_type = traits_type::eof ());
152
153 virtual int_type
154 pbackfail (int_type = traits_type::eof ());
155
156 virtual std::streamsize
157 xsputn (const char_type *buf, std::streamsize bufsize) {
158 if (!test (Xsputn))
159 return 0;
160 return Base::xsputn (buf, bufsize);
161 }
162
163 virtual int sync () {
164 test (Sync);
165 return 0;
166 }
167
168public:
169
170 int ncalls (MemFun) const;
171 int memfun_inx (MemFun) const;
172
174 std::streamsize bufsize_;
175
176 int throw_set_; // functions that should throw
177 int fail_set_; // functions that should fail
178 MemFun threw_; // which function threw
179 MemFun failed_; // which function failed
180
181 int fail_when_; // call number on which to fail
182
183 int throw_when_ [11]; // call number on which to throw for each func
184 int allthrows_; // total number of thrown exceptions
185
186 // max size of the pending input sequence
187 static std::streamsize in_pending_;
188
189 // max size of the pending output sequence
190 static std::streamsize out_pending_;
191
192private:
193
194 bool test (MemFun) const;
195
196 int ncalls_ [11]; // number of calls made to each function
197
198 int allcalls_; // total number of calls
199};
200
201
202template <class charT, class Traits>
203std::streamsize MyStreambuf<charT, Traits>::
204in_pending_ = 1;
205
206
207template <class charT, class Traits>
208std::streamsize MyStreambuf<charT, Traits>::
209out_pending_ = 1;
210
211
212template <class charT, class Traits>
214MyStreambuf (std::streamsize bufsize, int fail_set, int when)
215 : Base (), buf_ (0), bufsize_ (bufsize),
216 throw_set_ (0), fail_set_ (0), threw_ (None), failed_ (None),
217 fail_when_ (when), allthrows_ (0), allcalls_ (0)
218{
219 // reset the member function call counters
220 std::memset (ncalls_, 0, sizeof ncalls_);
221
222 // reset the member function throw counters
223 std::memset (throw_when_, 0, sizeof throw_when_);
224
225 // allocate a (possibly wide) character buffer for output
226 buf_ = new charT [bufsize_];
227
228 // invalidate the contents of the buffer
229 traits_type::assign (buf_, bufsize_, make_char ('\xfe', buf_));
230
231 // set the put area to 0 size to force a call to overflow()
232 // on the first write attempt to the buffer
233 this->setp (buf_, buf_);
234
235 // set the fail and throw flags
236 if (fail_set & Throw) {
237 throw_set_ = fail_set & ~Throw;
238
239 for (unsigned i = 0; i < 11; ++i)
240 if (throw_set_ & (1U << i))
241 throw_when_ [i] = when;
242 }
243 else {
244 fail_set_ = fail_set;
245 }
246}
247
248
249template <class charT, class Traits>
251MyStreambuf (const char *buf, std::streamsize bufsize, int fail_set, int when)
252 : Base (), buf_ (0), bufsize_ (bufsize),
253 throw_set_ (0), fail_set_ (0), threw_ (None), failed_ (None),
254 fail_when_ (when), allthrows_ (0), allcalls_ (0)
255{
256 // reset the member function call counters
257 std::memset (ncalls_, 0, sizeof ncalls_);
258
259 // reset the member function throw counters
260 std::memset (throw_when_, 0, sizeof throw_when_);
261
262 // as a convenience, if `bufsize == -1' compute the size
263 // from the length of `buf'
264 if (std::streamsize (-1) == bufsize_)
265 bufsize_ = std::streamsize (std::char_traits<char>::length (buf)) + 1;
266
267 // allocate a (possibly wide) character buffer to copy
268 // (and widen) the contents of `buf' into
269 buf_ = new charT [bufsize_ + 1];
270
271 for (std::streamsize inx = 0; inx != bufsize_; ++inx) {
272 typedef unsigned char UChar;
273
274 buf_ [inx] = make_char (buf [inx], buf_);
275 }
276
277 // zero out the (non-dereferenceable) element just past the end
278 // so that the buffer can be printed out as an ordinary string
279 buf_ [bufsize_] = charT ();
280
281 // set the get area to 0 size to force a call to underflow()
282 // on the first read attempt from the buffer
283 this->setg (buf_, buf_, buf_);
284
285 // set the fail and throw flags
286 if (fail_set & Throw) {
287 throw_set_ = fail_set & ~Throw;
288
289 for (unsigned i = 0; i < 11; ++i)
290 if (throw_set_ & (1U << i))
291 throw_when_ [i] = when;
292 }
293 else {
294 fail_set_ = fail_set;
295 }
296}
297
298
299template <class charT, class Traits>
302underflow ()
303{
304 if (!test (Underflow))
305 return traits_type::eof ();
306
307 if (this->egptr () - this->gptr () > 0) {
308 this->gbump (1);
309 return traits_type::to_int_type (*this->gptr ());
310 }
311
312 if (this->egptr () < buf_ + bufsize_) {
313
314 // increase the pending input sequence by no more than
315 // the lesser of the available buffer space and `in_pending_'
316 std::streamsize pending = buf_ + bufsize_ - this->egptr ();
317
318 if (pending > in_pending_)
319 pending = in_pending_;
320
321 this->setg (this->eback (), this->gptr (), this->egptr () + pending);
322 return traits_type::to_int_type (*this->gptr ());
323 }
324
325 failed_ = Underflow;
326 return traits_type::eof ();
327}
328
329
330template <class charT, class Traits>
333overflow (int_type c /* = traits_type::eof () */)
334{
335 if (!test (Overflow))
336 return traits_type::eof ();
337
338 if (this->epptr () - this->pptr () > 0) {
339 traits_type::assign (*this->pptr (), traits_type::to_char_type (c));
340 this->pbump (1);
341 return traits_type::not_eof (c);
342 }
343
344 if (this->epptr () < buf_ + bufsize_) {
345
346 // increase the pending output sequence by no more than
347 // the lesser of the available buffer space and `out_pending_'
348 std::streamsize pending = buf_ + bufsize_ - this->epptr ();
349
350 if (pending > out_pending_)
351 pending = out_pending_;
352
353 const std::streamsize pptr_off = this->pptr () - this->pbase ();
354
355 this->setp (this->pbase (), this->epptr () + pending);
356
357 this->pbump (pptr_off);
358
359 traits_type::assign (*this->pptr (), traits_type::to_char_type (c));
360
361 this->pbump (1);
362
363 return traits_type::not_eof (c);
364 }
365
366 failed_ = Overflow;
367 return traits_type::eof ();
368}
369
370
371template <class charT, class Traits>
374pbackfail (int_type c /* = traits_type::eof () */)
375{
376 if (!test (Pbackfail))
377 return traits_type::eof ();
378
379 if (this->gptr () == buf_) {
380 failed_ = Pbackfail;
381 return traits_type::eof ();
382 }
383
384 this->setg (this->gptr () - 1, this->gptr () - 1, this->gptr ());
385
386 const int_type last = traits_type::to_int_type (*this->gptr ());
387
388 if (!traits_type::eq_int_type (c, traits_type::eof ()))
389 traits_type::assign (*this->gptr (), traits_type::to_char_type (c));
390
391 return last;
392}
393
394
395template <class charT, class Traits>
398uflow ()
399{
400 if (!test (Uflow))
401 return traits_type::eof ();
402
403 if (this->egptr () - this->gptr () > 0) {
404 this->gbump (1);
405 return traits_type::to_int_type (*this->gptr ());
406 }
407
408 if (this->egptr () < buf_ + bufsize_) {
409
410 // increase the pending input sequence by no more than
411 // the lesser of the available buffer space and `in_pending_'
412 std::streamsize pending = buf_ + bufsize_ - this->egptr ();
413
414 if (pending > in_pending_)
415 pending = in_pending_;
416
417 this->setg (this->eback (), this->gptr (), this->egptr () + pending);
418 return traits_type::to_int_type (*this->gptr ());
419 }
420
421 failed_ = Uflow;
422 return traits_type::eof ();
423}
424
425template <class charT, class Traits>
426int
428memfun_inx (MemFun which) const
429{
430 int inx = -1;
431
432 for (unsigned i = 0; i < sizeof (which) * _RWSTD_CHAR_BIT; ++i) {
433 if (which & (1U << i)) {
434 if (inx < 0)
435 inx = i;
436 else
437 return -1;
438 }
439 }
440
441 return inx;
442}
443
444template <class charT, class Traits>
445int
447ncalls (MemFun which) const
448{
449 int inx = memfun_inx (which);
450 if (0 <= inx)
451 return ncalls_ [inx];
452
453 return -1;
454}
455
456
457template <class charT, class Traits>
458bool
460test (MemFun which) const
461{
462 MyStreambuf* const self = _RWSTD_CONST_CAST (MyStreambuf*, this);
463
464 const int inx = memfun_inx (which);
465 if (inx < 0)
466 return true;
467
468 // assert precondition to silence HP aCC 6/cadvise warning
469 // #20206-D: Out of bound access
470 RW_ASSERT ((_RWSTD_SIZE_T)inx < sizeof ncalls_ / sizeof *ncalls_);
471
472 // increment the counter tracking the number of calls made
473 // to each member function; do so regardless of whether
474 // an exception will be thrown below
475 self->ncalls_ [inx] ++;
476 self->allcalls_ ++;
477 const int callno = self->ncalls_ [inx];
478
479#ifndef _RWSTD_NO_EXCEPTIONS
480
481 // if the call counter is equal to the `fail_when_' watermark
482 // and `shich' is set in the `throw_set_' bitmask, throw an
483 // exception with the value of the member id
484 if (callno == throw_when_ [inx] && throw_set_ & which) {
485 self->threw_ = which;
486 self->allthrows_++;
487
488 rw_throw (ex_stream, __FILE__, __LINE__,
489 streambuf_func_names [inx],
490 "%s", "test exception");
491 }
492
493#else // if defined (_RWSTD_NO_EXCEPTIONS)
494
495 if (callno == throw_when_ [inx] && throw_set_ & which) {
496 self->threw_ = which;
497 return false;
498 }
499
500#endif // _RWSTD_NO_EXCEPTIONS
501
502 // ...otherwise check if the member should succeed or fail
503 // and return true or false, respectively
504 const bool success = !(fail_set_ & which) || callno != fail_when_;
505
506 if (!success)
507 self->failed_ = which;
508
509 return success;
510}
511
512
513#endif // RW_STREAMBUF_H_INCLUDED
#define i
Definition 17.names.cpp:126
#define last
Definition 17.names.cpp:487
#define which
Definition 17.names.cpp:575
#define pending
Definition 17.names.cpp:524
#define buf
Definition 17.names.cpp:452
#define c
Definition 17.names.cpp:111
#define charT
Definition 17.names.cpp:456
#define inx
Definition 17.names.cpp:484
std::char_traits< S > Traits
const int end
const int cur
#define _RWSTD_CONST_CAST(T, x)
Definition _defs.h:536
UserChar make_char(char c, UserChar *)
Definition rw_char.h:74
_TEST_EXPORT void rw_throw(ExceptionId exid, const char *file, int line, const char *function, const char *fmt,...)
@ ex_stream
MemFun
@ Pbackfail
@ Uflow
@ Overflow
@ Xsgetn
@ Throw
@ Failure
@ Seekoff
@ Sync
@ Showmanyc
@ Seekpos
@ None
@ Underflow
@ Xsputn
@ Setbuf
#define RW_ASSERT(expr)
unsigned char UChar
Definition collate.cpp:122
char_type * pubgptr() const
Traits traits_type
Base::pos_type pos_type
Base::int_type int_type
void pubsetg(charT *beg, charT *cur, charT *end)
charT char_type
char_type * pubepptr() const
static std::streamsize in_pending_
char_type * buf_
char_type * pubeback() const
char_type * pubpptr() const
char_type * pubegptr() const
char_type * pubpbase() const
void pubsetp(charT *beg, charT *cur, charT *end)
std::basic_streambuf< char_type, traits_type > Base
int memfun_inx(MemFun) const
std::streamsize bufsize_
int ncalls(MemFun) const
static std::streamsize out_pending_
Base::off_type off_type
int throw_when_[11]