[ACR][20/08/2013][Add]Enhance Double::ToString() andFloat::ToString() to set a specif...
[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 #include <cerrno>
22 #include <clocale>
23 #include <cmath>
24 #include <cwchar>
25 #include <limits>
26 #include <FBaseSysLog.h>
27 #include "FBase_LocalizedNumParser.h"
28
29 #define CHECK_NAN_OR_INF_AND_RETURN(value)      \
30         if (std::isnan(value))                  \
31         {                                       \
32                 return String(L"NaN");          \
33         }                                       \
34         if (std::isinf(value))                  \
35         {                                       \
36                 return String(L"Infinity");     \
37         }
38
39 namespace Tizen { namespace Base
40 {
41
42 class _CLocaleWrapper
43 {
44 public:
45         _CLocaleWrapper(void)
46                 : _locale(0)
47         {
48         }
49
50         ~_CLocaleWrapper(void)
51         {
52                 if (_locale != null)
53                 {
54                         freelocale(_locale);
55                         uselocale(LC_GLOBAL_LOCALE);
56                 }
57         }
58
59         result Construct(const char* pLocale)
60         {
61                 _locale = newlocale(LC_ALL, pLocale, null);
62                 SysTryReturnResult(NID_BASE, _locale != null, E_INVALID_ARG, "Creating a new locale object is failed. pLocale is invalid.");
63
64                 uselocale(_locale);
65                 return E_SUCCESS;
66         }
67
68 private:
69         locale_t _locale;
70 };
71
72 double
73 _LocalizedNumParser::ToDouble(const String& str, const char* pLocale)
74 {
75         ClearLastResult();
76
77         _CLocaleWrapper clocale;
78         result r = clocale.Construct(pLocale);
79         SysTryReturn(NID_BASE, r == E_SUCCESS, std::numeric_limits< double >::quiet_NaN(), r, "[%s] Propagating.", GetErrorMessage(r));
80
81         wchar_t* pEnd = null;
82         errno = 0;
83
84         double ret = wcstod(str.GetPointer(), &pEnd);
85         SysTryReturn(NID_BASE, !(ret == 0 && errno == EINVAL) && (pEnd[0] == 0), std::numeric_limits< double >::quiet_NaN(),
86                 E_NUM_FORMAT, "[%s] wcstod() failed. Scan stopped at (%ls)", GetErrorMessage(E_NUM_FORMAT), pEnd);
87         SysTryReturn(NID_BASE, errno == 0 || (ret != HUGE_VAL && ret != -HUGE_VAL), std::numeric_limits< double >::quiet_NaN(),
88                 E_NUM_FORMAT, "[%s] Parsed value cannot fit into a Double.", GetErrorMessage(E_NUM_FORMAT));
89
90         return ret;
91 }
92
93 float
94 _LocalizedNumParser::ToFloat(const String& str, const char* pLocale)
95 {
96         ClearLastResult();
97
98         _CLocaleWrapper clocale;
99         result r = clocale.Construct(pLocale);
100         SysTryReturn(NID_BASE, r == E_SUCCESS, std::numeric_limits< float >::quiet_NaN(), r, "[%s] Propagating.", GetErrorMessage(r));
101
102         wchar_t* pEnd = null;
103         errno = 0;
104
105         float ret = wcstof(str.GetPointer(), &pEnd);
106         SysTryReturn(NID_BASE, !(ret == 0 && errno == EINVAL) && pEnd[0] == 0, std::numeric_limits< float >::quiet_NaN(),
107                 E_NUM_FORMAT, "[%s] wcstof() failed. Scan stopped at (%ls).", GetErrorMessage(E_NUM_FORMAT), pEnd);
108         SysTryReturn(NID_BASE, errno == 0 || (ret != HUGE_VAL && ret != -HUGE_VAL), std::numeric_limits< float >::quiet_NaN(),
109                 E_NUM_FORMAT, "[%s] Parsed value cannot fit into a Float.", GetErrorMessage(E_NUM_FORMAT));
110
111         return ret;
112 }
113
114 String
115 _LocalizedNumParser::ToString(double value, const char* pLocale)
116 {
117         ClearLastResult();
118         CHECK_NAN_OR_INF_AND_RETURN(value);
119
120         _CLocaleWrapper clocale;
121         result r = clocale.Construct(pLocale);
122         SysTryReturn(NID_BASE, r == E_SUCCESS, String(L""), r, "[%s] Propagating.", GetErrorMessage(r));
123
124         wchar_t sValue[DBL_MAX_LENGTH + 1] = {0, };
125         swprintf(sValue, sizeof(sValue) / sizeof(sValue[0]), L"%#lg", value);
126
127         return String(sValue);
128 }
129
130 String
131 _LocalizedNumParser::ToString(double value, const char* pLocale, int precision)
132 {
133         ClearLastResult();
134         CHECK_NAN_OR_INF_AND_RETURN(value);
135
136         _CLocaleWrapper clocale;
137         result r = clocale.Construct(pLocale);
138         SysTryReturn(NID_BASE, r == E_SUCCESS, String(L""), r, "[%s] Propagating.", GetErrorMessage(r));
139
140         wchar_t sValue[DBL_MAX_LENGTH + 1] = {0, };
141         swprintf(sValue, sizeof(sValue) / sizeof(sValue[0]), L"%.*f", precision, value);
142
143         return String(sValue);
144 }
145
146 String
147 _LocalizedNumParser::ToString(float value, const char* pLocale)
148 {
149         ClearLastResult();
150         CHECK_NAN_OR_INF_AND_RETURN(value);
151
152         _CLocaleWrapper clocale;
153         result r = clocale.Construct(pLocale);
154         SysTryReturn(NID_BASE, r == E_SUCCESS, String(L""), r, "[%s] Propagating.", GetErrorMessage(r));
155
156         wchar_t sValue[FLOAT_LENGTH_MAX + 1] = {0, };
157         swprintf(sValue, sizeof(sValue) / sizeof(sValue[0]), L"%g", value);
158
159         return String(sValue);
160 }
161
162 String
163 _LocalizedNumParser::ToString(float value, const char* pLocale, int precision)
164 {
165         ClearLastResult();
166         CHECK_NAN_OR_INF_AND_RETURN(value);
167
168         _CLocaleWrapper clocale;
169         result r = clocale.Construct(pLocale);
170         SysTryReturn(NID_BASE, r == E_SUCCESS, String(L""), r, "[%s] Propagating.", GetErrorMessage(r));
171
172         wchar_t sValue[DBL_MAX_LENGTH + 1] = {0, };
173         swprintf(sValue, sizeof(sValue) / sizeof(sValue[0]), L"%.*f", precision, value);
174
175         return String(sValue);
176 }
177 }}  // Tizen::Base