CMagic  0.5.0
Portable C library of utilities and data structures
map.hpp
Go to the documentation of this file.
1 
7 #ifndef CMAGIC_MAP_HPP
8 #define CMAGIC_MAP_HPP
9 
10 #include <cassert>
11 #include <cstddef>
12 #include <iterator>
13 #include <new>
14 #include <type_traits>
15 #include <utility>
16 #include "cmagic/map.h"
17 
18 
19 namespace cmagic {
20 
21 template<typename Key, typename Value>
22 class map {
23 
24 public:
28  using key_type = Key;
29 
33  using mapped_type = Value;
34 
38  using value_type = std::pair<key_type, mapped_type>;
39 
43  using size_type = size_t;
44 
45  class iterator {
46 
47  public:
48  using iterator_category = std::bidirectional_iterator_tag;
49  using const_pointer = const value_type*;
50  using const_reference = const value_type&;
51 
52  private:
53  cmagic_map_iterator_t internal_iterator;
54  value_type adapter;
55 
56  constexpr value_type make_adapter() {
57  assert(internal_iterator);
58  return std::make_pair(*static_cast<const key_type *>(internal_iterator->key),
59  *static_cast<mapped_type *>(internal_iterator->value));
60  }
61 
62  void update_adapter() {
63  if (internal_iterator) {
64  adapter = make_adapter();
65  }
66  }
67 
68  void increment() {
69  assert(internal_iterator);
70  internal_iterator = CMAGIC_MAP_ITERATOR_NEXT(internal_iterator);
71  update_adapter();
72  }
73 
74  void decrement() {
75  assert(internal_iterator);
76  internal_iterator = CMAGIC_MAP_ITERATOR_PREV(internal_iterator);
77  update_adapter();
78  }
79 
80  public:
81  const_pointer operator->() const { return &adapter; }
82  const_reference operator*() const { return *this->operator->(); }
83  bool operator!=(const iterator &other) const { return !(*this == other); }
84 
85  iterator(cmagic_map_iterator_t initializer) : internal_iterator(initializer) {
86  update_adapter();
87  }
88 
89  iterator &operator++() {
90  increment();
91  return *this;
92  }
93 
94  iterator operator++(int) {
95  iterator to_return = *this;
96  ++(*this);
97  return to_return;
98  }
99 
100  iterator &operator--() {
101  decrement();
102  return *this;
103  }
104 
105  iterator operator--(int) {
106  iterator to_return = *this;
107  --(*this);
108  return to_return;
109  }
110 
111  bool operator==(const iterator &other) const {
112  return this->internal_iterator == other.internal_iterator;
113  }
114 
115  };
116 
117 private:
118  static_assert(std::is_copy_constructible<key_type>(), "key type must be copy-constructible");
119  static_assert(std::is_copy_constructible<mapped_type>(),
120  "mapped type must be copy-constructible");
121  static_assert(std::is_copy_assignable<mapped_type>(), "mapped type must be copy-assignable");
122 
123  CMAGIC_MAP(key_type) map_handle;
124 
125  static int key_comparator(const void *void_key1, const void *void_key2) {
126  const key_type &key1 = *static_cast<const key_type *>(void_key1);
127  const key_type &key2 = *static_cast<const key_type *>(void_key2);
128  if (key1 < key2) {
129  return -1;
130  } else if (key1 > key2) {
131  return 1;
132  } else {
133  return 0;
134  }
135  }
136 
137  explicit map(const cmagic_memory_alloc_packet_t *alloc_packet)
138  : map_handle(CMAGIC_MAP_NEW(key_type, mapped_type, key_comparator, alloc_packet)) {}
139 
140  template <typename Key_URef, typename Val_URef>
141  std::pair<iterator, bool> insert_template(Key_URef &&key, Val_URef &&value) {
142  assert(*this);
143  cmagic_map_insert_result_t insert_result = CMAGIC_MAP_ALLOCATE(map_handle, &key);
144  if (!insert_result.already_exists && insert_result.inserted_or_existing) {
145  new(const_cast<void *>(insert_result.inserted_or_existing->key))
146  key_type {std::forward<Key_URef>(key)};
147  new(insert_result.inserted_or_existing->value)
148  mapped_type {std::forward<Val_URef>(value)};
149  }
150  const bool insert_unique_success =
151  insert_result.inserted_or_existing && !insert_result.already_exists;
152  return std::make_pair(insert_result.inserted_or_existing, insert_unique_success);
153  }
154 
155 public:
161 
168  }
169 
170  map &operator=(const map &x) {
171  assert(*this);
172  if (&x == this) {
173  return *this;
174  }
175 
176  clear();
177  for (const value_type &val : x) {
178  auto insert_result = insert(val);
179  assert(insert_result.first == end() || insert_result.second);
180  if (insert_result.first == end()) {
181  clear();
182  CMAGIC_MAP_FREE(map_handle);
183  map_handle = nullptr;
184  return *this;
185  }
186  }
187  return *this;
188  }
189 
190  map(const map &x) : map(CMAGIC_MAP_GET_ALLOC_PACKET(x.map_handle)) {
191  if (*this) {
192  operator=(x);
193  }
194  }
195 
196  map &operator=(map &&x) {
197  assert(*this);
198  clear();
199  CMAGIC_MAP_FREE(map_handle);
200  map_handle = x.map_handle;
201  x.map_handle = CMAGIC_MAP_NEW(key_type, mapped_type, key_comparator,
202  CMAGIC_MAP_GET_ALLOC_PACKET(x.map_handle));
203  return *this;
204  }
205 
206  map(map &&x) : map_handle(x.map_handle) {
207  x.map_handle = CMAGIC_MAP_NEW(key_type, mapped_type, key_comparator,
208  CMAGIC_MAP_GET_ALLOC_PACKET(x.map_handle));
209  }
210 
225  operator bool() const {
226  return static_cast<bool>(map_handle);
227  }
228 
235  iterator begin() const {
236  assert(map_handle);
237  return CMAGIC_MAP_FIRST(map_handle);
238  }
239 
245  iterator end() const {
246  assert(map_handle);
247  return nullptr;
248  }
249 
253  void clear() {
254  assert(*this);
255  for (cmagic_map_iterator_t it = CMAGIC_MAP_FIRST(map_handle);
256  it;
257  it = CMAGIC_MAP_ITERATOR_NEXT(it)) {
258  const key_type *key_ptr = static_cast<const key_type *>(it->key);
259  mapped_type *value_ptr = static_cast<mapped_type *>(it->value);
260  key_ptr->~key_type();
261  value_ptr->~mapped_type();
262  }
263  CMAGIC_MAP_CLEAR(map_handle);
264  }
265 
279  std::pair<iterator, bool> insert(const value_type &val) {
280  return insert_template(val.first, val.second);
281  }
282 
286  std::pair<iterator, bool> insert(value_type &&val) {
287  return insert_template(std::move(val.first), std::move(val.second));
288  }
289 
295  void erase(const key_type &key) {
296  assert(*this);
297  CMAGIC_MAP_ERASE_EXT(map_handle, &key, [](void *raw_key, void *raw_value) {
298  static_cast<key_type *>(raw_key)->~key_type();
299  static_cast<mapped_type *>(raw_value)->~mapped_type();
300  });
301  }
302 
307  size_type size() const {
308  assert(*this);
309  return CMAGIC_MAP_SIZE(map_handle);
310  }
311 
318  bool empty() const {
319  return size() == 0;
320  }
321 
328  iterator find(const key_type &key) const {
329  return CMAGIC_MAP_FIND(map_handle, &key);
330  }
331 
332  ~map() {
333  if (*this) {
334  clear();
335  CMAGIC_MAP_FREE(map_handle);
336  }
337  }
338 
339 };
340 
341 } // namespace cmagic
342 
343 #endif /* CMAGIC_MAP_HPP */
void erase(const key_type &key)
Removes a single element from the map.
Definition: map.hpp:295
std::pair< iterator, bool > insert(const value_type &val)
Inserts a new element to the map if its key is not equivalent to any element already contained in the...
Definition: map.hpp:279
size_type size() const
Returns the number of elements in the map.
Definition: map.hpp:307
Value mapped_type
Type of map values.
Definition: map.hpp:33
iterator find(const key_type &key) const
Searches the container for an element with a key equivalent to key and returns an iterator to it if f...
Definition: map.hpp:328
Set of allocation functions. Used in some CMagic structures to specify a desired memory pool...
Definition: memory.h:187
void clear()
Removes all elements from the map, leaving the container with a size of 0.
Definition: map.hpp:253
Key key_type
Type of map keys.
Definition: map.hpp:28
#define CMAGIC_MAP_ERASE_EXT(cmagic_map, key, destructor)
Extended version of CMAGIC_MAP_ERASE.
Definition: map.h:175
bool empty() const
Returns whether the map is empty (i.e. whether its size is 0).
Definition: map.hpp:318
#define CMAGIC_MAP_FIND(cmagic_map, key)
Searches the container for an element with a key equivalent to key and returns an iterator to it if f...
Definition: map.h:240
#define CMAGIC_MAP_FREE(cmagic_map)
Frees the resources allocated by the map before.
Definition: map.h:138
bool already_exists
true if the element already exists in the map and the map was not modified, false if a new element ha...
Definition: map.h:74
#define CMAGIC_MAP(key_type)
Convenient alias for type*. Returned type of CMAGIC_MAP_NEW.
Definition: map.h:118
#define CMAGIC_MAP_GET_ALLOC_PACKET(cmagic_map)
Retrieves cmagic_memory_alloc_packet_t associated with the map.
Definition: map.h:268
#define CMAGIC_MAP_ITERATOR_PREV(iterator)
Returns iterator to the previous element in container.
Definition: map.h:232
map()
Constructs an empty map with standard memory allocation.
Definition: map.hpp:160
#define CMAGIC_MAP_CLEAR(cmagic_map)
Removes all elements from the map.
Definition: map.h:192
std::pair< iterator, bool > insert(value_type &&val)
Inserts a new element to the map if its key is not equivalent to any element already contained in the...
Definition: map.hpp:286
iterator begin() const
Return iterator to beginning.
Definition: map.hpp:235
#define CMAGIC_MAP_NEW(key_type, value_type, key_comparator, alloc_packet)
Allocates and returns an address of a newly created empty map.
Definition: map.h:130
#define CMAGIC_MAP_ITERATOR_NEXT(iterator)
Returns iterator to the next element in container.
Definition: map.h:224
static map custom_allocation_map()
Constructs an empty map using custom CMagic memory allocation from memory.h.
Definition: map.hpp:166
iterator end() const
Return iterator to end.
Definition: map.hpp:245
cmagic_map_iterator_t inserted_or_existing
iterator pointing to a new or already existing element or NULL if the allocation of a new element has...
Definition: map.h:68
Implementation of a map container.
Definition: map.hpp:22
static const cmagic_memory_alloc_packet_t CMAGIC_MEMORY_ALLOC_PACKET_STD
Allocation from the standard library.
Definition: memory.h:196
size_t size_type
Type used to measure element size.
Definition: map.hpp:43
static const cmagic_memory_alloc_packet_t CMAGIC_MEMORY_ALLOC_PACKET_CUSTOM_CMAGIC
Custom allocation from the CMagic library.
Definition: memory.h:203
Definition: map.h:54
Definition: map.hpp:19
#define CMAGIC_MAP_FIRST(cmagic_map)
Return iterator to the first element in map.
Definition: map.h:208
#define CMAGIC_MAP_SIZE(cmagic_map)
Returns the number of elements in the map.
Definition: map.h:199
Map insertion result.
Definition: map.h:62
#define CMAGIC_MAP_ALLOCATE(cmagic_map, key)
Allocates space for a new element (key-value pair) but does not initialize it.
Definition: map.h:151
Definition: map.hpp:45
std::pair< key_type, mapped_type > value_type
Type of map elements.
Definition: map.hpp:38