os/ossrv/genericopenlibs/cppstdlib/stl/test/unit/locale_test.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4  */
     5 #include <string>
     6 
     7 #if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS)
     8 #  include <sstream>
     9 #  include <locale>
    10 #  include <stdexcept>
    11 #  include <memory>
    12 #  include <algorithm>
    13 //#  include <iostream>
    14 
    15 #  include "cppunit/cppunit_proxy.h"
    16 
    17 #  if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
    18 using namespace std;
    19 #  endif
    20 
    21 struct ref_locale {
    22   const char *name;
    23   const char *decimal_point;
    24   const char *thousands_sep;
    25   const char *money_int_prefix;
    26   const char *money_int_prefix_old;
    27   const char *money_prefix;
    28   const char *money_suffix;
    29   const char *money_decimal_point;
    30   const char *money_thousands_sep;
    31 };
    32 
    33 // Pls, don't write #ifdef _STLP_REAL_LOCALE_IMPLEMENTED here!
    34 // It undefined in any case!!!!!
    35 
    36 static const ref_locale tested_locales[] = {
    37 //{  name,         decimal_point, thousands_sep, money_int_prefix, money_int_prefix_old, money_prefix, money_suffix, money_decimal_point, money_thousands_sep},
    38   { "fr_FR",       ",",           "\xa0",        "EUR ",           "FRF ",               "",           "",           ",",
    39 #  if defined (WIN32) || defined (_WIN32)
    40                                                                                                                                           "\xa0" },
    41 #  else
    42                                                                                                                                           " " },
    43 #  endif
    44   { "ru_RU.koi8r", ",",           ".",           "RUB ",           "RUR ",               "",           "\xd2\xd5\xc2", ".",               " " },
    45   { "en_GB",       ".",           ",",           "GBP ",           "",                   "\xa3",       "",           ".",                 "," },
    46   { "en_US",       ".",           ",",           "USD ",           "",                   "$",          "",           ".",                 "," },
    47   { "C",           ".",           ",",           "",               "",                   "",           "",           " ",                 " " },
    48 };
    49 
    50 
    51 //
    52 // TestCase class
    53 //
    54 class LocaleTest : public CPPUNIT_NS::TestCase
    55 {
    56   CPPUNIT_TEST_SUITE(LocaleTest);
    57 #  if defined (STLPORT) && !defined (_STLP_USE_EXCEPTIONS)
    58   CPPUNIT_IGNORE;
    59 #  endif
    60   CPPUNIT_TEST(locale_by_name);
    61   CPPUNIT_STOP_IGNORE;
    62   CPPUNIT_TEST(loc_has_facet);
    63   CPPUNIT_TEST(num_put_get);
    64   CPPUNIT_TEST(money_put_get);
    65   CPPUNIT_TEST(money_put_X_bug);
    66   CPPUNIT_TEST(time_put_get);
    67 #  if defined (__DMC__) && defined (_DLL)
    68   CPPUNIT_IGNORE;
    69 #  endif
    70   CPPUNIT_TEST(collate_facet);
    71   CPPUNIT_TEST(ctype_facet);
    72 #  if defined (STLPORT) && defined (_STLP_NO_MEMBER_TEMPLATES)
    73   CPPUNIT_IGNORE;
    74 #  endif
    75   CPPUNIT_TEST(locale_init_problem);
    76   CPPUNIT_STOP_IGNORE;
    77   CPPUNIT_TEST(default_locale);
    78 #  if !defined (STLPORT)
    79   CPPUNIT_IGNORE;
    80 #  endif
    81   CPPUNIT_TEST(facet_id);
    82   CPPUNIT_STOP_IGNORE;
    83 #  if defined (STLPORT) && \
    84      (!defined (_STLP_USE_EXCEPTIONS) || defined (_STLP_NO_MEMBER_TEMPLATES) || defined (_STLP_NO_EXPLICIT_FUNCTION_TMPL_ARGS))
    85   CPPUNIT_IGNORE;
    86 #  endif
    87   CPPUNIT_TEST(combine);
    88   CPPUNIT_TEST_SUITE_END();
    89 
    90 public:
    91   void locale_by_name();
    92   void loc_has_facet();
    93   void num_put_get();
    94   void money_put_get();
    95   void time_put_get();
    96   void collate_facet();
    97   void ctype_facet();
    98   void locale_init_problem();
    99   void money_put_X_bug();
   100   void default_locale();
   101   void facet_id();
   102   void combine();
   103 private:
   104   void _loc_has_facet( const locale&, const ref_locale& );
   105   void _num_put_get( const locale&, const ref_locale& );
   106   void _money_put_get( const locale&, const ref_locale& );
   107   void _money_put_get2( const locale& loc, const locale& streamLoc, const ref_locale& );
   108   void _time_put_get( const locale&, const ref_locale& );
   109   void _ctype_facet( const locale&, const ref_locale& );
   110   void _locale_init_problem( const locale&, const ref_locale& );
   111   void _money_put_X_bug( const locale&, const ref_locale& );
   112 };
   113 
   114 CPPUNIT_TEST_SUITE_REGISTRATION(LocaleTest);
   115 
   116 //
   117 // tests implementation
   118 //
   119 void LocaleTest::_num_put_get( const locale& loc, const ref_locale& rl ) {
   120   CPPUNIT_ASSERT( has_facet<numpunct<char> >(loc) );
   121   numpunct<char> const& npct = use_facet<numpunct<char> >(loc);
   122   CPPUNIT_ASSERT( npct.decimal_point() == *rl.decimal_point );
   123 
   124   float val = 1234.56f;
   125   ostringstream fostr;
   126   fostr.imbue(loc);
   127   fostr << val;
   128 
   129   string ref = "1";
   130   if (!npct.grouping().empty()) {
   131     ref += npct.thousands_sep();
   132   }
   133   ref += "234";
   134   ref += npct.decimal_point();
   135   ref += "56";
   136   //cout << "In " << loc.name() << " 1234.56 is written: " << fostr.str() << endl;
   137   CPPUNIT_ASSERT( fostr.str() == ref );
   138 
   139   val = 12345678.9f;
   140   ref = "1";
   141   ref += npct.decimal_point();
   142   ref += "23457e+07";
   143   fostr.str("");
   144   fostr << val;
   145   CPPUNIT_ASSERT( fostr.str() == ref );
   146 
   147   val = 1000000000.0f;
   148   fostr.str("");
   149   fostr << val;
   150   CPPUNIT_ASSERT( fostr.str() == "1e+09" );
   151 
   152   val = 1234.0f;
   153   ref = "1";
   154   if (!npct.grouping().empty()) {
   155     ref += npct.thousands_sep();
   156   }
   157   ref += "234";
   158   fostr.str("");
   159   fostr << val;
   160   CPPUNIT_ASSERT( fostr.str() == ref );
   161 
   162   val = 10000001.0f;
   163   fostr.str("");
   164   fostr << val;
   165   CPPUNIT_ASSERT( fostr.str() == "1e+07" );
   166 }
   167 
   168 void LocaleTest::_money_put_get( const locale& loc, const ref_locale& rl )
   169 {
   170   _money_put_get2(loc, loc, rl);
   171 }
   172 
   173 void LocaleTest::_money_put_get2( const locale& loc, const locale& streamLoc, const ref_locale& rl )
   174 {
   175   CPPUNIT_ASSERT( has_facet<money_put<char> >(loc) );
   176   money_put<char> const& fmp = use_facet<money_put<char> >(loc);
   177   CPPUNIT_ASSERT( has_facet<money_get<char> >(loc) );
   178   money_get<char> const& fmg = use_facet<money_get<char> >(loc);
   179 
   180   ostringstream ostr;
   181   ostr.imbue(streamLoc);
   182   ostr << showbase;
   183 
   184   //Check a positive value (international format)
   185   {
   186     string str_res;
   187     //money_put
   188     {
   189       CPPUNIT_ASSERT( (has_facet<moneypunct<char, true> >(loc)) );
   190       moneypunct<char, true> const& intl_fmp = use_facet<moneypunct<char, true> >(loc);
   191 
   192       ostreambuf_iterator<char, char_traits<char> > res = fmp.put(ostr, true, ostr, ' ', 123456);
   193 
   194       CPPUNIT_ASSERT( !res.failed() );
   195       str_res = ostr.str();
   196 
   197       size_t fieldIndex = 0;
   198       size_t index = 0;
   199 
   200       //On a positive value we skip the sign field if exists:
   201       if (intl_fmp.pos_format().field[fieldIndex] == money_base::sign) {
   202         ++fieldIndex;
   203       }
   204       // international currency abbreviation, if it is before value
   205 
   206       /*
   207        * int_curr_symbol
   208        *
   209        *   The international currency symbol. The operand is a four-character
   210        *   string, with the first three characters containing the alphabetic
   211        *   international currency symbol in accordance with those specified
   212        *   in the ISO 4217 specification. The fourth character is the character used
   213        *   to separate the international currency symbol from the monetary quantity.
   214        *
   215        * (http://www.opengroup.org/onlinepubs/7990989775/xbd/locale.html)
   216        */
   217       string::size_type p = strlen( rl.money_int_prefix );
   218       if (p != 0) {
   219         CPPUNIT_ASSERT( intl_fmp.pos_format().field[fieldIndex] == money_base::symbol );
   220         string::size_type p_old = strlen( rl.money_int_prefix_old );
   221         CPPUNIT_ASSERT( (str_res.substr(index, p) == rl.money_int_prefix) ||
   222                         ((p_old != 0) && (str_res.substr(index, p_old) ==  rl.money_int_prefix_old)) );
   223         if ( str_res.substr(index, p) == rl.money_int_prefix ) {
   224           index += p;
   225         } else {
   226           index += p_old;
   227         }
   228         ++fieldIndex;
   229       }
   230 
   231       // space after currency
   232       if (intl_fmp.pos_format().field[fieldIndex] == money_base::space ||
   233           intl_fmp.pos_format().field[fieldIndex] == money_base::none) {
   234         // iternational currency symobol has four chars, one of these chars
   235         // is separator, so if format has space on this place, it should
   236         // be skipped.
   237         ++fieldIndex;
   238       }
   239 
   240       // sign
   241       if (intl_fmp.pos_format().field[fieldIndex] == money_base::sign) {
   242         ++fieldIndex;
   243       }
   244 
   245       // value
   246       CPPUNIT_ASSERT( str_res[index++] == '1' );
   247       if (!intl_fmp.grouping().empty()) {
   248         CPPUNIT_ASSERT( str_res[index++] == /* intl_fmp.thousands_sep() */ *rl.money_thousands_sep );
   249       }
   250       CPPUNIT_ASSERT( str_res[index++] == '2' );
   251       CPPUNIT_ASSERT( str_res[index++] == '3' );
   252       CPPUNIT_ASSERT( str_res[index++] == '4' );
   253       if (intl_fmp.frac_digits() != 0) {
   254         CPPUNIT_ASSERT( str_res[index++] == /* intl_fmp.decimal_point() */ *rl.money_decimal_point );
   255       }
   256       CPPUNIT_ASSERT( str_res[index++] == '5' );
   257       CPPUNIT_ASSERT( str_res[index++] == '6' );
   258       ++fieldIndex;
   259 
   260       // sign
   261       if (intl_fmp.pos_format().field[fieldIndex] == money_base::sign) {
   262         ++fieldIndex;
   263       }
   264 
   265       // space
   266       if (intl_fmp.pos_format().field[fieldIndex] == money_base::space ) {
   267         CPPUNIT_ASSERT( str_res[index++] == ' ' );
   268         ++fieldIndex;
   269       }
   270 
   271       // sign
   272       if (intl_fmp.pos_format().field[fieldIndex] == money_base::sign) {
   273         ++fieldIndex;
   274       }
   275 
   276       //as space cannot be last the only left format can be none:
   277       while ( fieldIndex < 3 ) {
   278         CPPUNIT_ASSERT( intl_fmp.pos_format().field[fieldIndex] == money_base::none );
   279         ++fieldIndex;
   280       }
   281     }
   282 
   283     //money_get
   284     {
   285       ios_base::iostate err = ios_base::goodbit;
   286       string digits;
   287 
   288       istringstream istr(str_res);
   289       ostr.str( "" );
   290       ostr.clear();
   291       fmg.get(istr, istreambuf_iterator<char, char_traits<char> >(), true, ostr, err, digits);
   292       CPPUNIT_ASSERT( (err & (ios_base::failbit | ios_base::badbit)) == 0 );
   293       CPPUNIT_ASSERT( digits == "123456" );
   294     }
   295   }
   296 
   297   ostr.str("");
   298   //Check a negative value (national format)
   299   {
   300     CPPUNIT_ASSERT( (has_facet<moneypunct<char, false> >(loc)) );
   301     moneypunct<char, false> const& dom_fmp = use_facet<moneypunct<char, false> >(loc);
   302     string str_res;
   303     //Check money_put
   304     {
   305       ostreambuf_iterator<char, char_traits<char> > res = fmp.put(ostr, false, ostr, ' ', -123456);
   306 
   307       CPPUNIT_ASSERT( !res.failed() );
   308       str_res = ostr.str();
   309 
   310       size_t fieldIndex = 0;
   311       size_t index = 0;
   312 
   313       if (dom_fmp.neg_format().field[fieldIndex] == money_base::sign) {
   314         CPPUNIT_ASSERT( str_res.substr(index, dom_fmp.negative_sign().size()) == dom_fmp.negative_sign() );
   315         index += dom_fmp.negative_sign().size();
   316         ++fieldIndex;
   317       }
   318 
   319       string::size_type p = strlen( rl.money_prefix );
   320       if (p != 0) {
   321         CPPUNIT_ASSERT( str_res.substr(index, p) == rl.money_prefix );
   322         index += p;
   323         ++fieldIndex;
   324       }
   325       if (dom_fmp.neg_format().field[fieldIndex] == money_base::space ||
   326           dom_fmp.neg_format().field[fieldIndex] == money_base::none) {
   327         CPPUNIT_ASSERT( str_res[index++] == ' ' );
   328         ++fieldIndex;
   329       }
   330 
   331       CPPUNIT_ASSERT( str_res[index++] == '1' );
   332       if (!dom_fmp.grouping().empty()) {
   333         CPPUNIT_ASSERT( str_res[index++] == dom_fmp.thousands_sep() );
   334       }
   335       CPPUNIT_ASSERT( str_res[index++] == '2' );
   336       CPPUNIT_ASSERT( str_res[index++] == '3' );
   337       CPPUNIT_ASSERT( str_res[index++] == '4' );
   338       if (dom_fmp.frac_digits() != 0) {
   339         CPPUNIT_ASSERT( str_res[index++] == dom_fmp.decimal_point() );
   340       }
   341       CPPUNIT_ASSERT( str_res[index++] == '5' );
   342       CPPUNIT_ASSERT( str_res[index++] == '6' );
   343       ++fieldIndex;
   344 
   345       //space cannot be last:
   346       if ((fieldIndex < 3) &&
   347           dom_fmp.neg_format().field[fieldIndex] == money_base::space) {
   348         CPPUNIT_ASSERT( str_res[index++] == ' ' );
   349         ++fieldIndex;
   350       }
   351 
   352       if (fieldIndex == 3) {
   353         //If none is last we should not add anything to the resulting string:
   354         if (dom_fmp.neg_format().field[fieldIndex] == money_base::none) {
   355           CPPUNIT_ASSERT( index == str_res.size() );
   356         } else {
   357           CPPUNIT_ASSERT( dom_fmp.neg_format().field[fieldIndex] == money_base::symbol );
   358           CPPUNIT_ASSERT( str_res.substr(index, strlen(rl.money_suffix)) == rl.money_suffix );
   359         }
   360       }
   361     }
   362 
   363     //money_get
   364     {
   365       ios_base::iostate err = ios_base::goodbit;
   366 #  if defined (STLPORT)
   367       _STLP_LONGEST_FLOAT_TYPE val;
   368 #  else
   369       long double val;
   370 #  endif
   371 
   372       istringstream istr(str_res);
   373       fmg.get(istr, istreambuf_iterator<char, char_traits<char> >(), false, ostr, err, val);
   374       CPPUNIT_ASSERT( (err & (ios_base::failbit | ios_base::badbit)) == 0 );
   375       if (dom_fmp.negative_sign().empty()) {
   376         //Without negative sign there is no way to guess the resulting amount sign ("C" locale):
   377         CPPUNIT_ASSERT( val == 123456 );
   378       }
   379       else {
   380         CPPUNIT_ASSERT( val == -123456 );
   381       }
   382     }
   383   }
   384   ostr.str("");
   385   //Check a negative value (national format)
   386   {
   387     CPPUNIT_ASSERT( (has_facet<moneypunct<char, false> >(loc)) );
   388     moneypunct<char, true> const& dom_fmp = use_facet<moneypunct<char, true> >(loc);
   389     string str_res;
   390     //Check money_put
   391     {
   392       ostreambuf_iterator<char, char_traits<char> > res = fmp.put(ostr, true, ostr, ' ', -123456);
   393 
   394       CPPUNIT_ASSERT( !res.failed() );
   395       str_res = ostr.str();
   396 
   397       size_t fieldIndex = 0;
   398       size_t index = 0;
   399 
   400       if (dom_fmp.neg_format().field[fieldIndex] == money_base::sign) {
   401         CPPUNIT_ASSERT( str_res.substr(index, dom_fmp.negative_sign().size()) == dom_fmp.negative_sign() );
   402         index += dom_fmp.negative_sign().size();
   403         ++fieldIndex;
   404       }
   405 
   406       string::size_type p = strlen( rl.money_prefix );
   407       if (p != 0) {
   408         CPPUNIT_ASSERT( str_res.substr(index, p) == rl.money_prefix );
   409         index += p;
   410         ++fieldIndex;
   411       }
   412       if (dom_fmp.neg_format().field[fieldIndex] == money_base::space ||
   413           dom_fmp.neg_format().field[fieldIndex] == money_base::none) {
   414         CPPUNIT_ASSERT( str_res[index++] == ' ' );
   415         ++fieldIndex;
   416       }
   417 
   418       CPPUNIT_ASSERT( str_res[index++] == '1' );
   419       if (!dom_fmp.grouping().empty()) {
   420         CPPUNIT_ASSERT( str_res[index++] == dom_fmp.thousands_sep() );
   421       }
   422       CPPUNIT_ASSERT( str_res[index++] == '2' );
   423       CPPUNIT_ASSERT( str_res[index++] == '3' );
   424       CPPUNIT_ASSERT( str_res[index++] == '4' );
   425       if (dom_fmp.frac_digits() != 0) {
   426         CPPUNIT_ASSERT( str_res[index++] == dom_fmp.decimal_point() );
   427       }
   428       CPPUNIT_ASSERT( str_res[index++] == '5' );
   429       CPPUNIT_ASSERT( str_res[index++] == '6' );
   430       ++fieldIndex;
   431 
   432       //space cannot be last:
   433       if ((fieldIndex < 3) &&
   434           dom_fmp.neg_format().field[fieldIndex] == money_base::space) {
   435         CPPUNIT_ASSERT( str_res[index++] == ' ' );
   436         ++fieldIndex;
   437       }
   438 
   439       if (fieldIndex == 3) {
   440         //If none is last we should not add anything to the resulting string:
   441         if (dom_fmp.neg_format().field[fieldIndex] == money_base::none) {
   442           CPPUNIT_ASSERT( index == str_res.size() );
   443         } else {
   444           CPPUNIT_ASSERT( dom_fmp.neg_format().field[fieldIndex] == money_base::symbol );
   445           CPPUNIT_ASSERT( str_res.substr(index, strlen(rl.money_suffix)) == rl.money_suffix );
   446         }
   447       }
   448     }
   449 
   450     //money_get
   451     {
   452       ios_base::iostate err = ios_base::goodbit;
   453 #  if defined (STLPORT)
   454       _STLP_LONGEST_FLOAT_TYPE val;
   455 #  else
   456       long double val;
   457 #  endif
   458 
   459       istringstream istr(str_res);
   460       fmg.get(istr, istreambuf_iterator<char, char_traits<char> >(), false, ostr, err, val);
   461       CPPUNIT_ASSERT( (err & (ios_base::failbit | ios_base::badbit)) == 0 );
   462       if (dom_fmp.negative_sign().empty()) {
   463         //Without negative sign there is no way to guess the resulting amount sign ("C" locale):
   464         CPPUNIT_ASSERT( val == 123456 );
   465       }
   466       else {
   467         CPPUNIT_ASSERT( val == -123456 );
   468       }
   469     }
   470   }
   471 }
   472 
   473 
   474 // Test for bug in case when number of digits in value less then number
   475 // of digits in fraction. I.e. '9' should be printed as '0.09',
   476 // if x.frac_digits() == 2.
   477 
   478 void LocaleTest::_money_put_X_bug( const locale& loc, const ref_locale& rl )
   479 {
   480   CPPUNIT_ASSERT( has_facet<money_put<char> >(loc) );
   481   money_put<char> const& fmp = use_facet<money_put<char> >(loc);
   482 
   483   ostringstream ostr;
   484   ostr.imbue(loc);
   485   ostr << showbase;
   486 
   487   // ostr.str("");
   488   // Check value with one decimal digit:
   489   {
   490     CPPUNIT_ASSERT( (has_facet<moneypunct<char, false> >(loc)) );
   491     moneypunct<char, false> const& dom_fmp = use_facet<moneypunct<char, false> >(loc);
   492     string str_res;
   493     // Check money_put
   494     {
   495       ostreambuf_iterator<char, char_traits<char> > res = fmp.put(ostr, false, ostr, ' ', 9);
   496 
   497       CPPUNIT_ASSERT( !res.failed() );
   498       str_res = ostr.str();
   499 
   500       size_t fieldIndex = 0;
   501       size_t index = 0;
   502 
   503       if (dom_fmp.pos_format().field[fieldIndex] == money_base::sign) {
   504         CPPUNIT_ASSERT( str_res.substr(index, dom_fmp.positive_sign().size()) == dom_fmp.positive_sign() );
   505         index += dom_fmp.positive_sign().size();
   506         ++fieldIndex;
   507       }
   508 
   509       string::size_type p = strlen( rl.money_prefix );
   510       if (p != 0) {
   511         CPPUNIT_ASSERT( str_res.substr(index, p) == rl.money_prefix );
   512         index += p;
   513         ++fieldIndex;
   514       }
   515       if (dom_fmp.neg_format().field[fieldIndex] == money_base::space ||
   516           dom_fmp.neg_format().field[fieldIndex] == money_base::none) {
   517         CPPUNIT_ASSERT( str_res[index++] == ' ' );
   518         ++fieldIndex;
   519       }
   520       if (dom_fmp.frac_digits() != 0) {
   521         CPPUNIT_ASSERT( str_res[index++] == '0' );
   522         CPPUNIT_ASSERT( str_res[index++] == dom_fmp.decimal_point() );
   523         for ( int fd = 1; fd < dom_fmp.frac_digits(); ++fd ) {
   524           CPPUNIT_ASSERT( str_res[index++] == '0' );
   525         }
   526       }
   527       CPPUNIT_ASSERT( str_res[index++] == '9' );
   528       ++fieldIndex;
   529 
   530       //space cannot be last:
   531       if ((fieldIndex < 3) &&
   532           dom_fmp.neg_format().field[fieldIndex] == money_base::space) {
   533         CPPUNIT_ASSERT( str_res[index++] == ' ' );
   534         ++fieldIndex;
   535       }
   536 
   537       if (fieldIndex == 3) {
   538         //If none is last we should not add anything to the resulting string:
   539         if (dom_fmp.neg_format().field[fieldIndex] == money_base::none) {
   540           CPPUNIT_ASSERT( index == str_res.size() );
   541         } else {
   542           CPPUNIT_ASSERT( dom_fmp.neg_format().field[fieldIndex] == money_base::symbol );
   543           CPPUNIT_ASSERT( str_res.substr(index, strlen(rl.money_suffix)) == rl.money_suffix );
   544         }
   545       }
   546     }
   547   }
   548 
   549   ostr.str("");
   550   // Check value with two decimal digit:
   551   {
   552     CPPUNIT_ASSERT( (has_facet<moneypunct<char, false> >(loc)) );
   553     moneypunct<char, false> const& dom_fmp = use_facet<moneypunct<char, false> >(loc);
   554     string str_res;
   555     // Check money_put
   556     {
   557       ostreambuf_iterator<char, char_traits<char> > res = fmp.put(ostr, false, ostr, ' ', 90);
   558 
   559       CPPUNIT_ASSERT( !res.failed() );
   560       str_res = ostr.str();
   561 
   562       size_t fieldIndex = 0;
   563       size_t index = 0;
   564 
   565       if (dom_fmp.pos_format().field[fieldIndex] == money_base::sign) {
   566         CPPUNIT_ASSERT( str_res.substr(index, dom_fmp.positive_sign().size()) == dom_fmp.positive_sign() );
   567         index += dom_fmp.positive_sign().size();
   568         ++fieldIndex;
   569       }
   570 
   571       string::size_type p = strlen( rl.money_prefix );
   572       if (p != 0) {
   573         CPPUNIT_ASSERT( str_res.substr(index, p) == rl.money_prefix );
   574         index += p;
   575         ++fieldIndex;
   576       }
   577       if (dom_fmp.neg_format().field[fieldIndex] == money_base::space ||
   578           dom_fmp.neg_format().field[fieldIndex] == money_base::none) {
   579         CPPUNIT_ASSERT( str_res[index++] == ' ' );
   580         ++fieldIndex;
   581       }
   582       if (dom_fmp.frac_digits() != 0) {
   583         CPPUNIT_ASSERT( str_res[index++] == '0' );
   584         CPPUNIT_ASSERT( str_res[index++] == dom_fmp.decimal_point() );
   585         for ( int fd = 1; fd < dom_fmp.frac_digits() - 1; ++fd ) {
   586           CPPUNIT_ASSERT( str_res[index++] == '0' );
   587         }
   588       }
   589       CPPUNIT_ASSERT( str_res[index++] == '9' );
   590       if (dom_fmp.frac_digits() != 0) {
   591         CPPUNIT_ASSERT( str_res[index++] == '0' );
   592       }
   593       ++fieldIndex;
   594 
   595       //space cannot be last:
   596       if ((fieldIndex < 3) &&
   597           dom_fmp.neg_format().field[fieldIndex] == money_base::space) {
   598         CPPUNIT_ASSERT( str_res[index++] == ' ' );
   599         ++fieldIndex;
   600       }
   601 
   602       if (fieldIndex == 3) {
   603         //If none is last we should not add anything to the resulting string:
   604         if (dom_fmp.neg_format().field[fieldIndex] == money_base::none) {
   605           CPPUNIT_ASSERT( index == str_res.size() );
   606         } else {
   607           CPPUNIT_ASSERT( dom_fmp.neg_format().field[fieldIndex] == money_base::symbol );
   608           CPPUNIT_ASSERT( str_res.substr(index, strlen(rl.money_suffix)) == rl.money_suffix );
   609         }
   610       }
   611     }
   612   }
   613 }
   614 
   615 void LocaleTest::_time_put_get( const locale& loc, const ref_locale&)
   616 {
   617   CPPUNIT_ASSERT( has_facet<time_put<char> >(loc) );
   618   const time_put<char>& tmp = use_facet<time_put<char> >(loc);
   619 
   620   struct tm xmas = { 0, 0, 12, 25, 11, 93 };
   621   ostringstream ostr;
   622   ostr.imbue(loc);
   623   string format = "%B %d %Y";
   624 
   625   time_put<char>::iter_type ret = tmp.put(ostr, ostr, ' ', &xmas, format.data(), format.data() + format.size());
   626   CPPUNIT_ASSERT( !ret.failed() );
   627 
   628   /*
   629    * In other words, user conformation is required for reliable parsing
   630    * of user-entered dates and times, but machine-generated formats can be
   631    * parsed reliably. This allows parsers to be aggressive about interpreting
   632    * user variations on standard format.
   633    *
   634    *                                             ISO/IEC 14882, 22.2.5.1
   635    */
   636   CPPUNIT_ASSERT( has_facet<time_get<char> >(loc) );
   637   const time_get<char>& tmg = use_facet<time_get<char> >(loc);
   638   basic_ios<char> io(0);
   639   io.imbue(loc);
   640 
   641   istringstream istr( ostr.str() );
   642   istreambuf_iterator<char, char_traits<char> > i( istr );
   643   istreambuf_iterator<char, char_traits<char> > e;
   644   ios_base::iostate err = ios_base::goodbit;
   645   struct tm other = { 15, 20, 9, 14, 7, 105 };
   646 
   647   i = tmg.get_monthname( i, e, io, err, &other );
   648   CPPUNIT_ASSERT( err == ios_base::goodbit );
   649   CPPUNIT_ASSERT( other.tm_mon == xmas.tm_mon );
   650 
   651   ++i; ++i; ++i; ++i; // skip day of month and spaces around it
   652   i = tmg.get_year( i, e, io, err, &other );
   653 
   654   CPPUNIT_ASSERT( err == ios_base::eofbit );
   655   CPPUNIT_ASSERT( other.tm_year == xmas.tm_year );
   656 
   657   ostringstream ostrX;
   658   ostrX.imbue(loc);
   659   format = "%x %X";
   660 
   661   ret = tmp.put(ostrX, ostrX, ' ', &xmas, format.data(), format.data() + format.size());
   662   CPPUNIT_ASSERT( !ret.failed() );
   663 
   664   istringstream istrX( ostrX.str() );
   665   istreambuf_iterator<char, char_traits<char> > j( istrX );
   666 
   667   err = ios_base::goodbit;
   668 
   669   struct tm yet_more = { 15, 20, 9, 14, 7, 105 };
   670 
   671   j = tmg.get_date( j, e, io, err, &yet_more );
   672 
   673   CPPUNIT_ASSERT( err == ios_base::goodbit );
   674 
   675   CPPUNIT_ASSERT( yet_more.tm_sec != xmas.tm_sec );
   676   CPPUNIT_ASSERT( yet_more.tm_min != xmas.tm_min );
   677   CPPUNIT_ASSERT( yet_more.tm_hour != xmas.tm_hour );
   678   CPPUNIT_ASSERT( yet_more.tm_mday == xmas.tm_mday );
   679   CPPUNIT_ASSERT( yet_more.tm_mon == xmas.tm_mon );
   680   CPPUNIT_ASSERT( yet_more.tm_year == xmas.tm_year );
   681 
   682   ++j; // skip space
   683 
   684   j = tmg.get_time( j, e, io, err, &yet_more );
   685 
   686   CPPUNIT_ASSERT( err == ios_base::eofbit || err == ios_base::goodbit );
   687 
   688   CPPUNIT_ASSERT( yet_more.tm_sec == xmas.tm_sec );
   689   CPPUNIT_ASSERT( yet_more.tm_min == xmas.tm_min );
   690   CPPUNIT_ASSERT( yet_more.tm_hour == xmas.tm_hour );
   691   CPPUNIT_ASSERT( yet_more.tm_mday == xmas.tm_mday );
   692   CPPUNIT_ASSERT( yet_more.tm_mon == xmas.tm_mon );
   693   CPPUNIT_ASSERT( yet_more.tm_year == xmas.tm_year );
   694 }
   695 
   696 void LocaleTest::_ctype_facet( const locale& loc, const ref_locale&)
   697 {
   698 #  if !(defined (__DMC__) && defined (_DLL))
   699   CPPUNIT_ASSERT( has_facet<ctype<char> >(loc) );
   700   ctype<char> const& ct = use_facet<ctype<char> >(loc);
   701 
   702   //is
   703   {
   704     CPPUNIT_ASSERT( ct.is(ctype_base::digit, '0') );
   705     CPPUNIT_ASSERT( ct.is(ctype_base::upper, 'A') );
   706     CPPUNIT_ASSERT( ct.is(ctype_base::lower, 'a') );
   707     CPPUNIT_ASSERT( ct.is(ctype_base::alpha, 'A') );
   708     CPPUNIT_ASSERT( ct.is(ctype_base::space, ' ') );
   709     CPPUNIT_ASSERT( !ct.is(ctype_base::space, '2') );
   710     CPPUNIT_ASSERT( ct.is(ctype_base::punct, '.') );
   711     CPPUNIT_ASSERT( ct.is(ctype_base::xdigit, 'a') );
   712   }
   713 
   714   //is range
   715   {
   716     char values[] = "0Aa .";
   717     ctype_base::mask res[sizeof(values)];
   718     ct.is(values, values + sizeof(values), res);
   719     // '0'
   720     CPPUNIT_ASSERT( (res[0] & ctype_base::print) != 0 );
   721     CPPUNIT_ASSERT( (res[0] & ctype_base::digit) != 0 );
   722     CPPUNIT_ASSERT( (res[0] & ctype_base::xdigit) != 0 );
   723     // 'A'
   724     CPPUNIT_ASSERT( (res[1] & ctype_base::print) != 0 );
   725     CPPUNIT_ASSERT( (res[1] & ctype_base::alpha) != 0 );
   726     CPPUNIT_ASSERT( (res[1] & ctype_base::xdigit) != 0 );
   727     CPPUNIT_ASSERT( (res[1] & ctype_base::upper) != 0 );
   728     // 'a'
   729     CPPUNIT_ASSERT( (res[2] & ctype_base::print) != 0 );
   730     CPPUNIT_ASSERT( (res[2] & ctype_base::alpha) != 0 );
   731     CPPUNIT_ASSERT( (res[2] & ctype_base::xdigit) != 0 );
   732     CPPUNIT_ASSERT( (res[2] & ctype_base::lower) != 0 );
   733     CPPUNIT_ASSERT( (res[2] & ctype_base::space) == 0 );
   734     // ' '
   735     CPPUNIT_ASSERT( (res[3] & ctype_base::print) != 0 );
   736     CPPUNIT_ASSERT( (res[3] & ctype_base::space) != 0 );
   737     CPPUNIT_ASSERT( (res[3] & ctype_base::digit) == 0 );
   738     // '.'
   739     CPPUNIT_ASSERT( (res[4] & ctype_base::print) != 0 );
   740     CPPUNIT_ASSERT( (res[4] & ctype_base::punct) != 0 );
   741     CPPUNIT_ASSERT( (res[4] & ctype_base::digit) == 0 );
   742   }
   743 
   744   //scan_is
   745   {
   746     char range[] = "abAc123 .";
   747     const char *rbeg = range;
   748     const char *rend = range + sizeof(range);
   749 
   750     const char *res;
   751     res = ct.scan_is((ctype_base::mask)(ctype_base::alpha | ctype_base::lower), rbeg, rend);
   752     CPPUNIT_ASSERT( res != rend );
   753     CPPUNIT_ASSERT( *res == 'a' );
   754 
   755     res = ct.scan_is(ctype_base::upper, rbeg, rend);
   756     CPPUNIT_ASSERT( res != rend );
   757     CPPUNIT_ASSERT( *res == 'A' );
   758 
   759     res = ct.scan_is(ctype_base::punct, rbeg, rend);
   760     CPPUNIT_ASSERT( res != rend );
   761     CPPUNIT_ASSERT( *res == '.' );
   762   }
   763 
   764   //scan_not
   765   {
   766     char range[] = "abAc123 .";
   767     const char *rbeg = range;
   768     const char *rend = range + sizeof(range);
   769 
   770     const char *res;
   771     res = ct.scan_not((ctype_base::mask)(ctype_base::alpha | ctype_base::lower), rbeg, rend);
   772     CPPUNIT_ASSERT( res != rend );
   773     CPPUNIT_ASSERT( *res == '1' );
   774 
   775     res = ct.scan_not(ctype_base::alpha, rbeg, rend);
   776     CPPUNIT_ASSERT( res != rend );
   777     CPPUNIT_ASSERT( *res == '1' );
   778 
   779     res = ct.scan_not(ctype_base::punct, rbeg, rend);
   780     CPPUNIT_ASSERT( res != rend );
   781     CPPUNIT_ASSERT( *res == 'a' );
   782   }
   783 
   784   //toupper
   785   {
   786     CPPUNIT_ASSERT( ct.toupper('a') == 'A' );
   787     CPPUNIT_ASSERT( ct.toupper('A') == 'A' );
   788     CPPUNIT_ASSERT( ct.toupper('1') == '1' );
   789   }
   790 
   791   //toupper range
   792   {
   793     char range[] = "abAc1";
   794     char expected_range[] = "ABAC1";
   795     ct.toupper(range, range + sizeof(range));
   796     CPPUNIT_ASSERT( equal(range, range + sizeof(range), expected_range) );
   797   }
   798 
   799   //tolower
   800   {
   801     CPPUNIT_ASSERT( ct.tolower('A') == 'a' );
   802     CPPUNIT_ASSERT( ct.tolower('a') == 'a' );
   803     CPPUNIT_ASSERT( ct.tolower('1') == '1' );
   804   }
   805 
   806   //tolower range
   807   {
   808     char range[] = "ABaC1";
   809     char expected_range[] = "abac1";
   810     ct.tolower(range, range + sizeof(range));
   811     CPPUNIT_ASSERT( equal(range, range + sizeof(range), expected_range) );
   812   }
   813 
   814   //widen
   815   {
   816     CPPUNIT_ASSERT( ct.widen('a') == 'a' );
   817   }
   818 
   819   //widen range
   820   {
   821     char range[] = "ABaC1";
   822     char res[sizeof(range)];
   823     ct.widen(range, range + sizeof(range), res);
   824     CPPUNIT_ASSERT( equal(range, range + sizeof(range), res) );
   825   }
   826 
   827   //narrow
   828   {
   829     CPPUNIT_ASSERT( ct.narrow('a', 'b') == 'a' );
   830   }
   831 
   832   //narrow range
   833   {
   834     char range[] = "ABaC1";
   835     char res[sizeof(range)];
   836     ct.narrow(range, range + sizeof(range), 'b', res);
   837     CPPUNIT_ASSERT( equal(range, range + sizeof(range), res) );
   838   }
   839 #  endif /* __DMC__ */
   840 }
   841 
   842 template <class _Tp>
   843 void test_supported_locale(LocaleTest inst, _Tp __test) {
   844   size_t n = sizeof(tested_locales) / sizeof(tested_locales[0]);
   845   for (size_t i = 0; i < n; ++i) {
   846     auto_ptr<locale> loc;
   847 #  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
   848     try {
   849       loc.reset(new locale(tested_locales[i].name));
   850     }
   851     catch (runtime_error const&) {
   852       //This locale is not supported.
   853       continue;
   854     }
   855 #  else
   856     //Without exception support we only test C locale.
   857     if (tested_locales[i].name[0] != 'C' ||
   858         tested_locales[i].name[1] != 0)
   859       continue;
   860     loc.reset(new locale(tested_locales[i].name));
   861 #  endif
   862     CPPUNIT_MESSAGE( loc->name().c_str() );
   863     (inst.*__test)(*loc, tested_locales[i]);
   864   }
   865 }
   866 
   867 void LocaleTest::locale_by_name() {
   868 #  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
   869   /*
   870    * Check of the 22.1.1.2.7 standard point. Construction of a locale
   871    * instance from a null pointer or an unknown name should result in
   872    * a runtime_error exception.
   873    */
   874   try {
   875     locale loc(static_cast<char const*>(0));
   876     CPPUNIT_ASSERT( false );
   877   }
   878   catch (runtime_error const&) {
   879   }
   880   catch (...) {
   881     CPPUNIT_ASSERT( false );
   882   }
   883 
   884   try {
   885     locale loc("yasli_language");
   886     CPPUNIT_ASSERT( false );
   887   }
   888   catch (runtime_error const&) {
   889   }
   890   catch (...) {
   891     CPPUNIT_ASSERT( false );
   892   }
   893 #  endif
   894 }
   895 
   896 void LocaleTest::loc_has_facet() {
   897   locale loc("C");
   898   typedef numpunct<char> implemented_facet;
   899   CPPUNIT_ASSERT( has_facet<implemented_facet>(loc) );
   900   /*
   901   typedef num_put<char, back_insert_iterator<string> > not_implemented_facet;
   902   CPPUNIT_ASSERT( !has_facet<not_implemented_facet>(loc) );
   903   */
   904 }
   905 
   906 void LocaleTest::num_put_get()
   907 { test_supported_locale(*this, &LocaleTest::_num_put_get); }
   908 
   909 void LocaleTest::money_put_get()
   910 { test_supported_locale(*this, &LocaleTest::_money_put_get); }
   911 
   912 void LocaleTest::money_put_X_bug()
   913 { test_supported_locale(*this, &LocaleTest::_money_put_X_bug); }
   914 
   915 void LocaleTest::time_put_get()
   916 { test_supported_locale(*this, &LocaleTest::_time_put_get); }
   917 
   918 void LocaleTest::collate_facet()
   919 {
   920   {
   921     CPPUNIT_ASSERT( has_facet<collate<char> >(locale::classic()) );
   922     collate<char> const& col = use_facet<collate<char> >(locale::classic());
   923 
   924     char const str1[] = "abcdef1";
   925     char const str2[] = "abcdef2";
   926     const size_t size1 = sizeof(str1) / sizeof(str1[0]) - 1;
   927     const size_t size2 = sizeof(str2) / sizeof(str2[0]) - 1;
   928 
   929     CPPUNIT_ASSERT( col.compare(str1, str1 + size1 - 1, str2, str2 + size2 - 1) == 0 );
   930     CPPUNIT_ASSERT( col.compare(str1, str1 + size1, str2, str2 + size2) == -1 );
   931 
   932     //Smallest string should be before largest one:
   933     CPPUNIT_ASSERT( col.compare(str1, str1 + size1 - 2, str2, str2 + size2 - 1) == -1 );
   934     CPPUNIT_ASSERT( col.compare(str1, str1 + size1 - 1, str2, str2 + size2 - 2) == 1 );
   935   }
   936 
   937 #  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
   938   try {
   939     locale loc("fr_FR.ISO-8859-1");
   940     {
   941       CPPUNIT_ASSERT( has_facet<collate<char> >(loc) );
   942       collate<char> const& col = use_facet<collate<char> >(loc);
   943 
   944       char const str1[] = "abcdef1";
   945       char const str2[] = "abcdef2";
   946       const size_t size1 = sizeof(str1) / sizeof(str1[0]) - 1;
   947       const size_t size2 = sizeof(str2) / sizeof(str2[0]) - 1;
   948 
   949       CPPUNIT_ASSERT( col.compare(str1, str1 + size1 - 1, str2, str2 + size2 - 1) == 0 );
   950       CPPUNIT_ASSERT( col.compare(str1, str1 + size1, str2, str2 + size2) == -1 );
   951 
   952       //Smallest string should be before largest one:
   953       CPPUNIT_ASSERT( col.compare(str1, str1 + size1 - 2, str2, str2 + size2 - 1) == -1 );
   954       CPPUNIT_ASSERT( col.compare(str1, str1 + size1 - 1, str2, str2 + size2 - 2) == 1 );
   955     }
   956     {
   957       CPPUNIT_ASSERT( has_facet<collate<char> >(loc) );
   958       collate<char> const& col = use_facet<collate<char> >(loc);
   959 
   960       string strs[] = {"abdd", "abçd", "abbd", "abcd"};
   961 
   962       string transformed[4];
   963       for (size_t i = 0; i < 4; ++i) {
   964         transformed[i] = col.transform(strs[i].data(), strs[i].data() + strs[i].size());
   965       }
   966 
   967       sort(strs, strs + 4, loc);
   968       // c and ç are considered same when strxfrm() is done on the string
   969       CPPUNIT_ASSERT( strs[0] == "abbd" );
   970       CPPUNIT_ASSERT( strs[1] == "abçd" );
   971       CPPUNIT_ASSERT( strs[2] == "abcd" );
   972       CPPUNIT_ASSERT( strs[3] == "abdd" );
   973 
   974       sort(transformed, transformed + 4);
   975 
   976       CPPUNIT_ASSERT( col.transform(strs[0].data(), strs[0].data() + strs[0].size()) == transformed[0] );
   977       CPPUNIT_ASSERT( col.transform(strs[1].data(), strs[1].data() + strs[1].size()) == transformed[1] );
   978       CPPUNIT_ASSERT( col.transform(strs[2].data(), strs[2].data() + strs[2].size()) == transformed[2] );
   979       CPPUNIT_ASSERT( col.transform(strs[3].data(), strs[3].data() + strs[3].size()) == transformed[3] );
   980 
   981       // Check empty string result in empty key.
   982       CPPUNIT_ASSERT( col.transform(strs[0].data(), strs[0].data()).empty() );
   983 
   984       // Check that only characters that matter are taken into accout to build the key.
   985       CPPUNIT_ASSERT( col.transform(strs[0].data(), strs[0].data() + 2) == col.transform(strs[1].data(), strs[1].data() + 2) );
   986     }
   987 #    if !defined (STLPORT) || !defined (_STLP_NO_WCHAR_T)
   988     {
   989       CPPUNIT_ASSERT( has_facet<collate<wchar_t> >(loc) );
   990       collate<wchar_t> const& col = use_facet<collate<wchar_t> >(loc);
   991 
   992       wchar_t const str1[] = L"abcdef1";
   993       wchar_t const str2[] = L"abcdef2";
   994       const size_t size1 = sizeof(str1) / sizeof(str1[0]) - 1;
   995       const size_t size2 = sizeof(str2) / sizeof(str2[0]) - 1;
   996 
   997       CPPUNIT_ASSERT( col.compare(str1, str1 + size1 - 1, str2, str2 + size2 - 1) == 0 );
   998       CPPUNIT_ASSERT( col.compare(str1, str1 + size1, str2, str2 + size2) == -1 );
   999 
  1000       //Smallest string should be before largest one:
  1001       CPPUNIT_ASSERT( col.compare(str1, str1 + size1 - 2, str2, str2 + size2 - 1) == -1 );
  1002       CPPUNIT_ASSERT( col.compare(str1, str1 + size1 - 1, str2, str2 + size2 - 2) == 1 );
  1003     }
  1004     {
  1005       size_t i;
  1006       CPPUNIT_ASSERT( has_facet<collate<wchar_t> >(loc) );
  1007       collate<wchar_t> const& col = use_facet<collate<wchar_t> >(loc);
  1008 
  1009       // Here we would like to use L"abçd" but it looks like all compilers
  1010       // do not support storage of unicode characters in exe resulting in
  1011       // compilation error. We avoid this test for the moment.
  1012       wstring strs[] = {L"abdd", L"abcd", L"abbd", L"abcd"};
  1013 
  1014       wstring transformed[4];
  1015       for (i = 0; i < 4; ++i) {
  1016         transformed[i] = col.transform(strs[i].data(), strs[i].data() + strs[i].size());
  1017       }
  1018 
  1019       sort(strs, strs + 4, loc);
  1020       CPPUNIT_ASSERT( strs[0] == L"abbd" );
  1021       CPPUNIT_ASSERT( strs[1] == L"abcd" );
  1022       CPPUNIT_ASSERT( strs[2] == L"abcd" );
  1023       CPPUNIT_ASSERT( strs[3] == L"abdd" );
  1024 
  1025       sort(transformed, transformed + 4);
  1026 
  1027       CPPUNIT_ASSERT( col.transform(strs[0].data(), strs[0].data() + strs[0].size()) == transformed[0] );
  1028       CPPUNIT_ASSERT( col.transform(strs[1].data(), strs[1].data() + strs[1].size()) == transformed[1] );
  1029       CPPUNIT_ASSERT( col.transform(strs[2].data(), strs[2].data() + strs[2].size()) == transformed[2] );
  1030       CPPUNIT_ASSERT( col.transform(strs[3].data(), strs[3].data() + strs[3].size()) == transformed[3] );
  1031 
  1032       CPPUNIT_ASSERT( col.transform(strs[0].data(), strs[0].data()).empty() );
  1033 
  1034       CPPUNIT_ASSERT( col.transform(strs[0].data(), strs[0].data() + 2) == col.transform(strs[1].data(), strs[1].data() + 2) );
  1035     }
  1036 #    endif
  1037   }
  1038   catch (runtime_error const&) {
  1039     CPPUNIT_MESSAGE("No french locale to check collate facet");
  1040   }
  1041 #  endif
  1042 }
  1043 
  1044 void LocaleTest::ctype_facet()
  1045 { test_supported_locale(*this, &LocaleTest::_ctype_facet); }
  1046 
  1047 void LocaleTest::locale_init_problem() {
  1048 #  if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES)
  1049   test_supported_locale(*this, &LocaleTest::_locale_init_problem);
  1050 #  endif
  1051 }
  1052 
  1053 
  1054 /*
  1055  * Creation of a locale instance imply initialization of some STLport internal
  1056  * static objects first. We use a static instance of locale to check that this
  1057  * initialization is done correctly.
  1058  */
  1059 static locale global_loc;
  1060 static locale other_loc("");
  1061 
  1062 #  if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES)
  1063 void LocaleTest::_locale_init_problem( const locale& loc, const ref_locale&)
  1064 {
  1065 #    if !defined (__APPLE__) && !defined (__FreeBSD__) || \
  1066         !defined(__GNUC__) || ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__> 3)))
  1067   typedef codecvt<char,char,mbstate_t> my_facet;
  1068 #    else
  1069 // std::mbstate_t required for gcc 3.3.2 on FreeBSD...
  1070 // I am not sure what key here---FreeBSD or 3.3.2...
  1071 //      - ptr 2005-04-04
  1072   typedef codecvt<char,char,std::mbstate_t> my_facet;
  1073 #    endif
  1074 
  1075 #    if !(defined (__DMC__) && defined (_DLL))
  1076   locale loc_ref(global_loc);
  1077   {
  1078     locale gloc( loc_ref, new my_facet() );
  1079     CPPUNIT_ASSERT( has_facet<my_facet>( gloc ) );
  1080     //The following code is just here to try to confuse the reference counting underlying mecanism:
  1081     locale::global( locale::classic() );
  1082     locale::global( gloc );
  1083   }
  1084 
  1085 #      if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
  1086   try {
  1087 #      endif
  1088     ostringstream os("test") ;
  1089     locale loc2( loc, new my_facet() );
  1090     CPPUNIT_ASSERT( has_facet<my_facet>( loc2 ) );
  1091     os.imbue( loc2 );
  1092 #      if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
  1093   }
  1094   catch ( runtime_error& ) {
  1095     CPPUNIT_ASSERT( false );
  1096   }
  1097   catch ( ... ) {
  1098    CPPUNIT_ASSERT( false );
  1099   }
  1100 #      endif
  1101 
  1102 #      if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
  1103   try {
  1104 #      endif
  1105     ostringstream os2("test2");
  1106 #      if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
  1107   }
  1108   catch ( runtime_error& ) {
  1109     CPPUNIT_ASSERT( false );
  1110   }
  1111   catch ( ... ) {
  1112     CPPUNIT_ASSERT( false );
  1113   }
  1114 #      endif
  1115 #    endif /* __DMC__ */
  1116 }
  1117 #  endif
  1118 
  1119 void LocaleTest::default_locale()
  1120 {
  1121   locale loc( "" );
  1122 }
  1123 
  1124 void LocaleTest::facet_id()
  1125 {
  1126 #if defined (__SYMBIAN32__NO_STATIC_IMPORTS__) || defined (__SYMBIAN32__WSD__)
  1127 #  if defined (STLPORT)
  1128   locale::id _id_01 = collate<char>::GetFacetLocaleId();
  1129   CPPUNIT_CHECK( _id_01._M_index == 1 );
  1130 
  1131   locale::id _id_02 = ctype<char>::GetFacetLocaleId();
  1132   CPPUNIT_CHECK( _id_02._M_index == 2 );
  1133 
  1134 #    ifndef _STLP_NO_MBSTATE_T
  1135   locale::id _id_03 = codecvt<char, char, mbstate_t>::GetFacetLocaleId();
  1136   CPPUNIT_CHECK( _id_03._M_index == 3 );
  1137 #    endif
  1138 
  1139   locale::id _id_04 = moneypunct<char, true>::GetFacetLocaleId();
  1140   CPPUNIT_CHECK( _id_04._M_index == 4 );
  1141 
  1142   locale::id _id_05 = moneypunct<char, false>::GetFacetLocaleId();
  1143   CPPUNIT_CHECK( _id_05._M_index == 5 );
  1144 
  1145   locale::id _id_06 = numpunct<char>::GetFacetLocaleId();
  1146   CPPUNIT_CHECK( _id_06._M_index == 6 );
  1147 
  1148   locale::id _id_07 = messages<char>::GetFacetLocaleId();
  1149   CPPUNIT_CHECK( _id_07._M_index == 7 );
  1150 
  1151   locale::id _id_08 = money_get<char, istreambuf_iterator<char, char_traits<char> > >::GetFacetLocaleId();
  1152   CPPUNIT_CHECK( _id_08._M_index == 8 );
  1153 
  1154   /*
  1155   locale::id _id_09 = money_get<char, const char*>::id;
  1156   CPPUNIT_CHECK( _id_09._M_index == 9 );
  1157   */
  1158 
  1159   locale::id _id_10 = money_put<char, ostreambuf_iterator<char, char_traits<char> > >::GetFacetLocaleId();
  1160   CPPUNIT_CHECK( _id_10._M_index == 10 );
  1161 
  1162   /*
  1163   locale::id _id_11 = money_put<char, char*>::id;
  1164   CPPUNIT_CHECK( _id_11._M_index == 11 );
  1165   */
  1166 
  1167   locale::id _id_12 = num_get<char, istreambuf_iterator<char, char_traits<char> > >::GetFacetLocaleId();
  1168   CPPUNIT_CHECK( _id_12._M_index == 12 );
  1169 
  1170   /*
  1171   locale::id _id_13 = num_get<char, const char*>::id;
  1172   CPPUNIT_CHECK( _id_13._M_index == 13 );
  1173   */
  1174 
  1175   locale::id _id_14 = num_put<char, ostreambuf_iterator<char, char_traits<char> > >::GetFacetLocaleId();
  1176   CPPUNIT_CHECK( _id_14._M_index == 14 );
  1177 
  1178   /*
  1179   locale::id _id_15 = num_put<char, char*>::id;
  1180   CPPUNIT_CHECK( _id_15._M_index == 15 );
  1181   */
  1182 
  1183   locale::id _id_16 = time_get<char, istreambuf_iterator<char, char_traits<char> > >::GetFacetLocaleId();
  1184   CPPUNIT_CHECK( _id_16._M_index == 16 );
  1185 
  1186   /*
  1187   locale::id _id_17 = time_get<char, const char*>::id;
  1188   CPPUNIT_CHECK( _id_17._M_index == 17 );
  1189   */
  1190 
  1191   locale::id _id_18 = time_put<char, ostreambuf_iterator<char, char_traits<char> > >::GetFacetLocaleId();
  1192   CPPUNIT_CHECK( _id_18._M_index == 18 );
  1193 
  1194   /*
  1195   locale::id _id_19 = time_put<char, char*>::id;
  1196   CPPUNIT_CHECK( _id_19._M_index == 19 );
  1197   */
  1198 
  1199 #    ifndef _STLP_NO_WCHAR_T
  1200   locale::id _id_20 = collate<wchar_t>::GetFacetLocaleId();
  1201   CPPUNIT_CHECK( _id_20._M_index == 20 );
  1202 
  1203   locale::id _id_21 = ctype<wchar_t>::GetFacetLocaleId();
  1204   CPPUNIT_CHECK( _id_21._M_index == 21 );
  1205 
  1206 #      ifndef _STLP_NO_MBSTATE_T
  1207   locale::id _id_22 = codecvt<wchar_t, char, mbstate_t>::GetFacetLocaleId();
  1208   CPPUNIT_CHECK( _id_22._M_index == 22 );
  1209 #      endif
  1210   locale::id _id_23 = moneypunct<wchar_t, true>::GetFacetLocaleId();
  1211   CPPUNIT_CHECK( _id_23._M_index == 23 );
  1212 
  1213   locale::id _id_24 = moneypunct<wchar_t, false>::GetFacetLocaleId();
  1214   CPPUNIT_CHECK( _id_24._M_index == 24 );
  1215 
  1216   locale::id _id_25 = numpunct<wchar_t>::GetFacetLocaleId();
  1217   CPPUNIT_CHECK( _id_25._M_index == 25 );
  1218 
  1219   locale::id _id_26 = messages<wchar_t>::GetFacetLocaleId();
  1220   CPPUNIT_CHECK( _id_26._M_index == 26 );
  1221 
  1222   locale::id _id_27 = money_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::GetFacetLocaleId();
  1223   CPPUNIT_CHECK( _id_27._M_index == 27 );
  1224 
  1225   /*
  1226   locale::id _id_28 = money_get<wchar_t, const wchar_t*>::id;
  1227   CPPUNIT_CHECK( _id_28._M_index == 28 );
  1228   */
  1229 
  1230   locale::id _id_29 = money_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::GetFacetLocaleId();
  1231   CPPUNIT_CHECK( _id_29._M_index == 29 );
  1232 
  1233   /*
  1234   locale::id _id_30 = money_put<wchar_t, wchar_t*>::id;
  1235   CPPUNIT_CHECK( _id_30._M_index == 30 );
  1236   */
  1237 
  1238   locale::id _id_31 = num_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::GetFacetLocaleId();
  1239   CPPUNIT_CHECK( _id_31._M_index == 31 );
  1240 
  1241   /*
  1242   locale::id _id_32 = num_get<wchar_t, const wchar_t*>::id;
  1243   CPPUNIT_CHECK( _id_32._M_index == 32 );
  1244   */
  1245 
  1246   locale::id _id_33 = num_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > > ::GetFacetLocaleId();
  1247   CPPUNIT_CHECK( _id_33._M_index == 33 );
  1248 
  1249   /*
  1250   locale::id _id_34 = num_put<wchar_t, wchar_t*>::id;
  1251   CPPUNIT_CHECK( _id_34._M_index == 34 );
  1252   */
  1253 
  1254   locale::id _id_35 = time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::GetFacetLocaleId();
  1255   CPPUNIT_CHECK( _id_35._M_index == 35 );
  1256 
  1257   /*
  1258   locale::id _id_36 = time_get<wchar_t, const wchar_t*>::id;
  1259   CPPUNIT_CHECK( _id_36._M_index == 36 );
  1260   */
  1261 
  1262   locale::id _id_37 = time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::GetFacetLocaleId();
  1263   CPPUNIT_CHECK( _id_37._M_index == 37 );
  1264 
  1265   /*
  1266   locale::id _id_38 = time_put<wchar_t, wchar_t*>::id;
  1267   CPPUNIT_CHECK( _id_38._M_index == 38 );
  1268   */
  1269 #    endif
  1270 #  endif
  1271 
  1272 #else
  1273 
  1274 #  if defined (STLPORT)
  1275   locale::id _id_01 = collate<char>::id;
  1276   CPPUNIT_CHECK( _id_01._M_index == 1 );
  1277 
  1278   locale::id _id_02 = ctype<char>::id;
  1279   CPPUNIT_CHECK( _id_02._M_index == 2 );
  1280 
  1281 #    ifndef _STLP_NO_MBSTATE_T
  1282   locale::id _id_03 = codecvt<char, char, mbstate_t>::id;
  1283   CPPUNIT_CHECK( _id_03._M_index == 3 );
  1284 #    endif
  1285 
  1286   locale::id _id_04 = moneypunct<char, true>::id;
  1287   CPPUNIT_CHECK( _id_04._M_index == 4 );
  1288 
  1289   locale::id _id_05 = moneypunct<char, false>::id;
  1290   CPPUNIT_CHECK( _id_05._M_index == 5 );
  1291 
  1292   locale::id _id_06 = numpunct<char>::id;
  1293   CPPUNIT_CHECK( _id_06._M_index == 6 );
  1294 
  1295   locale::id _id_07 = messages<char>::id;
  1296   CPPUNIT_CHECK( _id_07._M_index == 7 );
  1297 
  1298   locale::id _id_08 = money_get<char, istreambuf_iterator<char, char_traits<char> > >::id;
  1299   CPPUNIT_CHECK( _id_08._M_index == 8 );
  1300 
  1301   /*
  1302   locale::id _id_09 = money_get<char, const char*>::id;
  1303   CPPUNIT_CHECK( _id_09._M_index == 9 );
  1304   */
  1305 
  1306   locale::id _id_10 = money_put<char, ostreambuf_iterator<char, char_traits<char> > >::id;
  1307   CPPUNIT_CHECK( _id_10._M_index == 10 );
  1308 
  1309   /*
  1310   locale::id _id_11 = money_put<char, char*>::id;
  1311   CPPUNIT_CHECK( _id_11._M_index == 11 );
  1312   */
  1313 
  1314   locale::id _id_12 = num_get<char, istreambuf_iterator<char, char_traits<char> > >::id;
  1315   CPPUNIT_CHECK( _id_12._M_index == 12 );
  1316 
  1317   /*
  1318   locale::id _id_13 = num_get<char, const char*>::id;
  1319   CPPUNIT_CHECK( _id_13._M_index == 13 );
  1320   */
  1321 
  1322   locale::id _id_14 = num_put<char, ostreambuf_iterator<char, char_traits<char> > >::id;
  1323   CPPUNIT_CHECK( _id_14._M_index == 14 );
  1324 
  1325   /*
  1326   locale::id _id_15 = num_put<char, char*>::id;
  1327   CPPUNIT_CHECK( _id_15._M_index == 15 );
  1328   */
  1329 
  1330   locale::id _id_16 = time_get<char, istreambuf_iterator<char, char_traits<char> > >::id;
  1331   CPPUNIT_CHECK( _id_16._M_index == 16 );
  1332 
  1333   /*
  1334   locale::id _id_17 = time_get<char, const char*>::id;
  1335   CPPUNIT_CHECK( _id_17._M_index == 17 );
  1336   */
  1337 
  1338   locale::id _id_18 = time_put<char, ostreambuf_iterator<char, char_traits<char> > >::id;
  1339   CPPUNIT_CHECK( _id_18._M_index == 18 );
  1340 
  1341   /*
  1342   locale::id _id_19 = time_put<char, char*>::id;
  1343   CPPUNIT_CHECK( _id_19._M_index == 19 );
  1344   */
  1345 
  1346 #    ifndef _STLP_NO_WCHAR_T
  1347   locale::id _id_20 = collate<wchar_t>::id;
  1348   CPPUNIT_CHECK( _id_20._M_index == 20 );
  1349 
  1350   locale::id _id_21 = ctype<wchar_t>::id;
  1351   CPPUNIT_CHECK( _id_21._M_index == 21 );
  1352 
  1353 #      ifndef _STLP_NO_MBSTATE_T
  1354   locale::id _id_22 = codecvt<wchar_t, char, mbstate_t>::id;
  1355   CPPUNIT_CHECK( _id_22._M_index == 22 );
  1356 #      endif
  1357   locale::id _id_23 = moneypunct<wchar_t, true>::id;
  1358   CPPUNIT_CHECK( _id_23._M_index == 23 );
  1359 
  1360   locale::id _id_24 = moneypunct<wchar_t, false>::id;
  1361   CPPUNIT_CHECK( _id_24._M_index == 24 );
  1362 
  1363   locale::id _id_25 = numpunct<wchar_t>::id;
  1364   CPPUNIT_CHECK( _id_25._M_index == 25 );
  1365 
  1366   locale::id _id_26 = messages<wchar_t>::id;
  1367   CPPUNIT_CHECK( _id_26._M_index == 26 );
  1368 
  1369   locale::id _id_27 = money_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id;
  1370   CPPUNIT_CHECK( _id_27._M_index == 27 );
  1371 
  1372   /*
  1373   locale::id _id_28 = money_get<wchar_t, const wchar_t*>::id;
  1374   CPPUNIT_CHECK( _id_28._M_index == 28 );
  1375   */
  1376 
  1377   locale::id _id_29 = money_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id;
  1378   CPPUNIT_CHECK( _id_29._M_index == 29 );
  1379 
  1380   /*
  1381   locale::id _id_30 = money_put<wchar_t, wchar_t*>::id;
  1382   CPPUNIT_CHECK( _id_30._M_index == 30 );
  1383   */
  1384 
  1385   locale::id _id_31 = num_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id;
  1386   CPPUNIT_CHECK( _id_31._M_index == 31 );
  1387 
  1388   /*
  1389   locale::id _id_32 = num_get<wchar_t, const wchar_t*>::id;
  1390   CPPUNIT_CHECK( _id_32._M_index == 32 );
  1391   */
  1392 
  1393   locale::id _id_33 = num_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > > ::id;
  1394   CPPUNIT_CHECK( _id_33._M_index == 33 );
  1395 
  1396   /*
  1397   locale::id _id_34 = num_put<wchar_t, wchar_t*>::id;
  1398   CPPUNIT_CHECK( _id_34._M_index == 34 );
  1399   */
  1400 
  1401   locale::id _id_35 = time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id;
  1402   CPPUNIT_CHECK( _id_35._M_index == 35 );
  1403 
  1404   /*
  1405   locale::id _id_36 = time_get<wchar_t, const wchar_t*>::id;
  1406   CPPUNIT_CHECK( _id_36._M_index == 36 );
  1407   */
  1408 
  1409   locale::id _id_37 = time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id;
  1410   CPPUNIT_CHECK( _id_37._M_index == 37 );
  1411 
  1412   /*
  1413   locale::id _id_38 = time_put<wchar_t, wchar_t*>::id;
  1414   CPPUNIT_CHECK( _id_38._M_index == 38 );
  1415   */
  1416 #    endif
  1417 #  endif
  1418 #  endif //__WINSCW__
  1419 }
  1420 
  1421 void LocaleTest::combine()
  1422 {
  1423 #  if (!defined (STLPORT) || \
  1424        (defined (_STLP_USE_EXCEPTIONS) && !defined (_STLP_NO_MEMBER_TEMPLATES) && !defined (_STLP_NO_EXPLICIT_FUNCTION_TMPL_ARGS)))
  1425   auto_ptr<locale> loc1, loc2;
  1426   size_t loc1_index = 0;
  1427   size_t n = sizeof(tested_locales) / sizeof(tested_locales[0]);
  1428   for (size_t i = 0; i < n; ++i) {
  1429     try {
  1430       locale *ploc = new locale(tested_locales[i].name);
  1431       if (loc1.get() == 0)
  1432       {
  1433         loc1.reset(ploc);
  1434         loc1_index = i;
  1435         continue;
  1436       }
  1437       else
  1438       {
  1439         loc2.reset(ploc);
  1440       }
  1441 
  1442       //We can start the test
  1443       ostringstream ostr;
  1444       ostr << "combining '" << loc2->name() << "' money facets with '" << loc1->name() << "'";
  1445       CPPUNIT_MESSAGE( ostr.str().c_str() );
  1446 
  1447       //We are going to combine money facets as all formats are different.
  1448       {
  1449         //We check that resulting locale has correctly acquire loc2 facets.
  1450         locale loc = loc1->combine<moneypunct<char, true> >(*loc2);
  1451         loc = loc.combine<moneypunct<char, false> >(*loc2);
  1452         loc = loc.combine<money_put<char> >(*loc2);
  1453         loc = loc.combine<money_get<char> >(*loc2);
  1454 
  1455         //Check loc has the correct facets:
  1456         _money_put_get2(*loc2, loc, tested_locales[i]);
  1457 
  1458         //Check loc1 has not been impacted:
  1459         _money_put_get2(*loc1, *loc1, tested_locales[loc1_index]);
  1460 
  1461         //Check loc2 has not been impacted:
  1462         _money_put_get2(*loc2, *loc2, tested_locales[i]);
  1463       }
  1464       {
  1465         //We check that resulting locale has not wrongly acquire loc1 facets that hasn't been combine:
  1466         locale loc = loc2->combine<numpunct<char> >(*loc1);
  1467         loc = loc.combine<time_put<char> >(*loc1);
  1468         loc = loc.combine<time_get<char> >(*loc1);
  1469 
  1470         //Check loc has the correct facets:
  1471         _money_put_get2(*loc2, loc, tested_locales[i]);
  1472 
  1473         //Check loc1 has not been impacted:
  1474         _money_put_get2(*loc1, *loc1, tested_locales[loc1_index]);
  1475 
  1476         //Check loc2 has not been impacted:
  1477         _money_put_get2(*loc2, *loc2, tested_locales[i]);
  1478       }
  1479 
  1480       {
  1481         // Check auto combination do not result in weird reference counting behavior 
  1482         // (might generate a crash).
  1483         loc1->combine<numpunct<char> >(*loc1);
  1484       }
  1485 
  1486       loc1.reset(loc2.release());
  1487       loc1_index = i;
  1488     }
  1489     catch (runtime_error const&) {
  1490       //This locale is not supported.
  1491       continue;
  1492     }
  1493   }
  1494 #  endif
  1495 }
  1496 
  1497 #endif