1#include <limits>
2
3#if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS)
4#  include <iomanip>
5#  include <string>
6#  include <sstream>
7#  include <cstdio>
8/*
9#  include <iostream>
10#  include <ieee754.h>
11*/
12
13#  include "complete_digits.h"
14#  include "cppunit/cppunit_proxy.h"
15
16#  if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
17using namespace std;
18#  endif
19
20//
21// TestCase class
22//
23class NumPutGetTest : public CPPUNIT_NS::TestCase
24{
25  CPPUNIT_TEST_SUITE(NumPutGetTest);
26#  if defined (__BORLANDC__)
27  /* Ignore FPU exceptions, set FPU precision to 64 bits */
28  unsigned int _float_control_word = _control87(0, 0);
29  _control87(PC_64|MCW_EM|IC_AFFINE, MCW_PC|MCW_EM|MCW_IC);
30#  endif
31  CPPUNIT_TEST(num_put_float);
32  CPPUNIT_TEST(num_put_integer);
33  CPPUNIT_TEST(num_get_float);
34  CPPUNIT_TEST(num_get_integer);
35  CPPUNIT_TEST(inhex);
36  CPPUNIT_TEST(pointer);
37  CPPUNIT_TEST(fix_float_long);
38  CPPUNIT_TEST(custom_numpunct);
39#  if defined (__BORLANDC__)
40  /* Reset floating point control word */
41  _clear87();
42  _control87(_float_control_word, MCW_PC|MCW_EM|MCW_IC);
43#  endif
44  CPPUNIT_TEST_SUITE_END();
45
46private:
47  void num_put_float();
48  void num_put_integer();
49  void num_get_float();
50  void num_get_integer();
51  void inhex();
52  void pointer();
53  void fix_float_long();
54  void custom_numpunct();
55
56  static bool check_float(float val, float ref)
57  {
58    float epsilon = numeric_limits<float>::epsilon();
59    return val <= ref + epsilon && val >= ref - epsilon;
60  }
61
62  static bool check_double(double val, double ref)
63  {
64    double epsilon = numeric_limits<double>::epsilon();
65    return val <= ref + epsilon && val >= ref - epsilon;
66  }
67
68  static string reset_stream(ostringstream &ostr)
69  {
70    string tmp = ostr.str();
71    ostr.str("");
72    return tmp;
73  }
74
75#if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES)
76  template <class F>
77  void check_get_float( F v )
78  {
79    F in_val_d = v;
80    typedef numeric_limits<F> limits;
81    {
82      stringstream str;
83
84      str << "1E+" << limits::max_exponent10;
85
86      str >> in_val_d;
87      CPPUNIT_ASSERT(!str.fail());
88      CPPUNIT_ASSERT(str.eof());
89      CPPUNIT_CHECK( in_val_d == in_val_d );
90      CPPUNIT_CHECK( in_val_d != limits::infinity() );
91    }
92    {
93      stringstream str;
94
95      str << "-1E+" << limits::max_exponent10;
96
97      str >> in_val_d;
98      CPPUNIT_ASSERT(!str.fail());
99      CPPUNIT_ASSERT(str.eof());
100      CPPUNIT_CHECK( in_val_d == in_val_d );
101      CPPUNIT_CHECK( in_val_d != -limits::infinity() );
102    }
103    {
104      stringstream str;
105
106      str << "1E" << limits::min_exponent10;
107
108      str >> in_val_d;
109      CPPUNIT_ASSERT(!str.fail());
110      CPPUNIT_ASSERT(str.eof());
111      CPPUNIT_CHECK( in_val_d == in_val_d );
112      CPPUNIT_CHECK( in_val_d != F(0.0) );
113    }
114    {
115      stringstream str;
116
117      str << "1E+" << (limits::max_exponent10 + 1);
118
119      str >> in_val_d;
120      CPPUNIT_ASSERT(!str.fail());
121      CPPUNIT_ASSERT(str.eof());
122      CPPUNIT_CHECK( in_val_d == in_val_d );
123      CPPUNIT_CHECK( in_val_d == limits::infinity() );
124    }
125    {
126      stringstream str;
127
128      str << "-1E+" << (limits::max_exponent10 + 1);
129
130      str >> in_val_d;
131      CPPUNIT_ASSERT(!str.fail());
132      CPPUNIT_ASSERT(str.eof());
133      CPPUNIT_CHECK( in_val_d == in_val_d );
134      CPPUNIT_CHECK( in_val_d == -limits::infinity() );
135    }
136    {
137      stringstream str;
138
139      str << "1E" << (limits::min_exponent10 - 1);
140
141      str >> in_val_d;
142      CPPUNIT_ASSERT(!str.fail());
143      CPPUNIT_ASSERT(str.eof());
144      CPPUNIT_CHECK( in_val_d == in_val_d );
145      CPPUNIT_CHECK( in_val_d >= F(0.0) && in_val_d <= limits::min() );
146    }
147#if !defined (__MINGW32__)
148    {
149      stringstream str;
150
151      str << limits::max();
152
153      CPPUNIT_ASSERT(!str.fail());
154      CPPUNIT_CHECK( str.str() != "inf" );
155      CPPUNIT_CHECK( str.str() != "-inf" );
156      CPPUNIT_CHECK( str.str() != "nan" );
157      CPPUNIT_CHECK( str.str() != "-nan" );
158      //CPPUNIT_MESSAGE( str.str().c_str() );
159
160      //str.str("");
161      //str << limits::max_exponent10;
162      //CPPUNIT_MESSAGE( str.str().c_str() );
163
164      str >> in_val_d;
165
166      CPPUNIT_ASSERT(!str.fail());
167      CPPUNIT_ASSERT(str.eof());
168      CPPUNIT_CHECK( in_val_d == in_val_d );
169      CPPUNIT_CHECK( in_val_d != limits::infinity() );
170    }
171    {
172      stringstream str;
173
174      str << fixed << limits::max();
175
176      CPPUNIT_ASSERT(!str.fail());
177      CPPUNIT_CHECK( str.str() != "inf" );
178      CPPUNIT_CHECK( str.str() != "-inf" );
179      CPPUNIT_CHECK( str.str() != "nan" );
180      CPPUNIT_CHECK( str.str() != "-nan" );
181      //CPPUNIT_MESSAGE( str.str().c_str() );
182
183      //str.str("");
184      //str << limits::max_exponent10;
185      //CPPUNIT_MESSAGE( str.str().c_str() );
186
187      str >> in_val_d;
188
189      CPPUNIT_ASSERT(!str.fail());
190      CPPUNIT_ASSERT(str.eof());
191      CPPUNIT_CHECK( in_val_d == in_val_d );
192      CPPUNIT_CHECK( in_val_d != limits::infinity() );
193    }
194    {
195      stringstream str;
196
197      str << scientific << setprecision(50) << limits::max();
198
199      CPPUNIT_ASSERT(!str.fail());
200      CPPUNIT_CHECK( str.str() != "inf" );
201      CPPUNIT_CHECK( str.str() != "-inf" );
202      CPPUNIT_CHECK( str.str() != "nan" );
203      CPPUNIT_CHECK( str.str() != "-nan" );
204      //CPPUNIT_MESSAGE( str.str().c_str() );
205
206      //str.str("");
207      //str << limits::max_exponent10;
208      //CPPUNIT_MESSAGE( str.str().c_str() );
209
210      str >> in_val_d;
211
212      CPPUNIT_ASSERT(!str.fail());
213      CPPUNIT_ASSERT(str.eof());
214      CPPUNIT_CHECK( in_val_d == in_val_d );
215      CPPUNIT_CHECK( in_val_d != limits::infinity() );
216    }
217#endif
218    {
219      stringstream str;
220
221      str << limits::infinity();
222
223      CPPUNIT_ASSERT( !str.fail() );
224      CPPUNIT_ASSERT( !limits::has_infinity || str.str() == "inf" );
225    }
226    {
227      stringstream str;
228
229      str << -limits::infinity();
230
231      CPPUNIT_ASSERT( !str.fail() );
232      CPPUNIT_ASSERT( !limits::has_infinity || str.str() == "-inf" );
233    }
234    {
235      stringstream str;
236
237      str << limits::quiet_NaN();
238
239      CPPUNIT_ASSERT( !str.fail() );
240      CPPUNIT_ASSERT( !limits::has_quiet_NaN || str.str() == "nan" );
241    }
242    {
243      stringstream str;
244
245      str << "0." << string(limits::max_exponent10, '0') << "1e" << (limits::max_exponent10 + 1);
246      CPPUNIT_ASSERT( !str.fail() );
247
248      str >> in_val_d;
249      CPPUNIT_ASSERT( !str.fail() );
250      CPPUNIT_ASSERT( str.eof() );
251      CPPUNIT_CHECK( in_val_d == 1 );
252    }
253    {
254      stringstream str;
255
256      str << "1" << string(-(limits::min_exponent10 - 1), '0') << "e" << (limits::min_exponent10 - 1);
257      CPPUNIT_ASSERT( !str.fail() );
258
259      str >> in_val_d;
260      CPPUNIT_ASSERT( !str.fail() );
261      CPPUNIT_ASSERT( str.eof() );
262      CPPUNIT_CHECK( in_val_d == 1 );
263    }
264#  if defined (_STLPORT_VERSION) && (_STLPORT_VERSION >= 0x530)
265    // The following tests are showing that simply changing stream
266    // precision lead to different result. Do not seems to be a real
267    // problem, simply rounding approximation but additional study should
268    // be done after 5.2 release.
269    {
270      stringstream str;
271      str << setprecision(limits::digits10 + 2) << limits::max();
272
273      CPPUNIT_MESSAGE(str.str().c_str());
274      CPPUNIT_ASSERT( !str.fail() );
275
276      F val;
277      str >> val;
278
279      CPPUNIT_ASSERT( !str.fail() );
280      CPPUNIT_ASSERT( limits::infinity() > val );
281    }
282    {
283      stringstream str;
284      str << setprecision(limits::digits10 + 1) << limits::max();
285
286      CPPUNIT_MESSAGE(str.str().c_str());
287      CPPUNIT_ASSERT( !str.fail() );
288
289      F val;
290      str >> val;
291
292      CPPUNIT_ASSERT( !str.fail() );
293      CPPUNIT_ASSERT( limits::infinity() > val );
294    }
295#  endif
296  }
297#else
298#  define __check_get_float( F ) \
299  void check_get_float( F v ) \
300  { \
301    F in_val_d = v; \
302    { \
303      stringstream str; \
304 \
305      str << "1E+" << numeric_limits<F>::max_exponent10; \
306 \
307      str >> in_val_d; \
308      CPPUNIT_ASSERT(!str.fail()); \
309      CPPUNIT_ASSERT(str.eof()); \
310      CPPUNIT_CHECK( in_val_d == in_val_d ); \
311      CPPUNIT_CHECK( in_val_d != numeric_limits<F>::infinity() ); \
312    } \
313    { \
314      stringstream str; \
315 \
316      str << "-1E+" << numeric_limits<F>::max_exponent10; \
317 \
318      str >> in_val_d; \
319      CPPUNIT_ASSERT(!str.fail()); \
320      CPPUNIT_ASSERT(str.eof()); \
321      CPPUNIT_CHECK( in_val_d == in_val_d ); \
322      CPPUNIT_CHECK( in_val_d != -numeric_limits<F>::infinity() ); \
323    } \
324    { \
325      stringstream str; \
326 \
327      str << "1E" << numeric_limits<F>::min_exponent10; \
328 \
329      str >> in_val_d; \
330      CPPUNIT_ASSERT(!str.fail()); \
331      CPPUNIT_ASSERT(str.eof()); \
332      CPPUNIT_CHECK( in_val_d == in_val_d ); \
333      CPPUNIT_CHECK( in_val_d != F(0.0) ); \
334    } \
335    { \
336      stringstream str; \
337 \
338      str << "1E+" << (numeric_limits<F>::max_exponent10 + 1); \
339 \
340      str >> in_val_d; \
341      CPPUNIT_ASSERT(!str.fail()); \
342      CPPUNIT_ASSERT(str.eof()); \
343      CPPUNIT_CHECK( in_val_d == in_val_d ); \
344      CPPUNIT_CHECK( in_val_d == numeric_limits<F>::infinity() ); \
345    } \
346    { \
347      stringstream str; \
348 \
349      str << "-1E+" << (numeric_limits<F>::max_exponent10 + 1); \
350 \
351      str >> in_val_d; \
352      CPPUNIT_ASSERT(!str.fail()); \
353      CPPUNIT_ASSERT(str.eof()); \
354      CPPUNIT_CHECK( in_val_d == in_val_d ); \
355      CPPUNIT_CHECK( in_val_d == -numeric_limits<F>::infinity() ); \
356    } \
357    { \
358      stringstream str; \
359 \
360      str << "1E" << (numeric_limits<F>::min_exponent10 - 1); \
361 \
362      str >> in_val_d; \
363      CPPUNIT_ASSERT(!str.fail()); \
364      CPPUNIT_ASSERT(str.eof()); \
365      CPPUNIT_CHECK( in_val_d == in_val_d ); \
366      CPPUNIT_CHECK( in_val_d >= F(0.0) && in_val_d <= numeric_limits<F>::min() ); \
367    } \
368  }
369
370  __check_get_float( float )
371  __check_get_float( double )
372#  if !defined (STLPORT) || !defined (_STLP_NO_LONG_DOUBLE)
373  __check_get_float( long double )
374#  endif
375#  undef __check_get_float
376#endif // _STLP_NO_MEMBER_TEMPLATES
377};
378
379CPPUNIT_TEST_SUITE_REGISTRATION(NumPutGetTest);
380
381#if defined (_MSC_VER)
382#  pragma warning (disable : 4056)
383#  pragma warning (disable : 4756)
384#endif
385
386//
387// tests implementation
388//
389void NumPutGetTest::num_put_float()
390{
391  {
392    string output, digits;
393
394    {
395      ostringstream ostr;
396      ostr << 1.23457e+17f;
397      CPPUNIT_ASSERT(ostr.good());
398      output = reset_stream(ostr);
399      digits = "17";
400      complete_digits(digits);
401      CPPUNIT_CHECK(output == string("1.23457e+") + digits );
402    }
403
404    {
405      ostringstream ostr;
406      ostr << setprecision(200) << 1.23457e+17f;
407      CPPUNIT_ASSERT(ostr.good());
408      output = reset_stream(ostr);
409      CPPUNIT_CHECK( output.size() < 200 );
410    }
411
412    {
413      ostringstream ostr;
414      ostr << setprecision(200) << numeric_limits<float>::min();
415      CPPUNIT_ASSERT(ostr.good());
416      output = reset_stream(ostr);
417      CPPUNIT_CHECK( output.size() < 200 );
418    }
419
420    {
421      ostringstream ostr;
422      ostr << fixed << 1.23457e+17f;
423      CPPUNIT_ASSERT(ostr.good());
424      output = reset_stream(ostr);
425      CPPUNIT_CHECK(output.size() == 25);
426      CPPUNIT_CHECK(output.substr(0, 5) == "12345");
427      CPPUNIT_CHECK(output.substr(18) == ".000000");
428    }
429
430    {
431      ostringstream ostr;
432      ostr << fixed << showpos << 1.23457e+17f;
433      CPPUNIT_ASSERT(ostr.good());
434      output = reset_stream(ostr);
435      CPPUNIT_CHECK(output.size() == 26);
436      CPPUNIT_CHECK(output.substr(0, 6) == "+12345");
437      CPPUNIT_CHECK(output.substr(19) == ".000000");
438    }
439
440    {
441      ostringstream ostr;
442      ostr << fixed << showpos << setprecision(100) << 1.23457e+17f;
443      CPPUNIT_ASSERT(ostr.good());
444      output = reset_stream(ostr);
445      CPPUNIT_CHECK(output.size() == 120);
446      CPPUNIT_CHECK(output.substr(0, 6) == "+12345");
447      CPPUNIT_CHECK(output.substr(19) == ".0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" );
448    }
449
450    {
451      ostringstream ostr;
452      ostr << scientific << setprecision(8) << 0.12345678f;
453      CPPUNIT_ASSERT(ostr.good());
454      output = reset_stream(ostr);
455      digits = "1";
456      complete_digits(digits);
457      CPPUNIT_CHECK(output == string("1.23456780e-") + digits );
458    }
459
460    {
461      ostringstream ostr;
462      ostr << fixed << setprecision(8) << setw(30) << setfill('0') << 0.12345678f;
463      CPPUNIT_ASSERT(ostr.good());
464      output = reset_stream(ostr);
465      CPPUNIT_CHECK(output == "000000000000000000000.12345678");
466    }
467
468    {
469      ostringstream ostr;
470      ostr << fixed << showpos << setprecision(8) << setw(30) << setfill('0') << 0.12345678f;
471      CPPUNIT_ASSERT(ostr.good());
472      output = reset_stream(ostr);
473      CPPUNIT_CHECK(output == "0000000000000000000+0.12345678");
474    }
475
476    {
477      ostringstream ostr;
478      ostr << fixed << showpos << setprecision(8) << setw(30) << left << setfill('0') << 0.12345678f;
479      CPPUNIT_ASSERT(ostr.good());
480      output = reset_stream(ostr);
481      CPPUNIT_CHECK(output == "+0.123456780000000000000000000");
482    }
483
484    {
485      ostringstream ostr;
486      ostr << fixed << showpos << setprecision(8) << setw(30) << internal << setfill('0') << 0.12345678f;
487      CPPUNIT_ASSERT(ostr.good());
488      output = reset_stream(ostr);
489      CPPUNIT_CHECK(output == "+00000000000000000000.12345678");
490    }
491
492    {
493      ostringstream ostr;
494      ostr << fixed << showpos << setprecision(100) << 1.234567e+17;
495      CPPUNIT_ASSERT(ostr.good());
496      output = reset_stream(ostr);
497      CPPUNIT_CHECK(output.size() == 120);
498      CPPUNIT_CHECK(output.substr(0, 6) == "+12345");
499      CPPUNIT_CHECK(output.substr(19) == ".0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" );
500    }
501
502#if !defined (STLPORT) || !defined (_STLP_NO_LONG_DOUBLE)
503    {
504      ostringstream ostr;
505      ostr << fixed << showpos << setprecision(100) << 1.234567e+17l;
506      CPPUNIT_ASSERT(ostr.good());
507      output = reset_stream(ostr);
508      CPPUNIT_CHECK(output.size() == 120);
509      CPPUNIT_CHECK(output.substr(0, 6) == "+12345");
510      CPPUNIT_CHECK(output.substr(19) == ".0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" );
511    }
512#endif
513
514    {
515      ostringstream ostr;
516      ostr << scientific << setprecision(50) << 0.0;
517      CPPUNIT_ASSERT(ostr.good());
518      output = reset_stream(ostr);
519      CPPUNIT_CHECK( output == "0.00000000000000000000000000000000000000000000000000e+00" );
520    }
521    {
522      ostringstream ostr;
523      ostr << fixed << setprecision(100) << numeric_limits<float>::max();
524      CPPUNIT_ASSERT(ostr.good());
525      output = reset_stream(ostr);
526      //CPPUNIT_MESSAGE( output.c_str() );
527    }
528
529    {
530      ostringstream ostr;
531      ostr << setprecision(100) << numeric_limits<double>::max();
532      CPPUNIT_ASSERT(ostr.good());
533      output = reset_stream(ostr);
534      //CPPUNIT_MESSAGE( output.c_str() );
535    }
536
537#if !defined (STLPORT) || !defined (_STLP_NO_LONG_DOUBLE)
538    {
539      ostringstream ostr;
540      ostr << setprecision(100) << numeric_limits<long double>::max();
541      CPPUNIT_ASSERT(ostr.good());
542      output = reset_stream(ostr);
543      //CPPUNIT_MESSAGE( output.c_str() );
544    }
545#endif
546
547    //{
548    //  ostringstream ostr;
549    //  ostr << setprecision(-numeric_limits<float>::min_exponent10 + numeric_limits<float>::digits10 + 9) << numeric_limits<float>::min();
550    //  CPPUNIT_ASSERT(ostr.good());
551    //  output = reset_stream(ostr);
552    //  //CPPUNIT_MESSAGE( output.c_str() );
553    //}
554
555    //{
556    //  ostringstream ostr;
557    //  ostr << setprecision(-numeric_limits<double>::min_exponent10 + numeric_limits<double>::digits10) << numeric_limits<double>::min();
558    //  CPPUNIT_ASSERT(ostr.good());
559    //  output = reset_stream(ostr);
560    //  //CPPUNIT_MESSAGE( output.c_str() );
561    //}
562
563//#if !defined (STLPORT) || !defined (_STLP_NO_LONG_DOUBLE)
564//    {
565//      ostringstream ostr;
566//      ostr << setprecision(-numeric_limits<long double>::min_exponent10 + numeric_limits<long double>::digits10) << numeric_limits<long double>::min();
567//      CPPUNIT_ASSERT(ostr.good());
568//      output = reset_stream(ostr);
569//      CPPUNIT_MESSAGE( output.c_str() );
570//    }
571//#endif
572  }
573
574  {
575    ostringstream str;
576
577    str.setf(ios::fixed, ios::floatfield);
578    str << 1.0e+5;
579    // cerr << str.str() << endl;
580    CPPUNIT_CHECK( str.str() == "100000.000000" );
581
582    reset_stream(str);
583    str.precision(0);
584    str << 1.0e+5;
585    CPPUNIT_CHECK( str.str() == "100000" );
586
587    reset_stream(str);
588    str.precision(4);
589    str << 1.0e+5;
590    CPPUNIT_CHECK( str.str() == "100000.0000" );
591
592    reset_stream(str);
593    str.precision(0);
594    str << 1.0e+83;
595    CPPUNIT_CHECK( str.str().size() == 84 );
596    //printf("\nC result: %.0f\n", 1.0e+83);
597    //CPPUNIT_MESSAGE( str.str().c_str() );
598    //CPPUNIT_CHECK( str.str() == "100000000000000000000000000000000000000000000000000000000000000000000000000000000000" );
599
600    // cerr.setf(ios::fixed, ios::floatfield);
601    // cerr << DBL_MAX << endl;
602    // cerr << 1.0e+37 << endl;
603  }
604}
605
606#define CHECK_COMPLETE(type, val, base, showbase, showpos, casing, width, adjust, expected) \
607{ \
608  type tmp = val; \
609  ostringstream ostr; \
610  ostr << base << showbase << showpos << casing << setw(width) << adjust << tmp; \
611  CPPUNIT_CHECK( ostr.str() == expected ); \
612}
613
614#define CHECK(type, val, base, expected) \
615  CHECK_COMPLETE(type, val, base, noshowbase, noshowpos, nouppercase, 0, right, expected)
616
617void NumPutGetTest::num_put_integer()
618{
619  //octal outputs
620  {
621    CHECK(short, 0, oct, "0")
622    CHECK(short, 1, oct, "1")
623    CHECK(short, 12345, oct, "30071")
624    if (sizeof(short) == 2) {
625      CHECK(short, -1, oct, "177777")
626      CHECK(short, -12345, oct, "147707")
627    }
628
629    CHECK(unsigned short, 0, oct, "0")
630    CHECK(unsigned short, 12345, oct, "30071")
631
632    CHECK(int, 0, oct, "0")
633    CHECK(int, 12345678, oct, "57060516")
634    if (sizeof(int) == 4) {
635      CHECK(int, -1, oct, "37777777777")
636      CHECK(int, -12345678, oct, "37720717262")
637    }
638
639    CHECK(unsigned int, 0, oct, "0")
640    CHECK(unsigned int, 12345678, oct, "57060516")
641
642    CHECK(long, 0, oct, "0")
643    CHECK(long, 12345678, oct, "57060516")
644    if (sizeof(long) == 4) {
645      CHECK(long, -1, oct, "37777777777")
646      CHECK(long, -12345678, oct, "37720717262")
647    }
648
649    CHECK(unsigned long, 0, oct, "0")
650    CHECK(unsigned long, 12345678, oct, "57060516")
651
652#if defined (STLPORT) && defined (_STLP_LONG_LONG)
653    CHECK(_STLP_LONG_LONG, 0, oct, "0")
654    CHECK(_STLP_LONG_LONG, 12345678, oct, "57060516")
655    if (sizeof(_STLP_LONG_LONG) == 8) {
656      CHECK(_STLP_LONG_LONG, -1, oct, "1777777777777777777777")
657      CHECK(_STLP_LONG_LONG, -12345678, oct, "1777777777777720717262")
658    }
659
660    CHECK(unsigned _STLP_LONG_LONG, 0, oct, "0")
661    CHECK(unsigned _STLP_LONG_LONG, 12345678, oct, "57060516")
662#endif
663
664    //Even with showbase, 0 value gives "0" (see printf documentation)
665    CHECK_COMPLETE(short, 0, oct, showbase, noshowpos, nouppercase, 0, right, "0")
666    CHECK_COMPLETE(short, 0, oct, showbase, showpos, nouppercase, 6, right, "     0")
667
668    CHECK_COMPLETE(short, 1, oct, showbase, noshowpos, nouppercase, 6, right, "    01")
669    CHECK_COMPLETE(short, 1, oct, showbase, noshowpos, nouppercase, 6, left, "01    ")
670    CHECK_COMPLETE(short, 1, oct, showbase, showpos, nouppercase, 6, internal, "    01")
671  }
672
673  //decimal outputs
674  {
675    CHECK(short, 0, dec, "0")
676    CHECK(short, -1, dec, "-1")
677    CHECK(short, 12345, dec, "12345")
678    CHECK(short, -12345, dec, "-12345")
679
680    CHECK(unsigned short, 0, dec, "0")
681    CHECK(unsigned short, 12345, dec, "12345")
682
683    CHECK(int, 0, dec, "0")
684    CHECK(int, -1, dec, "-1")
685    CHECK(int, 12345678, dec, "12345678")
686    CHECK(int, -12345678, dec, "-12345678")
687
688    CHECK(unsigned int, 0, dec, "0")
689    CHECK(unsigned int, 12345678, dec, "12345678")
690
691    CHECK(long, 0, dec, "0")
692    CHECK(long, -1, dec, "-1")
693    CHECK(long, 12345678, dec, "12345678")
694    CHECK(long, -12345678, dec, "-12345678")
695
696    CHECK(unsigned long, 0, dec, "0")
697    CHECK(unsigned long, 12345678, dec, "12345678")
698#if defined (STLPORT) && defined (_STLP_LONG_LONG)
699    CHECK(_STLP_LONG_LONG, 0, dec, "0")
700    CHECK(_STLP_LONG_LONG, -1, dec, "-1")
701    CHECK(_STLP_LONG_LONG, 12345678, dec, "12345678")
702    CHECK(_STLP_LONG_LONG, -12345678, dec, "-12345678")
703
704    CHECK(unsigned _STLP_LONG_LONG, 0, dec, "0")
705    CHECK(unsigned _STLP_LONG_LONG, 12345678, dec, "12345678")
706#endif
707
708    CHECK_COMPLETE(short, 0, dec, showbase, showpos, nouppercase, 0, right, "+0")
709    CHECK_COMPLETE(short, 0, dec, showbase, showpos, nouppercase, 6, right, "    +0")
710    CHECK_COMPLETE(short, 1, dec, showbase, showpos, nouppercase, 6, right, "    +1")
711    CHECK_COMPLETE(short, 1, dec, showbase, showpos, nouppercase, 6, left, "+1    ")
712    CHECK_COMPLETE(short, 1, dec, showbase, showpos, nouppercase, 6, internal, "+    1")
713  }
714
715  //hexadecimal outputs
716  {
717    CHECK(short, 0, hex, "0")
718    CHECK(short, 12345, hex, "3039")
719    if (sizeof(short) == 2) {
720      CHECK(short, -1, hex, "ffff")
721      CHECK(short, -12345, hex, "cfc7")
722    }
723
724    CHECK(unsigned short, 0, hex, "0")
725    CHECK(unsigned short, 12345, hex, "3039")
726
727    CHECK(int, 0, hex, "0")
728    CHECK(int, 12345678, hex, "bc614e")
729    if (sizeof(int) == 4) {
730      CHECK(int, -1, hex, "ffffffff")
731      CHECK(int, -12345678, hex, "ff439eb2")
732    }
733
734    CHECK(unsigned int, 0, hex, "0")
735    CHECK(unsigned int, 12345678, hex, "bc614e")
736
737    CHECK(long, 0, hex, "0")
738    CHECK(long, 12345678, hex, "bc614e")
739    if (sizeof(long) == 4) {
740      CHECK(long, -1, hex, "ffffffff")
741      CHECK(long, -12345678, hex, "ff439eb2")
742    }
743
744    CHECK(unsigned long, 0, hex, "0")
745    CHECK(unsigned long, 12345678, hex, "bc614e")
746#if defined (STLPORT) && defined (_STLP_LONG_LONG)
747    CHECK(_STLP_LONG_LONG, 0, hex, "0")
748    CHECK(_STLP_LONG_LONG, 12345678, hex, "bc614e")
749    if (sizeof(_STLP_LONG_LONG) == 8) {
750      CHECK(_STLP_LONG_LONG, -1, hex, "ffffffffffffffff")
751      CHECK(_STLP_LONG_LONG, -12345678, hex, "ffffffffff439eb2")
752    }
753
754    CHECK(unsigned _STLP_LONG_LONG, 0, hex, "0")
755    CHECK(unsigned _STLP_LONG_LONG, 12345678, hex, "bc614e")
756#endif
757
758    //Even with showbase, 0 value gives "0" output (see printf documentation)
759    CHECK_COMPLETE(short, 0, hex, showbase, showpos, nouppercase, 0, right, "0")
760    CHECK_COMPLETE(short, 0, hex, showbase, noshowpos, nouppercase, 6, right, "     0")
761    CHECK_COMPLETE(short, 0, hex, showbase, noshowpos, nouppercase, 6, internal, "     0")
762
763    CHECK_COMPLETE(short, 1, hex, showbase, noshowpos, nouppercase, 6, right, "   0x1")
764    CHECK_COMPLETE(short, 1, hex, showbase, noshowpos, nouppercase, 6, left, "0x1   ")
765    CHECK_COMPLETE(short, 1, hex, showbase, noshowpos, nouppercase, 6, internal, "0x   1")
766    CHECK_COMPLETE(short, 1, hex, showbase, noshowpos, uppercase, 6, left, "0X1   ")
767    CHECK_COMPLETE(short, 1, hex, showbase, showpos, uppercase, 6, internal, "0X   1")
768  }
769}
770
771void NumPutGetTest::num_get_float()
772{
773  float in_val;
774
775  istringstream istr;
776
777  istr.str("1.2345");
778  istr >> in_val;
779  CPPUNIT_ASSERT(!istr.fail());
780  CPPUNIT_ASSERT(istr.eof());
781  CPPUNIT_ASSERT(check_float(in_val, 1.2345f));
782  istr.clear();
783
784  istr.str("-1.2345");
785  istr >> in_val;
786  CPPUNIT_ASSERT(!istr.fail());
787  CPPUNIT_ASSERT(istr.eof());
788  CPPUNIT_ASSERT(check_float(in_val, -1.2345f));
789  istr.clear();
790
791  istr.str("+1.2345");
792  istr >> in_val;
793  CPPUNIT_ASSERT(!istr.fail());
794  CPPUNIT_ASSERT(check_float(in_val, 1.2345f));
795  istr.clear();
796
797  istr.str("000000000000001.234500000000");
798  istr >> in_val;
799  CPPUNIT_ASSERT(!istr.fail());
800  CPPUNIT_ASSERT(istr.eof());
801  CPPUNIT_ASSERT(check_float(in_val, 1.2345f));
802  istr.clear();
803
804  istr.str("1.2345e+04");
805  istr >> in_val;
806  CPPUNIT_ASSERT(!istr.fail());
807  CPPUNIT_ASSERT(istr.eof());
808  CPPUNIT_ASSERT(check_float(in_val, 12345.0f));
809  istr.clear();
810
811  CPPUNIT_MESSAGE( "float" );
812  check_get_float( 0.0F );
813  CPPUNIT_MESSAGE( "double" );
814  check_get_float( 0.0 );
815#if !defined (STLPORT) || !defined (_STLP_NO_LONG_DOUBLE)
816  CPPUNIT_MESSAGE( "long double" );
817  check_get_float( 0.0L );
818#endif
819  {
820    stringstream str;
821
822    str << "1e" << numeric_limits<double>::max_exponent10;
823    CPPUNIT_ASSERT(!str.fail());
824
825    float val;
826    str >> val;
827    CPPUNIT_ASSERT(!str.fail());
828    CPPUNIT_ASSERT(str.eof());
829    CPPUNIT_ASSERT( numeric_limits<double>::max_exponent10 <= numeric_limits<float>::max_exponent10 ||
830                    val == numeric_limits<float>::infinity() );
831  }
832  {
833    stringstream str;
834
835    str << "1e" << numeric_limits<double>::min_exponent10;
836    CPPUNIT_ASSERT(!str.fail());
837
838    float val;
839    str >> val;
840    CPPUNIT_ASSERT(!str.fail());
841    CPPUNIT_ASSERT(str.eof());
842    CPPUNIT_ASSERT( numeric_limits<double>::min_exponent10 >= numeric_limits<float>::min_exponent10 ||
843                    val == 0.0f );
844  }
845#if !defined (STLPORT) || !defined (_STLP_NO_LONG_DOUBLE)
846  {
847    stringstream str;
848
849    str << "1e" << numeric_limits<long double>::max_exponent10;
850    CPPUNIT_ASSERT(!str.fail());
851
852    double val;
853    str >> val;
854    CPPUNIT_ASSERT(!str.fail());
855    CPPUNIT_ASSERT(str.eof());
856    CPPUNIT_ASSERT( numeric_limits<long double>::max_exponent10 <= numeric_limits<double>::max_exponent10 ||
857                    val == numeric_limits<double>::infinity() );
858  }
859  {
860    stringstream str;
861
862    str << "1e" << numeric_limits<long double>::min_exponent10;
863    CPPUNIT_ASSERT(!str.fail());
864
865    double val;
866    str >> val;
867    CPPUNIT_ASSERT(!str.fail());
868    CPPUNIT_ASSERT(str.eof());
869    CPPUNIT_ASSERT( numeric_limits<long double>::min_exponent10 >= numeric_limits<double>::min_exponent10 ||
870                    val == 0.0 );
871  }
872  {
873    const char* p = "2.718281828459045235360287471352662497757247093e0";
874    std::stringstream s;
875    s << p;
876    long double x;
877    s >> x;
878    CPPUNIT_ASSERT( x > 2.70l && x < 2.72l );
879  }
880#endif
881}
882
883void NumPutGetTest::num_get_integer()
884{
885  //octal input
886  {
887    istringstream istr;
888    istr.str("30071");
889    short val;
890    istr >> oct >> val;
891    CPPUNIT_ASSERT( !istr.fail() );
892    CPPUNIT_ASSERT( istr.eof() );
893    CPPUNIT_ASSERT( val == 12345 );
894    istr.clear();
895
896    if (sizeof(short) == 2) {
897      istr.str("177777");
898      istr >> oct >> val;
899      CPPUNIT_ASSERT( !istr.fail() );
900      CPPUNIT_ASSERT( istr.eof() );
901      CPPUNIT_ASSERT( val == -1 );
902      istr.clear();
903    }
904  }
905
906  //decimal input
907  {
908    istringstream istr;
909    istr.str("10000");
910    short val = -1;
911    istr >> val;
912    CPPUNIT_ASSERT( !istr.fail() );
913    CPPUNIT_ASSERT( istr.eof() );
914    CPPUNIT_ASSERT( val == 10000 );
915    istr.clear();
916
917    istr.str("+10000");
918    val = -1;
919    istr >> val;
920    CPPUNIT_ASSERT( !istr.fail() );
921    CPPUNIT_ASSERT( istr.eof() );
922    CPPUNIT_ASSERT( val == 10000 );
923    istr.clear();
924
925    if (sizeof(short) == 2) {
926      val = -1;
927      istr.str("10000000");
928      istr >> val;
929      CPPUNIT_ASSERT( istr.fail() );
930      CPPUNIT_ASSERT( istr.eof() );
931      CPPUNIT_ASSERT( val == -1 );
932      istr.clear();
933    }
934
935    val = -1;
936    istr.str("0x0");
937    istr >> val;
938    CPPUNIT_ASSERT( !istr.fail() );
939    CPPUNIT_ASSERT( !istr.eof() );
940    CPPUNIT_ASSERT( val == 0 );
941    istr.clear();
942
943    val = -1;
944    istr.str("000001");
945    istr >> val;
946    CPPUNIT_ASSERT( !istr.fail() );
947    CPPUNIT_ASSERT( istr.eof() );
948    CPPUNIT_ASSERT( val == 1 );
949    istr.clear();
950  }
951
952  //hexadecimal input
953  {
954    istringstream istr;
955    istr.str("3039");
956    short val = -1;
957    istr >> hex >> val;
958    CPPUNIT_ASSERT( !istr.fail() );
959    CPPUNIT_ASSERT( istr.eof() );
960    CPPUNIT_ASSERT( val == 12345 );
961    istr.clear();
962
963    istr.str("x3039");
964    val = -1;
965    istr >> hex >> val;
966    CPPUNIT_ASSERT( istr.fail() );
967    CPPUNIT_ASSERT( !istr.eof() );
968    CPPUNIT_ASSERT( val == -1 );
969    istr.clear();
970
971    istr.str("03039");
972    val = -1;
973    istr >> hex >> val;
974    CPPUNIT_ASSERT( !istr.fail() );
975    CPPUNIT_ASSERT( istr.eof() );
976    CPPUNIT_ASSERT( val == 12345 );
977    istr.clear();
978
979    istr.str("0x3039");
980    istr >> hex >> val;
981    CPPUNIT_ASSERT( !istr.fail() );
982    CPPUNIT_ASSERT( istr.eof() );
983    CPPUNIT_ASSERT( val == 12345 );
984    istr.clear();
985
986    if (sizeof(short) == 2) {
987      val = -1;
988      istr.str("cfc7");
989      istr >> hex >> val;
990      CPPUNIT_ASSERT( !istr.fail() );
991      CPPUNIT_ASSERT( istr.eof() );
992      CPPUNIT_ASSERT( val == -12345 );
993      istr.clear();
994    }
995  }
996}
997
998void NumPutGetTest::inhex()
999{
1000  {
1001    ostringstream s;
1002    s << hex << 0;
1003    CPPUNIT_CHECK( s.str() == "0" );
1004  }
1005  {
1006    ostringstream s;
1007    s << hex << 0xff;
1008    CPPUNIT_CHECK( s.str() == "ff" );
1009  }
1010  {
1011    ostringstream s;
1012    s << hex << setw( 4 ) << 0xff;
1013    CPPUNIT_CHECK( s.str() == "  ff" );
1014  }
1015  {
1016    ostringstream s;
1017    s << hex << setw( 4 ) << 0;
1018    CPPUNIT_CHECK( s.str() == "   0" );
1019  }
1020  {
1021    ostringstream s;
1022    s << hex << showbase << 0;
1023    CPPUNIT_CHECK( s.str() == "0" );
1024  }
1025  {
1026    ostringstream s;
1027    s << hex << showbase << 0xff;
1028    CPPUNIT_CHECK( s.str() == "0xff" );
1029  }
1030  {
1031    ostringstream s;
1032    s << hex << showbase << setw( 4 ) << 0xff;
1033    CPPUNIT_CHECK( s.str() == "0xff" );
1034  }
1035  { // special case for regression (partially duplicate CHECK_COMPLETE above):
1036    ostringstream s;
1037    s.setf( ios_base::internal, ios_base::adjustfield );
1038    s << hex << showbase << setw(8+2) << 0;
1039    CPPUNIT_CHECK( s.str() == "         0" );
1040  }
1041}
1042
1043void NumPutGetTest::pointer()
1044{
1045  // Problem with printing pointer to null
1046
1047  /*
1048   * Really C's formatting not help here, due to:
1049   *
1050   * p  The argument shall be a pointer to void. The value of
1051   *    the pointer is converted to a sequence of printable characters,
1052   *    in an implementation-defined manner.
1053   */
1054  {
1055    /*
1056    char buf[128];
1057    void *p = (void *)0xff00;
1058    sprintf( buf, "%p", p );
1059    // cerr << buf << endl;
1060    // Hmmm, I see 0xff00 on box with 32-bits address; pointer like 'unsigned hex'?
1061    if ( sizeof( p ) == 2 ) {
1062      CPPUNIT_ASSERT( strcmp( buf, "0xff00" ) == 0 );
1063    } else if ( sizeof( p ) == 4 ) {
1064      CPPUNIT_ASSERT( strcmp( buf, "0x0000ff00" ) == 0 );
1065    } else if ( sizeof( p ) == 8 ) {
1066      CPPUNIT_ASSERT( strcmp( buf, "0x000000000000ff00" ) == 0 );
1067    } else {
1068      CPPUNIT_CHECK( sizeof( p ) == 2 || sizeof( p ) == 4 || sizeof( p ) == 8 );
1069    }
1070    */
1071  }
1072  {
1073    /*
1074    char buf[128];
1075    void *p = 0;
1076    */
1077    // sprintf( buf, "%p", p );
1078    /* Cool. "%p" print '(nil)'; "%#x" print '0' */
1079    // sprintf( buf, "%#x", (unsigned)p );
1080    // cerr << buf << endl;
1081  }
1082  {
1083    ostringstream s;
1084    void *p = (void *)0xff00;
1085    s << p;
1086    CPPUNIT_ASSERT( s.good() );
1087    if ( sizeof( p ) == 2 ) {
1088      CPPUNIT_ASSERT( s.str() == "0xff00" );
1089    } else if ( sizeof( p ) == 4 ) {
1090      CPPUNIT_ASSERT( s.str() == "0x0000ff00" ); // this pass
1091    } else if ( sizeof( p ) == 8 ) {
1092      CPPUNIT_ASSERT( s.str() == "0x000000000000ff00" );
1093    } else {
1094      CPPUNIT_CHECK( sizeof( p ) == 2 || sizeof( p ) == 4 || sizeof( p ) == 8 );
1095    }
1096  }
1097  {
1098    ostringstream s;
1099    void *p = 0;
1100    s << p;
1101    CPPUNIT_ASSERT( s.good() );
1102    if ( sizeof( p ) == 2 ) {
1103      CPPUNIT_ASSERT( s.str() == "0x0000" );
1104    } else if ( sizeof( p ) == 4 ) {
1105      CPPUNIT_ASSERT( s.str() == "0x00000000" ); // but this will fail, if follow %p
1106    } else if ( sizeof( p ) == 8 ) {
1107      CPPUNIT_ASSERT( s.str() == "0x0000000000000000" );
1108    } else {
1109      CPPUNIT_CHECK( sizeof( p ) == 2 || sizeof( p ) == 4 || sizeof( p ) == 8 );
1110    }
1111  }
1112}
1113
1114void NumPutGetTest::fix_float_long()
1115{
1116  ostringstream str;
1117
1118  str.setf(ios::fixed, ios::floatfield);
1119  str << 1.0e+5;
1120  CPPUNIT_CHECK( str.str() == "100000.000000" );
1121
1122  reset_stream(str);
1123  str.precision(0);
1124  str << 1.0e+5;
1125  CPPUNIT_CHECK( str.str() == "100000" );
1126
1127  reset_stream(str);
1128  str.precision(4);
1129  str << 1.0e+5;
1130  CPPUNIT_CHECK( str.str() == "100000.0000" );
1131
1132  reset_stream(str);
1133  str.precision(0);
1134  str << 1.0e+83;
1135  {
1136    istringstream istr( str.str() );
1137    double f;
1138    istr >> f;
1139    CPPUNIT_CHECK( !istr.fail() );
1140    if ( int(numeric_limits<double>::digits10) < 83 ) {
1141      double delta = 1.0;
1142      for ( int ee = 83 - int(numeric_limits<double>::digits10); ee > 0; --ee ) {
1143        delta *= 10.0;
1144      }
1145      // we may loss some digits here, but not more than mantissa:
1146      CPPUNIT_CHECK( (f > (1.0e+83 - delta)) && (f < (1.0e+83 + delta)) );
1147    } else {
1148      CPPUNIT_CHECK( check_double(f, 1.0e+83) );
1149    }
1150  }
1151
1152#if 0 // #ifndef _STLP_NO_LONG_DOUBLE
1153  reset_stream(str);
1154  str.precision(0);
1155  str << 1.0e+83l;
1156  {
1157    istringstream istr( str.str() );
1158    long double f;
1159    istr >> f;
1160    CPPUNIT_CHECK( !istr.fail() );
1161    if ( int(numeric_limits<long double>::digits10) < 83 ) {
1162      long double delta = 1.0l;
1163      for ( int ee = 83 - int(numeric_limits<long double>::digits10); ee > 0; --ee ) {
1164        delta *= 10.0l;
1165      }
1166      // we may loss some digits here, but not more than mantissa:
1167      cerr << "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" << endl;
1168      cerr << str.str() << endl;
1169      cerr << delta << endl;
1170      cerr << f << endl;
1171      CPPUNIT_CHECK( (f > (1.0e+83l - delta)) && (f < (1.0e+83l + delta)) );
1172    } else {
1173      CPPUNIT_CHECK( check_double(f, 1.0e+83l) );
1174    }
1175  }
1176#endif
1177
1178  reset_stream(str);
1179  str.precision(0);
1180  str << numeric_limits<double>::max();
1181  {
1182    istringstream istr( str.str() );
1183    double f;
1184    istr >> f;
1185    CPPUNIT_CHECK( !istr.fail() );
1186    if ( int(numeric_limits<double>::digits10) < int(numeric_limits<double>::max_exponent10) ) {
1187      double delta = 9.0;
1188      for ( int ee = int(numeric_limits<double>::max_exponent10) - int(numeric_limits<double>::digits10); ee > 0; --ee ) {
1189        delta *= 10.0;
1190      }
1191      // we may loss some digits here, but not more than mantissa:
1192      CPPUNIT_CHECK( (f > (numeric_limits<double>::max() - delta)) );
1193    }
1194  }
1195
1196#if 0 // #ifndef _STLP_NO_LONG_DOUBLE
1197  reset_stream(str);
1198  str.precision(0);
1199  str << numeric_limits<long double>::max();
1200  {
1201    istringstream istr( str.str() );
1202    long double f;
1203    istr >> f;
1204    CPPUNIT_CHECK( !istr.fail() );
1205    if ( int(numeric_limits<long double>::digits10) < int(numeric_limits<long double>::max_exponent10) ) {
1206      long double delta = 1.0l;
1207      for ( int ee = int(numeric_limits<long double>::max_exponent10) - int(numeric_limits<long double>::digits10); ee > 0; --ee ) {
1208        delta *= 10.0l;
1209      }
1210      // we may loss some digits here, but not more than mantissa:
1211      CPPUNIT_CHECK( (f > (numeric_limits<long double>::max() - delta)) );
1212    }
1213  }
1214#endif
1215}
1216
1217class CommaSepNumPunct : public numpunct<char> {
1218  char do_thousands_sep() const { return ','; }
1219  string do_grouping() const { return string("\1\2\3") + (char)CHAR_MAX; }
1220};
1221
1222#define CHECK2(val, expected) \
1223  os.str(""); os << fixed << setprecision(3) << showpos << val; \
1224  CPPUNIT_ASSERT( os.str() == expected )
1225
1226void NumPutGetTest::custom_numpunct()
1227{
1228    ostringstream os;
1229    locale loc(os.getloc(), new CommaSepNumPunct());
1230    os.imbue(loc);
1231
1232    CHECK2(1, "+1");
1233    CHECK2(10, "+1,0");
1234    CHECK2(100, "+10,0");
1235    CHECK2(1000, "+1,00,0");
1236
1237    CHECK2(1.234, "+1.234");
1238    CHECK2(123.456, "+12,3.456");
1239    CHECK2(1234.567, "+1,23,4.567");
1240    CHECK2(12345.678, "+12,34,5.678");
1241    CHECK2(123456.789, "+123,45,6.789");
1242    CHECK2(1234567.891, "+1,234,56,7.891");
1243    CHECK2(123456789.123, "+123,456,78,9.123");
1244    //CHECK2(100000000000000000000000000000.0, "+100000000000000000000000,000,00,0.000");
1245    CHECK2(numeric_limits<double>::infinity(), "+inf");
1246
1247    CHECK2(-1.234, "-1.234");
1248    CHECK2(-123.456, "-12,3.456");
1249    CHECK2(-1234.567, "-1,23,4.567");
1250    CHECK2(-12345.678, "-12,34,5.678");
1251    CHECK2(-123456.789, "-123,45,6.789");
1252    CHECK2(-1234567.891, "-1,234,56,7.891");
1253    CHECK2(-123456789.123, "-123,456,78,9.123");
1254    //CHECK2(-100000000000000000000000000000.0, "-100000000000000000000000,000,00,0.000");
1255    CHECK2(-numeric_limits<double>::infinity(), "-inf");
1256}
1257
1258#endif
1259