1#include "locale_test.h"
2
3#if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS)
4#  include <locale>
5#  include <sstream>
6#  include <stdexcept>
7
8#  include "complete_digits.h"
9
10#  if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
11using namespace std;
12#  endif
13
14struct ref_locale {
15  const char *name;
16  const char *decimal_point;
17  const char *thousands_sep;
18};
19
20static const ref_locale tested_locales[] = {
21//{  name,         decimal_point, thousands_sepy_thousands_sep},
22#  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
23  { "fr_FR",       ",",           "\xa0"},
24  { "ru_RU.koi8r", ",",           "."},
25  { "en_GB",       ".",           ","},
26  { "en_US",       ".",           ","},
27#  endif
28  { "C",           ".",           ","},
29};
30
31//
32// tests implementation
33//
34void LocaleTest::_num_put_get( const locale& loc, const ref_locale* prl ) {
35  const ref_locale& rl = *prl;
36  CPPUNIT_ASSERT( has_facet<numpunct<char> >(loc) );
37  numpunct<char> const& npct = use_facet<numpunct<char> >(loc);
38  CPPUNIT_ASSERT( npct.decimal_point() == *rl.decimal_point );
39
40  float val = 1234.56f;
41  ostringstream fostr;
42  fostr.imbue(loc);
43  fostr << val;
44
45  string ref = "1";
46  if (!npct.grouping().empty()) {
47    ref += npct.thousands_sep();
48  }
49  ref += "234";
50  ref += npct.decimal_point();
51  ref += "56";
52  //cout << "In " << loc.name() << " 1234.56 is written: " << fostr.str() << endl;
53  CPPUNIT_ASSERT( fostr.str() == ref );
54
55  val = 12345678.9f;
56  ref = "1";
57  ref += npct.decimal_point();
58  ref += "23457e+";
59  string digits = "7";
60  complete_digits(digits);
61  ref += digits;
62  fostr.str("");
63  fostr << val;
64  CPPUNIT_ASSERT( fostr.str() == ref );
65
66  val = 1000000000.0f;
67  fostr.str("");
68  fostr << val;
69  digits = "9";
70  complete_digits(digits);
71  CPPUNIT_ASSERT( fostr.str() == string("1e+") + digits );
72
73  val = 1234.0f;
74  ref = "1";
75  if (!npct.grouping().empty()) {
76    ref += npct.thousands_sep();
77  }
78  ref += "234";
79  fostr.str("");
80  fostr << val;
81  CPPUNIT_ASSERT( fostr.str() == ref );
82
83  val = 10000001.0f;
84  fostr.str("");
85  fostr << val;
86  digits = "7";
87  complete_digits(digits);
88  CPPUNIT_ASSERT( fostr.str() == string("1e+") + digits );
89
90  if (npct.grouping().size() == 1 && npct.grouping()[0] == 3) {
91    int ival = 1234567890;
92    fostr.str("");
93    fostr << ival;
94    ref = "1";
95    ref += npct.thousands_sep();
96    ref += "234";
97    ref += npct.thousands_sep();
98    ref += "567";
99    ref += npct.thousands_sep();
100    ref += "890";
101    CPPUNIT_ASSERT( fostr.str() == ref );
102  }
103
104#if defined (__BORLANDC__)
105  num_put<char> const& nput = use_facet<num_put<char> >(loc);
106  typedef numeric_limits<double> limd;
107  fostr.setf(ios_base::uppercase | ios_base::showpos);
108
109  if (limd::has_infinity) {
110    double infinity = limd::infinity();
111    fostr.str("");
112    nput.put(fostr, fostr, ' ', infinity);
113    CPPUNIT_ASSERT( fostr.str() == string("+Inf") );
114  }
115
116  if (limd::has_quiet_NaN) {
117    /* Ignore FPU exceptions */
118    unsigned int _float_control_word = _control87(0, 0);
119    _control87(EM_INVALID|EM_INEXACT, MCW_EM);
120    double qnan = limd::quiet_NaN();
121    /* Reset floating point control word */
122    _clear87();
123    _control87(_float_control_word, MCW_EM);
124    fostr.str("");
125    nput.put(fostr, fostr, ' ', qnan);
126    CPPUNIT_ASSERT( fostr.str() == string("+NaN") );
127  }
128#endif
129}
130
131typedef void (LocaleTest::*_Test) (const locale&, const ref_locale*);
132static void test_supported_locale(LocaleTest& inst, _Test __test) {
133  size_t n = sizeof(tested_locales) / sizeof(tested_locales[0]);
134  for (size_t i = 0; i < n; ++i) {
135    locale loc;
136#  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
137    try
138#  endif
139    {
140      locale tmp(tested_locales[i].name);
141      loc = tmp;
142    }
143#  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
144    catch (runtime_error const&) {
145      //This locale is not supported.
146      continue;
147    }
148#  endif
149    CPPUNIT_MESSAGE( loc.name().c_str() );
150    (inst.*__test)(loc, tested_locales + i);
151
152    {
153      locale tmp(locale::classic(), tested_locales[i].name, locale::numeric);
154      loc = tmp;
155    }
156    (inst.*__test)(loc, tested_locales + i);
157
158    {
159      locale tmp(locale::classic(), new numpunct_byname<char>(tested_locales[i].name));
160      loc = tmp;
161    }
162    (inst.*__test)(loc, tested_locales + i);
163  }
164}
165
166void LocaleTest::num_put_get()
167{ test_supported_locale(*this, &LocaleTest::_num_put_get); }
168
169void LocaleTest::numpunct_by_name()
170{
171  /*
172   * Check of the 22.1.1.2.7 standard point. Construction of a locale
173   * instance from a null pointer or an unknown name should result in
174   * a runtime_error exception.
175   */
176#  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
177#    if defined (STLPORT) || !defined (__GNUC__)
178  try {
179    locale loc(locale::classic(), new numpunct_byname<char>(static_cast<char const*>(0)));
180    CPPUNIT_FAIL;
181  }
182  catch (runtime_error const& /* e */) {
183    //CPPUNIT_MESSAGE( e.what() );
184  }
185  catch (...) {
186    CPPUNIT_FAIL;
187  }
188#    endif
189
190  try {
191    locale loc(locale::classic(), new numpunct_byname<char>("yasli_language"));
192    CPPUNIT_FAIL;
193  }
194  catch (runtime_error const& /* e */) {
195    //CPPUNIT_MESSAGE( e.what() );
196  }
197  catch (...) {
198    CPPUNIT_FAIL;
199  }
200
201  try {
202    string veryLongFacetName("LC_NUMERIC=");
203    veryLongFacetName.append(512, '?');
204    locale loc(locale::classic(), new numpunct_byname<char>(veryLongFacetName.c_str()));
205    CPPUNIT_FAIL;
206  }
207  catch (runtime_error const& /* e */) {
208    //CPPUNIT_MESSAGE( e.what() );
209  }
210  catch (...) {
211    CPPUNIT_FAIL;
212  }
213
214  try {
215    locale loc(locale::classic(), "C", locale::numeric);
216  }
217  catch (runtime_error const& e) {
218    CPPUNIT_MESSAGE( e.what() );
219    CPPUNIT_FAIL;
220  }
221  catch (...) {
222    CPPUNIT_FAIL;
223  }
224
225  try {
226    // On platform without real localization support we should rely on the "C" facet.
227    locale loc(locale::classic(), "", locale::numeric);
228  }
229  catch (runtime_error const& e) {
230    CPPUNIT_MESSAGE( e.what() );
231    CPPUNIT_FAIL;
232  }
233  catch (...) {
234    CPPUNIT_FAIL;
235  }
236
237  try {
238    locale loc(locale::classic(), new numpunct_byname<char>("C"));
239    numpunct<char> const& cfacet_byname = use_facet<numpunct<char> >(loc);
240    numpunct<char> const& cfacet = use_facet<numpunct<char> >(locale::classic());
241
242    CPPUNIT_CHECK( cfacet_byname.decimal_point() == cfacet.decimal_point() );
243    CPPUNIT_CHECK( cfacet_byname.grouping() == cfacet.grouping() );
244    if (!cfacet.grouping().empty())
245      CPPUNIT_CHECK( cfacet_byname.thousands_sep() == cfacet.thousands_sep() );
246#    if !defined (STLPORT) || !defined (__GLIBC__)
247    CPPUNIT_CHECK( cfacet_byname.truename() == cfacet.truename() );
248    CPPUNIT_CHECK( cfacet_byname.falsename() == cfacet.falsename() );
249#    endif
250  }
251  catch (runtime_error const& /* e */) {
252    //CPPUNIT_MESSAGE( e.what() );
253    CPPUNIT_FAIL;
254  }
255  catch (...) {
256    CPPUNIT_FAIL;
257  }
258
259  try {
260    // On platform without real localization support we should rely on the "C" locale facet.
261    locale loc(locale::classic(), new numpunct_byname<char>(""));
262  }
263  catch (runtime_error const& e) {
264    CPPUNIT_MESSAGE( e.what() );
265    CPPUNIT_FAIL;
266  }
267  catch (...) {
268    CPPUNIT_FAIL;
269  }
270
271#    if !defined (STLPORT) || !defined (_STLP_NO_WCHAR_T)
272#      if defined (STLPORT) || !defined (__GNUC__)
273  try {
274    locale loc(locale::classic(), new numpunct_byname<wchar_t>(static_cast<char const*>(0)));
275    CPPUNIT_FAIL;
276  }
277  catch (runtime_error const&) {
278  }
279  catch (...) {
280    CPPUNIT_FAIL;
281  }
282#      endif
283
284  try {
285    locale loc(locale::classic(), new numpunct_byname<wchar_t>("yasli_language"));
286    CPPUNIT_FAIL;
287  }
288  catch (runtime_error const&) {
289  }
290  catch (...) {
291    CPPUNIT_FAIL;
292  }
293#    endif
294#  endif
295}
296
297#endif
298