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