CMagic  0.5.0
Portable C library of utilities and data structures
set.hpp
Go to the documentation of this file.
1 
7 #ifndef CMAGIC_SET_HPP
8 #define CMAGIC_SET_HPP
9 
10 #include <cassert>
11 #include <cstddef>
12 #include <iterator>
13 #include <new>
14 #include <type_traits>
15 #include "cmagic/set.h"
16 
17 
18 namespace cmagic {
19 
26 template<typename T>
27 class set {
28 
29 public:
33  using value_type = T;
34 
38  using size_type = size_t;
39 
40  class iterator {
41 
42  public:
43  using iterator_category = std::bidirectional_iterator_tag;
44  using value_type = T;
45  using const_pointer = const value_type*;
46  using const_reference = const value_type&;
47 
48  private:
49  cmagic_set_iterator_t internal_iterator;
50 
51  public:
52  iterator(cmagic_set_iterator_t initializer) : internal_iterator(initializer) {}
53  const_reference operator*() const { return *this->operator->(); }
54  bool operator!=(const iterator &other) const { return !(*this == other); }
55 
56  const_pointer operator->() const {
57  return static_cast<const_pointer>(internal_iterator->key);
58  }
59 
60  iterator &operator++() {
61  assert(internal_iterator);
62  internal_iterator = CMAGIC_SET_ITERATOR_NEXT(internal_iterator);
63  return *this;
64  }
65 
66  iterator operator++(int) {
67  iterator to_return = *this;
68  ++(*this);
69  return to_return;
70  }
71 
72  iterator &operator--() {
73  assert(internal_iterator);
74  internal_iterator = CMAGIC_SET_ITERATOR_PREV(internal_iterator);
75  return *this;
76  }
77 
78  iterator operator--(int) {
79  iterator to_return = *this;
80  --(*this);
81  return to_return;
82  }
83 
84  bool operator==(const iterator &other) const {
85  return this->internal_iterator == other.internal_iterator;
86  }
87 
88  };
89 
90 private:
91  static_assert(std::is_copy_assignable<T>(), "value type must be copy-assignable");
92  static_assert(std::is_copy_constructible<T>(), "value type must be copy-constructible");
93  CMAGIC_SET(value_type) set_handle;
94 
95  static int key_comparator(const void *void_key1, const void *void_key2) {
96  const value_type &key1 = *static_cast<const value_type *>(void_key1);
97  const value_type &key2 = *static_cast<const value_type *>(void_key2);
98  if (key1 < key2) {
99  return -1;
100  } else if (key1 > key2) {
101  return 1;
102  } else {
103  return 0;
104  }
105  }
106 
107  explicit set(const cmagic_memory_alloc_packet_t *alloc_packet)
108  : set_handle(CMAGIC_SET_NEW(value_type, key_comparator, alloc_packet)) {}
109 
110  template <typename URef>
111  std::pair<iterator, bool> insert_template(URef &&val) {
112  assert(*this);
113  cmagic_set_insert_result_t insert_result = CMAGIC_SET_ALLOCATE(set_handle, &val);
114  if (!insert_result.already_exists && insert_result.inserted_or_existing) {
115  new(const_cast<void *>(insert_result.inserted_or_existing->key))
116  value_type {std::forward<URef>(val)};
117  }
118  const bool insert_unique_success =
119  insert_result.inserted_or_existing && !insert_result.already_exists;
120  return std::make_pair(insert_result.inserted_or_existing, insert_unique_success);
121  }
122 
123 public:
129 
134  static set custom_allocation_set() {
136  }
137 
138  set &operator=(const set &x) {
139  assert(*this);
140  if (&x == this) {
141  return *this;
142  }
143 
144  clear();
145  for (const value_type &val : x) {
146  auto insert_result = insert(val);
147  assert(insert_result.first == end() || insert_result.second);
148  if (insert_result.first == end()) {
149  clear();
150  CMAGIC_SET_FREE(set_handle);
151  set_handle = nullptr;
152  return *this;
153  }
154  }
155  return *this;
156  }
157 
158  set(const set &x) : set(CMAGIC_SET_GET_ALLOC_PACKET(x.set_handle)) {
159  if (*this) {
160  operator=(x);
161  }
162  }
163 
164  set &operator=(set &&x) {
165  assert(*this);
166  clear();
167  CMAGIC_SET_FREE(set_handle);
168  set_handle = x.set_handle;
169  x.set_handle = CMAGIC_SET_NEW(value_type, key_comparator,
170  CMAGIC_SET_GET_ALLOC_PACKET(x.set_handle));
171  return *this;
172  }
173 
174  set(set &&x) : set_handle(x.set_handle) {
175  x.set_handle = CMAGIC_SET_NEW(value_type, key_comparator,
176  CMAGIC_SET_GET_ALLOC_PACKET(x.set_handle));
177  }
178 
193  operator bool() const {
194  return static_cast<bool>(set_handle);
195  }
196 
203  iterator begin() const {
204  assert(set_handle);
205  return CMAGIC_SET_FIRST(set_handle);
206  }
207 
213  iterator end() const {
214  assert(set_handle);
215  return nullptr;
216  }
217 
221  void clear() {
222  assert(*this);
223  for (const value_type &key : *this) {
224  key.~value_type();
225  }
226  CMAGIC_SET_CLEAR(set_handle);
227  }
228 
242  std::pair<iterator, bool> insert(const value_type &val) {
243  return insert_template(val);
244  }
245 
249  std::pair<iterator, bool> insert(value_type &&val) {
250  return insert_template(std::move(val));
251  }
252 
258  void erase(const value_type &val) {
259  assert(*this);
260  CMAGIC_SET_ERASE_EXT(set_handle, &val, [](void *key) {
261  static_cast<value_type *>(key)->~value_type();
262  });
263  }
264 
269  size_type size() const {
270  assert(*this);
271  return CMAGIC_SET_SIZE(set_handle);
272  }
273 
280  bool empty() const {
281  return size() == 0;
282  }
283 
290  iterator find(const value_type &val) const {
291  return CMAGIC_SET_FIND(set_handle, &val);
292  }
293 
294  ~set() {
295  if (*this) {
296  clear();
297  CMAGIC_SET_FREE(set_handle);
298  }
299  }
300 
301 };
302 
303 } // namespace cmagic
304 
305 #endif /* CMAGIC_SET_HPP */
iterator end() const
Return iterator to end.
Definition: set.hpp:213
Definition: set.h:53
size_t size_type
Type used to measure element size.
Definition: set.hpp:38
A container that stores unique elements following a specific order.
Definition: set.hpp:27
#define CMAGIC_SET_FREE(cmagic_set)
Frees the resources allocated by the set before.
Definition: set.h:132
Set of allocation functions. Used in some CMagic structures to specify a desired memory pool...
Definition: memory.h:187
Implementation of a set container.
#define CMAGIC_SET_FIRST(cmagic_set)
Return iterator to the first element in set.
Definition: set.h:201
Set insertion result.
Definition: set.h:60
#define CMAGIC_SET_NEW(key_type, key_comparator, alloc_packet)
Allocates and returns an address of a newly created empty set.
Definition: set.h:124
#define CMAGIC_SET_GET_ALLOC_PACKET(cmagic_set)
Retrieves cmagic_memory_alloc_packet_t associated with the set.
Definition: set.h:251
#define CMAGIC_SET_FIND(cmagic_set, key)
Searches the container for an element equivalent to key and returns an iterator to it if found...
Definition: set.h:233
size_type size() const
Returns the number of elements in the set.
Definition: set.hpp:269
bool already_exists
true if the element already exists in the set and the set was not modified, false if a new element ha...
Definition: set.h:72
#define CMAGIC_SET_CLEAR(cmagic_set)
Removes all elements from the set.
Definition: set.h:185
cmagic_set_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: set.h:66
static set custom_allocation_set()
Constructs an empty set using custom CMagic memory allocation from memory.h.
Definition: set.hpp:134
T value_type
Type of set elements.
Definition: set.hpp:33
#define CMAGIC_SET_ITERATOR_PREV(iterator)
Returns iterator to the previous element in container.
Definition: set.h:225
#define CMAGIC_SET_ERASE_EXT(cmagic_set, key, destructor)
Extended version of CMAGIC_SET_ERASE.
Definition: set.h:168
#define CMAGIC_SET(key_type)
Convenient alias for type*. Returned type of CMAGIC_SET_NEW.
Definition: set.h:113
iterator find(const value_type &val) const
Searches the container for an element equivalent to val and returns an iterator to it if found...
Definition: set.hpp:290
#define CMAGIC_SET_ALLOCATE(cmagic_set, key)
Allocates space for a new element but does not initialize it.
Definition: set.h:145
void clear()
Removes all elements from the set, leaving the container with a size of 0.
Definition: set.hpp:221
iterator begin() const
Return iterator to beginning.
Definition: set.hpp:203
#define CMAGIC_SET_ITERATOR_NEXT(iterator)
Returns iterator to the next element in container.
Definition: set.h:217
#define CMAGIC_SET_SIZE(cmagic_set)
Returns the number of elements in the set.
Definition: set.h:192
void erase(const value_type &val)
Removes a single element from the set.
Definition: set.hpp:258
static const cmagic_memory_alloc_packet_t CMAGIC_MEMORY_ALLOC_PACKET_STD
Allocation from the standard library.
Definition: memory.h:196
std::pair< iterator, bool > insert(value_type &&val)
Inserts a new element to the set if it is not equivalent to any element already contained in the set...
Definition: set.hpp:249
static const cmagic_memory_alloc_packet_t CMAGIC_MEMORY_ALLOC_PACKET_CUSTOM_CMAGIC
Custom allocation from the CMagic library.
Definition: memory.h:203
Definition: set.hpp:40
Definition: map.hpp:19
std::pair< iterator, bool > insert(const value_type &val)
Inserts a new element to the set if it is not equivalent to any element already contained in the set...
Definition: set.hpp:242
bool empty() const
Returns whether the set is empty (i.e. whether its size is 0).
Definition: set.hpp:280