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