Source code formating unification
[platform/framework/web/wrt-plugins-common.git] / src / CommonsJavaScript / Converter.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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 #include <sstream>
17 #include <limits>
18 #include <dpl/scoped_array.h>
19 #include <dpl/scoped_free.h>
20 #include "ScopedJSStringRef.h"
21 #include "Converter.h"
22 #include <dpl/log/log.h>
23
24 using namespace WrtDeviceApis::Commons;
25
26 namespace WrtDeviceApis {
27 namespace CommonsJavaScript {
28 Converter::Converter(JSContextRef context) : m_context(context)
29 {}
30
31 Converter::~Converter()
32 {}
33
34 JSObjectRef Converter::toJSObjectRef(const JSValueRef& arg)
35 {
36     if (!arg) {
37         Throw(NullPointerException);
38     }
39     JSValueRef exception = NULL;
40     JSObjectRef result = JSValueToObject(m_context, arg, &exception);
41     if ((NULL == result) || (NULL != exception)) {
42         ThrowMsg(ConversionException, "Couldn't convert to a JS Object.");
43     }
44     return result;
45 }
46
47 bool Converter::toBool(const JSValueRef& arg)
48 {
49     return JSValueToBoolean(m_context, arg);
50 }
51
52 unsigned char Converter::toUChar(const JSValueRef& arg)
53 {
54     return static_cast<unsigned char>(toChar(arg));
55 }
56
57 char Converter::toChar(const JSValueRef& arg)
58 {
59     double tmp = toNumber_(arg);
60     return (isNan(tmp) ? 0 : static_cast<char>(tmp));
61 }
62
63 int Converter::toInt(const JSValueRef& arg)
64 {
65     double tmp = toNumber_(arg);
66     return (isNan(tmp) ? 0 : static_cast<int>(tmp));
67 }
68
69 int Converter::toInt(const std::string &arg)
70 {
71     return static_cast<int>(toNumber_(arg));
72 }
73
74 long Converter::toLong(const JSValueRef& arg)
75 {
76     double tmp = toNumber_(arg);
77     return (isNan(tmp) ? 0 : static_cast<long>(tmp));
78 }
79
80 long long Converter::toLongLong(const JSValueRef& arg)
81 {
82     double tmp = toNumber_(arg);
83     return (isNan(tmp) ? 0 : static_cast<long long>(tmp));
84 }
85
86 unsigned long Converter::toULong(const JSValueRef& arg)
87 {
88     return static_cast<unsigned long>(toLong(arg));
89 }
90
91 std::size_t Converter::toSizeT(const JSValueRef& arg)
92 {
93     double tmp = toNumber_(arg);
94     return (isNan(tmp) ? 0 : static_cast<std::size_t>(tmp));
95 }
96
97 std::size_t Converter::toSizeT(const JSStringRef& arg)
98 {
99     return static_cast<std::size_t>(toNumber_(arg));
100 }
101
102 double Converter::toDouble(const JSValueRef& arg)
103 {
104     return toNumber_(arg);
105 }
106
107 std::string Converter::toString(int arg)
108 {
109     return toString_(arg);
110 }
111
112 std::string Converter::toString(unsigned long arg)
113 {
114     return toString_(arg);
115 }
116
117 std::string Converter::toString(long arg)
118 {
119     return toString_(arg);
120 }
121
122 std::string Converter::toString(std::size_t arg)
123 {
124     return toString_(arg);
125 }
126
127 std::string Converter::toString(const JSValueRef& arg)
128 {
129     return toString_(arg);
130 }
131
132 std::string Converter::tryString(const JSValueRef& arg)
133 {
134     if (!JSValueIsString(m_context, arg) &&
135         !JSValueIsNumber(m_context, arg) &&
136         !JSValueIsBoolean(m_context, arg))
137     {
138         ThrowMsg(ConversionException,
139                  "Argument is not convertable to JS String.");
140     }
141
142     return toString_(arg);
143 }
144
145 std::string Converter::toDateString(const JSValueRef& arg)
146 {
147     if (!JSValueIsObject(m_context, arg)) {
148         ThrowMsg(ConversionException, "Argument is not JS Date.");
149     }
150
151     return toString_(arg);
152 }
153
154 std::string Converter::toString(const JSStringRef& arg)
155 {
156     std::string result;
157     size_t jsSize = JSStringGetMaximumUTF8CStringSize(arg);
158     if (jsSize > 0) {
159         jsSize = jsSize + 1;
160         DPL::ScopedArray<char> buffer(new char[jsSize]);
161         size_t written = JSStringGetUTF8CString(arg, buffer.Get(), jsSize);
162         if (written > jsSize) {
163             ThrowMsg(ConversionException,
164                      "Conversion could not be fully performed.");
165         }
166         result = buffer.Get();
167     }
168
169     return result;
170 }
171
172 time_t Converter::toDateTimeT(const JSValueRef& arg)
173 {
174     struct tm tm = toDateTm(arg);
175     return mktime(&tm);
176 }
177
178 tm Converter::toDateTm(const JSValueRef& arg)
179 {
180     std::string stringDate = toDateString(arg);
181     struct tm result;
182     char* currentLocale = setlocale(LC_TIME, NULL);
183     if (currentLocale == NULL) {
184         ThrowMsg(ConversionException, "Couldn't get current locale.");
185     }
186     DPL::ScopedFree<char> currentLocaleCopy(strdup(currentLocale));
187     if (setlocale(LC_TIME, "C") == NULL) {
188         ThrowMsg(ConversionException, "Couldn't set POSIX locale.");
189     }
190     if (strptime(stringDate.c_str(), "%a %b %d %Y %T", &result) == NULL) {
191         ThrowMsg(ConversionException, "Couldn't convert supplied date.");
192     }
193     if (setlocale(LC_TIME, currentLocaleCopy.Get()) == NULL) {
194         ThrowMsg(ConversionException, "Couldn't set previous locale back.");
195     }
196     //strptime function doesn't affect tm_isdst flag.
197     //It may cause -1hr conversion error. Setting it to -1 informs that
198     //there is no information about daylight saving time.
199     result.tm_isdst = -1;
200     return result;
201 }
202
203 std::vector<unsigned char> Converter::toVectorOfUChars(const JSValueRef& arg)
204 {
205     return toVectorOfT_(arg, &Converter::toUChar);
206 }
207
208 std::vector<char> Converter::toVectorOfChars(const JSValueRef& arg)
209 {
210     return toVectorOfT_(arg, &Converter::toChar);
211 }
212
213 std::vector<int> Converter::toVectorOfInts(const JSValueRef& arg)
214 {
215     return toVectorOfT_(arg, &Converter::toInt);
216 }
217
218 std::vector<std::string> Converter::toVectorOfStrings(const JSValueRef& arg)
219 {
220     return toVectorOfT_(arg, &Converter::toString);
221 }
222
223 std::vector<time_t> Converter::toVectorOfTimeT(const JSValueRef& arg)
224 {
225     return toVectorOfT_(arg, &Converter::toDateTimeT);
226 }
227
228 JSValueRef Converter::toJSValueRef(bool arg)
229 {
230     return JSValueMakeBoolean(m_context, arg);
231 }
232
233 JSValueRef Converter::toJSValueRef(int arg)
234 {
235     return JSValueMakeNumber(m_context, arg);
236 }
237
238 JSValueRef Converter::toJSValueRef(unsigned int arg)
239 {
240     return JSValueMakeNumber(m_context, arg);
241 }
242
243 JSValueRef Converter::toJSValueRef(unsigned long arg)
244 {
245     return JSValueMakeNumber(m_context, arg);
246 }
247
248 JSValueRef Converter::toJSValueRefLong(const long arg)
249 {
250     return JSValueMakeNumber(m_context, arg);
251 }
252
253 JSValueRef Converter::toJSValueRef(long long int arg)
254 {
255     return JSValueMakeNumber(m_context, arg);
256 }
257
258 JSValueRef Converter::toJSValueRef(double arg)
259 {
260     return JSValueMakeNumber(m_context, arg);
261 }
262
263 JSValueRef Converter::toJSValueRef(const std::string& arg)
264 {
265     JSValueRef result = NULL;
266     JSStringRef jsString = JSStringCreateWithUTF8CString(arg.c_str());
267     result = JSValueMakeString(m_context, jsString);
268     JSStringRelease(jsString);
269     return result;
270 }
271
272 JSValueRef Converter::toJSValueRef(const tm& arg)
273 {
274     JSValueRef args[6];
275     args[0] = JSValueMakeNumber(m_context, arg.tm_year + 1900);
276     args[1] = JSValueMakeNumber(m_context, arg.tm_mon);
277     args[2] = JSValueMakeNumber(m_context, arg.tm_mday);
278     args[3] = JSValueMakeNumber(m_context, arg.tm_hour);
279     args[4] = JSValueMakeNumber(m_context, arg.tm_min);
280     args[5] = JSValueMakeNumber(m_context, arg.tm_sec);
281
282     JSValueRef exception = NULL;
283     JSObjectRef result = JSObjectMakeDate(m_context, 6, args, &exception);
284     if (NULL != exception) {
285         ThrowMsg(ConversionException, "Couldn't convert to a JS Date.");
286     }
287
288     return result;
289 }
290
291 JSValueRef Converter::toJSValueRef(const time_t arg)
292 {
293     struct tm *tminfo = localtime(&arg);
294     return toJSValueRef(*tminfo);
295 }
296
297 JSValueRef Converter::toJSValueRef(const std::vector<std::string>& arg)
298 {
299     return toJSValueRef_(arg);
300 }
301
302 JSValueRef Converter::toJSValueRef(const char* arg)
303 {
304     return toJSValueRef(std::string(arg));
305 }
306
307 JSValueRef Converter::toJSValueRef(const std::vector<int>& arg)
308 {
309     return toJSValueRef_(arg);
310 }
311
312 JSValueRef Converter::toJSValueRef(const std::vector<time_t>& arg)
313 {
314     return toJSValueRef_(arg);
315 }
316
317 JSValueRef Converter::toJSValueRef(JSValueRef arg)
318 {
319     return arg;
320 }
321
322 JSValueRef Converter::toJSValueRef(const std::vector<JSValueRef>& arg)
323 {
324     return toJSValueRef_(arg);
325 }
326
327 JSStringRef Converter::toJSStringRef(const std::string& arg)
328 {
329     return JSStringCreateWithUTF8CString(arg.c_str());
330 }
331
332 double Converter::toNumber_(const JSStringRef& arg)
333 {
334     return toNumber_(toString(arg));
335 }
336
337 double Converter::toNumber_(const std::string& arg)
338 {
339     double result;
340     std::stringstream ss(arg);
341     if (!(ss >> result)) {
342         Throw(ConversionException);
343     }
344     return result;
345 }
346
347 double Converter::toNumber_(const JSValueRef& arg)
348 {
349     JSValueRef exception = NULL;
350     double result = JSValueToNumber(m_context, arg, &exception);
351     if (NULL != exception) {
352         ThrowMsg(ConversionException, "Couldn't convert to a number.");
353     }
354     return result;
355 }
356
357 std::string Converter::toString_(const JSValueRef& arg)
358 {
359     std::string result;
360
361     JSValueRef exception = NULL;
362     JSStringRef str = JSValueToStringCopy(m_context, arg, &exception);
363     if (NULL == str) {
364         ThrowMsg(ConversionException, "Couldn't cast to a string.");
365     }
366
367     size_t jsSize = JSStringGetMaximumUTF8CStringSize(str);
368     if (jsSize > 0) {
369         DPL::ScopedArray<char> buffer(new char[jsSize]);
370         JSStringGetUTF8CString(str, buffer.Get(), jsSize);
371         result = buffer.Get();
372     }
373     JSStringRelease(str);
374     return result;
375 }
376
377 bool Converter::isNan(double value) const
378 {
379     // This should work unless -ffast-math (GCC) option is used.
380     STATIC_CHECK(std::numeric_limits<double>::is_iec559,
381                  NOT_IEEE754_REPRESENTATION);
382     return (value != value);
383 }
384 } // CommonsJavaScript
385 } // WrtDeviceApis
386