c_locale.cc revision 146897
1// Wrapper for underlying C-language localization -*- C++ -*-
2
3// Copyright (C) 2001, 2002, 2003 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.8  Standard locale categories.
32//
33
34// Written by Benjamin Kosnik <bkoz@redhat.com>
35
36#include <cerrno>  // For errno
37#include <cmath>  // For isinf, finite, finitef, fabs
38#include <cstdlib>  // For strof, strtold
39#include <locale>
40
41#ifdef _GLIBCXX_HAVE_IEEEFP_H
42#include <ieeefp.h>
43#endif
44
45namespace std
46{
47  // Specializations for all types used in num_get.
48  template<>
49    void
50    __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
51		   const __c_locale&)
52    {
53      if (!(__err & ios_base::failbit))
54	{
55	  // Assumes __s formatted for "C" locale.
56	  char* __old = strdup(setlocale(LC_ALL, NULL));
57	  setlocale(LC_ALL, "C");
58	  char* __sanity;
59	  errno = 0;
60#if defined(_GLIBCXX_HAVE_STRTOF)
61	  float __f = strtof(__s, &__sanity);
62#else
63	  double __d = strtod(__s, &__sanity);
64	  float __f = static_cast<float>(__d);
65#ifdef _GLIBCXX_HAVE_FINITEF
66	  if (!finitef (__f))
67	    errno = ERANGE;
68#elif defined (_GLIBCXX_HAVE_FINITE)
69	  if (!finite (static_cast<double> (__f)))
70	    errno = ERANGE;
71#elif defined (_GLIBCXX_HAVE_ISINF)
72	  if (isinf (static_cast<double> (__f)))
73	    errno = ERANGE;
74#else
75	  if (fabs(__d) > numeric_limits<float>::max())
76	    errno = ERANGE;
77#endif
78#endif
79          if (__sanity != __s && errno != ERANGE)
80	    __v = __f;
81	  else
82	    __err |= ios_base::failbit;
83	  setlocale(LC_ALL, __old);
84	  free(__old);
85	}
86    }
87
88  template<>
89    void
90    __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
91		   const __c_locale&)
92    {
93      if (!(__err & ios_base::failbit))
94	{
95	  // Assumes __s formatted for "C" locale.
96	  char* __old = strdup(setlocale(LC_ALL, NULL));
97	  setlocale(LC_ALL, "C");
98	  char* __sanity;
99	  errno = 0;
100	  double __d = strtod(__s, &__sanity);
101          if (__sanity != __s && errno != ERANGE)
102	    __v = __d;
103	  else
104	    __err |= ios_base::failbit;
105	  setlocale(LC_ALL, __old);
106	  free(__old);
107	}
108    }
109
110  template<>
111    void
112    __convert_to_v(const char* __s, long double& __v,
113		   ios_base::iostate& __err, const __c_locale&)
114    {
115      if (!(__err & ios_base::failbit))
116	{
117	  // Assumes __s formatted for "C" locale.
118	  char* __old = strdup(setlocale(LC_ALL, NULL));
119	  setlocale(LC_ALL, "C");
120#if defined(_GLIBCXX_HAVE_STRTOLD)
121	  char* __sanity;
122	  errno = 0;
123	  long double __ld = strtold(__s, &__sanity);
124          if (__sanity != __s && errno != ERANGE)
125	    __v = __ld;
126#else
127	  typedef char_traits<char>::int_type int_type;
128	  long double __ld;
129	  errno = 0;
130	  int __p = sscanf(__s, "%Lf", &__ld);
131	  if (errno == ERANGE)
132	    __p = 0;
133#ifdef _GLIBCXX_HAVE_FINITEL
134	  if ((__p == 1) && !finitel (__ld))
135	    __p = 0;
136#endif
137	  if (__p && static_cast<int_type>(__p) != char_traits<char>::eof())
138	    __v = __ld;
139#endif
140	  else
141	    __err |= ios_base::failbit;
142	  setlocale(LC_ALL, __old);
143	  free(__old);
144	}
145    }
146
147  void
148  locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
149				    __c_locale)
150  {
151    // Currently, the generic model only supports the "C" locale.
152    // See http://gcc.gnu.org/ml/libstdc++/2003-02/msg00345.html
153    __cloc = NULL;
154    if (strcmp(__s, "C"))
155      __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
156			    "name not valid"));
157  }
158
159  void
160  locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
161  { __cloc = NULL; }
162
163  __c_locale
164  locale::facet::_S_clone_c_locale(__c_locale&)
165  { return __c_locale(); }
166} // namespace std
167
168namespace __gnu_cxx
169{
170  const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
171    {
172      "LC_CTYPE",
173      "LC_NUMERIC",
174      "LC_TIME",
175      "LC_COLLATE",
176      "LC_MONETARY",
177      "LC_MESSAGES"
178    };
179}
180
181namespace std
182{
183  const char* const* const locale::_S_categories = __gnu_cxx::category_names;
184}  // namespace std
185