sync with tizen_2.0
[platform/framework/native/appfw.git] / inc / FBaseColQueueT.h
1 //
2 // Open Service Platform
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  * @file                FBaseColQueueT.h
20  * @brief               This is the header file for the %QueueT class.
21  *
22  * This header file contains the declarations of the %QueueT class.
23  *
24  */
25 #ifndef _FBASE_COL_QUEUE_T_H_
26 #define _FBASE_COL_QUEUE_T_H_
27
28 #include <FBaseObject.h>
29 #include <FBaseResult.h>
30 #include <FBaseColICollectionT.h>
31
32
33 namespace Tizen { namespace Base { namespace Collection
34 {
35
36 template< class Type > class __QueueEnumeratorT;
37
38 /**
39  * @class       QueueT
40  * @brief       This represents a template-based queue (a first-in-first-out collection of objects).
41  *
42  * @since 2.0
43  *
44  * The %QueueT class represents a template-based queue (a first-in-first-out collection of objects).
45  *
46  * For more information on the class features, see <a href="../org.tizen.native.appprogramming/html/guide/base/queue_stack.htm">Stack and Queue</a>.
47  *
48  * The following example demonstrates how to use the %QueueT class.
49  *
50  * @code
51  *      #include <FBase.h>
52  *
53  *      using namespace Tizen::Base;
54  *      using namespace Tizen::Base::Collection;
55  *
56  *      void
57  *      MyClass::QueueTSample(void)
58  *      {
59  *              QueueT<String> queue;
60  *              queue.Construct();
61  *
62  *              String str1(L"First");
63  *              String str2(L"Second");
64  *              String str3(L"Third");
65  *
66  *              queue.Enqueue(str1);
67  *              queue.Enqueue(str2);
68  *              queue.Enqueue(str3);
69  *
70  *              // Reads the element at the beginning
71  *              String temp;
72  *              queue.Peek(temp);               // temp: "First", queue.GetCount(): 3
73  *
74  *              // Reads and removes the element at the beginning
75  *              queue.Dequeue(temp);    // temp: "First", queue.GetCount(): 2
76  *      }
77  * @endcode
78  */
79 template< class Type >
80 class QueueT
81         : public virtual ICollectionT< Type >
82         , public Object
83 {
84 public:
85         /**
86          * The object is not fully constructed after this constructor is called. For full construction, @n
87          * the Construct() method must be called right after calling this constructor.
88          *
89          * @since 2.0
90          */
91         QueueT(void)
92                 : __capacity(0)
93                 , __head(0)
94                 , __tail(0)
95                 , __pObjArray(null)
96                 , __modCount(0)
97         {
98         }
99
100         /**
101          * This destructor overrides Tizen::Base::Object::~Object().
102          *
103          * @since 2.0
104          */
105         virtual ~QueueT(void)
106         {
107                 __modCount++;
108                 RemoveAll();
109         }
110
111         /**
112          * Initializes this instance of %QueueT with the specified capacity.
113          *
114          * @since 2.0
115          *
116          * @return              An error code
117          * @param[in]   capacity                        The number of elements in the queue @n
118          *                                  The default capacity is @c 10.
119          * @exception   E_SUCCESS                       The method is successful.
120          * @exception   E_OUT_OF_MEMORY         The memory is insufficient.
121          * @exception   E_INVALID_ARG   The specified input parameter is invalid, or
122          *                                                                the specified @c capacity is negative.
123          */
124         result Construct(int capacity = DEFAULT_CAPACITY)
125         {
126                 TryReturn(capacity >= 0, E_INVALID_ARG, "[%s] The capacity(%d) MUST be greater than or equal to 0.", GetErrorMessage(E_INVALID_ARG), capacity);
127
128                 if (capacity > 0)
129                 {
130                         __pObjArray = new Type[capacity];
131                         TryReturn(__pObjArray != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
132                 }
133                 __capacity = capacity;
134
135                 return E_SUCCESS;
136         }
137
138         /**
139          * Initializes this instance of %QueueT that contains the elements of the specified @c collection. @n
140          * The capacity of the queue is the same as the number of elements copied.
141          *
142          * @since 2.0
143          *
144          * @return              An error code
145          * @param[in]   collection The collection to copy the elements from
146          * @exception   E_SUCCESS                       The method is successful.
147          * @exception   E_OUT_OF_MEMORY         The memory is insufficient.
148          * @exception   E_INVALID_OPERATION     The current state of the instance prohibits the execution of the specified operation, or
149          *                                                                      the @c collection is modified during the operation of this method.
150          * @see                 QueueT()
151          */
152         result Construct(const ICollectionT< Type >& collection)
153         {
154                 result r = E_SUCCESS;
155
156                 IEnumeratorT< Type >* pEnum = null;
157                 if (collection.GetCount() > 0)
158                 {
159                         ICollectionT< Type >* pCol = const_cast< ICollectionT< Type >* >(&collection);
160                         pEnum = pCol->GetEnumeratorN();
161                         TryCatch(pEnum != null, r = GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
162
163                         while (true)
164                         {
165                                 Type temp;
166                                 r = pEnum->MoveNext();
167
168                                 if (E_OUT_OF_RANGE == r)
169                                 {
170                                         r = E_SUCCESS;
171                                         break;
172                                 }
173                                 TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
174
175                                 r = pEnum->GetCurrent(temp);
176                                 TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
177
178                                 r = Enqueue(temp);
179                                 TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
180                         }
181                 }
182
183                 if (null != pEnum)
184                 {
185                         delete pEnum;
186                 }
187                 return r;
188
189 CATCH:
190                 RemoveAll();
191
192                 if (null != pEnum)
193                 {
194                         delete pEnum;
195                 }
196                 return r;
197         }
198
199         /**
200          * Reads and removes the element at the beginning of this queue.
201          *
202          * @since 2.0
203          *
204          * @return              An error code
205          * @param[out]  obj The element at the beginning of this queue
206          * @exception   E_SUCCESS       The method is successful.
207          * @exception   E_UNDERFLOW     The operation (arithmetic/casting/conversion) has caused an underflow, or
208          *                                                      this queue is empty.
209          * @see                 Enqueue()
210          */
211         virtual result Dequeue(Type& obj)
212         {
213                 if (__head <= __tail)
214                         return E_UNDERFLOW;
215
216                 __modCount++;
217                 int index = (__tail) % __capacity;
218                 obj = __pObjArray[index];
219
220                 __tail++;
221
222                 return E_SUCCESS;
223         }
224
225         /**
226          * Inserts an object at the end of this queue.
227          *
228          * @since 2.0
229          *
230          * @return              An error code
231          * @param[in]   obj The object to add to this queue
232          * @exception   E_SUCCESS               The method is successful.
233          * @exception   E_OUT_OF_MEMORY The memory is insufficient.
234          * @see                 Dequeue()
235          */
236         virtual result Enqueue(const Type& obj)
237         {
238                 if (null == __pObjArray)
239                 {
240                         __pObjArray = new Type[DEFAULT_CAPACITY];
241                         TryReturn(__pObjArray != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
242                         __capacity = DEFAULT_CAPACITY;
243                 }
244                 else if ((__head - __tail) >= __capacity)
245                 {
246                         Type* pArrayTemp = new Type[__capacity + DEFAULT_CAPACITY];
247                         TryReturn(pArrayTemp != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
248
249                         for (int i = 0, j = __tail; i < __capacity; i++, j++)
250                         {
251                                 pArrayTemp[i] = __pObjArray[j % __capacity];
252                         }
253
254                         delete[] __pObjArray;
255                         __pObjArray = pArrayTemp;
256                         __tail = 0;
257                         __head = __capacity;
258                         __capacity += DEFAULT_CAPACITY;
259                 }
260
261                 __modCount++;
262                 __pObjArray[__head % __capacity] = obj;
263                 __head++;
264
265                 return E_SUCCESS;
266         }
267
268         /**
269          * Removes all the elements in this queue.
270          *
271          * @since 2.0
272          */
273         virtual void RemoveAll(void)
274         {
275                 if (__pObjArray != null)
276                 {
277                         delete[] __pObjArray;
278                 }
279
280                 __pObjArray = null;
281
282                 __modCount++;
283                 __capacity = 0;
284                 __head = 0;
285                 __tail = 0;
286         }
287
288         /**
289          * Gets an enumerator of this queue.
290          *
291          * @since 2.0
292          *
293          * @return              An enumerator (an instance of the IEnumeratorT derived class) of this queue, @n
294          *                              else @c null if an exception occurs
295          * @exception   E_SUCCESS               The method is successful.
296          * @exception   E_OUT_OF_MEMORY The memory is insufficient.
297          * @remarks             The specific error code can be accessed using the GetLastResult() method.
298          * @see                 Tizen::Base::Collection::IEnumeratorT
299          */
300         virtual IEnumeratorT< Type >* GetEnumeratorN(void) const
301         {
302                 ClearLastResult();
303
304                 result r = E_SUCCESS;
305
306                 __QueueEnumeratorT< Type >* pEnum = new __QueueEnumeratorT< Type >(*this, __modCount);
307                 TryCatch(pEnum != null, r = E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
308
309                 return pEnum;
310
311 CATCH:
312                 SetLastResult(r);
313                 return null;
314         }
315
316         /**
317          * Reads the element at the beginning of this queue without removing it.
318          *
319          * @since 2.0
320          *
321          * @return              An error code
322          * @param[out]  obj The element at the beginning of this queue
323          * @exception   E_SUCCESS       The method is successful.
324          * @exception   E_UNDERFLOW     The operation (arithmetic/casting/conversion) has caused an underflow, or
325          *                                                      this queue is empty.
326          */
327         virtual result Peek(Type& obj) const
328         {
329                 if (__head <= __tail)
330                 {
331                         return E_UNDERFLOW;
332                 }
333
334                 obj = __pObjArray[__tail % __capacity];
335
336                 return E_SUCCESS;
337         }
338
339         /**
340          * Gets the number of objects currently stored in this queue.
341          *
342          * @since 2.0
343          *
344          * @return              The number of objects currently stored in this queue
345          */
346         virtual int GetCount(void) const
347         {
348                 return __head - __tail;
349         }
350
351         /**
352          * Checks whether this queue contains the specified object.
353          *
354          * @since 2.0
355          *
356          * @return              @c true if this queue contains the specified object, @n
357          *                              else @c false
358          * @param[in]   obj  The object to locate
359          */
360         virtual bool Contains(const Type& obj) const
361         {
362                 bool out = false;
363                 for (int i = 0; i < GetCount(); i++)
364                 {
365                         if (__pObjArray[(__tail + i) % __capacity] == obj)
366                         {
367                                 out = true;
368                                 break;
369                         }
370                 }
371
372                 return out;
373         }
374
375         /**
376          * Checks whether this queue contains all of the elements in the specified collection.
377          *
378          * @since 2.0
379          *
380          * @return              An error code
381          * @param[in]   collection      The collection to locate
382          * @param[out]  out  Set to @c true if this queue contains all of the elements in the specified collection, @n
383          *                                       else @c false
384          * @exception   E_SUCCESS                       The method is successful.
385          * @exception   E_INVALID_OPERATION     The current state of the instance prohibits the execution of the specified operation, or
386          *                                                                      the specified @c collection is modified during the operation of this method.
387          * @exception   E_OUT_OF_MEMORY         The memory is insufficient.
388          */
389         virtual result ContainsAll(const ICollectionT< Type >& collection, bool& out) const
390         {
391                 result r = E_SUCCESS;
392
393                 ICollectionT< Type >* pCol = const_cast< ICollectionT< Type >* >(&collection);
394                 IEnumeratorT< Type >* pEnum = pCol->GetEnumeratorN();
395                 TryCatch(pEnum != null, r = GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
396
397                 while (true)
398                 {
399                         Type temp;
400                         r = pEnum->MoveNext();
401
402                         if (E_OUT_OF_RANGE == r)
403                         {
404                                 r = E_SUCCESS;
405                                 out = true;
406                                 break;
407                         }
408                         TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
409
410                         r = pEnum->GetCurrent(temp);
411                         TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
412
413                         if (false == Contains(temp))
414                         {
415                                 out = false;
416                                 break;
417                         }
418                 }
419
420                 if (null != pEnum)
421                 {
422                         delete pEnum;
423                 }
424                 return r;
425
426 CATCH:
427                 if (null != pEnum)
428                 {
429                         delete pEnum;
430                 }
431                 return r;
432         }
433
434         /**
435          * Compares the specified instance to the current instance for equality.
436          *
437          * @since 2.0
438          *
439          * @return              @c true if the specified instance equals the current instance, @n
440          *                              else @c false
441          * @param[in]   obj The object to compare with the current instance
442          * @remarks             This method returns @c true if and only if the specified object is also an instance of %QueueT class,
443          *                              both queues have the same size, and all corresponding pairs of elements in the two queues are equal.
444          *                              In other words, two queues are equal if they contain the same elements in the same order.
445          */
446         virtual bool Equals(const Object& obj) const
447         {
448                 bool out = true;
449
450                 const QueueT< Type >* other = dynamic_cast< const QueueT< Type >* >(&obj);
451                 if (null == other)
452                 {
453                         out = false;
454                 }
455                 else if (other == this)
456                 {
457                         out = true;
458                 }
459                 else if (GetCount() != other->GetCount())
460                 {
461                         out = false;
462                 }
463                 else
464                 {
465                         for (int i = 0; i < GetCount(); i++)
466                         {
467                                 if (!(__pObjArray[(__tail + i) % __capacity] == other->__pObjArray[(other->__tail + i) % other->__capacity]))
468                                 {
469                                         out = false;
470                                         break;
471                                 }
472                         }
473                 }
474
475                 return out;
476         }
477
478         /**
479          * Gets the hash value of the current instance.
480          *
481          * @since 2.0
482          *
483          * @return      The hash value of the current instance
484          * @remarks     The two Tizen::Base::Object::Equals() instances must return the same hash value. For better performance, @n
485          *                      the used hash function must generate a random distribution for all inputs.
486          */
487         virtual int GetHashCode(void) const
488         {
489                 int hash = 0;
490                 int count = GetCount();
491                 for (int i = 0; i < count; i++)
492                 {
493                         if (&(__pObjArray[(__tail + i) % __capacity]) != null)
494                         {
495                                 hash += reinterpret_cast< int >(&(__pObjArray[(__tail + i) % __capacity]));
496                         }
497                 }
498                 return hash;
499         }
500
501 private:
502         /**
503          * The implementation of this copy constructor is intentionally blank and declared as private to prohibit copying of objects.
504          *
505          * @param[in]   queue The specified instance of %QueueT to initialize the current instance
506          */
507         QueueT(const QueueT< Type >& queue);
508
509         /**
510          * The implementation of this copy assignment operator is intentionally blank and declared as private to prohibit copying of objects.
511          *
512          * @param[in]   queue An instance of %QueueT
513          */
514         QueueT< Type >& operator =(const QueueT< Type >& queue);
515
516         int __capacity;
517         int __head;
518         int __tail;
519         Type* __pObjArray;
520         int __modCount;
521         static const int DEFAULT_CAPACITY = 10;
522
523         friend class __QueueEnumeratorT< Type >;
524
525 }; // QueueT
526
527 //
528 // @class       __QueueEnumeratorT
529 // @brief       This class is an implementation of IEnumeratorT for %QueueT.
530 // @since 2.0
531 //
532 template< class Type >
533 class __QueueEnumeratorT
534         : public IEnumeratorT< Type >
535         , public Object
536 {
537 public:
538         /**
539          * Initializes this instance of __QueueEnumeratorT with the specified parameters.
540          *
541          * @since 2.0
542          *
543          * @param[in]   queue           A queue to enumerate
544          * @param[in]   modeCount       The modification count to detect the change in the queue
545          */
546         __QueueEnumeratorT(const QueueT< Type >& queue, int modeCount)
547                 : __queue(queue)
548                 , __modCount(modeCount)
549                 , __position(-1)
550         {
551         }
552
553         /**
554          * This is the destructor for this class.
555          *
556          * @since 2.0
557          */
558         virtual ~__QueueEnumeratorT(void)
559         {
560         }
561
562         /**
563          * Gets the current object in the queue.
564          *
565          * @since 2.0
566          *
567          * @return              An error code
568          * @param[out]  obj The current object
569          * @exception   E_INVALID_OPERATION       Either of the following conditions has occurred: @n
570          *                                                                      - The current state of the instance prohibits the execution of the specified operation. @n
571          *                                                                      - This enumerator is currently positioned before the first element or
572          *                                                                      past the last element. @n
573          *                                                                      - The queue is modified after this enumerator is created.
574          * @exception   E_SUCCESS                       The method is successful.
575          */
576         result GetCurrent(Type& obj) const
577         {
578                 TryReturn((__modCount == __queue.__modCount), E_INVALID_OPERATION,
579                         "[%s] The source collection is modified after the creation of this enumerator.", GetErrorMessage(E_INVALID_OPERATION));
580                 TryReturn((__position >= __queue.__tail) && (__position < __queue.__head), E_INVALID_OPERATION,
581                         "[%s] Current position is before the first element or past the last element.", GetErrorMessage(E_INVALID_OPERATION));
582
583                 obj = __queue.__pObjArray[__position % __queue.__capacity];
584
585                 return E_SUCCESS;
586         }
587
588         /**
589          * Moves this enumerator to the next element of the queue. @n
590          * When this enumerator is first created or after the call to Reset(),
591          * the first call to MoveNext() positions this enumerator to the first element in the queue.
592          *
593          * @since 2.0
594          *
595          * @return              An error code
596          * @exception   E_SUCCESS                       The method is successful.
597          * @exception   E_INVALID_OPERATION     The current state of the instance prohibits the execution of the specified operation, or
598          *                                                                      the queue is modified after this enumerator is created.
599          * @exception   E_OUT_OF_RANGE          The enumerator has passed the end of the queue.
600          * @see                 Reset()
601          */
602         result MoveNext(void)
603         {
604                 TryReturn((__modCount == __queue.__modCount), E_INVALID_OPERATION,
605                         "[%s] The source collection is modified after the creation of this enumerator.", GetErrorMessage(E_INVALID_OPERATION));
606
607                 if ((__position + 1) >= __queue.__head)
608                 {
609                         return E_OUT_OF_RANGE;
610                 }
611                 else
612                 {
613                         if (__position == -1)
614                         {
615                                 __position = __queue.__tail;
616                         }
617                         else
618                         {
619                                 __position++;
620                         }
621                 }
622
623                 return E_SUCCESS;
624         }
625
626         /**
627          * Positions this enumerator before the first element in the queue.
628          *
629          * @since 2.0
630          *
631          * @return              An error code
632          * @exception   E_SUCCESS                       The method is successful.
633          * @exception   E_INVALID_OPERATION     The current state of the instance prohibits the execution of the specified operation, or
634          *                                                                      the queue is modified after this enumerator is created.
635          */
636         result Reset(void)
637         {
638                 TryReturn((__modCount == __queue.__modCount), E_INVALID_OPERATION,
639                         "[%s] The source collection is modified after the creation of this enumerator.", GetErrorMessage(E_INVALID_OPERATION));
640
641                 __position = -1;
642
643                 return E_SUCCESS;
644         }
645
646 private:
647         const QueueT< Type >& __queue;
648         int __modCount;
649         int __position;
650
651 }; // __QueueEnumeratorT
652
653 }}} // Tizen::Base::Collection
654
655 #endif //_FBASE_COL_QUEUE_T_H_