OSDN Git Service

2003-10-29 Paolo Carlini <pcarlini@suse.de>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / config / locale / generic / c_locale.cc
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 <locale>
38
39 #ifdef _GLIBCXX_HAVE_IEEEFP_H
40 #include <ieeefp.h>
41 #endif
42
43 namespace std 
44 {
45   // Specializations for all types used in num_get.
46   template<>
47     void
48     __convert_to_v(const char* __s, long& __v, ios_base::iostate& __err, 
49                    const __c_locale&, int __base)
50     {
51       if (!(__err & ios_base::failbit))
52       {
53         char* __sanity;
54         errno = 0;
55         long __l = strtol(__s, &__sanity, __base);
56         if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
57           __v = __l;
58         else
59           __err |= ios_base::failbit;
60       }
61     }
62
63   template<>
64     void
65     __convert_to_v(const char* __s, unsigned long& __v, 
66                    ios_base::iostate& __err, const __c_locale&, int __base)
67     {
68       if (!(__err & ios_base::failbit))
69         {
70           char* __sanity;
71           errno = 0;
72           unsigned long __ul = strtoul(__s, &__sanity, __base);
73           if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
74             __v = __ul;
75           else
76             __err |= ios_base::failbit;
77         }
78     }
79
80 #ifdef _GLIBCXX_USE_LONG_LONG
81   template<>
82     void
83     __convert_to_v(const char* __s, long long& __v, ios_base::iostate& __err, 
84                    const __c_locale&, int __base)
85     {
86       if (!(__err & ios_base::failbit))
87         {
88           char* __sanity;
89           errno = 0;
90           long long __ll = strtoll(__s, &__sanity, __base);
91           if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
92             __v = __ll;
93           else
94             __err |= ios_base::failbit;
95         }
96     }
97
98   template<>
99     void
100     __convert_to_v(const char* __s, unsigned long long& __v, 
101                    ios_base::iostate& __err, const __c_locale&, int __base)
102     {
103       if (!(__err & ios_base::failbit))
104         {      
105           char* __sanity;
106           errno = 0;
107           unsigned long long __ull = strtoull(__s, &__sanity, __base);
108           if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
109             __v = __ull;
110           else
111             __err |= ios_base::failbit;
112         }  
113     }
114 #endif
115
116   template<>
117     void
118     __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err, 
119                    const __c_locale&, int)            
120     {
121       if (!(__err & ios_base::failbit))
122         {
123           // Assumes __s formatted for "C" locale.
124           char* __old = strdup(setlocale(LC_ALL, NULL));
125           setlocale(LC_ALL, "C");
126           char* __sanity;
127           errno = 0;
128 #if defined(_GLIBCXX_USE_C99)
129           float __f = strtof(__s, &__sanity);
130 #else
131           double __d = strtod(__s, &__sanity);
132           float __f = static_cast<float>(__d);
133 #ifdef _GLIBCXX_HAVE_FINITEF
134           if (!finitef (__f))
135             errno = ERANGE;
136 #elif defined (_GLIBCXX_HAVE_FINITE)
137           if (!finite (static_cast<double> (__f)))
138             errno = ERANGE;
139 #elif defined (_GLIBCXX_HAVE_ISINF)
140           if (isinf (static_cast<double> (__f)))
141             errno = ERANGE;
142 #else
143           if (fabs(__d) > numeric_limits<float>::max())
144             errno = ERANGE;
145 #endif
146 #endif
147           if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
148             __v = __f;
149           else
150             __err |= ios_base::failbit;
151           setlocale(LC_ALL, __old);
152           free(__old);
153         }
154     }
155
156   template<>
157     void
158     __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err, 
159                    const __c_locale&, int) 
160     {
161       if (!(__err & ios_base::failbit))
162         {
163           // Assumes __s formatted for "C" locale.
164           char* __old = strdup(setlocale(LC_ALL, NULL));
165           setlocale(LC_ALL, "C");
166           char* __sanity;
167           errno = 0;
168           double __d = strtod(__s, &__sanity);
169           if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
170             __v = __d;
171           else
172             __err |= ios_base::failbit;
173           setlocale(LC_ALL, __old);
174           free(__old);
175         }
176     }
177
178   template<>
179     void
180     __convert_to_v(const char* __s, long double& __v, 
181                    ios_base::iostate& __err, const __c_locale&, int) 
182     {
183       if (!(__err & ios_base::failbit))
184         {
185           // Assumes __s formatted for "C" locale.
186           char* __old = strdup(setlocale(LC_ALL, NULL));
187           setlocale(LC_ALL, "C");
188 #if defined(_GLIBCXX_USE_C99)
189           char* __sanity;
190           errno = 0;
191           long double __ld = strtold(__s, &__sanity);
192           if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
193             __v = __ld;
194 #else
195           typedef char_traits<char>::int_type int_type;
196           long double __ld;
197           errno = 0;
198           int __p = sscanf(__s, "%Lf", &__ld);
199           if (errno == ERANGE)
200             __p = 0;
201 #ifdef _GLIBCXX_HAVE_FINITEL
202           if ((__p == 1) && !finitel (__ld))
203             __p = 0;
204 #endif
205           if (__p && static_cast<int_type>(__p) != char_traits<char>::eof())
206             __v = __ld;
207 #endif
208           else
209             __err |= ios_base::failbit;
210           setlocale(LC_ALL, __old);
211           free(__old);
212         }
213     }
214
215   void
216   locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s, 
217                                     __c_locale)
218   {
219     // Currently, the generic model only supports the "C" locale.
220     // See http://gcc.gnu.org/ml/libstdc++/2003-02/msg00345.html
221     __cloc = NULL;
222     if (strcmp(__s, "C"))
223       __throw_runtime_error("locale::facet::_S_create_c_locale "
224                             "name not valid");
225   }
226
227   void
228   locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
229   { __cloc = NULL; }
230
231   __c_locale
232   locale::facet::_S_clone_c_locale(__c_locale&)
233   { return __c_locale(); }
234 } // namespace std
235
236 namespace __gnu_cxx
237 {
238   const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
239     {
240       "LC_CTYPE", 
241       "LC_NUMERIC",
242       "LC_TIME",   
243       "LC_COLLATE", 
244       "LC_MONETARY",
245       "LC_MESSAGES"
246     };
247 }  
248
249 namespace std
250 {
251   const char* const* const locale::_S_categories = __gnu_cxx::category_names;
252 }  // namespace std