Update change log and spec for wrt-plugins-tizen_0.4.49
[framework/web/wrt-plugins-tizen.git] / src / Common / JSUtil.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 #include "JSUtil.h"
19 #include "PlatformException.h"
20 #include <cmath>
21 #include <limits>
22
23
24 using namespace std;
25
26 namespace DeviceAPI {
27 namespace Common{
28
29 JSValueRef JSUtil::getProperty(JSContextRef ctx , JSObjectRef object, const char *name, JSValueRef *exception){
30     JSValueRef value;
31     JSStringRef propertyName = JSStringCreateWithUTF8CString(name);
32     JSValueRef localException = NULL;
33     value = JSObjectGetProperty(ctx, object, propertyName, &localException);
34     JSStringRelease(propertyName);
35
36     if( localException != NULL ){
37         if( exception != NULL )
38             *exception = localException;
39         else
40             throw TypeMismatchException(ctx,localException);
41     }
42     return value;
43 }
44
45 void JSUtil::setProperty(JSContextRef ctx , JSObjectRef object, const char *name, JSValueRef value, JSPropertyAttributes attributes, JSValueRef *exception){
46     JSStringRef propertyName = JSStringCreateWithUTF8CString(name);
47     JSValueRef localException = NULL;
48     JSObjectSetProperty(ctx, object, propertyName, value,attributes, &localException);
49     JSStringRelease(propertyName);
50     if( localException != NULL ){
51         if( exception != NULL )
52             *exception = localException;
53         else
54             throw TypeMismatchException(ctx,localException);
55     }
56 }
57
58 string JSUtil::JSStringToString(JSContextRef ctx, JSStringRef str){
59     std::string result;
60     size_t jsSize = JSStringGetMaximumUTF8CStringSize(str);
61     {
62         char buffer[jsSize];
63         JSStringGetUTF8CString(str, buffer, jsSize);
64         result = buffer;
65     }
66     return result;
67 }
68
69 string JSUtil::JSValueToString(JSContextRef ctx, JSValueRef value){
70     std::string result;
71     JSValueRef exception = NULL;
72     JSStringRef str = JSValueToStringCopy(ctx, value, &exception);
73     if (exception != NULL) {
74         throw TypeMismatchException(ctx, exception);
75     }
76     size_t jsSize = JSStringGetMaximumUTF8CStringSize(str);
77     {
78         char buffer[jsSize];
79         JSStringGetUTF8CString(str, buffer, jsSize);
80         result = buffer;
81     }
82     JSStringRelease(str);
83     return result;
84 }
85
86 long JSUtil::JSValueToLong(JSContextRef ctx, JSValueRef value){
87     return static_cast<long>(JSValueToLongLong(ctx,value));
88 }
89
90 unsigned long JSUtil::JSValueToULong(JSContextRef ctx, JSValueRef value){
91     double number = JSValueToNumber(ctx, value);
92     if( number < 0 )
93         return static_cast<unsigned long>(static_cast<long>(number));
94     return static_cast<unsigned long>(number);
95 }
96
97
98 long long JSUtil::JSValueToLongLong(JSContextRef ctx, JSValueRef value){
99     return static_cast<long long>(JSValueToNumber(ctx, value));
100 }
101
102 unsigned long long JSUtil::JSValueToULongLong(JSContextRef ctx, JSValueRef value){
103     double number = JSValueToNumber(ctx, value);
104     if( number < 0 )
105         return static_cast<unsigned long long>(static_cast<long long>(number));
106     return static_cast<unsigned long long>(number);
107 }
108
109
110
111 double JSUtil::JSValueToDouble(JSContextRef ctx, JSValueRef value){
112     JSValueRef exception = NULL;
113
114     double doublevalue = ::JSValueToNumber(ctx, value, &exception);
115     if(exception != NULL){
116         throw TypeMismatchException(ctx, exception);
117     }
118     if( doublevalue == std::numeric_limits<double>::infinity() )
119         throw TypeMismatchException("Value is POSITIVE_INFINITY");
120     if( doublevalue == -std::numeric_limits<double>::infinity() )
121         throw TypeMismatchException("Value is NEGATIVE_INFINITY");
122     if( std::isnan(doublevalue)){
123         throw TypeMismatchException("Value is not number");
124     }
125     return doublevalue;
126 }
127
128 double JSUtil::JSValueToNumber(JSContextRef ctx, JSValueRef value){
129     JSValueRef exception = NULL;
130
131     double doublevalue = ::JSValueToNumber(ctx, value, &exception);
132     if(exception != NULL){
133         throw TypeMismatchException(ctx, exception);
134     }
135     if( doublevalue == std::numeric_limits<double>::infinity() )
136         doublevalue = 0.0;
137
138     if( doublevalue == -std::numeric_limits<double>::infinity() )
139         doublevalue = 0.0;
140
141     return doublevalue;
142 }
143
144 signed char JSUtil::JSValueToByte(JSContextRef ctx, JSValueRef value){
145     return static_cast<signed char>(JSValueToNumber(ctx,value));
146 }
147
148 unsigned char JSUtil::JSValueToOctet(JSContextRef ctx, JSValueRef value){
149     return static_cast<unsigned char>(JSValueToNumber(ctx,value));
150 }
151
152 bool JSUtil::JSValueToBoolean(JSContextRef ctx, JSValueRef value){
153     return ::JSValueToBoolean(ctx, value);
154 }
155
156 time_t JSUtil::JSValueToTimeT(JSContextRef ctx, JSValueRef value){
157     if(!JSValueIsDateObject(ctx, value))
158         throw TypeMismatchException("Value is not Date Object");
159
160     JSObjectRef timeobj = NULL;
161     timeobj = JSUtil::JSValueToObject(ctx, value);
162     JSValueRef exception = NULL;
163     JSObjectRef getTime = NULL;
164     try{
165         getTime = JSUtil::JSValueToObject(ctx, getProperty(ctx, timeobj, "getTime"));
166     }catch( const TypeMismatchException& err){
167         throw TypeMismatchException("Value is not Date Object");
168     }
169
170     JSValueRef timevalue = JSObjectCallAsFunction(ctx, getTime, timeobj, 0, NULL, &exception);
171     if( exception != NULL )
172         throw TypeMismatchException("Value is not Date Object");
173
174     double millisecond = JSValueToDouble(ctx, timevalue);
175     time_t second = millisecond/1000;
176     return second;
177 }
178
179 tm JSUtil::JSValueToDateTm(JSContextRef ctx, JSValueRef value){
180     tm result = {0};
181
182     time_t second = JSUtil::JSValueToTimeT(ctx, value);
183
184         if(localtime_r(&second, &result) == NULL)
185                 throw TypeMismatchException("Value is not Date Object");
186
187     return result;
188 }
189
190 tm JSUtil::JSValueToDateTmUTC(JSContextRef ctx, JSValueRef value){
191     tm result = {0};
192
193     time_t second = JSUtil::JSValueToTimeT(ctx, value);
194
195         if(gmtime_r(&second, &result) == NULL)
196                 throw TypeMismatchException("Value is not Date Object");
197
198     return result;
199 }
200
201 JSObjectRef JSUtil::JSValueToObject(JSContextRef ctx, JSValueRef value){
202     JSValueRef exception = NULL;
203     JSObjectRef obj = ::JSValueToObject(ctx, value,&exception);
204     if( exception != NULL){
205         throw TypeMismatchException(ctx, exception);
206     }
207     return obj;
208 }
209
210 std::map<std::string, std::string> JSUtil::JSValueToStringMap(JSContextRef ctx, JSValueRef value){
211     std::map<std::string, std::string> result;
212     JSObjectRef obj = JSUtil::JSValueToObject(ctx, value);
213     JSPropertyNameArrayRef jsPropNames = JSObjectCopyPropertyNames(ctx, obj);
214     for (std::size_t i = 0; i < JSPropertyNameArrayGetCount(jsPropNames); ++i) {
215         std::string propName = JSUtil::JSStringToString(ctx, JSPropertyNameArrayGetNameAtIndex(jsPropNames, i));
216         std::string propValue = JSUtil::JSValueToString(ctx, JSUtil::getProperty(ctx, obj, propName.c_str(), NULL));
217         result.insert(std::make_pair(propName, propValue));
218     }
219     JSPropertyNameArrayRelease(jsPropNames);
220     return result;
221 }
222
223 JSObjectRef JSUtil::makeDateObject(JSContextRef ctx, const time_t value){
224     JSValueRef exception = NULL;
225     JSValueRef args[1];
226     double millisecond = value*1000.0;
227     args[0] = toJSValueRef(ctx, millisecond);
228     JSObjectRef result = JSObjectMakeDate(ctx, 1, args, &exception);
229     if( exception != NULL){
230         throw TypeMismatchException("Can't create Date object");
231     }
232     return result;
233 }
234
235
236 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const string& str){
237     JSValueRef result = NULL;
238     JSStringRef jsString = JSStringCreateWithUTF8CString(str.c_str());
239     result = JSValueMakeString(ctx, jsString);
240     JSStringRelease(jsString);
241     return result;
242 }
243
244 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const unsigned long value){
245     return JSValueMakeNumber(ctx, value);
246 }
247
248 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const long value){
249     return JSValueMakeNumber(ctx, value);
250 }
251
252 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const unsigned long long value) {
253     return JSValueMakeNumber(ctx, value);
254 }
255
256 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const long long value) {
257     return JSValueMakeNumber(ctx, value);
258 }
259
260 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const double value){
261     return JSValueMakeNumber(ctx, value);
262 }
263
264 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const signed char value){
265     return JSValueMakeNumber(ctx, value);
266 }
267
268 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const unsigned char value){
269     return JSValueMakeNumber(ctx, value);
270 }
271
272
273 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const bool value){
274     return JSValueMakeBoolean(ctx, value);
275 }
276
277 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const std::vector<std::string>& value){
278     return toJSValueRef_(ctx, value);
279 }
280
281 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const std::vector<long>& value){
282     return toJSValueRef_(ctx, value);
283 }
284
285 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const std::vector<double>& value){
286     return toJSValueRef_(ctx, value);
287 }
288
289 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const std::vector<bool>& value){
290     return toJSValueRef_(ctx, value);
291 }
292
293 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const std::map<std::string, std::string>& value){
294     JSObjectRef obj = JSObjectMake(ctx, NULL, NULL);
295
296     std::map<std::string, std::string>::const_iterator iter;
297     for (iter = value.begin(); iter != value.end(); ++iter) {
298         std::string propName = iter->first;
299         JSUtil::setProperty(ctx, obj, propName.c_str(), JSUtil::toJSValueRef(ctx, iter->second), kJSPropertyAttributeNone);
300     }
301
302     return obj;
303 }
304
305 vector<string> JSUtil::JSArrayToStringVector(JSContextRef ctx, JSValueRef value){
306     return JSArrayToType_<string>(ctx, value, JSUtil::JSValueToString);
307 }
308 vector<double> JSUtil::JSArrayToDoubleVector(JSContextRef ctx, JSValueRef value){
309     return JSArrayToType_<double>(ctx, value, JSUtil::JSValueToDouble);
310 }
311 vector<long> JSUtil::JSArrayToLongVector(JSContextRef ctx, JSValueRef value){
312     return JSArrayToType_<long>(ctx, value, JSUtil::JSValueToLong);
313 }
314 vector<time_t> JSUtil::JSArrayToTimeTVector(JSContextRef ctx, JSValueRef value){
315     return JSArrayToType_<time_t>(ctx, value, JSUtil::JSValueToTimeT);
316 }
317 vector<bool> JSUtil::JSArrayToBoolVector(JSContextRef ctx, JSValueRef value){
318     return JSArrayToType_<bool>(ctx, value, JSUtil::JSValueToBoolean);
319 }
320
321 bool JSUtil::JSValueIsDateObject(JSContextRef ctx, JSValueRef jsValue) {
322     JSValueRef exception = NULL;
323
324     JSObjectRef globalObj = JSContextGetGlobalObject(ctx);
325
326     JSValueRef jsDate = getProperty(ctx, globalObj, "Date", &exception);
327     if(exception)
328         return false;
329
330     JSObjectRef jsDateObj = ::JSValueToObject(ctx, jsDate, &exception);
331     if(exception)
332         return false;
333
334     bool result = JSValueIsInstanceOfConstructor(ctx, jsValue, jsDateObj, &exception);
335     if(exception)
336         return false;
337
338     return result;
339 }
340
341 }
342 }