c_locale.cc revision 169691
1210284Sjmallett// Wrapper for underlying C-language localization -*- C++ -*-
2210284Sjmallett
3210284Sjmallett// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
4210284Sjmallett// Free Software Foundation, Inc.
5210284Sjmallett//
6210284Sjmallett// This file is part of the GNU ISO C++ Library.  This library is free
7210284Sjmallett// software; you can redistribute it and/or modify it under the
8210284Sjmallett// terms of the GNU General Public License as published by the
9210284Sjmallett// Free Software Foundation; either version 2, or (at your option)
10210284Sjmallett// any later version.
11210284Sjmallett
12210284Sjmallett// This library is distributed in the hope that it will be useful,
13210284Sjmallett// but WITHOUT ANY WARRANTY; without even the implied warranty of
14210284Sjmallett// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15210284Sjmallett// GNU General Public License for more details.
16210284Sjmallett
17210284Sjmallett// You should have received a copy of the GNU General Public License along
18210284Sjmallett// with this library; see the file COPYING.  If not, write to the Free
19210284Sjmallett// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20210284Sjmallett// USA.
21210284Sjmallett
22210284Sjmallett// As a special exception, you may use this file as part of a free software
23210284Sjmallett// library without restriction.  Specifically, if other files instantiate
24210284Sjmallett// templates or use macros or inline functions from this file, or you compile
25210284Sjmallett// this file and link it with other files to produce an executable, this
26210284Sjmallett// file does not by itself cause the resulting executable to be covered by
27210284Sjmallett// the GNU General Public License.  This exception does not however
28210284Sjmallett// invalidate any other reasons why the executable file might be covered by
29210284Sjmallett// the GNU General Public License.
30210284Sjmallett
31210284Sjmallett//
32210284Sjmallett// ISO C++ 14882: 22.8  Standard locale categories.
33210284Sjmallett//
34210284Sjmallett
35210284Sjmallett// Written by Benjamin Kosnik <bkoz@redhat.com>
36210284Sjmallett
37210284Sjmallett#include <cerrno>  // For errno
38210284Sjmallett#include <cmath>  // For isinf, finite, finitef, fabs
39210284Sjmallett#include <cstdlib>  // For strof, strtold
40210284Sjmallett#include <locale>
41210284Sjmallett
42210284Sjmallett#ifdef _GLIBCXX_HAVE_IEEEFP_H
43210284Sjmallett#include <ieeefp.h>
44210284Sjmallett#endif
45210284Sjmallett
46210284Sjmallett_GLIBCXX_BEGIN_NAMESPACE(std)
47210284Sjmallett
48210284Sjmallett  // Specializations for all types used in num_get.
49210284Sjmallett  template<>
50210284Sjmallett    void
51210284Sjmallett    __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
52210284Sjmallett		   const __c_locale&)
53210284Sjmallett    {
54210284Sjmallett      // Assumes __s formatted for "C" locale.
55210311Sjmallett      errno = 0;
56210284Sjmallett      char* __old = strdup(setlocale(LC_ALL, NULL));
57210284Sjmallett      setlocale(LC_ALL, "C");
58210311Sjmallett      char* __sanity;
59210284Sjmallett#if defined(_GLIBCXX_HAVE_STRTOF)
60210284Sjmallett      float __f = strtof(__s, &__sanity);
61210284Sjmallett#else
62210284Sjmallett      double __d = strtod(__s, &__sanity);
63210284Sjmallett      float __f = static_cast<float>(__d);
64210284Sjmallett#ifdef _GLIBCXX_HAVE_FINITEF
65210284Sjmallett      if (!finitef (__f))
66210284Sjmallett	errno = ERANGE;
67210284Sjmallett#elif defined (_GLIBCXX_HAVE_FINITE)
68210284Sjmallett      if (!finite (static_cast<double> (__f)))
69210284Sjmallett	errno = ERANGE;
70210284Sjmallett#elif defined (_GLIBCXX_HAVE_ISINF)
71210284Sjmallett      if (isinf (static_cast<double> (__f)))
72210284Sjmallett	errno = ERANGE;
73210284Sjmallett#else
74210284Sjmallett      if (fabs(__d) > numeric_limits<float>::max())
75210284Sjmallett	errno = ERANGE;
76210284Sjmallett#endif
77210284Sjmallett#endif
78210284Sjmallett      if (__sanity != __s && errno != ERANGE)
79210284Sjmallett	__v = __f;
80210284Sjmallett      else
81210284Sjmallett	__err |= ios_base::failbit;
82210284Sjmallett      setlocale(LC_ALL, __old);
83210284Sjmallett      free(__old);
84210284Sjmallett    }
85210284Sjmallett
86210284Sjmallett  template<>
87210284Sjmallett    void
88210284Sjmallett    __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
89210284Sjmallett		   const __c_locale&)
90210284Sjmallett    {
91210284Sjmallett      // Assumes __s formatted for "C" locale.
92210284Sjmallett      errno = 0;
93210284Sjmallett      char* __old = strdup(setlocale(LC_ALL, NULL));
94210284Sjmallett      setlocale(LC_ALL, "C");
95210284Sjmallett      char* __sanity;
96210284Sjmallett      double __d = strtod(__s, &__sanity);
97210284Sjmallett      if (__sanity != __s && errno != ERANGE)
98210284Sjmallett	__v = __d;
99210284Sjmallett      else
100210284Sjmallett	__err |= ios_base::failbit;
101210284Sjmallett      setlocale(LC_ALL, __old);
102210284Sjmallett      free(__old);
103210284Sjmallett    }
104210284Sjmallett
105210284Sjmallett  template<>
106210284Sjmallett    void
107210284Sjmallett    __convert_to_v(const char* __s, long double& __v,
108210284Sjmallett		   ios_base::iostate& __err, const __c_locale&)
109210284Sjmallett    {
110210284Sjmallett      // Assumes __s formatted for "C" locale.
111210284Sjmallett      errno = 0;
112210284Sjmallett      char* __old = strdup(setlocale(LC_ALL, NULL));
113210284Sjmallett      setlocale(LC_ALL, "C");
114210284Sjmallett#if defined(_GLIBCXX_HAVE_STRTOLD)
115210284Sjmallett      char* __sanity;
116210284Sjmallett      long double __ld = strtold(__s, &__sanity);
117210284Sjmallett      if (__sanity != __s && errno != ERANGE)
118210284Sjmallett	__v = __ld;
119210284Sjmallett#else
120210284Sjmallett      typedef char_traits<char>::int_type int_type;
121210284Sjmallett      long double __ld;
122210284Sjmallett      int __p = sscanf(__s, "%Lf", &__ld);
123210284Sjmallett      if (__p && static_cast<int_type>(__p) != char_traits<char>::eof()
124210284Sjmallett	  && errno != ERANGE)
125210284Sjmallett	__v = __ld;
126210284Sjmallett#endif
127210284Sjmallett      else
128210284Sjmallett	__err |= ios_base::failbit;
129210284Sjmallett      setlocale(LC_ALL, __old);
130210284Sjmallett      free(__old);
131210284Sjmallett    }
132210284Sjmallett
133210284Sjmallett  void
134210284Sjmallett  locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
135210284Sjmallett				    __c_locale)
136210284Sjmallett  {
137210284Sjmallett    // Currently, the generic model only supports the "C" locale.
138210284Sjmallett    // See http://gcc.gnu.org/ml/libstdc++/2003-02/msg00345.html
139210284Sjmallett    __cloc = NULL;
140210284Sjmallett    if (strcmp(__s, "C"))
141210284Sjmallett      __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
142210284Sjmallett			    "name not valid"));
143210284Sjmallett  }
144210284Sjmallett
145210284Sjmallett  void
146210284Sjmallett  locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
147210284Sjmallett  { __cloc = NULL; }
148210284Sjmallett
149210284Sjmallett  __c_locale
150210284Sjmallett  locale::facet::_S_clone_c_locale(__c_locale&)
151210284Sjmallett  { return __c_locale(); }
152210284Sjmallett
153210284Sjmallett_GLIBCXX_END_NAMESPACE
154210284Sjmallett
155210284Sjmallett_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
156210284Sjmallett
157210284Sjmallett  const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
158210284Sjmallett    {
159210284Sjmallett      "LC_CTYPE",
160210284Sjmallett      "LC_NUMERIC",
161210284Sjmallett      "LC_TIME",
162210284Sjmallett      "LC_COLLATE",
163210284Sjmallett      "LC_MONETARY",
164210284Sjmallett      "LC_MESSAGES"
165210284Sjmallett    };
166210284Sjmallett
167210284Sjmallett_GLIBCXX_END_NAMESPACE
168210284Sjmallett
169210284Sjmallett_GLIBCXX_BEGIN_NAMESPACE(std)
170210284Sjmallett
171210284Sjmallett  const char* const* const locale::_S_categories = __gnu_cxx::category_names;
172210284Sjmallett
173210284Sjmallett_GLIBCXX_END_NAMESPACE
174210284Sjmallett
175210284Sjmallett// XXX GLIBCXX_ABI Deprecated
176210284Sjmallett#ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
177210284Sjmallett#define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
178210284Sjmallett  extern "C" void ldbl (void) __attribute__ ((alias (#dbl)))
179210284Sjmallett_GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKPi, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKPi);
180210284Sjmallett#endif // _GLIBCXX_LONG_DOUBLE_COMPAT
181210284Sjmallett