blob: 552cb0e7242ca5861e5436fd1beb1e815ab6d9d9 [file] [log] [blame]
/***************************************************************************
*
* 27.stringbuf.virtuals.cpp - test exercising lib.stringbuf.virtuals
*
* $Id$
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
**************************************************************************/
#include <sstream> // for stringbuf
#include <cstring> // for size_t, strchr()
#include <rw_cmdopt.h> // for rw_enabled()
#include <rw_driver.h> // for rw_assert(), ...
#include <rw_char.h> // for rw_expand(), rw_match()
/**************************************************************************/
#undef EOF
#define EOF (_RWSTD_INT_MIN + 2)
#undef NOT_EOF
#define NOT_EOF (_RWSTD_INT_MIN + 1)
#undef IGN
#define IGN _RWSTD_INT_MIN
#undef NPOS
#define NPOS -1 // invalid position (post_type(off_type(-1))
#define MAYBE_1 0 // 0 or more write positions available
#define AT_LEAST_1 1 // at least one write position available
/**************************************************************************/
template <class charT, class Traits>
struct PubBuf: std::basic_stringbuf<charT, Traits>
{
typedef std::basic_stringbuf<charT> Base;
typedef typename Base::char_type char_type;
typedef typename Base::int_type int_type;
typedef typename Base::off_type off_type;
typedef typename Base::pos_type pos_type;
char_type* Eback () const { return this->eback (); }
char_type* Gptr () const { return this->gptr (); }
char_type* Egptr () const { return this->egptr (); }
void Gbump (int n) { this->gbump (n); }
char_type* Pbase () const { return this->pbase (); }
char_type* Pptr () const { return this->pptr (); }
char_type* Epptr () const { return this->epptr (); }
int_type Pbackfail () { return this->pbackfail (); }
int_type Pbackfail (int_type c) { return this->pbackfail (c); }
int_type Overflow () { return this->overflow (); }
int_type Overflow (int_type c) { return this->overflow (c); }
int_type Underflow () { return this->underflow (); }
pos_type Seekoff (off_type off, std::ios_base::seekdir way) {
return this->seekoff (off, way);
}
pos_type Seekoff (off_type off, std::ios_base::seekdir way,
std::ios_base::openmode which) {
return this->seekoff (off, way, which);
}
pos_type Seekpos (pos_type pos) {
return this->seekpos (pos);
}
pos_type Seekpos (pos_type pos, std::ios_base::openmode which) {
return this->seekpos (pos, which);
}
static int capacity (int n) {
Base buf (std::ios::out);
while (n--)
buf.sputc ('c');
return int (((PubBuf&)buf).Epptr () - ((PubBuf&)buf).Pbase ());
}
};
int traits_eof = -1;
template <class charT>
struct CharTraits: std::char_traits<charT>
{
typedef std::char_traits<charT> Base;
typedef typename Base::int_type int_type;
// override eof() to detect bad assumptions
static int_type eof () { return traits_eof; }
static int_type not_eof (int_type c) {
return c == eof () ? int_type (!c) : c;
}
};
/**************************************************************************/
struct VFun
{
enum charT { Char, WChar };
enum Traits { DefaultTraits, UserTraits };
enum VirtualTag {
// which virtual function to exercise
xsputn, pbackfail, overflow, underflow, seekoff, seekpos
};
VFun (charT cid, const char *cname,
Traits tid, const char *tname)
: cid_ (cid), tid_ (tid), vfun_ (),
cname_ (cname), tname_ (tname), fname_ (0),
strarg_ (0), sequence_ (0) { /* empty */ }
charT cid_;
Traits tid_;
VirtualTag vfun_;
const char *cname_; // character type name
const char *tname_; // traits name
const char *fname_; // function name
const char *strarg_; // string argument
const char *sequence_; // final sequence
};
static int stringbuf_capacity;
static char long_string [4096];
/**************************************************************************/
template <class charT, class Traits>
void test_virtual (charT, Traits, const VFun *pfid,
int line, // line number
const char *str, // ctor string argument
std::size_t, // length of string
int mode, // ctor mode argument
int gbump, // initial gptr offset
int arg0, // first argument
int arg1, // second argument
int arg2, // third argument
int ret_expect, // expected return value
int pback_expect, // ... size of putback area
int read_expect, // ... size of read area
int write_expect) // ... size of write area
{
typedef std::allocator<charT> Allocator;
typedef std::basic_stringbuf<charT, Traits, Allocator> Stringbuf;
typedef typename Stringbuf::int_type int_type;
typedef typename Stringbuf::off_type off_type;
typedef typename Stringbuf::pos_type pos_type;
if (!rw_enabled (line)) {
rw_note (0, 0, 0, "test on line %d disabled", line);
return;
}
if (EOF == arg0)
arg0 = Traits::eof ();
if (EOF == ret_expect)
ret_expect = Traits::eof ();
// widen the source sequence into the (possibly wide) character buffer
static charT wstr [4096];
static charT warg [4096];
std::size_t wstr_len = sizeof wstr / sizeof *wstr;
std::size_t warg_len = sizeof warg / sizeof *warg;
wstr [0] = charT ();
rw_expand (wstr, str, _RWSTD_SIZE_MAX, &wstr_len);
const std::ios_base::openmode openmode = std::ios_base::openmode (mode);
// construct three stringbuf objects but use only the one that
// matches the provided arguments
Stringbuf sb_0;
Stringbuf sb_m (openmode);
Stringbuf sb_s (wstr);
Stringbuf sb_s_m (wstr, openmode);
PubBuf<charT, Traits>* const pbuf = (PubBuf<charT, Traits>*)
(str ? -1 < mode ? &sb_s_m : &sb_s : -1 < mode ? &sb_m : &sb_0);
if (stringbuf_capacity < 0)
stringbuf_capacity =
PubBuf<charT, Traits>::capacity (-stringbuf_capacity);
if (gbump && IGN != gbump) {
// make sure gbump is valid
RW_ASSERT (gbump <= pbuf->Egptr () - pbuf->Eback ());
// advance gptr() as requested
pbuf->Gbump (gbump);
}
// create the argument to overflow
const int_type arg_int = int_type (arg0);
const off_type arg_off = off_type (arg0);
const pos_type arg_pos = arg_off;
const std::ios_base::seekdir arg_way = std::ios_base::seekdir (arg1);
const std::ios_base::openmode arg_which = std::ios_base::openmode (arg2);
int ret = EOF;
// invoke the virtual function with the expected argument (if any)
switch (pfid->vfun_) {
case VFun::xsputn: {
if (pfid->strarg_) {
rw_expand (warg, pfid->strarg_, _RWSTD_SIZE_MAX, &warg_len);
if (std::strchr (pfid->strarg_, '@'))
arg0 = int (warg_len);
RW_ASSERT (std::size_t (arg0) < sizeof wstr / sizeof *wstr);
ret = int (pbuf->sputn (warg, std::streamsize (arg0)));
}
else {
// invoke sputn() with pbase as an argument
ret = int (pbuf->sputn (pbuf->Pbase (), std::streamsize (arg0)));
}
break;
}
case VFun::pbackfail:
ret = IGN == arg0 ? pbuf->Pbackfail ()
: pbuf->Pbackfail (arg_int);
break;
case VFun::overflow:
ret = IGN == arg0 ? pbuf->Overflow ()
: pbuf->Overflow (arg_int);
break;
case VFun::underflow:
ret = pbuf->Underflow ();
break;
case VFun::seekoff:
ret = IGN == arg2 ? pbuf->Seekoff (arg_off, arg_way)
: pbuf->Seekoff (arg_off, arg_way, arg_which);
break;
case VFun::seekpos:
ret = IGN == arg2 ? pbuf->Seekpos (arg_pos)
: pbuf->Seekpos (arg_pos, arg_which);
break;
}
// compute the number of putback positions available
// see 27.5.1, p3, bullet 3
const int pback_pos = int (pbuf->Gptr () - pbuf->Eback ());
// compute the number of read positions available
// see 27.5.1, p3, bullet 4
const int read_pos = int (pbuf->Egptr () - pbuf->Gptr ());
// compute the number of write positions available
// see 27.5.1, p3, bullet 2
const int write_pos = int (pbuf->Epptr () - pbuf->Pptr ());
// set up a format string with the name of the class and member
// function being called and describing the function arguments
// basic_stringbuf<char> is formatted as stringbuf
// basic_stringbuf<wchar_t> is formatted as wstringbuf
// all other specializations are fully spelled out
#define CALLFMT \
"line %d. " \
"%{?}basic_%{:}%{?}w%{;}%{;}stringbuf%{?}<%s%{?}, %s%{;}>%{;}" \
"(%{?}%{*Ac}%{?}, %{Io}%{;}%{:}%{?}%{Io}%{;}%{;})" \
".%s (%{?}%{?}%{*Ac}%{:}pptr()%{;}, %d" /* xsputn */ \
"%{:}%{?}" /* pbackfail, over/underflow argument */ \
"%{?}%{#lc}%{;}" \
"%{:}" /* seekoff and seekpos */ \
"%d%{?}, %{Iw}%{?}, %{Io}%{;}" \
"%{:}%{?}, %{Io}%{;}%{;}" \
"%{;}%{;})"
// is the tested virtual function seekoff or seekpos?
const bool is_seek = VFun::seekoff <= pfid->vfun_;
// arguments corresponding to CALLFMT
#define CALLARGS \
__LINE__, \
0 != pfid->tname_, 'w' == *pfid->cname_, 0 != pfid->tname_, \
pfid->cname_, 0 != pfid->tname_, pfid->tname_, \
0 != str, int (sizeof *wstr), wstr, -1 < mode, mode, -1 < mode, mode, \
pfid->fname_, pfid->vfun_ == VFun::xsputn, 0 != pfid->strarg_, \
int (sizeof *warg), warg, arg0, \
!is_seek, \
IGN != arg0, arg_int, \
arg0, VFun::seekoff == pfid->vfun_, arg1, IGN != arg2, arg2, \
IGN != arg1, arg1
const int_type not_eof = Traits::not_eof (arg_int);
int success = ret == (NOT_EOF == ret_expect ? int (not_eof) : ret_expect);
// verify the expected return value
if (pfid->vfun_ == VFun::xsputn || is_seek) {
rw_assert (success, 0, line,
CALLFMT " == %d, got %d",
CALLARGS, ret_expect, ret);
}
else {
rw_assert (success, 0, line,
CALLFMT " == %{?}not EOF%{:}%{#lc}%{;}, got %{#lc}",
CALLARGS, NOT_EOF == ret_expect, ret_expect, ret);
}
// verify the expected size of the putback area
if (IGN != pback_expect)
rw_assert (pback_pos == pback_expect, 0, line,
CALLFMT ": putback positions (gptr - eback) == %d, got %d"
"%{?}: gptr = NULL%{;}",
CALLARGS, pback_expect, pback_pos,
0 == pbuf->Gptr ());
// verify the expected size of the read area
if (IGN != read_expect)
rw_assert (read_pos == read_expect, 0, line,
CALLFMT ": read positions (egptr - gptr) == %d, got %d: "
"gptr = %{?}NULL%{:}eback + %td%{;}",
CALLARGS, read_expect, read_pos,
0 == pbuf->Gptr (), pbuf->Gptr () - pbuf->Eback ());
// verify the expected size of the write area
if (IGN != write_expect) {
// at least as many write positions as expected
success = -1 < write_expect ?
write_expect <= write_pos : 0 == write_pos;
rw_assert (success, 0, line,
CALLFMT ": write positions (epptr - pptr) "
"%{?}==%{:}>=%{;} %d, got %d: "
"pptr = %{?}NULL%{:}pbase + %td%{;}",
CALLARGS, 1 < write_expect, write_expect, write_pos,
0 == pbuf->Pptr (), pbuf->Pptr () - pbuf->Pbase ());
}
if (pfid->sequence_) {
// verify that the put area matches the expected sequence
const std::size_t len = pbuf->Pptr () - pbuf->Pbase ();
const std::size_t xmatch =
rw_match (pfid->sequence_, pbuf->Pbase (), len);
rw_assert (xmatch == len, 0, line,
CALLFMT ": put area mismatch (pbase + %zu)",
CALLARGS, xmatch);
}
}
/**************************************************************************/
// dispatches to the appropriate specialization of the function template
void test_virtual (VFun *pfid,
int line,
const char *str,
std::size_t str_len,
int mode,
int gbump,
int arg0,
int arg1,
int arg2,
int ret_expect,
int pback_expect,
int read_expect,
int write_expect)
{
#undef TEST
#define TEST(charT, Traits) \
test_virtual (charT (), Traits (), pfid, line, \
str, str_len, mode, gbump, \
arg0, arg1, arg2, ret_expect, \
pback_expect, read_expect, write_expect)
static const char* const fnames[] = {
"xsputn", "pbackfail", "overflow", "underflow", "seekoff", "seekpos"
};
if (!rw_enabled (line)) {
rw_note (0, 0, __LINE__, "test on line %d disabled", line);
return;
}
pfid->fname_ = fnames [pfid->vfun_];
if (VFun:: DefaultTraits == pfid->tid_) {
if (VFun::Char == pfid->cid_)
TEST (char, std::char_traits<char>);
#ifndef _RWSTD_NO_WCHAR_T
else
TEST (wchar_t, std::char_traits<wchar_t>);
#endif // _RWSTD_NO_WCHAR_T
}
else {
if (VFun::Char == pfid->cid_)
TEST (char, CharTraits<char>);
#ifndef _RWSTD_NO_WCHAR_T
else
TEST (wchar_t, CharTraits<wchar_t>);
#endif // _RWSTD_NO_WCHAR_T
}
pfid->strarg_ = 0;
pfid->sequence_ = 0;
}
/**************************************************************************/
// convenience constants
const int in = std::ios::in;
const int out = std::ios::out;
const int ate = std::ios::ate;
const int cur = std::ios::cur;
const int end = std::ios::end;
static int rw_opt_max_size = 1024;
/**************************************************************************/
static void
test_xsputn (VFun *pfid)
{
rw_info (0, 0, 0, "basic_stringbuf<%s%{?}, %s%{;}>::xsputn"
"(const char_type*, streamsize)",
pfid->cname_, 0 != pfid->tname_, pfid->tname_);
pfid->vfun_ = VFun::xsputn;
#undef TEST
#define TEST(str, mode, gbump, sarg, result, pback, read, write) \
pfid->strarg_ = sarg; \
test_virtual (pfid, __LINE__, str, sizeof str - 1, mode, \
gbump, int (sizeof sarg - 1), IGN, IGN, result, \
pback, read, write)
// +-------------------------------------------- initial sequence
// | +------------------------------------- open mode
// | | +--------------------- gbump (gptr offset)
// | | | +----------------- xsputn argument
// | | | | +----------- expected return value
// | | | | | +-------- putback positions
// | | | | | | +----- read positions
// | | | | | | | +-- write positions
// | | | | | | | |
// V V V V V V V V
TEST (0, 0, 0, "", 0, 0, 0, -1);
TEST (0, 0, 0, "a", 0, 0, 0, -1);
TEST (0, in, 0, "a", 0, 0, 0, -1);
TEST (0, out, 0, "a", 1, 0, 0, MAYBE_1);
TEST (0, out, 0, "ab", 2, 0, 0, MAYBE_1);
TEST (0, out, 0, "abc", 3, 0, 0, MAYBE_1);
TEST (0, in | out, 0, "abc", 3, 0, 3, MAYBE_1);
TEST (0, in | out | ate, 0, "abc", 3, 0, 3, MAYBE_1);
TEST ("abc", in | out, 0, "def", 3, 0, 6, MAYBE_1);
TEST ("abc", in | out | ate, 0, "def", 3, 0, 6, MAYBE_1);
TEST ( 0, in | out, 0, "a@1000", 1000, 0, 1000, MAYBE_1);
TEST ( 0, in | out, 0, "a@1000", 1000, 0, 1000, MAYBE_1);
TEST ( 0, in | out, 0, "a@1001", 1001, 0, 1001, MAYBE_1);
TEST ( "a@1", in | out, 0, "a@1002", 1002, 0, 1003, MAYBE_1);
TEST ( "a@2", in | out, 0, "a@1003", 1003, 0, 1005, MAYBE_1);
TEST ( "a@3", in | out, 0, "a@1004", 1004, 0, 1007, MAYBE_1);
TEST ( 0, in | out | ate, 0, "a@1000", 1000, 0, 1000, MAYBE_1);
TEST ( 0, in | out | ate, 0, "a@1001", 1001, 0, 1001, MAYBE_1);
TEST ( "a@1", in | out | ate, 0, "a@1002", 1002, 0, 1003, MAYBE_1);
TEST ( "a@2", in | out | ate, 0, "a@1003", 1003, 0, 1005, MAYBE_1);
TEST ( "a@3", in | out | ate, 0, "a@1004", 1004, 0, 1007, MAYBE_1);
TEST ( "a@127", in | out | ate, 0, "a@1005", 1005, 0, 1132, MAYBE_1);
TEST ("a@1000", in | out | ate, 0, "a@1006", 1006, 0, 2006, MAYBE_1);
TEST ("a@2000", in | out | ate, 0, "a@1007", 1007, 0, 3007, MAYBE_1);
TEST ("a@2001", in | out | ate, 0, "a@1008", 1008, 0, 3009, MAYBE_1);
//////////////////////////////////////////////////////////////////
// exercise calling sputn() with pptr() as the first argument
#undef TEST
#define TEST(str, mode, len, result, seq, read) \
pfid->strarg_ = 0; pfid->sequence_ = seq; \
test_virtual (pfid, __LINE__, str, sizeof str - 1, mode, \
0, len, IGN, IGN, result, \
0, read, MAYBE_1)
// +---------------------------------------------- initial sequence
// | +------------------------------------ open mode
// | | +-------------------- xsputn 2nd argument
// | | | +-------------- return value
// | | | | +-------- sequence at pbase()
// | | | | | +-- read positions
// | | | | | |
// | | | | | +---------+
// | | | | | |
// V V V V V V
TEST ( "a@500b", in | out | ate, 11, 11, "a@500ba@11", 512);
TEST ( "a@500b", in | out | ate, 12, 12, "a@500ba@12", 513);
TEST ( "a@500b", in | out | ate, 13, 13, "a@500ba@13", 514);
TEST ( "a@500b", in | out | ate, 500, 500, "a@500ba@500", 1001);
TEST ( "a@500b", in | out | ate, 501, 501, "a@500ba@500b", 1002);
TEST ("a@1022b", in | out | ate, 1, 1, "a@1022ba", 1024);
TEST ("a@1023b", in | out | ate, 1, 1, "a@1023ba", 1025);
//////////////////////////////////////////////////////////////////
// exercise multiples of stringbuf capacity
#undef TEST
#define TEST(len, mode, gbump, arg_len, result, pback, read, write) \
pfid->strarg_ = long_string + (sizeof long_string - 1 - len), \
test_virtual (pfid, __LINE__, pfid->strarg_, \
len, mode, gbump, arg_len, IGN, IGN, \
result, pback, read, write)
// for convenience
#define CAP stringbuf_capacity
// compute the minimum buffer capacity
stringbuf_capacity = -1;
TEST ( 0, in | out, 0, 0, 0, 0, 0, -1);
// +----------------------------------------------- length of sequence
// | +------------------------------------------ open mode
// | | +-------------------------- gbump (gptr offset)
// | | | +-------------------- xsputn 2nd argument
// | | | | +-------------- expected return value
// | | | | | +-------- putback positions
// | | | | | | +----- read positions
// | | | | | | | +-- write positions
// | | | | | | | |
// | | | | | | | +--------+
// | | | | | | | |
// V V V V V V V V
TEST (CAP, in | out, 0, 1, 1, 0, CAP + 1, MAYBE_1);
TEST (CAP, in | out, 0, 2, 2, 0, CAP + 2, MAYBE_1);
TEST (CAP, in | out, 0, 3, 3, 0, CAP + 3, MAYBE_1);
TEST (CAP, in | out, 0, 127, 127, 0, CAP + 127, MAYBE_1);
TEST (CAP, in | out, 0, 1023, 1023, 0, CAP + 1023, MAYBE_1);
TEST (CAP, in | out, 0, 1024, 1024, 0, CAP + 1024, MAYBE_1);
TEST (CAP, in | out, 0, CAP, CAP, 0, CAP + CAP, MAYBE_1);
TEST (CAP, in | out | ate, 0, 1, 1, 0, CAP + 1, MAYBE_1);
TEST (CAP, in | out | ate, 0, 2, 2, 0, CAP + 2, MAYBE_1);
TEST (CAP, in | out | ate, 0, 3, 3, 0, CAP + 3, MAYBE_1);
TEST (CAP, in | out | ate, 0, CAP, CAP, 0, CAP + CAP, MAYBE_1);
TEST (CAP, in | out | ate, 0, 127, 127, 0, CAP + 127, MAYBE_1);
TEST (CAP, in | out | ate, 0, 1023, 1023, 0, CAP + 1023, MAYBE_1);
TEST (CAP, in | out | ate, 0, 1024, 1024, 0, CAP + 1024, MAYBE_1);
TEST (CAP, in | out | ate, 0, 1025, 1025, 0, CAP + 1025, MAYBE_1);
for (int i = 0; i != rw_opt_max_size; ++i) {
TEST ( 0, in | out, 0, i, i, 0, i + 0, MAYBE_1);
TEST ( 1, in | out, 0, i, i, 0, i + 1, MAYBE_1);
TEST ( 32, in | out, 0, i, i, 0, i + 32, MAYBE_1);
TEST (127, in | out, 0, i, i, 0, i + 127, MAYBE_1);
TEST (CAP, in | out, 0, i, i, 0, i + CAP, MAYBE_1);
}
}
/**************************************************************************/
static void
test_pbackfail (VFun *pfid)
{
rw_info (0, 0, 0, "basic_stringbuf<%s%{?}, %s%{;}>::pbackfail(int_type)",
pfid->cname_, 0 != pfid->tname_, pfid->tname_);
pfid->vfun_ = VFun::pbackfail;
#undef TEST
#define TEST(str, mode, gbump, arg, result, pback, read, write) \
test_virtual (pfid, __LINE__, str, sizeof str - 1, mode, \
gbump, arg, IGN, IGN, result, pback, read, write)
///////////////////////////////////////////////////////////////////////
// 27.7.1.3
//
// -2- Effects: Puts back the character designated by c to the input
// sequence, if possible, in one of three ways:
// -- If traits::eq_int_type(c,traits::eof()) returns false and
// if the input sequence has a putback position available,
// and if traits::eq(to_char_type(c),gptr()[-1]) returns true,
// assigns gptr() - 1 to gptr().
// Returns: c.
// -- If traits::eq_int_type(c,traits::eof()) returns false and
// if the input sequence has a putback position available, and
// if mode & ios_base::out is nonzero, assigns c to *--gptr().
// Returns: c.
// -- If traits::eq_int_type(c,traits::eof()) returns true and if
// the input sequence has a putback position available, assigns
// gptr() - 1 to gptr().
// Returns: traits::not_eof(c).
// -3- Returns: traits::eof() to indicate failure.
// -4- Notes: If the function can succeed in more than one of these ways,
// it is unspecified which way is chosen.
// +----------------------------------------- initial sequence (if any)
// | +---------------------------------- open mode
// | | +------------------------ gbump (gptr offset)
// | | | +-------------------- pbackfail argument
// | | | | +---------------- expected return value
// | | | | | +----------- number of putback positions
// | | | | | | +-------- number of read positions
// | | | | | | | +----- number of write positions
// | | | | | | | |
// V V V V V V V V
TEST (0, 0, 0, 'c', EOF, 0, 0, -1);
TEST (0, 0, 0, EOF, EOF, 0, 0, -1);
TEST (0, in, 0, 'c', EOF, 0, 0, -1);
TEST (0, out, 0, EOF, EOF, 0, 0, -1);
TEST (0, ate, 0, EOF, EOF, 0, 0, -1);
TEST (0, in | out, 0, 'c', EOF, 0, 0, -1);
TEST (0, in | out, 0, EOF, EOF, 0, 0, -1);
TEST ("a", 0, 0, 'c', EOF, 0, 0, -1);
TEST ("a", in, 0, 'c', EOF, 0, 1, -1);
TEST ("a", in, 1, 'c', EOF, 1, 0, -1);
TEST ("a", in, 1, 'a', 'a', 0, 1, -1);
TEST ("a", out, 0, 'c', EOF, 0, 0, AT_LEAST_1);
TEST ("a", ate, 0, 'c', EOF, 0, 0, -1);
TEST ("abc", in, 1, 'c', EOF, 1, 2, -1);
TEST ("abc", in, 2, 'c', EOF, 2, 1, -1);
TEST ("abc", in, 3, 'c', 'c', 2, 1, -1);
TEST ("abc", in | out, 0, 'c', EOF, 0, 3, AT_LEAST_1);
TEST ("abc", in | out, 1, 'c', 'c', 0, 3, AT_LEAST_1);
TEST ("abc", in | out, 2, 'c', 'c', 1, 2, AT_LEAST_1);
TEST ("abc", in | out, 3, 'c', 'c', 2, 1, AT_LEAST_1);
}
/**************************************************************************/
static void
test_overflow (VFun *pfid)
{
rw_info (0, 0, 0, "basic_stringbuf<%s%{?}, %s%{;}>::overflow(int_type)",
pfid->cname_, 0 != pfid->tname_, pfid->tname_);
pfid->vfun_ = VFun::overflow;
#undef TEST
#define TEST(str, mode, gbump, arg, result, pback, read, write) \
test_virtual (pfid, __LINE__, str, sizeof str - 1, mode, gbump, \
arg, IGN, IGN, result, pback, read, write);
///////////////////////////////////////////////////////////////////////
// 27.7.1.3 + LWG issues 169 and 432
//
// -5- Effects: Appends the character designated by c to the output
// sequence, if possible, in one of two ways:
// -- If traits::eq_int_type(c,traits::eof()) returns false and
// if either the output sequence has a write position available
// or the function makes a write position available (as described
// below), the function calls sputc(c).
// Signals success by returning c.
// -- If traits::eq_int_type(c,traits::eof()) returns true, there
// is no character to append.
// Signals success by returning a value other than traits::eof().
// -6- Notes: The function can alter the number of write positions
// available as a result of any call.
// -7- Returns: traits::eof() to indicate failure.
// -8- (blank)
// -9- Notes: The function can make a write position available only if
// (mode & ios_base::out) != 0. To make a write position available,
// the function reallocates (or initially allocates) an array object
// with a sufficient number of elements to hold the current array
// object (if any), plus one additional write position. If
// (mode & ios_base::in) != 0, the function alters the read end
// pointer egptr() to point just past the new write position.
///////////////////////////////////////////////////////////////////////
// +-------------------------------------- initial sequence (if any)
// | +---------------------------------- open mode
// | | +------------------------ gbump
// | | | +-------------------- overflow argument
// | | | | +---------------- result of call
// | | | | | +---------- putback positions after call
// | | | | | | +------ read positions after call
// | | | | | | | +-- write positions after call
// | | | | | | | |
// | | | | | | | |
// V V V V V V V V
TEST (0, 0, 0, 'c', EOF, 0, 0, -1);
TEST (0, in, 0, 'c', EOF, 0, 0, -1);
TEST (0, out, 0, 'c', 'c', 0, 0, AT_LEAST_1);
TEST (0, in | out, 0, 'c', 'c', 0, 1, AT_LEAST_1);
TEST (0, in | ate, 0, 'c', EOF, 0, 0, -1);
TEST (0, out | ate, 0, 'c', 'c', 0, 0, AT_LEAST_1);
TEST (0, in | out | ate, 0, 'c', 'c', 0, 1, AT_LEAST_1);
TEST ("", 0, 0, 'c', EOF, 0, 0, -1);
TEST ("", in, 0, 'c', EOF, 0, 0, -1);
TEST ("", out, 0, 'c', 'c', 0, 0, AT_LEAST_1);
TEST ("", in | out, 0, 'c', 'c', 0, 1, AT_LEAST_1);
TEST ("a", 0, 0, 'c', EOF, 0, 0, -1);
TEST ("a", in, 0, 'c', EOF, 0, 1, -1);
TEST ("a", out, 0, 'c', 'c', 0, 0, AT_LEAST_1);
TEST ("a", in | out, 0, 'c', 'c', 0, 2, AT_LEAST_1);
TEST ("a", in | ate, 0, 'c', EOF, 0, 1, -1);
TEST ("a", out | ate, 0, 'c', 'c', 0, 0, MAYBE_1);
TEST ("a", in | out | ate, 0, 'c', 'c', 0, 2, MAYBE_1);
TEST ("ab", 0, 0, 'c', EOF, 0, 0, -1);
TEST ("ab", in, 0, 'c', EOF, 0, 2, -1);
TEST ("ab", out, 0, 'c', 'c', 0, 0, AT_LEAST_1);
TEST ("ab", in | out, 0, 'c', 'c', 0, 3, AT_LEAST_1);
TEST ("ab", in | ate, 0, 'c', EOF, 0, 2, -1);
TEST ("ab", out | ate, 0, 'c', 'c', 0, 0, AT_LEAST_1);
TEST ("ab", in | out | ate, 0, 'c', 'c', 0, 3, AT_LEAST_1);
// verify that when the argument is EOF the function returns a value
// other than traits::eof() regardless of the streambuf open mode
TEST (0, 0, 0, EOF, NOT_EOF, 0, 0, -1);
TEST (0, in, 0, EOF, NOT_EOF, 0, 0, -1);
TEST (0, out, 0, EOF, NOT_EOF, 0, 0, -1);
TEST (0, in | out, 0, EOF, NOT_EOF, 0, 0, -1);
TEST (0, in | ate, 0, EOF, NOT_EOF, 0, 0, -1);
TEST (0, out | ate, 0, EOF, NOT_EOF, 0, 0, -1);
TEST (0, in | out | ate, 0, EOF, NOT_EOF, 0, 0, -1);
TEST ("abc", 0, 0, EOF, NOT_EOF, 0, 0, -1);
TEST ("abc", in, 0, EOF, NOT_EOF, 0, 3, -1);
TEST ("abc", out, 0, EOF, NOT_EOF, 0, 0, AT_LEAST_1);
TEST ("abc", in | out, 0, EOF, NOT_EOF, 0, 3, AT_LEAST_1);
TEST ("abc", in | ate, 0, EOF, NOT_EOF, 0, 3, -1);
TEST ("abc", out | ate, 0, EOF, NOT_EOF, 0, 0, MAYBE_1);
TEST ("abc", in | out | ate, 0, EOF, NOT_EOF, 0, 3, MAYBE_1);
}
/**************************************************************************/
static void
test_underflow (VFun *pfid)
{
rw_info (0, 0, 0, "basic_stringbuf<%s%{?}, %s%{;}>::underflow()",
pfid->cname_, 0 != pfid->tname_, pfid->tname_);
pfid->vfun_ = VFun::underflow;
#undef TEST
#define TEST(str, mode, gbump, result, pback, read, write) \
test_virtual (pfid, __LINE__, str, sizeof str - 1, mode, gbump, \
IGN, IGN, IGN, result, pback, read, write);
///////////////////////////////////////////////////////////////////////
// 27.7.1.3 + LWG issue 432
//
// int_type undeflow ()
//
// -1- If the input sequence has a read position available, returns
// traits::to_int_type(*gptr()). Otherwise, returns traits::eof().
// Any character in the underlying buffer which has been initialized
// is considered to be part of the input sequence.
// +------------------------------------------ initial sequence
// | +----------------------------------- open mode
// | | +------------------- gbump
// | | | +---------------- underflow result
// | | | | +----------- putback positions
// | | | | | +-------- read positions
// | | | | | | +---- write positions
// | | | | | | |
// | | | | | | |
// | | | | | | |
// V V V V V V V
TEST (0, 0, 0, EOF, 0, 0, -1);
TEST (0, in, 0, EOF, 0, 0, -1);
TEST (0, out, 0, EOF, 0, 0, -1);
TEST (0, in | out, 0, EOF, 0, 0, -1);
TEST (0, in | out | ate, 0, EOF, 0, 0, -1);
TEST ("", 0, 0, EOF, 0, 0, -1);
TEST ("", in, 0, EOF, 0, 0, -1);
TEST ("", out, 0, EOF, 0, 0, -1);
TEST ("", in | out, 0, EOF, 0, 0, -1);
TEST ("", in | out | ate, 0, EOF, 0, 0, -1);
TEST ("abc", 0, 0, EOF, 0, 0, -1);
TEST ("abc", in, 0, 'a', 0, 3, -1);
TEST ("abc", in, 1, 'b', 1, 2, -1);
TEST ("abc", in, 2, 'c', 2, 1, -1);
TEST ("abc", in, 3, EOF, 3, 0, -1);
TEST ("abc", out, 0, EOF, 0, 0, AT_LEAST_1);
TEST ("abc", in | out, 0, 'a', 0, 3, AT_LEAST_1);
TEST ("abc", in | out, 1, 'b', 1, 2, AT_LEAST_1);
TEST ("abc", in | out, 2, 'c', 2, 1, AT_LEAST_1);
TEST ("abc", in | out, 3, EOF, 3, 0, AT_LEAST_1);
TEST ("abc", in | out | ate, 0, 'a', 0, 3, MAYBE_1);
TEST ("abc", in | out | ate, 1, 'b', 1, 2, MAYBE_1);
TEST ("abc", in | out | ate, 2, 'c', 2, 1, MAYBE_1);
TEST ("abc", in | out | ate, 3, EOF, 3, 0, MAYBE_1);
//////////////////////////////////////////////////////////////////
// exercise UserTraits with an unusual eof
if (0 == pfid->tname_)
return;
TEST ("a$c", in, 0, 'a', 0, 3, -1);
TEST ("a$c", in, 1, EOF, 1, 2, -1);
}
/**************************************************************************/
// exercises both seekoff (seeking from the beginning) and seekpos
static void
test_seek (VFun *pfid)
{
RW_ASSERT ( VFun::seekoff == pfid->vfun_
|| VFun::seekpos == pfid->vfun_);
#undef TEST
#define TEST(str, mode, gbump, off, which, res, pback, read, write) \
test_virtual (pfid, __LINE__, str, sizeof str - 1, mode, gbump, \
off, std::ios::beg, which, res, pback, read, write)
//////////////////////////////////////////////////////////////////
//
// 27.7.1.3, p10 + LWG issue 432
//
// pos_type seekoff (off_type off, ios_base::seekdir way,
// ios_base::openmode which = in | out);
//
// -10- Effects: Alters the stream position within one of the controlled
// sequences, if possible, as indicated in Table 90:
//
// Table 90 -- seekoff positioning
// -------------------------------
// Conditions Result
// --------------- ---------------
// (which & in) positions the input sequence
// (which & out) positions the output sequence
// (which & (in | out)) == (in & out) && (way == beg || way == end)
// positions both sequences
// otherwise fails
// -------------------------------
//
// -11- For a sequence to be positioned, if its next pointer (either
// gptr() or pptr()) is a null pointer, the positioning operation
// fails. Otherwise, the function determines newoff as indicated
// in Table 91:
//
// Table 91 -- newoff values
// ----------------------------
//
// Condition Newoff value
// --------------- ------------
// (way == beg) 0
// (way == cur) xnext - xbeg
// (way == end) xend - xbeg
// ----------------------------
//
// -12- If (newoff + off) < 0, or if (newoff + off) refers to an
// uninitialized character (as defined in 27.7.1.2
// [lib.stringbuf.members] paragraph 1), the positioning operation
// fails. Otherwise, the function assigns (xbeg + newoff + off) to
// the next pointer xnext.
// -13- Returns: pos_type(newoff), constructed from the resultant offset
// newoff (of type off_type), that stores the resultant stream
// position, if possible. If the positioning operation fails, or
// if the constructed object cannot represent the resultant stream
// position, the return value is pos_type(off_type(-1)).
//
//////////////////////////////////////////////////////////////////
// +-- initial sequence
// | +-- open mode (in, out, ate)
// | | +-- gbump
// | | | +-- offset
// | | | | +-- which (in, out)
// | | | | | +--- resulting position
// | | | | | | +-- putback positions
// | | | | | | | +-- read positions
// | | | | | | | | +-- write pos.
// | | | | | | | | |
// | | | | | | | | |
// | | | | | | | | |
// V V V V V V V V V
TEST (0, 0, 0, 0, 0, NPOS, 0, 0, -1);
TEST (0, in, 0, 0, 0, NPOS, 0, 0, -1);
TEST (0, out, 0, 0, 0, NPOS, 0, 0, -1);
TEST (0, ate, 0, 0, 0, NPOS, 0, 0, -1);
TEST (0, in | out, 0, 0, 0, NPOS, 0, 0, -1);
TEST (0, in | out | ate, 0, 0, 0, NPOS, 0, 0, -1);
TEST (0, 0, 0, 0, 0, NPOS, 0, 0, -1);
TEST ("abc", 0, 0, 0, 0, NPOS, 0, 0, -1);
TEST ("abc", 0, 0, 1, 0, NPOS, 0, 0, -1);
TEST ("abc", 0, 0, -1, 0, NPOS, 0, 0, -1);
// seek within the input sequence from the beginning
TEST ("abc", in, 0, 0, in, 0, 0, 3, -1);
TEST ("abc", in, 0, 1, in, 1, 1, 2, -1);
TEST ("abc", in, 0, 2, in, 2, 2, 1, -1);
TEST ("abc", in, 0, 3, in, 3, 3, 0, -1);
TEST ("abc", in, 0, 4, in, NPOS, 0, 3, -1);
// advance gptr by one and seek within the input sequence
TEST ("abc", in, 1, 0, in, 0, 0, 3, -1);
TEST ("abc", in, 1, 1, in, 1, 1, 2, -1);
TEST ("abc", in, 1, 2, in, 2, 2, 1, -1);
TEST ("abc", in, 1, 3, in, 3, 3, 0, -1);
TEST ("abc", in, 1, 4, in, NPOS, 1, 2, -1);
// advance gptr by two and seek within the input sequence
TEST ("abc", in, 2, 0, in, 0, 0, 3, -1);
TEST ("abc", in, 2, 1, in, 1, 1, 2, -1);
TEST ("abc", in, 2, 2, in, 2, 2, 1, -1);
TEST ("abc", in, 2, 3, in, 3, 3, 0, -1);
TEST ("abc", in, 2, 4, in, NPOS, 2, 1, -1);
// exercise seeking within the output sequence
TEST ("abc", out, 0, 0, out, 0, 0, 0, MAYBE_1);
TEST ("abc", out, 0, 1, out, 1, 0, 0, MAYBE_1);
TEST ("abc", out, 0, -1, out, NPOS, 0, 0, MAYBE_1);
TEST ("abc", out, 0, 2, out, 2, 0, 0, MAYBE_1);
TEST ("abc", out, 0, 3, out, 3, 0, 0, MAYBE_1);
TEST ("abc", out, 0, 4, out, NPOS, 0, 0, MAYBE_1);
// seeking withing both input and output
TEST ("abc", in | out, 0, 0, in | out, 0, 0, 3, MAYBE_1);
TEST ("abc", in | out, 0, 1, in | out, 1, 1, 2, MAYBE_1);
TEST ("abc", in | out, 0, -1, in | out, NPOS, 0, 3, MAYBE_1);
TEST ("abc", in | out, 0, 2, in | out, 2, 2, 1, MAYBE_1);
TEST ("abc", in | out, 0, 3, in | out, 3, 3, 0, MAYBE_1);
TEST ("abc", in | out, 0, 4, in | out, NPOS, 0, 3, MAYBE_1);
}
/**************************************************************************/
static void
test_seekoff (VFun *pfid)
{
rw_info (0, 0, 0, "basic_stringbuf<%s%{?}, %s%{;}>::seekoff(off_type, "
"ios_base::seekdir, ios_base::openmode)",
pfid->cname_, 0 != pfid->tname_, pfid->tname_);
pfid->vfun_ = VFun::seekoff;
test_seek (pfid);
#undef TEST
#define TEST(str, mode, gbump, off, way, which, res, pback, read, write) \
test_virtual (pfid, __LINE__, str, sizeof str - 1, mode, gbump, \
off, way, which, res, pback, read, write)
// exercise seeking from the current position and from end
// +-- initial sequence
// | +-- open mode (in, out, ate)
// | | +-- gbump
// | | | +-- offset
// | | | | +-- way (cur or end)
// | | | | | +-- which (in, out)
// | | | | | | +--- resulting position
// | | | | | | | +-- putback positions
// | | | | | | | | +-- read positions
// | | | | | | | | | +-- write pos.
// | | | | | | | | | |
// | | | | | | | | | |
// | | | | | | | | | |
// V V V V V V V V V V
TEST (0, 0, 0, 0, cur, 0, NPOS, 0, 0, -1);
TEST (0, in, 0, 0, cur, 0, NPOS, 0, 0, -1);
TEST (0, out, 0, 0, cur, 0, NPOS, 0, 0, -1);
TEST (0, ate, 0, 0, cur, 0, NPOS, 0, 0, -1);
TEST (0, in | out, 0, 0, cur, 0, NPOS, 0, 0, -1);
TEST (0, in | out | ate, 0, 0, cur, 0, NPOS, 0, 0, -1);
TEST (0, 0, 0, 0, end, 0, NPOS, 0, 0, -1);
TEST (0, in, 0, 0, end, 0, NPOS, 0, 0, -1);
TEST (0, out, 0, 0, end, 0, NPOS, 0, 0, -1);
TEST (0, ate, 0, 0, end, 0, NPOS, 0, 0, -1);
TEST (0, in | out, 0, 0, end, 0, NPOS, 0, 0, -1);
TEST (0, in | out | ate, 0, 0, end, 0, NPOS, 0, 0, -1);
// exercise seeking within the output sequence
// (if (mode & in) == 0 then (pptr() == pbase()) is a postcondition
// of the constructor -- see also lwg issue 562)
TEST ("abc", out, 0, 0, cur, out, 0, 0, 0, MAYBE_1);
TEST ("abc", out, 0, 1, cur, out, 1, 0, 0, MAYBE_1);
TEST ("abc", out, 0, -1, cur, out, NPOS, 0, 0, MAYBE_1);
TEST ("abc", out, 0, 2, cur, out, 2, 0, 0, MAYBE_1);
TEST ("abc", out, 0, 3, cur, out, 3, 0, 0, MAYBE_1);
TEST ("abc", out, 0, 4, cur, out, NPOS, 0, 0, MAYBE_1);
// seek within the input sequence from the current position
TEST ("abc", in, 0, 0, cur, in, 0, 0, 3, -1);
TEST ("abc", in, 0, 1, cur, in, 1, 1, 2, -1);
TEST ("abc", in, 0, 2, cur, in, 2, 2, 1, -1);
TEST ("abc", in, 0, 3, cur, in, 3, 3, 0, -1);
TEST ("abc", in, 0, 4, cur, in, NPOS, 0, 3, -1);
// seek within the input sequence from the end
TEST ("abc", in, 0, 0, end, in, 3, 3, 0, -1);
TEST ("abc", in, 0, -1, end, in, 2, 2, 1, -1);
TEST ("abc", in, 0, -2, end, in, 1, 1, 2, -1);
TEST ("abc", in, 0, -3, end, in, 0, 0, 3, -1);
TEST ("abc", in, 0, -4, end, in, NPOS, 0, 3, -1);
// exercise positioning from the end: this behavior is not
// correctly specified even in LWG issue 432 (see the post
// in c++std-lib-16390)
// the implemented behavior considers end to be the "high
// mark" mentioned in DR 432 rather than epptr()
// see LWG issue 563:
// http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#563
TEST ("abc", out, 0, 0, end, out, 3, 0, 0, MAYBE_1);
TEST ("abc", out, 0, 1, end, out, NPOS, 0, 0, MAYBE_1);
TEST ("abc", out, 0, -1, end, out, 2, 0, 0, MAYBE_1);
TEST ("abc", out, 0, -2, end, out, 1, 0, 0, MAYBE_1);
TEST ("abc", out, 0, -3, end, out, 0, 0, 0, MAYBE_1);
TEST ("abc", out, 0, -4, end, out, NPOS, 0, 0, MAYBE_1);
TEST ("abc", out | ate, 0, 0, cur, out, 3, 0, 0, MAYBE_1);
TEST ("abc", out | ate, 0, 1, cur, out, NPOS, 0, 0, MAYBE_1);
TEST ("abc", out | ate, 0, -1, cur, out, 2, 0, 0, MAYBE_1);
TEST ("abc", out | ate, 0, -2, cur, out, 1, 0, 0, MAYBE_1);
TEST ("abc", out | ate, 0, -3, cur, out, 0, 0, 0, MAYBE_1);
TEST ("abc", out | ate, 0, -4, cur, out, NPOS, 0, 0, MAYBE_1);
// seeking within both input and output from the end
TEST ("abc", in | out, 0, 0, end, in | out, 3, 3, 0, MAYBE_1);
TEST ("abc", in | out, 0, 1, end, in | out, NPOS, 0, 3, MAYBE_1);
TEST ("abc", in | out, 0, -1, end, in | out, 2, 2, 1, MAYBE_1);
TEST ("abc", in | out, 0, -2, end, in | out, 1, 1, 2, MAYBE_1);
TEST ("abc", in | out, 0, -3, end, in | out, 0, 0, 3, MAYBE_1);
TEST ("abc", in | out, 0, -4, end, in | out, NPOS, 0, 3, MAYBE_1);
TEST ("abc", in, 0, 0, cur, in | out, NPOS, 0, 3, MAYBE_1);
TEST ("abc", out, 0, 0, cur, in | out, NPOS, 0, 0, MAYBE_1);
TEST ("abc", in | out, 0, 0, cur, in | out, NPOS, 0, 3, MAYBE_1);
TEST ("abc", in | out | ate, 0, 0, cur, in | out, NPOS, 0, 3, MAYBE_1);
TEST ("abc", in | out | ate, 1, -1, end, in, 2, 2, 1, MAYBE_1);
TEST ("abc", in | out | ate, 1, -1, end, out, 2, 1, 2, MAYBE_1);
TEST ("abc", in | out | ate, 1, -1, end, in | out, 2, 2, 1, MAYBE_1);
TEST ("abc", in | out | ate, 2, -1, end, in | out, 2, 2, 1, MAYBE_1);
TEST ("abc", in | out | ate, 3, -1, end, in | out, 2, 2, 1, MAYBE_1);
}
/**************************************************************************/
static void
test_seekpos (VFun *pfid)
{
rw_info (0, 0, 0, "basic_stringbuf<%s%{?}, %s%{;}>::seekpos(pos_type, "
"ios_base::openmode)",
pfid->cname_, 0 != pfid->tname_, pfid->tname_);
pfid->vfun_ = VFun::seekpos;
test_seek (pfid);
}
/**************************************************************************/
static int rw_opt_no_xsputn; // for --no-xsputn
static int rw_opt_no_pbackfail; // for --no-pbackfail
static int rw_opt_no_overflow; // for --no-overflow
static int rw_opt_no_underflow; // for --no-underflow
static int rw_opt_no_seekoff; // for --no-seekoff
static int rw_opt_no_seekpos; // for --no-seekpos
static int rw_opt_no_seek; // for --no-seek
static int rw_opt_no_char_traits; // for --no-char_traits
static int rw_opt_no_user_traits; // for --no-user_traits
static void
run_test (VFun *pfid)
{
#undef TEST
#define TEST(function) \
if (rw_opt_no_ ## function) \
rw_note (1 < rw_opt_no_ ## function++, 0, 0, \
"%s test disabled", #function); \
else \
test_ ## function (pfid)
if (pfid->tname_ && rw_opt_no_user_traits) {
rw_note (1 < rw_opt_no_user_traits++, 0, 0,
"user defined traits test disabled");
}
else if (!pfid->tname_ && rw_opt_no_char_traits) {
rw_note (1 < rw_opt_no_char_traits++, 0, 0,
"char_traits test disabled");
}
else {
TEST (xsputn);
TEST (pbackfail);
TEST (overflow);
TEST (underflow);
TEST (seekoff);
TEST (seekpos);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
if ('\0' == long_string [0]) {
// initialize long_string
for (std::size_t i = 0; i != sizeof long_string - 1; ++i)
long_string [i] = 'x';
}
if (rw_opt_no_seek) {
rw_opt_no_seekoff = 1;
rw_opt_no_seekpos = 1;
}
if (rw_enabled ("char")) {
VFun fid (VFun::Char, "char", VFun::DefaultTraits, 0);
traits_eof = -1;
run_test (&fid);
fid.tid_ = VFun::UserTraits;
fid.tname_ = "UserTraits";
traits_eof = '$';
run_test (&fid);
}
else
rw_note (0, 0, 0, "char tests disabled");
if (rw_enabled ("wchar_t")) {
VFun fid (VFun::WChar, "wchar_t", VFun::DefaultTraits, 0);
traits_eof = -1;
run_test (&fid);
fid.tid_ = VFun::UserTraits;
fid.tname_ = "UserTraits";
traits_eof = '$';
run_test (&fid);
}
else
rw_note (0, 0, 0, "char tests disabled");
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.stringbuf.virtuals",
0, // no comment
run_test,
"|-no-xsputn# "
"|-no-pbackfail# "
"|-no-overflow# "
"|-no-underflow# "
"|-no-seekoff# "
"|-no-seekpos# "
"|-no-seek# "
"|-no-char_traits# "
"|-no-user_traits# "
"|-max_buf_size#0-*",
&rw_opt_no_xsputn,
&rw_opt_no_pbackfail,
&rw_opt_no_overflow,
&rw_opt_no_underflow,
&rw_opt_no_seekoff,
&rw_opt_no_seekpos,
&rw_opt_no_seek,
&rw_opt_no_char_traits,
&rw_opt_no_user_traits,
int (sizeof long_string) - 1,
&rw_opt_max_size);
}