monetary_members.cc revision 97403
1// std::moneypunct implementation details, GNU version -*- C++ -*-
2
3// Copyright (C) 2001, 2002 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 2, 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// 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19// USA.
20
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.
29
30//
31// ISO C++ 14882: 22.2.6.3.2  moneypunct virtual functions
32//
33
34// Written by Benjamin Kosnik <bkoz@redhat.com>
35
36#include <locale>
37
38namespace std
39{
40  // Construct and return valid pattern consisting of some combination of:
41  // space none symbol sign value
42  money_base::pattern
43  money_base::_S_construct_pattern(char __precedes, char __space, char __posn)
44  {
45    pattern __ret;
46
47    // This insanely complicated routine attempts to construct a valid
48    // pattern for use with monyepunct. A couple of invariants:
49
50    // if (__precedes) symbol -> value
51    // else value -> symbol
52
53    // if (__space) space
54    // else none
55
56    // none == never first
57    // space never first or last
58
59    // Any elegant implementations of this are welcome.
60    switch (__posn)
61      {
62      case 0:
63      case 1:
64	// 1 The sign precedes the value and symbol.
65	if (__space)
66	  {
67	    // Pattern starts with sign.
68	    if (__precedes)
69	      {
70		__ret.field[1] = symbol;
71		__ret.field[2] = space;
72		__ret.field[3] = value;
73	      }
74	    else
75	      {
76		__ret.field[1] = value;
77		__ret.field[2] = space;
78		__ret.field[3] = symbol;
79	      }
80	    __ret.field[0] = sign;
81	  }
82	else
83	  {
84	    // Pattern starts with sign and ends with none.
85	    if (__precedes)
86	      {
87		__ret.field[1] = symbol;
88		__ret.field[2] = value;
89	      }
90	    else
91	      {
92		__ret.field[1] = value;
93		__ret.field[2] = symbol;
94	      }
95	    __ret.field[0] = sign;
96	    __ret.field[3] = none;
97	  }
98	break;
99      case 2:
100	// 2 The sign follows the value and symbol.
101	if (__space)
102	  {
103	    // Pattern either ends with sign.
104	    if (__precedes)
105	      {
106		__ret.field[0] = symbol;
107		__ret.field[1] = space;
108		__ret.field[2] = value;
109	      }
110	    else
111	      {
112		__ret.field[0] = value;
113		__ret.field[1] = space;
114		__ret.field[2] = symbol;
115	      }
116	    __ret.field[3] = sign;
117	  }
118	else
119	  {
120	    // Pattern ends with sign then none.
121	    if (__precedes)
122	      {
123		__ret.field[0] = symbol;
124		__ret.field[1] = value;
125	      }
126	    else
127	      {
128		__ret.field[0] = value;
129		__ret.field[1] = symbol;
130	      }
131	    __ret.field[2] = sign;
132	    __ret.field[3] = none;
133	  }
134	break;
135      case 3:
136	// 3 The sign immediately precedes the symbol.
137	if (__space)
138	  {
139	    // Have space.
140	    if (__precedes)
141	      {
142		__ret.field[0] = sign;
143		__ret.field[1] = symbol;
144		__ret.field[2] = space;
145		__ret.field[3] = value;
146	      }
147	    else
148	      {
149		__ret.field[0] = value;
150		__ret.field[1] = space;
151		__ret.field[2] = sign;
152		__ret.field[3] = symbol;
153	      }
154	  }
155	else
156	  {
157	    // Have none.
158	    if (__precedes)
159	      {
160		__ret.field[0] = sign;
161		__ret.field[1] = symbol;
162		__ret.field[2] = value;
163	      }
164	    else
165	      {
166		__ret.field[0] = value;
167		__ret.field[1] = sign;
168		__ret.field[2] = symbol;
169	      }
170	    __ret.field[3] = none;
171	  }
172	break;
173      case 4:
174	// 4 The sign immediately follows the symbol.
175	if (__space)
176	  {
177	    // Have space.
178	    if (__precedes)
179	      {
180		__ret.field[0] = symbol;
181		__ret.field[1] = sign;
182		__ret.field[2] = space;
183		__ret.field[3] = value;
184	      }
185	    else
186	      {
187		__ret.field[0] = value;
188		__ret.field[1] = space;
189		__ret.field[2] = symbol;
190		__ret.field[3] = sign;
191	      }
192	  }
193	else
194	  {
195	    // Have none.
196	    if (__precedes)
197	      {
198		__ret.field[0] = symbol;
199		__ret.field[1] = sign;
200		__ret.field[2] = value;
201	      }
202	    else
203	      {
204		__ret.field[0] = value;
205		__ret.field[1] = symbol;
206		__ret.field[2] = sign;
207	      }
208	    __ret.field[3] = none;
209	  }
210	break;
211      default:
212	;
213      }
214    return __ret;
215  }
216
217  template<>
218    void
219    moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc)
220    {
221      if (__cloc == _S_c_locale)
222	{
223	  // "C" locale
224	  _M_decimal_point = '.';
225	  _M_thousands_sep = ',';
226	  _M_grouping = "";
227	  _M_curr_symbol = "";
228	  _M_positive_sign = "";
229	  _M_negative_sign = "";
230	  _M_frac_digits = 0;
231	  _M_pos_format = money_base::_S_default_pattern;
232	  _M_neg_format = money_base::_S_default_pattern;
233	}
234      else
235	{
236	  // Named locale.
237	  _M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, __cloc));
238	  _M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, __cloc));
239	  _M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
240	  _M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
241
242	  char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
243	  if (!__nposn)
244	    _M_negative_sign = "()";
245	  else
246	    _M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
247
248	  // _Intl == true
249	  _M_curr_symbol = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
250	  _M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc));
251	  char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
252	  char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
253	  char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
254	  _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn);
255	  char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
256	  char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
257	  _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn);
258	}
259    }
260
261  template<>
262    void
263    moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc)
264    {
265      if (__cloc == _S_c_locale)
266	{
267	  // "C" locale
268	  _M_decimal_point = '.';
269	  _M_thousands_sep = ',';
270	  _M_grouping = "";
271	  _M_curr_symbol = "";
272	  _M_positive_sign = "";
273	  _M_negative_sign = "";
274	  _M_frac_digits = 0;
275	  _M_pos_format = money_base::_S_default_pattern;
276	  _M_neg_format = money_base::_S_default_pattern;
277	}
278      else
279	{
280	  // Named locale.
281	  _M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, __cloc));
282	  _M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, __cloc));
283	  _M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
284	  _M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
285
286	  char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
287	  if (!__nposn)
288	    _M_negative_sign = "()";
289	  else
290	    _M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
291
292	  // _Intl == false
293	  _M_curr_symbol = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
294	  _M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
295	  char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
296	  char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
297	  char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
298	  _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn);
299	  char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
300	  char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
301	  _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn);
302	}
303    }
304
305  template<>
306    moneypunct<char, true>::~moneypunct()
307    { }
308
309  template<>
310    moneypunct<char, false>::~moneypunct()
311    { }
312
313#ifdef _GLIBCPP_USE_WCHAR_T
314  template<>
315    void
316    moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc)
317    {
318      if (__cloc == _S_c_locale)
319	{
320	  // "C" locale
321	  _M_decimal_point = L'.';
322	  _M_thousands_sep = L',';
323	  _M_grouping = "";
324	  _M_curr_symbol = L"";
325	  _M_positive_sign = L"";
326	  _M_negative_sign = L"";
327	  _M_frac_digits = 0;
328	  _M_pos_format = money_base::_S_default_pattern;
329	  _M_neg_format = money_base::_S_default_pattern;
330	}
331      else
332	{
333	  // Named locale.
334	  _M_decimal_point = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc)}).__w);
335
336	  _M_thousands_sep = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc)}).__w);
337	  _M_grouping = __nl_langinfo_l(GROUPING, __cloc);
338
339	  mbstate_t __state;
340	  size_t __len;
341	  const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
342	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
343	  const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
344
345	  // NB: Should swich to __cloc's ctype info first.
346	  __len = strlen(__cpossign);
347	  if (__len)
348	    {
349	      ++__len;
350	      memset(&__state, 0, sizeof(mbstate_t));
351	      wchar_t* __wcs = new wchar_t[__len];
352	      mbsrtowcs(__wcs, &__cpossign, __len, &__state);
353	      _M_positive_sign = __wcs;
354	    }
355	  else
356	    _M_positive_sign = L"";
357
358	  char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
359	  __len = strlen(__cnegsign);
360	  if (!__nposn)
361	    _M_negative_sign = L"()";
362	  else if (__len)
363	    {
364	      ++__len;
365	      memset(&__state, 0, sizeof(mbstate_t));
366	      wchar_t* __wcs = new wchar_t[__len];
367	      mbsrtowcs(__wcs, &__cnegsign, __len, &__state);
368	      _M_negative_sign = __wcs;
369	    }
370	  else
371	    _M_negative_sign = L"";
372
373	  // _Intl == true.
374	  __len = strlen(__ccurr);
375	  if (__len)
376	    {
377	      ++__len;
378	      memset(&__state, 0, sizeof(mbstate_t));
379	      wchar_t* __wcs = new wchar_t[__len];
380	      mbsrtowcs(__wcs, &__ccurr, __len, &__state);
381	      _M_curr_symbol = __wcs;
382	    }
383	  else
384	    _M_curr_symbol = L"";
385
386	  _M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc));
387	  char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
388	  char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
389	  char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
390	  _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn);
391	  char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
392	  char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
393	  _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn);
394	}
395    }
396
397  template<>
398    void
399    moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc)
400    {
401      if (__cloc == _S_c_locale)
402	{
403	  // "C" locale
404	  _M_decimal_point = L'.';
405	  _M_thousands_sep = L',';
406	  _M_grouping = "";
407	  _M_curr_symbol = L"";
408	  _M_positive_sign = L"";
409	  _M_negative_sign = L"";
410	  _M_frac_digits = 0;
411	  _M_pos_format = money_base::_S_default_pattern;
412	  _M_neg_format = money_base::_S_default_pattern;
413	}
414      else
415	{
416	  // Named locale.
417	  _M_decimal_point = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc)}).__w);
418	  _M_thousands_sep = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc)}).__w);
419	  _M_grouping = __nl_langinfo_l(GROUPING, __cloc);
420
421	  mbstate_t __state;
422	  size_t __len;
423	  const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
424	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
425	  const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
426
427	  // NB: Should swich to __cloc's ctype info first.
428	  __len = strlen(__cpossign);
429	  if (__len)
430	    {
431	      ++__len;
432	      memset(&__state, 0, sizeof(mbstate_t));
433	      wchar_t* __wcs = new wchar_t[__len];
434	      mbsrtowcs(__wcs, &__cpossign, __len, &__state);
435	      _M_positive_sign = __wcs;
436	    }
437	  else
438	    _M_positive_sign = L"";
439
440	  char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
441	  __len = strlen(__cnegsign);
442	  if (!__nposn)
443	    _M_negative_sign = L"()";
444	  else if (__len)
445	    {
446	      ++__len;
447	      memset(&__state, 0, sizeof(mbstate_t));
448	      wchar_t* __wcs = new wchar_t[__len];
449	      mbsrtowcs(__wcs, &__cnegsign, __len, &__state);
450	      _M_negative_sign = __wcs;
451	    }
452	  else
453	    _M_negative_sign = L"";
454
455	  // _Intl == true.
456	  __len = strlen(__ccurr);
457	  if (__len)
458	    {
459	      ++__len;
460	      memset(&__state, 0, sizeof(mbstate_t));
461	      wchar_t* __wcs = new wchar_t[__len];
462	      mbsrtowcs(__wcs, &__ccurr, __len, &__state);
463	      _M_curr_symbol = __wcs;
464	    }
465	  else
466	    _M_curr_symbol = L"";
467
468	  _M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
469	  char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
470	  char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
471	  char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
472	  _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn);
473	  char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
474	  char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
475	  _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn);
476	}
477    }
478
479  template<>
480    moneypunct<wchar_t, true>::~moneypunct()
481    {
482      if (wcslen(_M_positive_sign))
483	delete [] _M_positive_sign;
484      if (wcslen(_M_negative_sign) && (wcscmp(_M_negative_sign, L"()") != 0))
485	delete [] _M_negative_sign;
486      if (wcslen(_M_curr_symbol))
487	delete [] _M_curr_symbol;
488    }
489
490  template<>
491    moneypunct<wchar_t, false>::~moneypunct()
492    {
493      if (wcslen(_M_positive_sign))
494	delete [] _M_positive_sign;
495      if (wcslen(_M_negative_sign) && (wcscmp(_M_negative_sign, L"()") != 0))
496	delete [] _M_negative_sign;
497      if (wcslen(_M_curr_symbol))
498	delete [] _M_curr_symbol;
499    }
500#endif
501}
502