Initialize Tizen 2.3
[framework/web/wrt-plugins-common.git] / src_wearable / 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     double tmp = toNumber_(arg);
55     return (isNan(tmp) ? 0 : static_cast<unsigned char>(static_cast<unsigned long>(static_cast<long long>(tmp))));
56 }
57
58 char Converter::toChar(const JSValueRef& arg)
59 {
60     double tmp = toNumber_(arg);
61     return (isNan(tmp) ? 0 : static_cast<char>(static_cast<long>(static_cast<long long>(tmp))));
62 }
63
64 int Converter::toInt(const JSValueRef& arg)
65 {
66     double tmp = toNumber_(arg);
67     return (isNan(tmp) ? 0 : static_cast<int>(static_cast<long long>(tmp)));
68 }
69
70 int Converter::toInt(const std::string &arg)
71 {
72     return static_cast<int>(static_cast<long long>(toNumber_(arg)));
73 }
74
75 long Converter::toLong(const JSValueRef& arg)
76 {
77     double tmp = toNumber_(arg);
78     return (isNan(tmp) ? 0 : static_cast<long>(static_cast<long long>(tmp)));
79 }
80
81 long long Converter::toLongLong(const JSValueRef& arg)
82 {
83     double tmp = toNumber_(arg);
84     return (isNan(tmp) ? 0 : static_cast<long long>(tmp));
85 }
86
87 unsigned long Converter::toULong(const JSValueRef& arg)
88 {
89     double tmp = toNumber_(arg);
90     return (isNan(tmp) ? 0 : static_cast<unsigned long>(static_cast<long long>(tmp)));
91 }
92
93 std::size_t Converter::toSizeT(const JSValueRef& arg)
94 {
95     double tmp = toNumber_(arg);
96     return (isNan(tmp) ? 0 : static_cast<std::size_t>(tmp));
97 }
98
99 std::size_t Converter::toSizeT(const JSStringRef& arg)
100 {
101     return static_cast<std::size_t>(toNumber_(arg));
102 }
103
104 double Converter::toDouble(const JSValueRef& arg)
105 {
106     return toNumber_(arg);
107 }
108
109 std::string Converter::toString(int arg)
110 {
111     return toString_(arg);
112 }
113
114 std::string Converter::toString(unsigned long arg)
115 {
116     return toString_(arg);
117 }
118
119 std::string Converter::toString(long arg)
120 {
121     return toString_(arg);
122 }
123
124 std::string Converter::toString(std::size_t arg)
125 {
126     return toString_(arg);
127 }
128
129 std::string Converter::toString(const JSValueRef& arg)
130 {
131     return toString_(arg);
132 }
133
134 std::string Converter::tryString(const JSValueRef& arg)
135 {
136     if (!JSValueIsString(m_context, arg) &&
137         !JSValueIsNumber(m_context, arg) &&
138         !JSValueIsBoolean(m_context, arg))
139     {
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 {
227     return toVectorOfT_(arg, &Converter::toDateTimeT);
228 }
229
230 JSValueRef Converter::toJSValueRef(bool arg)
231 {
232     return JSValueMakeBoolean(m_context, arg);
233 }
234
235 JSValueRef Converter::toJSValueRef(int arg)
236 {
237     return JSValueMakeNumber(m_context, arg);
238 }
239
240 JSValueRef Converter::toJSValueRef(unsigned int arg)
241 {
242     return JSValueMakeNumber(m_context, arg);
243 }
244
245 JSValueRef Converter::toJSValueRef(unsigned long arg)
246 {
247     return JSValueMakeNumber(m_context, arg);
248 }
249
250 JSValueRef Converter::toJSValueRefLong(const long arg)
251 {
252     return JSValueMakeNumber(m_context, arg);
253 }
254
255 JSValueRef Converter::toJSValueRef(long long int arg)
256 {
257     return JSValueMakeNumber(m_context, arg);
258 }
259
260 JSValueRef Converter::toJSValueRef(double arg)
261 {
262     return JSValueMakeNumber(m_context, arg);
263 }
264
265 JSValueRef Converter::toJSValueRef(const std::string& arg)
266 {
267     JSValueRef result = NULL;
268     JSStringRef jsString = JSStringCreateWithUTF8CString(arg.c_str());
269     result = JSValueMakeString(m_context, jsString);
270     JSStringRelease(jsString);
271     return result;
272 }
273
274 JSValueRef Converter::toJSValueRef(const tm& arg)
275 {
276     JSValueRef args[6];
277     args[0] = JSValueMakeNumber(m_context, arg.tm_year + 1900);
278     args[1] = JSValueMakeNumber(m_context, arg.tm_mon);
279     args[2] = JSValueMakeNumber(m_context, arg.tm_mday);
280     args[3] = JSValueMakeNumber(m_context, arg.tm_hour);
281     args[4] = JSValueMakeNumber(m_context, arg.tm_min);
282     args[5] = JSValueMakeNumber(m_context, arg.tm_sec);
283
284     JSValueRef exception = NULL;
285     JSObjectRef result = JSObjectMakeDate(m_context, 6, args, &exception);
286     if (NULL != exception) {
287         ThrowMsg(ConversionException, "Couldn't convert to a JS Date.");
288     }
289
290     return result;
291 }
292
293 JSValueRef Converter::toJSValueRef(const time_t arg)
294 {
295     struct tm tminfo;
296     memset(&tminfo,0,sizeof(tminfo));
297     localtime_r(&arg, &tminfo);
298     return toJSValueRef(tminfo);
299 }
300
301 JSValueRef Converter::toJSValueRef(const std::vector<std::string>& arg)
302 {
303     return toJSValueRef_(arg);
304 }
305
306 JSValueRef Converter::toJSValueRef(const char* arg)
307 {
308     return toJSValueRef(std::string(arg));
309 }
310
311 JSValueRef Converter::toJSValueRef(const std::vector<int>& arg)
312 {
313     return toJSValueRef_(arg);
314 }
315
316 JSValueRef Converter::toJSValueRef(const std::vector<time_t>& arg)
317 {
318     return toJSValueRef_(arg);
319 }
320
321 JSValueRef Converter::toJSValueRef(JSValueRef arg)
322 {
323     return arg;
324 }
325
326 JSValueRef Converter::toJSValueRef(const std::vector<JSValueRef>& arg)
327 {
328     return toJSValueRef_(arg);
329 }
330
331 JSStringRef Converter::toJSStringRef(const std::string& arg)
332 {
333     return JSStringCreateWithUTF8CString(arg.c_str());
334 }
335
336 double Converter::toNumber_(const JSStringRef& arg)
337 {
338     return toNumber_(toString(arg));
339 }
340
341 double Converter::toNumber_(const std::string& arg)
342 {
343     double result;
344     std::stringstream ss(arg);
345     if (!(ss >> result)) {
346         Throw(ConversionException);
347     }
348     return result;
349 }
350
351 double Converter::toNumber_(const JSValueRef& arg)
352 {
353     JSValueRef exception = NULL;
354     double result = JSValueToNumber(m_context, arg, &exception);
355     if (NULL != exception) {
356         ThrowMsg(ConversionException, "Couldn't convert to a number.");
357     }
358     return result;
359 }
360
361 std::string Converter::toString_(const JSValueRef& arg)
362 {
363     std::string result;
364
365     JSValueRef exception = NULL;
366     JSStringRef str = JSValueToStringCopy(m_context, arg, &exception);
367     if (NULL == str) {
368         ThrowMsg(ConversionException, "Couldn't cast to a string.");
369     }
370
371     size_t jsSize = JSStringGetMaximumUTF8CStringSize(str);
372     if (jsSize > 0) {
373         DPL::ScopedArray<char> buffer(new char[jsSize]);
374         JSStringGetUTF8CString(str, buffer.Get(), jsSize);
375         result = buffer.Get();
376     }
377     JSStringRelease(str);
378     return result;
379 }
380
381 bool Converter::isNan(double value) const
382 {
383     // This should work unless -ffast-math (GCC) option is used.
384     STATIC_CHECK(std::numeric_limits<double>::is_iec559,
385                  NOT_IEEE754_REPRESENTATION);
386     return (value != value);
387 }
388 } // CommonsJavaScript
389 } // WrtDeviceApis
390