1 // std::moneypunct implementation details, GNU version -*- C++ -*-
3 // Copyright (C) 2001, 2002, 2003, 2004, 2005 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
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>
39 _GLIBCXX_BEGIN_NAMESPACE(std)
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...
375 for (size_t __i = 0; __i < money_base::_S_end; ++__i)
376 _M_data->_M_atoms[__i] =
377 static_cast<wchar_t>(money_base::_S_atoms[__i]);
382 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
383 __c_locale __old = __uselocale(__cloc);
385 // Switch to named locale so that mbsrtowcs will work.
386 char* __old = strdup(setlocale(LC_ALL, NULL));
387 setlocale(LC_ALL, __name);
390 union { char *__s; wchar_t __w; } __u;
391 __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
392 _M_data->_M_decimal_point = __u.__w;
394 __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
395 _M_data->_M_thousands_sep = __u.__w;
396 _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
397 _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
399 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
400 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
401 const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
403 wchar_t* __wcs_ps = 0;
404 wchar_t* __wcs_ns = 0;
405 const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
409 size_t __len = strlen(__cpossign);
413 memset(&__state, 0, sizeof(mbstate_t));
414 __wcs_ps = new wchar_t[__len];
415 mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
416 _M_data->_M_positive_sign = __wcs_ps;
419 _M_data->_M_positive_sign = L"";
420 _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
422 __len = strlen(__cnegsign);
424 _M_data->_M_negative_sign = L"()";
428 memset(&__state, 0, sizeof(mbstate_t));
429 __wcs_ns = new wchar_t[__len];
430 mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
431 _M_data->_M_negative_sign = __wcs_ns;
434 _M_data->_M_negative_sign = L"";
435 _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
438 __len = strlen(__ccurr);
442 memset(&__state, 0, sizeof(mbstate_t));
443 wchar_t* __wcs = new wchar_t[__len];
444 mbsrtowcs(__wcs, &__ccurr, __len, &__state);
445 _M_data->_M_curr_symbol = __wcs;
448 _M_data->_M_curr_symbol = L"";
449 _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
457 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
460 setlocale(LC_ALL, __old);
463 __throw_exception_again;
466 _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
468 char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
469 char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
470 char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
471 _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
473 char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
474 char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
475 _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
478 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
481 setlocale(LC_ALL, __old);
489 moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
490 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
497 _M_data = new __moneypunct_cache<wchar_t, false>;
502 _M_data->_M_decimal_point = L'.';
503 _M_data->_M_thousands_sep = L',';
504 _M_data->_M_grouping = "";
505 _M_data->_M_grouping_size = 0;
506 _M_data->_M_curr_symbol = L"";
507 _M_data->_M_curr_symbol_size = 0;
508 _M_data->_M_positive_sign = L"";
509 _M_data->_M_positive_sign_size = 0;
510 _M_data->_M_negative_sign = L"";
511 _M_data->_M_negative_sign_size = 0;
512 _M_data->_M_frac_digits = 0;
513 _M_data->_M_pos_format = money_base::_S_default_pattern;
514 _M_data->_M_neg_format = money_base::_S_default_pattern;
516 // Use ctype::widen code without the facet...
517 for (size_t __i = 0; __i < money_base::_S_end; ++__i)
518 _M_data->_M_atoms[__i] =
519 static_cast<wchar_t>(money_base::_S_atoms[__i]);
524 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
525 __c_locale __old = __uselocale(__cloc);
527 // Switch to named locale so that mbsrtowcs will work.
528 char* __old = strdup(setlocale(LC_ALL, NULL));
529 setlocale(LC_ALL, __name);
532 union { char *__s; wchar_t __w; } __u;
533 __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
534 _M_data->_M_decimal_point = __u.__w;
536 __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
537 _M_data->_M_thousands_sep = __u.__w;
538 _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
539 _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
541 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
542 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
543 const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
545 wchar_t* __wcs_ps = 0;
546 wchar_t* __wcs_ns = 0;
547 const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
552 __len = strlen(__cpossign);
556 memset(&__state, 0, sizeof(mbstate_t));
557 __wcs_ps = new wchar_t[__len];
558 mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
559 _M_data->_M_positive_sign = __wcs_ps;
562 _M_data->_M_positive_sign = L"";
563 _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
565 __len = strlen(__cnegsign);
567 _M_data->_M_negative_sign = L"()";
571 memset(&__state, 0, sizeof(mbstate_t));
572 __wcs_ns = new wchar_t[__len];
573 mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
574 _M_data->_M_negative_sign = __wcs_ns;
577 _M_data->_M_negative_sign = L"";
578 _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
581 __len = strlen(__ccurr);
585 memset(&__state, 0, sizeof(mbstate_t));
586 wchar_t* __wcs = new wchar_t[__len];
587 mbsrtowcs(__wcs, &__ccurr, __len, &__state);
588 _M_data->_M_curr_symbol = __wcs;
591 _M_data->_M_curr_symbol = L"";
592 _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
600 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
603 setlocale(LC_ALL, __old);
606 __throw_exception_again;
609 _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
610 char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
611 char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
612 char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
613 _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
615 char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
616 char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
617 _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
620 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
623 setlocale(LC_ALL, __old);
630 moneypunct<wchar_t, true>::~moneypunct()
632 if (_M_data->_M_positive_sign_size)
633 delete [] _M_data->_M_positive_sign;
634 if (_M_data->_M_negative_sign_size
635 && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
636 delete [] _M_data->_M_negative_sign;
637 if (_M_data->_M_curr_symbol_size)
638 delete [] _M_data->_M_curr_symbol;
643 moneypunct<wchar_t, false>::~moneypunct()
645 if (_M_data->_M_positive_sign_size)
646 delete [] _M_data->_M_positive_sign;
647 if (_M_data->_M_negative_sign_size
648 && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
649 delete [] _M_data->_M_negative_sign;
650 if (_M_data->_M_curr_symbol_size)
651 delete [] _M_data->_M_curr_symbol;
656 _GLIBCXX_END_NAMESPACE