Implementation of ImmutableString
[platform/framework/native/appfw.git] / inc / FBaseColHashMapT.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                FBaseColHashMapT.h
19  * @brief               This is the header file for the %HashMapT class.
20  *
21  * This header file contains the declarations of the %HashMapT class.
22  */
23 #ifndef _FBASE_COL_HASH_MAP_T_H_
24 #define _FBASE_COL_HASH_MAP_T_H_
25
26 #include <FBaseObject.h>
27 #include <FBaseResult.h>
28 #include <FBaseColIComparerT.h>
29 #include <FBaseColIHashCodeProviderT.h>
30 #include <FBaseColIListT.h>
31 #include <FBaseColIMapT.h>
32 #include <FBaseColArrayListT.h>
33 #include <FBaseColMapEntryT.h>
34 #include <FBaseComparerT.h>
35 #include <FBaseFloat.h>
36
37 namespace Tizen { namespace Base { namespace Collection
38 {
39
40 template< class KeyType, class ValueType > class __HashMapEntryT;
41 template< class KeyType, class ValueType > class __HashMapEnumeratorT;
42 template< class KeyType > class __HashMapDefaultProviderT;
43
44 /**
45  * @class HashMapT
46  * @brief This class provides a template-based collection of associated keys and values
47  * that are organized based on the hash code of the key.
48  *
49  * @since 2.0
50  *
51  * The %HashMapT class provides a template-based collection of associated keys and values
52  * that are organized based on the hash code of the key.
53  * It contains unique keys and each key maps to one single value.
54  * The key and value cannot be a null reference. Several methods in the %HashMapT class need assignment (=) operators of KeyType and ValueType.
55  * @n
56  * For more information on the class features, see <a href="../org.tizen.native.appprogramming/html/guide/base/hashmap_multihashmap.htm">HashMap and MultiHashMap</a>.
57  *
58  * The following example demonstrates how to use the %HashMapT class.
59
60  * @code
61  *      #include <FBase.h>
62  *
63  *      using namespace Tizen::Base;
64  *      using namespace Tizen::Base::Collection;
65  *
66  *      void
67  *      MyClass::HashMapTSample(void)
68  *      {
69  *              HashMapT< int, int > map;
70  *
71  *              // Constructs a %HashMapT instance with default capacity, load factor, hash code provider, and comparer
72  *              map.Construct();
73  *
74  *              map.Add(1, 100);        // map.GetCount() : 1
75  *              map.Add(2, 200);        // map.GetCount() : 2
76  *              map.Add(3, 300);        // map.GetCount() : 3
77  *
78  *              int key;
79  *              int value;
80  *
81  *              // Gets a value with the specified key
82  *              key = 1;
83  *              map.GetValue(key, value);       // value : 100
84  *
85  *              // Removes the value with the specified key
86  *              map.Remove(key);
87  *
88  *              // Uses an enumerator to access elements in the map
89  *              IMapEnumeratorT< int, int >*    pMapEnum = map.GetMapEnumeratorN();
90  *              while (pMapEnum->MoveNext() == E_SUCCESS)
91  *              {
92  *                      pMapEnum->GetKey(key);
93  *                      pMapEnum->GetValue(value);
94  *              }
95  *
96  *              delete pMapEnum;
97  *      }
98  * @endcode
99  */
100 template< class KeyType, class ValueType >
101 class HashMapT
102         : public IMapT< KeyType, ValueType >
103         , public Object
104 {
105 public:
106         /**
107          * The object is not fully constructed after this constructor is called. For full construction, @n
108          * the Construct() method must be called right after calling this constructor.
109          *
110          * @since 2.0
111          */
112         HashMapT(void)
113                 : __pTable(null)
114                 , __count(0)
115                 , __capacity(0)
116                 , __loadFactor(0)
117                 , __threshold(0)
118                 , __pProvider(null)
119                 , __pComparer(null)
120                 , __defaultConstruct(false)
121                 , __modCount(0)
122         {
123         }
124
125         /**
126          * This destructor overrides Tizen::Base::Object::~Object().
127          *
128          * @since 2.0
129          */
130         virtual ~HashMapT(void)
131         {
132                 if (null != __pTable)
133                 {
134                         Reset();
135                         delete[] __pTable;
136                 }
137
138                 if (__defaultConstruct)
139                 {
140                         delete __pProvider;
141                         delete __pComparer;
142                 }
143
144         }
145
146         /**
147          * Initializes this instance of %HashMapT with the specified parameters.
148          *
149          * @since 2.0
150          *
151          * @return              An error code
152          * @param[in]   capacity                The initial capacity
153          * @param[in]   loadFactor              The maximum ratio of elements to buckets
154          * @exception   E_SUCCESS               The method is successful.
155          * @exception   E_INVALID_ARG   A specified input parameter is invalid, or
156          *                                                              the @c capacity or the @c loadFactor is negative.
157          * @remarks             To work properly, the key type must be of a primitive number type.
158          * @see                 HashMapT()
159          */
160         result Construct(int capacity = 16, float loadFactor = 0.75)
161         {
162                 TryReturn(capacity >= 0, E_INVALID_ARG, "[%s] The capacity(%d) MUST be greater than or equal to 0.", GetErrorMessage(E_INVALID_ARG), capacity);
163                 TryReturn(loadFactor >= 0, E_INVALID_ARG, "[%s] The loadFactor(%f) MUST be greater than or equal to 0.0.", GetErrorMessage(E_INVALID_ARG), loadFactor);
164
165                 result r = E_SUCCESS;
166
167                 if (capacity == 0)
168                 {
169                         __capacity = DEFAULT_CAPACITY;
170                 }
171                 else
172                 {
173                         __capacity = 1;
174                         while (__capacity < capacity)
175                         {
176                                 __capacity <<= 1;
177                         }
178                 }
179
180                 if (Float::Compare(loadFactor, 0) == 0)
181                 {
182                         __loadFactor = DEFAULT_LOAD_FACTOR;
183                 }
184                 else
185                 {
186                         __loadFactor = loadFactor;
187                 }
188
189                 __threshold = static_cast< int >(__capacity * __loadFactor);
190
191                 __pProvider = new __HashMapDefaultProviderT< KeyType >();
192                 TryCatch(__pProvider != null, r = E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
193
194                 __pComparer = new Tizen::Base::ComparerT< KeyType >();
195                 TryCatch(__pComparer != null, r = E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
196
197                 __defaultConstruct = true;
198
199                 __pTable = new __HashMapEntryT< KeyType, ValueType >*[__capacity];
200                 TryCatch(__pTable != null, r = E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
201
202                 memset(__pTable, null, sizeof(__HashMapEntryT< KeyType, ValueType >*) * __capacity);
203
204                 return r;
205
206 CATCH:
207                 __capacity = 0;
208                 delete __pProvider;
209                 delete __pComparer;
210
211                 return r;
212         }
213
214         /**
215          * Initializes this instance of %HashMapT by copying the elements of the specified @c map.
216          *
217          * @since 2.0
218          *
219          * @return              An error code
220          * @param[in]   map                     The map to copy
221          * @param[in]   loadFactor      The maximum ratio of elements to buckets
222          * @exception   E_SUCCESS                       The method is successful.
223          * @exception   E_INVALID_ARG           A specified input parameter is invalid, or
224          *                                                                      the @c loadFactor is negative.
225          * @exception   E_INVALID_OPERATION     The current state of the instance prohibits the execution of the specified operation, or
226          *                                                                      the @c map is modified during the operation of this method.
227          * @see                 HashMapT()
228          */
229         result Construct(const IMapT< KeyType, ValueType >& map, float loadFactor = 0.75)
230         {
231                 TryReturn(loadFactor >= 0, E_INVALID_ARG, "[%s] The loadFactor(%f) MUST be greater than or equal to 0.0.", GetErrorMessage(E_INVALID_ARG), loadFactor);
232
233                 result r = E_SUCCESS;
234
235                 if (Float::Compare(loadFactor, 0) == 0)
236                 {
237                         loadFactor = DEFAULT_LOAD_FACTOR;
238                 }
239
240                 int capacity = static_cast< int >(map.GetCount() / loadFactor) + 1;
241
242                 r = Construct(capacity, loadFactor);
243                 TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
244
245                 r = AddAll(map);
246                 TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
247
248                 return r;
249
250 CATCH:
251                 Reset();
252                 delete[] __pTable;
253                 __pTable = null;
254
255                 __capacity = 0;
256
257                 delete __pProvider;
258                 __pProvider = null;
259
260                 delete __pComparer;
261                 __pComparer = null;
262
263                 return r;
264         }
265
266         /**
267          * Initializes this instance of an empty %HashMapT class, with the specified initial capacity, load factor, hash code provider, and comparer.
268          *
269          * @since 2.0
270          *
271          * @return              An error code
272          * @param[in]   capacity        The initial capacity @n
273          *                                                      If it is @c 0, the default capacity (16) is used.
274          * @param[in]   loadFactor      The maximum ratio of the elements to buckets @n
275          *                                                      If it is @c 0, the default load factor (0.75) is used.
276          * @param[in]   provider        An instance of the IHashCodeProviderT-derived class that supplies the hash codes
277          *                                                      for all keys in this map
278          * @param[in]   comparer        An instance of the IComparerT-derived class to use when comparing keys
279          * @exception   E_SUCCESS               The method is successful.
280          * @exception   E_INVALID_ARG   Either of the following conditions has occurred: @n
281          *                                                              - A specified input parameter is invalid. @n
282          *                                                              - The specified @c capacity is negative. @n
283          *                                                              - The @c loadFactor is negative.
284          * @remarks             The instances of hash code provider and comparer will not be deallocated later from this map.
285          * @see                 HashMapT()
286          */
287         result Construct(int capacity, float loadFactor, const IHashCodeProviderT< KeyType >& provider,
288                                          const IComparerT< KeyType >& comparer)
289         {
290                 TryReturn(capacity >= 0, E_INVALID_ARG, "[%s] The capacity(%d) MUST be greater than or equal to 0.", GetErrorMessage(E_INVALID_ARG), capacity);
291                 TryReturn(loadFactor >= 0, E_INVALID_ARG, "[%s] The loadFactor(%f) MUST be greater than or equal to 0.0.", GetErrorMessage(E_INVALID_ARG), loadFactor);
292
293                 result r = E_SUCCESS;
294
295                 if (capacity == 0)
296                 {
297                         __capacity = DEFAULT_CAPACITY;
298                 }
299                 else
300                 {
301                         __capacity = 1;
302                         while (__capacity < capacity)
303                         {
304                                 __capacity <<= 1;
305                         }
306                 }
307
308                 if (Float::Compare(loadFactor, 0) == 0)
309                 {
310                         __loadFactor = DEFAULT_LOAD_FACTOR;
311                 }
312                 else
313                 {
314                         __loadFactor = loadFactor;
315                 }
316
317                 __threshold = static_cast< int >(__capacity * __loadFactor);
318
319                 __pProvider = const_cast< IHashCodeProviderT< KeyType >* >(&provider);
320
321                 __pComparer = const_cast< IComparerT< KeyType >* >(&comparer);
322
323                 __pTable = new __HashMapEntryT< KeyType, ValueType >*[__capacity];
324                 TryCatch(__pTable != null, r = E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
325
326                 memset(__pTable, null, sizeof(__HashMapEntryT< KeyType, ValueType >*) * __capacity);
327
328                 return r;
329
330 CATCH:
331                 __capacity = 0;
332                 __pProvider = null;
333                 __pComparer = null;
334
335                 return r;
336         }
337
338         /**
339          * Initializes this instance of %HashMapT by copying the elements of the specified @c map,
340          * with the specified load factor, hash code provider, and comparer.
341          *
342          * @since 2.0
343          *
344          * @return              An error code
345          * @param[in]   map                     The map to copy
346          * @param[in]   loadFactor      The maximum ratio of elements to buckets @n
347          *                                                      If it is @c 0, the default load factor (0.75) is used.
348          * @param[in]   provider        An instance of the IHashCodeProviderT-derived class that supplies the hash codes
349          *                                                      for all keys in this map
350          * @param[in]   comparer        An instance of the IComparerT-derived class to use when comparing keys
351          * @exception   E_SUCCESS                       The method is successful.
352          * @exception   E_INVALID_ARG           Either of the following conditions has occurred: @n
353          *                                                                      - A specified input parameter is invalid. @n
354          *                                                                      - The @c loadFactor is negative. @n
355          *                                                                      - The @c provider is a @c null or the @c comparer is a @c null.
356          * @exception   E_INVALID_OPERATION     The current state of the instance prohibits the execution of the specified operation, or
357          *                                                                      the @c map is modified during the operation of this method.
358          * @remarks             The instances of hash code provider and comparer will not be deallocated later from this map.
359          * @see                 HashMapT()
360          */
361         result Construct(const IMapT< KeyType, ValueType >& map, float loadFactor, const IHashCodeProviderT< KeyType >& provider,
362                                          const IComparerT< KeyType >& comparer)
363         {
364                 TryReturn((loadFactor >= 0), E_INVALID_ARG, "[%s] The loadFactor(%f) MUST be greater than or equal to 0.0.", GetErrorMessage(E_INVALID_ARG), loadFactor);
365
366                 result r = E_SUCCESS;
367                 if (Float::Compare(loadFactor, 0) == 0)
368                 {
369                         loadFactor = DEFAULT_LOAD_FACTOR;
370                 }
371
372                 int capacity = static_cast< int >(map.GetCount() / loadFactor) + 1;
373                 r = Construct(capacity, loadFactor, provider, comparer);
374                 TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
375
376                 r = AddAll(map);
377                 TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
378
379                 return r;
380
381 CATCH:
382                 Reset();
383                 delete[] __pTable;
384                 __pTable = null;
385
386                 __capacity = 0;
387                 __pProvider = null;
388                 __pComparer = null;
389
390                 return r;
391         }
392
393         /**
394          * Adds the specified key-value pair to a map.
395          *
396          * @since 2.0
397          *
398          * @return              An error code
399          * @param[in]   key             The key of the value to add
400          * @param[in]   value   The value to add
401          * @exception   E_SUCCESS                       The method is successful.
402          * @exception   E_INVALID_ARG           A specified input parameter is invalid, or
403          *                                                                      the comparer has failed to compare the keys.
404          * @exception   E_OBJ_ALREADY_EXIST     The specified @c key already exists.
405          * @see Remove()
406          */
407         virtual result Add(const KeyType& key, const ValueType& value)
408         {
409                 __HashMapEntryT< KeyType, ValueType >* pNewEntry;
410
411                 result r = E_SUCCESS;
412                 int hash = Hash(key);
413                 int i = hash & (__capacity - 1);
414                 bool out = false;
415
416                 r = ContainsKey(key, out);
417                 TryReturn((!out), E_OBJ_ALREADY_EXIST, "[%s] The key is already exist in this collection.", GetErrorMessage(E_OBJ_ALREADY_EXIST));
418                 TryReturn(r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
419
420                 r = E_SUCCESS;
421                 pNewEntry = new __HashMapEntryT< KeyType, ValueType >(key, value, __pTable[i], hash);
422                 TryReturn(pNewEntry != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
423                 __pTable[i] = pNewEntry;
424                 __modCount++;
425
426                 if (__count++ >= __threshold)
427                 {
428                         r = Resize(__capacity * 2);
429                         TryReturn(r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
430                 }
431
432                 return E_SUCCESS;
433         }
434
435         /**
436          * Gets the elements of a map in an instance of the IMapEnumeratorT-derived class.
437          *
438          * @since 2.0
439          *
440          * @return              An instance of the IMapEnumeratorT-derived class if successful, @n
441          *                              else @c null if an exception occurs
442          * @exception   E_SUCCESS               The method is successful.
443          * @exception   E_OUT_OF_MEMORY The memory is insufficient.
444          * @remarks             The specific error code can be accessed using the GetLastResult() method.
445          * @see                 Tizen::Base::Collection::IEnumerator
446          * @see                 Tizen::Base::Collection::IMapEnumerator
447          */
448         virtual IEnumeratorT< MapEntryT< KeyType, ValueType > >* GetEnumeratorN(void) const
449         {
450                 result r = E_SUCCESS;
451
452                 __HashMapEnumeratorT< KeyType, ValueType >* pEnum = new __HashMapEnumeratorT< KeyType, ValueType >(*this, __modCount);
453                 TryCatch(pEnum != null, r = E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
454
455                 SetLastResult(E_SUCCESS);
456                 return pEnum;
457
458 CATCH:
459                 SetLastResult(r);
460                 return null;
461         }
462
463         /**
464          * Gets the elements of a map in an instance of the IMapEnumeratorT class.
465          *
466          * @since 2.0
467          *
468          * @return              An instance of the IMapEnumeratorT class if successful, @n
469          *                              else @c null if an exception occurs
470          * @exception   E_SUCCESS               The method is successful.
471          * @exception   E_OUT_OF_MEMORY The memory is insufficient.
472          * @remarks             The specific error code can be accessed using the GetLastResult() method.
473          * @see                 Tizen::Base::Collection::IEnumerator
474          * @see                 Tizen::Base::Collection::IMapEnumerator
475          */
476         virtual IMapEnumeratorT< KeyType, ValueType >* GetMapEnumeratorN(void) const
477         {
478                 return dynamic_cast< IMapEnumeratorT< KeyType, ValueType >* >(GetEnumeratorN());
479         }
480
481         /**
482          * Gets the value associated with the specified @c key.
483          *
484          * @since 2.0
485          *
486          * @return              The value associated with the key, @n
487          *                              else @c null if an exception occurs
488          * @param[in]   key             The key to locate
489          * @param[out]  value   The value associated with the key
490          * @exception   E_SUCCESS                       The method is successful.
491          * @exception   E_INVALID_ARG           A specified input parameter is invalid, or
492          *                                                                      The comparer has failed to compare the keys.
493          * @exception   E_OBJ_NOT_FOUND         The specified @c key is not found in the map.
494          * @see                 SetValue()
495          */
496         virtual result GetValue(const KeyType& key, ValueType& value) const
497         {
498                 result r = E_OBJ_NOT_FOUND;
499
500                 int hash = Hash(key);
501                 int i = hash & (__capacity - 1);
502
503                 for (__HashMapEntryT< KeyType, ValueType >* pEntry = __pTable[i]; null != pEntry; pEntry = pEntry->pNext)
504                 {
505                         if (hash == pEntry->hash)
506                         {
507                                 int cmpResult;
508                                 r = __pComparer->Compare(key, pEntry->key, cmpResult);
509                                 TryReturn(r == E_SUCCESS, E_INVALID_ARG, "[%s] Propagating.", GetErrorMessage(r));
510
511                                 if (cmpResult == 0)
512                                 {
513                                         value = pEntry->value;
514                                         return E_SUCCESS;
515                                 }
516                         }
517                 }
518
519                 return E_OBJ_NOT_FOUND;
520         }
521
522         /**
523          * Gets the value associated with the specified @c key.
524          *
525          * @since 2.0
526          *
527          * @return              The value associated with the key, @n
528          *                              else @c null if an exception occurs
529          * @param[in]   key             The key to locate
530          * @param[out]  value   The value associated with the key
531          * @exception   E_SUCCESS                       The method is successful.
532          * @exception   E_INVALID_ARG           A specified input parameter is invalid, or
533          *                                                                      the comparer has failed to compare the keys.
534          * @exception   E_OBJ_NOT_FOUND         The specified @c key is not found in the map.
535          * @see                 SetValue()
536          */
537         virtual result GetValue(const KeyType& key, ValueType& value)
538         {
539                 return (static_cast< const HashMapT< KeyType, ValueType >* >(this))->GetValue(key, value);
540         }
541
542         /**
543          * Gets a list of all the keys in a map.
544          *
545          * @since 2.0
546          *
547          * @return              A pointer to an IListT object containing all the keys in the map, @n
548          *                              else @c null if an exception occurs
549          * @exception   E_SUCCESS               The method is successful.
550          * @exception   E_OUT_OF_MEMORY The memory is insufficient.
551          * @remarks             The order of the keys is the same as the corresponding values in the IListT interface returned by the GetValuesN() method.
552          * @remarks             The specific error code can be accessed using the GetLastResult() method.
553          * @see                 GetValuesN()
554          */
555         virtual IListT< KeyType >* GetKeysN(void) const
556         {
557                 result r = E_SUCCESS;
558
559                 ArrayListT< KeyType >* pList = new ArrayListT< KeyType >();
560                 TryCatch(pList != null, r = E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
561
562                 r = pList->Construct(__count);
563                 TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
564
565                 for (int i = 0; i < __capacity; i++)
566                 {
567                         for (__HashMapEntryT< KeyType, ValueType >* pEntry = __pTable[i]; null != pEntry; pEntry = pEntry->pNext)
568                         {
569                                 r = pList->Add(pEntry->key);
570                                 TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
571                         }
572                 }
573
574                 SetLastResult(E_SUCCESS);
575                 return pList;
576
577 CATCH:
578                 delete pList;
579
580                 SetLastResult(r);
581                 return null;
582         }
583
584         /**
585          * Gets all the values in a map.
586          *
587          * @since 2.0
588          *
589          * @return              A pointer to an IListT object containing all the values in the map, @n
590          *                              else @c null if an exception occurs
591          * @exception   E_SUCCESS               The method is successful.
592          * @exception   E_OUT_OF_MEMORY The memory is insufficient.
593          * @remarks             The specific error code can be accessed using the GetLastResult() method.
594          * @see                 GetKeysN()
595          */
596         virtual IListT< ValueType >* GetValuesN(void) const
597         {
598                 result r = E_SUCCESS;
599
600                 ArrayListT< ValueType >* pList = new ArrayListT< ValueType >();
601                 TryCatch(pList != null, r = E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
602
603                 r = pList->Construct(__count);
604                 TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
605
606                 for (int i = 0; i < __capacity; i++)
607                 {
608                         for (__HashMapEntryT< KeyType, ValueType >* pEntry = __pTable[i]; null != pEntry; pEntry = pEntry->pNext)
609                         {
610                                 r = pList->Add(pEntry->value);
611                                 TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
612                         }
613                 }
614
615                 SetLastResult(E_SUCCESS);
616                 return pList;
617
618 CATCH:
619                 delete pList;
620
621                 SetLastResult(r);
622                 return null;
623         }
624
625         /**
626          * Removes the value associated with the specified @c key.
627          *
628          * @since 2.0
629          *
630          * @return              An error code
631          * @param[in]   key The key to remove
632          * @exception   E_SUCCESS                       The method is successful.
633          * @exception   E_INVALID_ARG           The specified input parameter is invalid, or
634          *                                                                      the comparer has failed to compare the keys.
635          * @exception   E_OBJ_NOT_FOUND         The specified @c key is not found in the map.
636          * @see                 Add()
637          */
638         virtual result Remove(const KeyType& key)
639         {
640                 result r = E_OBJ_NOT_FOUND;
641                 int hash = Hash(key);
642                 int i = hash & (__capacity - 1);
643
644                 __HashMapEntryT< KeyType, ValueType >* pPrev = __pTable[i];
645                 for (__HashMapEntryT< KeyType, ValueType >* pEntry = __pTable[i]; null != pEntry; pEntry = pEntry->pNext)
646                 {
647                         if (hash == pEntry->hash)
648                         {
649                                 int cmpResult;
650                                 r = __pComparer->Compare(key, pEntry->key, cmpResult);
651                                 TryReturn(r == E_SUCCESS, E_INVALID_ARG, "[%s] Propagating.", GetErrorMessage(r));
652
653                                 if (cmpResult == 0)
654                                 {
655                                         __modCount++;
656                                         if (pPrev == pEntry)
657                                         {
658                                                 __pTable[i] = pEntry->pNext;
659                                         }
660                                         else
661                                         {
662                                                 pPrev->pNext = pEntry->pNext;
663                                         }
664
665                                         delete pEntry;
666                                         __count--;
667
668                                         return E_SUCCESS;
669                                 }
670                         }
671                         pPrev = pEntry;
672                 }
673
674                 return E_OBJ_NOT_FOUND;
675         }
676
677         /**
678          * Removes all key-value pairs in the map.
679          *
680          * @since 2.0
681          */
682         virtual void RemoveAll(void)
683         {
684                 if (__count > 0)
685                 {
686                         __modCount++;
687                         Reset();
688                         __count = 0;
689                 }
690         }
691
692         /**
693          * Replaces the value associated with the specified @c key with the specified new @c value.
694          *
695          * @since 2.0
696          *
697          * @return              An error code
698          * @param[in]   key             The key for which the value is to replace
699          * @param[in]   value   The new value to replace
700          * @exception   E_SUCCESS                       The method is successful.
701          * @exception   E_INVALID_ARG           A specified input parameter is invalid, or
702          *                                                                      the comparer has failed to compare the keys.
703          * @exception   E_OBJ_NOT_FOUND         The specified @c key is not found in the map.
704          * @remarks             Use the Add() method to add a new key-value pair.
705          * @see                 Add()
706          * @see                 GetValue()
707          */
708         virtual result SetValue(const KeyType& key, const ValueType& value)
709         {
710                 result r = E_SUCCESS;
711                 int hash = Hash(key);
712                 int i = hash & (__capacity - 1);
713
714                 int cmpResult = -1;
715                 for (__HashMapEntryT< KeyType, ValueType >* pEntry = __pTable[i]; null != pEntry; pEntry = pEntry->pNext)
716                 {
717                         if (hash == pEntry->hash)
718                         {
719                                 r = __pComparer->Compare(key, pEntry->key, cmpResult);
720                                 TryReturn(r == E_SUCCESS, E_INVALID_ARG, "[%s] Propagating.", GetErrorMessage(r));
721                                 if (cmpResult == 0)
722                                 {
723                                         pEntry->value = value;
724                                         break;
725                                 }
726                         }
727                 }
728
729                 if (cmpResult != 0)
730                 {
731                         r = E_OBJ_NOT_FOUND;
732                 }
733
734                 __modCount++;
735
736                 return r;
737         }
738
739         /**
740          * Gets the number of pairs currently stored in a map.
741          *
742          * @since 2.0
743          *
744          * @return              The pairs stored in the map
745          */
746         virtual int GetCount(void) const
747         {
748                 return __count;
749         }
750
751         /**
752          * Checks whether a map contains the specified @c key.
753          *
754          * @since 2.0
755          *
756          * @return              An error code
757          * @param[in]   key             The key to locate
758          * @param[out]  out     Set to @c true if the map contains the specified @c key, @n
759          *                                              else @c false
760          * @exception   E_SUCCESS                       The method is successful.
761          * @exception   E_INVALID_ARG           A specified input parameter is invalid, or
762          *                                                                      the comparer has failed to compare the keys.
763          * @see                 ContainsValue()
764          */
765         virtual result ContainsKey(const KeyType& key, bool& out) const
766         {
767                 out = false;
768
769                 result r = E_SUCCESS;
770                 int hash = Hash(key);
771                 int i = hash & (__capacity - 1);
772
773                 for (__HashMapEntryT< KeyType, ValueType >* pEntry = __pTable[i]; null != pEntry; pEntry = pEntry->pNext)
774                 {
775                         if (hash == pEntry->hash)
776                         {
777                                 int cmpResult;
778                                 r = __pComparer->Compare(key, pEntry->key, cmpResult);
779                                 TryReturn(r == E_SUCCESS, E_INVALID_ARG, "[%s] Propagating.", GetErrorMessage(r));
780
781                                 if (cmpResult == 0)
782                                 {
783                                         out = true;
784                                         break;
785                                 }
786                         }
787                 }
788
789                 return E_SUCCESS;
790         }
791
792         /**
793          * Checks whether a map contains the specified @c value.
794          *
795          * @since 2.0
796          *
797          * @return              @c true if the map contains the specified @c value, @n
798          *                              else @c false
799          * @param[in]   value   The value to locate
800          *
801          * @see                 ContainsKey()
802          */
803         virtual bool ContainsValue(const ValueType& value) const
804         {
805                 for (int i = 0; i < __capacity; i++)
806                 {
807                         for (__HashMapEntryT< KeyType, ValueType >* pEntry = __pTable[i]; null != pEntry; pEntry = pEntry->pNext)
808                         {
809                                 if (value == pEntry->value)
810                                 {
811                                         return true;
812                                 }
813                         }
814                 }
815
816                 return false;
817         }
818
819         /**
820          * Compares two instances of the %HashMapT class.
821          *
822          * @since 2.0
823          *
824          * @return              @c true if the two instances match, @n
825          *                              else @c false
826          * @param[in]   obj The object to compare with the current instance
827          * @remarks             This method returns @c true if and only if the two instances contain the same number of elements and all the elements of each other.
828          */
829         virtual bool Equals(const Object& obj) const
830         {
831                 const HashMapT< KeyType, ValueType >* other = dynamic_cast< const HashMapT< KeyType, ValueType >* >(&obj);
832                 if (null == other)
833                 {
834                         return false;
835                 }
836                 else if (other == this)
837                 {
838                         return true;
839                 }
840                 else if (__count != other->__count)
841                 {
842                         return false;
843                 }
844                 else
845                 {
846                         for (int i = 0; i < __capacity; i++)
847                         {
848                                 for (__HashMapEntryT< KeyType, ValueType >* pEntry = __pTable[i]; null != pEntry; pEntry = pEntry->pNext)
849                                 {
850                                         ValueType otherValue;
851                                         result r = other->GetValue(pEntry->key, otherValue);
852                                         if (IsFailed(r))
853                                         {
854                                                 return false;
855                                         }
856                                         if (pEntry->value != otherValue)
857                                         {
858                                                 return false;
859                                         }
860                                 }
861                         }
862                 }
863
864                 return true;
865         }
866
867         /**
868          * Gets the hash value of the current instance.
869          *
870          * @since 2.0
871          *
872          * @return      The hash value of the current instance
873          * @remarks     The two Tizen::Base::Object::Equals() instances must return the same hash value. For better performance, @n
874          *                      the used hash function must generate a random distribution for all inputs.
875          */
876         virtual int GetHashCode(void) const
877         {
878                 int hash = 0;
879                 for (int i = 0; i < __capacity; i++)
880                 {
881                         for (__HashMapEntryT< KeyType, ValueType >* pEntry = __pTable[i]; null != pEntry; pEntry = pEntry->pNext)
882                         {
883                                 hash += reinterpret_cast< int >(&pEntry->key);
884                                 hash += reinterpret_cast< int >(&pEntry->value);
885                         }
886                 }
887                 return hash;
888         }
889
890 private:
891         /**
892          * The implementation of this copy constructor is intentionally blank and declared as private to prohibit copying of objects.
893          *
894          * @param[in]   map The instance of the %HashMapT class to copy from
895          */
896         HashMapT(const HashMapT< KeyType, ValueType >& map);
897
898         /**
899          * The implementation of this copy assignment operator is intentionally blank and declared as private to prohibit copying of objects.
900          *
901          * @param[in]   map An instance of %HashMapT
902          */
903         HashMapT< KeyType, ValueType >& operator =(const HashMapT< KeyType, ValueType >& map);
904
905         /**
906          * Copies all the pairs from a specified @c map to this map.
907          *
908          * @return              An error code
909          * @param[in]   map                                     The map to copy
910          * @exception   E_SUCCESS                       The method is successful.
911          * @exception   E_INVALID_OPERATION     The current state of the instance prohibits the execution of the specified operation. @n
912          *                                                                      The @c map is modified during the operation of this method.
913          */
914         result AddAll(const IMapT< KeyType, ValueType >& map)
915         {
916                 result r = E_SUCCESS;
917
918                 IMapT< KeyType, ValueType >* pMap = const_cast< IMapT< KeyType, ValueType >* >(&map);
919                 IMapEnumeratorT< KeyType, ValueType >* pMapEnum = pMap->GetMapEnumeratorN();
920
921                 TryCatch(pMapEnum != null, r = GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
922
923                 while ((r = pMapEnum->MoveNext()) != E_OUT_OF_RANGE)
924                 {
925                         TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
926
927                         KeyType key;
928                         ValueType value;
929
930                         r = pMapEnum->GetKey(key);
931                         TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
932
933                         r = pMapEnum->GetValue(value);
934                         TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
935
936                         int hash = Hash(key);
937                         int i = hash & (__capacity - 1);
938                         __HashMapEntryT< KeyType, ValueType >* pNewEntry = new __HashMapEntryT< KeyType, ValueType >(key, value, __pTable[i], hash);
939
940                         TryCatch(pNewEntry != null, r = E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
941                         __pTable[i] = pNewEntry;
942                         __count++;
943                 }
944
945                 if (null != pMapEnum)
946                 {
947                         delete pMapEnum;
948                 }
949
950                 return E_SUCCESS;
951
952 CATCH:
953                 if (null != pMapEnum)
954                 {
955                         delete pMapEnum;
956                 }
957
958                 return r;
959         }
960
961         /**
962          * Gets the hash value for the specified object.
963          *
964          * @return              The hash value for the specified object
965          * @param[in]   obj             The object to get hash value
966          */
967         int Hash(const KeyType& obj) const
968         {
969                 int h = __pProvider->GetHashCode(obj);
970
971                 h ^= (h >> 20) ^ (h >> 12);
972
973                 return h ^ (h >> 7) ^ (h >> 4);
974         }
975
976         /**
977          * Resizes the content of a map to a new array with a greater capacity.
978          *
979          * @return              An error code
980          * @param[in]   newCapacity             The new capacity @n
981          *                                                              It must be a power of two and greater than the current capacity.
982          * @exception   E_SUCCESS                       The method is successful.
983          * @exception   E_OUT_OF_MEMORY         The memory is insufficient.
984          * @remarks     This method is called automatically when the number of keys in a map reaches its threshold.
985          */
986         result Resize(int newCapacity)
987         {
988                 result r = E_SUCCESS;
989                 __HashMapEntryT< KeyType, ValueType >** pNewTable = new __HashMapEntryT< KeyType, ValueType >*[newCapacity];
990                 TryReturn(pNewTable != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
991
992                 memset(pNewTable, null, sizeof(__HashMapEntryT< KeyType, ValueType >*) * newCapacity);
993
994                 for (int i = 0; i < __capacity; i++)
995                 {
996                         __HashMapEntryT< KeyType, ValueType >* pEntry = __pTable[i];
997                         while (null != pEntry)
998                         {
999                                 __HashMapEntryT< KeyType, ValueType >* pNext = pEntry->pNext;
1000                                 int i = pEntry->hash & (newCapacity - 1);
1001                                 pEntry->pNext = pNewTable[i];
1002                                 pNewTable[i] = pEntry;
1003                                 pEntry = pNext;
1004                         }
1005                 }
1006
1007                 delete[] __pTable;
1008                 __pTable = pNewTable;
1009                 __capacity = newCapacity;
1010                 __threshold = static_cast< int >(__capacity * __loadFactor);
1011
1012                 return r;
1013         }
1014
1015         /**
1016          * Clears all key-value pairs in this map.
1017          */
1018         void Reset(void)
1019         {
1020                 for (int i = 0; i < __capacity; i++)
1021                 {
1022                         __HashMapEntryT< KeyType, ValueType >* pEntry = __pTable[i];
1023                         while (null != pEntry)
1024                         {
1025                                 __HashMapEntryT< KeyType, ValueType >* pNext = pEntry->pNext;
1026                                 delete pEntry;
1027                                 pEntry = pNext;
1028                         }
1029                         __pTable[i] = null;
1030                 }
1031         }
1032
1033         __HashMapEntryT< KeyType, ValueType >** __pTable;
1034         int __count;
1035         int __capacity;
1036         float __loadFactor;
1037         int __threshold;
1038         IHashCodeProviderT< KeyType >* __pProvider;
1039         IComparerT< KeyType >* __pComparer;
1040         bool __defaultConstruct;
1041         int __modCount;
1042
1043         static const int DEFAULT_CAPACITY = 16;
1044         static const float DEFAULT_LOAD_FACTOR;
1045
1046         friend class __HashMapEnumeratorT< KeyType, ValueType >;
1047
1048 }; // HashMapT
1049
1050 //
1051 // @class       __HashMapEntryT
1052 // @brief       This is an entry for the %HashMapT class.
1053 // @since 2.0
1054 //
1055 template< class KeyType, class ValueType >
1056 class __HashMapEntryT
1057         : public Object
1058 {
1059 public:
1060         /**
1061          * This is the constructor for this class.
1062          *
1063          * @since 2.0
1064          *
1065          * @param[in]   k               The key to include in this entry
1066          * @param[in]   v               The value to include in this entry
1067          * @param[in]   next    A pointer to the next entry
1068          * @param[in]   h               A hash value of the key
1069          */
1070         __HashMapEntryT(const KeyType& k, const ValueType& v, __HashMapEntryT< KeyType, ValueType >* next, int h)
1071                 : key(k)
1072                 , value(v)
1073                 , hash(h)
1074                 , pNext(next)
1075         {
1076         }
1077
1078         /**
1079          * This is the destructor for this class.
1080          *
1081          * @since 2.0
1082          */
1083         virtual ~__HashMapEntryT(void)
1084         {
1085         }
1086
1087         /**
1088          * Internal variable.
1089          *
1090          * @since 2.0
1091          */
1092         KeyType key;
1093
1094         /**
1095          * Internal variable.
1096          *
1097          * @since 2.0
1098          */
1099         ValueType value;
1100
1101         /**
1102          * Internal variable.
1103          *
1104          * @since 2.0
1105          */
1106         int hash;
1107
1108         /**
1109          * Internal variable.
1110          *
1111          * @since 2.0
1112          */
1113         __HashMapEntryT< KeyType, ValueType >* pNext;
1114
1115 }; // __HashMapEntryT
1116
1117 //
1118 // @class       __HashMapEnumeratorT
1119 // @brief       This is an implementation of the IMapEnumeratorT interface for the %HashMapT class.
1120 // @since 2.0
1121 //
1122 template< class KeyType, class ValueType >
1123 class __HashMapEnumeratorT
1124         : public IMapEnumeratorT< KeyType, ValueType >
1125         , public Object
1126 {
1127 public:
1128         /**
1129          * This is the constructor for this class.
1130          *
1131          * @since 2.0
1132          *
1133          * @param[in]   map                     The map to enumerate
1134          * @param[in]   modCount        The modification count to detect the change in the map
1135          */
1136         __HashMapEnumeratorT(const HashMapT< KeyType, ValueType >& map, int modCount)
1137                 : __map(map)
1138                 , __modCount(modCount)
1139                 , __pEntry(null)
1140                 , __index(-1)
1141         {
1142
1143         }
1144
1145         /**
1146          * This is the destructor for this class.
1147          *
1148          * @since 2.0
1149          */
1150         virtual ~__HashMapEnumeratorT(void)
1151         {
1152
1153         }
1154
1155         /**
1156          * Gets the current object in the map.
1157          *
1158          * @since 2.0
1159          *
1160          * @return              An error code
1161          * @param[out]  obj                                     The current object
1162          * @exception   E_SUCCESS                       The method is successful.
1163          * @exception   E_INVALID_OPERATION     The current state of the instance prohibits the execution of the specified operation. @n
1164          *                                                                      This enumerator is currently positioned before the first element or
1165          *                                                                      past the last element or the map is modified after this enumerator is created.
1166          */
1167         virtual result GetCurrent(MapEntryT< KeyType, ValueType >& obj) const
1168         {
1169                 TryReturn((__modCount == __map.__modCount), E_INVALID_OPERATION,
1170                         "[%s] The source collection is modified after the creation of this enumerator.", GetErrorMessage(E_INVALID_OPERATION));
1171                 TryReturn((__pEntry != null), E_INVALID_OPERATION, "[%s] Invalid position(pEntry is null).", GetErrorMessage(E_INVALID_OPERATION));
1172
1173                 obj = MapEntryT< KeyType, ValueType >(__pEntry->key, __pEntry->value);
1174                 return E_SUCCESS;
1175         }
1176
1177         /**
1178          * Moves this enumerator to the next elements of the map.
1179          * When this enumerator is first created, or when the Reset() method is called, or when the %MoveNext() method is first called, the enumerator positions itself to the first element in the map.
1180          *
1181          * @since 2.0
1182          *
1183          * @return              An error code
1184          * @exception   E_SUCCESS                       The method is successful.
1185          * @exception   E_INVALID_OPERATION     The current state of the instance prohibits the execution of the specified operation, or
1186          *                                                                      the map is modified after this enumerator is created.
1187          * @exception   E_OUT_OF_RANGE          The enumerator has passed the end of the map.
1188          * @see                 Reset()
1189          */
1190         virtual result MoveNext(void)
1191         {
1192                 TryReturn((__modCount == __map.__modCount), E_INVALID_OPERATION,
1193                         "[%s] The source collection is modified after the creation of this enumerator.", GetErrorMessage(E_INVALID_OPERATION));
1194
1195                 if ((null != __pEntry) && (null != __pEntry->pNext))
1196                 {
1197                         __pEntry = __pEntry->pNext;
1198                         return E_SUCCESS;
1199                 }
1200                 else
1201                 {
1202                         while (++__index < __map.__capacity)
1203                         {
1204                                 __pEntry = __map.__pTable[__index];
1205                                 if (null != __pEntry)
1206                                 {
1207                                         return E_SUCCESS;
1208                                 }
1209                         }
1210                 }
1211
1212                 return E_OUT_OF_RANGE;
1213         }
1214
1215         /**
1216          * Positions the enumerator before the first element in a map.
1217          *
1218          * @since 2.0
1219          *
1220          * @return              An error code
1221          * @exception   E_SUCCESS                       The method is successful.
1222          * @exception   E_INVALID_OPERATION     The current state of the instance prohibits the execution of the specified operation, or
1223          *                                                                      the map is modified after this enumerator is created.
1224          */
1225         virtual result Reset(void)
1226         {
1227                 TryReturn((__modCount == __map.__modCount), E_INVALID_OPERATION,
1228                         "[%s] The source collection is modified after the creation of this enumerator.", GetErrorMessage(E_INVALID_OPERATION));
1229
1230                 __index = -1;
1231                 __pEntry = null;
1232                 return E_SUCCESS;
1233         }
1234
1235         /**
1236          * Gets the current key in a map.
1237          *
1238          * @since 2.0
1239          *
1240          * @return              An error code
1241          * @param[out]  key                                     The current key
1242          * @exception   E_SUCCESS                       The method is successful.
1243          * @exception   E_INVALID_OPERATION     The current state of the instance prohibits the execution of the specified operation. @n
1244          *                                                                      This enumerator is currently positioned before the first element or
1245          *                                                                      past the last element or the map is modified after this enumerator is created.
1246          */
1247         virtual result GetKey(KeyType& key) const
1248         {
1249                 TryReturn((__modCount == __map.__modCount), E_INVALID_OPERATION,
1250                         "[%s] The source collection is modified after the creation of this enumerator.", GetErrorMessage(E_INVALID_OPERATION));
1251                 TryReturn((__pEntry != null), E_INVALID_OPERATION, "[%s] Invalid position(pEntry is null).", GetErrorMessage(E_INVALID_OPERATION));
1252
1253                 key = __pEntry->key;
1254                 return E_SUCCESS;
1255         }
1256
1257         /**
1258          * Gets the current value in a map.
1259          *
1260          * @since 2.0
1261          *
1262          * @return              An error code
1263          * @param[out]  value The current value
1264          * @exception   E_SUCCESS                       The method is successful.
1265          * @exception   E_INVALID_OPERATION     The current state of the instance prohibits the execution of the specified operation. @n
1266          *                                                                      This enumerator is currently positioned before the first element or
1267          *                                                                      past the last element or the map is modified after the enumerator is created.
1268          */
1269         virtual result GetValue(ValueType& value) const
1270         {
1271                 TryReturn((__modCount == __map.__modCount), E_INVALID_OPERATION,
1272                         "[%s] The source collection is modified after the creation of this enumerator.", GetErrorMessage(E_INVALID_OPERATION));
1273                 TryReturn((__pEntry != null), E_INVALID_OPERATION, "[%s] Invalid position(pEntry is null).", GetErrorMessage(E_INVALID_OPERATION));
1274
1275                 value = __pEntry->value;
1276                 return E_SUCCESS;
1277         }
1278
1279 private:
1280         const HashMapT< KeyType, ValueType >& __map;
1281         int __modCount;
1282         __HashMapEntryT< KeyType, ValueType >* __pEntry;
1283         int __index;
1284
1285 }; // __HashMapEnumeratorT
1286
1287 //
1288 // @class       __HashMapDefaultProviderT
1289 // @brief       This is an implementation of the IHashCodeProviderT interface for the HashMap class.
1290 // @since 2.0
1291 //
1292 template< class KeyType >
1293 class __HashMapDefaultProviderT
1294         : public IHashCodeProviderT< KeyType >
1295         , public Object
1296 {
1297 public:
1298         /**
1299         * This is the default constructor for this class.
1300         *
1301         * @since 2.0
1302         */
1303         __HashMapDefaultProviderT(void) {}
1304
1305         /**
1306         * This is the destructor for this class.
1307         *
1308         * @since 2.0
1309         */
1310         virtual ~__HashMapDefaultProviderT(void) {}
1311
1312         /**
1313         * Gets the hash code of the specified object.
1314         *
1315         * @since 2.0
1316         *
1317         * @return               The hash code of the specified object
1318         * @see                  Tizen::Base::Object::GetHashCode
1319         */
1320         virtual int GetHashCode(const KeyType& obj) const
1321         {
1322                 return (int) obj;
1323         }
1324
1325 }; // __HashMapDefaultProviderT
1326
1327 template< class KeyType, class ValueType >
1328 const float HashMapT< KeyType, ValueType >::DEFAULT_LOAD_FACTOR = 0.75;
1329
1330 }}} // Tizen::Base::Collection
1331
1332 #endif //_FBASE_COL_HASH_MAP_T_H_