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