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