1#include "locale_test.h"
2
3#if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS)
4#  include <locale>
5#  include <stdexcept>
6
7#  if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
8using namespace std;
9#  endif
10
11static const char* tested_locales[] = {
12//name,
13#  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
14  // We need exception support to check support of the following localizations.
15  "fr_FR",
16  "ru_RU.koi8r",
17  "en_GB",
18  "en_US",
19#  endif
20  "",
21  "C"
22};
23
24//
25// tests implementation
26//
27void LocaleTest::_ctype_facet( const locale& loc)
28{
29  CPPUNIT_ASSERT( has_facet<ctype<char> >(loc) );
30  ctype<char> const& ct = use_facet<ctype<char> >(loc);
31  //is
32  {
33    CPPUNIT_ASSERT( ct.is(ctype_base::digit, '0') );
34    CPPUNIT_ASSERT( ct.is(ctype_base::upper, 'A') );
35    CPPUNIT_ASSERT( ct.is(ctype_base::lower, 'a') );
36    CPPUNIT_ASSERT( ct.is(ctype_base::alpha, 'A') );
37    CPPUNIT_ASSERT( ct.is(ctype_base::space, ' ') );
38    CPPUNIT_ASSERT( !ct.is(ctype_base::space, '2') );
39    CPPUNIT_ASSERT( ct.is(ctype_base::punct, '.') );
40    CPPUNIT_ASSERT( ct.is(ctype_base::xdigit, 'a') );
41  }
42
43  //is range
44  {
45    char values[] = "0Aa .";
46    ctype_base::mask res[sizeof(values)];
47    ct.is(values, values + sizeof(values), res);
48    // '0'
49    CPPUNIT_ASSERT( (res[0] & ctype_base::print) != 0 );
50    CPPUNIT_ASSERT( (res[0] & ctype_base::digit) != 0 );
51    CPPUNIT_ASSERT( (res[0] & ctype_base::xdigit) != 0 );
52    // 'A'
53    CPPUNIT_ASSERT( (res[1] & ctype_base::print) != 0 );
54    CPPUNIT_ASSERT( (res[1] & ctype_base::alpha) != 0 );
55    CPPUNIT_ASSERT( (res[1] & ctype_base::xdigit) != 0 );
56    CPPUNIT_ASSERT( (res[1] & ctype_base::upper) != 0 );
57    // 'a'
58    CPPUNIT_ASSERT( (res[2] & ctype_base::print) != 0 );
59    CPPUNIT_ASSERT( (res[2] & ctype_base::alpha) != 0 );
60    CPPUNIT_ASSERT( (res[2] & ctype_base::xdigit) != 0 );
61    CPPUNIT_ASSERT( (res[2] & ctype_base::lower) != 0 );
62    CPPUNIT_ASSERT( (res[2] & ctype_base::space) == 0 );
63    // ' '
64    CPPUNIT_ASSERT( (res[3] & ctype_base::print) != 0 );
65    CPPUNIT_ASSERT( (res[3] & ctype_base::space) != 0 );
66    CPPUNIT_ASSERT( (res[3] & ctype_base::digit) == 0 );
67    // '.'
68    CPPUNIT_ASSERT( (res[4] & ctype_base::print) != 0 );
69    CPPUNIT_ASSERT( (res[4] & ctype_base::punct) != 0 );
70    CPPUNIT_ASSERT( (res[4] & ctype_base::digit) == 0 );
71  }
72
73  //scan_is
74  {
75    char range[] = "abAc123 .";
76    const char *rbeg = range;
77    const char *rend = range + sizeof(range);
78
79    const char *res;
80    res = ct.scan_is((ctype_base::mask)(ctype_base::alpha | ctype_base::lower), rbeg, rend);
81    CPPUNIT_ASSERT( res != rend );
82    CPPUNIT_ASSERT( *res == 'a' );
83
84    res = ct.scan_is(ctype_base::upper, rbeg, rend);
85    CPPUNIT_ASSERT( res != rend );
86    CPPUNIT_ASSERT( *res == 'A' );
87
88    res = ct.scan_is(ctype_base::punct, rbeg, rend);
89    CPPUNIT_ASSERT( res != rend );
90    CPPUNIT_ASSERT( *res == '.' );
91  }
92
93  //scan_not
94  {
95    char range[] = "abAc123 .";
96    const char *rbeg = range;
97    const char *rend = range + sizeof(range);
98
99    const char *res;
100    res = ct.scan_not((ctype_base::mask)(ctype_base::alpha | ctype_base::lower), rbeg, rend);
101    CPPUNIT_ASSERT( res != rend );
102    CPPUNIT_ASSERT( *res == '1' );
103
104    res = ct.scan_not(ctype_base::alpha, rbeg, rend);
105    CPPUNIT_ASSERT( res != rend );
106    CPPUNIT_ASSERT( *res == '1' );
107
108    res = ct.scan_not(ctype_base::punct, rbeg, rend);
109    CPPUNIT_ASSERT( res != rend );
110    CPPUNIT_ASSERT( *res == 'a' );
111  }
112
113  //toupper
114  {
115    CPPUNIT_ASSERT( ct.toupper('a') == 'A' );
116    CPPUNIT_ASSERT( ct.toupper('A') == 'A' );
117    CPPUNIT_ASSERT( ct.toupper('1') == '1' );
118  }
119
120  //toupper range
121  {
122    char range[] = "abAc1";
123    char expected_range[] = "ABAC1";
124    ct.toupper(range, range + sizeof(range));
125    CPPUNIT_ASSERT( equal(range, range + sizeof(range), expected_range) );
126  }
127
128  //tolower
129  {
130    CPPUNIT_ASSERT( ct.tolower('A') == 'a' );
131    CPPUNIT_ASSERT( ct.tolower('a') == 'a' );
132    CPPUNIT_ASSERT( ct.tolower('1') == '1' );
133  }
134
135  //tolower range
136  {
137    char range[] = "ABaC1";
138    char expected_range[] = "abac1";
139    ct.tolower(range, range + sizeof(range));
140    CPPUNIT_ASSERT( equal(range, range + sizeof(range), expected_range) );
141  }
142
143  //widen
144  {
145    CPPUNIT_ASSERT( ct.widen('a') == 'a' );
146  }
147
148  //widen range
149  {
150    char range[] = "ABaC1";
151    char res[sizeof(range)];
152    ct.widen(range, range + sizeof(range), res);
153    CPPUNIT_ASSERT( equal(range, range + sizeof(range), res) );
154  }
155
156  //narrow
157  {
158    CPPUNIT_ASSERT( ct.narrow('a', 'b') == 'a' );
159  }
160
161  //narrow range
162  {
163    char range[] = "ABaC1";
164    char res[sizeof(range)];
165    ct.narrow(range, range + sizeof(range), 'b', res);
166    CPPUNIT_ASSERT( equal(range, range + sizeof(range), res) );
167  }
168}
169
170void LocaleTest::_ctype_facet_w( const locale& loc )
171{
172# ifndef _STLP_NO_WCHAR_T
173  CPPUNIT_ASSERT( has_facet<ctype<wchar_t> >(loc) );
174  ctype<wchar_t> const& wct = use_facet<ctype<wchar_t> >(loc);
175  //is
176  {
177    CPPUNIT_CHECK( wct.is(ctype_base::digit, L'0') );
178    CPPUNIT_CHECK( wct.is(ctype_base::upper, L'A') );
179    CPPUNIT_CHECK( wct.is(ctype_base::lower, L'a') );
180    CPPUNIT_CHECK( wct.is(ctype_base::alpha, L'A') );
181    CPPUNIT_CHECK( wct.is(ctype_base::space, L' ') );
182    CPPUNIT_CHECK( !wct.is(ctype_base::space, L'2') );
183    CPPUNIT_CHECK( wct.is(ctype_base::punct, L'.') );
184    CPPUNIT_CHECK( wct.is(ctype_base::xdigit, L'a') );
185  }
186
187  //is range
188  {
189    wchar_t values[] = L"0Aa .";
190    ctype_base::mask res[sizeof(values) / sizeof(wchar_t)];
191    wct.is(values, values + (sizeof(values) / sizeof(wchar_t)), res);
192    // '0'
193    CPPUNIT_CHECK( (res[0] & ctype_base::print) != 0 );
194    CPPUNIT_CHECK( (res[0] & ctype_base::digit) != 0 );
195    CPPUNIT_CHECK( (res[0] & ctype_base::xdigit) != 0 );
196    // 'A'
197    CPPUNIT_CHECK( (res[1] & ctype_base::print) != 0 );
198    CPPUNIT_CHECK( (res[1] & ctype_base::alpha) != 0 );
199    CPPUNIT_CHECK( (res[1] & ctype_base::xdigit) != 0 );
200    CPPUNIT_CHECK( (res[1] & ctype_base::upper) != 0 );
201    // 'a'
202    CPPUNIT_CHECK( (res[2] & ctype_base::print) != 0 );
203    CPPUNIT_CHECK( (res[2] & ctype_base::alpha) != 0 );
204    CPPUNIT_CHECK( (res[2] & ctype_base::xdigit) != 0 );
205    CPPUNIT_CHECK( (res[2] & ctype_base::lower) != 0 );
206    CPPUNIT_CHECK( (res[2] & ctype_base::space) == 0 );
207    // ' '
208    CPPUNIT_CHECK( (res[3] & ctype_base::print) != 0 );
209    CPPUNIT_CHECK( (res[3] & ctype_base::space) != 0 );
210    CPPUNIT_CHECK( (res[3] & ctype_base::digit) == 0 );
211    // '.'
212    CPPUNIT_CHECK( (res[4] & ctype_base::print) != 0 );
213    CPPUNIT_CHECK( (res[4] & ctype_base::punct) != 0 );
214    CPPUNIT_CHECK( (res[4] & ctype_base::digit) == 0 );
215  }
216
217  //scan_is
218  {
219    wchar_t range[] = L"abAc123 .";
220    const wchar_t *rbeg = range;
221    const wchar_t *rend = range + (sizeof(range) / sizeof(wchar_t));
222
223    const wchar_t *res;
224    res = wct.scan_is((ctype_base::mask)(ctype_base::alpha | ctype_base::lower), rbeg, rend);
225    CPPUNIT_CHECK( res != rend );
226    CPPUNIT_CHECK( *res == L'a' );
227
228    res = wct.scan_is(ctype_base::upper, rbeg, rend);
229    CPPUNIT_CHECK( res != rend );
230    CPPUNIT_CHECK( *res == L'A' );
231
232    res = wct.scan_is(ctype_base::punct, rbeg, rend);
233    CPPUNIT_CHECK( res != rend );
234    CPPUNIT_CHECK( *res == L'.' );
235  }
236
237  //scan_not
238  {
239    wchar_t range[] = L"abAc123 .";
240    const wchar_t *rbeg = range;
241    const wchar_t *rend = range + (sizeof(range) / sizeof(wchar_t));
242
243    const wchar_t *res;
244    res = wct.scan_not((ctype_base::mask)(ctype_base::alpha | ctype_base::lower), rbeg, rend);
245    CPPUNIT_CHECK( res != rend );
246    CPPUNIT_CHECK( *res == L'1' );
247
248    res = wct.scan_not(ctype_base::alpha, rbeg, rend);
249    CPPUNIT_CHECK( res != rend );
250    CPPUNIT_CHECK( *res == L'1' );
251
252    res = wct.scan_not(ctype_base::punct, rbeg, rend);
253    CPPUNIT_CHECK( res != rend );
254    CPPUNIT_CHECK( *res == L'a' );
255  }
256
257  //toupper
258  {
259    CPPUNIT_CHECK( wct.toupper(L'a') == L'A' );
260    CPPUNIT_CHECK( wct.toupper(L'A') == L'A' );
261    CPPUNIT_CHECK( wct.toupper(L'1') == L'1' );
262  }
263
264  //toupper range
265  {
266    wchar_t range[] = L"abAc1";
267    wchar_t expected_range[] = L"ABAC1";
268    wct.toupper(range, range + sizeof(range) / sizeof(wchar_t));
269    CPPUNIT_CHECK( equal(range, range + sizeof(range) / sizeof(wchar_t), expected_range) );
270  }
271
272  //tolower
273  {
274    CPPUNIT_CHECK( wct.tolower(L'A') == L'a' );
275    CPPUNIT_CHECK( wct.tolower(L'a') == L'a' );
276    CPPUNIT_CHECK( wct.tolower(L'1') == L'1' );
277  }
278
279  //tolower range
280  {
281    wchar_t range[] = L"ABaC1";
282    wchar_t expected_range[] = L"abac1";
283    wct.tolower(range, range + sizeof(range) / sizeof(wchar_t));
284    CPPUNIT_CHECK( equal(range, range + sizeof(range) / sizeof(wchar_t), expected_range) );
285  }
286
287  //widen
288  {
289    CPPUNIT_CHECK( wct.widen('a') == L'a' );
290  }
291
292  //widen range
293  {
294    char range[] = "ABaC1";
295    wchar_t res[sizeof(range)];
296    wchar_t expected_res[] = L"ABaC1";
297    wct.widen(range, range + sizeof(range), res);
298    CPPUNIT_CHECK( equal(expected_res, expected_res + sizeof(range), res) );
299  }
300
301  //narrow
302  {
303    CPPUNIT_CHECK( wct.narrow(L'a', 'b') == L'a' );
304  }
305
306  //narrow range
307  {
308    wchar_t range[] = L"ABaC1";
309    char res[sizeof(range) / sizeof(wchar_t)];
310    char expected_res[] = "ABaC1";
311    wct.narrow(range, range + sizeof(range) / sizeof(wchar_t), 'b', res);
312    CPPUNIT_CHECK( equal(expected_res, expected_res + sizeof(range) / sizeof(wchar_t), res) );
313  }
314# endif
315}
316
317
318typedef void (LocaleTest::*_Test) (const locale&);
319static void test_supported_locale(LocaleTest& inst, _Test __test) {
320  size_t n = sizeof(tested_locales) / sizeof(tested_locales[0]);
321  for (size_t i = 0; i < n; ++i) {
322    locale loc;
323#  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
324    try
325#  endif
326    {
327      locale tmp(tested_locales[i]);
328      loc = tmp;
329    }
330#  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
331    catch (runtime_error const&) {
332      //This locale is not supported.
333      continue;
334    }
335#  endif
336
337    CPPUNIT_MESSAGE( loc.name().c_str() );
338    (inst.*__test)(loc);
339
340    {
341      locale tmp(locale::classic(), tested_locales[i], locale::ctype);
342      loc = tmp;
343    }
344    (inst.*__test)(loc);
345
346    {
347      locale tmp(locale::classic(), new ctype_byname<char>(tested_locales[i]));
348#ifndef _STLP_NO_WCHAR_T
349      locale tmp0(tmp, new ctype_byname<wchar_t>(tested_locales[i]));
350      tmp = tmp0;
351#endif
352      loc = tmp;
353    }
354    (inst.*__test)(loc);
355  }
356}
357
358void LocaleTest::ctype_facet()
359{
360  test_supported_locale(*this, &LocaleTest::_ctype_facet);
361#ifndef _STLP_NO_WCHAR_T
362  test_supported_locale(*this, &LocaleTest::_ctype_facet_w);
363#endif
364}
365
366void LocaleTest::ctype_by_name()
367{
368  /*
369   * Check of the 22.1.1.2.7 standard point. Construction of a locale
370   * instance from a null pointer or an unknown name should result in
371   * a runtime_error exception.
372   */
373#  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
374#    if  defined (STLPORT) || (!defined(__GNUC__) && (!defined (_MSC_VER) || (_MSC_VER > 1400)))
375   // libstdc++ call freelocate on bad locale
376  try {
377    locale loc(locale::classic(), new ctype_byname<char>(static_cast<char const*>(0)));
378    CPPUNIT_ASSERT( false );
379  }
380  catch (runtime_error const& /* e */) {
381    //CPPUNIT_MESSAGE( e.what() );
382  }
383  catch (...) {
384    CPPUNIT_ASSERT( false );
385  }
386#    endif
387
388  try {
389    locale loc(locale::classic(), new ctype_byname<char>("yasli_language"));
390    CPPUNIT_FAIL;
391  }
392  catch (runtime_error const& /* e */) {
393    //CPPUNIT_MESSAGE( e.what() );
394  }
395  catch (...) {
396    CPPUNIT_FAIL;
397  }
398
399#    if  defined(STLPORT) || !defined(__GNUC__)
400  try {
401    locale loc(locale::classic(), new codecvt_byname<char, char, mbstate_t>(static_cast<char const*>(0)));
402    CPPUNIT_FAIL;
403  }
404  catch (runtime_error const& /* e */) {
405    //CPPUNIT_MESSAGE( e.what() );
406  }
407  catch (...) {
408    CPPUNIT_FAIL;
409  }
410#    endif
411
412  try {
413    locale loc(locale::classic(), new codecvt_byname<char, char, mbstate_t>("yasli_language"));
414    //STLport implementation do not care about name pass to this facet.
415#    if !defined (STLPORT)
416    CPPUNIT_FAIL;
417#    endif
418  }
419  catch (runtime_error const& /* e */) {
420    //CPPUNIT_MESSAGE( e.what() );
421  }
422  catch (...) {
423    CPPUNIT_FAIL;
424  }
425
426  try {
427    locale loc(locale::classic(), new ctype_byname<char>("fr_FR"));
428    CPPUNIT_ASSERT( has_facet<ctype<char> >(loc) );
429    ctype<char> const& ct = use_facet<ctype<char> >(loc);
430    CPPUNIT_ASSERT( ct.is(ctype_base::mask(ctype_base::print | ctype_base::lower | ctype_base::alpha), '�') );
431  }
432  catch (runtime_error const& /* e */) {
433    //CPPUNIT_MESSAGE( e.what() );
434  }
435  catch (...) {
436    CPPUNIT_FAIL;
437  }
438
439  try {
440    locale loc(locale::classic(), new ctype_byname<char>("C"));
441    ctype<char> const& cfacet_byname = use_facet<ctype<char> >(loc);
442    ctype<char> const& cfacet = use_facet<ctype<char> >(locale::classic());
443
444    for (char c = 0;; ++c) {
445      CPPUNIT_CHECK(cfacet_byname.is(ctype_base::space, c) == cfacet.is(ctype_base::space, c));
446      if (cfacet_byname.is(ctype_base::print, c) != cfacet.is(ctype_base::print, c))
447      {
448        CPPUNIT_CHECK(cfacet_byname.is(ctype_base::print, c) == cfacet.is(ctype_base::print, c));
449      }
450      CPPUNIT_CHECK(cfacet_byname.is(ctype_base::cntrl, c) == cfacet.is(ctype_base::cntrl, c));
451      CPPUNIT_CHECK(cfacet_byname.is(ctype_base::upper, c) == cfacet.is(ctype_base::upper, c));
452      CPPUNIT_CHECK(cfacet_byname.is(ctype_base::lower, c) == cfacet.is(ctype_base::lower, c));
453      CPPUNIT_CHECK(cfacet_byname.is(ctype_base::alpha, c) == cfacet.is(ctype_base::alpha, c));
454      CPPUNIT_CHECK(cfacet_byname.is(ctype_base::digit, c) == cfacet.is(ctype_base::digit, c));
455      CPPUNIT_CHECK(cfacet_byname.is(ctype_base::punct, c) == cfacet.is(ctype_base::punct, c));
456      CPPUNIT_CHECK(cfacet_byname.is(ctype_base::xdigit, c) == cfacet.is(ctype_base::xdigit, c));
457      CPPUNIT_CHECK(cfacet_byname.is(ctype_base::alnum, c) == cfacet.is(ctype_base::alnum, c));
458      CPPUNIT_CHECK(cfacet_byname.is(ctype_base::graph, c) == cfacet.is(ctype_base::graph, c));
459      if (c == 127) break;
460    }
461  }
462  catch (runtime_error const& /* e */) {
463    /* CPPUNIT_MESSAGE( e.what() ); */
464    CPPUNIT_FAIL;
465  }
466  catch (...) {
467    CPPUNIT_FAIL;
468  }
469
470#    if !defined (STLPORT) || !defined (_STLP_NO_WCHAR_T)
471#      if  defined(STLPORT) || !defined(__GNUC__)
472  try {
473    locale loc(locale::classic(), new ctype_byname<wchar_t>(static_cast<char const*>(0)));
474    CPPUNIT_FAIL;
475  }
476  catch (runtime_error const&) {
477  }
478  catch (...) {
479    CPPUNIT_FAIL;
480  }
481#      endif
482
483  try {
484    locale loc(locale::classic(), new ctype_byname<wchar_t>("yasli_language"));
485    CPPUNIT_FAIL;
486  }
487  catch (runtime_error const&) {
488  }
489  catch (...) {
490    CPPUNIT_FAIL;
491  }
492
493#      if  defined(STLPORT) || !defined(__GNUC__)
494  try {
495    locale loc(locale::classic(), new codecvt_byname<wchar_t, char, mbstate_t>(static_cast<char const*>(0)));
496    CPPUNIT_FAIL;
497  }
498  catch (runtime_error const& /* e */) {
499    //CPPUNIT_MESSAGE( e.what() );
500  }
501  catch (...) {
502    CPPUNIT_FAIL;
503  }
504#      endif
505
506  try {
507    locale loc(locale::classic(), new codecvt_byname<wchar_t, char, mbstate_t>("yasli_language"));
508    CPPUNIT_FAIL;
509  }
510  catch (runtime_error const& /* e */) {
511    //CPPUNIT_MESSAGE( e.what() );
512  }
513  catch (...) {
514    CPPUNIT_FAIL;
515  }
516#    endif
517#  endif
518}
519
520#endif
521