/home/ntakagi/work/STLport-5.1.5/src/facets_byname.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1999
00003  * Silicon Graphics Computer Systems, Inc.
00004  *
00005  * Copyright (c) 1999
00006  * Boris Fomitchev
00007  *
00008  * This material is provided "as is", with absolutely no warranty expressed
00009  * or implied. Any use is at your own risk.
00010  *
00011  * Permission to use or copy this software for any purpose is hereby granted
00012  * without fee, provided the above notices are retained on all copies.
00013  * Permission to modify the code and to distribute modified code is granted,
00014  * provided the above notices are retained, and a notice that the code was
00015  * modified is included with the above copyright notice.
00016  *
00017  */
00018 #include "stlport_prefix.h"
00019 
00020 #include <hash_map>
00021 #include <vector>
00022 
00023 #include <locale>
00024 #include <istream>
00025 
00026 #include <algorithm>
00027 #include <functional>
00028 
00029 #include "c_locale.h"
00030 #include "locale_impl.h"
00031 #include "acquire_release.h"
00032 
00033 _STLP_BEGIN_NAMESPACE
00034 
00035 //----------------------------------------------------------------------
00036 // ctype_byname<char>
00037 
00038 ctype_byname<char>::ctype_byname(const char* name, size_t refs, _Locale_name_hint* hint) :
00039     ctype<char>( 0, false, refs),
00040     _M_ctype(_STLP_PRIV __acquire_ctype(name, hint)) {
00041   ctype<char>::_M_ctype_table = _M_byname_table;
00042   if (!_M_ctype)
00043     locale::_M_throw_runtime_error();
00044 
00045   // We have to do this, instead of just pointer twiddling, because
00046   // ctype_base::mask isn't the same type as _Locale_mask_t.
00047 
00048   const _Locale_mask_t* p = _Locale_ctype_table(_M_ctype);
00049 
00050   if (!p)
00051     locale::_M_throw_runtime_error();
00052 
00053   for (size_t i = 0; i < table_size; ++i) {
00054     _Locale_mask_t __m = p[i];
00055     if (__m & (upper | lower))
00056       __m |= alpha;
00057     _M_byname_table[i] = ctype_base::mask(__m);
00058   }
00059 }
00060 
00061 ctype_byname<char>::~ctype_byname()
00062 { _STLP_PRIV __release_ctype(_M_ctype); }
00063 
00064 char ctype_byname<char>::do_toupper(char c) const
00065 { return (char)_Locale_toupper(_M_ctype, c); }
00066 
00067 char ctype_byname<char>::do_tolower(char c) const
00068 { return (char)_Locale_tolower(_M_ctype, c); }
00069 
00070 const char*
00071 ctype_byname<char>::do_toupper(char* first, const char* last) const {
00072   for ( ; first != last ; ++first)
00073     *first = (char)_Locale_toupper(_M_ctype, *first);
00074   return last;
00075 }
00076 
00077 const char*
00078 ctype_byname<char>::do_tolower(char* first, const char* last) const {
00079   for ( ; first != last ; ++first)
00080     *first = (char)_Locale_tolower(_M_ctype, *first);
00081   return last;
00082 }
00083 
00084 
00085 // Some helper functions used in ctype<>::scan_is and scan_is_not.
00086 #if !defined (_STLP_NO_WCHAR_T)
00087 
00088 _STLP_MOVE_TO_PRIV_NAMESPACE
00089 
00090 // ctype_byname<wchar_t>
00091 
00092 struct _Ctype_byname_w_is_mask {
00093   typedef wchar_t argument_type;
00094   typedef bool    result_type;
00095 
00096   /* ctype_base::mask*/ int  M;
00097   _Locale_ctype* M_ctp;
00098 
00099   _Ctype_byname_w_is_mask(/* ctype_base::mask */ int m, _Locale_ctype* c) : M((int)m), M_ctp(c) {}
00100   bool operator()(wchar_t c) const
00101     { return (M & _Locale_wchar_ctype(M_ctp, c, M)) != 0; }
00102 };
00103 
00104 _STLP_MOVE_TO_STD_NAMESPACE
00105 
00106 ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs, _Locale_name_hint* hint)
00107   : ctype<wchar_t>(refs),
00108     _M_ctype(_STLP_PRIV __acquire_ctype(name, hint)) {
00109   if (!_M_ctype)
00110     locale::_M_throw_runtime_error();
00111 }
00112 
00113 ctype_byname<wchar_t>::~ctype_byname()
00114 { _STLP_PRIV __release_ctype(_M_ctype); }
00115 
00116 bool ctype_byname<wchar_t>::do_is(ctype_base::mask  m, wchar_t c) const
00117 { return (m & _Locale_wchar_ctype(_M_ctype, c, m)) != 0; }
00118 
00119 const wchar_t*
00120 ctype_byname<wchar_t>::do_is(const wchar_t* low, const wchar_t* high,
00121                              ctype_base::mask * m) const {
00122   ctype_base::mask all_bits = ctype_base::mask(
00123     ctype_base::space |
00124     ctype_base::print |
00125     ctype_base::cntrl |
00126     ctype_base::upper |
00127     ctype_base::lower |
00128     ctype_base::alpha |
00129     ctype_base::digit |
00130     ctype_base::punct |
00131     ctype_base::xdigit);
00132 
00133   for ( ; low < high; ++low, ++m)
00134     *m = ctype_base::mask (_Locale_wchar_ctype(_M_ctype, *low, all_bits));
00135   return high;
00136 }
00137 
00138 const wchar_t*
00139 ctype_byname<wchar_t>
00140   ::do_scan_is(ctype_base::mask  m, const wchar_t* low, const wchar_t* high) const
00141 { return find_if(low, high, _STLP_PRIV _Ctype_byname_w_is_mask(m, _M_ctype)); }
00142 
00143 const wchar_t*
00144 ctype_byname<wchar_t>
00145   ::do_scan_not(ctype_base::mask  m, const wchar_t* low, const wchar_t* high) const
00146 { return find_if(low, high, not1(_STLP_PRIV _Ctype_byname_w_is_mask(m, _M_ctype))); }
00147 
00148 wchar_t ctype_byname<wchar_t>::do_toupper(wchar_t c) const
00149 { return _Locale_wchar_toupper(_M_ctype, c); }
00150 
00151 const wchar_t*
00152 ctype_byname<wchar_t>::do_toupper(wchar_t* low, const wchar_t* high) const {
00153   for ( ; low < high; ++low)
00154     *low = _Locale_wchar_toupper(_M_ctype, *low);
00155   return high;
00156 }
00157 
00158 wchar_t ctype_byname<wchar_t>::do_tolower(wchar_t c) const
00159 { return _Locale_wchar_tolower(_M_ctype, c); }
00160 
00161 const wchar_t*
00162 ctype_byname<wchar_t>::do_tolower(wchar_t* low, const wchar_t* high) const {
00163   for ( ; low < high; ++low)
00164     *low = _Locale_wchar_tolower(_M_ctype, *low);
00165   return high;
00166 }
00167 
00168 #endif /* WCHAR_T */
00169 
00170 // collate_byname<char>
00171 collate_byname<char>::collate_byname(const char* name, size_t refs, _Locale_name_hint* hint)
00172   : collate<char>(refs),
00173     _M_collate(_STLP_PRIV __acquire_collate(name, hint)) {
00174   if (!_M_collate)
00175     locale::_M_throw_runtime_error();
00176 }
00177 
00178 collate_byname<char>::~collate_byname()
00179 { _STLP_PRIV __release_collate(_M_collate); }
00180 
00181 int collate_byname<char>::do_compare(const char* __low1,
00182                                      const char* __high1,
00183                                      const char* __low2,
00184                                      const char* __high2) const {
00185   return _Locale_strcmp(_M_collate,
00186                         __low1, __high1 - __low1,
00187                         __low2, __high2 - __low2);
00188 }
00189 
00190 collate_byname<char>::string_type
00191 collate_byname<char>::do_transform(const char* low, const char* high) const {
00192   if (low == high)
00193     return string_type();
00194 
00195   size_t n = _Locale_strxfrm(_M_collate, NULL, 0, low, high - low);
00196 
00197   // NOT PORTABLE.  What we're doing relies on internal details of the
00198   // string implementation.  (Contiguity of string elements and presence
00199   // of trailing zero.)
00200   string_type buf(n, 0);
00201   _Locale_strxfrm(_M_collate, &(*buf.begin()), n + 1, low, high - low);
00202   return buf;
00203 }
00204 
00205 
00206 #if !defined (_STLP_NO_WCHAR_T)
00207 
00208 // collate_byname<wchar_t>
00209 
00210 collate_byname<wchar_t>::collate_byname(const char* name, size_t refs, _Locale_name_hint* hint)
00211   : collate<wchar_t>(refs),
00212     _M_collate(_STLP_PRIV __acquire_collate(name, hint)) {
00213   if (!_M_collate)
00214     locale::_M_throw_runtime_error();
00215 }
00216 
00217 collate_byname<wchar_t>::~collate_byname()
00218 { _STLP_PRIV __release_collate(_M_collate); }
00219 
00220 int collate_byname<wchar_t>::do_compare(const wchar_t* low1,
00221                                         const wchar_t* high1,
00222                                         const wchar_t* low2,
00223                                         const wchar_t* high2) const {
00224   return _Locale_strwcmp(_M_collate,
00225                          low1, high1 - low1,
00226                          low2, high2 - low2);
00227 }
00228 
00229 collate_byname<wchar_t>::string_type
00230 collate_byname<wchar_t>::do_transform(const wchar_t* low,
00231                                       const wchar_t* high) const {
00232   if (low == high)
00233     return string_type();
00234 
00235   size_t n = _Locale_strwxfrm(_M_collate, NULL, 0, low, high - low);
00236 
00237   // NOT PORTABLE.  What we're doing relies on internal details of the
00238   // string implementation.  (Contiguity of string elements and presence
00239   // of trailing zero.)
00240   string_type buf(n, 0);
00241   _Locale_strwxfrm(_M_collate, &(*buf.begin()), n + 1, low, high - low);
00242   return buf;
00243 }
00244 
00245 #endif /*  _STLP_NO_WCHAR_T */
00246 
00247 _STLP_END_NAMESPACE
00248 
00249 #if !defined (_STLP_NO_MBSTATE_T)
00250 
00251 _STLP_BEGIN_NAMESPACE
00252 
00253 //----------------------------------------------------------------------
00254 // codecvt_byname<char>
00255 
00256 codecvt_byname<char, char, mbstate_t>
00257   ::codecvt_byname(const char* /* name */, size_t refs)
00258     : codecvt<char, char, mbstate_t>(refs) {}
00259 
00260 codecvt_byname<char, char, mbstate_t>::~codecvt_byname() {}
00261 
00262 
00263 #  if !defined (_STLP_NO_WCHAR_T)
00264 
00265 //----------------------------------------------------------------------
00266 // codecvt_byname<wchar_t>
00267 codecvt_byname<wchar_t, char, mbstate_t>
00268   ::codecvt_byname(const char* name, size_t refs, _Locale_name_hint* hint)
00269     : codecvt<wchar_t, char, mbstate_t>(refs),
00270       _M_ctype(_STLP_PRIV __acquire_ctype(name, hint)) {
00271   if (!_M_ctype)
00272     locale::_M_throw_runtime_error();
00273 }
00274 
00275 codecvt_byname<wchar_t, char, mbstate_t>::~codecvt_byname()
00276 { _STLP_PRIV __release_ctype(_M_ctype); }
00277 
00278 codecvt<wchar_t, char, mbstate_t>::result
00279 codecvt_byname<wchar_t, char, mbstate_t>
00280   ::do_out(state_type&     state,
00281            const wchar_t*  from,
00282            const wchar_t*  from_end,
00283            const wchar_t*& from_next,
00284            char*           to,
00285            char*           to_limit,
00286            char*&          to_next) const {
00287   while (from != from_end) {
00288     size_t chars_stored = _Locale_wctomb(_M_ctype,
00289                                          to, to_limit - to, *from,
00290                                          &state);
00291     if (chars_stored == (size_t) -1) {
00292       from_next = from;
00293       to_next   = to;
00294       return error;
00295     }
00296     else if (chars_stored == (size_t) -2) {
00297       from_next = from;
00298       to_next   = to;
00299       return partial;
00300     }
00301 
00302     ++from;
00303     to += chars_stored;
00304   }
00305 
00306   from_next = from;
00307   to_next   = to;
00308   return ok;
00309 }
00310 
00311 codecvt<wchar_t, char, mbstate_t>::result
00312 codecvt_byname<wchar_t, char, mbstate_t>
00313   ::do_in(state_type&         state,
00314           const extern_type*  from,
00315           const extern_type*  from_end,
00316           const extern_type*& from_next,
00317           intern_type*        to,
00318           intern_type*        ,
00319           intern_type*&       to_next) const {
00320   while (from != from_end) {
00321     size_t chars_read = _Locale_mbtowc(_M_ctype,
00322                                        to, from, from_end - from,
00323                                        &state);
00324     if (chars_read == (size_t) -1) {
00325       from_next = from;
00326       to_next   = to;
00327       return error;
00328     }
00329 
00330     if (chars_read == (size_t) -2) {
00331       from_next = from;
00332       to_next   = to;
00333       return partial;
00334     }
00335 
00336     from += chars_read;
00337     to++;
00338   }
00339 
00340   from_next = from;
00341   to_next   = to;
00342   return ok;
00343 }
00344 
00345 codecvt<wchar_t, char, mbstate_t>::result
00346 codecvt_byname<wchar_t, char, mbstate_t>
00347   ::do_unshift(state_type&   state,
00348                extern_type*  to,
00349                extern_type*  to_limit,
00350                extern_type*& to_next) const {
00351   to_next = to;
00352   size_t result = _Locale_unshift(_M_ctype, &state,
00353                                   to, to_limit - to, &to_next);
00354   if (result == (size_t) -1)
00355     return error;
00356   else if (result == (size_t) -2)
00357     return partial;
00358   else
00359 #    if defined (__ISCPP__)
00360     return /*to_next == to ? noconv :*/ ok;
00361 #    else
00362     return to_next == to ? noconv : ok;
00363 #    endif
00364 }
00365 
00366 int
00367 codecvt_byname<wchar_t, char, mbstate_t>::do_encoding() const _STLP_NOTHROW {
00368   if (_Locale_is_stateless(_M_ctype)) {
00369     int max_width = _Locale_mb_cur_max(_M_ctype);
00370     int min_width = _Locale_mb_cur_min(_M_ctype);
00371     return min_width == max_width ? min_width : 0;
00372   }
00373   else
00374     return -1;
00375 }
00376 
00377 bool codecvt_byname<wchar_t, char, mbstate_t>
00378   ::do_always_noconv() const _STLP_NOTHROW {
00379   return false;
00380 }
00381 
00382 int
00383 codecvt_byname<wchar_t, char, mbstate_t>::do_length(const state_type&,
00384                                                     const  extern_type* from, const  extern_type* end,
00385                                                     size_t mx) const
00386 { return (int)(min) ((size_t) (end - from), mx); }
00387 
00388 int
00389 codecvt_byname<wchar_t, char, mbstate_t>::do_max_length() const _STLP_NOTHROW
00390 { return _Locale_mb_cur_max(_M_ctype); }
00391 #  endif
00392 
00393 _STLP_END_NAMESPACE
00394 
00395 #endif /* MBSTATE_T */
00396 
00397 _STLP_BEGIN_NAMESPACE
00398 
00399 // numpunct_byname<char>
00400 numpunct_byname<char>::numpunct_byname(const char* name, size_t refs, _Locale_name_hint* hint)
00401   : numpunct<char>(refs),
00402     _M_numeric(_STLP_PRIV __acquire_numeric(name, hint)) {
00403   if (!_M_numeric)
00404     locale::_M_throw_runtime_error();
00405 
00406   _M_truename  = _Locale_true(_M_numeric);
00407   _M_falsename = _Locale_false(_M_numeric);
00408 }
00409 
00410 numpunct_byname<char>::~numpunct_byname()
00411 { _STLP_PRIV __release_numeric(_M_numeric); }
00412 
00413 char numpunct_byname<char>::do_decimal_point() const
00414 { return _Locale_decimal_point(_M_numeric); }
00415 
00416 char numpunct_byname<char>::do_thousands_sep() const
00417 { return _Locale_thousands_sep(_M_numeric); }
00418 
00419 string numpunct_byname<char>::do_grouping() const {
00420   const char * __grouping = _Locale_grouping(_M_numeric);
00421   if (__grouping != NULL && __grouping[0] == CHAR_MAX)
00422     __grouping = "";
00423   return __grouping;
00424 }
00425 
00426 //----------------------------------------------------------------------
00427 // numpunct<wchar_t>
00428 
00429 #if !defined (_STLP_NO_WCHAR_T)
00430 
00431 // numpunct_byname<wchar_t>
00432 
00433 numpunct_byname<wchar_t>::numpunct_byname(const char* name, size_t refs, _Locale_name_hint* hint)
00434   : numpunct<wchar_t>(refs),
00435     _M_numeric(_STLP_PRIV __acquire_numeric(name, hint)) {
00436   if (!_M_numeric)
00437     locale::_M_throw_runtime_error();
00438 
00439   const char* truename  = _Locale_true(_M_numeric);
00440   const char* falsename = _Locale_false(_M_numeric);
00441   _M_truename.resize(strlen(truename));
00442   _M_falsename.resize(strlen(falsename));
00443   copy(truename,  truename  + strlen(truename), _M_truename.begin());
00444   copy(falsename, falsename + strlen(falsename), _M_falsename.begin());
00445 }
00446 
00447 numpunct_byname<wchar_t>::~numpunct_byname()
00448 { _STLP_PRIV __release_numeric(_M_numeric); }
00449 
00450 wchar_t numpunct_byname<wchar_t>::do_decimal_point() const
00451 { return (wchar_t) _Locale_decimal_point(_M_numeric); }
00452 
00453 wchar_t numpunct_byname<wchar_t>::do_thousands_sep() const
00454 { return (wchar_t) _Locale_thousands_sep(_M_numeric); }
00455 
00456 string numpunct_byname<wchar_t>::do_grouping() const {
00457   const char * __grouping = _Locale_grouping(_M_numeric);
00458   if (__grouping != NULL && __grouping[0] == CHAR_MAX)
00459     __grouping = "";
00460   return __grouping;
00461 }
00462 
00463 #endif
00464 
00465 _STLP_MOVE_TO_PRIV_NAMESPACE
00466 
00467 static void _Init_monetary_formats(money_base::pattern& pos_format,
00468                                    money_base::pattern& neg_format,
00469                                    _Locale_monetary * monetary) {
00470   switch (_Locale_p_sign_posn(monetary)) {
00471     case 0: // Parentheses surround the quantity and currency_symbol
00472     case 1: // The sign string precedes the quantity and currency_symbol
00473       pos_format.field[0] = (char) money_base::sign;
00474       if (_Locale_p_cs_precedes(monetary)) {
00475         // 1 if currency_symbol precedes a positive value
00476         pos_format.field[1] = (char) money_base::symbol;
00477         if (_Locale_p_sep_by_space(monetary)) {
00478           // a space separates currency_symbol from a positive value.
00479           pos_format.field[2] = (char) money_base::space;
00480           pos_format.field[3] = (char) money_base::value;
00481         } else {
00482           // a space not separates currency_symbol from a positive value.
00483           pos_format.field[2] = (char) money_base::value;
00484           pos_format.field[3] = (char) money_base::none;
00485         }
00486       } else {
00487         // 0 if currency_symbol succeeds a positive value
00488         pos_format.field[1] = (char) money_base::value;
00489         if (_Locale_p_sep_by_space(monetary)) {
00490           // a space separates currency_symbol from a positive value.
00491           pos_format.field[2] = (char) money_base::space;
00492           pos_format.field[3] = (char) money_base::symbol;
00493         } else {
00494           // a space not separates currency_symbol from a positive value.
00495           pos_format.field[2] = (char) money_base::symbol;
00496           pos_format.field[3] = (char) money_base::none;
00497         }
00498       }
00499       break;
00500     case 2: // The sign string succeeds the quantity and currency_symbol.
00501       if (_Locale_p_cs_precedes(monetary)) {
00502         // 1 if currency_symbol precedes a positive value
00503         pos_format.field[0] = (char) money_base::symbol;
00504         if (_Locale_p_sep_by_space(monetary)) {
00505           // a space separates currency_symbol from a positive value.
00506           pos_format.field[1] = (char) money_base::space;
00507           pos_format.field[2] = (char) money_base::value;
00508           pos_format.field[3] = (char) money_base::sign;
00509         } else {
00510           // a space not separates currency_symbol from a positive value.
00511           pos_format.field[1] = (char) money_base::value;
00512           pos_format.field[2] = (char) money_base::sign;
00513           pos_format.field[3] = (char) money_base::none;
00514         }
00515       } else {
00516         // 0 if currency_symbol succeeds a positive value
00517         pos_format.field[0] = (char) money_base::value;
00518         if (_Locale_p_sep_by_space(monetary)) {
00519           // a space separates currency_symbol from a positive value.
00520           pos_format.field[1] = (char) money_base::space;
00521           pos_format.field[2] = (char) money_base::symbol;
00522           pos_format.field[3] = (char) money_base::sign;
00523         } else {
00524           // a space not separates currency_symbol from a positive value.
00525           pos_format.field[1] = (char) money_base::symbol;
00526           pos_format.field[2] = (char) money_base::sign;
00527           pos_format.field[3] = (char) money_base::none;
00528         }
00529       }
00530       break;
00531     case 3: // The sign string immediately precedes the currency_symbol.
00532       if (_Locale_p_cs_precedes(monetary)) {
00533         // 1 if currency_symbol precedes a positive value
00534         pos_format.field[0] = (char) money_base::sign;
00535         pos_format.field[1] = (char) money_base::symbol;
00536         if (_Locale_p_sep_by_space(monetary)) {
00537           // a space separates currency_symbol from a positive value.
00538           pos_format.field[2] = (char) money_base::space;
00539           pos_format.field[3] = (char) money_base::value;
00540         } else {
00541           // a space not separates currency_symbol from a positive value.
00542           pos_format.field[2] = (char) money_base::value;
00543           pos_format.field[3] = (char) money_base::none;
00544         }
00545       } else {
00546         // 0 if currency_symbol succeeds a positive value
00547         pos_format.field[0] = (char) money_base::value;
00548         pos_format.field[1] = (char) money_base::sign;
00549         pos_format.field[2] = (char) money_base::symbol;
00550         pos_format.field[3] = (char) money_base::none;
00551       }
00552       break;
00553     case 4: // The sign string immediately succeeds the currency_symbol.
00554     default:
00555       if (_Locale_p_cs_precedes(monetary)) {
00556         // 1 if currency_symbol precedes a positive value
00557         pos_format.field[0] = (char) money_base::symbol;
00558         pos_format.field[1] = (char) money_base::sign;
00559         pos_format.field[2] = (char) money_base::value;
00560         pos_format.field[3] = (char) money_base::none;
00561       } else {
00562         // 0 if currency_symbol succeeds a positive value
00563         pos_format.field[0] = (char) money_base::value;
00564         if (_Locale_p_sep_by_space(monetary)) {
00565           // a space separates currency_symbol from a positive value.
00566           pos_format.field[1] = (char) money_base::space;
00567           pos_format.field[2] = (char) money_base::symbol;
00568           pos_format.field[3] = (char) money_base::sign;
00569         } else {
00570           // a space not separates currency_symbol from a positive value.
00571           pos_format.field[1] = (char) money_base::symbol;
00572           pos_format.field[2] = (char) money_base::sign;
00573           pos_format.field[3] = (char) money_base::none;
00574         }
00575       }
00576     break;
00577   }
00578 
00579   switch (_Locale_n_sign_posn(monetary)) {
00580     case 0: // Parentheses surround the quantity and currency_symbol
00581     case 1: // The sign string precedes the quantity and currency_symbol
00582       neg_format.field[0] = (char) money_base::sign;
00583       if (_Locale_n_cs_precedes(monetary)) {
00584         // 1 if currency_symbol precedes a negative value
00585         neg_format.field[1] = (char) money_base::symbol;
00586         if (_Locale_n_sep_by_space(monetary)) {
00587           // a space separates currency_symbol from a negative value.
00588           neg_format.field[2] = (char) money_base::space;
00589           neg_format.field[3] = (char) money_base::value;
00590         } else {
00591           // a space not separates currency_symbol from a negative value.
00592           neg_format.field[2] = (char) money_base::value;
00593           neg_format.field[3] = (char) money_base::none;
00594         }
00595       } else {
00596         // 0 if currency_symbol succeeds a negative value
00597         neg_format.field[1] = (char) money_base::value;
00598         if (_Locale_n_sep_by_space(monetary)) {
00599           // a space separates currency_symbol from a negative value.
00600           neg_format.field[2] = (char) money_base::space;
00601           neg_format.field[3] = (char) money_base::symbol;
00602         } else {
00603           // a space not separates currency_symbol from a negative value.
00604           neg_format.field[2] = (char) money_base::symbol;
00605           neg_format.field[3] = (char) money_base::none;
00606         }
00607       }
00608       break;
00609     case 2: // The sign string succeeds the quantity and currency_symbol.
00610       if (_Locale_n_cs_precedes(monetary)) {
00611         // 1 if currency_symbol precedes a negative value
00612         neg_format.field[0] = (char) money_base::symbol;
00613         if (_Locale_n_sep_by_space(monetary)) {
00614           // a space separates currency_symbol from a negative value.
00615           neg_format.field[1] = (char) money_base::space;
00616           neg_format.field[2] = (char) money_base::value;
00617           neg_format.field[3] = (char) money_base::sign;
00618         } else {
00619           // a space not separates currency_symbol from a negative value.
00620           neg_format.field[1] = (char) money_base::value;
00621           neg_format.field[2] = (char) money_base::sign;
00622           neg_format.field[3] = (char) money_base::none;
00623         }
00624       } else {
00625         // 0 if currency_symbol succeeds a negative value
00626         neg_format.field[0] = (char) money_base::value;
00627         if (_Locale_n_sep_by_space(monetary)) {
00628           // a space separates currency_symbol from a negative value.
00629           neg_format.field[1] = (char) money_base::space;
00630           neg_format.field[2] = (char) money_base::symbol;
00631           neg_format.field[3] = (char) money_base::sign;
00632         } else {
00633           // a space not separates currency_symbol from a negative value.
00634           neg_format.field[1] = (char) money_base::symbol;
00635           neg_format.field[2] = (char) money_base::sign;
00636           neg_format.field[3] = (char) money_base::none;
00637         }
00638       }
00639       break;
00640     case 3: // The sign string immediately precedes the currency_symbol.
00641       if (_Locale_n_cs_precedes(monetary)) {
00642         // 1 if currency_symbol precedes a negative value
00643         neg_format.field[0] = (char) money_base::sign;
00644         neg_format.field[1] = (char) money_base::symbol;
00645         if (_Locale_n_sep_by_space(monetary)) {
00646           // a space separates currency_symbol from a negative value.
00647           neg_format.field[2] = (char) money_base::space;
00648           neg_format.field[3] = (char) money_base::value;
00649         } else {
00650           // a space not separates currency_symbol from a negative value.
00651           neg_format.field[2] = (char) money_base::value;
00652           neg_format.field[3] = (char) money_base::none;
00653         }
00654       } else {
00655         // 0 if currency_symbol succeeds a negative value
00656         neg_format.field[0] = (char) money_base::value;
00657         neg_format.field[1] = (char) money_base::sign;
00658         neg_format.field[2] = (char) money_base::symbol;
00659         neg_format.field[3] = (char) money_base::none;
00660       }
00661       break;
00662     case 4: // The sign string immediately succeeds the currency_symbol.
00663     default:
00664       if (_Locale_n_cs_precedes(monetary)) {
00665         // 1 if currency_symbol precedes a negative value
00666         neg_format.field[0] = (char) money_base::symbol;
00667         neg_format.field[1] = (char) money_base::sign;
00668         neg_format.field[2] = (char) money_base::value;
00669         neg_format.field[3] = (char) money_base::none;
00670       } else {
00671         // 0 if currency_symbol succeeds a negative value
00672         neg_format.field[0] = (char) money_base::value;
00673         if (_Locale_n_sep_by_space(monetary)) {
00674           // a space separates currency_symbol from a negative value.
00675           neg_format.field[1] = (char) money_base::space;
00676           neg_format.field[2] = (char) money_base::symbol;
00677           neg_format.field[3] = (char) money_base::sign;
00678         } else {
00679           // a space not separates currency_symbol from a negative value.
00680           neg_format.field[1] = (char) money_base::symbol;
00681           neg_format.field[2] = (char) money_base::sign;
00682           neg_format.field[3] = (char) money_base::none;
00683         }
00684       }
00685       break;
00686   }
00687 }
00688 
00689 // international variant of monetary
00690 
00691 /*
00692  * int_curr_symbol
00693  *
00694  *   The international currency symbol. The operand is a four-character
00695  *   string, with the first three characters containing the alphabetic
00696  *   international currency symbol in accordance with those specified
00697  *   in the ISO 4217 specification. The fourth character is the character used
00698  *   to separate the international currency symbol from the monetary quantity.
00699  *
00700  * (http://www.opengroup.org/onlinepubs/7990989775/xbd/locale.html)
00701  */
00702 
00703 /*
00704  * Standards are unclear in the usage of international currency
00705  * and monetary formats.
00706  * But I am expect that international currency symbol should be the first
00707  * (not depends upon where currency symbol situated in the national
00708  * format).
00709  *
00710  * If this isn't so, let's see:
00711  *       1 234.56 RUR
00712  *       GBP 1,234.56
00713  *       USD 1,234.56
00714  * The situation really is worse than you see above:
00715  * RUR typed wrong here---it prints '1 234.56 RUR ' (see space after RUR).
00716  * This is due to intl_fmp.curr_symbol() == "RUR ". (see reference in comments
00717  * above).
00718  *
00719  */
00720 
00721 static void _Init_monetary_formats_int(money_base::pattern& pos_format,
00722                                        money_base::pattern& neg_format,
00723                                        _Locale_monetary * monetary)
00724 {
00725   pos_format.field[0] = (char) money_base::symbol;
00726   // pos_format.field[1] = (char) money_base::space;
00727 
00728   switch (_Locale_p_sign_posn(monetary)) {
00729     case 0: // Parentheses surround the quantity and currency_symbol
00730     case 1: // The sign string precedes the quantity and currency_symbol
00731       pos_format.field[1] = (char) money_base::sign;
00732       pos_format.field[2] = (char) money_base::value;
00733       break;
00734     case 2: // The sign string succeeds the quantity and currency_symbol.
00735       pos_format.field[1] = (char) money_base::value;
00736       pos_format.field[2] = (char) money_base::sign;
00737       break;
00738     case 3: // The sign string immediately precedes the currency_symbol.
00739     case 4: // The sign string immediately succeeds the currency_symbol.
00740     default:
00741       if (_Locale_p_cs_precedes(monetary)) {
00742         // 1 if currency_symbol precedes a positive value
00743         pos_format.field[1] = (char) money_base::sign;
00744         pos_format.field[2] = (char) money_base::value;
00745       } else {
00746         // 0 if currency_symbol succeeds a positive value
00747         pos_format.field[1] = (char) money_base::value;
00748         pos_format.field[2] = (char) money_base::sign;
00749       }
00750       break;
00751   }
00752   pos_format.field[3] = (char) money_base::none;
00753 
00754   neg_format.field[0] = (char) money_base::symbol;
00755   // neg_format.field[1] = (char) money_base::space;
00756 
00757   switch (_Locale_n_sign_posn(monetary)) {
00758     case 0: // Parentheses surround the quantity and currency_symbol
00759     case 1: // The sign string precedes the quantity and currency_symbol
00760       neg_format.field[1] = (char) money_base::sign;
00761       neg_format.field[2] = (char) money_base::value;
00762       break;
00763     case 2: // The sign string succeeds the quantity and currency_symbol.
00764       neg_format.field[1] = (char) money_base::value;
00765       neg_format.field[2] = (char) money_base::sign;
00766       break;
00767     case 3: // The sign string immediately precedes the currency_symbol.
00768     case 4: // The sign string immediately succeeds the currency_symbol.
00769     default:
00770       if (_Locale_n_cs_precedes(monetary)) {
00771         // 1 if currency_symbol precedes a negative value
00772         neg_format.field[1] = (char) money_base::sign;
00773         neg_format.field[2] = (char) money_base::value;
00774       } else {
00775         // 0 if currency_symbol succeeds a negative value
00776         neg_format.field[1] = (char) money_base::value;
00777         neg_format.field[2] = (char) money_base::sign;
00778       }
00779       break;
00780   }
00781   neg_format.field[3] = (char) money_base::none;
00782 }
00783 
00784 _STLP_MOVE_TO_STD_NAMESPACE
00785 
00786 //
00787 // moneypunct_byname<>
00788 //
00789 moneypunct_byname<char, true>::moneypunct_byname(const char * name,
00790                                                  size_t refs, _Locale_name_hint* hint):
00791   moneypunct<char, true>(refs), _M_monetary(_STLP_PRIV __acquire_monetary(name, hint)) {
00792   if (!_M_monetary)
00793     locale::_M_throw_runtime_error();
00794   _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
00795 }
00796 
00797 moneypunct_byname<char, true>::~moneypunct_byname()
00798 { _STLP_PRIV __release_monetary(_M_monetary); }
00799 
00800 char moneypunct_byname<char, true>::do_decimal_point() const
00801 { return _Locale_mon_decimal_point(_M_monetary); }
00802 
00803 char moneypunct_byname<char, true>::do_thousands_sep() const
00804 { return _Locale_mon_thousands_sep(_M_monetary); }
00805 
00806 string moneypunct_byname<char, true>::do_grouping() const
00807 { return _Locale_mon_grouping(_M_monetary); }
00808 
00809 string moneypunct_byname<char, true>::do_curr_symbol() const
00810 { return _Locale_int_curr_symbol(_M_monetary); }
00811 
00812 string moneypunct_byname<char, true>::do_positive_sign() const
00813 { return _Locale_positive_sign(_M_monetary); }
00814 
00815 string moneypunct_byname<char, true>::do_negative_sign() const
00816 { return _Locale_negative_sign(_M_monetary); }
00817 
00818 int moneypunct_byname<char, true>::do_frac_digits() const
00819 { return _Locale_int_frac_digits(_M_monetary); }
00820 
00821 moneypunct_byname<char, false>::moneypunct_byname(const char * name,
00822                                                   size_t refs, _Locale_name_hint* hint):
00823   moneypunct<char, false>(refs), _M_monetary(_STLP_PRIV __acquire_monetary(name, hint)) {
00824   if (!_M_monetary)
00825     locale::_M_throw_runtime_error();
00826   _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
00827 }
00828 
00829 moneypunct_byname<char, false>::~moneypunct_byname()
00830 { _STLP_PRIV __release_monetary(_M_monetary); }
00831 
00832 char moneypunct_byname<char, false>::do_decimal_point() const
00833 { return _Locale_mon_decimal_point(_M_monetary); }
00834 
00835 char moneypunct_byname<char, false>::do_thousands_sep() const
00836 { return _Locale_mon_thousands_sep(_M_monetary); }
00837 
00838 string moneypunct_byname<char, false>::do_grouping() const
00839 { return _Locale_mon_grouping(_M_monetary); }
00840 
00841 string moneypunct_byname<char, false>::do_curr_symbol() const
00842 { return _Locale_currency_symbol(_M_monetary); }
00843 
00844 string moneypunct_byname<char, false>::do_positive_sign() const
00845 { return _Locale_positive_sign(_M_monetary); }
00846 
00847 string moneypunct_byname<char, false>::do_negative_sign() const
00848 { return _Locale_negative_sign(_M_monetary); }
00849 
00850 int moneypunct_byname<char, false>::do_frac_digits() const
00851 { return _Locale_frac_digits(_M_monetary); }
00852 
00853 //
00854 // moneypunct_byname<wchar_t>
00855 //
00856 #if !defined (_STLP_NO_WCHAR_T)
00857 
00858 moneypunct_byname<wchar_t, true>::moneypunct_byname(const char * name,
00859                                                     size_t refs, _Locale_name_hint* hint):
00860   moneypunct<wchar_t, true>(refs), _M_monetary(_STLP_PRIV __acquire_monetary(name, hint)) {
00861   if (!_M_monetary)
00862     locale::_M_throw_runtime_error();
00863   _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
00864 }
00865 
00866 moneypunct_byname<wchar_t, true>::~moneypunct_byname()
00867 { _STLP_PRIV __release_monetary(_M_monetary); }
00868 
00869 wchar_t moneypunct_byname<wchar_t, true>::do_decimal_point() const
00870 { return _Locale_mon_decimal_point(_M_monetary); }
00871 
00872 wchar_t moneypunct_byname<wchar_t, true>::do_thousands_sep() const
00873 { return _Locale_mon_thousands_sep(_M_monetary); }
00874 
00875 string moneypunct_byname<wchar_t, true>::do_grouping() const
00876 { return _Locale_mon_grouping(_M_monetary); }
00877 
00878 inline wstring __do_widen (string const& str) {
00879 #if defined (_STLP_NO_MEMBER_TEMPLATES) || defined (_STLP_MSVC) || defined(__MRC__) || defined(__SC__) //*ty 05/26/2001 - added workaround for mpw
00880   wstring::_Reserve_t __Reserve;
00881   size_t __size = str.size();
00882   wstring result(__Reserve, __size);
00883   copy(str.begin(), str.end(), result.begin());
00884 #else
00885   wstring result(str.begin(), str.end());
00886 #endif
00887   return result;
00888 }
00889 
00890 wstring moneypunct_byname<wchar_t, true>::do_curr_symbol() const
00891 { return __do_widen(_Locale_int_curr_symbol(_M_monetary)); }
00892 
00893 wstring moneypunct_byname<wchar_t, true>::do_positive_sign() const
00894 { return __do_widen(_Locale_positive_sign(_M_monetary)); }
00895 
00896 wstring moneypunct_byname<wchar_t, true>::do_negative_sign() const
00897 { return __do_widen(_Locale_negative_sign(_M_monetary)); }
00898 
00899 int moneypunct_byname<wchar_t, true>::do_frac_digits() const
00900 { return _Locale_int_frac_digits(_M_monetary); }
00901 
00902 moneypunct_byname<wchar_t, false>::moneypunct_byname(const char * name,
00903                                                      size_t refs, _Locale_name_hint* hint):
00904   moneypunct<wchar_t, false>(refs), _M_monetary(_STLP_PRIV __acquire_monetary(name, hint)) {
00905   if (!_M_monetary)
00906     locale::_M_throw_runtime_error() ;
00907   _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
00908 }
00909 
00910 moneypunct_byname<wchar_t, false>::~moneypunct_byname()
00911 { _STLP_PRIV __release_monetary(_M_monetary); }
00912 
00913 wchar_t moneypunct_byname<wchar_t, false>::do_decimal_point() const
00914 { return _Locale_mon_decimal_point(_M_monetary); }
00915 
00916 wchar_t moneypunct_byname<wchar_t, false>::do_thousands_sep() const
00917 { return _Locale_mon_thousands_sep(_M_monetary); }
00918 
00919 string moneypunct_byname<wchar_t, false>::do_grouping() const
00920 { return _Locale_mon_grouping(_M_monetary); }
00921 
00922 wstring moneypunct_byname<wchar_t, false>::do_curr_symbol() const
00923 { return __do_widen(_Locale_currency_symbol(_M_monetary)); }
00924 
00925 wstring moneypunct_byname<wchar_t, false>::do_positive_sign() const
00926 { return __do_widen(_Locale_positive_sign(_M_monetary)); }
00927 
00928 wstring moneypunct_byname<wchar_t, false>::do_negative_sign() const
00929 { return __do_widen(_Locale_negative_sign(_M_monetary)); }
00930 
00931 int moneypunct_byname<wchar_t, false>::do_frac_digits() const
00932 { return _Locale_frac_digits(_M_monetary); }
00933 
00934 #endif
00935 
00936 _STLP_END_NAMESPACE
00937 
00938 #include "message_facets.h"
00939 
00940 _STLP_BEGIN_NAMESPACE
00941 
00942 _STLP_MOVE_TO_PRIV_NAMESPACE
00943 
00944 void _Catalog_locale_map::insert(nl_catd_type key, const locale& L) {
00945   _STLP_TRY {
00946 #if !defined(_STLP_NO_TYPEINFO) && !defined(_STLP_NO_RTTI)
00947     // Don't bother to do anything unless we're using a non-default ctype facet
00948 # ifdef _STLP_NO_WCHAR_T
00949     typedef char _Char;
00950 # else
00951     typedef wchar_t _Char;
00952 # endif
00953 
00954     typedef ctype<_Char> wctype;
00955     wctype const& wct = use_facet<wctype>(L);
00956     if (typeid(wct) != typeid(wctype)) {
00957 # endif /* _STLP_NO_TYPEINFO */
00958       if (!M)
00959         M = new map_type;
00960 
00961 #if defined (__SC__)
00962       if (!M) delete M;
00963 #endif
00964       M->insert(map_type::value_type(key, L));
00965 #if !defined(_STLP_NO_TYPEINFO) && !defined(_STLP_NO_RTTI)
00966     }
00967 # endif /* _STLP_NO_TYPEINFO */
00968   }
00969   _STLP_CATCH_ALL {}
00970 }
00971 
00972 void _Catalog_locale_map::erase(nl_catd_type key) {
00973   if (M)
00974     M->erase(key);
00975 }
00976 
00977 locale _Catalog_locale_map::lookup(nl_catd_type key) const {
00978   if (M) {
00979     map_type::const_iterator i = M->find(key);
00980     return i != M->end() ? (*i).second : locale::classic();
00981   }
00982   else
00983     return locale::classic();
00984 }
00985 
00986 
00987 #if defined (_STLP_USE_NL_CATD_MAPPING)
00988 _STLP_VOLATILE __stl_atomic_t _Catalog_nl_catd_map::_count = 0;
00989 
00990 messages_base::catalog _Catalog_nl_catd_map::insert(nl_catd_type cat) {
00991   messages_base::catalog &res = Mr[cat];
00992   if ( res == 0 ) {
00993 #if defined (_STLP_ATOMIC_INCREMENT)
00994     res = __STATIC_CAST(int, _STLP_ATOMIC_INCREMENT(&_count));
00995 #else
00996     static _STLP_STATIC_MUTEX _Count_lock _STLP_MUTEX_INITIALIZER;
00997     {
00998       _STLP_auto_lock sentry(_Count_lock);
00999       res = __STATIC_CAST(int, ++_count);
01000     }
01001 #endif
01002     M[res] = cat;
01003   }
01004   return res;
01005 }
01006 
01007 void _Catalog_nl_catd_map::erase(messages_base::catalog cat) {
01008   map_type::iterator mit(M.find(cat));
01009   if (mit != M.end()) {
01010     Mr.erase((*mit).second);
01011     M.erase(mit);
01012   }
01013 }
01014 #endif
01015 
01016 //----------------------------------------------------------------------
01017 //
01018 //
01019 
01020 _Messages_impl::_Messages_impl(bool is_wide, _Locale_name_hint* hint) :
01021   _M_message_obj(0), _M_map(0) {
01022   _M_delete = true;
01023   if (is_wide)
01024     _M_map = new _Catalog_locale_map;
01025   _M_message_obj = __acquire_messages("C", hint);
01026 }
01027 
01028 _Messages_impl::_Messages_impl(bool is_wide, _Locale_messages* msg_obj ) :
01029   _M_message_obj(msg_obj), _M_map(0) {
01030   _M_delete = true;
01031   if (is_wide)
01032     _M_map = new _Catalog_locale_map;
01033 }
01034 
01035 _Messages_impl::~_Messages_impl() {
01036   __release_messages(_M_message_obj);
01037   if (_M_map) delete _M_map;
01038 }
01039 
01040 _Messages::catalog _Messages_impl::do_open(const string& filename, const locale& L) const {
01041   nl_catd_type result = _M_message_obj ? _Locale_catopen(_M_message_obj, filename.c_str())
01042     : (nl_catd_type)(-1);
01043 
01044   if ( result != (nl_catd_type)(-1) ) {
01045     if ( _M_map != 0 ) {
01046       _M_map->insert(result, L);
01047     }
01048     return _M_cat.insert( result );
01049   }
01050 
01051   return -1;
01052 }
01053 
01054 string _Messages_impl::do_get(catalog cat,
01055                               int set, int p_id, const string& dfault) const {
01056   return _M_message_obj != 0 && cat >= 0
01057     ? string(_Locale_catgets(_M_message_obj, _M_cat[cat], set, p_id, dfault.c_str()))
01058     : dfault;
01059 }
01060 
01061 #if !defined (_STLP_NO_WCHAR_T)
01062 
01063 wstring
01064 _Messages_impl::do_get(catalog thecat,
01065                        int set, int p_id, const wstring& dfault) const {
01066   typedef ctype<wchar_t> wctype;
01067   const wctype& ct = use_facet<wctype>(_M_map->lookup( _M_cat[thecat] ) );
01068 
01069   const char* str = _Locale_catgets(_M_message_obj, _M_cat[thecat], set, p_id, "");
01070 
01071   // Verify that the lookup failed; an empty string might represent success.
01072   if (!str)
01073     return dfault;
01074   else if (str[0] == '\0') {
01075     const char* str2 = _Locale_catgets(_M_message_obj, _M_cat[thecat], set, p_id, "*");
01076     if (!str2 || ((str2[0] == '*') && (str2[1] == '\0')))
01077       return dfault;
01078   }
01079 
01080   // str is correct.  Now we must widen it to get a wstring.
01081   size_t n = strlen(str);
01082 
01083   // NOT PORTABLE.  What we're doing relies on internal details of the
01084   // string implementation.  (Contiguity of string elements.)
01085   wstring result(n, wchar_t(0));
01086   ct.widen(str, str + n, &*result.begin());
01087   return result;
01088 }
01089 
01090 #endif
01091 
01092 void _Messages_impl::do_close(catalog thecat) const {
01093   if (_M_message_obj)
01094     _Locale_catclose(_M_message_obj, _M_cat[thecat]);
01095   if (_M_map) _M_map->erase(_M_cat[thecat]);
01096   _M_cat.erase( thecat );
01097 }
01098 
01099 _STLP_MOVE_TO_STD_NAMESPACE
01100 
01101 //----------------------------------------------------------------------
01102 // messages<char>
01103 
01104 messages<char>::messages(size_t refs) :
01105   locale::facet(refs), _M_impl(new _STLP_PRIV _Messages_impl(false)) {}
01106 
01107 messages<char>::messages(size_t refs, _Locale_messages* msg_obj) : locale::facet(refs),
01108   _M_impl(new _STLP_PRIV _Messages_impl(false, msg_obj)) {}
01109 
01110 
01111 //----------------------------------------------------------------------
01112 // messages_byname<char>
01113 
01114 messages_byname<char>::messages_byname(const char* name, size_t refs, _Locale_name_hint* hint)
01115   : messages<char>(refs, name ? _STLP_PRIV __acquire_messages(name, hint) : 0) {}
01116 
01117 messages_byname<char>::~messages_byname() {}
01118 
01119 #if !defined (_STLP_NO_WCHAR_T)
01120 
01121 //----------------------------------------------------------------------
01122 // messages<wchar_t>
01123 
01124 messages<wchar_t>::messages(size_t refs)  :
01125   locale::facet(refs), _M_impl(new _STLP_PRIV _Messages_impl(true)) {}
01126 
01127 messages<wchar_t>::messages(size_t refs, _Locale_messages* msg_obj)
01128   : locale::facet(refs),
01129     _M_impl(new _STLP_PRIV _Messages_impl(true, msg_obj)) {}
01130 
01131 //----------------------------------------------------------------------
01132 // messages_byname<wchar_t>
01133 
01134 
01135 messages_byname<wchar_t>::messages_byname(const char* name, size_t refs, _Locale_name_hint* hint)
01136   : messages<wchar_t>(refs, name ? _STLP_PRIV __acquire_messages(name, hint) : 0) {}
01137 
01138 messages_byname<wchar_t>::~messages_byname() {}
01139 
01140 #endif
01141 
01142 _STLP_END_NAMESPACE
01143 



Generated on Mon Mar 10 15:32:16 2008 by  doxygen 1.5.1