Remove harcoded library path , change some variable type
[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     double tmp = toNumber_(arg);
89     return (isNan(tmp) ? 0 : static_cast<unsigned long>(tmp));
90 }
91
92 std::size_t Converter::toSizeT(const JSValueRef& arg)
93 {
94     double tmp = toNumber_(arg);
95     return (isNan(tmp) ? 0 : static_cast<std::size_t>(tmp));
96 }
97
98 std::size_t Converter::toSizeT(const JSStringRef& arg)
99 {
100     return static_cast<std::size_t>(toNumber_(arg));
101 }
102
103 double Converter::toDouble(const JSValueRef& arg)
104 {
105     return toNumber_(arg);
106 }
107
108 std::string Converter::toString(int arg)
109 {
110     return toString_(arg);
111 }
112
113 std::string Converter::toString(unsigned long arg)
114 {
115     return toString_(arg);
116 }
117
118 std::string Converter::toString(long arg)
119 {
120     return toString_(arg);
121 }
122 #ifndef __x86_64__
123 std::string Converter::toString(std::size_t arg)
124 {
125     return toString_(arg);
126 }
127 #endif
128 std::string Converter::toString(const JSValueRef& arg)
129 {
130     return toString_(arg);
131 }
132
133 std::string Converter::tryString(const JSValueRef& arg)
134 {
135     if (!JSValueIsString(m_context, arg) &&
136         !JSValueIsNumber(m_context, arg) &&
137         !JSValueIsBoolean(m_context, arg))
138     {
139         ThrowMsg(ConversionException,
140                  "Argument is not convertable to JS String.");
141     }
142
143     return toString_(arg);
144 }
145
146 std::string Converter::toDateString(const JSValueRef& arg)
147 {
148     if (!JSValueIsObject(m_context, arg)) {
149         ThrowMsg(ConversionException, "Argument is not JS Date.");
150     }
151
152     return toString_(arg);
153 }
154
155 std::string Converter::toString(const JSStringRef& arg)
156 {
157     std::string result;
158     size_t jsSize = JSStringGetMaximumUTF8CStringSize(arg);
159     if (jsSize > 0) {
160         jsSize = jsSize + 1;
161         DPL::ScopedArray<char> buffer(new char[jsSize]);
162         size_t written = JSStringGetUTF8CString(arg, buffer.Get(), jsSize);
163         if (written > jsSize) {
164             ThrowMsg(ConversionException,
165                      "Conversion could not be fully performed.");
166         }
167         result = buffer.Get();
168     }
169
170     return result;
171 }
172
173 time_t Converter::toDateTimeT(const JSValueRef& arg)
174 {
175     struct tm tm = toDateTm(arg);
176     return mktime(&tm);
177 }
178
179 tm Converter::toDateTm(const JSValueRef& arg)
180 {
181     std::string stringDate = toDateString(arg);
182     struct tm result;
183     char* currentLocale = setlocale(LC_TIME, NULL);
184     if (currentLocale == NULL) {
185         ThrowMsg(ConversionException, "Couldn't get current locale.");
186     }
187     DPL::ScopedFree<char> currentLocaleCopy(strdup(currentLocale));
188     if (setlocale(LC_TIME, "C") == NULL) {
189         ThrowMsg(ConversionException, "Couldn't set POSIX locale.");
190     }
191     if (strptime(stringDate.c_str(), "%a %b %d %Y %T", &result) == NULL) {
192         ThrowMsg(ConversionException, "Couldn't convert supplied date.");
193     }
194     if (setlocale(LC_TIME, currentLocaleCopy.Get()) == NULL) {
195         ThrowMsg(ConversionException, "Couldn't set previous locale back.");
196     }
197     //strptime function doesn't affect tm_isdst flag.
198     //It may cause -1hr conversion error. Setting it to -1 informs that
199     //there is no information about daylight saving time.
200     result.tm_isdst = -1;
201     return result;
202 }
203
204 std::vector<unsigned char> Converter::toVectorOfUChars(const JSValueRef& arg)
205 {
206     return toVectorOfT_(arg, &Converter::toUChar);
207 }
208
209 std::vector<char> Converter::toVectorOfChars(const JSValueRef& arg)
210 {
211     return toVectorOfT_(arg, &Converter::toChar);
212 }
213
214 std::vector<int> Converter::toVectorOfInts(const JSValueRef& arg)
215 {
216     return toVectorOfT_(arg, &Converter::toInt);
217 }
218
219 std::vector<std::string> Converter::toVectorOfStrings(const JSValueRef& arg)
220 {
221     return toVectorOfT_(arg, &Converter::toString);
222 }
223
224 std::vector<time_t> Converter::toVectorOfTimeT(const JSValueRef& arg)
225 {
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 {
251     return JSValueMakeNumber(m_context, arg);
252 }
253
254 JSValueRef Converter::toJSValueRef(long long int arg)
255 {
256     return JSValueMakeNumber(m_context, arg);
257 }
258
259 JSValueRef Converter::toJSValueRef(double arg)
260 {
261     return JSValueMakeNumber(m_context, arg);
262 }
263
264 JSValueRef Converter::toJSValueRef(const std::string& arg)
265 {
266     JSValueRef result = NULL;
267     JSStringRef jsString = JSStringCreateWithUTF8CString(arg.c_str());
268     result = JSValueMakeString(m_context, jsString);
269     JSStringRelease(jsString);
270     return result;
271 }
272
273 JSValueRef Converter::toJSValueRef(const tm& arg)
274 {
275     JSValueRef args[6];
276     args[0] = JSValueMakeNumber(m_context, arg.tm_year + 1900);
277     args[1] = JSValueMakeNumber(m_context, arg.tm_mon);
278     args[2] = JSValueMakeNumber(m_context, arg.tm_mday);
279     args[3] = JSValueMakeNumber(m_context, arg.tm_hour);
280     args[4] = JSValueMakeNumber(m_context, arg.tm_min);
281     args[5] = JSValueMakeNumber(m_context, arg.tm_sec);
282
283     JSValueRef exception = NULL;
284     JSObjectRef result = JSObjectMakeDate(m_context, 6, args, &exception);
285     if (NULL != exception) {
286         ThrowMsg(ConversionException, "Couldn't convert to a JS Date.");
287     }
288
289     return result;
290 }
291
292 JSValueRef Converter::toJSValueRef(const time_t arg)
293 {
294     struct tm tminfo;
295     memset(&tminfo,0,sizeof(tminfo));
296     localtime_r(&arg, &tminfo);
297     return toJSValueRef(tminfo);
298 }
299
300 JSValueRef Converter::toJSValueRef(const std::vector<std::string>& arg)
301 {
302     return toJSValueRef_(arg);
303 }
304
305 JSValueRef Converter::toJSValueRef(const char* arg)
306 {
307     return toJSValueRef(std::string(arg));
308 }
309
310 JSValueRef Converter::toJSValueRef(const std::vector<int>& arg)
311 {
312     return toJSValueRef_(arg);
313 }
314
315 JSValueRef Converter::toJSValueRef(const std::vector<time_t>& arg)
316 {
317     return toJSValueRef_(arg);
318 }
319
320 JSValueRef Converter::toJSValueRef(JSValueRef arg)
321 {
322     return arg;
323 }
324
325 JSValueRef Converter::toJSValueRef(const std::vector<JSValueRef>& arg)
326 {
327     return toJSValueRef_(arg);
328 }
329
330 JSStringRef Converter::toJSStringRef(const std::string& arg)
331 {
332     return JSStringCreateWithUTF8CString(arg.c_str());
333 }
334
335 double Converter::toNumber_(const JSStringRef& arg)
336 {
337     return toNumber_(toString(arg));
338 }
339
340 double Converter::toNumber_(const std::string& arg)
341 {
342     double result;
343     std::stringstream ss(arg);
344     if (!(ss >> result)) {
345         Throw(ConversionException);
346     }
347     return result;
348 }
349
350 double Converter::toNumber_(const JSValueRef& arg)
351 {
352     JSValueRef exception = NULL;
353     double result = JSValueToNumber(m_context, arg, &exception);
354     if (NULL != exception) {
355         ThrowMsg(ConversionException, "Couldn't convert to a number.");
356     }
357     return result;
358 }
359
360 std::string Converter::toString_(const JSValueRef& arg)
361 {
362     std::string result;
363
364     JSValueRef exception = NULL;
365     JSStringRef str = JSValueToStringCopy(m_context, arg, &exception);
366     if (NULL == str) {
367         ThrowMsg(ConversionException, "Couldn't cast to a string.");
368     }
369
370     size_t jsSize = JSStringGetMaximumUTF8CStringSize(str);
371     if (jsSize > 0) {
372         DPL::ScopedArray<char> buffer(new char[jsSize]);
373         JSStringGetUTF8CString(str, buffer.Get(), jsSize);
374         result = buffer.Get();
375     }
376     JSStringRelease(str);
377     return result;
378 }
379
380 bool Converter::isNan(double value) const
381 {
382     // This should work unless -ffast-math (GCC) option is used.
383     STATIC_CHECK(std::numeric_limits<double>::is_iec559,
384                  NOT_IEEE754_REPRESENTATION);
385     return (value != value);
386 }
387 } // CommonsJavaScript
388 } // WrtDeviceApis
389