1 // std::moneypunct implementation details, GNU version -*- C++ -*-
3 // Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING. If not, write to the Free
18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction. Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License. This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
31 // ISO C++ 14882: 22.2.6.3.2 moneypunct virtual functions
34 // Written by Benjamin Kosnik <bkoz@redhat.com>
37 #include <bits/c++locale_internal.h>
41 // Construct and return valid pattern consisting of some combination of:
42 // space none symbol sign value
44 money_base::_S_construct_pattern(char __precedes
, char __space
, char __posn
)
48 // This insanely complicated routine attempts to construct a valid
49 // pattern for use with monyepunct. A couple of invariants:
51 // if (__precedes) symbol -> value
52 // else value -> symbol
57 // none == never first
58 // space never first or last
60 // Any elegant implementations of this are welcome.
65 // 1 The sign precedes the value and symbol.
66 __ret
.field
[0] = sign
;
69 // Pattern starts with sign.
72 __ret
.field
[1] = symbol
;
73 __ret
.field
[3] = value
;
77 __ret
.field
[1] = value
;
78 __ret
.field
[3] = symbol
;
80 __ret
.field
[2] = space
;
84 // Pattern starts with sign and ends with none.
87 __ret
.field
[1] = symbol
;
88 __ret
.field
[2] = value
;
92 __ret
.field
[1] = value
;
93 __ret
.field
[2] = symbol
;
95 __ret
.field
[3] = none
;
99 // 2 The sign follows the value and symbol.
102 // Pattern either ends with sign.
105 __ret
.field
[0] = symbol
;
106 __ret
.field
[2] = value
;
110 __ret
.field
[0] = value
;
111 __ret
.field
[2] = symbol
;
113 __ret
.field
[1] = space
;
114 __ret
.field
[3] = sign
;
118 // Pattern ends with sign then none.
121 __ret
.field
[0] = symbol
;
122 __ret
.field
[1] = value
;
126 __ret
.field
[0] = value
;
127 __ret
.field
[1] = symbol
;
129 __ret
.field
[2] = sign
;
130 __ret
.field
[3] = none
;
134 // 3 The sign immediately precedes the symbol.
137 __ret
.field
[0] = sign
;
138 __ret
.field
[1] = symbol
;
141 __ret
.field
[2] = space
;
142 __ret
.field
[3] = value
;
146 __ret
.field
[2] = value
;
147 __ret
.field
[3] = none
;
152 __ret
.field
[0] = value
;
155 __ret
.field
[1] = space
;
156 __ret
.field
[2] = sign
;
157 __ret
.field
[3] = symbol
;
161 __ret
.field
[1] = sign
;
162 __ret
.field
[2] = symbol
;
163 __ret
.field
[3] = none
;
168 // 4 The sign immediately follows the symbol.
171 __ret
.field
[0] = symbol
;
172 __ret
.field
[1] = sign
;
175 __ret
.field
[2] = space
;
176 __ret
.field
[3] = value
;
180 __ret
.field
[2] = value
;
181 __ret
.field
[3] = none
;
186 __ret
.field
[0] = value
;
189 __ret
.field
[1] = space
;
190 __ret
.field
[2] = symbol
;
191 __ret
.field
[3] = sign
;
195 __ret
.field
[1] = symbol
;
196 __ret
.field
[2] = sign
;
197 __ret
.field
[3] = none
;
209 moneypunct
<char, true>::_M_initialize_moneypunct(__c_locale __cloc
,
213 _M_data
= new __moneypunct_cache
<char, true>;
218 _M_data
->_M_decimal_point
= '.';
219 _M_data
->_M_thousands_sep
= ',';
220 _M_data
->_M_grouping
= "";
221 _M_data
->_M_grouping_size
= 0;
222 _M_data
->_M_curr_symbol
= "";
223 _M_data
->_M_curr_symbol_size
= 0;
224 _M_data
->_M_positive_sign
= "";
225 _M_data
->_M_positive_sign_size
= 0;
226 _M_data
->_M_negative_sign
= "";
227 _M_data
->_M_negative_sign_size
= 0;
228 _M_data
->_M_frac_digits
= 0;
229 _M_data
->_M_pos_format
= money_base::_S_default_pattern
;
230 _M_data
->_M_neg_format
= money_base::_S_default_pattern
;
232 for (size_t __i
= 0; __i
< money_base::_S_end
; ++__i
)
233 _M_data
->_M_atoms
[__i
] = money_base::_S_atoms
[__i
];
238 _M_data
->_M_decimal_point
= *(__nl_langinfo_l(__MON_DECIMAL_POINT
,
240 _M_data
->_M_thousands_sep
= *(__nl_langinfo_l(__MON_THOUSANDS_SEP
,
242 _M_data
->_M_grouping
= __nl_langinfo_l(__MON_GROUPING
, __cloc
);
243 _M_data
->_M_grouping_size
= strlen(_M_data
->_M_grouping
);
244 _M_data
->_M_positive_sign
= __nl_langinfo_l(__POSITIVE_SIGN
, __cloc
);
245 _M_data
->_M_positive_sign_size
= strlen(_M_data
->_M_positive_sign
);
247 char __nposn
= *(__nl_langinfo_l(__INT_N_SIGN_POSN
, __cloc
));
249 _M_data
->_M_negative_sign
= "()";
251 _M_data
->_M_negative_sign
= __nl_langinfo_l(__NEGATIVE_SIGN
,
253 _M_data
->_M_negative_sign_size
= strlen(_M_data
->_M_negative_sign
);
256 _M_data
->_M_curr_symbol
= __nl_langinfo_l(__INT_CURR_SYMBOL
, __cloc
);
257 _M_data
->_M_curr_symbol_size
= strlen(_M_data
->_M_curr_symbol
);
258 _M_data
->_M_frac_digits
= *(__nl_langinfo_l(__INT_FRAC_DIGITS
,
260 char __pprecedes
= *(__nl_langinfo_l(__INT_P_CS_PRECEDES
, __cloc
));
261 char __pspace
= *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE
, __cloc
));
262 char __pposn
= *(__nl_langinfo_l(__INT_P_SIGN_POSN
, __cloc
));
263 _M_data
->_M_pos_format
= _S_construct_pattern(__pprecedes
, __pspace
,
265 char __nprecedes
= *(__nl_langinfo_l(__INT_N_CS_PRECEDES
, __cloc
));
266 char __nspace
= *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE
, __cloc
));
267 _M_data
->_M_neg_format
= _S_construct_pattern(__nprecedes
, __nspace
,
274 moneypunct
<char, false>::_M_initialize_moneypunct(__c_locale __cloc
,
278 _M_data
= new __moneypunct_cache
<char, false>;
283 _M_data
->_M_decimal_point
= '.';
284 _M_data
->_M_thousands_sep
= ',';
285 _M_data
->_M_grouping
= "";
286 _M_data
->_M_grouping_size
= 0;
287 _M_data
->_M_curr_symbol
= "";
288 _M_data
->_M_curr_symbol_size
= 0;
289 _M_data
->_M_positive_sign
= "";
290 _M_data
->_M_positive_sign_size
= 0;
291 _M_data
->_M_negative_sign
= "";
292 _M_data
->_M_negative_sign_size
= 0;
293 _M_data
->_M_frac_digits
= 0;
294 _M_data
->_M_pos_format
= money_base::_S_default_pattern
;
295 _M_data
->_M_neg_format
= money_base::_S_default_pattern
;
297 for (size_t __i
= 0; __i
< money_base::_S_end
; ++__i
)
298 _M_data
->_M_atoms
[__i
] = money_base::_S_atoms
[__i
];
303 _M_data
->_M_decimal_point
= *(__nl_langinfo_l(__MON_DECIMAL_POINT
,
305 _M_data
->_M_thousands_sep
= *(__nl_langinfo_l(__MON_THOUSANDS_SEP
,
307 _M_data
->_M_grouping
= __nl_langinfo_l(__MON_GROUPING
, __cloc
);
308 _M_data
->_M_grouping_size
= strlen(_M_data
->_M_grouping
);
309 _M_data
->_M_positive_sign
= __nl_langinfo_l(__POSITIVE_SIGN
, __cloc
);
310 _M_data
->_M_positive_sign_size
= strlen(_M_data
->_M_positive_sign
);
312 char __nposn
= *(__nl_langinfo_l(__N_SIGN_POSN
, __cloc
));
314 _M_data
->_M_negative_sign
= "()";
316 _M_data
->_M_negative_sign
= __nl_langinfo_l(__NEGATIVE_SIGN
,
318 _M_data
->_M_negative_sign_size
= strlen(_M_data
->_M_negative_sign
);
321 _M_data
->_M_curr_symbol
= __nl_langinfo_l(__CURRENCY_SYMBOL
, __cloc
);
322 _M_data
->_M_curr_symbol_size
= strlen(_M_data
->_M_curr_symbol
);
323 _M_data
->_M_frac_digits
= *(__nl_langinfo_l(__FRAC_DIGITS
, __cloc
));
324 char __pprecedes
= *(__nl_langinfo_l(__P_CS_PRECEDES
, __cloc
));
325 char __pspace
= *(__nl_langinfo_l(__P_SEP_BY_SPACE
, __cloc
));
326 char __pposn
= *(__nl_langinfo_l(__P_SIGN_POSN
, __cloc
));
327 _M_data
->_M_pos_format
= _S_construct_pattern(__pprecedes
, __pspace
,
329 char __nprecedes
= *(__nl_langinfo_l(__N_CS_PRECEDES
, __cloc
));
330 char __nspace
= *(__nl_langinfo_l(__N_SEP_BY_SPACE
, __cloc
));
331 _M_data
->_M_neg_format
= _S_construct_pattern(__nprecedes
, __nspace
,
337 moneypunct
<char, true>::~moneypunct()
341 moneypunct
<char, false>::~moneypunct()
344 #ifdef _GLIBCXX_USE_WCHAR_T
347 moneypunct
<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc
,
348 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
355 _M_data
= new __moneypunct_cache
<wchar_t, true>;
360 _M_data
->_M_decimal_point
= L
'.';
361 _M_data
->_M_thousands_sep
= L
',';
362 _M_data
->_M_grouping
= "";
363 _M_data
->_M_grouping_size
= 0;
364 _M_data
->_M_curr_symbol
= L
"";
365 _M_data
->_M_curr_symbol_size
= 0;
366 _M_data
->_M_positive_sign
= L
"";
367 _M_data
->_M_positive_sign_size
= 0;
368 _M_data
->_M_negative_sign
= L
"";
369 _M_data
->_M_negative_sign_size
= 0;
370 _M_data
->_M_frac_digits
= 0;
371 _M_data
->_M_pos_format
= money_base::_S_default_pattern
;
372 _M_data
->_M_neg_format
= money_base::_S_default_pattern
;
374 // Use ctype::widen code without the facet...
376 for (size_t __i
= 0; __i
< money_base::_S_end
; ++__i
)
378 uc
= static_cast<unsigned char>(money_base::_S_atoms
[__i
]);
379 _M_data
->_M_atoms
[__i
] = btowc(uc
);
385 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
386 __c_locale __old
= __uselocale(__cloc
);
388 // Switch to named locale so that mbsrtowcs will work.
389 char* __old
= strdup(setlocale(LC_ALL
, NULL
));
390 setlocale(LC_ALL
, __name
);
393 union __s_and_w
{ const char *__s
; unsigned int __w
; } __u
;
394 __u
.__s
= __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC
, __cloc
);
395 _M_data
->_M_decimal_point
= static_cast<wchar_t>(__u
.__w
);
397 __u
.__s
= __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC
, __cloc
);
398 _M_data
->_M_thousands_sep
= static_cast<wchar_t>(__u
.__w
);
399 _M_data
->_M_grouping
= __nl_langinfo_l(__MON_GROUPING
, __cloc
);
400 _M_data
->_M_grouping_size
= strlen(_M_data
->_M_grouping
);
402 const char* __cpossign
= __nl_langinfo_l(__POSITIVE_SIGN
, __cloc
);
403 const char* __cnegsign
= __nl_langinfo_l(__NEGATIVE_SIGN
, __cloc
);
404 const char* __ccurr
= __nl_langinfo_l(__INT_CURR_SYMBOL
, __cloc
);
406 wchar_t* __wcs_ps
= 0;
407 wchar_t* __wcs_ns
= 0;
408 const char __nposn
= *(__nl_langinfo_l(__INT_N_SIGN_POSN
, __cloc
));
412 size_t __len
= strlen(__cpossign
);
416 memset(&__state
, 0, sizeof(mbstate_t));
417 __wcs_ps
= new wchar_t[__len
];
418 mbsrtowcs(__wcs_ps
, &__cpossign
, __len
, &__state
);
419 _M_data
->_M_positive_sign
= __wcs_ps
;
422 _M_data
->_M_positive_sign
= L
"";
423 _M_data
->_M_positive_sign_size
= wcslen(_M_data
->_M_positive_sign
);
425 __len
= strlen(__cnegsign
);
427 _M_data
->_M_negative_sign
= L
"()";
431 memset(&__state
, 0, sizeof(mbstate_t));
432 __wcs_ns
= new wchar_t[__len
];
433 mbsrtowcs(__wcs_ns
, &__cnegsign
, __len
, &__state
);
434 _M_data
->_M_negative_sign
= __wcs_ns
;
437 _M_data
->_M_negative_sign
= L
"";
438 _M_data
->_M_negative_sign_size
= wcslen(_M_data
->_M_negative_sign
);
441 __len
= strlen(__ccurr
);
445 memset(&__state
, 0, sizeof(mbstate_t));
446 wchar_t* __wcs
= new wchar_t[__len
];
447 mbsrtowcs(__wcs
, &__ccurr
, __len
, &__state
);
448 _M_data
->_M_curr_symbol
= __wcs
;
451 _M_data
->_M_curr_symbol
= L
"";
452 _M_data
->_M_curr_symbol_size
= wcslen(_M_data
->_M_curr_symbol
);
460 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
463 setlocale(LC_ALL
, __old
);
466 __throw_exception_again
;
469 _M_data
->_M_frac_digits
= *(__nl_langinfo_l(__INT_FRAC_DIGITS
,
471 char __pprecedes
= *(__nl_langinfo_l(__INT_P_CS_PRECEDES
, __cloc
));
472 char __pspace
= *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE
, __cloc
));
473 char __pposn
= *(__nl_langinfo_l(__INT_P_SIGN_POSN
, __cloc
));
474 _M_data
->_M_pos_format
= _S_construct_pattern(__pprecedes
, __pspace
,
476 char __nprecedes
= *(__nl_langinfo_l(__INT_N_CS_PRECEDES
, __cloc
));
477 char __nspace
= *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE
, __cloc
));
478 _M_data
->_M_neg_format
= _S_construct_pattern(__nprecedes
, __nspace
,
481 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
484 setlocale(LC_ALL
, __old
);
492 moneypunct
<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc
,
493 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
500 _M_data
= new __moneypunct_cache
<wchar_t, false>;
505 _M_data
->_M_decimal_point
= L
'.';
506 _M_data
->_M_thousands_sep
= L
',';
507 _M_data
->_M_grouping
= "";
508 _M_data
->_M_grouping_size
= 0;
509 _M_data
->_M_curr_symbol
= L
"";
510 _M_data
->_M_curr_symbol_size
= 0;
511 _M_data
->_M_positive_sign
= L
"";
512 _M_data
->_M_positive_sign_size
= 0;
513 _M_data
->_M_negative_sign
= L
"";
514 _M_data
->_M_negative_sign_size
= 0;
515 _M_data
->_M_frac_digits
= 0;
516 _M_data
->_M_pos_format
= money_base::_S_default_pattern
;
517 _M_data
->_M_neg_format
= money_base::_S_default_pattern
;
519 // Use ctype::widen code without the facet...
521 for (size_t __i
= 0; __i
< money_base::_S_end
; ++__i
)
523 uc
= static_cast<unsigned char>(money_base::_S_atoms
[__i
]);
524 _M_data
->_M_atoms
[__i
] = btowc(uc
);
530 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
531 __c_locale __old
= __uselocale(__cloc
);
533 // Switch to named locale so that mbsrtowcs will work.
534 char* __old
= strdup(setlocale(LC_ALL
, NULL
));
535 setlocale(LC_ALL
, __name
);
538 union __s_and_w
{ const char *__s
; unsigned int __w
; } __u
;
539 __u
.__s
= __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC
, __cloc
);
540 _M_data
->_M_decimal_point
= static_cast<wchar_t>(__u
.__w
);
542 __u
.__s
= __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC
, __cloc
);
543 _M_data
->_M_thousands_sep
= static_cast<wchar_t>(__u
.__w
);
544 _M_data
->_M_grouping
= __nl_langinfo_l(__MON_GROUPING
, __cloc
);
545 _M_data
->_M_grouping_size
= strlen(_M_data
->_M_grouping
);
547 const char* __cpossign
= __nl_langinfo_l(__POSITIVE_SIGN
, __cloc
);
548 const char* __cnegsign
= __nl_langinfo_l(__NEGATIVE_SIGN
, __cloc
);
549 const char* __ccurr
= __nl_langinfo_l(__CURRENCY_SYMBOL
, __cloc
);
551 wchar_t* __wcs_ps
= 0;
552 wchar_t* __wcs_ns
= 0;
553 const char __nposn
= *(__nl_langinfo_l(__N_SIGN_POSN
, __cloc
));
558 __len
= strlen(__cpossign
);
562 memset(&__state
, 0, sizeof(mbstate_t));
563 __wcs_ps
= new wchar_t[__len
];
564 mbsrtowcs(__wcs_ps
, &__cpossign
, __len
, &__state
);
565 _M_data
->_M_positive_sign
= __wcs_ps
;
568 _M_data
->_M_positive_sign
= L
"";
569 _M_data
->_M_positive_sign_size
= wcslen(_M_data
->_M_positive_sign
);
571 __len
= strlen(__cnegsign
);
573 _M_data
->_M_negative_sign
= L
"()";
577 memset(&__state
, 0, sizeof(mbstate_t));
578 __wcs_ns
= new wchar_t[__len
];
579 mbsrtowcs(__wcs_ns
, &__cnegsign
, __len
, &__state
);
580 _M_data
->_M_negative_sign
= __wcs_ns
;
583 _M_data
->_M_negative_sign
= L
"";
584 _M_data
->_M_negative_sign_size
= wcslen(_M_data
->_M_negative_sign
);
587 __len
= strlen(__ccurr
);
591 memset(&__state
, 0, sizeof(mbstate_t));
592 wchar_t* __wcs
= new wchar_t[__len
];
593 mbsrtowcs(__wcs
, &__ccurr
, __len
, &__state
);
594 _M_data
->_M_curr_symbol
= __wcs
;
597 _M_data
->_M_curr_symbol
= L
"";
598 _M_data
->_M_curr_symbol_size
= wcslen(_M_data
->_M_curr_symbol
);
606 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
609 setlocale(LC_ALL
, __old
);
612 __throw_exception_again
;
615 _M_data
->_M_frac_digits
= *(__nl_langinfo_l(__FRAC_DIGITS
, __cloc
));
616 char __pprecedes
= *(__nl_langinfo_l(__P_CS_PRECEDES
, __cloc
));
617 char __pspace
= *(__nl_langinfo_l(__P_SEP_BY_SPACE
, __cloc
));
618 char __pposn
= *(__nl_langinfo_l(__P_SIGN_POSN
, __cloc
));
619 _M_data
->_M_pos_format
= _S_construct_pattern(__pprecedes
, __pspace
,
621 char __nprecedes
= *(__nl_langinfo_l(__N_CS_PRECEDES
, __cloc
));
622 char __nspace
= *(__nl_langinfo_l(__N_SEP_BY_SPACE
, __cloc
));
623 _M_data
->_M_neg_format
= _S_construct_pattern(__nprecedes
, __nspace
,
626 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
629 setlocale(LC_ALL
, __old
);
636 moneypunct
<wchar_t, true>::~moneypunct()
638 if (_M_data
->_M_positive_sign_size
)
639 delete [] _M_data
->_M_positive_sign
;
640 if (_M_data
->_M_negative_sign_size
641 && wcscmp(_M_data
->_M_negative_sign
, L
"()") != 0)
642 delete [] _M_data
->_M_negative_sign
;
643 if (_M_data
->_M_curr_symbol_size
)
644 delete [] _M_data
->_M_curr_symbol
;
649 moneypunct
<wchar_t, false>::~moneypunct()
651 if (_M_data
->_M_positive_sign_size
)
652 delete [] _M_data
->_M_positive_sign
;
653 if (_M_data
->_M_negative_sign_size
654 && wcscmp(_M_data
->_M_negative_sign
, L
"()") != 0)
655 delete [] _M_data
->_M_negative_sign
;
656 if (_M_data
->_M_curr_symbol_size
)
657 delete [] _M_data
->_M_curr_symbol
;