1 // std::moneypunct implementation details, DragonFly version -*- C++ -*-
3 // Copyright (C) 2015 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 3, 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 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
26 // ISO C++ 14882: 22.2.6.3.2 moneypunct virtual functions
29 // Written by Benjamin Kosnik <bkoz@redhat.com>
30 // Modified for DragonFly by John Marino <gnugcc@marino.st>
36 namespace std _GLIBCXX_VISIBILITY(default)
38 _GLIBCXX_BEGIN_NAMESPACE_VERSION
40 // This file might be compiled twice, but we only want to define the members
41 // of money_base once.
42 #if ! _GLIBCXX_USE_CXX11_ABI
44 // Construct and return valid pattern consisting of some combination of:
45 // space none symbol sign value
47 money_base::_S_construct_pattern(char __precedes, char __space,
52 // This insanely complicated routine attempts to construct a valid
53 // pattern for use with moneypunct. A couple of invariants:
55 // if (__precedes) symbol -> value
56 // else value -> symbol
61 // none == never first
62 // space never first or last
64 // Any elegant implementations of this are welcome.
69 // 1 The sign precedes the value and symbol.
70 __ret.field[0] = sign;
73 // Pattern starts with sign.
76 __ret.field[1] = symbol;
77 __ret.field[3] = value;
81 __ret.field[1] = value;
82 __ret.field[3] = symbol;
84 __ret.field[2] = space;
88 // Pattern starts with sign and ends with none.
91 __ret.field[1] = symbol;
92 __ret.field[2] = value;
96 __ret.field[1] = value;
97 __ret.field[2] = symbol;
99 __ret.field[3] = none;
103 // 2 The sign follows the value and symbol.
106 // Pattern either ends with sign.
109 __ret.field[0] = symbol;
110 __ret.field[2] = value;
114 __ret.field[0] = value;
115 __ret.field[2] = symbol;
117 __ret.field[1] = space;
118 __ret.field[3] = sign;
122 // Pattern ends with sign then none.
125 __ret.field[0] = symbol;
126 __ret.field[1] = value;
130 __ret.field[0] = value;
131 __ret.field[1] = symbol;
133 __ret.field[2] = sign;
134 __ret.field[3] = none;
138 // 3 The sign immediately precedes the symbol.
141 __ret.field[0] = sign;
142 __ret.field[1] = symbol;
145 __ret.field[2] = space;
146 __ret.field[3] = value;
150 __ret.field[2] = value;
151 __ret.field[3] = none;
156 __ret.field[0] = value;
159 __ret.field[1] = space;
160 __ret.field[2] = sign;
161 __ret.field[3] = symbol;
165 __ret.field[1] = sign;
166 __ret.field[2] = symbol;
167 __ret.field[3] = none;
172 // 4 The sign immediately follows the symbol.
175 __ret.field[0] = symbol;
176 __ret.field[1] = sign;
179 __ret.field[2] = space;
180 __ret.field[3] = value;
184 __ret.field[2] = value;
185 __ret.field[3] = none;
190 __ret.field[0] = value;
193 __ret.field[1] = space;
194 __ret.field[2] = symbol;
195 __ret.field[3] = sign;
199 __ret.field[1] = symbol;
200 __ret.field[2] = sign;
201 __ret.field[3] = none;
214 moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc,
218 _M_data = new __moneypunct_cache<char, true>;
223 _M_data->_M_decimal_point = '.';
224 _M_data->_M_thousands_sep = ',';
225 _M_data->_M_grouping = "";
226 _M_data->_M_grouping_size = 0;
227 _M_data->_M_use_grouping = false;
228 _M_data->_M_curr_symbol = "";
229 _M_data->_M_curr_symbol_size = 0;
230 _M_data->_M_positive_sign = "";
231 _M_data->_M_positive_sign_size = 0;
232 _M_data->_M_negative_sign = "";
233 _M_data->_M_negative_sign_size = 0;
234 _M_data->_M_frac_digits = 0;
235 _M_data->_M_pos_format = money_base::_S_default_pattern;
236 _M_data->_M_neg_format = money_base::_S_default_pattern;
238 for (size_t __i = 0; __i < money_base::_S_end; ++__i)
239 _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
244 lconv* lc = localeconv_l((locale_t) __cloc);
246 // Check for NULL, which implies no fractional digits.
247 if (lc->mon_decimal_point == NULL ||
248 lc->mon_decimal_point[0] == '\0')
250 // Like in "C" locale.
251 _M_data->_M_frac_digits = 0;
252 _M_data->_M_decimal_point = '.';
256 _M_data->_M_decimal_point = lc->mon_decimal_point[0];
257 _M_data->_M_frac_digits = lc->int_frac_digits;
260 const char* __cgroup = lc->mon_grouping;
261 const char* __cpossign = lc->positive_sign;
262 const char* __cnegsign = lc->negative_sign;
264 const char* __ccurr = lc->int_curr_symbol;
269 const char __nposn = lc->int_n_sign_posn;
274 // Check for NULL, which implies no grouping.
275 if (lc->mon_thousands_sep == NULL ||
276 lc->mon_thousands_sep[0] == '\0')
278 // Like in "C" locale.
279 _M_data->_M_grouping = "";
280 _M_data->_M_grouping_size = 0;
281 _M_data->_M_use_grouping = false;
282 _M_data->_M_thousands_sep = ',';
286 _M_data->_M_thousands_sep = lc->mon_thousands_sep[0];
288 __len = strlen(__cgroup);
291 __group = new char[__len + 1];
292 memcpy(__group, __cgroup, __len + 1);
293 _M_data->_M_grouping = __group;
297 _M_data->_M_grouping = "";
298 _M_data->_M_use_grouping = false;
300 _M_data->_M_grouping_size = __len;
303 __len = strlen(__cpossign);
306 __ps = new char[__len + 1];
307 memcpy(__ps, __cpossign, __len + 1);
308 _M_data->_M_positive_sign = __ps;
311 _M_data->_M_positive_sign = "";
312 _M_data->_M_positive_sign_size = __len;
316 _M_data->_M_negative_sign = "()";
317 _M_data->_M_negative_sign_size = 2;
321 __len = strlen(__cnegsign);
324 __ns = new char[__len + 1];
325 memcpy(__ns, __cnegsign, __len + 1);
326 _M_data->_M_negative_sign = __ns;
329 _M_data->_M_negative_sign = "";
330 _M_data->_M_negative_sign_size = __len;
333 __len = strlen(__ccurr);
336 char* __curr = new char[__len + 1];
337 memcpy(__curr, __ccurr, __len + 1);
338 _M_data->_M_curr_symbol = __curr;
341 _M_data->_M_curr_symbol = "";
342 _M_data->_M_curr_symbol_size = __len;
351 __throw_exception_again;
354 char __pprecedes = lc->int_p_cs_precedes;
355 char __pspace = lc->int_p_sep_by_space;
356 char __pposn = lc->int_p_sign_posn;
357 _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
359 char __nprecedes = lc->int_n_cs_precedes;
360 char __nspace = lc->int_n_sep_by_space;
361 _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
368 moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc,
372 _M_data = new __moneypunct_cache<char, false>;
377 _M_data->_M_decimal_point = '.';
378 _M_data->_M_thousands_sep = ',';
379 _M_data->_M_grouping = "";
380 _M_data->_M_grouping_size = 0;
381 _M_data->_M_use_grouping = false;
382 _M_data->_M_curr_symbol = "";
383 _M_data->_M_curr_symbol_size = 0;
384 _M_data->_M_positive_sign = "";
385 _M_data->_M_positive_sign_size = 0;
386 _M_data->_M_negative_sign = "";
387 _M_data->_M_negative_sign_size = 0;
388 _M_data->_M_frac_digits = 0;
389 _M_data->_M_pos_format = money_base::_S_default_pattern;
390 _M_data->_M_neg_format = money_base::_S_default_pattern;
392 for (size_t __i = 0; __i < money_base::_S_end; ++__i)
393 _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
398 lconv* lc = localeconv_l((locale_t) __cloc);
400 // Check for NULL, which implies no fractional digits.
401 if (lc->mon_decimal_point == NULL ||
402 lc->mon_decimal_point[0] == '\0')
404 // Like in "C" locale.
405 _M_data->_M_frac_digits = 0;
406 _M_data->_M_decimal_point = '.';
410 _M_data->_M_decimal_point = lc->mon_decimal_point[0];
411 _M_data->_M_frac_digits = lc->frac_digits;
414 const char* __cgroup = lc->mon_grouping;
415 const char* __cpossign = lc->positive_sign;
416 const char* __cnegsign = lc->negative_sign;
418 const char* __ccurr = lc->currency_symbol;
423 const char __nposn = lc->n_sign_posn;
428 // Check for NULL, which implies no grouping.
429 if (lc->mon_thousands_sep == NULL ||
430 lc->mon_thousands_sep[0] == '\0')
432 // Like in "C" locale.
433 _M_data->_M_grouping = "";
434 _M_data->_M_grouping_size = 0;
435 _M_data->_M_use_grouping = false;
436 _M_data->_M_thousands_sep = ',';
440 _M_data->_M_thousands_sep = lc->mon_thousands_sep[0];
442 __len = strlen(__cgroup);
445 __group = new char[__len + 1];
446 memcpy(__group, __cgroup, __len + 1);
447 _M_data->_M_grouping = __group;
451 _M_data->_M_grouping = "";
452 _M_data->_M_use_grouping = false;
454 _M_data->_M_grouping_size = __len;
457 __len = strlen(__cpossign);
460 __ps = new char[__len + 1];
461 memcpy(__ps, __cpossign, __len + 1);
462 _M_data->_M_positive_sign = __ps;
465 _M_data->_M_positive_sign = "";
466 _M_data->_M_positive_sign_size = __len;
470 _M_data->_M_negative_sign = "()";
471 _M_data->_M_negative_sign_size = 2;
475 __len = strlen(__cnegsign);
478 __ns = new char[__len + 1];
479 memcpy(__ns, __cnegsign, __len + 1);
480 _M_data->_M_negative_sign = __ns;
483 _M_data->_M_negative_sign = "";
484 _M_data->_M_negative_sign_size = __len;
487 __len = strlen(__ccurr);
490 char* __curr = new char[__len + 1];
491 memcpy(__curr, __ccurr, __len + 1);
492 _M_data->_M_curr_symbol = __curr;
495 _M_data->_M_curr_symbol = "";
496 _M_data->_M_curr_symbol_size = __len;
505 __throw_exception_again;
508 char __pprecedes = lc->p_cs_precedes;
509 char __pspace = lc->p_sep_by_space;
510 char __pposn = lc->p_sign_posn;
511 _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
513 char __nprecedes = lc->n_cs_precedes;
514 char __nspace = lc->n_sep_by_space;
515 _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
521 moneypunct<char, true>::~moneypunct()
523 if (_M_data->_M_grouping_size)
524 delete [] _M_data->_M_grouping;
525 if (_M_data->_M_positive_sign_size)
526 delete [] _M_data->_M_positive_sign;
527 if (_M_data->_M_negative_sign_size
528 && strcmp(_M_data->_M_negative_sign, "()") != 0)
529 delete [] _M_data->_M_negative_sign;
530 if (_M_data->_M_curr_symbol_size)
531 delete [] _M_data->_M_curr_symbol;
536 moneypunct<char, false>::~moneypunct()
538 if (_M_data->_M_grouping_size)
539 delete [] _M_data->_M_grouping;
540 if (_M_data->_M_positive_sign_size)
541 delete [] _M_data->_M_positive_sign;
542 if (_M_data->_M_negative_sign_size
543 && strcmp(_M_data->_M_negative_sign, "()") != 0)
544 delete [] _M_data->_M_negative_sign;
545 if (_M_data->_M_curr_symbol_size)
546 delete [] _M_data->_M_curr_symbol;
550 #ifdef _GLIBCXX_USE_WCHAR_T
553 moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc,
557 _M_data = new __moneypunct_cache<wchar_t, true>;
562 _M_data->_M_decimal_point = L'.';
563 _M_data->_M_thousands_sep = L',';
564 _M_data->_M_grouping = "";
565 _M_data->_M_grouping_size = 0;
566 _M_data->_M_use_grouping = false;
567 _M_data->_M_curr_symbol = L"";
568 _M_data->_M_curr_symbol_size = 0;
569 _M_data->_M_positive_sign = L"";
570 _M_data->_M_positive_sign_size = 0;
571 _M_data->_M_negative_sign = L"";
572 _M_data->_M_negative_sign_size = 0;
573 _M_data->_M_frac_digits = 0;
574 _M_data->_M_pos_format = money_base::_S_default_pattern;
575 _M_data->_M_neg_format = money_base::_S_default_pattern;
577 // Use ctype::widen code without the facet...
578 for (size_t __i = 0; __i < money_base::_S_end; ++__i)
579 _M_data->_M_atoms[__i] =
580 static_cast<wchar_t>(money_base::_S_atoms[__i]);
584 __c_locale __old = (__c_locale)uselocale((locale_t)__cloc);
586 lconv* lc = localeconv_l((locale_t) __cloc);
588 // Check for NULL, which implies no fractional digits.
589 if (lc->mon_decimal_point == NULL ||
590 lc->mon_decimal_point[0] == '\0')
592 // Like in "C" locale.
593 _M_data->_M_frac_digits = 0;
594 _M_data->_M_decimal_point = L'.';
598 _M_data->_M_frac_digits = lc->int_frac_digits;
599 _M_data->_M_decimal_point = (wchar_t)lc->mon_decimal_point[0];
602 const char* __cgroup = lc->mon_grouping;
603 const char* __cpossign = lc->positive_sign;
604 const char* __cnegsign = lc->negative_sign;
605 const char* __ccurr = lc->int_curr_symbol;
608 wchar_t* __wcs_ps = 0;
609 wchar_t* __wcs_ns = 0;
610 const char __nposn = lc->int_n_sign_posn;
615 // Check for NULL, which implies no grouping.
616 if (lc->mon_thousands_sep == NULL ||
617 lc->mon_thousands_sep[0] == '\0')
619 // Like in "C" locale.
620 _M_data->_M_grouping = "";
621 _M_data->_M_grouping_size = 0;
622 _M_data->_M_use_grouping = false;
623 _M_data->_M_thousands_sep = L',';
627 _M_data->_M_thousands_sep =
628 (wchar_t)lc->mon_thousands_sep[0];
629 __len = strlen(__cgroup);
632 __group = new char[__len + 1];
633 memcpy(__group, __cgroup, __len + 1);
634 _M_data->_M_grouping = __group;
638 _M_data->_M_grouping = "";
639 _M_data->_M_use_grouping = false;
641 _M_data->_M_grouping_size = __len;
645 __len = strlen(__cpossign);
648 memset(&__state, 0, sizeof(mbstate_t));
649 __wcs_ps = new wchar_t[__len + 1];
650 mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state);
651 _M_data->_M_positive_sign = __wcs_ps;
654 _M_data->_M_positive_sign = L"";
655 _M_data->_M_positive_sign_size =
656 wcslen(_M_data->_M_positive_sign);
658 __len = strlen(__cnegsign);
660 _M_data->_M_negative_sign = L"()";
663 memset(&__state, 0, sizeof(mbstate_t));
664 __wcs_ns = new wchar_t[__len + 1];
665 mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state);
666 _M_data->_M_negative_sign = __wcs_ns;
669 _M_data->_M_negative_sign = L"";
670 _M_data->_M_negative_sign_size =
671 wcslen(_M_data->_M_negative_sign);
674 __len = strlen(__ccurr);
677 memset(&__state, 0, sizeof(mbstate_t));
678 wchar_t* __wcs = new wchar_t[__len + 1];
679 mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state);
680 _M_data->_M_curr_symbol = __wcs;
683 _M_data->_M_curr_symbol = L"";
684 _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
693 uselocale((locale_t)__old);
694 __throw_exception_again;
697 char __pprecedes = lc->int_p_cs_precedes;
698 char __pspace = lc->int_p_sep_by_space;
699 char __pposn = lc->int_p_sign_posn;
700 _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
702 char __nprecedes = lc->int_n_cs_precedes;
703 char __nspace = lc->int_n_sep_by_space;
704 _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
707 uselocale((locale_t)__old);
713 moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
717 _M_data = new __moneypunct_cache<wchar_t, false>;
722 _M_data->_M_decimal_point = L'.';
723 _M_data->_M_thousands_sep = L',';
724 _M_data->_M_grouping = "";
725 _M_data->_M_grouping_size = 0;
726 _M_data->_M_use_grouping = false;
727 _M_data->_M_curr_symbol = L"";
728 _M_data->_M_curr_symbol_size = 0;
729 _M_data->_M_positive_sign = L"";
730 _M_data->_M_positive_sign_size = 0;
731 _M_data->_M_negative_sign = L"";
732 _M_data->_M_negative_sign_size = 0;
733 _M_data->_M_frac_digits = 0;
734 _M_data->_M_pos_format = money_base::_S_default_pattern;
735 _M_data->_M_neg_format = money_base::_S_default_pattern;
737 // Use ctype::widen code without the facet...
738 for (size_t __i = 0; __i < money_base::_S_end; ++__i)
739 _M_data->_M_atoms[__i] =
740 static_cast<wchar_t>(money_base::_S_atoms[__i]);
744 __c_locale __old = (__c_locale)uselocale((locale_t)__cloc);
746 lconv* lc = localeconv_l((locale_t) __cloc);
748 // Check for NULL, which implies no fractional digits.
749 if (lc->mon_decimal_point == NULL ||
750 lc->mon_decimal_point[0] == '\0')
752 // Like in "C" locale.
753 _M_data->_M_frac_digits = 0;
754 _M_data->_M_decimal_point = L'.';
758 _M_data->_M_frac_digits = lc->frac_digits;
759 _M_data->_M_decimal_point = (wchar_t)lc->mon_decimal_point[0];
762 const char* __cgroup = lc->mon_grouping;
763 const char* __cpossign = lc->positive_sign;
764 const char* __cnegsign = lc->negative_sign;
765 const char* __ccurr = lc->currency_symbol;
768 wchar_t* __wcs_ps = 0;
769 wchar_t* __wcs_ns = 0;
770 const char __nposn = lc->n_sign_posn;
775 // Check for NULL, which implies no grouping.
776 if (lc->mon_thousands_sep == NULL ||
777 lc->mon_thousands_sep[0] == '\0')
779 // Like in "C" locale.
780 _M_data->_M_grouping = "";
781 _M_data->_M_grouping_size = 0;
782 _M_data->_M_use_grouping = false;
783 _M_data->_M_thousands_sep = L',';
787 _M_data->_M_thousands_sep =
788 (wchar_t)lc->mon_thousands_sep[0];
789 __len = strlen(__cgroup);
792 __group = new char[__len + 1];
793 memcpy(__group, __cgroup, __len + 1);
794 _M_data->_M_grouping = __group;
798 _M_data->_M_grouping = "";
799 _M_data->_M_use_grouping = false;
801 _M_data->_M_grouping_size = __len;
805 __len = strlen(__cpossign);
808 memset(&__state, 0, sizeof(mbstate_t));
809 __wcs_ps = new wchar_t[__len + 1];
810 mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state);
811 _M_data->_M_positive_sign = __wcs_ps;
814 _M_data->_M_positive_sign = L"";
815 _M_data->_M_positive_sign_size =
816 wcslen(_M_data->_M_positive_sign);
818 __len = strlen(__cnegsign);
820 _M_data->_M_negative_sign = L"()";
823 memset(&__state, 0, sizeof(mbstate_t));
824 __wcs_ns = new wchar_t[__len + 1];
825 mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state);
826 _M_data->_M_negative_sign = __wcs_ns;
829 _M_data->_M_negative_sign = L"";
830 _M_data->_M_negative_sign_size =
831 wcslen(_M_data->_M_negative_sign);
834 __len = strlen(__ccurr);
837 memset(&__state, 0, sizeof(mbstate_t));
838 wchar_t* __wcs = new wchar_t[__len + 1];
839 mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state);
840 _M_data->_M_curr_symbol = __wcs;
843 _M_data->_M_curr_symbol = L"";
844 _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
853 uselocale((locale_t)__old);
854 __throw_exception_again;
857 char __pprecedes = lc->p_cs_precedes;
858 char __pspace = lc->p_sep_by_space;
859 char __pposn = lc->p_sign_posn;
860 _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
862 char __nprecedes = lc->n_cs_precedes;
863 char __nspace = lc->n_sep_by_space;
864 _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
867 uselocale((locale_t)__old);
872 moneypunct<wchar_t, true>::~moneypunct()
874 if (_M_data->_M_grouping_size)
875 delete [] _M_data->_M_grouping;
876 if (_M_data->_M_positive_sign_size)
877 delete [] _M_data->_M_positive_sign;
878 if (_M_data->_M_negative_sign_size
879 && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
880 delete [] _M_data->_M_negative_sign;
881 if (_M_data->_M_curr_symbol_size)
882 delete [] _M_data->_M_curr_symbol;
887 moneypunct<wchar_t, false>::~moneypunct()
889 if (_M_data->_M_grouping_size)
890 delete [] _M_data->_M_grouping;
891 if (_M_data->_M_positive_sign_size)
892 delete [] _M_data->_M_positive_sign;
893 if (_M_data->_M_negative_sign_size
894 && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
895 delete [] _M_data->_M_negative_sign;
896 if (_M_data->_M_curr_symbol_size)
897 delete [] _M_data->_M_curr_symbol;
902 _GLIBCXX_END_NAMESPACE_VERSION