Home | History | Annotate | Line # | Download | only in dragonfly
      1 // std::numpunct implementation details, DragonFly version -*- C++ -*-
      2 
      3 // Copyright (C) 2015-2022 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 (at) redhat.com>
     30 // Modified for DragonFly by John Marino <gnugcc (at) marino.st>
     31 
     32 #include <locale>
     33 #include <cstring>
     34 
     35 #include "xlocale_port.h"
     36 
     37 namespace std _GLIBCXX_VISIBILITY(default)
     38 {
     39 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     40 
     41   template<>
     42     void
     43     numpunct<char>::_M_initialize_numpunct(__c_locale __cloc)
     44     {
     45       if (!_M_data)
     46 	_M_data = new __numpunct_cache<char>;
     47 
     48       if (!__cloc)
     49 	{
     50 	  // "C" locale
     51 	  _M_data->_M_grouping = "";
     52 	  _M_data->_M_grouping_size = 0;
     53 	  _M_data->_M_use_grouping = false;
     54 
     55 	  _M_data->_M_decimal_point = '.';
     56 	  _M_data->_M_thousands_sep = ',';
     57 
     58 	  for (size_t __i = 0; __i < __num_base::_S_oend; ++__i)
     59 	    _M_data->_M_atoms_out[__i] = __num_base::_S_atoms_out[__i];
     60 
     61 	  for (size_t __j = 0; __j < __num_base::_S_iend; ++__j)
     62 	    _M_data->_M_atoms_in[__j] = __num_base::_S_atoms_in[__j];
     63 	}
     64       else
     65 	{
     66 	  // Named locale.
     67 	  lconv* lc = localeconv_l((locale_t) __cloc);
     68 
     69 	  // Decimal point should always be defined, but check null anyway
     70 	  if (lc->decimal_point == NULL)
     71 	    {
     72 	      // Not defined, so use "C" locale default
     73 	      _M_data->_M_decimal_point = '.';
     74 	    }
     75 	  else
     76 	    {
     77 	      _M_data->_M_decimal_point = lc->decimal_point[0];
     78 	    }
     79 	  // Check for NULL, which implies no grouping.
     80 	  if (lc->thousands_sep == NULL || lc->thousands_sep[0] == '\0')
     81 	    {
     82 	      // Like in "C" locale.
     83 	      _M_data->_M_grouping = "";
     84 	      _M_data->_M_grouping_size = 0;
     85 	      _M_data->_M_use_grouping = false;
     86 	      _M_data->_M_thousands_sep = ',';
     87 	    }
     88 	  else
     89 	    {
     90 	      _M_data->_M_thousands_sep = lc->thousands_sep[0];
     91 
     92 	      const char* __src = lc->grouping;
     93 	      const size_t __len = strlen(__src);
     94 	      if (__len)
     95 		{
     96 		  __try
     97 		    {
     98 		      char* __dst = new char[__len + 1];
     99 		      memcpy(__dst, __src, __len + 1);
    100 		      _M_data->_M_grouping = __dst;
    101 		      _M_data->_M_use_grouping = true;
    102 		    }
    103 		  __catch(...)
    104 		    {
    105 		      delete _M_data;
    106 		      _M_data = 0;
    107 		      __throw_exception_again;
    108 		    }
    109 		}
    110 	      else
    111 		{
    112 		  _M_data->_M_grouping = "";
    113 		  _M_data->_M_use_grouping = false;
    114 		}
    115 	      _M_data->_M_grouping_size = __len;
    116 	    }
    117 	}
    118 
    119       // NB: There is no way to extact this info from posix locales.
    120       // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
    121       _M_data->_M_truename = "true";
    122       _M_data->_M_truename_size = 4;
    123       // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
    124       _M_data->_M_falsename = "false";
    125       _M_data->_M_falsename_size = 5;
    126     }
    127 
    128   template<>
    129     numpunct<char>::~numpunct()
    130     {
    131       if (_M_data->_M_grouping_size)
    132 	delete [] _M_data->_M_grouping;
    133       delete _M_data;
    134     }
    135 
    136 #ifdef _GLIBCXX_USE_WCHAR_T
    137   template<>
    138     void
    139     numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc)
    140     {
    141       if (!_M_data)
    142 	_M_data = new __numpunct_cache<wchar_t>;
    143 
    144       if (!__cloc)
    145 	{
    146 	  // "C" locale
    147 	  _M_data->_M_grouping = "";
    148 	  _M_data->_M_grouping_size = 0;
    149 	  _M_data->_M_use_grouping = false;
    150 
    151 	  _M_data->_M_decimal_point = L'.';
    152 	  _M_data->_M_thousands_sep = L',';
    153 
    154 	  // Use ctype::widen code without the facet...
    155 	  for (size_t __i = 0; __i < __num_base::_S_oend; ++__i)
    156 	    _M_data->_M_atoms_out[__i] =
    157 	      static_cast<wchar_t>(__num_base::_S_atoms_out[__i]);
    158 
    159 	  for (size_t __j = 0; __j < __num_base::_S_iend; ++__j)
    160 	    _M_data->_M_atoms_in[__j] =
    161 	      static_cast<wchar_t>(__num_base::_S_atoms_in[__j]);
    162 	}
    163       else
    164 	{
    165 	  // Named locale.
    166 	  lconv* lc = localeconv_l((locale_t) __cloc);
    167 
    168 	  // Decimal point should always be defined, but check null anyway
    169 	  if (lc->decimal_point == NULL)
    170 	    {
    171 	      // Not defined, so use "C" locale default
    172 	      _M_data->_M_decimal_point = L'.';
    173 	    }
    174 	  else
    175 	    {
    176 	      _M_data->_M_decimal_point = (wchar_t)lc->decimal_point[0];
    177 	    }
    178 	  // Check for NULL, which implies no grouping.
    179 	  if (lc->thousands_sep == NULL || lc->thousands_sep[0] == '\0')
    180 	    {
    181 	      // Like in "C" locale.
    182 	      _M_data->_M_grouping = "";
    183 	      _M_data->_M_grouping_size = 0;
    184 	      _M_data->_M_use_grouping = false;
    185 	      _M_data->_M_thousands_sep = L',';
    186 	    }
    187 	  else
    188 	    {
    189 	      _M_data->_M_thousands_sep = (wchar_t)lc->thousands_sep[0];
    190 
    191   	      const char* __src = lc->grouping;
    192 	      const size_t __len = strlen(__src);
    193 	      if (__len)
    194 		{
    195 		  __try
    196 		    {
    197 		      char* __dst = new char[__len + 1];
    198 		      memcpy(__dst, __src, __len + 1);
    199 		      _M_data->_M_grouping = __dst;
    200 		    }
    201 		  __catch(...)
    202 		    {
    203 		      delete _M_data;
    204 		      _M_data = 0;
    205 		      __throw_exception_again;
    206 		    }
    207 		}
    208 	      else
    209 		{
    210 		  _M_data->_M_grouping = "";
    211 		  _M_data->_M_use_grouping = false;
    212 		}
    213 	      _M_data->_M_grouping_size = __len;
    214 	    }
    215 	}
    216 
    217       // NB: There is no way to extact this info from posix locales.
    218       // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
    219       _M_data->_M_truename = L"true";
    220       _M_data->_M_truename_size = 4;
    221       // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
    222       _M_data->_M_falsename = L"false";
    223       _M_data->_M_falsename_size = 5;
    224     }
    225 
    226   template<>
    227     numpunct<wchar_t>::~numpunct()
    228     {
    229       if (_M_data->_M_grouping_size)
    230 	delete [] _M_data->_M_grouping;
    231       delete _M_data;
    232     }
    233  #endif
    234 
    235 _GLIBCXX_END_NAMESPACE_VERSION
    236 } // namespace
    237