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_free.h>
19 #include "ScopedJSStringRef.h"
20 #include "Converter.h"
21 #include <dpl/log/log.h>
23 using namespace WrtDeviceApis::Commons;
25 namespace WrtDeviceApis {
26 namespace CommonsJavaScript {
27 Converter::Converter(JSContextRef context) : m_context(context)
30 Converter::~Converter()
33 JSObjectRef Converter::toJSObjectRef(const JSValueRef& arg)
36 Throw(NullPointerException);
38 JSValueRef exception = NULL;
39 JSObjectRef result = JSValueToObject(m_context, arg, &exception);
40 if ((NULL == result) || (NULL != exception)) {
41 ThrowMsg(ConversionException, "Couldn't convert to a JS Object.");
46 bool Converter::toBool(const JSValueRef& arg)
48 return JSValueToBoolean(m_context, arg);
51 unsigned char Converter::toUChar(const JSValueRef& arg)
53 double tmp = toNumber_(arg);
54 return (isNan(tmp) ? 0 : static_cast<unsigned char>(static_cast<unsigned long>(static_cast<long long>(tmp))));
57 char Converter::toChar(const JSValueRef& arg)
59 double tmp = toNumber_(arg);
60 return (isNan(tmp) ? 0 : static_cast<char>(static_cast<long>(static_cast<long long>(tmp))));
63 int Converter::toInt(const JSValueRef& arg)
65 double tmp = toNumber_(arg);
66 return (isNan(tmp) ? 0 : static_cast<int>(static_cast<long long>(tmp)));
69 int Converter::toInt(const std::string &arg)
71 return static_cast<int>(static_cast<long long>(toNumber_(arg)));
74 long Converter::toLong(const JSValueRef& arg)
76 double tmp = toNumber_(arg);
77 return (isNan(tmp) ? 0 : static_cast<long>(static_cast<long long>(tmp)));
80 long long Converter::toLongLong(const JSValueRef& arg)
82 double tmp = toNumber_(arg);
83 return (isNan(tmp) ? 0 : static_cast<long long>(tmp));
86 unsigned long Converter::toULong(const JSValueRef& arg)
88 double tmp = toNumber_(arg);
89 return (isNan(tmp) ? 0 : static_cast<unsigned long>(static_cast<long long>(tmp)));
92 std::size_t Converter::toSizeT(const JSValueRef& arg)
94 double tmp = toNumber_(arg);
95 return (isNan(tmp) ? 0 : static_cast<std::size_t>(tmp));
98 std::size_t Converter::toSizeT(const JSStringRef& arg)
100 return static_cast<std::size_t>(toNumber_(arg));
103 double Converter::toDouble(const JSValueRef& arg)
105 return toNumber_(arg);
108 std::string Converter::toString(int arg)
110 return toString_(arg);
113 std::string Converter::toString(unsigned long arg)
115 return toString_(arg);
118 std::string Converter::toString(long arg)
120 return toString_(arg);
123 std::string Converter::toString(std::size_t arg)
125 return toString_(arg);
128 std::string Converter::toString(const JSValueRef& arg)
130 return toString_(arg);
133 std::string Converter::tryString(const JSValueRef& arg)
135 if (!JSValueIsString(m_context, arg) &&
136 !JSValueIsNumber(m_context, arg) &&
137 !JSValueIsBoolean(m_context, arg))
139 ThrowMsg(ConversionException,
140 "Argument is not convertable to JS String.");
143 return toString_(arg);
146 std::string Converter::toDateString(const JSValueRef& arg)
148 if (!JSValueIsObject(m_context, arg)) {
149 ThrowMsg(ConversionException, "Argument is not JS Date.");
152 return toString_(arg);
155 std::string Converter::toString(const JSStringRef& arg)
158 size_t jsSize = JSStringGetMaximumUTF8CStringSize(arg);
161 std::unique_ptr<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.");
167 result = buffer.get();
173 time_t Converter::toDateTimeT(const JSValueRef& arg)
175 struct tm tm = toDateTm(arg);
179 tm Converter::toDateTm(const JSValueRef& arg)
181 using namespace std::placeholders;
183 std::string stringDate = toDateString(arg);
185 char* currentLocale = setlocale(LC_TIME, NULL);
186 if (currentLocale == NULL) {
187 ThrowMsg(ConversionException, "Couldn't get current locale.");
189 std::unique_ptr<char, void(*)(void*)> currentLocaleCopy(strdup(currentLocale), &free);
190 if (setlocale(LC_TIME, "C") == NULL) {
191 ThrowMsg(ConversionException, "Couldn't set POSIX locale.");
193 if (strptime(stringDate.c_str(), "%a %b %d %Y %T", &result) == NULL) {
194 ThrowMsg(ConversionException, "Couldn't convert supplied date.");
196 if (setlocale(LC_TIME, currentLocaleCopy.get()) == NULL) {
197 ThrowMsg(ConversionException, "Couldn't set previous locale back.");
199 //strptime function doesn't affect tm_isdst flag.
200 //It may cause -1hr conversion error. Setting it to -1 informs that
201 //there is no information about daylight saving time.
202 result.tm_isdst = -1;
206 std::vector<unsigned char> Converter::toVectorOfUChars(const JSValueRef& arg)
208 return toVectorOfT_(arg, &Converter::toUChar);
211 std::vector<char> Converter::toVectorOfChars(const JSValueRef& arg)
213 return toVectorOfT_(arg, &Converter::toChar);
216 std::vector<int> Converter::toVectorOfInts(const JSValueRef& arg)
218 return toVectorOfT_(arg, &Converter::toInt);
221 std::vector<std::string> Converter::toVectorOfStrings(const JSValueRef& arg)
223 return toVectorOfT_(arg, &Converter::toString);
226 std::vector<time_t> Converter::toVectorOfTimeT(const JSValueRef& arg)
228 return toVectorOfT_(arg, &Converter::toDateTimeT);
231 JSValueRef Converter::toJSValueRef(bool arg)
233 return JSValueMakeBoolean(m_context, arg);
236 JSValueRef Converter::toJSValueRef(int arg)
238 return JSValueMakeNumber(m_context, arg);
241 JSValueRef Converter::toJSValueRef(unsigned int arg)
243 return JSValueMakeNumber(m_context, arg);
246 JSValueRef Converter::toJSValueRef(unsigned long arg)
248 return JSValueMakeNumber(m_context, arg);
251 JSValueRef Converter::toJSValueRefLong(const long arg)
253 return JSValueMakeNumber(m_context, arg);
256 JSValueRef Converter::toJSValueRef(long long int arg)
258 return JSValueMakeNumber(m_context, arg);
261 JSValueRef Converter::toJSValueRef(double arg)
263 return JSValueMakeNumber(m_context, arg);
266 JSValueRef Converter::toJSValueRef(const std::string& arg)
268 JSValueRef result = NULL;
269 JSStringRef jsString = JSStringCreateWithUTF8CString(arg.c_str());
270 result = JSValueMakeString(m_context, jsString);
271 JSStringRelease(jsString);
275 JSValueRef Converter::toJSValueRef(const tm& arg)
278 args[0] = JSValueMakeNumber(m_context, arg.tm_year + 1900);
279 args[1] = JSValueMakeNumber(m_context, arg.tm_mon);
280 args[2] = JSValueMakeNumber(m_context, arg.tm_mday);
281 args[3] = JSValueMakeNumber(m_context, arg.tm_hour);
282 args[4] = JSValueMakeNumber(m_context, arg.tm_min);
283 args[5] = JSValueMakeNumber(m_context, arg.tm_sec);
285 JSValueRef exception = NULL;
286 JSObjectRef result = JSObjectMakeDate(m_context, 6, args, &exception);
287 if (NULL != exception) {
288 ThrowMsg(ConversionException, "Couldn't convert to a JS Date.");
294 JSValueRef Converter::toJSValueRef(const time_t arg)
297 memset(&tminfo,0,sizeof(tminfo));
298 localtime_r(&arg, &tminfo);
299 return toJSValueRef(tminfo);
302 JSValueRef Converter::toJSValueRef(const std::vector<std::string>& arg)
304 return toJSValueRef_(arg);
307 JSValueRef Converter::toJSValueRef(const char* arg)
309 return toJSValueRef(std::string(arg));
312 JSValueRef Converter::toJSValueRef(const std::vector<int>& arg)
314 return toJSValueRef_(arg);
317 JSValueRef Converter::toJSValueRef(const std::vector<time_t>& arg)
319 return toJSValueRef_(arg);
322 JSValueRef Converter::toJSValueRef(JSValueRef arg)
327 JSValueRef Converter::toJSValueRef(const std::vector<JSValueRef>& arg)
329 return toJSValueRef_(arg);
332 JSStringRef Converter::toJSStringRef(const std::string& arg)
334 return JSStringCreateWithUTF8CString(arg.c_str());
337 double Converter::toNumber_(const JSStringRef& arg)
339 return toNumber_(toString(arg));
342 double Converter::toNumber_(const std::string& arg)
345 std::stringstream ss(arg);
346 if (!(ss >> result)) {
347 Throw(ConversionException);
352 double Converter::toNumber_(const JSValueRef& arg)
354 JSValueRef exception = NULL;
355 double result = JSValueToNumber(m_context, arg, &exception);
356 if (NULL != exception) {
357 ThrowMsg(ConversionException, "Couldn't convert to a number.");
362 std::string Converter::toString_(const JSValueRef& arg)
366 JSValueRef exception = NULL;
367 JSStringRef str = JSValueToStringCopy(m_context, arg, &exception);
369 ThrowMsg(ConversionException, "Couldn't cast to a string.");
372 size_t jsSize = JSStringGetMaximumUTF8CStringSize(str);
374 std::unique_ptr<char[]> buffer(new char[jsSize]);
375 JSStringGetUTF8CString(str, buffer.get(), jsSize);
376 result = buffer.get();
378 JSStringRelease(str);
382 bool Converter::isNan(double value) const
384 // This should work unless -ffast-math (GCC) option is used.
385 STATIC_CHECK(std::numeric_limits<double>::is_iec559,
386 NOT_IEEE754_REPRESENTATION);
387 return (value != value);
389 } // CommonsJavaScript