First public contribution.
3 * Silicon Graphics Computer Systems, Inc.
8 * This material is provided "as is", with absolutely no warranty expressed
9 * or implied. Any use is at your own risk.
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.
18 #include "stlport_prefix.h"
30 #include "locale_impl.h"
31 #include "acquire_release.h"
35 //----------------------------------------------------------------------
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;
43 locale::_M_throw_runtime_error();
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.
48 const _Locale_mask_t* p = _Locale_ctype_table(_M_ctype);
51 locale::_M_throw_runtime_error();
53 for (size_t i = 0; i < table_size; ++i) {
54 _Locale_mask_t __m = p[i];
55 if (__m & (upper | lower))
57 _M_byname_table[i] = ctype_base::mask(__m);
61 _STLP_DECLSPEC ctype_byname<char>::~ctype_byname()
62 { _STLP_PRIV __release_ctype(_M_ctype); }
64 _STLP_DECLSPEC char ctype_byname<char>::do_toupper(char c) const
65 { return (char)_Locale_toupper(_M_ctype, c); }
67 _STLP_DECLSPEC char ctype_byname<char>::do_tolower(char c) const
68 { return (char)_Locale_tolower(_M_ctype, c); }
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);
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);
85 // Some helper functions used in ctype<>::scan_is and scan_is_not.
86 #if !defined (_STLP_NO_WCHAR_T)
88 _STLP_MOVE_TO_PRIV_NAMESPACE
90 // ctype_byname<wchar_t>
92 struct _Ctype_byname_w_is_mask {
93 typedef wchar_t argument_type;
94 typedef bool result_type;
96 /* ctype_base::mask*/ int M;
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; }
104 _STLP_MOVE_TO_STD_NAMESPACE
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)) {
110 locale::_M_throw_runtime_error();
113 _STLP_DECLSPEC ctype_byname<wchar_t>::~ctype_byname()
114 { _STLP_PRIV __release_ctype(_M_ctype); }
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; }
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(
133 for ( ; low < high; ++low, ++m)
134 *m = ctype_base::mask (_Locale_wchar_ctype(_M_ctype, *low, all_bits));
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)); }
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))); }
148 _STLP_DECLSPEC wchar_t ctype_byname<wchar_t>::do_toupper(wchar_t c) const
149 { return _Locale_wchar_toupper(_M_ctype, c); }
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);
158 _STLP_DECLSPEC wchar_t ctype_byname<wchar_t>::do_tolower(wchar_t c) const
159 { return _Locale_wchar_tolower(_M_ctype, c); }
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);
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)) {
175 locale::_M_throw_runtime_error();
178 _STLP_DECLSPEC collate_byname<char>::~collate_byname()
179 { _STLP_PRIV __release_collate(_M_collate); }
181 _STLP_DECLSPEC int collate_byname<char>::do_compare(const char* __low1,
184 const char* __high2) const {
185 return _Locale_strcmp(_M_collate,
186 __low1, __high1 - __low1,
187 __low2, __high2 - __low2);
190 _STLP_DECLSPEC collate_byname<char>::string_type
191 collate_byname<char>::do_transform(const char* low, const char* high) const {
193 return string_type();
195 size_t n = _Locale_strxfrm(_M_collate, NULL, 0, low, high - low);
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);
206 #if !defined (_STLP_NO_WCHAR_T)
208 // collate_byname<wchar_t>
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)) {
214 locale::_M_throw_runtime_error();
217 _STLP_DECLSPEC collate_byname<wchar_t>::~collate_byname()
218 { _STLP_PRIV __release_collate(_M_collate); }
220 _STLP_DECLSPEC int collate_byname<wchar_t>::do_compare(const wchar_t* low1,
221 const wchar_t* high1,
223 const wchar_t* high2) const {
224 return _Locale_strwcmp(_M_collate,
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 {
233 return string_type();
235 size_t n = _Locale_strwxfrm(_M_collate, NULL, 0, low, high - low);
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);
245 #endif /* _STLP_NO_WCHAR_T */
249 #if !defined (_STLP_NO_MBSTATE_T)
251 _STLP_BEGIN_NAMESPACE
253 //----------------------------------------------------------------------
254 // codecvt_byname<char>
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) {}
260 _STLP_DECLSPEC codecvt_byname<char, char, mbstate_t>::~codecvt_byname() {}
263 # if !defined (_STLP_NO_WCHAR_T)
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)) {
272 locale::_M_throw_runtime_error();
275 _STLP_DECLSPEC codecvt_byname<wchar_t, char, mbstate_t>::~codecvt_byname()
276 { _STLP_PRIV __release_ctype(_M_ctype); }
278 _STLP_DECLSPEC codecvt<wchar_t, char, mbstate_t>::result
279 codecvt_byname<wchar_t, char, mbstate_t>
280 ::do_out(state_type& state,
282 const wchar_t* from_end,
283 const wchar_t*& from_next,
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,
291 if (chars_stored == (size_t) -1) {
296 else if (chars_stored == (size_t) -2) {
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,
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,
324 if (chars_read == (size_t) -1) {
330 if (chars_read == (size_t) -2) {
345 _STLP_DECLSPEC codecvt<wchar_t, char, mbstate_t>::result
346 codecvt_byname<wchar_t, char, mbstate_t>
347 ::do_unshift(state_type& state,
349 extern_type* to_limit,
350 extern_type*& to_next) const {
352 size_t result = _Locale_unshift(_M_ctype, &state,
353 to, to_limit - to, &to_next);
354 if (result == (size_t) -1)
356 else if (result == (size_t) -2)
359 # if defined (__ISCPP__)
360 return /*to_next == to ? noconv :*/ ok;
362 return to_next == to ? noconv : ok;
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;
377 _STLP_DECLSPEC bool codecvt_byname<wchar_t, char, mbstate_t>
378 ::do_always_noconv() const _STLP_NOTHROW {
383 codecvt_byname<wchar_t, char, mbstate_t>::do_length(const state_type&,
384 const extern_type* from, const extern_type* end,
386 { return (int)(min) ((size_t) (end - from), mx); }
389 codecvt_byname<wchar_t, char, mbstate_t>::do_max_length() const _STLP_NOTHROW
390 { return _Locale_mb_cur_max(_M_ctype); }
395 #endif /* MBSTATE_T */
397 _STLP_BEGIN_NAMESPACE
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)) {
404 locale::_M_throw_runtime_error();
406 _M_truename = _Locale_true(_M_numeric);
407 _M_falsename = _Locale_false(_M_numeric);
410 _STLP_DECLSPEC numpunct_byname<char>::~numpunct_byname()
411 { _STLP_PRIV __release_numeric(_M_numeric); }
413 _STLP_DECLSPEC char numpunct_byname<char>::do_decimal_point() const
414 { return _Locale_decimal_point(_M_numeric); }
416 _STLP_DECLSPEC char numpunct_byname<char>::do_thousands_sep() const
417 { return _Locale_thousands_sep(_M_numeric); }
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)
426 //----------------------------------------------------------------------
429 #if !defined (_STLP_NO_WCHAR_T)
431 // numpunct_byname<wchar_t>
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)) {
437 locale::_M_throw_runtime_error();
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());
447 _STLP_DECLSPEC numpunct_byname<wchar_t>::~numpunct_byname()
448 { _STLP_PRIV __release_numeric(_M_numeric); }
450 _STLP_DECLSPEC wchar_t numpunct_byname<wchar_t>::do_decimal_point() const
451 { return (wchar_t) _Locale_decimal_point(_M_numeric); }
453 _STLP_DECLSPEC wchar_t numpunct_byname<wchar_t>::do_thousands_sep() const
454 { return (wchar_t) _Locale_thousands_sep(_M_numeric); }
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)
465 _STLP_MOVE_TO_PRIV_NAMESPACE
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
553 case 4: // The sign string immediately succeeds the currency_symbol.
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
662 case 4: // The sign string immediately succeeds the currency_symbol.
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;
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;
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;
689 // international variant of monetary
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.
700 * (http://www.opengroup.org/onlinepubs/7990989775/xbd/locale.html)
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
710 * If this isn't so, let's see:
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
721 static void _Init_monetary_formats_int(money_base::pattern& pos_format,
722 money_base::pattern& neg_format,
723 _Locale_monetary * monetary)
725 pos_format.field[0] = (char) money_base::symbol;
726 // pos_format.field[1] = (char) money_base::space;
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;
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;
738 case 3: // The sign string immediately precedes the currency_symbol.
739 case 4: // The sign string immediately succeeds the currency_symbol.
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;
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;
752 pos_format.field[3] = (char) money_base::none;
754 neg_format.field[0] = (char) money_base::symbol;
755 // neg_format.field[1] = (char) money_base::space;
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;
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;
767 case 3: // The sign string immediately precedes the currency_symbol.
768 case 4: // The sign string immediately succeeds the currency_symbol.
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;
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;
781 neg_format.field[3] = (char) money_base::none;
784 _STLP_MOVE_TO_STD_NAMESPACE
787 // moneypunct_byname<>
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)) {
793 locale::_M_throw_runtime_error();
794 _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
797 _STLP_DECLSPEC moneypunct_byname<char, true>::~moneypunct_byname()
798 { _STLP_PRIV __release_monetary(_M_monetary); }
800 _STLP_DECLSPEC char moneypunct_byname<char, true>::do_decimal_point() const
801 { return _Locale_mon_decimal_point(_M_monetary); }
803 _STLP_DECLSPEC char moneypunct_byname<char, true>::do_thousands_sep() const
804 { return _Locale_mon_thousands_sep(_M_monetary); }
806 _STLP_DECLSPEC string moneypunct_byname<char, true>::do_grouping() const
807 { return _Locale_mon_grouping(_M_monetary); }
809 _STLP_DECLSPEC string moneypunct_byname<char, true>::do_curr_symbol() const
810 { return _Locale_int_curr_symbol(_M_monetary); }
812 _STLP_DECLSPEC string moneypunct_byname<char, true>::do_positive_sign() const
813 { return _Locale_positive_sign(_M_monetary); }
815 _STLP_DECLSPEC string moneypunct_byname<char, true>::do_negative_sign() const
816 { return _Locale_negative_sign(_M_monetary); }
818 _STLP_DECLSPEC int moneypunct_byname<char, true>::do_frac_digits() const
819 { return _Locale_int_frac_digits(_M_monetary); }
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)) {
825 locale::_M_throw_runtime_error();
826 _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
829 _STLP_DECLSPEC moneypunct_byname<char, false>::~moneypunct_byname()
830 { _STLP_PRIV __release_monetary(_M_monetary); }
832 _STLP_DECLSPEC char moneypunct_byname<char, false>::do_decimal_point() const
833 { return _Locale_mon_decimal_point(_M_monetary); }
835 _STLP_DECLSPEC char moneypunct_byname<char, false>::do_thousands_sep() const
836 { return _Locale_mon_thousands_sep(_M_monetary); }
838 _STLP_DECLSPEC string moneypunct_byname<char, false>::do_grouping() const
839 { return _Locale_mon_grouping(_M_monetary); }
841 _STLP_DECLSPEC string moneypunct_byname<char, false>::do_curr_symbol() const
842 { return _Locale_currency_symbol(_M_monetary); }
844 _STLP_DECLSPEC string moneypunct_byname<char, false>::do_positive_sign() const
845 { return _Locale_positive_sign(_M_monetary); }
847 _STLP_DECLSPEC string moneypunct_byname<char, false>::do_negative_sign() const
848 { return _Locale_negative_sign(_M_monetary); }
850 _STLP_DECLSPEC int moneypunct_byname<char, false>::do_frac_digits() const
851 { return _Locale_frac_digits(_M_monetary); }
854 // moneypunct_byname<wchar_t>
856 #if !defined (_STLP_NO_WCHAR_T)
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)) {
862 locale::_M_throw_runtime_error();
863 _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
866 _STLP_DECLSPEC moneypunct_byname<wchar_t, true>::~moneypunct_byname()
867 { _STLP_PRIV __release_monetary(_M_monetary); }
869 _STLP_DECLSPEC wchar_t moneypunct_byname<wchar_t, true>::do_decimal_point() const
870 { return _Locale_mon_decimal_point(_M_monetary); }
872 _STLP_DECLSPEC wchar_t moneypunct_byname<wchar_t, true>::do_thousands_sep() const
873 { return _Locale_mon_thousands_sep(_M_monetary); }
875 _STLP_DECLSPEC string moneypunct_byname<wchar_t, true>::do_grouping() const
876 { return _Locale_mon_grouping(_M_monetary); }
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());
885 wstring result(str.begin(), str.end());
890 _STLP_DECLSPEC wstring moneypunct_byname<wchar_t, true>::do_curr_symbol() const
891 { return __do_widen(_Locale_int_curr_symbol(_M_monetary)); }
893 _STLP_DECLSPEC wstring moneypunct_byname<wchar_t, true>::do_positive_sign() const
894 { return __do_widen(_Locale_positive_sign(_M_monetary)); }
896 _STLP_DECLSPEC wstring moneypunct_byname<wchar_t, true>::do_negative_sign() const
897 { return __do_widen(_Locale_negative_sign(_M_monetary)); }
899 _STLP_DECLSPEC int moneypunct_byname<wchar_t, true>::do_frac_digits() const
900 { return _Locale_int_frac_digits(_M_monetary); }
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)) {
906 locale::_M_throw_runtime_error() ;
907 _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
910 _STLP_DECLSPEC moneypunct_byname<wchar_t, false>::~moneypunct_byname()
911 { _STLP_PRIV __release_monetary(_M_monetary); }
913 _STLP_DECLSPEC wchar_t moneypunct_byname<wchar_t, false>::do_decimal_point() const
914 { return _Locale_mon_decimal_point(_M_monetary); }
916 _STLP_DECLSPEC wchar_t moneypunct_byname<wchar_t, false>::do_thousands_sep() const
917 { return _Locale_mon_thousands_sep(_M_monetary); }
919 _STLP_DECLSPEC string moneypunct_byname<wchar_t, false>::do_grouping() const
920 { return _Locale_mon_grouping(_M_monetary); }
922 _STLP_DECLSPEC wstring moneypunct_byname<wchar_t, false>::do_curr_symbol() const
923 { return __do_widen(_Locale_currency_symbol(_M_monetary)); }
925 _STLP_DECLSPEC wstring moneypunct_byname<wchar_t, false>::do_positive_sign() const
926 { return __do_widen(_Locale_positive_sign(_M_monetary)); }
928 _STLP_DECLSPEC wstring moneypunct_byname<wchar_t, false>::do_negative_sign() const
929 { return __do_widen(_Locale_negative_sign(_M_monetary)); }
931 _STLP_DECLSPEC int moneypunct_byname<wchar_t, false>::do_frac_digits() const
932 { return _Locale_frac_digits(_M_monetary); }
938 #include "message_facets.h"
940 _STLP_BEGIN_NAMESPACE
942 _STLP_MOVE_TO_PRIV_NAMESPACE
944 void _Catalog_locale_map::insert(nl_catd_type key, const locale& L) {
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
951 typedef wchar_t _Char;
954 typedef ctype<_Char> wctype;
955 wctype const& wct = use_facet<wctype>(L);
956 if (typeid(wct) != typeid(wctype)) {
957 # endif /* _STLP_NO_TYPEINFO */
964 M->insert(map_type::value_type(key, L));
965 #if !defined(_STLP_NO_TYPEINFO) && !defined(_STLP_NO_RTTI)
967 # endif /* _STLP_NO_TYPEINFO */
972 void _Catalog_locale_map::erase(nl_catd_type key) {
977 locale _Catalog_locale_map::lookup(nl_catd_type key) const {
979 map_type::const_iterator i = M->find(key);
980 return i != M->end() ? (*i).second : locale::classic();
983 return locale::classic();
987 #if defined (_STLP_USE_NL_CATD_MAPPING)
988 _STLP_VOLATILE __stl_atomic_t _Catalog_nl_catd_map::_count = 0;
990 messages_base::catalog _Catalog_nl_catd_map::insert(nl_catd_type cat) {
991 messages_base::catalog &res = Mr[cat];
993 #if defined (_STLP_ATOMIC_INCREMENT)
994 res = __STATIC_CAST(int, _STLP_ATOMIC_INCREMENT(&_count));
996 static _STLP_STATIC_MUTEX _Count_lock _STLP_MUTEX_INITIALIZER;
998 _STLP_auto_lock sentry(_Count_lock);
999 res = __STATIC_CAST(int, ++_count);
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);
1016 //----------------------------------------------------------------------
1020 _Messages_impl::_Messages_impl(bool is_wide, _Locale_name_hint* hint) :
1021 _M_message_obj(0), _M_map(0) {
1024 _M_map = new _Catalog_locale_map;
1025 _M_message_obj = __acquire_messages("C", hint);
1028 _Messages_impl::_Messages_impl(bool is_wide, _Locale_messages* msg_obj ) :
1029 _M_message_obj(msg_obj), _M_map(0) {
1032 _M_map = new _Catalog_locale_map;
1035 _Messages_impl::~_Messages_impl() {
1036 __release_messages(_M_message_obj);
1037 if (_M_map) delete _M_map;
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);
1044 if ( result != (nl_catd_type)(-1) ) {
1045 if ( _M_map != 0 ) {
1046 _M_map->insert(result, L);
1048 return _M_cat.insert( result );
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()))
1061 #if !defined (_STLP_NO_WCHAR_T)
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] ) );
1069 const char* str = _Locale_catgets(_M_message_obj, _M_cat[thecat], set, p_id, "");
1071 // Verify that the lookup failed; an empty string might represent success.
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')))
1080 // str is correct. Now we must widen it to get a wstring.
1081 size_t n = strlen(str);
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());
1092 void _Messages_impl::do_close(catalog thecat) const {
1094 _Locale_catclose(_M_message_obj, _M_cat[thecat]);
1095 if (_M_map) _M_map->erase(_M_cat[thecat]);
1096 _M_cat.erase( thecat );
1099 _STLP_MOVE_TO_STD_NAMESPACE
1101 //----------------------------------------------------------------------
1104 _STLP_DECLSPEC messages<char>::messages(size_t refs) :
1105 locale::facet(refs), _M_impl(new _STLP_PRIV _Messages_impl(false)) {}
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)) {}
1111 //----------------------------------------------------------------------
1112 // messages_byname<char>
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) {}
1117 _STLP_DECLSPEC messages_byname<char>::~messages_byname() {}
1119 #if !defined (_STLP_NO_WCHAR_T)
1121 //----------------------------------------------------------------------
1122 // messages<wchar_t>
1124 _STLP_DECLSPEC messages<wchar_t>::messages(size_t refs) :
1125 locale::facet(refs), _M_impl(new _STLP_PRIV _Messages_impl(true)) {}
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)) {}
1131 //----------------------------------------------------------------------
1132 // messages_byname<wchar_t>
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) {}
1138 _STLP_DECLSPEC messages_byname<wchar_t>::~messages_byname() {}