Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
24.istream.iterator.cpp
Go to the documentation of this file.
1
27#include <sstream> // for stringstream
28#include <iterator> // for istream_iterator
29
30#include <cstddef> // for ptrdiff_t
31
32#include <rw_char.h>
33#include <rw_printf.h>
34#include <rw_driver.h>
35
36
38// names of template parameters
39struct ParamNames {
40 const char *tname; // name of the T parameter
41 const char *tfmt; // rw_printf()-style format for T
42 const char *cname; // name of the CharT parameter
43 const char *trname; // name of the Traits parameter
44 const char *dname; // name of the Distance parameter
45};
46
47
48// format the template-id of the iterator
49void fmtnam (const ParamNames &pn)
50{
51 // omit names of unspecified (default) template arguments
52 const char* const id = pn.cname ? pn.trname ? pn.dname ?
53 "<%s, %s, %s, %s>" : "<%s, %s, %s>" : "<%s, %s>" : "<%s>";
54
55 rw_fprintf (0, "%{$ITER!:@}",
56 "istream_iterator%{@}",
57 id, pn.tname, pn.cname, pn.trname, pn.dname);
58}
59
60
62// for convenience
63template <class T, class CharT, class Traits, class Dist>
65
66
67// exercise istream_iterator ctors
68template <class T, class CharT, class Traits, class Dist>
70{
71 typedef std::istream_iterator<T, CharT, Traits, Dist> Iterator;
72 typedef std::basic_stringstream<CharT, Traits> StringStream;
73
74 const Iterator eos1;
75 const Iterator eos2;
76
77 // verify [reverse.iter], p3, i.e., that two end-of-istream
78 // always compare equal, and that no end-of-stream iterator
79 // compares equal to a non-end-of-stream iterator
80
81 fmtnam (params.names);
82
83 rw_assert (eos1 == eos2, 0, __LINE__,
84 "%{$ITER}::istream_iterator() == %{$ITER}::istream_iterator()");
85
86 StringStream strm1;
87
88 // make sure the stream object's locale contains the expected
89 // specialization of the num_get facet (in case CharT isn't
90 // char or wchar_t, or Traits isn't std::char_traits)
91 typedef std::istreambuf_iterator<CharT, Traits> StreambufIterator;
92 typedef std::num_get<CharT, StreambufIterator> NumGet;
93
94 if (false == std::has_facet<NumGet>(strm1.getloc ())) {
95 const std::locale loc (std::locale::classic (), new NumGet);
96 strm1.imbue (loc);
97 }
98
99 // insert a couple of items into the stream, one for each iterator
100 // below, to prevent the iterator ctor from creating an end-of-stream
101 // iterator (in case it doesn't delay extracting a value until it's
102 // needed)
103 strm1 << "1 2 ";
104
105 // verify [reverse.iter], p3, i.e., that two istream_iterators
106 // constructed from the same stream always compare equal
107 const Iterator iter1 (strm1);
108 const Iterator iter2 (strm1);
109
110 rw_assert (iter1 != eos1, 0, __LINE__,
111 "%{$ITER}::istream_iterator(basic_istream&) != "
112 "%{$ITER}()");
113
114 rw_assert (iter1 == iter2, 0, __LINE__,
115 "%{$ITER}::istream_iterator(basic_istream&) == "
116 "%{$ITER}::istream_iterator(basic_istream&)");
117
118 StringStream strm2;
119 strm2.imbue (strm1.getloc ());
120
121 strm2 << "2 ";
122
123 const Iterator iter3 (strm2);
124
125 rw_assert (iter3 != eos1, 0, __LINE__,
126 "%{$ITER}::istream_iterator(basic_istream&) != "
127 "%{$ITER}()");
128
129 // verify that iterators into different streams compare unequal
130 rw_assert (iter3 != iter1, 0, __LINE__,
131 "%{$ITER}::istream_iterator(basic_istream& [@%#p]) != "
132 "%{$ITER}::istream_iterator(basic_istream& [@%#p])",
133 &strm2, &strm1);
134}
135
136
138// worker to exercise operator*()
139template <class T, class CharT, class Traits, class Dist>
141 int line,
142 const char *input,
143 T expect,
144 bool is_eos,
145 int state)
146{
147 typedef std::istream_iterator<T, CharT, Traits, Dist> Iterator;
148 typedef std::basic_stringstream<CharT, Traits> StringStream;
149
150 fmtnam (params.names);
151
152 StringStream strm;
153
154 typedef std::istreambuf_iterator<CharT, Traits> StreambufIterator;
155 typedef std::num_get<CharT, StreambufIterator> NumGet;
156
157 if (false == std::has_facet<NumGet>(strm.getloc ())) {
158 const std::locale loc (std::locale::classic (), new NumGet);
159 strm.imbue (loc);
160 }
161
162 if (input && *input)
163 strm << input;
164
165 const Iterator eos;
166
167 const Iterator it (strm);
168
169 rw_assert (is_eos ^ (it != eos), 0, line,
170 "line %d: %{$ITER}::operator() != %{$ITER}()", __LINE__);
171
172 if (0 == (strm.rdstate () & (strm.badbit | strm.failbit))) {
173 // operator*() is defined only for non-eos iterators
174 // avoid calling it on a bad or failed stream too
175
176 const T val = *it;
177
178 rw_assert (val == expect, 0, line,
179 "line %d: %{$ITER}::operator*() == %{@}, got %{@}",
180 __LINE__, params.names.tfmt, expect, params.names.tfmt, val);
181 }
182
183 rw_assert (strm.rdstate () == state, 0, line,
184 "line %d: %{$ITER}::operator*(), rdstate() == %{Is}, got %{Is}",
185 __LINE__, state, strm.rdstate ());
186}
187
188
190// exercise operator*()
191template <class T, class CharT, class Traits, class Dist>
193{
194 // const int Bad = std::ios::badbit;
195 const int Eof = std::ios::eofbit;
196 const int Fail = std::ios::failbit;
197 const int Good = std::ios::goodbit;
198
199#undef TEST
200#define TEST(input, expect, is_eos, state) \
201 test_ops (params, __LINE__, input, T (expect), is_eos, state)
202
203 volatile T one = T (1);
204 volatile T zero = one - one;
205 volatile T two = one + one;
206
207 const bool is_char = sizeof (T) == sizeof (char);
208 const bool is_signed = zero - one < zero;
209 const bool is_exact = one / two == zero;
210
211 // see LWG issue 788
212 // an istream_iterator object becomes an end-of-stream iterator
213 // after a failed extraction (i.e., when the call to fail() on
214 // the associated stream returns true)
215
216 if (is_char) {
217
218 // +-- controlled sequence
219 // | +-- extracted value
220 // | | +-- iterator equal to EOS after extraction
221 // | | | +-- stream state after extraction
222 // | | | |
223 // V V V V
224 TEST ("", '\0', true, Eof | Fail);
225 TEST ("1", '1', false, Good);
226 TEST ("2", '2', false, Good);
227 }
228 else {
229 TEST ("", 0, true, Eof | Fail);
230 TEST ("1", 1, false, Eof);
231 TEST ("1 ", 1, false, Good);
232 TEST ("+1", 1, false, Eof);
233 TEST (" 1", 1, false, Eof);
234 TEST (" 1 ", 1, false, Good);
235 TEST (" +1", 1, false, Eof);
236 TEST ("2", 2, false, Eof);
237 TEST ("+2", 2, false, Eof);
238 TEST (" 2", 2, false, Eof);
239 TEST (" +2", 2, false, Eof);
240 TEST ("99", 99, false, Eof);
241 TEST ("+99", 99, false, Eof);
242 TEST (" 99", 99, false, Eof);
243 TEST (" +99", 99, false, Eof);
244
245 TEST ("+", 0, true, Eof | Fail);
246 TEST ("-", 0, true, Eof | Fail);
247 TEST (" +", 0, true, Eof | Fail);
248 TEST (" -", 0, true, Eof | Fail);
249 TEST ("++", 0, true, Fail);
250 TEST ("--", 0, true, Fail);
251 TEST (" ++", 0, true, Fail);
252 TEST (" --", 0, true, Fail);
253 TEST ("*", 0, true, Fail);
254 TEST (" *", 0, true, Fail);
255
256 if (is_signed) {
257 TEST ("-1", -1, false, Eof);
258 TEST (" -1", -1, false, Eof);
259 TEST ("-2", -2, false, Eof);
260 TEST (" -2", -2, false, Eof);
261 TEST ("-99", -99, false, Eof);
262 TEST (" -99", -99, false, Eof);
263 }
264
265 if (is_exact) {
266 TEST ("1.2", 1, false, Good);
267 TEST ("2.3 ", 2, false, Good);
268 TEST (" 3.4", 3, false, Good);
269 TEST (" +4.", 4, false, Good);
270 }
271 else {
272 TEST (".1", 0.1, false, Eof);
273 TEST ("+.2", 0.2, false, Eof);
274 TEST ("-.3", -0.3, false, Eof);
275 TEST (" +.4", 0.4, false, Eof);
276 TEST (" -.5", -0.5, false, Eof);
277 TEST ("1..", 1.0, false, Good);
278
279 TEST ("1.234", 1.234, false, Eof);
280 TEST ("+1.235", +1.235, false, Eof);
281 TEST ("-1.236", -1.236, false, Eof);
282 TEST (" +1.237", +1.237, false, Eof);
283 TEST (" -1.238", -1.238, false, Eof);
284 TEST ("1.239e1", 1.239e1, false, Eof);
285 TEST ("1.240e+1", 1.240e+1, false, Eof);
286 TEST ("-1.241e+2", -1.241e+2, false, Eof);
287 TEST ("-1.242e-3 ", -1.242e-3, false, Good);
288
289 TEST ("1.3e", 0, true, Eof | Fail);
290 TEST ("1.4e+", 0, true, Eof | Fail);
291 TEST ("1.5e-", 0, true, Eof | Fail);
292 TEST ("1.6e+ ", 0, true, Fail);
293 }
294 }
295}
296
297
300
301// dispatch to test_ctors to test_ops
302template <class T, class CharT, class Traits, class Dist>
304 const char *tname,
305 const char *tfmt,
306 const char *cname,
307 const char *trname,
308 const char *dname)
309{
310 const ParamNames names = { tname, tfmt, cname, trname, dname };
311 const TempParams<T, CharT, Traits, Dist> params = { names };
312
313 if (TestCtors == id) {
314 test_ctors (params);
315 }
316 else if (TestOps == id) {
317 test_ops (params);
318 }
319}
320
321
330
331
332// exercise different specializations of T
333template <class CharT, class Traits, class Dist>
335 const char *cname,
336 const char *trname,
337 const char *dname)
338{
339#undef TEST
340#define TEST(T, fmt) \
341 if (opt_ ## T) \
342 do_test<T, CharT, Traits, Dist>(id, #T, fmt, cname, trname, dname)
343
344 // cannot instantiate basic_istream<CharT>::operator>>(char&)
345 // for any CharT other than char
346 // TEST (char, "%{hhi}");
347
348 TEST (short, "%hi");
349 TEST (int, " %i");
350 TEST (long, "%li");
351 TEST (double, "%g");
352}
353
354
355
357// exercise different specializations of Distance
358template <class CharT, class Traits>
359void do_test (TestId id, const char *cname, const char *trname)
360{
361 do_test<CharT, Traits, short>(id, cname, trname, "short");
362 do_test<CharT, Traits, std::ptrdiff_t>(id, cname, trname, 0);
363}
364
365
367static int
368run_test (int, char*[])
369{
370 static const TestId test_ids [] = { TestCtors, TestOps };
371
372 if (opt_char < 0)
373 rw_note (0, 0, __LINE__, "tests of char specialization disabled");
374
375 if (opt_wchar_t < 0)
376 rw_note (0, 0, __LINE__, "tests of wchar_t specialization disabled");
377
378 if (opt_UserTraits < 0)
379 rw_note (0, 0, __LINE__, "tests of UserTraits specialization disabled");
380
381 typedef std::char_traits<char> Traits;
382 typedef UserTraits<char> UsrTraits;
383
384 for (unsigned i = 0; i != sizeof test_ids / sizeof *test_ids; ++i) {
385
386 const TestId id = test_ids [i];
387
388 if (0 <= opt_char) {
389
390 // call these helper functions directly to avoid instantiating
391 // basic_istream<CharT>::operator>>(char&) on any CharT other
392 // than char
393 do_test<char, char, Traits, std::ptrdiff_t>(id, "char", "%{hhi}",
394 0, 0, 0);
395
396 if (0 <= opt_UserTraits)
397 do_test<char, char, UsrTraits, std::ptrdiff_t>(id, "char",
398 "%{hhi}", 0, "UserTraits<char>", "std::ptrdiff_t");
399
400 do_test<char, Traits>(id, 0, 0);
401
402 if (0 <= opt_UserTraits)
403 do_test<char, UsrTraits>(id, "char", "UserTraits<char>");
404 }
405
406#ifndef _RWSTD_NO_WCHAR_T
407
408 if (0 <= opt_wchar_t) {
409
410 typedef std::char_traits<wchar_t> WTraits;
411 typedef UserTraits<wchar_t> WUsrTraits;
412
413 do_test<wchar_t, WTraits>(id, 0, 0);
414
415 if (0 <= opt_UserTraits)
416 do_test<wchar_t, WUsrTraits>(id, "wchar_t",
417 "UserTraits<wchar_t>");
418
419 }
420
421#endif // _RWSTD_NO_WCHAR_T
422
423 }
424
425 return 0;
426}
427
428
429
431int main (int argc, char *argv[])
432{
433 return rw_test (argc, argv, __FILE__,
434 "lib.istream.iterator",
435 0 /* no comment */,
436 run_test,
437 "|-char~ "
438 "|-wchar_t~ "
439 "|-UserTraits~ "
440 "|-short~ "
441 "|-int~ "
442 "|-long~ "
443 "|-double~ ",
444 &opt_char,
447 &opt_short,
448 &opt_int,
449 &opt_long,
450 &opt_double,
451 (void*)0 /* sentinel */);
452}
InputIter< UserClass > Iterator
#define i
Definition 17.names.cpp:126
#define T
Definition 17.names.cpp:163
#define line
Definition 17.names.cpp:490
#define loc
Definition 17.names.cpp:492
#define Traits
Definition 17.names.cpp:556
#define strm
Definition 17.names.cpp:549
#define val
Definition 17.names.cpp:570
void test_ctors()
int opt_UserTraits
int opt_wchar_t
void fmtnam(const ParamNames &pn)
void test_ops(const TempParams< T, CharT, Traits, Dist > &params, int line, const char *input, T expect, bool is_eos, int state)
int opt_double
#define TEST(input, expect, is_eos, state)
int opt_short
void do_test(int line, const char *src, std::size_t resoff, ForwardIterator dummy_iter, const T *, const char *predname)
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define main
volatile int one
Definition LIMITS.cpp:61
volatile int two
Definition LIMITS.cpp:62
volatile int zero
Definition LIMITS.cpp:60
_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_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 char * cname
const char * trname
const char * dname
const char * tfmt
const char * tname