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