void test_readsome (const charT *cbuf, const Traits*, unsigned cbuf_size, unsigned i, // index into states unsigned j, // number of chars to read unsigned k, // when underflow() will fail int l, // value returned from showmanyc() unsigned m) // how underflow should fail() { typedef std::basic_istream<charT, Traits> Istream; static unsigned iter = 0; // iteration counter // construct a stream buffer object and initialize its read // sequence with the character buffer Streambuf<charT, Traits> sb (cbuf, cbuf + cbuf_size - 1); sb.showmanyc_ = l; const char* err_type = 0; if (m < 1) { // have the stream buffer object's underflow() fail (by // throwing an exception if possible) after k characters // have been extracted (this object calls underflow() for // every char) sb.throw_after_ = k; err_type = "threw"; } else { // have the stream buffer object's underflow() fail by // returning eof after k characters have been extracted // (this object calls underflow() for every char) sb.fail_after_ = k; err_type = "returned EOF"; } // construct an istream object and initialize it with the user // defined streambuf object Istream is (&sb); // set the stream object's initial state is.setstate (states [i]); // the number of extracted whitespace characters expected to // be reported by gcount() must equal the number of successful // extractions computed by the the stream buffer overridden // underflow member function const int extract = is.good () ? j < k ? int (j) < l ? j : l < 0 ? 0 : l : int (k) < l ? k : l < 0 ? 0 : l : 0; charT buf [256] = { 0 }; std::streamsize nread = -1; // format the FCALL environment variable so that it can be // conveniently used in diagnostics below rw_fprintf (0, "%u. %{$FCALL!:@}", iter, "%{$ISTREAM}(%{*Ac}).readsome(%p, %d)", int (sizeof *cbuf), cbuf, buf, j); #ifndef _RWSTD_NO_EXCEPTIONS const char *caught = 0; // on every other iteration set badbit in exceptions to check // that the thrown object is propagated by the function if (k % 2 && !is.bad ()) is.exceptions (std::ios_base::badbit); try { nread = is.readsome (buf, j); } catch (const char *s) { caught = s; } catch (...) { caught = "..."; rw_assert (0, 0, __LINE__, "%{$FCALL} threw an exception of unexpected type"); } ////////////////////////////////////////////////////////////////// // verify that the function propagates exceptions thrown from the // streambuf object only when badbit is set in the stream object's // exceptions() rw_assert (!caught || (k % 2), 0, __LINE__, "%{$FCALL} unexpectedly propagated an exception"); #else // if defined (_RWSTD_NO_EXCEPTIONS) nread = is.readsome (buf, j); #endif // _RWSTD_NO_EXCEPTIONS ////////////////////////////////////////////////////////////////// // verify that the function returned the expected number of // extracted characters const std::streamsize extracted = sb.pubgptr () - sb.pubeback (); rw_assert (extract == extracted, 0, __LINE__, "%{$FCALL} expected to extract %d chars, got %u; " "initial state = %{Is}, underflow %s at extraction %u", extract, extracted, states [i], err_type, k); ////////////////////////////////////////////////////////////////// // verify that the expected number of characters have been // extracted from the stream rw_assert (cbuf + extract == sb.pubgptr (), 0, __LINE__, "%{$FCALL} expected to extract %d chars, got %u; " "initial state = %{Is}, underflow %s at extraction %u", extract, extracted, states [i], err_type, k); ////////////////////////////////////////////////////////////////// // verify that the extracted characters match those in the buffer rw_assert (0 == std::char_traits<charT>::compare (buf, cbuf, extract), 0, __LINE__, "%{$FCALL} expected to extract the first %d chars, got %{*Ac}", extract, int (sizeof *buf), buf); ////////////////////////////////////////////////////////////////// // verify that gcount() correctly reflects the number of // characters successfully extracted from the stream rw_assert (extract == is.gcount (), 0, __LINE__, "%{$FCALL}: gcount() == %d, got %d; initial state = %{Is}, " "underflow %s at extraction %u", extract, is.gcount (), states [i], err_type, k); ////////////////////////////////////////////////////////////////// // verify the state of the stream object after the function call // expected stream state after the function call is unchanged // (i.e., the initial stream state), except... std::ios_base::iostate expect_state = states [i]; if (!states [i]) { #ifndef _RWSTD_NO_EXCEPTIONS // ...if an extraction is attempted, or even if the first // character on the stream is peeked at, and an exception // is thrown during input, badbit should be set, otherwise // if in_avail() returned -1, eofbit should be set, else // the state should be good if (-2 == l) expect_state = std::ios_base::badbit; else if (l < 0) expect_state = std::ios_base::eofbit; else expect_state = std::ios_base::goodbit; #else // if defined (_RWSTD_NO_EXCEPTIONS) if (l < 0) expect_state = std::ios_base::eofbit; else expect_state = std::ios_base::goodbit; #endif // _RWSTD_NO_EXCEPTIONS } else { // ...if the initial stream state is not good, failbit // must be set expect_state = states [i] | std::ios_base::failbit; } rw_assert (is.rdstate () == expect_state, 0, __LINE__, "%{$FCALL}: rdstate() == %{Is}, got %{Is}; " "extracted %u characters; " "initial state = %{Is}, underflow %s at extraction %u", expect_state, is.rdstate (), extracted, states [i], err_type, k); ++iter; }