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