2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
24 using namespace WrtDeviceApis::Commons;
26 namespace WrtDeviceApis {
27 namespace CommonsJavaScript {
28 Converter::Converter(JSContextRef context) : m_context(context)
31 Converter::~Converter()
34 JSObjectRef Converter::toJSObjectRef(const JSValueRef& arg)
37 Throw(NullPointerException);
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.");
47 bool Converter::toBool(const JSValueRef& arg)
49 return JSValueToBoolean(m_context, arg);
52 unsigned char Converter::toUChar(const JSValueRef& arg)
54 double tmp = toNumber_(arg);
55 return (isNan(tmp) ? 0 : static_cast<unsigned char>(static_cast<unsigned long>(static_cast<long long>(tmp))));
58 char Converter::toChar(const JSValueRef& arg)
60 double tmp = toNumber_(arg);
61 return (isNan(tmp) ? 0 : static_cast<char>(static_cast<long>(static_cast<long long>(tmp))));
64 int Converter::toInt(const JSValueRef& arg)
66 double tmp = toNumber_(arg);
67 return (isNan(tmp) ? 0 : static_cast<int>(static_cast<long long>(tmp)));
70 int Converter::toInt(const std::string &arg)
72 return static_cast<int>(static_cast<long long>(toNumber_(arg)));
75 long Converter::toLong(const JSValueRef& arg)
77 double tmp = toNumber_(arg);
78 return (isNan(tmp) ? 0 : static_cast<long>(static_cast<long long>(tmp)));
81 long long Converter::toLongLong(const JSValueRef& arg)
83 double tmp = toNumber_(arg);
84 return (isNan(tmp) ? 0 : static_cast<long long>(tmp));
87 unsigned long Converter::toULong(const JSValueRef& arg)
89 double tmp = toNumber_(arg);
90 return (isNan(tmp) ? 0 : static_cast<unsigned long>(static_cast<long long>(tmp)));
93 std::size_t Converter::toSizeT(const JSValueRef& arg)
95 double tmp = toNumber_(arg);
96 return (isNan(tmp) ? 0 : static_cast<std::size_t>(tmp));
99 std::size_t Converter::toSizeT(const JSStringRef& arg)
101 return static_cast<std::size_t>(toNumber_(arg));
104 double Converter::toDouble(const JSValueRef& arg)
106 return toNumber_(arg);
109 std::string Converter::toString(int arg)
111 return toString_(arg);
114 std::string Converter::toString(unsigned long arg)
116 return toString_(arg);
119 std::string Converter::toString(long arg)
121 return toString_(arg);
124 std::string Converter::toString(std::size_t arg)
126 return toString_(arg);
129 std::string Converter::toString(const JSValueRef& arg)
131 return toString_(arg);
134 std::string Converter::tryString(const JSValueRef& arg)
136 if (!JSValueIsString(m_context, arg) &&
137 !JSValueIsNumber(m_context, arg) &&
138 !JSValueIsBoolean(m_context, arg))
140 ThrowMsg(ConversionException,
141 "Argument is not convertable to JS String.");
144 return toString_(arg);
147 std::string Converter::toDateString(const JSValueRef& arg)
149 if (!JSValueIsObject(m_context, arg)) {
150 ThrowMsg(ConversionException, "Argument is not JS Date.");
153 return toString_(arg);
156 std::string Converter::toString(const JSStringRef& arg)
159 size_t jsSize = JSStringGetMaximumUTF8CStringSize(arg);
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.");
168 result = buffer.Get();
174 time_t Converter::toDateTimeT(const JSValueRef& arg)
176 struct tm tm = toDateTm(arg);
180 tm Converter::toDateTm(const JSValueRef& arg)
182 std::string stringDate = toDateString(arg);
184 char* currentLocale = setlocale(LC_TIME, NULL);
185 if (currentLocale == NULL) {
186 ThrowMsg(ConversionException, "Couldn't get current locale.");
188 DPL::ScopedFree<char> currentLocaleCopy(strdup(currentLocale));
189 if (setlocale(LC_TIME, "C") == NULL) {
190 ThrowMsg(ConversionException, "Couldn't set POSIX locale.");
192 if (strptime(stringDate.c_str(), "%a %b %d %Y %T", &result) == NULL) {
193 ThrowMsg(ConversionException, "Couldn't convert supplied date.");
195 if (setlocale(LC_TIME, currentLocaleCopy.Get()) == NULL) {
196 ThrowMsg(ConversionException, "Couldn't set previous locale back.");
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;
205 std::vector<unsigned char> Converter::toVectorOfUChars(const JSValueRef& arg)
207 return toVectorOfT_(arg, &Converter::toUChar);
210 std::vector<char> Converter::toVectorOfChars(const JSValueRef& arg)
212 return toVectorOfT_(arg, &Converter::toChar);
215 std::vector<int> Converter::toVectorOfInts(const JSValueRef& arg)
217 return toVectorOfT_(arg, &Converter::toInt);
220 std::vector<std::string> Converter::toVectorOfStrings(const JSValueRef& arg)
222 return toVectorOfT_(arg, &Converter::toString);
225 std::vector<time_t> Converter::toVectorOfTimeT(const JSValueRef& arg)
227 return toVectorOfT_(arg, &Converter::toDateTimeT);
230 JSValueRef Converter::toJSValueRef(bool arg)
232 return JSValueMakeBoolean(m_context, arg);
235 JSValueRef Converter::toJSValueRef(int arg)
237 return JSValueMakeNumber(m_context, arg);
240 JSValueRef Converter::toJSValueRef(unsigned int arg)
242 return JSValueMakeNumber(m_context, arg);
245 JSValueRef Converter::toJSValueRef(unsigned long arg)
247 return JSValueMakeNumber(m_context, arg);
250 JSValueRef Converter::toJSValueRefLong(const long arg)
252 return JSValueMakeNumber(m_context, arg);
255 JSValueRef Converter::toJSValueRef(long long int arg)
257 return JSValueMakeNumber(m_context, arg);
260 JSValueRef Converter::toJSValueRef(double arg)
262 return JSValueMakeNumber(m_context, arg);
265 JSValueRef Converter::toJSValueRef(const std::string& arg)
267 JSValueRef result = NULL;
268 JSStringRef jsString = JSStringCreateWithUTF8CString(arg.c_str());
269 result = JSValueMakeString(m_context, jsString);
270 JSStringRelease(jsString);
274 JSValueRef Converter::toJSValueRef(const tm& arg)
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);
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.");
293 JSValueRef Converter::toJSValueRef(const time_t arg)
296 memset(&tminfo,0,sizeof(tminfo));
297 localtime_r(&arg, &tminfo);
298 return toJSValueRef(tminfo);
301 JSValueRef Converter::toJSValueRef(const std::vector<std::string>& arg)
303 return toJSValueRef_(arg);
306 JSValueRef Converter::toJSValueRef(const char* arg)
308 return toJSValueRef(std::string(arg));
311 JSValueRef Converter::toJSValueRef(const std::vector<int>& arg)
313 return toJSValueRef_(arg);
316 JSValueRef Converter::toJSValueRef(const std::vector<time_t>& arg)
318 return toJSValueRef_(arg);
321 JSValueRef Converter::toJSValueRef(JSValueRef arg)
326 JSValueRef Converter::toJSValueRef(const std::vector<JSValueRef>& arg)
328 return toJSValueRef_(arg);
331 JSStringRef Converter::toJSStringRef(const std::string& arg)
333 return JSStringCreateWithUTF8CString(arg.c_str());
336 double Converter::toNumber_(const JSStringRef& arg)
338 return toNumber_(toString(arg));
341 double Converter::toNumber_(const std::string& arg)
344 std::stringstream ss(arg);
345 if (!(ss >> result)) {
346 Throw(ConversionException);
351 double Converter::toNumber_(const JSValueRef& arg)
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.");
361 std::string Converter::toString_(const JSValueRef& arg)
365 JSValueRef exception = NULL;
366 JSStringRef str = JSValueToStringCopy(m_context, arg, &exception);
368 ThrowMsg(ConversionException, "Couldn't cast to a string.");
371 size_t jsSize = JSStringGetMaximumUTF8CStringSize(str);
373 DPL::ScopedArray<char> buffer(new char[jsSize]);
374 JSStringGetUTF8CString(str, buffer.Get(), jsSize);
375 result = buffer.Get();
377 JSStringRelease(str);
381 bool Converter::isNan(double value) const
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);
388 } // CommonsJavaScript