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