Update change log and spec for wrt-plugins-tizen_0.4.12-1
[framework/web/wrt-plugins-tizen.git] / src / Calendar / JSNumberArray.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 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
19 #include <algorithm>
20 #include <sstream>
21 #include <dpl/log/log.h>
22 #include <CommonsJavaScript/Converter.h>
23 #include <CommonsJavaScript/ScopedJSStringRef.h>
24 #include <JSTizenExceptionFactory.h>
25 #include <JSTizenException.h>
26 #include <CommonsJavaScript/Converter.h>
27 #include "JSNumberArray.h"
28
29 #define FUNCTION_CONCAT "concat"
30 #define FUNCTION_JOIN "join"
31 #define FUNCTION_POP "pop"
32 #define FUNCTION_PUSH "push"
33 #define FUNCTION_REVERSE "reverse"
34 #define FUNCTION_SHIFT "shift"
35 #define FUNCTION_SLICE "slice"
36 #define FUNCTION_SORT "sort"
37 #define FUNCTION_SPLICE "splice"
38 #define FUNCTION_TOSTRING "toString"
39 #define FUNCTION_UNSHIFT "unshift"
40 #define FUNCTION_VALUEOF "valueOf"
41 #define ARRAY "Array"
42 #define ATTRIBUTE_LENGTH "length"
43
44 namespace DeviceAPI {
45 namespace Calendar {
46
47
48 using namespace DeviceAPI::Common;
49 using namespace WrtDeviceApis::CommonsJavaScript;
50
51 JSClassDefinition JSNumberArray::m_classInfo = {
52         0,
53         kJSClassAttributeNone,
54         ARRAY,
55         0,
56         m_property,
57         m_function,
58         initialize,
59         finalize,
60         hasProperty,
61         getProperty,
62         setProperty,
63         NULL, //deleteProperty,
64         getPropertyNames,
65         NULL, //callAsFunction,
66         NULL, //callAsConstructor,
67         NULL, //hasInstance,
68         NULL, //convertToType,
69 };
70
71 JSStaticValue JSNumberArray::m_property[] = {
72         { ATTRIBUTE_LENGTH, getLength, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete },
73         { 0, 0, 0, 0 }
74 };
75
76 JSStaticFunction JSNumberArray::m_function[] = {
77         { FUNCTION_CONCAT, concat, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete },
78         { FUNCTION_JOIN, join, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete },
79         { FUNCTION_POP, pop, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete },
80         { FUNCTION_PUSH, push, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete },
81         { FUNCTION_REVERSE, reverse, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete },
82         { FUNCTION_SHIFT, shift, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete },
83         { FUNCTION_SLICE, slice, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete },
84         { FUNCTION_SORT, sort, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete },
85         { FUNCTION_SPLICE, splice, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete },
86         { FUNCTION_TOSTRING, toString, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete },
87         { FUNCTION_UNSHIFT, unshift, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete },
88         { FUNCTION_VALUEOF, valueOf, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete },
89         { 0, 0, 0 }
90 };
91
92 JSClassRef JSNumberArray::m_jsClassRef = JSClassCreate(
93                 JSNumberArray::getClassInfo());
94
95 JSValueRef JSNumberArray::getLength(JSContextRef context,
96                 JSObjectRef object,
97                 JSStringRef propertyName,
98                 JSValueRef* exception)
99 {
100         Try
101         {
102                 JSNumberArrayPriv* priv =
103                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(object));
104                 if (!priv) {
105                         Throw(WrtDeviceApis::Commons::NullPointerException);
106                 }
107                 NumberArrayPtr numbers = priv->getObject();
108                 if (numbers) {
109                         WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
110                                         WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
111                         return converter->toJSValueRef(numbers->size());
112                 }
113         }
114         Catch(WrtDeviceApis::Commons::Exception)
115         {
116                 LogError("invalid conversion");
117         }
118         return JSValueMakeUndefined(context);
119 }
120
121 JSObjectRef JSNumberArray::createArray(JSContextRef context,
122                 const NumberArrayPtr &numbers)
123 {
124         JSNumberArrayPriv *priv = new JSNumberArrayPriv(context, numbers);
125         return JSObjectMake(context, getClassRef(), priv);
126 }
127
128 const JSClassDefinition* JSNumberArray::getClassInfo()
129 {
130         return &(m_classInfo);
131 }
132
133 JSClassRef JSNumberArray::getClassRef()
134 {
135         if (!m_jsClassRef) {
136                 m_jsClassRef = JSClassCreate(&m_classInfo);
137         }
138         return m_jsClassRef;
139 }
140
141 bool JSNumberArray::isObjectOfClass(JSContextRef context, JSValueRef value)
142 {
143         return JSValueIsObjectOfClass(context, value, getClassRef());
144 }
145
146 NumberArrayPtr JSNumberArray::getNumberArray(JSContextRef context, JSValueRef value)
147 {
148         if (!isObjectOfClass(context, value)) {
149                 Throw(WrtDeviceApis::Commons::InvalidArgumentException);
150         }
151         JSObjectRef object = JSValueToObject(context, value, NULL);
152         if (!object) {
153                 Throw(WrtDeviceApis::Commons::InvalidArgumentException);
154         }
155         JSNumberArrayPriv* priv = static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(object));
156         if (!priv) {
157                 Throw(WrtDeviceApis::Commons::NullPointerException);
158         }
159         return priv->getObject();
160 }
161
162 void JSNumberArray::initialize(JSContextRef context,
163                 JSObjectRef object)
164 {
165 }
166
167 void JSNumberArray::finalize(JSObjectRef object)
168 {
169         JSNumberArrayPriv* priv =
170                 static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(object));
171         delete priv;
172         JSObjectSetPrivate(object, NULL);
173 }
174
175 bool JSNumberArray::hasProperty(JSContextRef context,
176                 JSObjectRef object,
177                 JSStringRef propertyName)
178 {
179         WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
180                         WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
181         Try
182         {
183                 size_t index = converter->toSizeT(propertyName);
184                 JSNumberArrayPriv* priv =
185                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(object));
186                 if (!priv) {
187                         Throw(WrtDeviceApis::Commons::NullPointerException);
188                 }
189                 NumberArrayPtr numbers = priv->getObject();
190                 if (index < numbers->size()) {
191                         return true;
192                 }
193         }
194         Catch(WrtDeviceApis::Commons::Exception)
195         {
196                 //not reporting error is intended
197         }
198         return false;
199 }
200
201 JSValueRef JSNumberArray::getProperty(JSContextRef context,
202                 JSObjectRef object,
203                 JSStringRef propertyName,
204                 JSValueRef* exception)
205 {
206         WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
207                         WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
208
209         Try
210         {
211                 size_t index = converter->toSizeT(propertyName);
212                 JSNumberArrayPriv* priv =
213                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(object));
214                 if (!priv) {
215                         Throw(WrtDeviceApis::Commons::NullPointerException);
216                 }
217                 NumberArrayPtr numbers = priv->getObject();
218                 if (index < numbers->size()) {
219                         long long int result = numbers->at(index);
220             LogInfo("index: "<<index<<", result: "<<result);
221             return converter->toJSValueRef(result);
222                 }
223         }
224         Catch(WrtDeviceApis::Commons::Exception)
225         {
226                 LogError("invalid property");
227         }
228         return JSValueMakeUndefined(context);
229 }
230
231 bool JSNumberArray::setProperty(JSContextRef context,
232                 JSObjectRef object,
233                 JSStringRef propertyName,
234                 JSValueRef value,
235                 JSValueRef* exception)
236 {
237         WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
238                         WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
239
240         Try
241         {
242                 size_t index = converter->toSizeT(propertyName);
243                 long long int number = 0;
244                 if (!JSValueIsUndefined(context, value)) {
245                         number = converter->toLongLong(value);
246                 }
247                 JSNumberArrayPriv* priv =
248                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(object));
249                 if (!priv) {
250                         Throw(WrtDeviceApis::Commons::NullPointerException);
251                 }
252                 NumberArrayPtr numbers = priv->getObject();
253                 if (!numbers) {
254                         Throw(WrtDeviceApis::Commons::NullPointerException);
255                 }
256                 if (numbers->size() <= index) {
257                         numbers->resize(index + 1);
258                 }
259                 (*numbers)[index] = number;
260                 return true;
261         }
262         Catch(WrtDeviceApis::Commons::Exception)
263         {
264                 LogError("error occured");
265                 JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch");
266         }
267         return false;
268 }
269
270 void JSNumberArray::getPropertyNames(JSContextRef context,
271                 JSObjectRef object,
272                 JSPropertyNameAccumulatorRef propertyNames)
273 {
274     Converter converter(context);
275
276         Try
277         {
278                 JSNumberArrayPriv* priv =
279                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(object));
280                 if (!priv) {
281                         Throw(WrtDeviceApis::Commons::NullPointerException);
282                 }
283                 NumberArrayPtr numbers = priv->getObject();
284
285                 int count = numbers->size();
286
287                 for(int i=0; i < count; i++)
288                 {
289                         ScopedJSStringRef name(converter.toJSStringRef(converter.toString(i)));
290                         JSPropertyNameAccumulatorAddName(propertyNames, name.get());
291                 }
292         }
293         Catch(WrtDeviceApis::Commons::Exception)
294         {
295                 LogError("invalid property");
296         }
297 }
298
299 JSValueRef JSNumberArray::concat(JSContextRef context,
300                 JSObjectRef function,
301                 JSObjectRef thisObject,
302                 size_t argumentCount,
303                 const JSValueRef arguments[],
304                 JSValueRef* exception)
305 {
306         Try
307         {
308                 NumberArrayPtr numbers = NumberArrayPtr(new NumberArray());
309                 JSNumberArrayPriv *newPrivateObject = new JSNumberArrayPriv(
310                                 context,
311                                 numbers);
312                 JSValueRef result = JSObjectMake(context,
313                                                                                  getClassRef(), newPrivateObject);
314
315                 //copy current numbers
316                 JSNumberArrayPriv* priv =
317                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(thisObject));
318                 NumberArrayPtr currentNumbers = priv->getObject();
319                 for (size_t i = 0; i < currentNumbers->size(); ++i) {
320                         numbers->push_back(currentNumbers->at(i));
321                 }
322
323                 //copy submitted arrays
324                 WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
325                                 WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
326                 for (size_t i = 0; i < argumentCount; ++i) {
327                         if (!JSIsArrayValue(context, arguments[i])) {
328                                 Throw(WrtDeviceApis::Commons::ConversionException);
329                         }
330                         // process array of numbers
331                         JSObjectRef arrayObj = converter->toJSObjectRef(arguments[i]);
332                         unsigned int len = JSGetArrayLength(context, arrayObj);
333                         for (unsigned int e = 0; e < len; ++e) {
334                                 JSValueRef att = JSGetArrayElement(context, arrayObj, e);
335                                 numbers->push_back(converter->toLong(att));
336                         }
337                 }
338                 return result;
339         }
340         Catch(WrtDeviceApis::Commons::Exception)
341         {
342                 LogError("error occured");
343         }
344         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch");
345 }
346
347 JSValueRef JSNumberArray::join(JSContextRef context,
348                 JSObjectRef function,
349                 JSObjectRef thisObject,
350                 size_t argumentCount,
351                 const JSValueRef arguments[],
352                 JSValueRef* exception)
353 {
354         Try
355         {
356                 std::string result;
357                 std::string separator(",");
358                 WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
359                                 WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
360                 JSNumberArrayPriv* priv = static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(thisObject));
361                 NumberArrayPtr currentNumbers = priv->getObject();
362                 if (argumentCount > 0 && JSValueIsString(context, arguments[0])) {
363                         separator = converter->toString(arguments[0]);
364                         LogDebug("Separator: "<<separator);
365                 }
366                 for (size_t i = 0; i < currentNumbers->size(); ++i) {
367                         if (i != 0) {
368                                 result += separator;
369                         }
370                         std::stringstream ss;
371                         ss<<currentNumbers->at(i);
372                         result += ss.str();
373                 }
374                 LogDebug("Resulting string: "<<result);
375                 return converter->toJSValueRef(result);
376         }
377         Catch(WrtDeviceApis::Commons::Exception)
378         {
379                 LogError("error occured");
380         }
381         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch");
382 }
383
384 JSValueRef JSNumberArray::pop(JSContextRef context,
385                 JSObjectRef function,
386                 JSObjectRef thisObject,
387                 size_t argumentCount,
388                 const JSValueRef arguments[],
389                 JSValueRef* exception)
390 {
391         Try
392         {
393                 WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
394                                 WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
395                 JSNumberArrayPriv* priv =
396                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(thisObject));
397                 NumberArrayPtr currentNumbers = priv->getObject();
398                 if (currentNumbers->size() > 0) {
399                         long long int result = currentNumbers->at(
400                                         currentNumbers->size() - 1);
401                         currentNumbers->pop_back();
402                         return converter->toJSValueRef(result);
403                 }
404         }
405         Catch(WrtDeviceApis::Commons::Exception)
406         {
407                 LogError("error occured");
408         }
409         return JSValueMakeUndefined(context);
410 }
411
412 JSValueRef JSNumberArray::push(JSContextRef context,
413                 JSObjectRef function,
414                 JSObjectRef thisObject,
415                 size_t argumentCount,
416                 const JSValueRef arguments[],
417                 JSValueRef* exception)
418 {
419         Try
420         {
421                 WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
422                                 WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
423                 JSNumberArrayPriv* priv =
424                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(thisObject));
425                 NumberArrayPtr currentNumbers = priv->getObject();
426                 for (size_t i = 0; i < argumentCount; ++i) {
427                         currentNumbers->push_back(converter->toLong(arguments[i]));
428                 }
429                 return converter->toJSValueRef(currentNumbers->size());
430         }
431         Catch(WrtDeviceApis::Commons::Exception)
432         {
433                 LogError("error occured");
434         }
435         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch");
436 }
437
438 JSValueRef JSNumberArray::reverse(JSContextRef context,
439                 JSObjectRef function,
440                 JSObjectRef thisObject,
441                 size_t argumentCount,
442                 const JSValueRef arguments[],
443                 JSValueRef* exception)
444 {
445         Try
446         {
447                 WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
448                                 WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
449                 JSNumberArrayPriv* priv =
450                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(thisObject));
451                 NumberArrayPtr currentNumbers = priv->getObject();
452                 std::reverse(currentNumbers->begin(), currentNumbers->end());
453                 return thisObject;
454         }
455         Catch(WrtDeviceApis::Commons::Exception)
456         {
457                 LogError("error occured");
458         }
459         return JSValueMakeUndefined(context);
460 }
461
462 JSValueRef JSNumberArray::shift(JSContextRef context,
463                 JSObjectRef function,
464                 JSObjectRef thisObject,
465                 size_t argumentCount,
466                 const JSValueRef arguments[],
467                 JSValueRef* exception)
468 {
469         Try
470         {
471                 WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
472                                 WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
473                 JSNumberArrayPriv* priv =
474                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(thisObject));
475                 NumberArrayPtr currentNumbers = priv->getObject();
476                 if (currentNumbers->size() > 0) {
477                         long long int result = currentNumbers->at(0);
478                         currentNumbers->erase(currentNumbers->begin());
479                         return converter->toJSValueRef(result);
480                 }
481         }
482         Catch(WrtDeviceApis::Commons::Exception)
483         {
484                 LogError("error occured");
485         }
486         return JSValueMakeUndefined(context);
487 }
488
489 JSValueRef JSNumberArray::slice(JSContextRef context,
490                 JSObjectRef function,
491                 JSObjectRef thisObject,
492                 size_t argumentCount,
493                 const JSValueRef arguments[],
494                 JSValueRef* exception)
495 {
496         Try
497         {
498                 if (argumentCount < 1) {
499                         return JSValueMakeUndefined(context);
500                 }
501                 WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
502                                 WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
503                 NumberArrayPtr numbers = NumberArrayPtr(new NumberArray());
504                 JSNumberArrayPriv *newPrivateObject = new JSNumberArrayPriv(
505                                 context,
506                                 numbers);
507                 JSValueRef result = JSObjectMake(context,
508                                                                                  getClassRef(), newPrivateObject);
509
510                 //copy current numbers
511                 JSNumberArrayPriv* priv =
512                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(thisObject));
513                 NumberArrayPtr currentNumbers = priv->getObject();
514                 std::size_t first = converter->toSizeT(arguments[0]);
515                 std::size_t last = currentNumbers->size() - 1;
516                 if (argumentCount > 1) {
517                         last = converter->toSizeT(arguments[1]);
518                         if (last >= currentNumbers->size()) {
519                                 last = currentNumbers->size() - 1;
520                         }
521                 }
522                 for (size_t i = first; i <= last; ++i) {
523                         numbers->push_back(currentNumbers->at(i));
524                 }
525
526                 return result;
527         }
528         Catch(WrtDeviceApis::Commons::Exception)
529         {
530                 LogError("error occured");
531         }
532         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch");
533 }
534
535 JSValueRef JSNumberArray::sort(JSContextRef context,
536                 JSObjectRef function,
537                 JSObjectRef thisObject,
538                 size_t argumentCount,
539                 const JSValueRef arguments[],
540                 JSValueRef* exception)
541 {
542         Try
543         {
544                 WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
545                                 WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
546                 JSNumberArrayPriv* priv =
547                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(thisObject));
548                 NumberArrayPtr currentNumbers = priv->getObject();
549                 std::sort(currentNumbers->begin(), currentNumbers->end());
550                 return thisObject;
551         }
552         Catch(WrtDeviceApis::Commons::Exception)
553         {
554                 LogError("error occured");
555         }
556         return JSValueMakeUndefined(context);
557 }
558
559 JSValueRef JSNumberArray::splice(JSContextRef context,
560                 JSObjectRef function,
561                 JSObjectRef thisObject,
562                 size_t argumentCount,
563                 const JSValueRef arguments[],
564                 JSValueRef* exception)
565 {
566         return JSValueMakeUndefined(context);
567 }
568
569 JSValueRef JSNumberArray::toString(JSContextRef context,
570                 JSObjectRef function,
571                 JSObjectRef thisObject,
572                 size_t argumentCount,
573                 const JSValueRef arguments[],
574                 JSValueRef* exception)
575 {
576         return join(context, function, thisObject, 0, arguments, exception);
577 }
578
579 JSValueRef JSNumberArray::unshift(JSContextRef context,
580                 JSObjectRef function,
581                 JSObjectRef thisObject,
582                 size_t argumentCount,
583                 const JSValueRef arguments[],
584                 JSValueRef* exception)
585 {
586         return JSValueMakeUndefined(context);
587 }
588
589 JSValueRef JSNumberArray::valueOf(JSContextRef context,
590                 JSObjectRef function,
591                 JSObjectRef thisObject,
592                 size_t argumentCount,
593                 const JSValueRef arguments[],
594                 JSValueRef* exception)
595 {
596         return JSValueMakeUndefined(context);
597 }
598
599 } // Calendar
600 } // DeviceAPI