genericopenlibs/cppstdlib/stl/src/facets_byname.cpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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 _STLP_DECLSPEC ctype_byname<char>::ctype_byname(const char* name, size_t refs, _Locale_name_hint* hint) :
       
    39     ctype<char>( 0, false, refs),
       
    40     _M_ctype(_STLP_PRIV __acquire_ctype(name, hint)) {
       
    41   ctype<char>::_M_ctype_table = _M_byname_table;
       
    42   if (!_M_ctype)
       
    43     locale::_M_throw_runtime_error();
       
    44 
       
    45   // We have to do this, instead of just pointer twiddling, because
       
    46   // ctype_base::mask isn't the same type as _Locale_mask_t.
       
    47 
       
    48   const _Locale_mask_t* p = _Locale_ctype_table(_M_ctype);
       
    49 
       
    50   if (!p)
       
    51     locale::_M_throw_runtime_error();
       
    52 
       
    53   for (size_t i = 0; i < table_size; ++i) {
       
    54     _Locale_mask_t __m = p[i];
       
    55     if (__m & (upper | lower))
       
    56       __m |= alpha;
       
    57     _M_byname_table[i] = ctype_base::mask(__m);
       
    58   }
       
    59 }
       
    60 
       
    61 _STLP_DECLSPEC ctype_byname<char>::~ctype_byname()
       
    62 { _STLP_PRIV __release_ctype(_M_ctype); }
       
    63 
       
    64 _STLP_DECLSPEC char ctype_byname<char>::do_toupper(char c) const
       
    65 { return (char)_Locale_toupper(_M_ctype, c); }
       
    66 
       
    67 _STLP_DECLSPEC char ctype_byname<char>::do_tolower(char c) const
       
    68 { return (char)_Locale_tolower(_M_ctype, c); }
       
    69 
       
    70 _STLP_DECLSPEC const char*
       
    71 ctype_byname<char>::do_toupper(char* first, const char* last) const {
       
    72   for ( ; first != last ; ++first)
       
    73     *first = (char)_Locale_toupper(_M_ctype, *first);
       
    74   return last;
       
    75 }
       
    76 
       
    77 _STLP_DECLSPEC const char*
       
    78 ctype_byname<char>::do_tolower(char* first, const char* last) const {
       
    79   for ( ; first != last ; ++first)
       
    80     *first = (char)_Locale_tolower(_M_ctype, *first);
       
    81   return last;
       
    82 }
       
    83 
       
    84 
       
    85 // Some helper functions used in ctype<>::scan_is and scan_is_not.
       
    86 #if !defined (_STLP_NO_WCHAR_T)
       
    87 
       
    88 _STLP_MOVE_TO_PRIV_NAMESPACE
       
    89 
       
    90 // ctype_byname<wchar_t>
       
    91 
       
    92 struct _Ctype_byname_w_is_mask {
       
    93   typedef wchar_t argument_type;
       
    94   typedef bool    result_type;
       
    95 
       
    96   /* ctype_base::mask*/ int  M;
       
    97   _Locale_ctype* M_ctp;
       
    98 
       
    99   _Ctype_byname_w_is_mask(/* ctype_base::mask */ int m, _Locale_ctype* c) : M((int)m), M_ctp(c) {}
       
   100   bool operator()(wchar_t c) const
       
   101     { return (M & _Locale_wchar_ctype(M_ctp, c, M)) != 0; }
       
   102 };
       
   103 
       
   104 _STLP_MOVE_TO_STD_NAMESPACE
       
   105 
       
   106 _STLP_DECLSPEC ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs, _Locale_name_hint* hint)
       
   107   : ctype<wchar_t>(refs),
       
   108     _M_ctype(_STLP_PRIV __acquire_ctype(name, hint)) {
       
   109   if (!_M_ctype)
       
   110     locale::_M_throw_runtime_error();
       
   111 }
       
   112 
       
   113 _STLP_DECLSPEC ctype_byname<wchar_t>::~ctype_byname()
       
   114 { _STLP_PRIV __release_ctype(_M_ctype); }
       
   115 
       
   116 _STLP_DECLSPEC bool ctype_byname<wchar_t>::do_is(ctype_base::mask  m, wchar_t c) const
       
   117 { return (m & _Locale_wchar_ctype(_M_ctype, c, m)) != 0; }
       
   118 
       
   119 _STLP_DECLSPEC const wchar_t*
       
   120 ctype_byname<wchar_t>::do_is(const wchar_t* low, const wchar_t* high,
       
   121                              ctype_base::mask * m) const {
       
   122   ctype_base::mask all_bits = ctype_base::mask(
       
   123     ctype_base::space |
       
   124     ctype_base::print |
       
   125     ctype_base::cntrl |
       
   126     ctype_base::upper |
       
   127     ctype_base::lower |
       
   128     ctype_base::alpha |
       
   129     ctype_base::digit |
       
   130     ctype_base::punct |
       
   131     ctype_base::xdigit);
       
   132 
       
   133   for ( ; low < high; ++low, ++m)
       
   134     *m = ctype_base::mask (_Locale_wchar_ctype(_M_ctype, *low, all_bits));
       
   135   return high;
       
   136 }
       
   137 
       
   138 _STLP_DECLSPEC const wchar_t*
       
   139 ctype_byname<wchar_t>
       
   140   ::do_scan_is(ctype_base::mask  m, const wchar_t* low, const wchar_t* high) const
       
   141 { return find_if(low, high, _STLP_PRIV _Ctype_byname_w_is_mask(m, _M_ctype)); }
       
   142 
       
   143 _STLP_DECLSPEC const wchar_t*
       
   144 ctype_byname<wchar_t>
       
   145   ::do_scan_not(ctype_base::mask  m, const wchar_t* low, const wchar_t* high) const
       
   146 { return find_if(low, high, not1(_STLP_PRIV _Ctype_byname_w_is_mask(m, _M_ctype))); }
       
   147 
       
   148 _STLP_DECLSPEC wchar_t ctype_byname<wchar_t>::do_toupper(wchar_t c) const
       
   149 { return _Locale_wchar_toupper(_M_ctype, c); }
       
   150 
       
   151 _STLP_DECLSPEC const wchar_t*
       
   152 ctype_byname<wchar_t>::do_toupper(wchar_t* low, const wchar_t* high) const {
       
   153   for ( ; low < high; ++low)
       
   154     *low = _Locale_wchar_toupper(_M_ctype, *low);
       
   155   return high;
       
   156 }
       
   157 
       
   158 _STLP_DECLSPEC wchar_t ctype_byname<wchar_t>::do_tolower(wchar_t c) const
       
   159 { return _Locale_wchar_tolower(_M_ctype, c); }
       
   160 
       
   161 _STLP_DECLSPEC const wchar_t*
       
   162 ctype_byname<wchar_t>::do_tolower(wchar_t* low, const wchar_t* high) const {
       
   163   for ( ; low < high; ++low)
       
   164     *low = _Locale_wchar_tolower(_M_ctype, *low);
       
   165   return high;
       
   166 }
       
   167 
       
   168 #endif /* WCHAR_T */
       
   169 
       
   170 // collate_byname<char>
       
   171 _STLP_DECLSPEC collate_byname<char>::collate_byname(const char* name, size_t refs, _Locale_name_hint* hint)
       
   172   : collate<char>(refs),
       
   173     _M_collate(_STLP_PRIV __acquire_collate(name, hint)) {
       
   174   if (!_M_collate)
       
   175     locale::_M_throw_runtime_error();
       
   176 }
       
   177 
       
   178 _STLP_DECLSPEC collate_byname<char>::~collate_byname()
       
   179 { _STLP_PRIV __release_collate(_M_collate); }
       
   180 
       
   181 _STLP_DECLSPEC int collate_byname<char>::do_compare(const char* __low1,
       
   182                                      const char* __high1,
       
   183                                      const char* __low2,
       
   184                                      const char* __high2) const {
       
   185   return _Locale_strcmp(_M_collate,
       
   186                         __low1, __high1 - __low1,
       
   187                         __low2, __high2 - __low2);
       
   188 }
       
   189 
       
   190 _STLP_DECLSPEC collate_byname<char>::string_type
       
   191 collate_byname<char>::do_transform(const char* low, const char* high) const {
       
   192   if (low == high)
       
   193     return string_type();
       
   194 
       
   195   size_t n = _Locale_strxfrm(_M_collate, NULL, 0, low, high - low);
       
   196 
       
   197   // NOT PORTABLE.  What we're doing relies on internal details of the
       
   198   // string implementation.  (Contiguity of string elements and presence
       
   199   // of trailing zero.)
       
   200   string_type buf(n, 0);
       
   201   _Locale_strxfrm(_M_collate, &(*buf.begin()), n + 1, low, high - low);
       
   202   return buf;
       
   203 }
       
   204 
       
   205 
       
   206 #if !defined (_STLP_NO_WCHAR_T)
       
   207 
       
   208 // collate_byname<wchar_t>
       
   209 
       
   210 _STLP_DECLSPEC collate_byname<wchar_t>::collate_byname(const char* name, size_t refs, _Locale_name_hint* hint)
       
   211   : collate<wchar_t>(refs),
       
   212     _M_collate(_STLP_PRIV __acquire_collate(name, hint)) {
       
   213   if (!_M_collate)
       
   214     locale::_M_throw_runtime_error();
       
   215 }
       
   216 
       
   217 _STLP_DECLSPEC collate_byname<wchar_t>::~collate_byname()
       
   218 { _STLP_PRIV __release_collate(_M_collate); }
       
   219 
       
   220 _STLP_DECLSPEC int collate_byname<wchar_t>::do_compare(const wchar_t* low1,
       
   221                                         const wchar_t* high1,
       
   222                                         const wchar_t* low2,
       
   223                                         const wchar_t* high2) const {
       
   224   return _Locale_strwcmp(_M_collate,
       
   225                          low1, high1 - low1,
       
   226                          low2, high2 - low2);
       
   227 }
       
   228 
       
   229 _STLP_DECLSPEC collate_byname<wchar_t>::string_type
       
   230 collate_byname<wchar_t>::do_transform(const wchar_t* low,
       
   231                                       const wchar_t* high) const {
       
   232   if (low == high)
       
   233     return string_type();
       
   234 
       
   235   size_t n = _Locale_strwxfrm(_M_collate, NULL, 0, low, high - low);
       
   236 
       
   237   // NOT PORTABLE.  What we're doing relies on internal details of the
       
   238   // string implementation.  (Contiguity of string elements and presence
       
   239   // of trailing zero.)
       
   240   string_type buf(n, 0);
       
   241   _Locale_strwxfrm(_M_collate, &(*buf.begin()), n + 1, low, high - low);
       
   242   return buf;
       
   243 }
       
   244 
       
   245 #endif /*  _STLP_NO_WCHAR_T */
       
   246 
       
   247 _STLP_END_NAMESPACE
       
   248 
       
   249 #if !defined (_STLP_NO_MBSTATE_T)
       
   250 
       
   251 _STLP_BEGIN_NAMESPACE
       
   252 
       
   253 //----------------------------------------------------------------------
       
   254 // codecvt_byname<char>
       
   255 
       
   256 _STLP_DECLSPEC codecvt_byname<char, char, mbstate_t>
       
   257   ::codecvt_byname(const char* /* name */, size_t refs)
       
   258     : codecvt<char, char, mbstate_t>(refs) {}
       
   259 
       
   260 _STLP_DECLSPEC codecvt_byname<char, char, mbstate_t>::~codecvt_byname() {}
       
   261 
       
   262 
       
   263 #  if !defined (_STLP_NO_WCHAR_T)
       
   264 
       
   265 //----------------------------------------------------------------------
       
   266 // codecvt_byname<wchar_t>
       
   267 _STLP_DECLSPEC codecvt_byname<wchar_t, char, mbstate_t>
       
   268   ::codecvt_byname(const char* name, size_t refs, _Locale_name_hint* hint)
       
   269     : codecvt<wchar_t, char, mbstate_t>(refs),
       
   270       _M_ctype(_STLP_PRIV __acquire_ctype(name, hint)) {
       
   271   if (!_M_ctype)
       
   272     locale::_M_throw_runtime_error();
       
   273 }
       
   274 
       
   275 _STLP_DECLSPEC codecvt_byname<wchar_t, char, mbstate_t>::~codecvt_byname()
       
   276 { _STLP_PRIV __release_ctype(_M_ctype); }
       
   277 
       
   278 _STLP_DECLSPEC codecvt<wchar_t, char, mbstate_t>::result
       
   279 codecvt_byname<wchar_t, char, mbstate_t>
       
   280   ::do_out(state_type&     state,
       
   281            const wchar_t*  from,
       
   282            const wchar_t*  from_end,
       
   283            const wchar_t*& from_next,
       
   284            char*           to,
       
   285            char*           to_limit,
       
   286            char*&          to_next) const {
       
   287   while (from != from_end) {
       
   288     size_t chars_stored = _Locale_wctomb(_M_ctype,
       
   289                                          to, to_limit - to, *from,
       
   290                                          &state);
       
   291     if (chars_stored == (size_t) -1) {
       
   292       from_next = from;
       
   293       to_next   = to;
       
   294       return error;
       
   295     }
       
   296     else if (chars_stored == (size_t) -2) {
       
   297       from_next = from;
       
   298       to_next   = to;
       
   299       return partial;
       
   300     }
       
   301 
       
   302     ++from;
       
   303     to += chars_stored;
       
   304   }
       
   305 
       
   306   from_next = from;
       
   307   to_next   = to;
       
   308   return ok;
       
   309 }
       
   310 
       
   311  _STLP_DECLSPEC codecvt<wchar_t, char, mbstate_t>::result
       
   312 codecvt_byname<wchar_t, char, mbstate_t>
       
   313   ::do_in(state_type&         state,
       
   314           const extern_type*  from,
       
   315           const extern_type*  from_end,
       
   316           const extern_type*& from_next,
       
   317           intern_type*        to,
       
   318           intern_type*        ,
       
   319           intern_type*&       to_next) const {
       
   320   while (from != from_end) {
       
   321     size_t chars_read = _Locale_mbtowc(_M_ctype,
       
   322                                        to, from, from_end - from,
       
   323                                        &state);
       
   324     if (chars_read == (size_t) -1) {
       
   325       from_next = from;
       
   326       to_next   = to;
       
   327       return error;
       
   328     }
       
   329 
       
   330     if (chars_read == (size_t) -2) {
       
   331       from_next = from;
       
   332       to_next   = to;
       
   333       return partial;
       
   334     }
       
   335 
       
   336     from += chars_read;
       
   337     to++;
       
   338   }
       
   339 
       
   340   from_next = from;
       
   341   to_next   = to;
       
   342   return ok;
       
   343 }
       
   344 
       
   345 _STLP_DECLSPEC codecvt<wchar_t, char, mbstate_t>::result
       
   346 codecvt_byname<wchar_t, char, mbstate_t>
       
   347   ::do_unshift(state_type&   state,
       
   348                extern_type*  to,
       
   349                extern_type*  to_limit,
       
   350                extern_type*& to_next) const {
       
   351   to_next = to;
       
   352   size_t result = _Locale_unshift(_M_ctype, &state,
       
   353                                   to, to_limit - to, &to_next);
       
   354   if (result == (size_t) -1)
       
   355     return error;
       
   356   else if (result == (size_t) -2)
       
   357     return partial;
       
   358   else
       
   359 #    if defined (__ISCPP__)
       
   360     return /*to_next == to ? noconv :*/ ok;
       
   361 #    else
       
   362     return to_next == to ? noconv : ok;
       
   363 #    endif
       
   364 }
       
   365 
       
   366 _STLP_DECLSPEC int
       
   367 codecvt_byname<wchar_t, char, mbstate_t>::do_encoding() const _STLP_NOTHROW {
       
   368   if (_Locale_is_stateless(_M_ctype)) {
       
   369     int max_width = _Locale_mb_cur_max(_M_ctype);
       
   370     int min_width = _Locale_mb_cur_min(_M_ctype);
       
   371     return min_width == max_width ? min_width : 0;
       
   372   }
       
   373   else
       
   374     return -1;
       
   375 }
       
   376 
       
   377 _STLP_DECLSPEC bool codecvt_byname<wchar_t, char, mbstate_t>
       
   378   ::do_always_noconv() const _STLP_NOTHROW {
       
   379   return false;
       
   380 }
       
   381 
       
   382 _STLP_DECLSPEC int
       
   383 codecvt_byname<wchar_t, char, mbstate_t>::do_length(const state_type&,
       
   384                                                     const  extern_type* from, const  extern_type* end,
       
   385                                                     size_t mx) const
       
   386 { return (int)(min) ((size_t) (end - from), mx); }
       
   387 
       
   388 _STLP_DECLSPEC int
       
   389 codecvt_byname<wchar_t, char, mbstate_t>::do_max_length() const _STLP_NOTHROW
       
   390 { return _Locale_mb_cur_max(_M_ctype); }
       
   391 #  endif
       
   392 
       
   393 _STLP_END_NAMESPACE
       
   394 
       
   395 #endif /* MBSTATE_T */
       
   396 
       
   397 _STLP_BEGIN_NAMESPACE
       
   398 
       
   399 // numpunct_byname<char>
       
   400 _STLP_DECLSPEC numpunct_byname<char>::numpunct_byname(const char* name, size_t refs, _Locale_name_hint* hint)
       
   401   : numpunct<char>(refs),
       
   402     _M_numeric(_STLP_PRIV __acquire_numeric(name, hint)) {
       
   403   if (!_M_numeric)
       
   404     locale::_M_throw_runtime_error();
       
   405 
       
   406   _M_truename  = _Locale_true(_M_numeric);
       
   407   _M_falsename = _Locale_false(_M_numeric);
       
   408 }
       
   409 
       
   410 _STLP_DECLSPEC numpunct_byname<char>::~numpunct_byname()
       
   411 { _STLP_PRIV __release_numeric(_M_numeric); }
       
   412 
       
   413 _STLP_DECLSPEC char numpunct_byname<char>::do_decimal_point() const
       
   414 { return _Locale_decimal_point(_M_numeric); }
       
   415 
       
   416 _STLP_DECLSPEC char numpunct_byname<char>::do_thousands_sep() const
       
   417 { return _Locale_thousands_sep(_M_numeric); }
       
   418 
       
   419 _STLP_DECLSPEC string numpunct_byname<char>::do_grouping() const {
       
   420   const char * __grouping = _Locale_grouping(_M_numeric);
       
   421   if (__grouping != NULL && __grouping[0] == CHAR_MAX)
       
   422     __grouping = "";
       
   423   return __grouping;
       
   424 }
       
   425 
       
   426 //----------------------------------------------------------------------
       
   427 // numpunct<wchar_t>
       
   428 
       
   429 #if !defined (_STLP_NO_WCHAR_T)
       
   430 
       
   431 // numpunct_byname<wchar_t>
       
   432 
       
   433 _STLP_DECLSPEC numpunct_byname<wchar_t>::numpunct_byname(const char* name, size_t refs, _Locale_name_hint* hint)
       
   434   : numpunct<wchar_t>(refs),
       
   435     _M_numeric(_STLP_PRIV __acquire_numeric(name, hint)) {
       
   436   if (!_M_numeric)
       
   437     locale::_M_throw_runtime_error();
       
   438 
       
   439   const char* truename  = _Locale_true(_M_numeric);
       
   440   const char* falsename = _Locale_false(_M_numeric);
       
   441   _M_truename.resize(strlen(truename));
       
   442   _M_falsename.resize(strlen(falsename));
       
   443   copy(truename,  truename  + strlen(truename), _M_truename.begin());
       
   444   copy(falsename, falsename + strlen(falsename), _M_falsename.begin());
       
   445 }
       
   446 
       
   447 _STLP_DECLSPEC numpunct_byname<wchar_t>::~numpunct_byname()
       
   448 { _STLP_PRIV __release_numeric(_M_numeric); }
       
   449 
       
   450 _STLP_DECLSPEC wchar_t numpunct_byname<wchar_t>::do_decimal_point() const
       
   451 { return (wchar_t) _Locale_decimal_point(_M_numeric); }
       
   452 
       
   453 _STLP_DECLSPEC wchar_t numpunct_byname<wchar_t>::do_thousands_sep() const
       
   454 { return (wchar_t) _Locale_thousands_sep(_M_numeric); }
       
   455 
       
   456 _STLP_DECLSPEC string numpunct_byname<wchar_t>::do_grouping() const {
       
   457   const char * __grouping = _Locale_grouping(_M_numeric);
       
   458   if (__grouping != NULL && __grouping[0] == CHAR_MAX)
       
   459     __grouping = "";
       
   460   return __grouping;
       
   461 }
       
   462 
       
   463 #endif
       
   464 
       
   465 _STLP_MOVE_TO_PRIV_NAMESPACE
       
   466 
       
   467 static void _Init_monetary_formats(money_base::pattern& pos_format,
       
   468                                    money_base::pattern& neg_format,
       
   469                                    _Locale_monetary * monetary) {
       
   470   switch (_Locale_p_sign_posn(monetary)) {
       
   471     case 0: // Parentheses surround the quantity and currency_symbol
       
   472     case 1: // The sign string precedes the quantity and currency_symbol
       
   473       pos_format.field[0] = (char) money_base::sign;
       
   474       if (_Locale_p_cs_precedes(monetary)) {
       
   475         // 1 if currency_symbol precedes a positive value
       
   476         pos_format.field[1] = (char) money_base::symbol;
       
   477         if (_Locale_p_sep_by_space(monetary)) {
       
   478           // a space separates currency_symbol from a positive value.
       
   479           pos_format.field[2] = (char) money_base::space;
       
   480           pos_format.field[3] = (char) money_base::value;
       
   481         } else {
       
   482           // a space not separates currency_symbol from a positive value.
       
   483           pos_format.field[2] = (char) money_base::value;
       
   484           pos_format.field[3] = (char) money_base::none;
       
   485         }
       
   486       } else {
       
   487         // 0 if currency_symbol succeeds a positive value
       
   488         pos_format.field[1] = (char) money_base::value;
       
   489         if (_Locale_p_sep_by_space(monetary)) {
       
   490           // a space separates currency_symbol from a positive value.
       
   491           pos_format.field[2] = (char) money_base::space;
       
   492           pos_format.field[3] = (char) money_base::symbol;
       
   493         } else {
       
   494           // a space not separates currency_symbol from a positive value.
       
   495           pos_format.field[2] = (char) money_base::symbol;
       
   496           pos_format.field[3] = (char) money_base::none;
       
   497         }
       
   498       }
       
   499       break;
       
   500     case 2: // The sign string succeeds the quantity and currency_symbol.
       
   501       if (_Locale_p_cs_precedes(monetary)) {
       
   502         // 1 if currency_symbol precedes a positive value
       
   503         pos_format.field[0] = (char) money_base::symbol;
       
   504         if (_Locale_p_sep_by_space(monetary)) {
       
   505           // a space separates currency_symbol from a positive value.
       
   506           pos_format.field[1] = (char) money_base::space;
       
   507           pos_format.field[2] = (char) money_base::value;
       
   508           pos_format.field[3] = (char) money_base::sign;
       
   509         } else {
       
   510           // a space not separates currency_symbol from a positive value.
       
   511           pos_format.field[1] = (char) money_base::value;
       
   512           pos_format.field[2] = (char) money_base::sign;
       
   513           pos_format.field[3] = (char) money_base::none;
       
   514         }
       
   515       } else {
       
   516         // 0 if currency_symbol succeeds a positive value
       
   517         pos_format.field[0] = (char) money_base::value;
       
   518         if (_Locale_p_sep_by_space(monetary)) {
       
   519           // a space separates currency_symbol from a positive value.
       
   520           pos_format.field[1] = (char) money_base::space;
       
   521           pos_format.field[2] = (char) money_base::symbol;
       
   522           pos_format.field[3] = (char) money_base::sign;
       
   523         } else {
       
   524           // a space not separates currency_symbol from a positive value.
       
   525           pos_format.field[1] = (char) money_base::symbol;
       
   526           pos_format.field[2] = (char) money_base::sign;
       
   527           pos_format.field[3] = (char) money_base::none;
       
   528         }
       
   529       }
       
   530       break;
       
   531     case 3: // The sign string immediately precedes the currency_symbol.
       
   532       if (_Locale_p_cs_precedes(monetary)) {
       
   533         // 1 if currency_symbol precedes a positive value
       
   534         pos_format.field[0] = (char) money_base::sign;
       
   535         pos_format.field[1] = (char) money_base::symbol;
       
   536         if (_Locale_p_sep_by_space(monetary)) {
       
   537           // a space separates currency_symbol from a positive value.
       
   538           pos_format.field[2] = (char) money_base::space;
       
   539           pos_format.field[3] = (char) money_base::value;
       
   540         } else {
       
   541           // a space not separates currency_symbol from a positive value.
       
   542           pos_format.field[2] = (char) money_base::value;
       
   543           pos_format.field[3] = (char) money_base::none;
       
   544         }
       
   545       } else {
       
   546         // 0 if currency_symbol succeeds a positive value
       
   547         pos_format.field[0] = (char) money_base::value;
       
   548         pos_format.field[1] = (char) money_base::sign;
       
   549         pos_format.field[2] = (char) money_base::symbol;
       
   550         pos_format.field[3] = (char) money_base::none;
       
   551       }
       
   552       break;
       
   553     case 4: // The sign string immediately succeeds the currency_symbol.
       
   554     default:
       
   555       if (_Locale_p_cs_precedes(monetary)) {
       
   556         // 1 if currency_symbol precedes a positive value
       
   557         pos_format.field[0] = (char) money_base::symbol;
       
   558         pos_format.field[1] = (char) money_base::sign;
       
   559         pos_format.field[2] = (char) money_base::value;
       
   560         pos_format.field[3] = (char) money_base::none;
       
   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   }
       
   578 
       
   579   switch (_Locale_n_sign_posn(monetary)) {
       
   580     case 0: // Parentheses surround the quantity and currency_symbol
       
   581     case 1: // The sign string precedes the quantity and currency_symbol
       
   582       neg_format.field[0] = (char) money_base::sign;
       
   583       if (_Locale_n_cs_precedes(monetary)) {
       
   584         // 1 if currency_symbol precedes a negative value
       
   585         neg_format.field[1] = (char) money_base::symbol;
       
   586         if (_Locale_n_sep_by_space(monetary)) {
       
   587           // a space separates currency_symbol from a negative value.
       
   588           neg_format.field[2] = (char) money_base::space;
       
   589           neg_format.field[3] = (char) money_base::value;
       
   590         } else {
       
   591           // a space not separates currency_symbol from a negative value.
       
   592           neg_format.field[2] = (char) money_base::value;
       
   593           neg_format.field[3] = (char) money_base::none;
       
   594         }
       
   595       } else {
       
   596         // 0 if currency_symbol succeeds a negative value
       
   597         neg_format.field[1] = (char) money_base::value;
       
   598         if (_Locale_n_sep_by_space(monetary)) {
       
   599           // a space separates currency_symbol from a negative value.
       
   600           neg_format.field[2] = (char) money_base::space;
       
   601           neg_format.field[3] = (char) money_base::symbol;
       
   602         } else {
       
   603           // a space not separates currency_symbol from a negative value.
       
   604           neg_format.field[2] = (char) money_base::symbol;
       
   605           neg_format.field[3] = (char) money_base::none;
       
   606         }
       
   607       }
       
   608       break;
       
   609     case 2: // The sign string succeeds the quantity and currency_symbol.
       
   610       if (_Locale_n_cs_precedes(monetary)) {
       
   611         // 1 if currency_symbol precedes a negative value
       
   612         neg_format.field[0] = (char) money_base::symbol;
       
   613         if (_Locale_n_sep_by_space(monetary)) {
       
   614           // a space separates currency_symbol from a negative value.
       
   615           neg_format.field[1] = (char) money_base::space;
       
   616           neg_format.field[2] = (char) money_base::value;
       
   617           neg_format.field[3] = (char) money_base::sign;
       
   618         } else {
       
   619           // a space not separates currency_symbol from a negative value.
       
   620           neg_format.field[1] = (char) money_base::value;
       
   621           neg_format.field[2] = (char) money_base::sign;
       
   622           neg_format.field[3] = (char) money_base::none;
       
   623         }
       
   624       } else {
       
   625         // 0 if currency_symbol succeeds a negative value
       
   626         neg_format.field[0] = (char) money_base::value;
       
   627         if (_Locale_n_sep_by_space(monetary)) {
       
   628           // a space separates currency_symbol from a negative value.
       
   629           neg_format.field[1] = (char) money_base::space;
       
   630           neg_format.field[2] = (char) money_base::symbol;
       
   631           neg_format.field[3] = (char) money_base::sign;
       
   632         } else {
       
   633           // a space not separates currency_symbol from a negative value.
       
   634           neg_format.field[1] = (char) money_base::symbol;
       
   635           neg_format.field[2] = (char) money_base::sign;
       
   636           neg_format.field[3] = (char) money_base::none;
       
   637         }
       
   638       }
       
   639       break;
       
   640     case 3: // The sign string immediately precedes the currency_symbol.
       
   641       if (_Locale_n_cs_precedes(monetary)) {
       
   642         // 1 if currency_symbol precedes a negative value
       
   643         neg_format.field[0] = (char) money_base::sign;
       
   644         neg_format.field[1] = (char) money_base::symbol;
       
   645         if (_Locale_n_sep_by_space(monetary)) {
       
   646           // a space separates currency_symbol from a negative value.
       
   647           neg_format.field[2] = (char) money_base::space;
       
   648           neg_format.field[3] = (char) money_base::value;
       
   649         } else {
       
   650           // a space not separates currency_symbol from a negative value.
       
   651           neg_format.field[2] = (char) money_base::value;
       
   652           neg_format.field[3] = (char) money_base::none;
       
   653         }
       
   654       } else {
       
   655         // 0 if currency_symbol succeeds a negative value
       
   656         neg_format.field[0] = (char) money_base::value;
       
   657         neg_format.field[1] = (char) money_base::sign;
       
   658         neg_format.field[2] = (char) money_base::symbol;
       
   659         neg_format.field[3] = (char) money_base::none;
       
   660       }
       
   661       break;
       
   662     case 4: // The sign string immediately succeeds the currency_symbol.
       
   663     default:
       
   664       if (_Locale_n_cs_precedes(monetary)) {
       
   665         // 1 if currency_symbol precedes a negative value
       
   666         neg_format.field[0] = (char) money_base::symbol;
       
   667         neg_format.field[1] = (char) money_base::sign;
       
   668         neg_format.field[2] = (char) money_base::value;
       
   669         neg_format.field[3] = (char) money_base::none;
       
   670       } else {
       
   671         // 0 if currency_symbol succeeds a negative value
       
   672         neg_format.field[0] = (char) money_base::value;
       
   673         if (_Locale_n_sep_by_space(monetary)) {
       
   674           // a space separates currency_symbol from a negative value.
       
   675           neg_format.field[1] = (char) money_base::space;
       
   676           neg_format.field[2] = (char) money_base::symbol;
       
   677           neg_format.field[3] = (char) money_base::sign;
       
   678         } else {
       
   679           // a space not separates currency_symbol from a negative value.
       
   680           neg_format.field[1] = (char) money_base::symbol;
       
   681           neg_format.field[2] = (char) money_base::sign;
       
   682           neg_format.field[3] = (char) money_base::none;
       
   683         }
       
   684       }
       
   685       break;
       
   686   }
       
   687 }
       
   688 
       
   689 // international variant of monetary
       
   690 
       
   691 /*
       
   692  * int_curr_symbol
       
   693  *
       
   694  *   The international currency symbol. The operand is a four-character
       
   695  *   string, with the first three characters containing the alphabetic
       
   696  *   international currency symbol in accordance with those specified
       
   697  *   in the ISO 4217 specification. The fourth character is the character used
       
   698  *   to separate the international currency symbol from the monetary quantity.
       
   699  *
       
   700  * (http://www.opengroup.org/onlinepubs/7990989775/xbd/locale.html)
       
   701  */
       
   702 
       
   703 /*
       
   704  * Standards are unclear in the usage of international currency
       
   705  * and monetary formats.
       
   706  * But I am expect that international currency symbol should be the first
       
   707  * (not depends upon where currency symbol situated in the national
       
   708  * format).
       
   709  *
       
   710  * If this isn't so, let's see:
       
   711  *       1 234.56 RUR
       
   712  *       GBP 1,234.56
       
   713  *       USD 1,234.56
       
   714  * The situation really is worse than you see above:
       
   715  * RUR typed wrong here---it prints '1 234.56 RUR ' (see space after RUR).
       
   716  * This is due to intl_fmp.curr_symbol() == "RUR ". (see reference in comments
       
   717  * above).
       
   718  *
       
   719  */
       
   720 
       
   721 static void _Init_monetary_formats_int(money_base::pattern& pos_format,
       
   722                                        money_base::pattern& neg_format,
       
   723                                        _Locale_monetary * monetary)
       
   724 {
       
   725   pos_format.field[0] = (char) money_base::symbol;
       
   726   // pos_format.field[1] = (char) money_base::space;
       
   727 
       
   728   switch (_Locale_p_sign_posn(monetary)) {
       
   729     case 0: // Parentheses surround the quantity and currency_symbol
       
   730     case 1: // The sign string precedes the quantity and currency_symbol
       
   731       pos_format.field[1] = (char) money_base::sign;
       
   732       pos_format.field[2] = (char) money_base::value;
       
   733       break;
       
   734     case 2: // The sign string succeeds the quantity and currency_symbol.
       
   735       pos_format.field[1] = (char) money_base::value;
       
   736       pos_format.field[2] = (char) money_base::sign;
       
   737       break;
       
   738     case 3: // The sign string immediately precedes the currency_symbol.
       
   739     case 4: // The sign string immediately succeeds the currency_symbol.
       
   740     default:
       
   741       if (_Locale_p_cs_precedes(monetary)) {
       
   742         // 1 if currency_symbol precedes a positive value
       
   743         pos_format.field[1] = (char) money_base::sign;
       
   744         pos_format.field[2] = (char) money_base::value;
       
   745       } else {
       
   746         // 0 if currency_symbol succeeds a positive value
       
   747         pos_format.field[1] = (char) money_base::value;
       
   748         pos_format.field[2] = (char) money_base::sign;
       
   749       }
       
   750       break;
       
   751   }
       
   752   pos_format.field[3] = (char) money_base::none;
       
   753 
       
   754   neg_format.field[0] = (char) money_base::symbol;
       
   755   // neg_format.field[1] = (char) money_base::space;
       
   756 
       
   757   switch (_Locale_n_sign_posn(monetary)) {
       
   758     case 0: // Parentheses surround the quantity and currency_symbol
       
   759     case 1: // The sign string precedes the quantity and currency_symbol
       
   760       neg_format.field[1] = (char) money_base::sign;
       
   761       neg_format.field[2] = (char) money_base::value;
       
   762       break;
       
   763     case 2: // The sign string succeeds the quantity and currency_symbol.
       
   764       neg_format.field[1] = (char) money_base::value;
       
   765       neg_format.field[2] = (char) money_base::sign;
       
   766       break;
       
   767     case 3: // The sign string immediately precedes the currency_symbol.
       
   768     case 4: // The sign string immediately succeeds the currency_symbol.
       
   769     default:
       
   770       if (_Locale_n_cs_precedes(monetary)) {
       
   771         // 1 if currency_symbol precedes a negative value
       
   772         neg_format.field[1] = (char) money_base::sign;
       
   773         neg_format.field[2] = (char) money_base::value;
       
   774       } else {
       
   775         // 0 if currency_symbol succeeds a negative value
       
   776         neg_format.field[1] = (char) money_base::value;
       
   777         neg_format.field[2] = (char) money_base::sign;
       
   778       }
       
   779       break;
       
   780   }
       
   781   neg_format.field[3] = (char) money_base::none;
       
   782 }
       
   783 
       
   784 _STLP_MOVE_TO_STD_NAMESPACE
       
   785 
       
   786 //
       
   787 // moneypunct_byname<>
       
   788 //
       
   789 _STLP_DECLSPEC moneypunct_byname<char, true>::moneypunct_byname(const char * name,
       
   790                                                  size_t refs, _Locale_name_hint* hint):
       
   791   moneypunct<char, true>(refs), _M_monetary(_STLP_PRIV __acquire_monetary(name, hint)) {
       
   792   if (!_M_monetary)
       
   793     locale::_M_throw_runtime_error();
       
   794   _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
       
   795 }
       
   796 
       
   797 _STLP_DECLSPEC moneypunct_byname<char, true>::~moneypunct_byname()
       
   798 { _STLP_PRIV __release_monetary(_M_monetary); }
       
   799 
       
   800 _STLP_DECLSPEC char moneypunct_byname<char, true>::do_decimal_point() const
       
   801 { return _Locale_mon_decimal_point(_M_monetary); }
       
   802 
       
   803 _STLP_DECLSPEC char moneypunct_byname<char, true>::do_thousands_sep() const
       
   804 { return _Locale_mon_thousands_sep(_M_monetary); }
       
   805 
       
   806 _STLP_DECLSPEC string moneypunct_byname<char, true>::do_grouping() const
       
   807 { return _Locale_mon_grouping(_M_monetary); }
       
   808 
       
   809 _STLP_DECLSPEC string moneypunct_byname<char, true>::do_curr_symbol() const
       
   810 { return _Locale_int_curr_symbol(_M_monetary); }
       
   811 
       
   812 _STLP_DECLSPEC string moneypunct_byname<char, true>::do_positive_sign() const
       
   813 { return _Locale_positive_sign(_M_monetary); }
       
   814 
       
   815 _STLP_DECLSPEC string moneypunct_byname<char, true>::do_negative_sign() const
       
   816 { return _Locale_negative_sign(_M_monetary); }
       
   817 
       
   818 _STLP_DECLSPEC int moneypunct_byname<char, true>::do_frac_digits() const
       
   819 { return _Locale_int_frac_digits(_M_monetary); }
       
   820 
       
   821 _STLP_DECLSPEC moneypunct_byname<char, false>::moneypunct_byname(const char * name,
       
   822                                                   size_t refs, _Locale_name_hint* hint):
       
   823   moneypunct<char, false>(refs), _M_monetary(_STLP_PRIV __acquire_monetary(name, hint)) {
       
   824   if (!_M_monetary)
       
   825     locale::_M_throw_runtime_error();
       
   826   _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
       
   827 }
       
   828 
       
   829 _STLP_DECLSPEC moneypunct_byname<char, false>::~moneypunct_byname()
       
   830 { _STLP_PRIV __release_monetary(_M_monetary); }
       
   831 
       
   832 _STLP_DECLSPEC char moneypunct_byname<char, false>::do_decimal_point() const
       
   833 { return _Locale_mon_decimal_point(_M_monetary); }
       
   834 
       
   835 _STLP_DECLSPEC char moneypunct_byname<char, false>::do_thousands_sep() const
       
   836 { return _Locale_mon_thousands_sep(_M_monetary); }
       
   837 
       
   838 _STLP_DECLSPEC string moneypunct_byname<char, false>::do_grouping() const
       
   839 { return _Locale_mon_grouping(_M_monetary); }
       
   840 
       
   841 _STLP_DECLSPEC string moneypunct_byname<char, false>::do_curr_symbol() const
       
   842 { return _Locale_currency_symbol(_M_monetary); }
       
   843 
       
   844 _STLP_DECLSPEC string moneypunct_byname<char, false>::do_positive_sign() const
       
   845 { return _Locale_positive_sign(_M_monetary); }
       
   846 
       
   847 _STLP_DECLSPEC string moneypunct_byname<char, false>::do_negative_sign() const
       
   848 { return _Locale_negative_sign(_M_monetary); }
       
   849 
       
   850 _STLP_DECLSPEC int moneypunct_byname<char, false>::do_frac_digits() const
       
   851 { return _Locale_frac_digits(_M_monetary); }
       
   852 
       
   853 //
       
   854 // moneypunct_byname<wchar_t>
       
   855 //
       
   856 #if !defined (_STLP_NO_WCHAR_T)
       
   857 
       
   858 _STLP_DECLSPEC moneypunct_byname<wchar_t, true>::moneypunct_byname(const char * name,
       
   859                                                     size_t refs, _Locale_name_hint* hint):
       
   860   moneypunct<wchar_t, true>(refs), _M_monetary(_STLP_PRIV __acquire_monetary(name, hint)) {
       
   861   if (!_M_monetary)
       
   862     locale::_M_throw_runtime_error();
       
   863   _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
       
   864 }
       
   865 
       
   866 _STLP_DECLSPEC moneypunct_byname<wchar_t, true>::~moneypunct_byname()
       
   867 { _STLP_PRIV __release_monetary(_M_monetary); }
       
   868 
       
   869 _STLP_DECLSPEC wchar_t moneypunct_byname<wchar_t, true>::do_decimal_point() const
       
   870 { return _Locale_mon_decimal_point(_M_monetary); }
       
   871 
       
   872 _STLP_DECLSPEC wchar_t moneypunct_byname<wchar_t, true>::do_thousands_sep() const
       
   873 { return _Locale_mon_thousands_sep(_M_monetary); }
       
   874 
       
   875 _STLP_DECLSPEC string moneypunct_byname<wchar_t, true>::do_grouping() const
       
   876 { return _Locale_mon_grouping(_M_monetary); }
       
   877 
       
   878 inline wstring __do_widen (string const& str) {
       
   879 #if defined (_STLP_NO_MEMBER_TEMPLATES) || defined (_STLP_MSVC) || defined(__MRC__) || defined(__SC__) //*ty 05/26/2001 - added workaround for mpw
       
   880   wstring::_Reserve_t __Reserve;
       
   881   size_t __size = str.size();
       
   882   wstring result(__Reserve, __size);
       
   883   copy(str.begin(), str.end(), result.begin());
       
   884 #else
       
   885   wstring result(str.begin(), str.end());
       
   886 #endif
       
   887   return result;
       
   888 }
       
   889 
       
   890 _STLP_DECLSPEC wstring moneypunct_byname<wchar_t, true>::do_curr_symbol() const
       
   891 { return __do_widen(_Locale_int_curr_symbol(_M_monetary)); }
       
   892 
       
   893 _STLP_DECLSPEC wstring moneypunct_byname<wchar_t, true>::do_positive_sign() const
       
   894 { return __do_widen(_Locale_positive_sign(_M_monetary)); }
       
   895 
       
   896 _STLP_DECLSPEC wstring moneypunct_byname<wchar_t, true>::do_negative_sign() const
       
   897 { return __do_widen(_Locale_negative_sign(_M_monetary)); }
       
   898 
       
   899 _STLP_DECLSPEC int moneypunct_byname<wchar_t, true>::do_frac_digits() const
       
   900 { return _Locale_int_frac_digits(_M_monetary); }
       
   901 
       
   902 _STLP_DECLSPEC moneypunct_byname<wchar_t, false>::moneypunct_byname(const char * name,
       
   903                                                      size_t refs, _Locale_name_hint* hint):
       
   904   moneypunct<wchar_t, false>(refs), _M_monetary(_STLP_PRIV __acquire_monetary(name, hint)) {
       
   905   if (!_M_monetary)
       
   906     locale::_M_throw_runtime_error() ;
       
   907   _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
       
   908 }
       
   909 
       
   910 _STLP_DECLSPEC moneypunct_byname<wchar_t, false>::~moneypunct_byname()
       
   911 { _STLP_PRIV __release_monetary(_M_monetary); }
       
   912 
       
   913 _STLP_DECLSPEC wchar_t moneypunct_byname<wchar_t, false>::do_decimal_point() const
       
   914 { return _Locale_mon_decimal_point(_M_monetary); }
       
   915 
       
   916 _STLP_DECLSPEC wchar_t moneypunct_byname<wchar_t, false>::do_thousands_sep() const
       
   917 { return _Locale_mon_thousands_sep(_M_monetary); }
       
   918 
       
   919 _STLP_DECLSPEC string moneypunct_byname<wchar_t, false>::do_grouping() const
       
   920 { return _Locale_mon_grouping(_M_monetary); }
       
   921 
       
   922 _STLP_DECLSPEC wstring moneypunct_byname<wchar_t, false>::do_curr_symbol() const
       
   923 { return __do_widen(_Locale_currency_symbol(_M_monetary)); }
       
   924 
       
   925 _STLP_DECLSPEC wstring moneypunct_byname<wchar_t, false>::do_positive_sign() const
       
   926 { return __do_widen(_Locale_positive_sign(_M_monetary)); }
       
   927 
       
   928 _STLP_DECLSPEC wstring moneypunct_byname<wchar_t, false>::do_negative_sign() const
       
   929 { return __do_widen(_Locale_negative_sign(_M_monetary)); }
       
   930 
       
   931 _STLP_DECLSPEC int moneypunct_byname<wchar_t, false>::do_frac_digits() const
       
   932 { return _Locale_frac_digits(_M_monetary); }
       
   933 
       
   934 #endif
       
   935 
       
   936 _STLP_END_NAMESPACE
       
   937 
       
   938 #include "message_facets.h"
       
   939 
       
   940 _STLP_BEGIN_NAMESPACE
       
   941 
       
   942 _STLP_MOVE_TO_PRIV_NAMESPACE
       
   943 
       
   944 void _Catalog_locale_map::insert(nl_catd_type key, const locale& L) {
       
   945   _STLP_TRY {
       
   946 #if !defined(_STLP_NO_TYPEINFO) && !defined(_STLP_NO_RTTI)
       
   947     // Don't bother to do anything unless we're using a non-default ctype facet
       
   948 # ifdef _STLP_NO_WCHAR_T
       
   949     typedef char _Char;
       
   950 # else
       
   951     typedef wchar_t _Char;
       
   952 # endif
       
   953 
       
   954     typedef ctype<_Char> wctype;
       
   955     wctype const& wct = use_facet<wctype>(L);
       
   956     if (typeid(wct) != typeid(wctype)) {
       
   957 # endif /* _STLP_NO_TYPEINFO */
       
   958       if (!M)
       
   959         M = new map_type;
       
   960 
       
   961 #if defined (__SC__)
       
   962       if (!M) delete M;
       
   963 #endif
       
   964       M->insert(map_type::value_type(key, L));
       
   965 #if !defined(_STLP_NO_TYPEINFO) && !defined(_STLP_NO_RTTI)
       
   966     }
       
   967 # endif /* _STLP_NO_TYPEINFO */
       
   968   }
       
   969   _STLP_CATCH_ALL {}
       
   970 }
       
   971 
       
   972 void _Catalog_locale_map::erase(nl_catd_type key) {
       
   973   if (M)
       
   974     M->erase(key);
       
   975 }
       
   976 
       
   977 locale _Catalog_locale_map::lookup(nl_catd_type key) const {
       
   978   if (M) {
       
   979     map_type::const_iterator i = M->find(key);
       
   980     return i != M->end() ? (*i).second : locale::classic();
       
   981   }
       
   982   else
       
   983     return locale::classic();
       
   984 }
       
   985 
       
   986 
       
   987 #if defined (_STLP_USE_NL_CATD_MAPPING)
       
   988 _STLP_VOLATILE __stl_atomic_t _Catalog_nl_catd_map::_count = 0;
       
   989 
       
   990 messages_base::catalog _Catalog_nl_catd_map::insert(nl_catd_type cat) {
       
   991   messages_base::catalog &res = Mr[cat];
       
   992   if ( res == 0 ) {
       
   993 #if defined (_STLP_ATOMIC_INCREMENT)
       
   994     res = __STATIC_CAST(int, _STLP_ATOMIC_INCREMENT(&_count));
       
   995 #else
       
   996     static _STLP_STATIC_MUTEX _Count_lock _STLP_MUTEX_INITIALIZER;
       
   997     {
       
   998       _STLP_auto_lock sentry(_Count_lock);
       
   999       res = __STATIC_CAST(int, ++_count);
       
  1000     }
       
  1001 #endif
       
  1002     M[res] = cat;
       
  1003   }
       
  1004   return res;
       
  1005 }
       
  1006 
       
  1007 void _Catalog_nl_catd_map::erase(messages_base::catalog cat) {
       
  1008   map_type::iterator mit(M.find(cat));
       
  1009   if (mit != M.end()) {
       
  1010     Mr.erase((*mit).second);
       
  1011     M.erase(mit);
       
  1012   }
       
  1013 }
       
  1014 #endif
       
  1015 
       
  1016 //----------------------------------------------------------------------
       
  1017 //
       
  1018 //
       
  1019 
       
  1020 _Messages_impl::_Messages_impl(bool is_wide, _Locale_name_hint* hint) :
       
  1021   _M_message_obj(0), _M_map(0) {
       
  1022   _M_delete = true;
       
  1023   if (is_wide)
       
  1024     _M_map = new _Catalog_locale_map;
       
  1025   _M_message_obj = __acquire_messages("C", hint);
       
  1026 }
       
  1027 
       
  1028 _Messages_impl::_Messages_impl(bool is_wide, _Locale_messages* msg_obj ) :
       
  1029   _M_message_obj(msg_obj), _M_map(0) {
       
  1030   _M_delete = true;
       
  1031   if (is_wide)
       
  1032     _M_map = new _Catalog_locale_map;
       
  1033 }
       
  1034 
       
  1035 _Messages_impl::~_Messages_impl() {
       
  1036   __release_messages(_M_message_obj);
       
  1037   if (_M_map) delete _M_map;
       
  1038 }
       
  1039 
       
  1040 _Messages::catalog _Messages_impl::do_open(const string& filename, const locale& L) const {
       
  1041   nl_catd_type result = _M_message_obj ? _Locale_catopen(_M_message_obj, filename.c_str())
       
  1042     : (nl_catd_type)(-1);
       
  1043 
       
  1044   if ( result != (nl_catd_type)(-1) ) {
       
  1045     if ( _M_map != 0 ) {
       
  1046       _M_map->insert(result, L);
       
  1047     }
       
  1048     return _M_cat.insert( result );
       
  1049   }
       
  1050 
       
  1051   return -1;
       
  1052 }
       
  1053 
       
  1054 string _Messages_impl::do_get(catalog cat,
       
  1055                               int set, int p_id, const string& dfault) const {
       
  1056   return _M_message_obj != 0 && cat >= 0
       
  1057     ? string(_Locale_catgets(_M_message_obj, _M_cat[cat], set, p_id, dfault.c_str()))
       
  1058     : dfault;
       
  1059 }
       
  1060 
       
  1061 #if !defined (_STLP_NO_WCHAR_T)
       
  1062 
       
  1063 wstring
       
  1064 _Messages_impl::do_get(catalog thecat,
       
  1065                        int set, int p_id, const wstring& dfault) const {
       
  1066   typedef ctype<wchar_t> wctype;
       
  1067   const wctype& ct = use_facet<wctype>(_M_map->lookup( _M_cat[thecat] ) );
       
  1068 
       
  1069   const char* str = _Locale_catgets(_M_message_obj, _M_cat[thecat], set, p_id, "");
       
  1070 
       
  1071   // Verify that the lookup failed; an empty string might represent success.
       
  1072   if (!str)
       
  1073     return dfault;
       
  1074   else if (str[0] == '\0') {
       
  1075     const char* str2 = _Locale_catgets(_M_message_obj, _M_cat[thecat], set, p_id, "*");
       
  1076     if (!str2 || ((str2[0] == '*') && (str2[1] == '\0')))
       
  1077       return dfault;
       
  1078   }
       
  1079 
       
  1080   // str is correct.  Now we must widen it to get a wstring.
       
  1081   size_t n = strlen(str);
       
  1082 
       
  1083   // NOT PORTABLE.  What we're doing relies on internal details of the
       
  1084   // string implementation.  (Contiguity of string elements.)
       
  1085   wstring result(n, wchar_t(0));
       
  1086   ct.widen(str, str + n, &*result.begin());
       
  1087   return result;
       
  1088 }
       
  1089 
       
  1090 #endif
       
  1091 
       
  1092 void _Messages_impl::do_close(catalog thecat) const {
       
  1093   if (_M_message_obj)
       
  1094     _Locale_catclose(_M_message_obj, _M_cat[thecat]);
       
  1095   if (_M_map) _M_map->erase(_M_cat[thecat]);
       
  1096   _M_cat.erase( thecat );
       
  1097 }
       
  1098 
       
  1099 _STLP_MOVE_TO_STD_NAMESPACE
       
  1100 
       
  1101 //----------------------------------------------------------------------
       
  1102 // messages<char>
       
  1103 
       
  1104 _STLP_DECLSPEC messages<char>::messages(size_t refs) :
       
  1105   locale::facet(refs), _M_impl(new _STLP_PRIV _Messages_impl(false)) {}
       
  1106 
       
  1107 _STLP_DECLSPEC messages<char>::messages(size_t refs, _Locale_messages* msg_obj) : locale::facet(refs),
       
  1108   _M_impl(new _STLP_PRIV _Messages_impl(false, msg_obj)) {}
       
  1109 
       
  1110 
       
  1111 //----------------------------------------------------------------------
       
  1112 // messages_byname<char>
       
  1113 
       
  1114 _STLP_DECLSPEC messages_byname<char>::messages_byname(const char* name, size_t refs, _Locale_name_hint* hint)
       
  1115   : messages<char>(refs, name ? _STLP_PRIV __acquire_messages(name, hint) : 0) {}
       
  1116 
       
  1117 _STLP_DECLSPEC messages_byname<char>::~messages_byname() {}
       
  1118 
       
  1119 #if !defined (_STLP_NO_WCHAR_T)
       
  1120 
       
  1121 //----------------------------------------------------------------------
       
  1122 // messages<wchar_t>
       
  1123 
       
  1124 _STLP_DECLSPEC messages<wchar_t>::messages(size_t refs)  :
       
  1125   locale::facet(refs), _M_impl(new _STLP_PRIV _Messages_impl(true)) {}
       
  1126 
       
  1127 _STLP_DECLSPEC messages<wchar_t>::messages(size_t refs, _Locale_messages* msg_obj)
       
  1128   : locale::facet(refs),
       
  1129     _M_impl(new _STLP_PRIV _Messages_impl(true, msg_obj)) {}
       
  1130 
       
  1131 //----------------------------------------------------------------------
       
  1132 // messages_byname<wchar_t>
       
  1133 
       
  1134 
       
  1135 _STLP_DECLSPEC messages_byname<wchar_t>::messages_byname(const char* name, size_t refs, _Locale_name_hint* hint)
       
  1136   : messages<wchar_t>(refs, name ? _STLP_PRIV __acquire_messages(name, hint) : 0) {}
       
  1137 
       
  1138 _STLP_DECLSPEC messages_byname<wchar_t>::~messages_byname() {}
       
  1139 
       
  1140 #endif
       
  1141 
       
  1142 _STLP_END_NAMESPACE
       
  1143