PcapPlusPlus  Next
PointerVector.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cstddef>
4 #include <cstdio>
5 #include <cstdint>
6 #include <stdexcept>
7 #include <vector>
8 #include <memory>
9 #include <type_traits>
10 
11 #include "DeprecationUtils.h"
12 
14 
17 namespace pcpp
18 {
19  namespace internal
20  {
24  template <class T, class Enable = void> struct Copier
25  {
26  std::unique_ptr<T> operator()(const T& obj) const
27  {
28  return std::unique_ptr<T>(new T(obj));
29  }
30  };
31 
34  template <class T> struct Copier<T, typename std::enable_if<std::is_polymorphic<T>::value>::type>
35  {
36  std::unique_ptr<T> operator()(const T& obj) const
37  {
38  // Clone can return unique_ptr or raw pointer.
39  return std::unique_ptr<T>(std::move(obj.clone()));
40  }
41  };
42  } // namespace internal
43 
49  template <typename T, typename Deleter = std::default_delete<T>> class PointerVector
50  {
51  public:
53  using VectorIterator = typename std::vector<T*>::iterator;
54 
56  using ConstVectorIterator = typename std::vector<T*>::const_iterator;
57 
59  PointerVector() = default;
60 
66  PointerVector(const PointerVector& other) : m_Vector(deepCopyUnsafe(other.m_Vector))
67  {}
68 
71  PointerVector(PointerVector&& other) noexcept : m_Vector(std::move(other.m_Vector))
72  {
73  other.m_Vector.clear();
74  }
75 
78  {
79  freeVectorUnsafe(m_Vector);
80  }
81 
87  {
88  // Self-assignment check.
89  if (this == &other)
90  {
91  return *this;
92  }
93 
94  // Saves a copy of the old pointer to defer cleanup.
95  auto oldValues = m_Vector;
96  try
97  {
98  m_Vector = deepCopyUnsafe(other.m_Vector);
99  }
100  // If an exception is thrown during the copy operation, restore old values and rethrow.
101  catch (const std::exception&)
102  {
103  m_Vector = std::move(oldValues);
104  throw;
105  }
106  // Free old values as the new ones have been successfully assigned.
107  freeVectorUnsafe(oldValues);
108  return *this;
109  }
110 
116  {
117  if (this == &other)
118  {
119  return *this;
120  }
121 
122  // Releases all current elements.
123  clear();
124  // Moves the elements of the other vector.
125  m_Vector = std::move(other.m_Vector);
126  // Explicitly clear the other vector as the standard only guarantees an unspecified valid state after move.
127  other.m_Vector.clear();
128  return *this;
129  }
130 
132  void clear()
133  {
134  freeVectorUnsafe(m_Vector);
135  m_Vector.clear();
136  }
137 
139  void pushBack(std::nullptr_t element, bool freeElementOnError = true) = delete;
140 
146  void pushBack(T* element, bool freeElementOnError = true)
147  {
148  if (element == nullptr)
149  {
150  throw std::invalid_argument("Element is nullptr");
151  }
152 
153  try
154  {
155  m_Vector.push_back(element);
156  }
157  catch (const std::exception&)
158  {
159  if (freeElementOnError)
160  {
161  Deleter{}(element);
162  }
163  throw;
164  }
165  }
166 
171  void pushBack(std::unique_ptr<T> element)
172  {
173  if (!element)
174  {
175  throw std::invalid_argument("Element is nullptr");
176  }
177 
178  // Release is called after the raw pointer is already inserted into the vector to prevent
179  // a memory leak if push_back throws.
180  // cppcheck-suppress danglingLifetime
181  m_Vector.push_back(element.get());
182  element.release();
183  }
184 
188  {
189  return m_Vector.begin();
190  }
191 
195  {
196  return m_Vector.begin();
197  }
198 
202  {
203  return m_Vector.end();
204  }
205 
209  {
210  return m_Vector.end();
211  }
212 
215  size_t size() const
216  {
217  return m_Vector.size();
218  }
219 
222  size_t capacity() const
223  {
224  return m_Vector.capacity();
225  }
226 
231  void reserve(size_t size)
232  {
233  m_Vector.reserve(size);
234  }
235 
237  T* front() const
238  {
239  return m_Vector.front();
240  }
241 
243  T* back() const
244  {
245  return m_Vector.back();
246  }
247 
253  {
254  Deleter{}(*position);
255  return m_Vector.erase(position);
256  }
257 
264  {
265  for (auto iter = first; iter != last; ++iter)
266  {
267  Deleter{}(*iter);
268  }
269  return m_Vector.erase(first, last);
270  }
271 
278  PCPP_DEPRECATED("Please use the memory safe 'getAndDetach' instead.")
280  {
281  T* result = *position;
282  position = m_Vector.erase(position);
283  return result;
284  }
285 
289  std::unique_ptr<T> getAndDetach(size_t index)
290  {
291  return getAndDetach(m_Vector.begin() + index);
292  }
293 
298  std::unique_ptr<T> getAndDetach(VectorIterator& position)
299  {
300  std::unique_ptr<T> result(*position);
301  position = m_Vector.erase(position);
302  return result;
303  }
304 
308  std::unique_ptr<T> getAndDetach(const VectorIterator& position)
309  {
310  std::unique_ptr<T> result(*position);
311  m_Vector.erase(position);
312  return result;
313  }
314 
318  T* at(int index) const
319  {
320  return m_Vector.at(index);
321  }
322 
323  private:
327  static std::vector<T*> deepCopyUnsafe(const std::vector<T*>& origin)
328  {
329  std::vector<T*> copyVec;
330  // Allocate the vector initially to ensure no exceptions are thrown during push_back.
331  copyVec.reserve(origin.size());
332 
333  try
334  {
335  for (const auto iter : origin)
336  {
337  std::unique_ptr<T> objCopy = internal::Copier<T>()(*iter);
338  // There shouldn't be a memory leak as the vector is reserved.
339  copyVec.push_back(objCopy.release());
340  }
341  }
342  catch (const std::exception&)
343  {
344  freeVectorUnsafe(copyVec);
345  throw;
346  }
347 
348  return copyVec;
349  }
350 
355  static void freeVectorUnsafe(const std::vector<T*>& origin)
356  {
357  for (auto& obj : origin)
358  {
359  Deleter{}(obj);
360  }
361  }
362 
363  std::vector<T*> m_Vector;
364  };
365 
366 } // namespace pcpp
Definition: PointerVector.h:50
std::unique_ptr< T > getAndDetach(const VectorIterator &position)
Definition: PointerVector.h:308
void pushBack(std::nullptr_t element, bool freeElementOnError=true)=delete
Adding a nullptr to the vector is not allowed.
T * front() const
Definition: PointerVector.h:237
void clear()
Clears all elements of the vector while freeing them.
Definition: PointerVector.h:132
VectorIterator erase(VectorIterator position)
Definition: PointerVector.h:252
T * at(int index) const
Definition: PointerVector.h:318
ConstVectorIterator end() const
Definition: PointerVector.h:208
ConstVectorIterator begin() const
Definition: PointerVector.h:194
VectorIterator erase(ConstVectorIterator first, ConstVectorIterator last)
Definition: PointerVector.h:263
typename std::vector< T * >::iterator VectorIterator
Iterator object that is used for iterating all elements in the vector.
Definition: PointerVector.h:53
PointerVector()=default
A constructor that create an empty instance of this object.
PointerVector & operator=(const PointerVector &other)
Definition: PointerVector.h:86
T * back() const
Definition: PointerVector.h:243
size_t capacity() const
Get the current capacity of the vector.
Definition: PointerVector.h:222
std::unique_ptr< T > getAndDetach(VectorIterator &position)
Definition: PointerVector.h:298
size_t size() const
Definition: PointerVector.h:215
PointerVector(PointerVector &&other) noexcept
Definition: PointerVector.h:71
void pushBack(std::unique_ptr< T > element)
Definition: PointerVector.h:171
PointerVector & operator=(PointerVector &&other) noexcept
Definition: PointerVector.h:115
~PointerVector()
A destructor for this class. The destructor frees all elements that are binded to the vector.
Definition: PointerVector.h:77
VectorIterator begin()
Definition: PointerVector.h:187
typename std::vector< T * >::const_iterator ConstVectorIterator
Const iterator object that is used for iterating all elements in a constant vector.
Definition: PointerVector.h:56
PointerVector(const PointerVector &other)
Definition: PointerVector.h:66
std::unique_ptr< T > getAndDetach(size_t index)
Definition: PointerVector.h:289
void reserve(size_t size)
Reserve storage for the vector.
Definition: PointerVector.h:231
VectorIterator end()
Definition: PointerVector.h:201
T * getAndRemoveFromVector(VectorIterator &position)
Definition: PointerVector.h:279
void pushBack(T *element, bool freeElementOnError=true)
Definition: PointerVector.h:146
The main namespace for the PcapPlusPlus lib.
A helper struct to facilitate the creation of a copy of an object.
Definition: PointerVector.h:25