1 // std::numpunct implementation details, GNU version -*- C++ -*- 2 3 // Copyright (C) 2001-2015 Free Software Foundation, Inc. 4 // 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) 9 // any later version. 10 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. 15 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. 19 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/>. 24 25 // 26 // ISO C++ 14882: 22.2.3.1.2 numpunct virtual functions 27 // 28 29 // Written by Benjamin Kosnik <bkoz@redhat.com> 30 31 #include <locale> 32 #include <bits/c++locale_internal.h> 33 34 namespace std _GLIBCXX_VISIBILITY(default) 35 { 36 _GLIBCXX_BEGIN_NAMESPACE_VERSION 37 38 template<> 39 void _M_initialize_numpunct(__c_locale __cloc)40 numpunct<char>::_M_initialize_numpunct(__c_locale __cloc) 41 { 42 if (!_M_data) 43 _M_data = new __numpunct_cache<char>; 44 45 if (!__cloc) 46 { 47 // "C" locale 48 _M_data->_M_grouping = ""; 49 _M_data->_M_grouping_size = 0; 50 _M_data->_M_use_grouping = false; 51 52 _M_data->_M_decimal_point = '.'; 53 _M_data->_M_thousands_sep = ','; 54 55 for (size_t __i = 0; __i < __num_base::_S_oend; ++__i) 56 _M_data->_M_atoms_out[__i] = __num_base::_S_atoms_out[__i]; 57 58 for (size_t __j = 0; __j < __num_base::_S_iend; ++__j) 59 _M_data->_M_atoms_in[__j] = __num_base::_S_atoms_in[__j]; 60 } 61 else 62 { 63 // Named locale. 64 _M_data->_M_decimal_point = *(__nl_langinfo_l(DECIMAL_POINT, 65 __cloc)); 66 _M_data->_M_thousands_sep = *(__nl_langinfo_l(THOUSANDS_SEP, 67 __cloc)); 68 69 // Check for NULL, which implies no grouping. 70 if (_M_data->_M_thousands_sep == '\0') 71 { 72 // Like in "C" locale. 73 _M_data->_M_grouping = ""; 74 _M_data->_M_grouping_size = 0; 75 _M_data->_M_use_grouping = false; 76 _M_data->_M_thousands_sep = ','; 77 } 78 else 79 { 80 const char* __src = __nl_langinfo_l(GROUPING, __cloc); 81 const size_t __len = strlen(__src); 82 if (__len) 83 { 84 __try 85 { 86 char* __dst = new char[__len + 1]; 87 memcpy(__dst, __src, __len + 1); 88 _M_data->_M_grouping = __dst; 89 } 90 __catch(...) 91 { 92 delete _M_data; 93 _M_data = 0; 94 __throw_exception_again; 95 } 96 } 97 else 98 { 99 _M_data->_M_grouping = ""; 100 _M_data->_M_use_grouping = false; 101 } 102 _M_data->_M_grouping_size = __len; 103 } 104 } 105 106 // NB: There is no way to extact this info from posix locales. 107 // _M_truename = __nl_langinfo_l(YESSTR, __cloc); 108 _M_data->_M_truename = "true"; 109 _M_data->_M_truename_size = 4; 110 // _M_falsename = __nl_langinfo_l(NOSTR, __cloc); 111 _M_data->_M_falsename = "false"; 112 _M_data->_M_falsename_size = 5; 113 } 114 115 template<> ~numpunct()116 numpunct<char>::~numpunct() 117 { 118 if (_M_data->_M_grouping_size) 119 delete [] _M_data->_M_grouping; 120 delete _M_data; 121 } 122 123 #ifdef _GLIBCXX_USE_WCHAR_T 124 template<> 125 void _M_initialize_numpunct(__c_locale __cloc)126 numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc) 127 { 128 if (!_M_data) 129 _M_data = new __numpunct_cache<wchar_t>; 130 131 if (!__cloc) 132 { 133 // "C" locale 134 _M_data->_M_grouping = ""; 135 _M_data->_M_grouping_size = 0; 136 _M_data->_M_use_grouping = false; 137 138 _M_data->_M_decimal_point = L'.'; 139 _M_data->_M_thousands_sep = L','; 140 141 // Use ctype::widen code without the facet... 142 for (size_t __i = 0; __i < __num_base::_S_oend; ++__i) 143 _M_data->_M_atoms_out[__i] = 144 static_cast<wchar_t>(__num_base::_S_atoms_out[__i]); 145 146 for (size_t __j = 0; __j < __num_base::_S_iend; ++__j) 147 _M_data->_M_atoms_in[__j] = 148 static_cast<wchar_t>(__num_base::_S_atoms_in[__j]); 149 } 150 else 151 { 152 // Named locale. 153 // NB: In the GNU model wchar_t is always 32 bit wide. 154 union { char *__s; wchar_t __w; } __u; 155 __u.__s = __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc); 156 _M_data->_M_decimal_point = __u.__w; 157 158 __u.__s = __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc); 159 _M_data->_M_thousands_sep = __u.__w; 160 161 // Check for NULL, which implies no grouping. 162 if (_M_data->_M_thousands_sep == L'\0') 163 { 164 // Like in "C" locale. 165 _M_data->_M_grouping = ""; 166 _M_data->_M_grouping_size = 0; 167 _M_data->_M_use_grouping = false; 168 _M_data->_M_thousands_sep = L','; 169 } 170 else 171 { 172 const char* __src = __nl_langinfo_l(GROUPING, __cloc); 173 const size_t __len = strlen(__src); 174 if (__len) 175 { 176 __try 177 { 178 char* __dst = new char[__len + 1]; 179 memcpy(__dst, __src, __len + 1); 180 _M_data->_M_grouping = __dst; 181 } 182 __catch(...) 183 { 184 delete _M_data; 185 _M_data = 0; 186 __throw_exception_again; 187 } 188 } 189 else 190 { 191 _M_data->_M_grouping = ""; 192 _M_data->_M_use_grouping = false; 193 } 194 _M_data->_M_grouping_size = __len; 195 } 196 } 197 198 // NB: There is no way to extact this info from posix locales. 199 // _M_truename = __nl_langinfo_l(YESSTR, __cloc); 200 _M_data->_M_truename = L"true"; 201 _M_data->_M_truename_size = 4; 202 // _M_falsename = __nl_langinfo_l(NOSTR, __cloc); 203 _M_data->_M_falsename = L"false"; 204 _M_data->_M_falsename_size = 5; 205 } 206 207 template<> ~numpunct()208 numpunct<wchar_t>::~numpunct() 209 { 210 if (_M_data->_M_grouping_size) 211 delete [] _M_data->_M_grouping; 212 delete _M_data; 213 } 214 #endif 215 216 _GLIBCXX_END_NAMESPACE_VERSION 217 } // namespace 218