Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (c) 1999
      3  * Silicon Graphics Computer Systems, Inc.
      4  *
      5  * Copyright (c) 1999
      6  * Boris Fomitchev
      7  *
      8  * This material is provided "as is", with absolutely no warranty expressed
      9  * or implied. Any use is at your own risk.
     10  *
     11  * Permission to use or copy this software for any purpose is hereby granted
     12  * without fee, provided the above notices are retained on all copies.
     13  * Permission to modify the code and to distribute modified code is granted,
     14  * provided the above notices are retained, and a notice that the code was
     15  * modified is included with the above copyright notice.
     16  *
     17  */
     18 #include "stlport_prefix.h"
     19 
     20 #include <hash_map>
     21 #include <vector>
     22 
     23 #include <locale>
     24 #include <istream>
     25 
     26 #include <algorithm>
     27 #include <functional>
     28 
     29 #include "c_locale.h"
     30 #include "locale_impl.h"
     31 #include "acquire_release.h"
     32 
     33 _STLP_BEGIN_NAMESPACE
     34 
     35 //----------------------------------------------------------------------
     36 // ctype_byname<char>
     37 
     38 #if defined (__DMC__)
     39 _STLP_DECLSPEC
     40 #endif
     41 ctype_byname<char>::ctype_byname(const char* name, size_t refs)
     42     : ctype<char>( 0, false, refs) {
     43   if (!name)
     44     locale::_M_throw_on_null_name();
     45 
     46   int __err_code;
     47   char buf[_Locale_MAX_SIMPLE_NAME];
     48   _M_ctype = _STLP_PRIV __acquire_ctype(name, buf, 0, &__err_code);
     49   if (!_M_ctype)
     50     locale::_M_throw_on_creation_failure(__err_code, name, "ctype");
     51 
     52   _M_init();
     53 }
     54 
     55 void ctype_byname<char>::_M_init() {
     56   _M_ctype_table = _M_byname_table;
     57 
     58   // We have to do this, instead of just pointer twiddling, because
     59   // ctype_base::mask isn't the same type as _Locale_mask_t.
     60   const _Locale_mask_t* p = _Locale_ctype_table(_M_ctype);
     61   for (size_t i = 0; i != table_size; ++i) {
     62     _M_byname_table[i] = ctype_base::mask(p[i]);
     63   }
     64 }
     65 
     66 ctype_byname<char>::~ctype_byname()
     67 { _STLP_PRIV __release_ctype(_M_ctype); }
     68 
     69 char ctype_byname<char>::do_toupper(char c) const
     70 { return (char)_Locale_toupper(_M_ctype, c); }
     71 
     72 char ctype_byname<char>::do_tolower(char c) const
     73 { return (char)_Locale_tolower(_M_ctype, c); }
     74 
     75 const char*
     76 ctype_byname<char>::do_toupper(char* first, const char* last) const {
     77   for ( ; first != last ; ++first)
     78     *first = (char)_Locale_toupper(_M_ctype, *first);
     79   return last;
     80 }
     81 
     82 const char*
     83 ctype_byname<char>::do_tolower(char* first, const char* last) const {
     84   for ( ; first != last ; ++first)
     85     *first = (char)_Locale_tolower(_M_ctype, *first);
     86   return last;
     87 }
     88 
     89 
     90 // Some helper functions used in ctype<>::scan_is and scan_is_not.
     91 #if !defined (_STLP_NO_WCHAR_T)
     92 
     93 _STLP_MOVE_TO_PRIV_NAMESPACE
     94 
     95 // ctype_byname<wchar_t>
     96 
     97 struct _Ctype_byname_w_is_mask : public unary_function<wchar_t, bool> {
     98   _Locale_mask_t M;
     99   _Locale_ctype* M_ctp;
    100 
    101   _Ctype_byname_w_is_mask(_Locale_mask_t m, _Locale_ctype* c)
    102     : M(m), M_ctp(c) {}
    103   bool operator()(wchar_t c) const
    104   { return _WLocale_ctype(M_ctp, c, M) != 0; }
    105 };
    106 
    107 _STLP_MOVE_TO_STD_NAMESPACE
    108 
    109 #if defined (__DMC__)
    110 _STLP_DECLSPEC
    111 #endif
    112 ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
    113   : ctype<wchar_t>(refs) {
    114   if (!name)
    115     locale::_M_throw_on_null_name();
    116 
    117   int __err_code;
    118   char buf[_Locale_MAX_SIMPLE_NAME];
    119   _M_ctype = _STLP_PRIV __acquire_ctype(name, buf, 0, &__err_code);
    120   if (!_M_ctype)
    121     locale::_M_throw_on_creation_failure(__err_code, name, "ctype");
    122 }
    123 
    124 ctype_byname<wchar_t>::~ctype_byname()
    125 { _STLP_PRIV __release_ctype(_M_ctype); }
    126 
    127 bool ctype_byname<wchar_t>::do_is(ctype_base::mask  m, wchar_t c) const
    128 { return _WLocale_ctype(_M_ctype, c, (_Locale_mask_t)m) != 0; }
    129 
    130 const wchar_t*
    131 ctype_byname<wchar_t>::do_is(const wchar_t* low, const wchar_t* high,
    132                              ctype_base::mask * m) const {
    133   _Locale_mask_t all_bits = _Locale_mask_t(ctype_base::space |
    134                                            ctype_base::print |
    135                                            ctype_base::cntrl |
    136                                            ctype_base::upper |
    137                                            ctype_base::lower |
    138                                            ctype_base::alpha |
    139                                            ctype_base::digit |
    140                                            ctype_base::punct |
    141                                            ctype_base::xdigit);
    142 
    143   for ( ; low < high; ++low, ++m)
    144     *m = ctype_base::mask (_WLocale_ctype(_M_ctype, *low, all_bits));
    145   return high;
    146 }
    147 
    148 const wchar_t*
    149 ctype_byname<wchar_t>
    150   ::do_scan_is(ctype_base::mask  m, const wchar_t* low, const wchar_t* high) const
    151 { return find_if(low, high, _STLP_PRIV _Ctype_byname_w_is_mask(m, _M_ctype)); }
    152 
    153 const wchar_t*
    154 ctype_byname<wchar_t>
    155   ::do_scan_not(ctype_base::mask  m, const wchar_t* low, const wchar_t* high) const
    156 { return find_if(low, high, not1(_STLP_PRIV _Ctype_byname_w_is_mask(m, _M_ctype))); }
    157 
    158 wchar_t ctype_byname<wchar_t>::do_toupper(wchar_t c) const
    159 { return _WLocale_toupper(_M_ctype, c); }
    160 
    161 const wchar_t*
    162 ctype_byname<wchar_t>::do_toupper(wchar_t* low, const wchar_t* high) const {
    163   for ( ; low < high; ++low)
    164     *low = _WLocale_toupper(_M_ctype, *low);
    165   return high;
    166 }
    167 
    168 wchar_t ctype_byname<wchar_t>::do_tolower(wchar_t c) const
    169 { return _WLocale_tolower(_M_ctype, c); }
    170 
    171 const wchar_t*
    172 ctype_byname<wchar_t>::do_tolower(wchar_t* low, const wchar_t* high) const {
    173   for ( ; low < high; ++low)
    174     *low = _WLocale_tolower(_M_ctype, *low);
    175   return high;
    176 }
    177 
    178 #endif /* WCHAR_T */
    179 
    180 // collate_byname<char>
    181 #if defined (__DMC__)
    182 _STLP_DECLSPEC
    183 #endif
    184 collate_byname<char>::collate_byname(const char* name, size_t refs)
    185   : collate<char>(refs) {
    186   if (!name)
    187     locale::_M_throw_on_null_name();
    188 
    189   int __err_code;
    190   char buf[_Locale_MAX_SIMPLE_NAME];
    191   _M_collate = _STLP_PRIV __acquire_collate(name, buf, 0, &__err_code);
    192   if (!_M_collate)
    193     locale::_M_throw_on_creation_failure(__err_code, name, "collate");
    194 }
    195 
    196 collate_byname<char>::~collate_byname()
    197 { _STLP_PRIV __release_collate(_M_collate); }
    198 
    199 int collate_byname<char>::do_compare(const char* __low1,
    200                                      const char* __high1,
    201                                      const char* __low2,
    202                                      const char* __high2) const {
    203   return _Locale_strcmp(_M_collate,
    204                         __low1, __high1 - __low1,
    205                         __low2, __high2 - __low2);
    206 }
    207 
    208 collate_byname<char>::string_type
    209 collate_byname<char>::do_transform(const char* low, const char* high) const {
    210   if (low == high)
    211     return string_type();
    212 
    213   size_t n = _Locale_strxfrm(_M_collate, NULL, 0, low, high - low);
    214 
    215   // NOT PORTABLE.  What we're doing relies on internal details of the
    216   // string implementation.  (Contiguity of string elements and presence
    217   // of trailing zero.)
    218   string_type buf(n, 0);
    219   _Locale_strxfrm(_M_collate, &(*buf.begin()), n + 1, low, high - low);
    220   return buf;
    221 }
    222 
    223 
    224 #if !defined (_STLP_NO_WCHAR_T)
    225 
    226 // collate_byname<wchar_t>
    227 
    228 #if defined (__DMC__)
    229 _STLP_DECLSPEC
    230 #endif
    231 collate_byname<wchar_t>::collate_byname(const char* name, size_t refs)
    232   : collate<wchar_t>(refs) {
    233   if (!name)
    234     locale::_M_throw_on_null_name();
    235 
    236   int __err_code;
    237   char buf[_Locale_MAX_SIMPLE_NAME];
    238   _M_collate = _STLP_PRIV __acquire_collate(name, buf, 0, &__err_code);
    239   if (!_M_collate)
    240     locale::_M_throw_on_creation_failure(__err_code, name, "collate");
    241 }
    242 
    243 collate_byname<wchar_t>::~collate_byname()
    244 { _STLP_PRIV __release_collate(_M_collate); }
    245 
    246 int collate_byname<wchar_t>::do_compare(const wchar_t* low1,
    247                                         const wchar_t* high1,
    248                                         const wchar_t* low2,
    249                                         const wchar_t* high2) const {
    250   return _WLocale_strcmp(_M_collate,
    251                          low1, high1 - low1,
    252                          low2, high2 - low2);
    253 }
    254 
    255 collate_byname<wchar_t>::string_type
    256 collate_byname<wchar_t>::do_transform(const wchar_t* low,
    257                                       const wchar_t* high) const {
    258   if (low == high)
    259     return string_type();
    260 
    261   size_t n = _WLocale_strxfrm(_M_collate, NULL, 0, low, high - low);
    262 
    263   // NOT PORTABLE.  What we're doing relies on internal details of the
    264   // string implementation.  (Contiguity of string elements and presence
    265   // of trailing zero.)
    266   string_type buf(n, 0);
    267   _WLocale_strxfrm(_M_collate, &(*buf.begin()), n + 1, low, high - low);
    268   return buf;
    269 }
    270 
    271 #endif /*  _STLP_NO_WCHAR_T */
    272 
    273 //----------------------------------------------------------------------
    274 // codecvt_byname<char>
    275 
    276 codecvt_byname<char, char, mbstate_t>
    277   ::codecvt_byname(const char* name, size_t refs)
    278     : codecvt<char, char, mbstate_t>(refs) {
    279   if (!name)
    280     locale::_M_throw_on_null_name();
    281 }
    282 
    283 codecvt_byname<char, char, mbstate_t>::~codecvt_byname() {}
    284 
    285 
    286 #if !defined (_STLP_NO_WCHAR_T)
    287 
    288 //----------------------------------------------------------------------
    289 // codecvt_byname<wchar_t>
    290 codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname(const char* name, size_t refs)
    291   : codecvt<wchar_t, char, mbstate_t>(refs) {
    292   if (!name)
    293     locale::_M_throw_on_null_name();
    294 
    295   int __err_code;
    296   char buf[_Locale_MAX_SIMPLE_NAME];
    297   _M_codecvt = _STLP_PRIV __acquire_codecvt(name, buf, 0, &__err_code);
    298   if (!_M_codecvt)
    299     locale::_M_throw_on_creation_failure(__err_code, name, "ctype");
    300 }
    301 
    302 codecvt_byname<wchar_t, char, mbstate_t>::~codecvt_byname()
    303 { _STLP_PRIV __release_codecvt(_M_codecvt); }
    304 
    305 codecvt<wchar_t, char, mbstate_t>::result
    306 codecvt_byname<wchar_t, char, mbstate_t>::do_out(state_type&         state,
    307                                                  const intern_type*  from,
    308                                                  const intern_type*  from_end,
    309                                                  const intern_type*& from_next,
    310                                                  extern_type*        to,
    311                                                  extern_type*        to_limit,
    312                                                  extern_type*&       to_next) const {
    313   while (from != from_end && to != to_limit) {
    314     size_t chars_stored = _WLocale_wctomb(_M_codecvt,
    315                                           to, to_limit - to, *from,
    316                                           &state);
    317     if (chars_stored == (size_t) -1) {
    318       from_next = from;
    319       to_next   = to;
    320       return error;
    321     }
    322     else if (chars_stored == (size_t) -2) {
    323       from_next = from;
    324       to_next   = to;
    325       return partial;
    326     }
    327 
    328     ++from;
    329     to += chars_stored;
    330   }
    331 
    332   from_next = from;
    333   to_next   = to;
    334   return ok;
    335 }
    336 
    337 codecvt<wchar_t, char, mbstate_t>::result
    338 codecvt_byname<wchar_t, char, mbstate_t>::do_in(state_type&         state,
    339                                                 const extern_type*  from,
    340                                                 const extern_type*  from_end,
    341                                                 const extern_type*& from_next,
    342                                                 intern_type*        to,
    343                                                 intern_type*        to_end,
    344                                                 intern_type*&       to_next) const {
    345   while (from != from_end && to != to_end) {
    346     size_t chars_read = _WLocale_mbtowc(_M_codecvt,
    347                                         to, from, from_end - from,
    348                                         &state);
    349     if (chars_read == (size_t) -1) {
    350       from_next = from;
    351       to_next   = to;
    352       return error;
    353     }
    354 
    355     if (chars_read == (size_t) -2) {
    356       from_next = from;
    357       to_next   = to;
    358       return partial;
    359     }
    360 
    361     from += chars_read;
    362     to++;
    363   }
    364 
    365   from_next = from;
    366   to_next   = to;
    367   return ok;
    368 }
    369 
    370 codecvt<wchar_t, char, mbstate_t>::result
    371 codecvt_byname<wchar_t, char, mbstate_t>::do_unshift(state_type&   state,
    372                                                      extern_type*  to,
    373                                                      extern_type*  to_limit,
    374                                                      extern_type*& to_next) const {
    375   to_next = to;
    376   size_t result = _WLocale_unshift(_M_codecvt, &state,
    377                                    to, to_limit - to, &to_next);
    378   if (result == (size_t) -1)
    379     return error;
    380   else if (result == (size_t) -2)
    381     return partial;
    382   else
    383 #    if defined (__ISCPP__)
    384     return /*to_next == to ? noconv :*/ ok;
    385 #    else
    386     return to_next == to ? noconv : ok;
    387 #    endif
    388 }
    389 
    390 int
    391 codecvt_byname<wchar_t, char, mbstate_t>::do_encoding() const _STLP_NOTHROW {
    392   if (_WLocale_is_stateless(_M_codecvt)) {
    393     int max_width = _WLocale_mb_cur_max(_M_codecvt);
    394     int min_width = _WLocale_mb_cur_min(_M_codecvt);
    395     return min_width == max_width ? min_width : 0;
    396   }
    397   else
    398     return -1;
    399 }
    400 
    401 bool
    402 codecvt_byname<wchar_t, char, mbstate_t>::do_always_noconv() const _STLP_NOTHROW
    403 { return false; }
    404 
    405 int
    406 codecvt_byname<wchar_t, char, mbstate_t>::do_length(state_type&         state,
    407                                                     const  extern_type* from,
    408                                                     const  extern_type* end,
    409                                                     size_t              mx) const {
    410   size_t __count = 0;
    411   while (from != end && mx--) {
    412     intern_type __dummy;
    413     size_t chars_read = _WLocale_mbtowc(_M_codecvt,
    414                                         &__dummy, from, end - from,
    415                                         &state);
    416     if ((chars_read == (size_t) -1) || (chars_read == (size_t) -2)) // error or partial
    417       break;
    418     __count += chars_read;
    419     from += chars_read;
    420   }
    421   return int(__count);
    422 }
    423 
    424 int
    425 codecvt_byname<wchar_t, char, mbstate_t>::do_max_length() const _STLP_NOTHROW
    426 { return _WLocale_mb_cur_max(_M_codecvt); }
    427 #endif
    428 
    429 // numpunct_byname<char>
    430 numpunct_byname<char>::numpunct_byname(const char* name, size_t refs)
    431 : numpunct<char>(refs) {
    432   if (!name)
    433     locale::_M_throw_on_null_name();
    434 
    435   int __err_code;
    436   char buf[_Locale_MAX_SIMPLE_NAME];
    437   _M_numeric = _STLP_PRIV __acquire_numeric(name, buf, 0, &__err_code);
    438   if (!_M_numeric)
    439     locale::_M_throw_on_creation_failure(__err_code, name, "numpunct");
    440 }
    441 
    442 numpunct_byname<char>::~numpunct_byname()
    443 { _STLP_PRIV __release_numeric(_M_numeric); }
    444 
    445 char numpunct_byname<char>::do_decimal_point() const
    446 { return _Locale_decimal_point(_M_numeric); }
    447 
    448 char numpunct_byname<char>::do_thousands_sep() const
    449 { return _Locale_thousands_sep(_M_numeric); }
    450 
    451 string numpunct_byname<char>::do_grouping() const {
    452   const char * __grouping = _Locale_grouping(_M_numeric);
    453   if (__grouping != NULL && __grouping[0] == CHAR_MAX)
    454     __grouping = "";
    455   return __grouping;
    456 }
    457 
    458 string numpunct_byname<char>::do_truename() const
    459 { return _Locale_true(_M_numeric); }
    460 
    461 string numpunct_byname<char>::do_falsename() const
    462 { return _Locale_false(_M_numeric); }
    463 
    464 //----------------------------------------------------------------------
    465 // numpunct<wchar_t>
    466 
    467 #if !defined (_STLP_NO_WCHAR_T)
    468 
    469 // numpunct_byname<wchar_t>
    470 
    471 numpunct_byname<wchar_t>::numpunct_byname(const char* name, size_t refs)
    472 : numpunct<wchar_t>(refs) {
    473   if (!name)
    474     locale::_M_throw_on_null_name();
    475 
    476   int __err_code;
    477   char buf[_Locale_MAX_SIMPLE_NAME];
    478   _M_numeric = _STLP_PRIV __acquire_numeric(name, buf, 0, &__err_code);
    479   if (!_M_numeric)
    480     locale::_M_throw_on_creation_failure(__err_code, name, "numpunct");
    481 }
    482 
    483 numpunct_byname<wchar_t>::~numpunct_byname()
    484 { _STLP_PRIV __release_numeric(_M_numeric); }
    485 
    486 wchar_t numpunct_byname<wchar_t>::do_decimal_point() const
    487 { return _WLocale_decimal_point(_M_numeric); }
    488 
    489 wchar_t numpunct_byname<wchar_t>::do_thousands_sep() const
    490 { return _WLocale_thousands_sep(_M_numeric); }
    491 
    492 string numpunct_byname<wchar_t>::do_grouping() const {
    493   const char * __grouping = _Locale_grouping(_M_numeric);
    494   if (__grouping != NULL && __grouping[0] == CHAR_MAX)
    495     __grouping = "";
    496   return __grouping;
    497 }
    498 
    499 wstring numpunct_byname<wchar_t>::do_truename() const {
    500   wchar_t buf[16];
    501   return _WLocale_true(_M_numeric, _STLP_ARRAY_AND_SIZE(buf));
    502 }
    503 
    504 wstring numpunct_byname<wchar_t>::do_falsename() const {
    505   wchar_t buf[16];
    506   return _WLocale_false(_M_numeric, _STLP_ARRAY_AND_SIZE(buf));
    507 }
    508 
    509 #endif
    510 
    511 _STLP_MOVE_TO_PRIV_NAMESPACE
    512 
    513 static void _Init_monetary_formats(money_base::pattern& pos_format,
    514                                    money_base::pattern& neg_format,
    515                                    _Locale_monetary * monetary) {
    516   switch (_Locale_p_sign_posn(monetary)) {
    517     case 0: // Parentheses surround the quantity and currency symbol
    518     case 1: // The sign string precedes the quantity and currency symbol
    519       pos_format.field[0] = (char) money_base::sign;
    520       if (_Locale_p_cs_precedes(monetary)) {
    521         // 1 if currency symbol precedes a positive value
    522         pos_format.field[1] = (char) money_base::symbol;
    523         if (_Locale_p_sep_by_space(monetary)) {
    524           // a space separates currency symbol from a positive value.
    525           pos_format.field[2] = (char) money_base::space;
    526           pos_format.field[3] = (char) money_base::value;
    527         } else {
    528           // a space not separates currency symbol from a positive value.
    529           pos_format.field[2] = (char) money_base::value;
    530           pos_format.field[3] = (char) money_base::none;
    531         }
    532       } else {
    533         // 0 if currency symbol succeeds a positive value
    534         pos_format.field[1] = (char) money_base::value;
    535         if (_Locale_p_sep_by_space(monetary)) {
    536           // a space separates currency symbol from a positive value.
    537           pos_format.field[2] = (char) money_base::space;
    538           pos_format.field[3] = (char) money_base::symbol;
    539         } else {
    540           // a space not separates currency symbol from a positive value.
    541           pos_format.field[2] = (char) money_base::symbol;
    542           pos_format.field[3] = (char) money_base::none;
    543         }
    544       }
    545       break;
    546     case 2: // The sign string succeeds the quantity and currency symbol.
    547       if (_Locale_p_cs_precedes(monetary)) {
    548         // 1 if currency symbol precedes a positive value
    549         pos_format.field[0] = (char) money_base::symbol;
    550         if (_Locale_p_sep_by_space(monetary)) {
    551           // a space separates currency symbol from a positive value.
    552           pos_format.field[1] = (char) money_base::space;
    553           pos_format.field[2] = (char) money_base::value;
    554           pos_format.field[3] = (char) money_base::sign;
    555         } else {
    556           // a space not separates currency symbol from a positive value.
    557           pos_format.field[1] = (char) money_base::value;
    558           pos_format.field[2] = (char) money_base::sign;
    559           pos_format.field[3] = (char) money_base::none;
    560         }
    561       } else {
    562         // 0 if currency symbol succeeds a positive value
    563         pos_format.field[0] = (char) money_base::value;
    564         if (_Locale_p_sep_by_space(monetary)) {
    565           // a space separates currency symbol from a positive value.
    566           pos_format.field[1] = (char) money_base::space;
    567           pos_format.field[2] = (char) money_base::symbol;
    568           pos_format.field[3] = (char) money_base::sign;
    569         } else {
    570           // a space not separates currency symbol from a positive value.
    571           pos_format.field[1] = (char) money_base::symbol;
    572           pos_format.field[2] = (char) money_base::sign;
    573           pos_format.field[3] = (char) money_base::none;
    574         }
    575       }
    576       break;
    577     case 3: // The sign string immediately precedes the currency symbol.
    578       if (_Locale_p_cs_precedes(monetary)) {
    579         // 1 if currency symbol precedes a positive value
    580         pos_format.field[0] = (char) money_base::sign;
    581         pos_format.field[1] = (char) money_base::symbol;
    582         if (_Locale_p_sep_by_space(monetary)) {
    583           // a space separates currency symbol from a positive value.
    584           pos_format.field[2] = (char) money_base::space;
    585           pos_format.field[3] = (char) money_base::value;
    586         } else {
    587           // a space not separates currency symbol from a positive value.
    588           pos_format.field[2] = (char) money_base::value;
    589           pos_format.field[3] = (char) money_base::none;
    590         }
    591       } else {
    592         // 0 if currency symbol succeeds a positive value
    593         pos_format.field[0] = (char) money_base::value;
    594         pos_format.field[1] = (char) money_base::sign;
    595         pos_format.field[2] = (char) money_base::symbol;
    596         pos_format.field[3] = (char) money_base::none;
    597       }
    598       break;
    599     case 4: // The sign string immediately succeeds the currency symbol.
    600       if (_Locale_p_cs_precedes(monetary)) {
    601         // 1 if currency symbol precedes a positive value
    602         pos_format.field[0] = (char) money_base::symbol;
    603         pos_format.field[1] = (char) money_base::sign;
    604         pos_format.field[2] = (char) money_base::value;
    605         pos_format.field[3] = (char) money_base::none;
    606       } else {
    607         // 0 if currency symbol succeeds a positive value
    608         pos_format.field[0] = (char) money_base::value;
    609         if (_Locale_p_sep_by_space(monetary)) {
    610           // a space separates currency symbol from a positive value.
    611           pos_format.field[1] = (char) money_base::space;
    612           pos_format.field[2] = (char) money_base::symbol;
    613           pos_format.field[3] = (char) money_base::sign;
    614         } else {
    615           // a space not separates currency symbol from a positive value.
    616           pos_format.field[1] = (char) money_base::symbol;
    617           pos_format.field[2] = (char) money_base::sign;
    618           pos_format.field[3] = (char) money_base::none;
    619         }
    620       }
    621       break;
    622     default: // Default C++ Standard format
    623       pos_format.field[0] = (char) money_base::symbol;
    624       pos_format.field[1] = (char) money_base::sign;
    625       pos_format.field[2] = (char) money_base::none;
    626       pos_format.field[3] = (char) money_base::value;
    627       break;
    628   }
    629 
    630   switch (_Locale_n_sign_posn(monetary)) {
    631     case 0: // Parentheses surround the quantity and currency symbol
    632     case 1: // The sign string precedes the quantity and currency symbol
    633       neg_format.field[0] = (char) money_base::sign;
    634       if (_Locale_n_cs_precedes(monetary)) {
    635         // 1 if currency symbol precedes a negative value
    636         neg_format.field[1] = (char) money_base::symbol;
    637         if (_Locale_n_sep_by_space(monetary)) {
    638           // a space separates currency symbol from a negative value.
    639           neg_format.field[2] = (char) money_base::space;
    640           neg_format.field[3] = (char) money_base::value;
    641         } else {
    642           // a space not separates currency symbol from a negative value.
    643           neg_format.field[2] = (char) money_base::value;
    644           neg_format.field[3] = (char) money_base::none;
    645         }
    646       } else {
    647         // 0 if currency symbol succeeds a negative value
    648         neg_format.field[1] = (char) money_base::value;
    649         if (_Locale_n_sep_by_space(monetary)) {
    650           // a space separates currency symbol from a negative value.
    651           neg_format.field[2] = (char) money_base::space;
    652           neg_format.field[3] = (char) money_base::symbol;
    653         } else {
    654           // a space not separates currency symbol from a negative value.
    655           neg_format.field[2] = (char) money_base::symbol;
    656           neg_format.field[3] = (char) money_base::none;
    657         }
    658       }
    659       break;
    660     case 2: // The sign string succeeds the quantity and currency symbol.
    661       if (_Locale_n_cs_precedes(monetary)) {
    662         // 1 if currency symbol precedes a negative value
    663         neg_format.field[0] = (char) money_base::symbol;
    664         if (_Locale_n_sep_by_space(monetary)) {
    665           // a space separates currency symbol from a negative value.
    666           neg_format.field[1] = (char) money_base::space;
    667           neg_format.field[2] = (char) money_base::value;
    668           neg_format.field[3] = (char) money_base::sign;
    669         } else {
    670           // a space not separates currency symbol from a negative value.
    671           neg_format.field[1] = (char) money_base::value;
    672           neg_format.field[2] = (char) money_base::sign;
    673           neg_format.field[3] = (char) money_base::none;
    674         }
    675       } else {
    676         // 0 if currency symbol succeeds a negative value
    677         neg_format.field[0] = (char) money_base::value;
    678         if (_Locale_n_sep_by_space(monetary)) {
    679           // a space separates currency symbol from a negative value.
    680           neg_format.field[1] = (char) money_base::space;
    681           neg_format.field[2] = (char) money_base::symbol;
    682           neg_format.field[3] = (char) money_base::sign;
    683         } else {
    684           // a space not separates currency symbol from a negative value.
    685           neg_format.field[1] = (char) money_base::symbol;
    686           neg_format.field[2] = (char) money_base::sign;
    687           neg_format.field[3] = (char) money_base::none;
    688         }
    689       }
    690       break;
    691     case 3: // The sign string immediately precedes the currency symbol.
    692       if (_Locale_n_cs_precedes(monetary)) {
    693         // 1 if currency symbol precedes a negative value
    694         neg_format.field[0] = (char) money_base::sign;
    695         neg_format.field[1] = (char) money_base::symbol;
    696         if (_Locale_n_sep_by_space(monetary)) {
    697           // a space separates currency symbol from a negative value.
    698           neg_format.field[2] = (char) money_base::space;
    699           neg_format.field[3] = (char) money_base::value;
    700         } else {
    701           // a space not separates currency symbol from a negative value.
    702           neg_format.field[2] = (char) money_base::value;
    703           neg_format.field[3] = (char) money_base::none;
    704         }
    705       } else {
    706         // 0 if currency symbol succeeds a negative value
    707         neg_format.field[0] = (char) money_base::value;
    708         neg_format.field[1] = (char) money_base::sign;
    709         neg_format.field[2] = (char) money_base::symbol;
    710         neg_format.field[3] = (char) money_base::none;
    711       }
    712       break;
    713     case 4: // The sign string immediately succeeds the currency symbol.
    714       if (_Locale_n_cs_precedes(monetary)) {
    715         // 1 if currency symbol precedes a negative value
    716         neg_format.field[0] = (char) money_base::symbol;
    717         neg_format.field[1] = (char) money_base::sign;
    718         neg_format.field[2] = (char) money_base::none;
    719         neg_format.field[3] = (char) money_base::value;
    720       } else {
    721         // 0 if currency symbol succeeds a negative value
    722         neg_format.field[0] = (char) money_base::value;
    723         if (_Locale_n_sep_by_space(monetary)) {
    724           // a space separates currency symbol from a negative value.
    725           neg_format.field[1] = (char) money_base::space;
    726           neg_format.field[2] = (char) money_base::symbol;
    727           neg_format.field[3] = (char) money_base::sign;
    728         } else {
    729           // a space not separates currency symbol from a negative value.
    730           neg_format.field[1] = (char) money_base::symbol;
    731           neg_format.field[2] = (char) money_base::sign;
    732           neg_format.field[3] = (char) money_base::none;
    733         }
    734       }
    735       break;
    736     default: // Default C++ Standard format
    737       neg_format.field[0] = (char) money_base::symbol;
    738       neg_format.field[1] = (char) money_base::sign;
    739       neg_format.field[2] = (char) money_base::none;
    740       neg_format.field[3] = (char) money_base::value;
    741       break;
    742   }
    743 }
    744 
    745 // international variant of monetary
    746 
    747 /*
    748  * int_curr_symbol
    749  *
    750  *   The international currency symbol. The operand is a four-character
    751  *   string, with the first three characters containing the alphabetic
    752  *   international currency symbol in accordance with those specified
    753  *   in the ISO 4217 specification. The fourth character is the character used
    754  *   to separate the international currency symbol from the monetary quantity.
    755  *
    756  * (http://www.opengroup.org/onlinepubs/7990989775/xbd/locale.html)
    757  */
    758 
    759 /*
    760  * Standards are unclear in the usage of international currency
    761  * and monetary formats.
    762  * But I am expect that international currency symbol should be the first
    763  * (not depends upon where currency symbol situated in the national
    764  * format).
    765  *
    766  * If this isn't so, let's see:
    767  *       1 234.56 RUR
    768  *       GBP 1,234.56
    769  *       USD 1,234.56
    770  * The situation really is worse than you see above:
    771  * RUR typed wrong here---it prints '1 234.56 RUR ' (see space after RUR).
    772  * This is due to intl_fmp.curr_symbol() == "RUR ". (see reference in comments
    773  * above).
    774  *
    775  */
    776 
    777 static void _Init_monetary_formats_int(money_base::pattern& pos_format,
    778                                        money_base::pattern& neg_format,
    779                                        _Locale_monetary * monetary)
    780 {
    781 
    782   switch (_Locale_p_sign_posn(monetary)) {
    783     case 0: // Parentheses surround the quantity and currency symbol
    784     case 1: // The sign string precedes the quantity and currency symbol
    785       pos_format.field[0] = (char) money_base::symbol;
    786       pos_format.field[1] = (char) money_base::sign;
    787       pos_format.field[2] = (char) money_base::value;
    788       pos_format.field[3] = (char) money_base::none;
    789       break;
    790     case 2: // The sign string succeeds the quantity and currency symbol.
    791       pos_format.field[0] = (char) money_base::symbol;
    792       pos_format.field[1] = (char) money_base::value;
    793       pos_format.field[2] = (char) money_base::sign;
    794       pos_format.field[3] = (char) money_base::none;
    795       break;
    796     case 3: // The sign string immediately precedes the currency symbol.
    797     case 4: // The sign string immediately succeeds the currency symbol.
    798       pos_format.field[0] = (char) money_base::symbol;
    799       if (_Locale_p_cs_precedes(monetary)) {
    800         // 1 if currency symbol precedes a positive value
    801         pos_format.field[1] = (char) money_base::sign;
    802         pos_format.field[2] = (char) money_base::value;
    803       } else {
    804         // 0 if currency symbol succeeds a positive value
    805         pos_format.field[1] = (char) money_base::value;
    806         pos_format.field[2] = (char) money_base::sign;
    807       }
    808       pos_format.field[3] = (char) money_base::none;
    809       break;
    810     default: // Default C++ Standard format
    811       pos_format.field[0] = (char) money_base::symbol;
    812       pos_format.field[1] = (char) money_base::sign;
    813       pos_format.field[2] = (char) money_base::none;
    814       pos_format.field[3] = (char) money_base::value;
    815       break;
    816   }
    817 
    818 
    819   switch (_Locale_n_sign_posn(monetary)) {
    820     case 0: // Parentheses surround the quantity and currency symbol
    821     case 1: // The sign string precedes the quantity and currency symbol
    822       neg_format.field[0] = (char) money_base::symbol;
    823       neg_format.field[1] = (char) money_base::sign;
    824       neg_format.field[2] = (char) money_base::value;
    825       neg_format.field[3] = (char) money_base::none;
    826       break;
    827     case 2: // The sign string succeeds the quantity and currency symbol.
    828       neg_format.field[0] = (char) money_base::symbol;
    829       neg_format.field[1] = (char) money_base::value;
    830       neg_format.field[2] = (char) money_base::sign;
    831       neg_format.field[3] = (char) money_base::none;
    832       break;
    833     case 3: // The sign string immediately precedes the currency symbol.
    834     case 4: // The sign string immediately succeeds the currency symbol.
    835       neg_format.field[0] = (char) money_base::symbol;
    836       if (_Locale_n_cs_precedes(monetary)) {
    837         // 1 if currency symbol precedes a negative value
    838         neg_format.field[1] = (char) money_base::sign;
    839         neg_format.field[2] = (char) money_base::value;
    840       } else {
    841         // 0 if currency symbol succeeds a negative value
    842         neg_format.field[1] = (char) money_base::value;
    843         neg_format.field[2] = (char) money_base::sign;
    844       }
    845       neg_format.field[3] = (char) money_base::none;
    846       break;
    847     default: // Default C++ Standard format
    848       neg_format.field[0] = (char) money_base::symbol;
    849       neg_format.field[1] = (char) money_base::sign;
    850       neg_format.field[2] = (char) money_base::none;
    851       neg_format.field[3] = (char) money_base::value;
    852       break;
    853   }
    854 }
    855 
    856 _STLP_MOVE_TO_STD_NAMESPACE
    857 
    858 //
    859 // moneypunct_byname<>
    860 //
    861 moneypunct_byname<char, true>::moneypunct_byname(const char * name,
    862                                                  size_t refs)
    863     : moneypunct<char, true>(refs) {
    864   if (!name)
    865     locale::_M_throw_on_null_name();
    866 
    867   int __err_code;
    868   char buf[_Locale_MAX_SIMPLE_NAME];
    869   _M_monetary = _STLP_PRIV __acquire_monetary(name, buf, 0, &__err_code);
    870   if (!_M_monetary)
    871     locale::_M_throw_on_creation_failure(__err_code, name, "moneypunct");
    872 
    873   _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
    874 }
    875 
    876 moneypunct_byname<char, true>::moneypunct_byname(_Locale_monetary *__mon)
    877   : _M_monetary(__mon) {
    878   _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
    879 }
    880 
    881 moneypunct_byname<char, true>::~moneypunct_byname()
    882 { _STLP_PRIV __release_monetary(_M_monetary); }
    883 
    884 char moneypunct_byname<char, true>::do_decimal_point() const
    885 { return _Locale_mon_decimal_point(_M_monetary); }
    886 
    887 char moneypunct_byname<char, true>::do_thousands_sep() const
    888 { return _Locale_mon_thousands_sep(_M_monetary); }
    889 
    890 string moneypunct_byname<char, true>::do_grouping() const
    891 { return _Locale_mon_grouping(_M_monetary); }
    892 
    893 string moneypunct_byname<char, true>::do_curr_symbol() const
    894 { return _Locale_int_curr_symbol(_M_monetary); }
    895 
    896 string moneypunct_byname<char, true>::do_positive_sign() const
    897 { return _Locale_positive_sign(_M_monetary); }
    898 
    899 string moneypunct_byname<char, true>::do_negative_sign() const
    900 { return _Locale_negative_sign(_M_monetary); }
    901 
    902 int moneypunct_byname<char, true>::do_frac_digits() const
    903 { return _Locale_int_frac_digits(_M_monetary); }
    904 
    905 moneypunct_byname<char, false>::moneypunct_byname(const char * name,
    906                                                   size_t refs)
    907     : moneypunct<char, false>(refs) {
    908   if (!name)
    909     locale::_M_throw_on_null_name();
    910 
    911   int __err_code;
    912   char buf[_Locale_MAX_SIMPLE_NAME];
    913   _M_monetary = _STLP_PRIV __acquire_monetary(name, buf, 0, &__err_code);
    914   if (!_M_monetary)
    915     locale::_M_throw_on_creation_failure(__err_code, name, "moneypunct");
    916 
    917   _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
    918 }
    919 
    920 moneypunct_byname<char, false>::moneypunct_byname(_Locale_monetary *__mon)
    921   : _M_monetary(__mon) {
    922   _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
    923 }
    924 
    925 moneypunct_byname<char, false>::~moneypunct_byname()
    926 { _STLP_PRIV __release_monetary(_M_monetary); }
    927 
    928 char moneypunct_byname<char, false>::do_decimal_point() const
    929 { return _Locale_mon_decimal_point(_M_monetary); }
    930 
    931 char moneypunct_byname<char, false>::do_thousands_sep() const
    932 { return _Locale_mon_thousands_sep(_M_monetary); }
    933 
    934 string moneypunct_byname<char, false>::do_grouping() const
    935 { return _Locale_mon_grouping(_M_monetary); }
    936 
    937 string moneypunct_byname<char, false>::do_curr_symbol() const
    938 { return _Locale_currency_symbol(_M_monetary); }
    939 
    940 string moneypunct_byname<char, false>::do_positive_sign() const
    941 { return _Locale_positive_sign(_M_monetary); }
    942 
    943 string moneypunct_byname<char, false>::do_negative_sign() const
    944 { return _Locale_negative_sign(_M_monetary); }
    945 
    946 int moneypunct_byname<char, false>::do_frac_digits() const
    947 { return _Locale_frac_digits(_M_monetary); }
    948 
    949 //
    950 // moneypunct_byname<wchar_t>
    951 //
    952 #if !defined (_STLP_NO_WCHAR_T)
    953 
    954 moneypunct_byname<wchar_t, true>::moneypunct_byname(const char * name,
    955                                                     size_t refs)
    956     : moneypunct<wchar_t, true>(refs) {
    957   if (!name)
    958     locale::_M_throw_on_null_name();
    959 
    960   int __err_code;
    961   char buf[_Locale_MAX_SIMPLE_NAME];
    962   _M_monetary = _STLP_PRIV __acquire_monetary(name, buf, 0, &__err_code);
    963   if (!_M_monetary)
    964     locale::_M_throw_on_creation_failure(__err_code, name, "moneypunct");
    965 
    966   _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
    967 }
    968 
    969 moneypunct_byname<wchar_t, true>::moneypunct_byname(_Locale_monetary *__mon)
    970   : _M_monetary(__mon) {
    971   _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
    972 }
    973 
    974 moneypunct_byname<wchar_t, true>::~moneypunct_byname()
    975 { _STLP_PRIV __release_monetary(_M_monetary); }
    976 
    977 wchar_t moneypunct_byname<wchar_t, true>::do_decimal_point() const
    978 { return _Locale_mon_decimal_point(_M_monetary); }
    979 
    980 wchar_t moneypunct_byname<wchar_t, true>::do_thousands_sep() const
    981 { return _Locale_mon_thousands_sep(_M_monetary); }
    982 
    983 string moneypunct_byname<wchar_t, true>::do_grouping() const
    984 { return _Locale_mon_grouping(_M_monetary); }
    985 
    986 inline wstring __do_widen (string const& str) {
    987 #if defined (_STLP_NO_MEMBER_TEMPLATES) || defined (_STLP_MSVC)
    988   wstring::_Reserve_t __Reserve;
    989   size_t __size = str.size();
    990   wstring result(__Reserve, __size);
    991   copy(str.begin(), str.end(), result.begin());
    992 #else
    993   wstring result(str.begin(), str.end());
    994 #endif
    995   return result;
    996 }
    997 
    998 wstring moneypunct_byname<wchar_t, true>::do_curr_symbol() const
    999 { wchar_t buf[16]; return _WLocale_int_curr_symbol(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); }
   1000 
   1001 wstring moneypunct_byname<wchar_t, true>::do_positive_sign() const
   1002 { wchar_t buf[16]; return _WLocale_positive_sign(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); }
   1003 
   1004 wstring moneypunct_byname<wchar_t, true>::do_negative_sign() const
   1005 { wchar_t buf[16]; return _WLocale_negative_sign(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); }
   1006 
   1007 int moneypunct_byname<wchar_t, true>::do_frac_digits() const
   1008 { return _Locale_int_frac_digits(_M_monetary); }
   1009 
   1010 moneypunct_byname<wchar_t, false>::moneypunct_byname(const char * name,
   1011                                                      size_t refs)
   1012     : moneypunct<wchar_t, false>(refs) {
   1013   if (!name)
   1014     locale::_M_throw_on_null_name() ;
   1015 
   1016   int __err_code;
   1017   char buf[_Locale_MAX_SIMPLE_NAME];
   1018   _M_monetary = _STLP_PRIV __acquire_monetary(name, buf, 0, &__err_code);
   1019   if (!_M_monetary)
   1020     locale::_M_throw_on_creation_failure(__err_code, name, "moneypunct");
   1021 
   1022   _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
   1023 }
   1024 
   1025 moneypunct_byname<wchar_t, false>::moneypunct_byname(_Locale_monetary *__mon)
   1026   : _M_monetary(__mon) {
   1027   _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
   1028 }
   1029 
   1030 moneypunct_byname<wchar_t, false>::~moneypunct_byname()
   1031 { _STLP_PRIV __release_monetary(_M_monetary); }
   1032 
   1033 wchar_t moneypunct_byname<wchar_t, false>::do_decimal_point() const
   1034 { return _Locale_mon_decimal_point(_M_monetary); }
   1035 
   1036 wchar_t moneypunct_byname<wchar_t, false>::do_thousands_sep() const
   1037 { return _Locale_mon_thousands_sep(_M_monetary); }
   1038 
   1039 string moneypunct_byname<wchar_t, false>::do_grouping() const
   1040 { return _Locale_mon_grouping(_M_monetary); }
   1041 
   1042 wstring moneypunct_byname<wchar_t, false>::do_curr_symbol() const
   1043 { wchar_t buf[16]; return _WLocale_currency_symbol(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); }
   1044 
   1045 wstring moneypunct_byname<wchar_t, false>::do_positive_sign() const
   1046 { wchar_t buf[16]; return _WLocale_positive_sign(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); }
   1047 
   1048 wstring moneypunct_byname<wchar_t, false>::do_negative_sign() const
   1049 { wchar_t buf[16]; return _WLocale_negative_sign(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); }
   1050 
   1051 int moneypunct_byname<wchar_t, false>::do_frac_digits() const
   1052 { return _Locale_frac_digits(_M_monetary); }
   1053 
   1054 #endif
   1055 
   1056 _STLP_END_NAMESPACE
   1057 
   1058