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