Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
27.istream.readsome.cpp
Go to the documentation of this file.
1
29#include <istream>
30#include <sstream>
31
32#include <rw_driver.h>
33#include <rw_char.h> // for UserChar, UserTraits
34#include <rw_printf.h> // for rw_printf()
35
36
38template <class charT, class Traits>
39struct Streambuf: std::basic_streambuf<charT, Traits>
40{
41 typedef std::basic_streambuf<charT, Traits> Base;
42 typedef typename Base::traits_type traits_type;
43 typedef typename Base::int_type int_type;
44
45 // value returned from showmanyc()
47
48 // underflow() will return eof () after extracting this many chars
49 int fail_after_;
50
51 // underflow() will throw am exception after extracting this many chars
52 int throw_after_;
53
54 const charT *end_; // the end of the buffer (future eback())
55
56 Streambuf (const charT *gbeg, const charT *gend)
57 : Base (),
58 showmanyc_ (0),
59 fail_after_ (-1), // never fail
60 throw_after_ (-1), // never throw
61 end_ (gend) {
62 this->setg (_RWSTD_CONST_CAST (charT*, gbeg),
63 _RWSTD_CONST_CAST (charT*, gbeg),
64 _RWSTD_CONST_CAST (charT*, gbeg));
65 }
66
67 const charT* pubeback () const {
68 return this->eback ();
69 }
70
71 const charT* pubgptr () const {
72 return this->gptr ();
73 }
74
75 const charT* pubegptr () const {
76 return this->egptr ();
77 }
78
79 /* virtual */ std::streamsize showmanyc () {
80#ifndef _RWSTD_NO_EXCEPTIONS
81
82 if (-2 == showmanyc_)
83 throw (const char*)"showmanyc";
84
85#endif // _RWSTD_NO_EXCEPTIONS
86
87 return showmanyc_;
88 }
89
90 /* virtual */ int_type underflow () {
91 if (this->gptr () == end_)
92 return traits_type::eof ();
93
94 if (throw_after_ == this->gptr () - this->eback ()) {
95
96#ifndef _RWSTD_NO_EXCEPTIONS
97
98 throw (const char*)"underflow";
99
100#else // if defined (_RWSTD_NO_EXCEPTIONS)
101
102 return traits_type::eof ();
103
104#endif // _RWSTD_NO_EXCEPTIONS
105
106 }
107
108 if (fail_after_ == this->gptr () - this->eback ())
109 return traits_type::eof ();
110
111 this->setg (this->eback (), this->gptr (), this->gptr () + 1);
112 return traits_type::to_int_type (*this->gptr ());
113 }
114};
115
116
136void
137memfun_info (int line, const char *cname, const char *tname)
138{
139 // format the ISTREAM environment variable w/o writing
140 // out any output
141 rw_fprintf (0,
142 "%{$ISTREAM!:@}",
143 "%{?}istream%{:}%{?}wistream"
144 "%{:}basic_istream<%s, %s>%{;}%{;}",
145 'c' == *cname && 'c' == *tname,
146 'w' == *cname && 'c' == *tname,
147 cname, tname);
148
149 rw_info (0, 0, line,
150 "std::%{$ISTREAM}::readsome (char_type*, streamsize)");
151}
152
153
155extern const std::ios_base::iostate
156states[] = {
157 std::ios_base::badbit,
158 std::ios_base::eofbit,
159 std::ios_base::failbit,
160 std::ios_base::goodbit,
161 std::ios_base::badbit | std::ios_base::eofbit,
162 std::ios_base::badbit | std::ios_base::failbit,
163 std::ios_base::eofbit | std::ios_base::failbit,
164 std::ios_base::badbit | std::ios_base::eofbit | std::ios_base::failbit
165};
166
167extern const unsigned nstates = sizeof states / sizeof *states;
168
169
170template <class charT, class Traits>
171void test_readsome (const charT *cbuf, const Traits*,
172 unsigned cbuf_size,
173 unsigned i, // index into states
174 unsigned j, // number of chars to read
175 unsigned k, // when underflow() will fail
176 int l, // value returned from showmanyc()
177 unsigned m) // how underflow should fail()
178{
179 typedef std::basic_istream<charT, Traits> Istream;
180
181 static unsigned iter = 0; // iteration counter
182
183 // construct a stream buffer object and initialize its read
184 // sequence with the character buffer
185 Streambuf<charT, Traits> sb (cbuf, cbuf + cbuf_size - 1);
186
187 sb.showmanyc_ = l;
188
189 const char* err_type = 0;
190
191 if (m < 1) {
192 // have the stream buffer object's underflow() fail (by
193 // throwing an exception if possible) after k characters
194 // have been extracted (this object calls underflow() for
195 // every char)
196 sb.throw_after_ = k;
197 err_type = "threw";
198 }
199 else {
200 // have the stream buffer object's underflow() fail by
201 // returning eof after k characters have been extracted
202 // (this object calls underflow() for every char)
203 sb.fail_after_ = k;
204 err_type = "returned EOF";
205 }
206
207 // construct an istream object and initialize it with the user
208 // defined streambuf object
209 Istream is (&sb);
210
211 // set the stream object's initial state
212 is.setstate (states [i]);
213
214 // the number of extracted whitespace characters expected to
215 // be reported by gcount() must equal the number of successful
216 // extractions computed by the the stream buffer overridden
217 // underflow member function
218 const int extract =
219 is.good () ? j < k ? int (j) < l ? j
220 : l < 0 ? 0 : l
221 : int (k) < l ? k
222 : l < 0 ? 0 : l
223 : 0;
224
225 charT buf [256] = { 0 };
226
227 std::streamsize nread = -1;
228
229 // format the FCALL environment variable so that it can be
230 // conveniently used in diagnostics below
231 rw_fprintf (0, "%u. %{$FCALL!:@}",
232 iter,
233 "%{$ISTREAM}(%{*Ac}).readsome(%p, %d)",
234 int (sizeof *cbuf), cbuf, buf, j);
235
236#ifndef _RWSTD_NO_EXCEPTIONS
237
238 const char *caught = 0;
239
240 // on every other iteration set badbit in exceptions to check
241 // that the thrown object is propagated by the function
242 if (k % 2 && !is.bad ())
243 is.exceptions (std::ios_base::badbit);
244
245 try {
246 nread = is.readsome (buf, j);
247 }
248 catch (const char *s) {
249 caught = s;
250 }
251 catch (...) {
252
253 caught = "...";
254
255 rw_assert (0, 0, __LINE__,
256 "%{$FCALL} threw an exception of unexpected type");
257 }
258
260 // verify that the function propagates exceptions thrown from the
261 // streambuf object only when badbit is set in the stream object's
262 // exceptions()
263
264 rw_assert (!caught || (k % 2), 0, __LINE__,
265 "%{$FCALL} unexpectedly propagated an exception");
266
267#else // if defined (_RWSTD_NO_EXCEPTIONS)
268
269 nread = is.readsome (buf, j);
270
271#endif // _RWSTD_NO_EXCEPTIONS
272
274 // verify that the function returned the expected number of
275 // extracted characters
276
277 const std::streamsize extracted = sb.pubgptr () - sb.pubeback ();
278
279 rw_assert (extract == extracted, 0, __LINE__,
280 "%{$FCALL} expected to extract %d chars, got %u; "
281 "initial state = %{Is}, underflow %s at extraction %u",
282 extract, extracted, states [i],
283 err_type, k);
284
286 // verify that the expected number of characters have been
287 // extracted from the stream
288
289 rw_assert (cbuf + extract == sb.pubgptr (), 0, __LINE__,
290 "%{$FCALL} expected to extract %d chars, got %u; "
291 "initial state = %{Is}, underflow %s at extraction %u",
292 extract, extracted, states [i],
293 err_type, k);
294
296 // verify that the extracted characters match those in the buffer
297
298 rw_assert (0 == std::char_traits<charT>::compare (buf, cbuf, extract),
299 0, __LINE__,
300 "%{$FCALL} expected to extract the first %d chars, got %{*Ac}",
301 extract, int (sizeof *buf), buf);
302
304 // verify that gcount() correctly reflects the number of
305 // characters successfully extracted from the stream
306
307 rw_assert (extract == is.gcount (), 0, __LINE__,
308 "%{$FCALL}: gcount() == %d, got %d; initial state = %{Is}, "
309 "underflow %s at extraction %u",
310 extract, is.gcount (), states [i],
311 err_type, k);
312
314 // verify the state of the stream object after the function call
315
316 // expected stream state after the function call is unchanged
317 // (i.e., the initial stream state), except...
318 std::ios_base::iostate expect_state = states [i];
319
320 if (!states [i]) {
321
322#ifndef _RWSTD_NO_EXCEPTIONS
323
324 // ...if an extraction is attempted, or even if the first
325 // character on the stream is peeked at, and an exception
326 // is thrown during input, badbit should be set, otherwise
327 // if in_avail() returned -1, eofbit should be set, else
328 // the state should be good
329 if (-2 == l)
330 expect_state = std::ios_base::badbit;
331 else if (l < 0)
332 expect_state = std::ios_base::eofbit;
333 else
334 expect_state = std::ios_base::goodbit;
335
336#else // if defined (_RWSTD_NO_EXCEPTIONS)
337
338 if (l < 0)
339 expect_state = std::ios_base::eofbit;
340 else
341 expect_state = std::ios_base::goodbit;
342
343#endif // _RWSTD_NO_EXCEPTIONS
344
345 }
346 else {
347
348 // ...if the initial stream state is not good, failbit
349 // must be set
350 expect_state = states [i] | std::ios_base::failbit;
351 }
352
353 rw_assert (is.rdstate () == expect_state, 0, __LINE__,
354 "%{$FCALL}: rdstate() == %{Is}, got %{Is}; "
355 "extracted %u characters; "
356 "initial state = %{Is}, underflow %s at extraction %u",
357 expect_state, is.rdstate (), extracted,
358 states [i], err_type, k);
359
360 ++iter;
361}
362
363
366template <class charT, class Traits>
367void test_readsome (const charT*, const Traits*,
368 const char *cname, const char *tname)
369{
370 memfun_info (__LINE__, cname, tname);
371
373 // exercise 27.6.1.3, p1
374
375 const charT cbuf[] = { ' ', 'a', ' ', 'b', 'c', '\0' };
376 const unsigned cbuf_size = sizeof cbuf / sizeof *cbuf;
377
378 unsigned iter = 0; // iteration counter
379
380 // iterate over all possible settings of the stream state
381 for (unsigned i = 0; i != nstates; ++i) {
382
383 // call readsome(..., j) to extract j characters
384 for (unsigned j = 0; j != cbuf_size - 1; ++j) {
385
386 // have underflow() fail after the `k-th' extraction
387 for (unsigned k = 0; k != j + 1; ++k) {
388
389 // return `l' from showmanyc(); -2 will throw
390 for (int l = -4; l != int (k); ++l) {
391
392 // if (0 == m), underflow() will throw an exception
393 // at `k-th' extraction, otherwise the function will
394 // return EOF
395 for (unsigned m = 0; m != 2; ++m, ++iter) {
396
397 // prevent causing underflow() to fail by
398 // returning EOF when in_avail() promised
399 // it wouldn't (by returning a value
400 // greater than the number of extractions
401 // underflow() will allow to succeed)
402 if (1U == m && int (k) < l)
403 continue;
404
405 test_readsome (cbuf, (Traits*)0,
406 cbuf_size, i, j, k, l, m);
407 }
408 }
409 }
410 }
411 }
412}
413
414
416static int opt_char;
417static int opt_wchar;
418static int opt_char_traits;
419static int opt_user_traits;
420
421
422static int
423run_test (int, char**)
424{
425 // introduce char_traits into scope
426 using namespace std;
427
428#undef TEST
429#define TEST(CharT, Traits) \
430 test_readsome ((CharT*)0, (Traits*)0, #CharT, #Traits)
431
432 if (rw_note (0 <= opt_char && 0 <= opt_char_traits, 0, __LINE__,
433 "basic_istream<char, char_traits<char>>::readsome() "
434 "tests disabled"))
435 TEST (char, char_traits<char>);
436
437 if (rw_note (0 <= opt_char && 0 <= opt_user_traits, 0, __LINE__,
438 "basic_istream<char, UserTraits<char>>::readsome() "
439 "tests disabled"))
440 TEST (char, UserTraits<char>);
441
442#ifndef _RWSTD_NO_WCHAR_T
443
444 if (rw_note (0 <= opt_wchar && 0 <= opt_char_traits, 0, __LINE__,
445 "basic_istream<wchar_t, char_traits<wchar_t>>::readsome() "
446 "tests disabled"))
447 TEST (wchar_t, char_traits<wchar_t>);
448
449 if (rw_note (0 <= opt_wchar && 0 <= opt_user_traits, 0, __LINE__,
450 "basic_istream<wchar_t, UserTraits<wchar_t>>::readsome() "
451 "tests disabled"))
452 TEST (wchar_t, UserTraits<wchar_t>);
453
454#endif // _RWSTD_NO_WCHAR_T
455
456 return 0;
457}
458
459
461int main (int argc, char *argv[])
462{
463 return rw_test (argc, argv, __FILE__,
464 "istream.unformatted",
465 "readsome",
466 run_test,
467 "|-char~ "
468 "|-wchar_t~ "
469 "|-char_traits~ "
470 "|-UserTraits~ ",
471 &opt_char,
472 &opt_wchar,
473 &opt_char_traits,
474 &opt_user_traits,
475 (void*)0 /* sentinel */);
476}
#define m
Definition 17.names.cpp:129
#define i
Definition 17.names.cpp:126
#define k
Definition 17.names.cpp:128
#define line
Definition 17.names.cpp:490
#define sb
Definition 17.names.cpp:542
#define buf
Definition 17.names.cpp:452
#define j
Definition 17.names.cpp:127
#define charT
Definition 17.names.cpp:456
#define s
int opt_wchar
int opt_char
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
std::char_traits< S > Traits
void test_readsome(const charT *cbuf, const Traits *, unsigned cbuf_size, unsigned i, unsigned j, unsigned k, int l, unsigned m)
const std::ios_base::iostate states[]
void memfun_info(int line, const char *cname, const char *tname)
#define TEST(CharT, Traits)
const unsigned nstates
#define main
int caught
#define _RWSTD_CONST_CAST(T, x)
Definition _defs.h:536
Definition json.h:5363
_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
_TEST_EXPORT int rw_fprintf(rw_file *, const char *,...)
Definition printf.cpp:3397
const charT * end_
const charT * pubeback() const
Base::int_type int_type
std::basic_streambuf< charT, Traits > Base
const charT * pubgptr() const
std::streamsize showmanyc()
int_type underflow()
Streambuf(const charT *gbeg, const charT *gend)
Base::traits_type traits_type
const charT * pubegptr() const