1/* Copyright (c) 2012 Massachusetts Institute of Technology
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 * THE SOFTWARE.
20 */
21
22#ifndef __MAP_H__
23#define __MAP_H__
24
25#include <iostream>
26#include <map>
27
28#include "String.h"
29#include "Assert.h"
30
31namespace LibUtil
32{
33    using std::map;
34
35    template<class T> class Map
36    {
37        public:
38            typedef typename map<String, T>::iterator       Iterator;
39            typedef typename map<String, T>::const_iterator ConstIterator;
40            typedef typename map<String, T>::size_type      SizeType;
41
42        public:
43            Map();
44            virtual ~Map();
45
46        public:
47            // Return a new copy of this Map instance
48            Map* clone() const;
49            // Copy map_ to this instance
50            void copyFrom(const Map<T>* map_);
51            // Return the size of the map
52            SizeType size() const;
53            // Check if the map is empty
54            bool isEmpty() const;
55            // Check if the key exists
56            bool keyExist(const String& key_) const;
57            // Get the value_ corresponding to the key_
58            const T& get(const String& key_) const;
59            // Get the value_ corresponding to the key_ if the key_ exist, otherwise, the default_value_is returned
60            const T& getIfKeyExist(const String& key_, const T& default_value_ = T()) const;
61            // Add/Update a <key_, value_> entry
62            void set(const String& key_, const T& value_);
63            // Get iterator to the element
64            Iterator find(const String& key_);
65            ConstIterator find(const String& key_) const;
66            // Remove an entry corresponding to key_
67            void remove(const String& key_);
68            // Remove an entry at 'it'
69            void remove(Iterator it);
70            // Remove all keys
71            void clear();
72            // Merge a map. Values with same key will be overwritten.
73            void merge(const Map<T>* map_);
74            // Returns a MapIterator referring to the first element in the map
75            Iterator begin();
76            ConstIterator begin() const;
77            // Returns a MapIterator referring to the past-the-end element in the map
78            Iterator end();
79            ConstIterator end() const;
80
81        protected:
82            Map(const Map& map_);
83
84        protected:
85            map<String, T> mMap;
86    };
87
88    template<class T> Map<T>::Map()
89    {}
90
91    template<class T> Map<T>::~Map()
92    {}
93
94    template<class T> Map<T>* Map<T>::clone() const
95    {
96        return new Map<T>(*this);
97    }
98
99    template<class T> void Map<T>::copyFrom(const Map<T>* map_)
100    {
101        // Remove all keys (it won't free the content if T is a pointer)
102        mMap.clear();
103
104        // Copy the contents
105        mMap = map_->mMap;
106    }
107
108    template<class T> typename Map<T>::SizeType Map<T>::size() const
109    {
110        return mMap.size();
111    }
112
113    template<class T> bool Map<T>::isEmpty() const
114    {
115        return (mMap.empty());
116    }
117
118    template<class T> bool Map<T>::keyExist(const String& key_) const
119    {
120        ConstIterator it = mMap.find(key_);
121        return (it != mMap.end());
122    }
123
124    template<class T> const T& Map<T>::get(const String& key_) const
125    {
126        ConstIterator it;
127
128        it = mMap.find(key_);
129        ASSERT((it != mMap.end()), "Key not found: " + key_);
130        return (it->second);
131    }
132
133    template<class T> const T& Map<T>::getIfKeyExist(const String& key_, const T& default_value_) const
134    {
135        if(keyExist(key_))
136        {
137            return get(key_);
138        }
139        else
140        {
141            return default_value_;
142        }
143    }
144
145    template<class T> void Map<T>::set(const String& key_, const T& value_)
146    {
147        mMap[key_] = value_;
148        return;
149    }
150
151    template<class T> typename Map<T>::Iterator Map<T>::find(const String& key_)
152    {
153        return mMap.find(key_);
154    }
155
156    template<class T> typename Map<T>::ConstIterator Map<T>::find(const String& key_) const
157    {
158        return mMap.find(key_);
159    }
160
161    template<class T> void Map<T>::remove(const String& key_)
162    {
163        mMap.erase(key_);
164        return;
165    }
166
167    template<class T> void Map<T>::remove(Iterator it)
168    {
169        mMap.erase(it);
170        return;
171    }
172
173    template<class T> void Map<T>::clear()
174    {
175        mMap.clear();
176        return;
177    }
178
179    template<class T> void Map<T>::merge(const Map<T>* map_)
180    {
181        ConstIterator it;
182        for(it = map_->begin(); it != map_->end(); it++)
183        {
184            const String& key = it->first;
185            const T& value = it->second;
186            set(key, value);
187        }
188        return;
189    }
190
191    template<class T> typename Map<T>::Iterator Map<T>::begin()
192    {
193        return mMap.begin();
194    }
195
196    template<class T> typename Map<T>::ConstIterator Map<T>::begin() const
197    {
198        return mMap.begin();
199    }
200
201    template<class T> typename Map<T>::Iterator Map<T>::end()
202    {
203        return mMap.end();
204    }
205
206    template<class T> typename Map<T>::ConstIterator Map<T>::end() const
207    {
208        return mMap.end();
209    }
210
211    inline std::ostream& operator<<(std::ostream& ost_, const Map<String>& map_)
212    {
213        Map<String>::ConstIterator it;
214        for(it = map_.begin(); it != map_.end(); it++)
215        {
216            ost_ << it->first << " = " << it->second << std::endl;
217        }
218        return ost_;
219    }
220
221    template<class T> Map<T>::Map(const Map<T>& map_)
222        : mMap(map_.mMap)
223    {}
224
225    typedef Map<String> StringMap;
226
227
228    // Handy function to delete all pointers in a map
229    template<class T> void clearPtrMap(Map<T*>* map_)
230    {
231        for(typename Map<T*>::Iterator it = map_->begin(); it != map_->end(); ++it)
232        {
233            T* temp_T = it->second;
234            delete temp_T;
235        }
236        map_->clear();
237        return;
238    }
239
240    // Handy function to delete all pointers in a map and the map itself
241    template<class T> void deletePtrMap(Map<T*>* map_)
242    {
243        clearPtrMap<T>(map_);
244        delete map_;
245        return;
246    }
247
248    // Handy function to clone all pointers in a map
249    template<class T> Map<T*>* clonePtrMap(const Map<T*>* map_)
250    {
251        Map<T*>* new_T_map = new Map<T*>;
252        for(typename Map<T*>::ConstIterator it = map_->begin(); it != map_->end(); ++it)
253        {
254            const String& temp_name = it->first;
255            const T* temp_T = it->second;
256            new_T_map->set(temp_name, temp_T->clone());
257        }
258        return new_T_map;
259    }
260}
261
262#endif // __MAP_H__
263
264