9a637c6ec690b9f539c1b61340f8e9e307b1a7cd
[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     JSObjectRef timeobj = NULL;
158     timeobj = JSUtil::JSValueToObject(ctx, value);
159     JSValueRef exception = NULL;
160     JSObjectRef getTime = NULL;
161     try{
162         getTime = JSUtil::JSValueToObject(ctx, getProperty(ctx, timeobj, "getTime"));
163     }catch( const TypeMismatchException& err){
164         throw TypeMismatchException("Value is not Date Object");
165     }
166
167     JSValueRef timevalue = JSObjectCallAsFunction(ctx, getTime, timeobj, 0, NULL, &exception);
168     if( exception != NULL )
169         throw TypeMismatchException("Value is not Date Object");
170
171     double millisecond = JSValueToDouble(ctx, timevalue);
172     time_t second = millisecond/1000;
173     return second;
174 }
175
176 JSObjectRef JSUtil::JSValueToObject(JSContextRef ctx, JSValueRef value){
177     JSValueRef exception = NULL;
178     JSObjectRef obj = ::JSValueToObject(ctx, value,&exception);
179     if( exception != NULL){
180         throw TypeMismatchException(ctx, exception);
181     }
182     return obj;
183 }
184
185 std::map<std::string, std::string> JSUtil::JSValueToStringMap(JSContextRef ctx, JSValueRef value){
186     std::map<std::string, std::string> result;
187     JSObjectRef obj = JSUtil::JSValueToObject(ctx, value);
188     JSPropertyNameArrayRef jsPropNames = JSObjectCopyPropertyNames(ctx, obj);
189     for (std::size_t i = 0; i < JSPropertyNameArrayGetCount(jsPropNames); ++i) {
190         std::string propName = JSUtil::JSStringToString(ctx, JSPropertyNameArrayGetNameAtIndex(jsPropNames, i));
191         std::string propValue = JSUtil::JSValueToString(ctx, JSUtil::getProperty(ctx, obj, propName.c_str(), NULL));
192         result.insert(std::make_pair(propName, propValue));
193     }
194     JSPropertyNameArrayRelease(jsPropNames);
195     return result;
196 }
197
198 JSObjectRef JSUtil::makeDateObject(JSContextRef ctx, const time_t value){
199     JSValueRef exception = NULL;
200     JSValueRef args[1];
201     double millisecond = value*1000.0;
202     args[0] = toJSValueRef(ctx, millisecond);
203     JSObjectRef result = JSObjectMakeDate(ctx, 1, args, &exception);
204     if( exception != NULL){
205         throw TypeMismatchException("Can't create Date object");
206     }
207     return result;
208 }
209
210
211 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const string& str){
212     JSValueRef result = NULL;
213     JSStringRef jsString = JSStringCreateWithUTF8CString(str.c_str());
214     result = JSValueMakeString(ctx, jsString);
215     JSStringRelease(jsString);
216     return result;
217 }
218
219 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const unsigned long value){
220     return JSValueMakeNumber(ctx, value);
221 }
222
223 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const long value){
224     return JSValueMakeNumber(ctx, value);
225 }
226
227 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const unsigned long long value) {
228     return JSValueMakeNumber(ctx, value);
229 }
230
231 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const long long value) {
232     return JSValueMakeNumber(ctx, value);
233 }
234
235 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const double value){
236     return JSValueMakeNumber(ctx, value);
237 }
238
239 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const signed char value){
240     return JSValueMakeNumber(ctx, value);
241 }
242
243 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const unsigned char value){
244     return JSValueMakeNumber(ctx, value);
245 }
246
247
248 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const bool value){
249     return JSValueMakeBoolean(ctx, value);
250 }
251
252 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const std::vector<std::string>& value){
253     return toJSValueRef_(ctx, value);
254 }
255
256 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const std::vector<long>& value){
257     return toJSValueRef_(ctx, value);
258 }
259
260 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const std::vector<double>& value){
261     return toJSValueRef_(ctx, value);
262 }
263
264 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const std::vector<bool>& value){
265     return toJSValueRef_(ctx, value);
266 }
267
268 JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const std::map<std::string, std::string>& value){
269     JSObjectRef obj = JSObjectMake(ctx, NULL, NULL);
270
271     std::map<std::string, std::string>::const_iterator iter;
272     for (iter = value.begin(); iter != value.end(); ++iter) {
273         std::string propName = iter->first;
274         JSUtil::setProperty(ctx, obj, propName.c_str(), JSUtil::toJSValueRef(ctx, iter->second), kJSPropertyAttributeNone);
275     }
276
277     return obj;
278 }
279
280 vector<string> JSUtil::JSArrayToStringVector(JSContextRef ctx, JSValueRef value){
281     return JSArrayToType_<string>(ctx, value, JSUtil::JSValueToString);
282 }
283 vector<double> JSUtil::JSArrayToDoubleVector(JSContextRef ctx, JSValueRef value){
284     return JSArrayToType_<double>(ctx, value, JSUtil::JSValueToDouble);
285 }
286 vector<long> JSUtil::JSArrayToLongVector(JSContextRef ctx, JSValueRef value){
287     return JSArrayToType_<long>(ctx, value, JSUtil::JSValueToLong);
288 }
289 vector<time_t> JSUtil::JSArrayToTimeTVector(JSContextRef ctx, JSValueRef value){
290     return JSArrayToType_<time_t>(ctx, value, JSUtil::JSValueToTimeT);
291 }
292 vector<bool> JSUtil::JSArrayToBoolVector(JSContextRef ctx, JSValueRef value){
293     return JSArrayToType_<bool>(ctx, value, JSUtil::JSValueToBoolean);
294 }
295
296
297 }
298 }