Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
27.stringbuf.virtuals.cpp
Go to the documentation of this file.
1
27#include <sstream> // for stringbuf
28#include <cstring> // for size_t, strchr()
29
30#include <rw_cmdopt.h> // for rw_enabled()
31#include <rw_driver.h> // for rw_assert(), ...
32#include <rw_char.h> // for rw_expand(), rw_match()
33
34
36#undef EOF
37#define EOF (_RWSTD_INT_MIN + 2)
38
39#undef NOT_EOF
40#define NOT_EOF (_RWSTD_INT_MIN + 1)
41
42#undef IGN
43#define IGN _RWSTD_INT_MIN
44
45#undef NPOS
46#define NPOS -1 // invalid position (post_type(off_type(-1))
47
48#define MAYBE_1 0 // 0 or more write positions available
49#define AT_LEAST_1 1 // at least one write position available
50
51
53template <class charT, class Traits>
54struct PubBuf: std::basic_stringbuf<charT, Traits>
55{
56 typedef std::basic_stringbuf<charT> Base;
57 typedef typename Base::char_type char_type;
58 typedef typename Base::int_type int_type;
59 typedef typename Base::off_type off_type;
60 typedef typename Base::pos_type pos_type;
61
62 char_type* Eback () const { return this->eback (); }
63 char_type* Gptr () const { return this->gptr (); }
64 char_type* Egptr () const { return this->egptr (); }
65
66 void Gbump (int n) { this->gbump (n); }
67
68 char_type* Pbase () const { return this->pbase (); }
69 char_type* Pptr () const { return this->pptr (); }
70 char_type* Epptr () const { return this->epptr (); }
71
72 int_type Pbackfail () { return this->pbackfail (); }
73 int_type Pbackfail (int_type c) { return this->pbackfail (c); }
74
75 int_type Overflow () { return this->overflow (); }
76 int_type Overflow (int_type c) { return this->overflow (c); }
77
78 int_type Underflow () { return this->underflow (); }
79
80 pos_type Seekoff (off_type off, std::ios_base::seekdir way) {
81 return this->seekoff (off, way);
82 }
83
84 pos_type Seekoff (off_type off, std::ios_base::seekdir way,
85 std::ios_base::openmode which) {
86 return this->seekoff (off, way, which);
87 }
88
90 return this->seekpos (pos);
91 }
92
93 pos_type Seekpos (pos_type pos, std::ios_base::openmode which) {
94 return this->seekpos (pos, which);
95 }
96
97 static int capacity (int n) {
98 Base buf (std::ios::out);
99 while (n--)
100 buf.sputc ('c');
101 return int (((PubBuf&)buf).Epptr () - ((PubBuf&)buf).Pbase ());
102 }
103};
104
105
106int traits_eof = -1;
107
108template <class charT>
109struct CharTraits: std::char_traits<charT>
110{
111 typedef std::char_traits<charT> Base;
112 typedef typename Base::int_type int_type;
113
114 // override eof() to detect bad assumptions
115 static int_type eof () { return traits_eof; }
117 return c == eof () ? int_type (!c) : c;
118 }
119};
120
121
123struct VFun
124{
125 enum charT { Char, WChar };
128 // which virtual function to exercise
130 };
131
132 VFun (charT cid, const char *cname,
133 Traits tid, const char *tname)
134 : cid_ (cid), tid_ (tid), vfun_ (),
135 cname_ (cname), tname_ (tname), fname_ (0),
136 strarg_ (0), sequence_ (0) { /* empty */ }
137
141 const char *cname_; // character type name
142 const char *tname_; // traits name
143 const char *fname_; // function name
144
145 const char *strarg_; // string argument
146 const char *sequence_; // final sequence
147};
148
149
150static int stringbuf_capacity;
151static char long_string [4096];
152
153
155template <class charT, class Traits>
156void test_virtual (charT, Traits, const VFun *pfid,
157 int line, // line number
158 const char *str, // ctor string argument
159 std::size_t, // length of string
160 int mode, // ctor mode argument
161 int gbump, // initial gptr offset
162 int arg0, // first argument
163 int arg1, // second argument
164 int arg2, // third argument
165 int ret_expect, // expected return value
166 int pback_expect, // ... size of putback area
167 int read_expect, // ... size of read area
168 int write_expect) // ... size of write area
169{
170 typedef std::allocator<charT> Allocator;
171 typedef std::basic_stringbuf<charT, Traits, Allocator> Stringbuf;
172
173 typedef typename Stringbuf::int_type int_type;
174 typedef typename Stringbuf::off_type off_type;
175 typedef typename Stringbuf::pos_type pos_type;
176
177 if (!rw_enabled (line)) {
178 rw_note (0, 0, 0, "test on line %d disabled", line);
179 return;
180 }
181
182 if (EOF == arg0)
183 arg0 = Traits::eof ();
184
185 if (EOF == ret_expect)
186 ret_expect = Traits::eof ();
187
188 // widen the source sequence into the (possibly wide) character buffer
189 static charT wstr [4096];
190 static charT warg [4096];
191
192 std::size_t wstr_len = sizeof wstr / sizeof *wstr;
193 std::size_t warg_len = sizeof warg / sizeof *warg;
194
195 wstr [0] = charT ();
196 rw_expand (wstr, str, _RWSTD_SIZE_MAX, &wstr_len);
197
198 const std::ios_base::openmode openmode = std::ios_base::openmode (mode);
199
200 // construct three stringbuf objects but use only the one that
201 // matches the provided arguments
202 Stringbuf sb_0;
203 Stringbuf sb_m (openmode);
204 Stringbuf sb_s (wstr);
205 Stringbuf sb_s_m (wstr, openmode);
206
208 (str ? -1 < mode ? &sb_s_m : &sb_s : -1 < mode ? &sb_m : &sb_0);
209
210 if (stringbuf_capacity < 0)
211 stringbuf_capacity =
212 PubBuf<charT, Traits>::capacity (-stringbuf_capacity);
213
214 if (gbump && IGN != gbump) {
215 // make sure gbump is valid
216 RW_ASSERT (gbump <= pbuf->Egptr () - pbuf->Eback ());
217
218 // advance gptr() as requested
219 pbuf->Gbump (gbump);
220 }
221
222 // create the argument to overflow
223 const int_type arg_int = int_type (arg0);
224 const off_type arg_off = off_type (arg0);
225 const pos_type arg_pos = arg_off;
226
227 const std::ios_base::seekdir arg_way = std::ios_base::seekdir (arg1);
228 const std::ios_base::openmode arg_which = std::ios_base::openmode (arg2);
229
230 int ret = EOF;
231
232 // invoke the virtual function with the expected argument (if any)
233 switch (pfid->vfun_) {
234 case VFun::xsputn: {
235
236 if (pfid->strarg_) {
237 rw_expand (warg, pfid->strarg_, _RWSTD_SIZE_MAX, &warg_len);
238 if (std::strchr (pfid->strarg_, '@'))
239 arg0 = int (warg_len);
240
241 RW_ASSERT (std::size_t (arg0) < sizeof wstr / sizeof *wstr);
242 ret = int (pbuf->sputn (warg, std::streamsize (arg0)));
243 }
244 else {
245 // invoke sputn() with pbase as an argument
246 ret = int (pbuf->sputn (pbuf->Pbase (), std::streamsize (arg0)));
247 }
248
249 break;
250 }
251
252 case VFun::pbackfail:
253 ret = IGN == arg0 ? pbuf->Pbackfail ()
254 : pbuf->Pbackfail (arg_int);
255 break;
256
257 case VFun::overflow:
258 ret = IGN == arg0 ? pbuf->Overflow ()
259 : pbuf->Overflow (arg_int);
260 break;
261
262 case VFun::underflow:
263 ret = pbuf->Underflow ();
264 break;
265
266 case VFun::seekoff:
267 ret = IGN == arg2 ? pbuf->Seekoff (arg_off, arg_way)
268 : pbuf->Seekoff (arg_off, arg_way, arg_which);
269 break;
270
271 case VFun::seekpos:
272 ret = IGN == arg2 ? pbuf->Seekpos (arg_pos)
273 : pbuf->Seekpos (arg_pos, arg_which);
274 break;
275 }
276
277 // compute the number of putback positions available
278 // see 27.5.1, p3, bullet 3
279 const int pback_pos = int (pbuf->Gptr () - pbuf->Eback ());
280
281 // compute the number of read positions available
282 // see 27.5.1, p3, bullet 4
283 const int read_pos = int (pbuf->Egptr () - pbuf->Gptr ());
284
285 // compute the number of write positions available
286 // see 27.5.1, p3, bullet 2
287 const int write_pos = int (pbuf->Epptr () - pbuf->Pptr ());
288
289 // set up a format string with the name of the class and member
290 // function being called and describing the function arguments
291 // basic_stringbuf<char> is formatted as stringbuf
292 // basic_stringbuf<wchar_t> is formatted as wstringbuf
293 // all other specializations are fully spelled out
294#define CALLFMT \
295 "line %d. " \
296 "%{?}basic_%{:}%{?}w%{;}%{;}stringbuf%{?}<%s%{?}, %s%{;}>%{;}" \
297 "(%{?}%{*Ac}%{?}, %{Io}%{;}%{:}%{?}%{Io}%{;}%{;})" \
298 ".%s (%{?}%{?}%{*Ac}%{:}pptr()%{;}, %d" /* xsputn */ \
299 "%{:}%{?}" /* pbackfail, over/underflow argument */ \
300 "%{?}%{#lc}%{;}" \
301 "%{:}" /* seekoff and seekpos */ \
302 "%d%{?}, %{Iw}%{?}, %{Io}%{;}" \
303 "%{:}%{?}, %{Io}%{;}%{;}" \
304 "%{;}%{;})"
305
306 // is the tested virtual function seekoff or seekpos?
307 const bool is_seek = VFun::seekoff <= pfid->vfun_;
308
309 // arguments corresponding to CALLFMT
310#define CALLARGS \
311 __LINE__, \
312 0 != pfid->tname_, 'w' == *pfid->cname_, 0 != pfid->tname_, \
313 pfid->cname_, 0 != pfid->tname_, pfid->tname_, \
314 0 != str, int (sizeof *wstr), wstr, -1 < mode, mode, -1 < mode, mode, \
315 pfid->fname_, pfid->vfun_ == VFun::xsputn, 0 != pfid->strarg_, \
316 int (sizeof *warg), warg, arg0, \
317 !is_seek, \
318 IGN != arg0, arg_int, \
319 arg0, VFun::seekoff == pfid->vfun_, arg1, IGN != arg2, arg2, \
320 IGN != arg1, arg1
321
322 const int_type not_eof = Traits::not_eof (arg_int);
323
324 int success = ret == (NOT_EOF == ret_expect ? int (not_eof) : ret_expect);
325
326 // verify the expected return value
327 if (pfid->vfun_ == VFun::xsputn || is_seek) {
328 rw_assert (success, 0, line,
329 CALLFMT " == %d, got %d",
330 CALLARGS, ret_expect, ret);
331 }
332 else {
333 rw_assert (success, 0, line,
334 CALLFMT " == %{?}not EOF%{:}%{#lc}%{;}, got %{#lc}",
335 CALLARGS, NOT_EOF == ret_expect, ret_expect, ret);
336 }
337
338 // verify the expected size of the putback area
339 if (IGN != pback_expect)
340 rw_assert (pback_pos == pback_expect, 0, line,
341 CALLFMT ": putback positions (gptr - eback) == %d, got %d"
342 "%{?}: gptr = NULL%{;}",
343 CALLARGS, pback_expect, pback_pos,
344 0 == pbuf->Gptr ());
345
346 // verify the expected size of the read area
347 if (IGN != read_expect)
348 rw_assert (read_pos == read_expect, 0, line,
349 CALLFMT ": read positions (egptr - gptr) == %d, got %d: "
350 "gptr = %{?}NULL%{:}eback + %td%{;}",
351 CALLARGS, read_expect, read_pos,
352 0 == pbuf->Gptr (), pbuf->Gptr () - pbuf->Eback ());
353
354 // verify the expected size of the write area
355 if (IGN != write_expect) {
356
357 // at least as many write positions as expected
358 success = -1 < write_expect ?
359 write_expect <= write_pos : 0 == write_pos;
360
361 rw_assert (success, 0, line,
362 CALLFMT ": write positions (epptr - pptr) "
363 "%{?}==%{:}>=%{;} %d, got %d: "
364 "pptr = %{?}NULL%{:}pbase + %td%{;}",
365 CALLARGS, 1 < write_expect, write_expect, write_pos,
366 0 == pbuf->Pptr (), pbuf->Pptr () - pbuf->Pbase ());
367 }
368
369 if (pfid->sequence_) {
370
371 // verify that the put area matches the expected sequence
372 const std::size_t len = pbuf->Pptr () - pbuf->Pbase ();
373 const std::size_t xmatch =
374 rw_match (pfid->sequence_, pbuf->Pbase (), len);
375
376 rw_assert (xmatch == len, 0, line,
377 CALLFMT ": put area mismatch (pbase + %zu)",
378 CALLARGS, xmatch);
379 }
380}
381
382
384// dispatches to the appropriate specialization of the function template
385void test_virtual (VFun *pfid,
386 int line,
387 const char *str,
388 std::size_t str_len,
389 int mode,
390 int gbump,
391 int arg0,
392 int arg1,
393 int arg2,
394 int ret_expect,
395 int pback_expect,
396 int read_expect,
397 int write_expect)
398{
399#undef TEST
400#define TEST(charT, Traits) \
401 test_virtual (charT (), Traits (), pfid, line, \
402 str, str_len, mode, gbump, \
403 arg0, arg1, arg2, ret_expect, \
404 pback_expect, read_expect, write_expect)
405
406 static const char* const fnames[] = {
407 "xsputn", "pbackfail", "overflow", "underflow", "seekoff", "seekpos"
408 };
409
410 if (!rw_enabled (line)) {
411 rw_note (0, 0, __LINE__, "test on line %d disabled", line);
412 return;
413 }
414
415 pfid->fname_ = fnames [pfid->vfun_];
416
417 if (VFun:: DefaultTraits == pfid->tid_) {
418 if (VFun::Char == pfid->cid_)
419 TEST (char, std::char_traits<char>);
420#ifndef _RWSTD_NO_WCHAR_T
421 else
422 TEST (wchar_t, std::char_traits<wchar_t>);
423#endif // _RWSTD_NO_WCHAR_T
424 }
425 else {
426 if (VFun::Char == pfid->cid_)
427 TEST (char, CharTraits<char>);
428
429#ifndef _RWSTD_NO_WCHAR_T
430 else
431 TEST (wchar_t, CharTraits<wchar_t>);
432#endif // _RWSTD_NO_WCHAR_T
433 }
434
435 pfid->strarg_ = 0;
436 pfid->sequence_ = 0;
437}
438
439
441// convenience constants
442const int in = std::ios::in;
443const int out = std::ios::out;
444const int ate = std::ios::ate;
445
446const int cur = std::ios::cur;
447const int end = std::ios::end;
448
449static int rw_opt_max_size = 1024;
450
451
453static void
454test_xsputn (VFun *pfid)
455{
456 rw_info (0, 0, 0, "basic_stringbuf<%s%{?}, %s%{;}>::xsputn"
457 "(const char_type*, streamsize)",
458 pfid->cname_, 0 != pfid->tname_, pfid->tname_);
459
460 pfid->vfun_ = VFun::xsputn;
461
462#undef TEST
463#define TEST(str, mode, gbump, sarg, result, pback, read, write) \
464 pfid->strarg_ = sarg; \
465 test_virtual (pfid, __LINE__, str, sizeof str - 1, mode, \
466 gbump, int (sizeof sarg - 1), IGN, IGN, result, \
467 pback, read, write)
468
469 // +-------------------------------------------- initial sequence
470 // | +------------------------------------- open mode
471 // | | +--------------------- gbump (gptr offset)
472 // | | | +----------------- xsputn argument
473 // | | | | +----------- expected return value
474 // | | | | | +-------- putback positions
475 // | | | | | | +----- read positions
476 // | | | | | | | +-- write positions
477 // | | | | | | | |
478 // V V V V V V V V
479 TEST (0, 0, 0, "", 0, 0, 0, -1);
480 TEST (0, 0, 0, "a", 0, 0, 0, -1);
481 TEST (0, in, 0, "a", 0, 0, 0, -1);
482 TEST (0, out, 0, "a", 1, 0, 0, MAYBE_1);
483 TEST (0, out, 0, "ab", 2, 0, 0, MAYBE_1);
484 TEST (0, out, 0, "abc", 3, 0, 0, MAYBE_1);
485 TEST (0, in | out, 0, "abc", 3, 0, 3, MAYBE_1);
486 TEST (0, in | out | ate, 0, "abc", 3, 0, 3, MAYBE_1);
487
488 TEST ("abc", in | out, 0, "def", 3, 0, 6, MAYBE_1);
489 TEST ("abc", in | out | ate, 0, "def", 3, 0, 6, MAYBE_1);
490
491 TEST ( 0, in | out, 0, "a@1000", 1000, 0, 1000, MAYBE_1);
492 TEST ( 0, in | out, 0, "a@1000", 1000, 0, 1000, MAYBE_1);
493
494 TEST ( 0, in | out, 0, "a@1001", 1001, 0, 1001, MAYBE_1);
495 TEST ( "a@1", in | out, 0, "a@1002", 1002, 0, 1003, MAYBE_1);
496 TEST ( "a@2", in | out, 0, "a@1003", 1003, 0, 1005, MAYBE_1);
497 TEST ( "a@3", in | out, 0, "a@1004", 1004, 0, 1007, MAYBE_1);
498
499 TEST ( 0, in | out | ate, 0, "a@1000", 1000, 0, 1000, MAYBE_1);
500 TEST ( 0, in | out | ate, 0, "a@1001", 1001, 0, 1001, MAYBE_1);
501 TEST ( "a@1", in | out | ate, 0, "a@1002", 1002, 0, 1003, MAYBE_1);
502 TEST ( "a@2", in | out | ate, 0, "a@1003", 1003, 0, 1005, MAYBE_1);
503 TEST ( "a@3", in | out | ate, 0, "a@1004", 1004, 0, 1007, MAYBE_1);
504 TEST ( "a@127", in | out | ate, 0, "a@1005", 1005, 0, 1132, MAYBE_1);
505
506 TEST ("a@1000", in | out | ate, 0, "a@1006", 1006, 0, 2006, MAYBE_1);
507 TEST ("a@2000", in | out | ate, 0, "a@1007", 1007, 0, 3007, MAYBE_1);
508 TEST ("a@2001", in | out | ate, 0, "a@1008", 1008, 0, 3009, MAYBE_1);
509
511 // exercise calling sputn() with pptr() as the first argument
512#undef TEST
513#define TEST(str, mode, len, result, seq, read) \
514 pfid->strarg_ = 0; pfid->sequence_ = seq; \
515 test_virtual (pfid, __LINE__, str, sizeof str - 1, mode, \
516 0, len, IGN, IGN, result, \
517 0, read, MAYBE_1)
518
519 // +---------------------------------------------- initial sequence
520 // | +------------------------------------ open mode
521 // | | +-------------------- xsputn 2nd argument
522 // | | | +-------------- return value
523 // | | | | +-------- sequence at pbase()
524 // | | | | | +-- read positions
525 // | | | | | |
526 // | | | | | +---------+
527 // | | | | | |
528 // V V V V V V
529 TEST ( "a@500b", in | out | ate, 11, 11, "a@500ba@11", 512);
530 TEST ( "a@500b", in | out | ate, 12, 12, "a@500ba@12", 513);
531 TEST ( "a@500b", in | out | ate, 13, 13, "a@500ba@13", 514);
532 TEST ( "a@500b", in | out | ate, 500, 500, "a@500ba@500", 1001);
533 TEST ( "a@500b", in | out | ate, 501, 501, "a@500ba@500b", 1002);
534 TEST ("a@1022b", in | out | ate, 1, 1, "a@1022ba", 1024);
535 TEST ("a@1023b", in | out | ate, 1, 1, "a@1023ba", 1025);
536
538 // exercise multiples of stringbuf capacity
539#undef TEST
540#define TEST(len, mode, gbump, arg_len, result, pback, read, write) \
541 pfid->strarg_ = long_string + (sizeof long_string - 1 - len), \
542 test_virtual (pfid, __LINE__, pfid->strarg_, \
543 len, mode, gbump, arg_len, IGN, IGN, \
544 result, pback, read, write)
545
546// for convenience
547#define CAP stringbuf_capacity
548
549 // compute the minimum buffer capacity
550 stringbuf_capacity = -1;
551 TEST ( 0, in | out, 0, 0, 0, 0, 0, -1);
552
553 // +----------------------------------------------- length of sequence
554 // | +------------------------------------------ open mode
555 // | | +-------------------------- gbump (gptr offset)
556 // | | | +-------------------- xsputn 2nd argument
557 // | | | | +-------------- expected return value
558 // | | | | | +-------- putback positions
559 // | | | | | | +----- read positions
560 // | | | | | | | +-- write positions
561 // | | | | | | | |
562 // | | | | | | | +--------+
563 // | | | | | | | |
564 // V V V V V V V V
565 TEST (CAP, in | out, 0, 1, 1, 0, CAP + 1, MAYBE_1);
566 TEST (CAP, in | out, 0, 2, 2, 0, CAP + 2, MAYBE_1);
567 TEST (CAP, in | out, 0, 3, 3, 0, CAP + 3, MAYBE_1);
568 TEST (CAP, in | out, 0, 127, 127, 0, CAP + 127, MAYBE_1);
569 TEST (CAP, in | out, 0, 1023, 1023, 0, CAP + 1023, MAYBE_1);
570 TEST (CAP, in | out, 0, 1024, 1024, 0, CAP + 1024, MAYBE_1);
571 TEST (CAP, in | out, 0, CAP, CAP, 0, CAP + CAP, MAYBE_1);
572
573 TEST (CAP, in | out | ate, 0, 1, 1, 0, CAP + 1, MAYBE_1);
574 TEST (CAP, in | out | ate, 0, 2, 2, 0, CAP + 2, MAYBE_1);
575 TEST (CAP, in | out | ate, 0, 3, 3, 0, CAP + 3, MAYBE_1);
576 TEST (CAP, in | out | ate, 0, CAP, CAP, 0, CAP + CAP, MAYBE_1);
577 TEST (CAP, in | out | ate, 0, 127, 127, 0, CAP + 127, MAYBE_1);
578 TEST (CAP, in | out | ate, 0, 1023, 1023, 0, CAP + 1023, MAYBE_1);
579 TEST (CAP, in | out | ate, 0, 1024, 1024, 0, CAP + 1024, MAYBE_1);
580 TEST (CAP, in | out | ate, 0, 1025, 1025, 0, CAP + 1025, MAYBE_1);
581
582 for (int i = 0; i != rw_opt_max_size; ++i) {
583 TEST ( 0, in | out, 0, i, i, 0, i + 0, MAYBE_1);
584 TEST ( 1, in | out, 0, i, i, 0, i + 1, MAYBE_1);
585 TEST ( 32, in | out, 0, i, i, 0, i + 32, MAYBE_1);
586 TEST (127, in | out, 0, i, i, 0, i + 127, MAYBE_1);
587 TEST (CAP, in | out, 0, i, i, 0, i + CAP, MAYBE_1);
588 }
589}
590
591
593static void
594test_pbackfail (VFun *pfid)
595{
596 rw_info (0, 0, 0, "basic_stringbuf<%s%{?}, %s%{;}>::pbackfail(int_type)",
597 pfid->cname_, 0 != pfid->tname_, pfid->tname_);
598
599 pfid->vfun_ = VFun::pbackfail;
600
601#undef TEST
602#define TEST(str, mode, gbump, arg, result, pback, read, write) \
603 test_virtual (pfid, __LINE__, str, sizeof str - 1, mode, \
604 gbump, arg, IGN, IGN, result, pback, read, write)
605
607 // 27.7.1.3
608 //
609 // -2- Effects: Puts back the character designated by c to the input
610 // sequence, if possible, in one of three ways:
611 // -- If traits::eq_int_type(c,traits::eof()) returns false and
612 // if the input sequence has a putback position available,
613 // and if traits::eq(to_char_type(c),gptr()[-1]) returns true,
614 // assigns gptr() - 1 to gptr().
615 // Returns: c.
616 // -- If traits::eq_int_type(c,traits::eof()) returns false and
617 // if the input sequence has a putback position available, and
618 // if mode & ios_base::out is nonzero, assigns c to *--gptr().
619 // Returns: c.
620 // -- If traits::eq_int_type(c,traits::eof()) returns true and if
621 // the input sequence has a putback position available, assigns
622 // gptr() - 1 to gptr().
623 // Returns: traits::not_eof(c).
624 // -3- Returns: traits::eof() to indicate failure.
625 // -4- Notes: If the function can succeed in more than one of these ways,
626 // it is unspecified which way is chosen.
627
628 // +----------------------------------------- initial sequence (if any)
629 // | +---------------------------------- open mode
630 // | | +------------------------ gbump (gptr offset)
631 // | | | +-------------------- pbackfail argument
632 // | | | | +---------------- expected return value
633 // | | | | | +----------- number of putback positions
634 // | | | | | | +-------- number of read positions
635 // | | | | | | | +----- number of write positions
636 // | | | | | | | |
637 // V V V V V V V V
638 TEST (0, 0, 0, 'c', EOF, 0, 0, -1);
639 TEST (0, 0, 0, EOF, EOF, 0, 0, -1);
640
641 TEST (0, in, 0, 'c', EOF, 0, 0, -1);
642 TEST (0, out, 0, EOF, EOF, 0, 0, -1);
643 TEST (0, ate, 0, EOF, EOF, 0, 0, -1);
644 TEST (0, in | out, 0, 'c', EOF, 0, 0, -1);
645 TEST (0, in | out, 0, EOF, EOF, 0, 0, -1);
646
647 TEST ("a", 0, 0, 'c', EOF, 0, 0, -1);
648 TEST ("a", in, 0, 'c', EOF, 0, 1, -1);
649 TEST ("a", in, 1, 'c', EOF, 1, 0, -1);
650 TEST ("a", in, 1, 'a', 'a', 0, 1, -1);
651 TEST ("a", out, 0, 'c', EOF, 0, 0, AT_LEAST_1);
652 TEST ("a", ate, 0, 'c', EOF, 0, 0, -1);
653
654 TEST ("abc", in, 1, 'c', EOF, 1, 2, -1);
655 TEST ("abc", in, 2, 'c', EOF, 2, 1, -1);
656 TEST ("abc", in, 3, 'c', 'c', 2, 1, -1);
657
658 TEST ("abc", in | out, 0, 'c', EOF, 0, 3, AT_LEAST_1);
659 TEST ("abc", in | out, 1, 'c', 'c', 0, 3, AT_LEAST_1);
660 TEST ("abc", in | out, 2, 'c', 'c', 1, 2, AT_LEAST_1);
661 TEST ("abc", in | out, 3, 'c', 'c', 2, 1, AT_LEAST_1);
662}
663
664
666static void
667test_overflow (VFun *pfid)
668{
669 rw_info (0, 0, 0, "basic_stringbuf<%s%{?}, %s%{;}>::overflow(int_type)",
670 pfid->cname_, 0 != pfid->tname_, pfid->tname_);
671
672 pfid->vfun_ = VFun::overflow;
673
674#undef TEST
675#define TEST(str, mode, gbump, arg, result, pback, read, write) \
676 test_virtual (pfid, __LINE__, str, sizeof str - 1, mode, gbump, \
677 arg, IGN, IGN, result, pback, read, write);
678
680 // 27.7.1.3 + LWG issues 169 and 432
681 //
682 // -5- Effects: Appends the character designated by c to the output
683 // sequence, if possible, in one of two ways:
684 // -- If traits::eq_int_type(c,traits::eof()) returns false and
685 // if either the output sequence has a write position available
686 // or the function makes a write position available (as described
687 // below), the function calls sputc(c).
688 // Signals success by returning c.
689 // -- If traits::eq_int_type(c,traits::eof()) returns true, there
690 // is no character to append.
691 // Signals success by returning a value other than traits::eof().
692 // -6- Notes: The function can alter the number of write positions
693 // available as a result of any call.
694 // -7- Returns: traits::eof() to indicate failure.
695 // -8- (blank)
696 // -9- Notes: The function can make a write position available only if
697 // (mode & ios_base::out) != 0. To make a write position available,
698 // the function reallocates (or initially allocates) an array object
699 // with a sufficient number of elements to hold the current array
700 // object (if any), plus one additional write position. If
701 // (mode & ios_base::in) != 0, the function alters the read end
702 // pointer egptr() to point just past the new write position.
704
705 // +-------------------------------------- initial sequence (if any)
706 // | +---------------------------------- open mode
707 // | | +------------------------ gbump
708 // | | | +-------------------- overflow argument
709 // | | | | +---------------- result of call
710 // | | | | | +---------- putback positions after call
711 // | | | | | | +------ read positions after call
712 // | | | | | | | +-- write positions after call
713 // | | | | | | | |
714 // | | | | | | | |
715 // V V V V V V V V
716 TEST (0, 0, 0, 'c', EOF, 0, 0, -1);
717 TEST (0, in, 0, 'c', EOF, 0, 0, -1);
718 TEST (0, out, 0, 'c', 'c', 0, 0, AT_LEAST_1);
719 TEST (0, in | out, 0, 'c', 'c', 0, 1, AT_LEAST_1);
720
721 TEST (0, in | ate, 0, 'c', EOF, 0, 0, -1);
722 TEST (0, out | ate, 0, 'c', 'c', 0, 0, AT_LEAST_1);
723 TEST (0, in | out | ate, 0, 'c', 'c', 0, 1, AT_LEAST_1);
724
725 TEST ("", 0, 0, 'c', EOF, 0, 0, -1);
726 TEST ("", in, 0, 'c', EOF, 0, 0, -1);
727 TEST ("", out, 0, 'c', 'c', 0, 0, AT_LEAST_1);
728 TEST ("", in | out, 0, 'c', 'c', 0, 1, AT_LEAST_1);
729
730 TEST ("a", 0, 0, 'c', EOF, 0, 0, -1);
731 TEST ("a", in, 0, 'c', EOF, 0, 1, -1);
732 TEST ("a", out, 0, 'c', 'c', 0, 0, AT_LEAST_1);
733 TEST ("a", in | out, 0, 'c', 'c', 0, 2, AT_LEAST_1);
734
735 TEST ("a", in | ate, 0, 'c', EOF, 0, 1, -1);
736 TEST ("a", out | ate, 0, 'c', 'c', 0, 0, MAYBE_1);
737 TEST ("a", in | out | ate, 0, 'c', 'c', 0, 2, MAYBE_1);
738
739 TEST ("ab", 0, 0, 'c', EOF, 0, 0, -1);
740 TEST ("ab", in, 0, 'c', EOF, 0, 2, -1);
741 TEST ("ab", out, 0, 'c', 'c', 0, 0, AT_LEAST_1);
742 TEST ("ab", in | out, 0, 'c', 'c', 0, 3, AT_LEAST_1);
743
744 TEST ("ab", in | ate, 0, 'c', EOF, 0, 2, -1);
745 TEST ("ab", out | ate, 0, 'c', 'c', 0, 0, AT_LEAST_1);
746 TEST ("ab", in | out | ate, 0, 'c', 'c', 0, 3, AT_LEAST_1);
747
748 // verify that when the argument is EOF the function returns a value
749 // other than traits::eof() regardless of the streambuf open mode
750 TEST (0, 0, 0, EOF, NOT_EOF, 0, 0, -1);
751 TEST (0, in, 0, EOF, NOT_EOF, 0, 0, -1);
752 TEST (0, out, 0, EOF, NOT_EOF, 0, 0, -1);
753 TEST (0, in | out, 0, EOF, NOT_EOF, 0, 0, -1);
754 TEST (0, in | ate, 0, EOF, NOT_EOF, 0, 0, -1);
755 TEST (0, out | ate, 0, EOF, NOT_EOF, 0, 0, -1);
756 TEST (0, in | out | ate, 0, EOF, NOT_EOF, 0, 0, -1);
757
758 TEST ("abc", 0, 0, EOF, NOT_EOF, 0, 0, -1);
759 TEST ("abc", in, 0, EOF, NOT_EOF, 0, 3, -1);
760 TEST ("abc", out, 0, EOF, NOT_EOF, 0, 0, AT_LEAST_1);
761 TEST ("abc", in | out, 0, EOF, NOT_EOF, 0, 3, AT_LEAST_1);
762 TEST ("abc", in | ate, 0, EOF, NOT_EOF, 0, 3, -1);
763 TEST ("abc", out | ate, 0, EOF, NOT_EOF, 0, 0, MAYBE_1);
764 TEST ("abc", in | out | ate, 0, EOF, NOT_EOF, 0, 3, MAYBE_1);
765}
766
767
769static void
770test_underflow (VFun *pfid)
771{
772 rw_info (0, 0, 0, "basic_stringbuf<%s%{?}, %s%{;}>::underflow()",
773 pfid->cname_, 0 != pfid->tname_, pfid->tname_);
774
775 pfid->vfun_ = VFun::underflow;
776
777#undef TEST
778#define TEST(str, mode, gbump, result, pback, read, write) \
779 test_virtual (pfid, __LINE__, str, sizeof str - 1, mode, gbump, \
780 IGN, IGN, IGN, result, pback, read, write);
781
782
784 // 27.7.1.3 + LWG issue 432
785 //
786 // int_type undeflow ()
787 //
788 // -1- If the input sequence has a read position available, returns
789 // traits::to_int_type(*gptr()). Otherwise, returns traits::eof().
790 // Any character in the underlying buffer which has been initialized
791 // is considered to be part of the input sequence.
792
793 // +------------------------------------------ initial sequence
794 // | +----------------------------------- open mode
795 // | | +------------------- gbump
796 // | | | +---------------- underflow result
797 // | | | | +----------- putback positions
798 // | | | | | +-------- read positions
799 // | | | | | | +---- write positions
800 // | | | | | | |
801 // | | | | | | |
802 // | | | | | | |
803 // V V V V V V V
804 TEST (0, 0, 0, EOF, 0, 0, -1);
805 TEST (0, in, 0, EOF, 0, 0, -1);
806 TEST (0, out, 0, EOF, 0, 0, -1);
807 TEST (0, in | out, 0, EOF, 0, 0, -1);
808 TEST (0, in | out | ate, 0, EOF, 0, 0, -1);
809
810 TEST ("", 0, 0, EOF, 0, 0, -1);
811 TEST ("", in, 0, EOF, 0, 0, -1);
812 TEST ("", out, 0, EOF, 0, 0, -1);
813 TEST ("", in | out, 0, EOF, 0, 0, -1);
814 TEST ("", in | out | ate, 0, EOF, 0, 0, -1);
815
816 TEST ("abc", 0, 0, EOF, 0, 0, -1);
817 TEST ("abc", in, 0, 'a', 0, 3, -1);
818 TEST ("abc", in, 1, 'b', 1, 2, -1);
819 TEST ("abc", in, 2, 'c', 2, 1, -1);
820 TEST ("abc", in, 3, EOF, 3, 0, -1);
821 TEST ("abc", out, 0, EOF, 0, 0, AT_LEAST_1);
822 TEST ("abc", in | out, 0, 'a', 0, 3, AT_LEAST_1);
823 TEST ("abc", in | out, 1, 'b', 1, 2, AT_LEAST_1);
824 TEST ("abc", in | out, 2, 'c', 2, 1, AT_LEAST_1);
825 TEST ("abc", in | out, 3, EOF, 3, 0, AT_LEAST_1);
826 TEST ("abc", in | out | ate, 0, 'a', 0, 3, MAYBE_1);
827 TEST ("abc", in | out | ate, 1, 'b', 1, 2, MAYBE_1);
828 TEST ("abc", in | out | ate, 2, 'c', 2, 1, MAYBE_1);
829 TEST ("abc", in | out | ate, 3, EOF, 3, 0, MAYBE_1);
830
832 // exercise UserTraits with an unusual eof
833
834 if (0 == pfid->tname_)
835 return;
836
837 TEST ("a$c", in, 0, 'a', 0, 3, -1);
838 TEST ("a$c", in, 1, EOF, 1, 2, -1);
839}
840
841
843// exercises both seekoff (seeking from the beginning) and seekpos
844static void
845test_seek (VFun *pfid)
846{
847 RW_ASSERT ( VFun::seekoff == pfid->vfun_
848 || VFun::seekpos == pfid->vfun_);
849
850#undef TEST
851#define TEST(str, mode, gbump, off, which, res, pback, read, write) \
852 test_virtual (pfid, __LINE__, str, sizeof str - 1, mode, gbump, \
853 off, std::ios::beg, which, res, pback, read, write)
854
856 //
857 // 27.7.1.3, p10 + LWG issue 432
858 //
859 // pos_type seekoff (off_type off, ios_base::seekdir way,
860 // ios_base::openmode which = in | out);
861 //
862 // -10- Effects: Alters the stream position within one of the controlled
863 // sequences, if possible, as indicated in Table 90:
864 //
865 // Table 90 -- seekoff positioning
866 // -------------------------------
867 // Conditions Result
868 // --------------- ---------------
869 // (which & in) positions the input sequence
870 // (which & out) positions the output sequence
871 // (which & (in | out)) == (in & out) && (way == beg || way == end)
872 // positions both sequences
873 // otherwise fails
874 // -------------------------------
875 //
876 // -11- For a sequence to be positioned, if its next pointer (either
877 // gptr() or pptr()) is a null pointer, the positioning operation
878 // fails. Otherwise, the function determines newoff as indicated
879 // in Table 91:
880 //
881 // Table 91 -- newoff values
882 // ----------------------------
883 //
884 // Condition Newoff value
885 // --------------- ------------
886 // (way == beg) 0
887 // (way == cur) xnext - xbeg
888 // (way == end) xend - xbeg
889 // ----------------------------
890 //
891 // -12- If (newoff + off) < 0, or if (newoff + off) refers to an
892 // uninitialized character (as defined in 27.7.1.2
893 // [lib.stringbuf.members] paragraph 1), the positioning operation
894 // fails. Otherwise, the function assigns (xbeg + newoff + off) to
895 // the next pointer xnext.
896
897 // -13- Returns: pos_type(newoff), constructed from the resultant offset
898 // newoff (of type off_type), that stores the resultant stream
899 // position, if possible. If the positioning operation fails, or
900 // if the constructed object cannot represent the resultant stream
901 // position, the return value is pos_type(off_type(-1)).
902 //
904
905 // +-- initial sequence
906 // | +-- open mode (in, out, ate)
907 // | | +-- gbump
908 // | | | +-- offset
909 // | | | | +-- which (in, out)
910 // | | | | | +--- resulting position
911 // | | | | | | +-- putback positions
912 // | | | | | | | +-- read positions
913 // | | | | | | | | +-- write pos.
914 // | | | | | | | | |
915 // | | | | | | | | |
916 // | | | | | | | | |
917 // V V V V V V V V V
918 TEST (0, 0, 0, 0, 0, NPOS, 0, 0, -1);
919 TEST (0, in, 0, 0, 0, NPOS, 0, 0, -1);
920 TEST (0, out, 0, 0, 0, NPOS, 0, 0, -1);
921 TEST (0, ate, 0, 0, 0, NPOS, 0, 0, -1);
922 TEST (0, in | out, 0, 0, 0, NPOS, 0, 0, -1);
923 TEST (0, in | out | ate, 0, 0, 0, NPOS, 0, 0, -1);
924
925 TEST (0, 0, 0, 0, 0, NPOS, 0, 0, -1);
926
927 TEST ("abc", 0, 0, 0, 0, NPOS, 0, 0, -1);
928 TEST ("abc", 0, 0, 1, 0, NPOS, 0, 0, -1);
929 TEST ("abc", 0, 0, -1, 0, NPOS, 0, 0, -1);
930
931 // seek within the input sequence from the beginning
932 TEST ("abc", in, 0, 0, in, 0, 0, 3, -1);
933 TEST ("abc", in, 0, 1, in, 1, 1, 2, -1);
934 TEST ("abc", in, 0, 2, in, 2, 2, 1, -1);
935 TEST ("abc", in, 0, 3, in, 3, 3, 0, -1);
936 TEST ("abc", in, 0, 4, in, NPOS, 0, 3, -1);
937
938 // advance gptr by one and seek within the input sequence
939 TEST ("abc", in, 1, 0, in, 0, 0, 3, -1);
940 TEST ("abc", in, 1, 1, in, 1, 1, 2, -1);
941 TEST ("abc", in, 1, 2, in, 2, 2, 1, -1);
942 TEST ("abc", in, 1, 3, in, 3, 3, 0, -1);
943 TEST ("abc", in, 1, 4, in, NPOS, 1, 2, -1);
944
945 // advance gptr by two and seek within the input sequence
946 TEST ("abc", in, 2, 0, in, 0, 0, 3, -1);
947 TEST ("abc", in, 2, 1, in, 1, 1, 2, -1);
948 TEST ("abc", in, 2, 2, in, 2, 2, 1, -1);
949 TEST ("abc", in, 2, 3, in, 3, 3, 0, -1);
950 TEST ("abc", in, 2, 4, in, NPOS, 2, 1, -1);
951
952 // exercise seeking within the output sequence
953 TEST ("abc", out, 0, 0, out, 0, 0, 0, MAYBE_1);
954 TEST ("abc", out, 0, 1, out, 1, 0, 0, MAYBE_1);
955 TEST ("abc", out, 0, -1, out, NPOS, 0, 0, MAYBE_1);
956 TEST ("abc", out, 0, 2, out, 2, 0, 0, MAYBE_1);
957 TEST ("abc", out, 0, 3, out, 3, 0, 0, MAYBE_1);
958 TEST ("abc", out, 0, 4, out, NPOS, 0, 0, MAYBE_1);
959
960 // seeking withing both input and output
961 TEST ("abc", in | out, 0, 0, in | out, 0, 0, 3, MAYBE_1);
962 TEST ("abc", in | out, 0, 1, in | out, 1, 1, 2, MAYBE_1);
963 TEST ("abc", in | out, 0, -1, in | out, NPOS, 0, 3, MAYBE_1);
964 TEST ("abc", in | out, 0, 2, in | out, 2, 2, 1, MAYBE_1);
965 TEST ("abc", in | out, 0, 3, in | out, 3, 3, 0, MAYBE_1);
966 TEST ("abc", in | out, 0, 4, in | out, NPOS, 0, 3, MAYBE_1);
967}
968
969
971static void
972test_seekoff (VFun *pfid)
973{
974 rw_info (0, 0, 0, "basic_stringbuf<%s%{?}, %s%{;}>::seekoff(off_type, "
975 "ios_base::seekdir, ios_base::openmode)",
976 pfid->cname_, 0 != pfid->tname_, pfid->tname_);
977
978 pfid->vfun_ = VFun::seekoff;
979
980 test_seek (pfid);
981
982#undef TEST
983#define TEST(str, mode, gbump, off, way, which, res, pback, read, write) \
984 test_virtual (pfid, __LINE__, str, sizeof str - 1, mode, gbump, \
985 off, way, which, res, pback, read, write)
986
987 // exercise seeking from the current position and from end
988
989 // +-- initial sequence
990 // | +-- open mode (in, out, ate)
991 // | | +-- gbump
992 // | | | +-- offset
993 // | | | | +-- way (cur or end)
994 // | | | | | +-- which (in, out)
995 // | | | | | | +--- resulting position
996 // | | | | | | | +-- putback positions
997 // | | | | | | | | +-- read positions
998 // | | | | | | | | | +-- write pos.
999 // | | | | | | | | | |
1000 // | | | | | | | | | |
1001 // | | | | | | | | | |
1002 // V V V V V V V V V V
1003 TEST (0, 0, 0, 0, cur, 0, NPOS, 0, 0, -1);
1004 TEST (0, in, 0, 0, cur, 0, NPOS, 0, 0, -1);
1005 TEST (0, out, 0, 0, cur, 0, NPOS, 0, 0, -1);
1006 TEST (0, ate, 0, 0, cur, 0, NPOS, 0, 0, -1);
1007 TEST (0, in | out, 0, 0, cur, 0, NPOS, 0, 0, -1);
1008 TEST (0, in | out | ate, 0, 0, cur, 0, NPOS, 0, 0, -1);
1009
1010 TEST (0, 0, 0, 0, end, 0, NPOS, 0, 0, -1);
1011 TEST (0, in, 0, 0, end, 0, NPOS, 0, 0, -1);
1012 TEST (0, out, 0, 0, end, 0, NPOS, 0, 0, -1);
1013 TEST (0, ate, 0, 0, end, 0, NPOS, 0, 0, -1);
1014 TEST (0, in | out, 0, 0, end, 0, NPOS, 0, 0, -1);
1015 TEST (0, in | out | ate, 0, 0, end, 0, NPOS, 0, 0, -1);
1016
1017 // exercise seeking within the output sequence
1018 // (if (mode & in) == 0 then (pptr() == pbase()) is a postcondition
1019 // of the constructor -- see also lwg issue 562)
1020 TEST ("abc", out, 0, 0, cur, out, 0, 0, 0, MAYBE_1);
1021 TEST ("abc", out, 0, 1, cur, out, 1, 0, 0, MAYBE_1);
1022 TEST ("abc", out, 0, -1, cur, out, NPOS, 0, 0, MAYBE_1);
1023 TEST ("abc", out, 0, 2, cur, out, 2, 0, 0, MAYBE_1);
1024 TEST ("abc", out, 0, 3, cur, out, 3, 0, 0, MAYBE_1);
1025 TEST ("abc", out, 0, 4, cur, out, NPOS, 0, 0, MAYBE_1);
1026
1027 // seek within the input sequence from the current position
1028 TEST ("abc", in, 0, 0, cur, in, 0, 0, 3, -1);
1029 TEST ("abc", in, 0, 1, cur, in, 1, 1, 2, -1);
1030 TEST ("abc", in, 0, 2, cur, in, 2, 2, 1, -1);
1031 TEST ("abc", in, 0, 3, cur, in, 3, 3, 0, -1);
1032 TEST ("abc", in, 0, 4, cur, in, NPOS, 0, 3, -1);
1033
1034 // seek within the input sequence from the end
1035 TEST ("abc", in, 0, 0, end, in, 3, 3, 0, -1);
1036 TEST ("abc", in, 0, -1, end, in, 2, 2, 1, -1);
1037 TEST ("abc", in, 0, -2, end, in, 1, 1, 2, -1);
1038 TEST ("abc", in, 0, -3, end, in, 0, 0, 3, -1);
1039 TEST ("abc", in, 0, -4, end, in, NPOS, 0, 3, -1);
1040
1041 // exercise positioning from the end: this behavior is not
1042 // correctly specified even in LWG issue 432 (see the post
1043 // in c++std-lib-16390)
1044
1045 // the implemented behavior considers end to be the "high
1046 // mark" mentioned in DR 432 rather than epptr()
1047
1048 // see LWG issue 563:
1049 // http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#563
1050 TEST ("abc", out, 0, 0, end, out, 3, 0, 0, MAYBE_1);
1051 TEST ("abc", out, 0, 1, end, out, NPOS, 0, 0, MAYBE_1);
1052 TEST ("abc", out, 0, -1, end, out, 2, 0, 0, MAYBE_1);
1053 TEST ("abc", out, 0, -2, end, out, 1, 0, 0, MAYBE_1);
1054 TEST ("abc", out, 0, -3, end, out, 0, 0, 0, MAYBE_1);
1055 TEST ("abc", out, 0, -4, end, out, NPOS, 0, 0, MAYBE_1);
1056
1057 TEST ("abc", out | ate, 0, 0, cur, out, 3, 0, 0, MAYBE_1);
1058 TEST ("abc", out | ate, 0, 1, cur, out, NPOS, 0, 0, MAYBE_1);
1059 TEST ("abc", out | ate, 0, -1, cur, out, 2, 0, 0, MAYBE_1);
1060 TEST ("abc", out | ate, 0, -2, cur, out, 1, 0, 0, MAYBE_1);
1061 TEST ("abc", out | ate, 0, -3, cur, out, 0, 0, 0, MAYBE_1);
1062 TEST ("abc", out | ate, 0, -4, cur, out, NPOS, 0, 0, MAYBE_1);
1063
1064 // seeking within both input and output from the end
1065 TEST ("abc", in | out, 0, 0, end, in | out, 3, 3, 0, MAYBE_1);
1066 TEST ("abc", in | out, 0, 1, end, in | out, NPOS, 0, 3, MAYBE_1);
1067 TEST ("abc", in | out, 0, -1, end, in | out, 2, 2, 1, MAYBE_1);
1068 TEST ("abc", in | out, 0, -2, end, in | out, 1, 1, 2, MAYBE_1);
1069 TEST ("abc", in | out, 0, -3, end, in | out, 0, 0, 3, MAYBE_1);
1070 TEST ("abc", in | out, 0, -4, end, in | out, NPOS, 0, 3, MAYBE_1);
1071
1072 TEST ("abc", in, 0, 0, cur, in | out, NPOS, 0, 3, MAYBE_1);
1073 TEST ("abc", out, 0, 0, cur, in | out, NPOS, 0, 0, MAYBE_1);
1074 TEST ("abc", in | out, 0, 0, cur, in | out, NPOS, 0, 3, MAYBE_1);
1075 TEST ("abc", in | out | ate, 0, 0, cur, in | out, NPOS, 0, 3, MAYBE_1);
1076
1077 TEST ("abc", in | out | ate, 1, -1, end, in, 2, 2, 1, MAYBE_1);
1078 TEST ("abc", in | out | ate, 1, -1, end, out, 2, 1, 2, MAYBE_1);
1079
1080 TEST ("abc", in | out | ate, 1, -1, end, in | out, 2, 2, 1, MAYBE_1);
1081 TEST ("abc", in | out | ate, 2, -1, end, in | out, 2, 2, 1, MAYBE_1);
1082 TEST ("abc", in | out | ate, 3, -1, end, in | out, 2, 2, 1, MAYBE_1);
1083}
1084
1085
1087static void
1088test_seekpos (VFun *pfid)
1089{
1090 rw_info (0, 0, 0, "basic_stringbuf<%s%{?}, %s%{;}>::seekpos(pos_type, "
1091 "ios_base::openmode)",
1092 pfid->cname_, 0 != pfid->tname_, pfid->tname_);
1093
1094 pfid->vfun_ = VFun::seekpos;
1095
1096 test_seek (pfid);
1097}
1098
1099
1101static int rw_opt_no_xsputn; // for --no-xsputn
1102static int rw_opt_no_pbackfail; // for --no-pbackfail
1103static int rw_opt_no_overflow; // for --no-overflow
1104static int rw_opt_no_underflow; // for --no-underflow
1105static int rw_opt_no_seekoff; // for --no-seekoff
1106static int rw_opt_no_seekpos; // for --no-seekpos
1107static int rw_opt_no_seek; // for --no-seek
1108static int rw_opt_no_char_traits; // for --no-char_traits
1109static int rw_opt_no_user_traits; // for --no-user_traits
1110
1111static void
1112run_test (VFun *pfid)
1113{
1114#undef TEST
1115#define TEST(function) \
1116 if (rw_opt_no_ ## function) \
1117 rw_note (1 < rw_opt_no_ ## function++, 0, 0, \
1118 "%s test disabled", #function); \
1119 else \
1120 test_ ## function (pfid)
1121
1122 if (pfid->tname_ && rw_opt_no_user_traits) {
1123 rw_note (1 < rw_opt_no_user_traits++, 0, 0,
1124 "user defined traits test disabled");
1125 }
1126 else if (!pfid->tname_ && rw_opt_no_char_traits) {
1127 rw_note (1 < rw_opt_no_char_traits++, 0, 0,
1128 "char_traits test disabled");
1129 }
1130 else {
1131 TEST (xsputn);
1132 TEST (pbackfail);
1133 TEST (overflow);
1134 TEST (underflow);
1135 TEST (seekoff);
1136 TEST (seekpos);
1137 }
1138}
1139
1140
1142static int
1143run_test (int, char*[])
1144{
1145 if ('\0' == long_string [0]) {
1146 // initialize long_string
1147 for (std::size_t i = 0; i != sizeof long_string - 1; ++i)
1148 long_string [i] = 'x';
1149 }
1150
1151 if (rw_opt_no_seek) {
1152 rw_opt_no_seekoff = 1;
1153 rw_opt_no_seekpos = 1;
1154 }
1155
1156 if (rw_enabled ("char")) {
1157
1158 VFun fid (VFun::Char, "char", VFun::DefaultTraits, 0);
1159
1160 traits_eof = -1;
1161
1162 run_test (&fid);
1163
1164 fid.tid_ = VFun::UserTraits;
1165 fid.tname_ = "UserTraits";
1166 traits_eof = '$';
1167
1168 run_test (&fid);
1169 }
1170 else
1171 rw_note (0, 0, 0, "char tests disabled");
1172
1173 if (rw_enabled ("wchar_t")) {
1174 VFun fid (VFun::WChar, "wchar_t", VFun::DefaultTraits, 0);
1175
1176 traits_eof = -1;
1177
1178 run_test (&fid);
1179
1180 fid.tid_ = VFun::UserTraits;
1181 fid.tname_ = "UserTraits";
1182 traits_eof = '$';
1183
1184 run_test (&fid);
1185 }
1186 else
1187 rw_note (0, 0, 0, "char tests disabled");
1188
1189 return 0;
1190}
1191
1192
1194int main (int argc, char *argv[])
1195{
1196 return rw_test (argc, argv, __FILE__,
1197 "lib.stringbuf.virtuals",
1198 0, // no comment
1199 run_test,
1200 "|-no-xsputn# "
1201 "|-no-pbackfail# "
1202 "|-no-overflow# "
1203 "|-no-underflow# "
1204 "|-no-seekoff# "
1205 "|-no-seekpos# "
1206 "|-no-seek# "
1207 "|-no-char_traits# "
1208 "|-no-user_traits# "
1209 "|-max_buf_size#0-*",
1210 &rw_opt_no_xsputn,
1211 &rw_opt_no_pbackfail,
1212 &rw_opt_no_overflow,
1213 &rw_opt_no_underflow,
1214 &rw_opt_no_seekoff,
1215 &rw_opt_no_seekpos,
1216 &rw_opt_no_seek,
1217 &rw_opt_no_char_traits,
1218 &rw_opt_no_user_traits,
1219 int (sizeof long_string) - 1,
1220 &rw_opt_max_size);
1221}
#define i
Definition 17.names.cpp:126
#define line
Definition 17.names.cpp:490
#define which
Definition 17.names.cpp:575
#define way
Definition 17.names.cpp:574
#define Allocator
Definition 17.names.cpp:440
#define buf
Definition 17.names.cpp:452
#define off
Definition 17.names.cpp:507
#define c
Definition 17.names.cpp:111
#define charT
Definition 17.names.cpp:456
#define len
Definition 17.names.cpp:488
#define n
Definition 17.names.cpp:130
#define mode
Definition 17.names.cpp:497
#define pos
Definition 17.names.cpp:518
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
const char *const fnames[]
Definition 25.remove.cpp:77
std::char_traits< S > Traits
const int end
#define NOT_EOF
#define CAP
#define AT_LEAST_1
#define NPOS
#define EOF
#define MAYBE_1
const int out
void test_virtual(charT, Traits, const VFun *pfid, int line, const char *str, std::size_t, int mode, int gbump, int arg0, int arg1, int arg2, int ret_expect, int pback_expect, int read_expect, int write_expect)
const int ate
#define TEST(charT, Traits)
#define CALLFMT
const int cur
#define CALLARGS
#define IGN
const int in
#define main
const char * str
Definition exec.cpp:170
_TEST_EXPORT char * rw_expand(char *, const char *, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX, _RWSTD_SIZE_T *=0)
_TEST_EXPORT _RWSTD_SIZE_T rw_match(const char *, const char *, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX)
_TEST_EXPORT int rw_enabled(const char *name)
_TEST_EXPORT int rw_test(int argc, char *argv[], const char *filename, const char *clause, const char *comment, int(*testfun)(int, char **), const char *optspec,...)
_TEST_EXPORT int rw_info(int, const char *, int, const char *,...)
Definition driver.cpp:1681
_TEST_EXPORT int rw_note(int, const char *, int, const char *,...)
Definition driver.cpp:1664
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630
#define RW_ASSERT(expr)
static int_type eof()
static int_type not_eof(int_type c)
Base::int_type int_type
std::char_traits< charT > Base
pos_type Seekpos(pos_type pos, std::ios_base::openmode which)
int_type Overflow()
void Gbump(int n)
char_type * Pptr() const
pos_type Seekpos(pos_type pos)
Base::int_type int_type
char_type * Egptr() const
pos_type Seekoff(off_type off, std::ios_base::seekdir way, std::ios_base::openmode which)
int_type Overflow(int_type c)
char_type * Eback() const
int_type Pbackfail()
char_type * Pbase() const
char_type * Epptr() const
pos_type Seekoff(off_type off, std::ios_base::seekdir way)
Base::off_type off_type
char_type * Gptr() const
int_type Pbackfail(int_type c)
int_type Underflow()
Base::char_type char_type
static int capacity(int n)
std::basic_stringbuf< charT > Base
Base::pos_type pos_type
VFun(charT cid, const char *cname, Traits tid, const char *tname)
const char * tname_
VirtualTag vfun_
const char * strarg_
const char * fname_
const char * cname_
const char * sequence_