Calling g_io_channel_set_close_on_unref() after crating channel
[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 the specified @c 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 the specified @c map,
342          * with the 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 the specified @c 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 the specified @c 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 the specified @c 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 the specified @c key with the specified new @c 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 @c 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 @c 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 @c value.
796          *
797          * @since 2.0
798          *
799          * @return              @c true if the map contains the specified @c 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 @c 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 the 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_