Update change log and spec for wrt-plugins-tizen_0.2.84
[framework/web/wrt-plugins-tizen.git] / src / standards / Tizen / Calendar / JSNumberArray.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17
18 #include <algorithm>
19 #include <dpl/log/log.h>
20 #include <CommonsJavaScript/Converter.h>
21 #include <CommonsJavaScript/ScopedJSStringRef.h>
22 #include <Tizen/Common/JSTizenExceptionFactory.h>
23 #include <Tizen/Common/JSTizenException.h>
24 #include "CalendarConverter.h"
25 #include "JSNumberArray.h"
26 #include <Tizen/TimeUtil/TimeUtilConverter.h>
27
28 #define FUNCTION_CONCAT "concat"
29 #define FUNCTION_JOIN "join"
30 #define FUNCTION_POP "pop"
31 #define FUNCTION_PUSH "push"
32 #define FUNCTION_REVERSE "reverse"
33 #define FUNCTION_SHIFT "shift"
34 #define FUNCTION_SLICE "slice"
35 #define FUNCTION_SORT "sort"
36 #define FUNCTION_SPLICE "splice"
37 #define FUNCTION_TOSTRING "toString"
38 #define FUNCTION_UNSHIFT "unshift"
39 #define FUNCTION_VALUEOF "valueOf"
40 #define ARRAY "Array"
41 #define ATTRIBUTE_LENGTH "length"
42
43 namespace TizenApis {
44 namespace Tizen1_0 {
45 namespace Calendar {
46
47 using namespace TizenApis::Api::Calendar;
48 using namespace TizenApis::Commons;
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     LogDebug("entered");
207         WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
208                         WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
209     TimeUtilConverter timeConverter(context);
210
211         Try
212         {
213                 size_t index = converter->toSizeT(propertyName);
214                 JSNumberArrayPriv* priv =
215                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(object));
216                 if (!priv) {
217                         Throw(WrtDeviceApis::Commons::NullPointerException);
218                 }
219                 NumberArrayPtr numbers = priv->getObject();
220                 if (index < numbers->size()) {
221                         long long int result = numbers->at(index);
222             LogInfo("index: "<<index<<", result: "<<result);
223             return timeConverter.toJSValueRefTZDate((double)(result*1000.0), "");
224                 }
225         }
226         Catch(WrtDeviceApis::Commons::Exception)
227         {
228                 LogError("invalid property");
229         }
230         return JSValueMakeUndefined(context);
231 }
232
233 bool JSNumberArray::setProperty(JSContextRef context,
234                 JSObjectRef object,
235                 JSStringRef propertyName,
236                 JSValueRef value,
237                 JSValueRef* exception)
238 {
239         WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
240                         WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
241     TimeUtilConverter timeConverter(context);
242
243         Try
244         {
245                 size_t index = converter->toSizeT(propertyName);
246                 long long int number = 0;
247                 if (!JSValueIsUndefined(context, value)) {
248                         number = timeConverter.getTimeInMilliseconds(value)/1000;
249                 }
250                 JSNumberArrayPriv* priv =
251                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(object));
252                 if (!priv) {
253                         Throw(WrtDeviceApis::Commons::NullPointerException);
254                 }
255                 NumberArrayPtr numbers = priv->getObject();
256                 if (!numbers) {
257                         Throw(WrtDeviceApis::Commons::NullPointerException);
258                 }
259                 if (numbers->size() <= index) {
260                         numbers->resize(index + 1);
261                 }
262                 (*numbers)[index] = number;
263                 return true;
264         }
265         Catch(WrtDeviceApis::Commons::Exception)
266         {
267                 LogError("error occured");
268                 JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch");
269         }
270         return false;
271 }
272
273 void JSNumberArray::getPropertyNames(JSContextRef context,
274                 JSObjectRef object,
275                 JSPropertyNameAccumulatorRef propertyNames)
276 {
277     CalendarConverter converter(context);
278
279         Try
280         {
281                 JSNumberArrayPriv* priv =
282                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(object));
283                 if (!priv) {
284                         Throw(WrtDeviceApis::Commons::NullPointerException);
285                 }
286                 NumberArrayPtr numbers = priv->getObject();
287
288                 int count = numbers->size();
289
290                 for(int i=0; i < count; i++)
291                 {
292                         ScopedJSStringRef name(converter.toJSStringRef(converter.toString(i)));
293                         JSPropertyNameAccumulatorAddName(propertyNames, name.get());
294                 }
295         }
296         Catch(WrtDeviceApis::Commons::Exception)
297         {
298                 LogError("invalid property");
299         }
300 }
301
302 JSValueRef JSNumberArray::concat(JSContextRef context,
303                 JSObjectRef function,
304                 JSObjectRef thisObject,
305                 size_t argumentCount,
306                 const JSValueRef arguments[],
307                 JSValueRef* exception)
308 {
309         Try
310         {
311                 NumberArrayPtr numbers = NumberArrayPtr(new NumberArray());
312                 JSNumberArrayPriv *newPrivateObject = new JSNumberArrayPriv(
313                                 context,
314                                 numbers);
315                 JSValueRef result = JSObjectMake(context,
316                                                                                  getClassRef(), newPrivateObject);
317
318                 //copy current numbers
319                 JSNumberArrayPriv* priv =
320                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(thisObject));
321                 NumberArrayPtr currentNumbers = priv->getObject();
322                 for (size_t i = 0; i < currentNumbers->size(); ++i) {
323                         numbers->push_back(currentNumbers->at(i));
324                 }
325
326                 //copy submitted arrays
327                 WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
328                                 WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
329                 for (size_t i = 0; i < argumentCount; ++i) {
330                         if (!JSIsArrayValue(context, arguments[i])) {
331                                 Throw(WrtDeviceApis::Commons::ConversionException);
332                         }
333                         // process array of numbers
334                         JSObjectRef arrayObj = converter->toJSObjectRef(arguments[i]);
335                         unsigned int len = JSGetArrayLength(context, arrayObj);
336                         for (unsigned int e = 0; e < len; ++e) {
337                                 JSValueRef att = JSGetArrayElement(context, arrayObj, e);
338                                 numbers->push_back(converter->toLong(att));
339                         }
340                 }
341                 return result;
342         }
343         Catch(WrtDeviceApis::Commons::Exception)
344         {
345                 LogError("error occured");
346         }
347         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch");
348 }
349
350 JSValueRef JSNumberArray::join(JSContextRef context,
351                 JSObjectRef function,
352                 JSObjectRef thisObject,
353                 size_t argumentCount,
354                 const JSValueRef arguments[],
355                 JSValueRef* exception)
356 {
357         Try
358         {
359                 std::string result;
360                 std::string separator(",");
361                 WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
362                                 WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
363                 JSNumberArrayPriv* priv =
364                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(thisObject));
365                 NumberArrayPtr currentNumbers = priv->getObject();
366                 if (argumentCount > 0 && JSValueIsNumber(context, arguments[0])) {
367                         separator = converter->toLong(arguments[0]);
368                 }
369                 for (size_t i = 0; i < currentNumbers->size(); ++i) {
370                         if (i != 0) {
371                                 result += separator;
372                         }
373                         result += currentNumbers->at(i);
374                 }
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                 if (first < 0) {
523                         first = 0;
524                 }
525                 for (size_t i = first; i <= last; ++i) {
526                         numbers->push_back(currentNumbers->at(i));
527                 }
528
529                 return result;
530         }
531         Catch(WrtDeviceApis::Commons::Exception)
532         {
533                 LogError("error occured");
534         }
535         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch");
536 }
537
538 JSValueRef JSNumberArray::sort(JSContextRef context,
539                 JSObjectRef function,
540                 JSObjectRef thisObject,
541                 size_t argumentCount,
542                 const JSValueRef arguments[],
543                 JSValueRef* exception)
544 {
545         Try
546         {
547                 WrtDeviceApis::CommonsJavaScript::BasicConverter converter =
548                                 WrtDeviceApis::CommonsJavaScript::BasicConverterFactory::getConverter(context);
549                 JSNumberArrayPriv* priv =
550                         static_cast<JSNumberArrayPriv*>(JSObjectGetPrivate(thisObject));
551                 NumberArrayPtr currentNumbers = priv->getObject();
552                 std::sort(currentNumbers->begin(), currentNumbers->end());
553                 return thisObject;
554         }
555         Catch(WrtDeviceApis::Commons::Exception)
556         {
557                 LogError("error occured");
558         }
559         return JSValueMakeUndefined(context);
560 }
561
562 JSValueRef JSNumberArray::splice(JSContextRef context,
563                 JSObjectRef function,
564                 JSObjectRef thisObject,
565                 size_t argumentCount,
566                 const JSValueRef arguments[],
567                 JSValueRef* exception)
568 {
569         return JSValueMakeUndefined(context);
570 }
571
572 JSValueRef JSNumberArray::toString(JSContextRef context,
573                 JSObjectRef function,
574                 JSObjectRef thisObject,
575                 size_t argumentCount,
576                 const JSValueRef arguments[],
577                 JSValueRef* exception)
578 {
579         return join(context, function, thisObject, 0, arguments, exception);
580 }
581
582 JSValueRef JSNumberArray::unshift(JSContextRef context,
583                 JSObjectRef function,
584                 JSObjectRef thisObject,
585                 size_t argumentCount,
586                 const JSValueRef arguments[],
587                 JSValueRef* exception)
588 {
589         return JSValueMakeUndefined(context);
590 }
591
592 JSValueRef JSNumberArray::valueOf(JSContextRef context,
593                 JSObjectRef function,
594                 JSObjectRef thisObject,
595                 size_t argumentCount,
596                 const JSValueRef arguments[],
597                 JSValueRef* exception)
598 {
599         return JSValueMakeUndefined(context);
600 }
601
602 } // Calendar
603 } // Tizen1_0
604 } // TizenApis