Update wrt-plugins-common_0.3.60
[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
29 Converter::Converter(JSContextRef context) : m_context(context)
30 {
31 }
32
33 Converter::~Converter()
34 {
35 }
36
37 JSObjectRef Converter::toJSObjectRef(const JSValueRef& arg)
38 {
39     if (!arg) {
40         Throw(NullPointerException);
41     }
42     JSValueRef exception = NULL;
43     JSObjectRef result = JSValueToObject(m_context, arg, &exception);
44     if ((NULL == result) || (NULL != exception)) {
45         ThrowMsg(ConversionException, "Couldn't convert to a JS Object.");
46     }
47     return result;
48 }
49
50 bool Converter::toBool(const JSValueRef& arg)
51 {
52     return JSValueToBoolean(m_context, arg);
53 }
54
55 unsigned char Converter::toUChar(const JSValueRef& arg)
56 {
57     return static_cast<unsigned char>(toChar(arg));
58 }
59
60 char Converter::toChar(const JSValueRef& arg)
61 {
62     double tmp = toNumber_(arg);
63     return (isNan(tmp) ? 0 : static_cast<char>(tmp));
64 }
65
66 int Converter::toInt(const JSValueRef& arg)
67 {
68     double tmp = toNumber_(arg);
69     return (isNan(tmp) ? 0 : static_cast<int>(tmp));
70 }
71
72 int Converter::toInt(const std::string &arg)
73 {
74     return static_cast<int>(toNumber_(arg));
75 }
76
77 long Converter::toLong(const JSValueRef& arg)
78 {
79     double tmp = toNumber_(arg);
80     return (isNan(tmp) ? 0 : static_cast<long>(tmp));
81 }
82
83 long long Converter::toLongLong(const JSValueRef& arg)
84 {
85     double tmp = toNumber_(arg);
86     return (isNan(tmp) ? 0 : static_cast<long long>(tmp));
87 }
88
89 unsigned long Converter::toULong(const JSValueRef& arg)
90 {
91     return static_cast<unsigned long>(toLong(arg));
92 }
93
94 std::size_t Converter::toSizeT(const JSValueRef& arg)
95 {
96     double tmp = toNumber_(arg);
97     return (isNan(tmp) ? 0 : static_cast<std::size_t>(tmp));
98 }
99
100 std::size_t Converter::toSizeT(const JSStringRef& arg)
101 {
102     return static_cast<std::size_t>(toNumber_(arg));
103 }
104
105 double Converter::toDouble(const JSValueRef& arg)
106 {
107     return toNumber_(arg);
108 }
109
110 std::string Converter::toString(int arg)
111 {
112     return toString_(arg);
113 }
114
115 std::string Converter::toString(unsigned long arg)
116 {
117     return toString_(arg);
118 }
119
120 std::string Converter::toString(long arg)
121 {
122     return toString_(arg);
123 }
124
125 std::string Converter::toString(std::size_t arg)
126 {
127     return toString_(arg);
128 }
129
130 std::string Converter::toString(const JSValueRef& arg)
131 {
132     return toString_(arg);
133 }
134
135 std::string Converter::tryString(const JSValueRef& arg)
136 {
137     if (!JSValueIsString(m_context, arg) &&
138         !JSValueIsNumber(m_context, arg) &&
139         !JSValueIsBoolean(m_context, arg)) {
140         ThrowMsg(ConversionException,
141                  "Argument is not convertable to JS String.");
142     }
143
144     return toString_(arg);
145 }
146
147 std::string Converter::toDateString(const JSValueRef& arg)
148 {
149     if (!JSValueIsObject(m_context, arg)) {
150         ThrowMsg(ConversionException, "Argument is not JS Date.");
151     }
152
153     return toString_(arg);
154 }
155
156 std::string Converter::toString(const JSStringRef& arg)
157 {
158     std::string result;
159     size_t jsSize = JSStringGetMaximumUTF8CStringSize(arg);
160     if (jsSize > 0) {
161         jsSize = jsSize + 1;
162         DPL::ScopedArray<char> buffer(new char[jsSize]);
163         size_t written = JSStringGetUTF8CString(arg, buffer.Get(), jsSize);
164         if (written > jsSize) {
165             ThrowMsg(ConversionException,
166                      "Conversion could not be fully performed.");
167         }
168         result = buffer.Get();
169     }
170
171     return result;
172 }
173
174 time_t Converter::toDateTimeT(const JSValueRef& arg)
175 {
176     struct tm tm = toDateTm(arg);
177     return mktime(&tm);
178 }
179
180 tm Converter::toDateTm(const JSValueRef& arg)
181 {
182     std::string stringDate = toDateString(arg);
183     struct tm result;
184     char* currentLocale = setlocale(LC_TIME, NULL);
185     if (currentLocale == NULL) {
186         ThrowMsg(ConversionException, "Couldn't get current locale.");
187     }
188     DPL::ScopedFree<char> currentLocaleCopy(strdup(currentLocale));
189     if (setlocale(LC_TIME, "C") == NULL) {
190         ThrowMsg(ConversionException, "Couldn't set POSIX locale.");
191     }
192     if (strptime(stringDate.c_str(), "%a %b %d %Y %T", &result) == NULL) {
193         ThrowMsg(ConversionException, "Couldn't convert supplied date.");
194     }
195     if (setlocale(LC_TIME, currentLocaleCopy.Get()) == NULL) {
196         ThrowMsg(ConversionException, "Couldn't set previous locale back.");
197     }
198     //strptime function doesn't affect tm_isdst flag.
199     //It may cause -1hr conversion error. Setting it to -1 informs that
200     //there is no information about daylight saving time.
201     result.tm_isdst = -1;
202     return result;
203 }
204
205 std::vector<unsigned char> Converter::toVectorOfUChars(const JSValueRef& arg)
206 {
207     return toVectorOfT_(arg, &Converter::toUChar);
208 }
209
210 std::vector<char> Converter::toVectorOfChars(const JSValueRef& arg)
211 {
212     return toVectorOfT_(arg, &Converter::toChar);
213 }
214
215 std::vector<int> Converter::toVectorOfInts(const JSValueRef& arg)
216 {
217     return toVectorOfT_(arg, &Converter::toInt);
218 }
219
220 std::vector<std::string> Converter::toVectorOfStrings(const JSValueRef& arg)
221 {
222     return toVectorOfT_(arg, &Converter::toString);
223 }
224
225 std::vector<time_t> Converter::toVectorOfTimeT(const JSValueRef& arg) {
226     return toVectorOfT_(arg, &Converter::toDateTimeT);
227 }
228
229 JSValueRef Converter::toJSValueRef(bool arg)
230 {
231     return JSValueMakeBoolean(m_context, arg);
232 }
233
234 JSValueRef Converter::toJSValueRef(int arg)
235 {
236     return JSValueMakeNumber(m_context, arg);
237 }
238
239 JSValueRef Converter::toJSValueRef(unsigned int arg)
240 {
241     return JSValueMakeNumber(m_context, arg);
242 }
243
244 JSValueRef Converter::toJSValueRef(unsigned long arg)
245 {
246     return JSValueMakeNumber(m_context, arg);
247 }
248
249 JSValueRef Converter::toJSValueRefLong(const long arg) {
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     return toJSValueRef_(arg);
309 }
310
311 JSValueRef Converter::toJSValueRef(const std::vector<time_t>& arg) {
312     return toJSValueRef_(arg);
313 }
314
315 JSValueRef Converter::toJSValueRef(JSValueRef arg)
316 {
317     return arg;
318 }
319
320 JSValueRef Converter::toJSValueRef(const std::vector<JSValueRef>& arg)
321 {
322     return toJSValueRef_(arg);
323 }
324
325 JSStringRef Converter::toJSStringRef(const std::string& arg)
326 {
327     return JSStringCreateWithUTF8CString(arg.c_str());
328 }
329
330 double Converter::toNumber_(const JSStringRef& arg)
331 {
332     return toNumber_(toString(arg));
333 }
334
335 double Converter::toNumber_(const std::string& arg)
336 {
337     double result;
338     std::stringstream ss(arg);
339     if (!(ss >> result)) {
340         Throw(ConversionException);
341     }
342     return result;
343 }
344
345 double Converter::toNumber_(const JSValueRef& arg)
346 {
347     JSValueRef exception = NULL;
348     double result = JSValueToNumber(m_context, arg, &exception);
349     if (NULL != exception) {
350         ThrowMsg(ConversionException, "Couldn't convert to a number.");
351     }
352     return result;
353 }
354
355 std::string Converter::toString_(const JSValueRef& arg)
356 {
357     std::string result;
358
359     JSValueRef exception = NULL;
360     JSStringRef str = JSValueToStringCopy(m_context, arg, &exception);
361     if (NULL == str) {
362         ThrowMsg(ConversionException, "Couldn't cast to a string.");
363     }
364
365     size_t jsSize = JSStringGetMaximumUTF8CStringSize(str);
366     if (jsSize > 0) {
367         DPL::ScopedArray<char> buffer(new char[jsSize]);
368         JSStringGetUTF8CString(str, buffer.Get(), jsSize);
369         result = buffer.Get();
370     }
371     JSStringRelease(str);
372     return result;
373 }
374
375 bool Converter::isNan(double value) const
376 {
377     // This should work unless -ffast-math (GCC) option is used.
378     STATIC_CHECK(std::numeric_limits<double>::is_iec559,
379                  NOT_IEEE754_REPRESENTATION);
380     return (value != value);
381 }
382
383 } // CommonsJavaScript
384 } // WrtDeviceApis
385