1 // std::moneypunct implementation details, GNU version -*- C++ -*-
3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 // Free Software Foundation, Inc.
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 2, or (at your option)
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING. If not, write to the Free
19 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction. Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License. This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
32 // ISO C++ 14882: 22.2.6.3.2 moneypunct virtual functions
35 // Written by Benjamin Kosnik <bkoz@redhat.com>
38 #include <bits/c++locale_internal.h>
40 _GLIBCXX_BEGIN_NAMESPACE(std
)
42 // Construct and return valid pattern consisting of some combination of:
43 // space none symbol sign value
45 money_base::_S_construct_pattern(char __precedes
, char __space
, char __posn
)
49 // This insanely complicated routine attempts to construct a valid
50 // pattern for use with monyepunct. A couple of invariants:
52 // if (__precedes) symbol -> value
53 // else value -> symbol
58 // none == never first
59 // space never first or last
61 // Any elegant implementations of this are welcome.
66 // 1 The sign precedes the value and symbol.
67 __ret
.field
[0] = sign
;
70 // Pattern starts with sign.
73 __ret
.field
[1] = symbol
;
74 __ret
.field
[3] = value
;
78 __ret
.field
[1] = value
;
79 __ret
.field
[3] = symbol
;
81 __ret
.field
[2] = space
;
85 // Pattern starts with sign and ends with none.
88 __ret
.field
[1] = symbol
;
89 __ret
.field
[2] = value
;
93 __ret
.field
[1] = value
;
94 __ret
.field
[2] = symbol
;
96 __ret
.field
[3] = none
;
100 // 2 The sign follows the value and symbol.
103 // Pattern either ends with sign.
106 __ret
.field
[0] = symbol
;
107 __ret
.field
[2] = value
;
111 __ret
.field
[0] = value
;
112 __ret
.field
[2] = symbol
;
114 __ret
.field
[1] = space
;
115 __ret
.field
[3] = sign
;
119 // Pattern ends with sign then none.
122 __ret
.field
[0] = symbol
;
123 __ret
.field
[1] = value
;
127 __ret
.field
[0] = value
;
128 __ret
.field
[1] = symbol
;
130 __ret
.field
[2] = sign
;
131 __ret
.field
[3] = none
;
135 // 3 The sign immediately precedes the symbol.
138 __ret
.field
[0] = sign
;
139 __ret
.field
[1] = symbol
;
142 __ret
.field
[2] = space
;
143 __ret
.field
[3] = value
;
147 __ret
.field
[2] = value
;
148 __ret
.field
[3] = none
;
153 __ret
.field
[0] = value
;
156 __ret
.field
[1] = space
;
157 __ret
.field
[2] = sign
;
158 __ret
.field
[3] = symbol
;
162 __ret
.field
[1] = sign
;
163 __ret
.field
[2] = symbol
;
164 __ret
.field
[3] = none
;
169 // 4 The sign immediately follows the symbol.
172 __ret
.field
[0] = symbol
;
173 __ret
.field
[1] = sign
;
176 __ret
.field
[2] = space
;
177 __ret
.field
[3] = value
;
181 __ret
.field
[2] = value
;
182 __ret
.field
[3] = none
;
187 __ret
.field
[0] = value
;
190 __ret
.field
[1] = space
;
191 __ret
.field
[2] = symbol
;
192 __ret
.field
[3] = sign
;
196 __ret
.field
[1] = symbol
;
197 __ret
.field
[2] = sign
;
198 __ret
.field
[3] = none
;
210 moneypunct
<char, true>::_M_initialize_moneypunct(__c_locale __cloc
,
214 _M_data
= new __moneypunct_cache
<char, true>;
219 _M_data
->_M_decimal_point
= '.';
220 _M_data
->_M_thousands_sep
= ',';
221 _M_data
->_M_grouping
= "";
222 _M_data
->_M_grouping_size
= 0;
223 _M_data
->_M_curr_symbol
= "";
224 _M_data
->_M_curr_symbol_size
= 0;
225 _M_data
->_M_positive_sign
= "";
226 _M_data
->_M_positive_sign_size
= 0;
227 _M_data
->_M_negative_sign
= "";
228 _M_data
->_M_negative_sign_size
= 0;
229 _M_data
->_M_frac_digits
= 0;
230 _M_data
->_M_pos_format
= money_base::_S_default_pattern
;
231 _M_data
->_M_neg_format
= money_base::_S_default_pattern
;
233 for (size_t __i
= 0; __i
< money_base::_S_end
; ++__i
)
234 _M_data
->_M_atoms
[__i
] = money_base::_S_atoms
[__i
];
239 _M_data
->_M_decimal_point
= *(__nl_langinfo_l(__MON_DECIMAL_POINT
,
241 _M_data
->_M_thousands_sep
= *(__nl_langinfo_l(__MON_THOUSANDS_SEP
,
243 _M_data
->_M_grouping
= __nl_langinfo_l(__MON_GROUPING
, __cloc
);
244 _M_data
->_M_grouping_size
= strlen(_M_data
->_M_grouping
);
245 _M_data
->_M_positive_sign
= __nl_langinfo_l(__POSITIVE_SIGN
, __cloc
);
246 _M_data
->_M_positive_sign_size
= strlen(_M_data
->_M_positive_sign
);
248 char __nposn
= *(__nl_langinfo_l(__INT_N_SIGN_POSN
, __cloc
));
250 _M_data
->_M_negative_sign
= "()";
252 _M_data
->_M_negative_sign
= __nl_langinfo_l(__NEGATIVE_SIGN
,
254 _M_data
->_M_negative_sign_size
= strlen(_M_data
->_M_negative_sign
);
257 _M_data
->_M_curr_symbol
= __nl_langinfo_l(__INT_CURR_SYMBOL
, __cloc
);
258 _M_data
->_M_curr_symbol_size
= strlen(_M_data
->_M_curr_symbol
);
259 _M_data
->_M_frac_digits
= *(__nl_langinfo_l(__INT_FRAC_DIGITS
,
261 char __pprecedes
= *(__nl_langinfo_l(__INT_P_CS_PRECEDES
, __cloc
));
262 char __pspace
= *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE
, __cloc
));
263 char __pposn
= *(__nl_langinfo_l(__INT_P_SIGN_POSN
, __cloc
));
264 _M_data
->_M_pos_format
= _S_construct_pattern(__pprecedes
, __pspace
,
266 char __nprecedes
= *(__nl_langinfo_l(__INT_N_CS_PRECEDES
, __cloc
));
267 char __nspace
= *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE
, __cloc
));
268 _M_data
->_M_neg_format
= _S_construct_pattern(__nprecedes
, __nspace
,
275 moneypunct
<char, false>::_M_initialize_moneypunct(__c_locale __cloc
,
279 _M_data
= new __moneypunct_cache
<char, false>;
284 _M_data
->_M_decimal_point
= '.';
285 _M_data
->_M_thousands_sep
= ',';
286 _M_data
->_M_grouping
= "";
287 _M_data
->_M_grouping_size
= 0;
288 _M_data
->_M_curr_symbol
= "";
289 _M_data
->_M_curr_symbol_size
= 0;
290 _M_data
->_M_positive_sign
= "";
291 _M_data
->_M_positive_sign_size
= 0;
292 _M_data
->_M_negative_sign
= "";
293 _M_data
->_M_negative_sign_size
= 0;
294 _M_data
->_M_frac_digits
= 0;
295 _M_data
->_M_pos_format
= money_base::_S_default_pattern
;
296 _M_data
->_M_neg_format
= money_base::_S_default_pattern
;
298 for (size_t __i
= 0; __i
< money_base::_S_end
; ++__i
)
299 _M_data
->_M_atoms
[__i
] = money_base::_S_atoms
[__i
];
304 _M_data
->_M_decimal_point
= *(__nl_langinfo_l(__MON_DECIMAL_POINT
,
306 _M_data
->_M_thousands_sep
= *(__nl_langinfo_l(__MON_THOUSANDS_SEP
,
308 _M_data
->_M_grouping
= __nl_langinfo_l(__MON_GROUPING
, __cloc
);
309 _M_data
->_M_grouping_size
= strlen(_M_data
->_M_grouping
);
310 _M_data
->_M_positive_sign
= __nl_langinfo_l(__POSITIVE_SIGN
, __cloc
);
311 _M_data
->_M_positive_sign_size
= strlen(_M_data
->_M_positive_sign
);
313 char __nposn
= *(__nl_langinfo_l(__N_SIGN_POSN
, __cloc
));
315 _M_data
->_M_negative_sign
= "()";
317 _M_data
->_M_negative_sign
= __nl_langinfo_l(__NEGATIVE_SIGN
,
319 _M_data
->_M_negative_sign_size
= strlen(_M_data
->_M_negative_sign
);
322 _M_data
->_M_curr_symbol
= __nl_langinfo_l(__CURRENCY_SYMBOL
, __cloc
);
323 _M_data
->_M_curr_symbol_size
= strlen(_M_data
->_M_curr_symbol
);
324 _M_data
->_M_frac_digits
= *(__nl_langinfo_l(__FRAC_DIGITS
, __cloc
));
325 char __pprecedes
= *(__nl_langinfo_l(__P_CS_PRECEDES
, __cloc
));
326 char __pspace
= *(__nl_langinfo_l(__P_SEP_BY_SPACE
, __cloc
));
327 char __pposn
= *(__nl_langinfo_l(__P_SIGN_POSN
, __cloc
));
328 _M_data
->_M_pos_format
= _S_construct_pattern(__pprecedes
, __pspace
,
330 char __nprecedes
= *(__nl_langinfo_l(__N_CS_PRECEDES
, __cloc
));
331 char __nspace
= *(__nl_langinfo_l(__N_SEP_BY_SPACE
, __cloc
));
332 _M_data
->_M_neg_format
= _S_construct_pattern(__nprecedes
, __nspace
,
338 moneypunct
<char, true>::~moneypunct()
342 moneypunct
<char, false>::~moneypunct()
345 #ifdef _GLIBCXX_USE_WCHAR_T
348 moneypunct
<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc
,
349 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
356 _M_data
= new __moneypunct_cache
<wchar_t, true>;
361 _M_data
->_M_decimal_point
= L
'.';
362 _M_data
->_M_thousands_sep
= L
',';
363 _M_data
->_M_grouping
= "";
364 _M_data
->_M_grouping_size
= 0;
365 _M_data
->_M_curr_symbol
= L
"";
366 _M_data
->_M_curr_symbol_size
= 0;
367 _M_data
->_M_positive_sign
= L
"";
368 _M_data
->_M_positive_sign_size
= 0;
369 _M_data
->_M_negative_sign
= L
"";
370 _M_data
->_M_negative_sign_size
= 0;
371 _M_data
->_M_frac_digits
= 0;
372 _M_data
->_M_pos_format
= money_base::_S_default_pattern
;
373 _M_data
->_M_neg_format
= money_base::_S_default_pattern
;
375 // Use ctype::widen code without the facet...
376 for (size_t __i
= 0; __i
< money_base::_S_end
; ++__i
)
377 _M_data
->_M_atoms
[__i
] =
378 static_cast<wchar_t>(money_base::_S_atoms
[__i
]);
383 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
384 __c_locale __old
= __uselocale(__cloc
);
386 // Switch to named locale so that mbsrtowcs will work.
387 char* __old
= setlocale(LC_ALL
, NULL
);
388 const size_t __llen
= strlen(__old
) + 1;
389 char* __sav
= new char[__llen
];
390 memcpy(__sav
, __old
, __llen
);
391 setlocale(LC_ALL
, __name
);
394 union { char *__s
; wchar_t __w
; } __u
;
395 __u
.__s
= __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC
, __cloc
);
396 _M_data
->_M_decimal_point
= __u
.__w
;
398 __u
.__s
= __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC
, __cloc
);
399 _M_data
->_M_thousands_sep
= __u
.__w
;
400 _M_data
->_M_grouping
= __nl_langinfo_l(__MON_GROUPING
, __cloc
);
401 _M_data
->_M_grouping_size
= strlen(_M_data
->_M_grouping
);
403 const char* __cpossign
= __nl_langinfo_l(__POSITIVE_SIGN
, __cloc
);
404 const char* __cnegsign
= __nl_langinfo_l(__NEGATIVE_SIGN
, __cloc
);
405 const char* __ccurr
= __nl_langinfo_l(__INT_CURR_SYMBOL
, __cloc
);
407 wchar_t* __wcs_ps
= 0;
408 wchar_t* __wcs_ns
= 0;
409 const char __nposn
= *(__nl_langinfo_l(__INT_N_SIGN_POSN
, __cloc
));
413 size_t __len
= strlen(__cpossign
);
417 memset(&__state
, 0, sizeof(mbstate_t));
418 __wcs_ps
= new wchar_t[__len
];
419 mbsrtowcs(__wcs_ps
, &__cpossign
, __len
, &__state
);
420 _M_data
->_M_positive_sign
= __wcs_ps
;
423 _M_data
->_M_positive_sign
= L
"";
424 _M_data
->_M_positive_sign_size
= wcslen(_M_data
->_M_positive_sign
);
426 __len
= strlen(__cnegsign
);
428 _M_data
->_M_negative_sign
= L
"()";
432 memset(&__state
, 0, sizeof(mbstate_t));
433 __wcs_ns
= new wchar_t[__len
];
434 mbsrtowcs(__wcs_ns
, &__cnegsign
, __len
, &__state
);
435 _M_data
->_M_negative_sign
= __wcs_ns
;
438 _M_data
->_M_negative_sign
= L
"";
439 _M_data
->_M_negative_sign_size
= wcslen(_M_data
->_M_negative_sign
);
442 __len
= strlen(__ccurr
);
446 memset(&__state
, 0, sizeof(mbstate_t));
447 wchar_t* __wcs
= new wchar_t[__len
];
448 mbsrtowcs(__wcs
, &__ccurr
, __len
, &__state
);
449 _M_data
->_M_curr_symbol
= __wcs
;
452 _M_data
->_M_curr_symbol
= L
"";
453 _M_data
->_M_curr_symbol_size
= wcslen(_M_data
->_M_curr_symbol
);
461 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
464 setlocale(LC_ALL
, __sav
);
467 __throw_exception_again
;
470 _M_data
->_M_frac_digits
= *(__nl_langinfo_l(__INT_FRAC_DIGITS
,
472 char __pprecedes
= *(__nl_langinfo_l(__INT_P_CS_PRECEDES
, __cloc
));
473 char __pspace
= *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE
, __cloc
));
474 char __pposn
= *(__nl_langinfo_l(__INT_P_SIGN_POSN
, __cloc
));
475 _M_data
->_M_pos_format
= _S_construct_pattern(__pprecedes
, __pspace
,
477 char __nprecedes
= *(__nl_langinfo_l(__INT_N_CS_PRECEDES
, __cloc
));
478 char __nspace
= *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE
, __cloc
));
479 _M_data
->_M_neg_format
= _S_construct_pattern(__nprecedes
, __nspace
,
482 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
485 setlocale(LC_ALL
, __sav
);
493 moneypunct
<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc
,
494 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
501 _M_data
= new __moneypunct_cache
<wchar_t, false>;
506 _M_data
->_M_decimal_point
= L
'.';
507 _M_data
->_M_thousands_sep
= L
',';
508 _M_data
->_M_grouping
= "";
509 _M_data
->_M_grouping_size
= 0;
510 _M_data
->_M_curr_symbol
= L
"";
511 _M_data
->_M_curr_symbol_size
= 0;
512 _M_data
->_M_positive_sign
= L
"";
513 _M_data
->_M_positive_sign_size
= 0;
514 _M_data
->_M_negative_sign
= L
"";
515 _M_data
->_M_negative_sign_size
= 0;
516 _M_data
->_M_frac_digits
= 0;
517 _M_data
->_M_pos_format
= money_base::_S_default_pattern
;
518 _M_data
->_M_neg_format
= money_base::_S_default_pattern
;
520 // Use ctype::widen code without the facet...
521 for (size_t __i
= 0; __i
< money_base::_S_end
; ++__i
)
522 _M_data
->_M_atoms
[__i
] =
523 static_cast<wchar_t>(money_base::_S_atoms
[__i
]);
528 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
529 __c_locale __old
= __uselocale(__cloc
);
531 // Switch to named locale so that mbsrtowcs will work.
532 char* __old
= setlocale(LC_ALL
, NULL
);
533 const size_t __llen
= strlen(__old
) + 1;
534 char* __sav
= new char[__llen
];
535 memcpy(__sav
, __old
, __llen
);
536 setlocale(LC_ALL
, __name
);
539 union { char *__s
; wchar_t __w
; } __u
;
540 __u
.__s
= __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC
, __cloc
);
541 _M_data
->_M_decimal_point
= __u
.__w
;
543 __u
.__s
= __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC
, __cloc
);
544 _M_data
->_M_thousands_sep
= __u
.__w
;
545 _M_data
->_M_grouping
= __nl_langinfo_l(__MON_GROUPING
, __cloc
);
546 _M_data
->_M_grouping_size
= strlen(_M_data
->_M_grouping
);
548 const char* __cpossign
= __nl_langinfo_l(__POSITIVE_SIGN
, __cloc
);
549 const char* __cnegsign
= __nl_langinfo_l(__NEGATIVE_SIGN
, __cloc
);
550 const char* __ccurr
= __nl_langinfo_l(__CURRENCY_SYMBOL
, __cloc
);
552 wchar_t* __wcs_ps
= 0;
553 wchar_t* __wcs_ns
= 0;
554 const char __nposn
= *(__nl_langinfo_l(__N_SIGN_POSN
, __cloc
));
559 __len
= strlen(__cpossign
);
563 memset(&__state
, 0, sizeof(mbstate_t));
564 __wcs_ps
= new wchar_t[__len
];
565 mbsrtowcs(__wcs_ps
, &__cpossign
, __len
, &__state
);
566 _M_data
->_M_positive_sign
= __wcs_ps
;
569 _M_data
->_M_positive_sign
= L
"";
570 _M_data
->_M_positive_sign_size
= wcslen(_M_data
->_M_positive_sign
);
572 __len
= strlen(__cnegsign
);
574 _M_data
->_M_negative_sign
= L
"()";
578 memset(&__state
, 0, sizeof(mbstate_t));
579 __wcs_ns
= new wchar_t[__len
];
580 mbsrtowcs(__wcs_ns
, &__cnegsign
, __len
, &__state
);
581 _M_data
->_M_negative_sign
= __wcs_ns
;
584 _M_data
->_M_negative_sign
= L
"";
585 _M_data
->_M_negative_sign_size
= wcslen(_M_data
->_M_negative_sign
);
588 __len
= strlen(__ccurr
);
592 memset(&__state
, 0, sizeof(mbstate_t));
593 wchar_t* __wcs
= new wchar_t[__len
];
594 mbsrtowcs(__wcs
, &__ccurr
, __len
, &__state
);
595 _M_data
->_M_curr_symbol
= __wcs
;
598 _M_data
->_M_curr_symbol
= L
"";
599 _M_data
->_M_curr_symbol_size
= wcslen(_M_data
->_M_curr_symbol
);
607 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
610 setlocale(LC_ALL
, __sav
);
613 __throw_exception_again
;
616 _M_data
->_M_frac_digits
= *(__nl_langinfo_l(__FRAC_DIGITS
, __cloc
));
617 char __pprecedes
= *(__nl_langinfo_l(__P_CS_PRECEDES
, __cloc
));
618 char __pspace
= *(__nl_langinfo_l(__P_SEP_BY_SPACE
, __cloc
));
619 char __pposn
= *(__nl_langinfo_l(__P_SIGN_POSN
, __cloc
));
620 _M_data
->_M_pos_format
= _S_construct_pattern(__pprecedes
, __pspace
,
622 char __nprecedes
= *(__nl_langinfo_l(__N_CS_PRECEDES
, __cloc
));
623 char __nspace
= *(__nl_langinfo_l(__N_SEP_BY_SPACE
, __cloc
));
624 _M_data
->_M_neg_format
= _S_construct_pattern(__nprecedes
, __nspace
,
627 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
630 setlocale(LC_ALL
, __sav
);
637 moneypunct
<wchar_t, true>::~moneypunct()
639 if (_M_data
->_M_positive_sign_size
)
640 delete [] _M_data
->_M_positive_sign
;
641 if (_M_data
->_M_negative_sign_size
642 && wcscmp(_M_data
->_M_negative_sign
, L
"()") != 0)
643 delete [] _M_data
->_M_negative_sign
;
644 if (_M_data
->_M_curr_symbol_size
)
645 delete [] _M_data
->_M_curr_symbol
;
650 moneypunct
<wchar_t, false>::~moneypunct()
652 if (_M_data
->_M_positive_sign_size
)
653 delete [] _M_data
->_M_positive_sign
;
654 if (_M_data
->_M_negative_sign_size
655 && wcscmp(_M_data
->_M_negative_sign
, L
"()") != 0)
656 delete [] _M_data
->_M_negative_sign
;
657 if (_M_data
->_M_curr_symbol_size
)
658 delete [] _M_data
->_M_curr_symbol
;
663 _GLIBCXX_END_NAMESPACE