bdcf7ecc7aa5b636b74a6c64256b4f57dc99d85b
[platform/framework/native/appfw.git] / src / base / FBase_LocalizedNumParser.cpp
1 //
2 // Copyright (c) 2013 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18  * @file                FBase_LocalizedNumParser.cpp
19  * @brief               This is the implementation file for _LocalizedNumParser class.
20  */
21
22 #include <cerrno>
23 #include <clocale>
24 #include <cmath>
25 #include <cwchar>
26 #include <limits>
27 #include <FBaseSysLog.h>
28 #include "FBase_LocalizedNumParser.h"
29
30 namespace Tizen { namespace Base
31 {
32
33 class _CLocaleWrapper
34 {
35 public:
36         _CLocaleWrapper(void)
37                 : _locale(0)
38         {
39         }
40
41         ~_CLocaleWrapper(void)
42         {
43                 if (_locale != null)
44                 {
45                         freelocale(_locale);
46                         uselocale(LC_GLOBAL_LOCALE);
47                 }
48         }
49
50         result
51         Construct(const char* pLocale)
52         {
53                 _locale = newlocale(LC_ALL, pLocale, null);
54                 SysTryReturnResult(NID_BASE, _locale != null, E_INVALID_ARG, "Creating a new locale object is failed. pLocale is invalid.");
55
56                 uselocale(_locale);
57                 return E_SUCCESS;
58         }
59
60 private:
61         locale_t _locale;
62 };
63
64 double
65 _LocalizedNumParser::ToDouble(const String& str, const char* pLocale)
66 {
67         ClearLastResult();
68
69         _CLocaleWrapper clocale;
70         result r = clocale.Construct(pLocale);
71         SysTryReturn(NID_BASE, r == E_SUCCESS, std::numeric_limits< double >::quiet_NaN(), r, "[%s] Propagating.", GetErrorMessage(r));
72
73         wchar_t* pEnd = null;
74         errno = 0;
75
76         double ret = wcstod(str.GetPointer(), &pEnd);
77         SysTryReturn(NID_BASE, !(ret == 0 && errno == EINVAL) && (pEnd[0] == 0), std::numeric_limits< double >::quiet_NaN(),
78                 E_NUM_FORMAT, "[%s] wcstod() failed. Scan stopped at (%ls)", GetErrorMessage(E_NUM_FORMAT), pEnd);
79         SysTryReturn(NID_BASE, errno == 0 && ret != HUGE_VAL && ret != -HUGE_VAL, std::numeric_limits< double >::quiet_NaN(),
80                 E_NUM_FORMAT, "[%s] Parsed value cannot fit into a Double.", GetErrorMessage(E_NUM_FORMAT));
81
82         return ret;
83 }
84
85 float
86 _LocalizedNumParser::ToFloat(const String& str, const char* pLocale)
87 {
88         ClearLastResult();
89
90         _CLocaleWrapper clocale;
91         result r = clocale.Construct(pLocale);
92         SysTryReturn(NID_BASE, r == E_SUCCESS, std::numeric_limits< float >::quiet_NaN(), r, "[%s] Propagating.", GetErrorMessage(r));
93
94         wchar_t* pEnd = null;
95         errno = 0;
96
97         float ret = wcstof(str.GetPointer(), &pEnd);
98         SysTryReturn(NID_BASE, !(ret == 0 && errno == EINVAL) && pEnd[0] == 0, std::numeric_limits< float >::quiet_NaN(),
99                 E_NUM_FORMAT, "[%s] wcstof() failed. Scan stopped at (%ls).", GetErrorMessage(E_NUM_FORMAT), pEnd);
100         SysTryReturn(NID_BASE, errno == 0 && ret != HUGE_VAL && ret != -HUGE_VAL, std::numeric_limits< float >::quiet_NaN(),
101                 E_NUM_FORMAT, "[%s] Parsed value cannot fit into a Float.", GetErrorMessage(E_NUM_FORMAT));
102
103         return ret;
104 }
105
106 String
107 _LocalizedNumParser::ToString(double value, const char* pLocale)
108 {
109         ClearLastResult();
110
111         if (std::isnan(value))
112         {
113                 return String(L"NaN");
114         }
115
116         if (std::isinf(value))
117         {
118                 return String(L"Infinity");
119         }
120
121         _CLocaleWrapper clocale;
122         result r = clocale.Construct(pLocale);
123         SysTryReturn(NID_BASE, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
124
125         wchar_t sValue[DBL_MAX_LENGTH + 1] = {0, };
126         swprintf(sValue, sizeof(sValue) / sizeof(sValue[0]), L"%#lg", value);
127
128         return String(sValue);
129 }
130
131 String
132 _LocalizedNumParser::ToString(float value, const char* pLocale)
133 {
134         ClearLastResult();
135
136         if (std::isnan(value))
137         {
138                 return String(L"NaN");
139         }
140
141         if (std::isinf(value))
142         {
143                 return String(L"Infinity");
144         }
145
146         _CLocaleWrapper clocale;
147         result r = clocale.Construct(pLocale);
148         SysTryReturn(NID_BASE, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
149
150         wchar_t sValue[FLOAT_LENGTH_MAX + 1] = {0, };
151         swprintf(sValue, sizeof(sValue) / sizeof(sValue[0]), L"%g", value);
152
153         return String(sValue);
154 }
155
156 }}      // Tizen::Base