-
Notifications
You must be signed in to change notification settings - Fork 0
/
MtmMap.h
374 lines (352 loc) · 10.4 KB
/
MtmMap.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
#ifndef MTMMAP_H_
#define MTMMAP_H_
#include <cassert>
#include <functional>
#include <cstdlib>
#include "Exceptions.h"
#define mapTemplate <KeyType, ValueType, CompareFunction>
namespace mtm {
/**
* A generic map, which stores pairs formed by a combination of key value
* and a value type, following a specific order between keys.
* Key value is used to sort and uniquely identify the elements, while
* the mapped value store the content associated to the key.
*/
template<class KeyType, class ValueType, class CompareFunction = std::less<
KeyType> >
class MtmMap {
class Node;
Node* _head;
ValueType _defaultValue;
CompareFunction compare;
public:
/**
* A pointer to an object in the map.
*/
class iterator;
/**
* Couples together a pair of key and value which may be of different types.
*/
class Pair {
public:
Pair(const KeyType& key, const ValueType& value) :
first(key), second(value) {
}
Pair(const Pair& pair) :
first(pair.first), second(pair.second) {
}
const KeyType first;
ValueType second;
};
/**
* Map Constructor.
* receives @defaultValue and creates a new map by allocating head
* - creating an empty linked list.
*/
MtmMap(const ValueType& defaultValue);
/**
* Copy Constructor.
* creates a new allocated copy of a given map.
*/
MtmMap(const MtmMap& map);
/**
* Destructor.
* de-allocates all the map's objects, and the head of the linked list.
*/
~MtmMap();
/**
* Placement operator.
* de-allocates the old content of left operand, and places a new copy
* of the given map (right operand) to the left operand.
*/
MtmMap& operator=(const MtmMap& map);
/**
* De-allocates all the elements that were inserted to the map.
* excluding head node, leaving the linked list empty but
* still usable.
*/
void clear();
/**
* Allocates a new node in the linked list and inserts the given pair
* into the map container.
* uses CompareFunction criterion to locate the maximal key which is bigger
* than the given key, and inserts the new element before that key.
* IF given key already exists in the map, replaces the old value of
* the element with the new given value.
*/
void insert(Pair pair);
/*
* Second version of the map that receives two parameters : a key and a value.
* Creates a pair from these two parameters and then inserts it according to the
* "original" insert function.
*/
void insert(const KeyType& key, const ValueType& value);
/**
* Removes an element from the map.
* if the given key does not match any element's key in the map -
* throws MapElementNotFoundException.
* if the given key is found, the element is removed from the map.
*/
void remove(const KeyType& key);
/**
* Returns an iterator to the element with the requested key.
* if no such element was found - throws MapElementNotFoundException.
*/
iterator find(const KeyType& key) const;
/**
* Returns an iterator to the first element in the map.
*/
iterator begin() const;
/**
* Returns an iterator to tail of the linked list (no data).
*/
iterator end() const;
/**
* Returns a boolean value stating if the given key exists in an element
* in the map or not.
*/
bool containsKey(const KeyType& key) const;
/**
* Returns the amount of elements in the map.
*/
unsigned int size() const;
/**
* Returns a reference to the value of the element according to the key.
*/
ValueType& operator[](const KeyType& key);
/**
* Returns a const reference to the value of the element according to the
* key (for const maps).
*/
const ValueType& operator[](const KeyType& key) const;
};
template<class KeyType, class ValueType, class CompareFunction>
class MtmMap mapTemplate::Node {
Pair _data;
Node* _next;
friend class MtmMap;
public:
Node(Pair& data, Node* next = NULL) : _data(data), _next(next) {};
};
template<class KeyType, class ValueType, class CompareFunction>
class MtmMap mapTemplate::iterator {
const MtmMap* _map;
Node* _current;
friend class MtmMap;
public:
/** Explicit constructor, disables casting of the iterator.
* receives a @current and a @map and creates an iterator to that node
* which belongs to the given map.
*/
explicit iterator(const MtmMap<KeyType,ValueType,CompareFunction>* map = NULL, Node* current = NULL)
: _map(map), _current(current) {}
/** Copy constructor,
* receives a @iterator and creates an iterator strictly
* identical to the parameter
*/
iterator(const iterator& it)
: _map(it._map), _current(it._current) {}
/**
* Placement operator. sets an iterator (left operand) to point to
* the same element as right operand iterator.
*/
iterator& operator=(const iterator& it) = default;
/**
* First promote an iterator to point to the next element in the container
* and then allows placements.
*/
iterator& operator++() {
if(*this == _map->end()) {
return *this;
}
_current = _current->_next;
return *this;
}
/**
* Point to the current element in the container and then promote it.
*/
iterator operator++(int) {
iterator tmp_iter = *this;
++(*this);
return tmp_iter;
}
/**
* Dereferencing of a pointer, returning a const reference to the data
* saved in the node of the element pointed by the iterator.
* throws MapElementNotFoundException if iterator is pointing to the
* end of the container.
*/
Pair& operator*() const {
if(*this == _map->end()) {
throw MapElementNotFoundException();
}
return _current->_data;
}
/**
* Compares iterators, first by checking if they belong to the same map,
* then checking if both iterators point to the same element inside the map.
*/
bool operator==(const iterator& iterator) const {
return (_map == iterator._map && _current == iterator._current);
}
/**
* Compares iterators, returning the opposite value returned by
* operator == (in other words if iterators are different).
*/
bool operator!=(const iterator& iterator) const {
return !(*this == iterator);
}
};
template<class KeyType, class ValueType, class CompareFunction>
MtmMap mapTemplate::MtmMap(const ValueType& defaultValue)
: _head(NULL), _defaultValue(defaultValue) {}
template<class KeyType, class ValueType, class CompareFunction>
MtmMap mapTemplate::MtmMap(const MtmMap& map) : _defaultValue(map._defaultValue), compare(map.compare) {
_head = NULL;
iterator it = map.begin();
for(unsigned int i = 0; i < map.size(); i++) {
insert(it._current->_data);
it++;
}
}
template<class KeyType, class ValueType, class CompareFunction>
MtmMap mapTemplate::~MtmMap() {
clear();
}
template<class KeyType, class ValueType, class CompareFunction>
MtmMap mapTemplate& MtmMap<KeyType, ValueType,
CompareFunction>::operator=(const MtmMap& map) {
if(_head == map._head) {
return *this;
}
clear();
for(iterator it = map.begin(); it != map.end(); it++) {
insert(it._current->_data);
}
_defaultValue = map._defaultValue;
compare = map.compare;
return *this;
}
template<class KeyType, class ValueType, class CompareFunction>
typename MtmMap mapTemplate::iterator MtmMap<KeyType,
ValueType, CompareFunction>::find(const KeyType &key) const {
for(MtmMap::iterator it = begin(); it != end(); it++) {
if(!compare(it._current->_data.first, key)
&& !compare(key, it._current->_data.first)) {
return it;
}
}
return end();
}
template<class KeyType, class ValueType, class CompareFunction>
void MtmMap mapTemplate::insert(Pair pair) {
iterator it = begin();
// edge case : if size is empty then insert first
if(size() == 0) {
_head = new Node(pair, NULL);
return;
}
int count = 0;
while(it != end() && compare(it._current->_data.first, pair.first)) {
it++;
count++;
}
if(it != end()
&& !compare(it._current->_data.first, pair.first)
&& !compare(pair.first, it._current->_data.first)) {
it._current->_data.second = pair.second;
} else {
Node* toInsert = new Node(pair, _head);
//edge case: the iterator is pointing on the head of the list
if (it._current == _head) {
_head = toInsert;
return;
}
iterator tmp_iterator = begin();
for(int i = 0; i < count - 1; i++) {
tmp_iterator++;
}
tmp_iterator._current->_next = toInsert;
toInsert->_next = it._current;
}
}
template<class KeyType, class ValueType, class CompareFunction>
void MtmMap mapTemplate::insert(const KeyType& key, const ValueType& value) {
Pair pair = Pair(key, value);
insert(pair);
}
template<class KeyType, class ValueType, class CompareFunction>
void MtmMap mapTemplate::remove(const KeyType& key) {
if(!containsKey(key)) {
throw MapElementNotFoundException();
}
iterator it = begin();
while(it != end() && it._current->_data.first != key) {
it++;
}
if (it._current == _head) {
_head = it._current->_next;
} else {
iterator tmp_iterator = begin();
while (tmp_iterator._current->_next != it._current) {
tmp_iterator++;
}
tmp_iterator._current->_next = it._current->_next;
}
delete it._current;
}
template<class KeyType, class ValueType, class CompareFunction>
void MtmMap mapTemplate::clear() {
while(size() > 0) {
iterator it = begin();
remove(it._current->_data.first);
}
}
template<class KeyType, class ValueType, class CompareFunction>
typename MtmMap mapTemplate::iterator MtmMap<KeyType,
ValueType, CompareFunction>::begin() const {
return iterator(this, _head);
}
template<class KeyType, class ValueType, class CompareFunction>
typename MtmMap mapTemplate::iterator MtmMap<KeyType,
ValueType, CompareFunction>::end() const {
return iterator(this, NULL);
}
template<class KeyType, class ValueType, class CompareFunction>
bool MtmMap mapTemplate::containsKey(const KeyType& key) const {
iterator iterator = begin();
while(iterator != end()) {
if(!compare(iterator._current->_data.first, key)
&& !compare(key, iterator._current->_data.first)) {
return true;
}
iterator++;
}
return false;
}
template<class KeyType, class ValueType, class CompareFunction>
unsigned int MtmMap mapTemplate::size() const {
iterator iterator = begin();
unsigned int count = 0;
while(iterator != end()) {
iterator++;
count++;
}
return count;
}
template<class KeyType, class ValueType, class CompareFunction>
ValueType& MtmMap mapTemplate::operator[](const KeyType& key) {
if(!containsKey(key)) {
insert(key, _defaultValue);
}
return find(key)._current->_data.second;
}
template<class KeyType, class ValueType, class CompareFunction>
const ValueType& MtmMap mapTemplate::operator[](const KeyType& key) const {
if(containsKey(key)) {
return find(key)._current->_data.second;
}
return _defaultValue;
}
}
#endif