PcapPlusPlus  Next
PointerVector.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cstddef>
4 #include <stdio.h>
5 #include <stdint.h>
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> class PointerVector
50  {
51  public:
53  using VectorIterator = typename std::vector<T*>::iterator;
54 
56  using ConstVectorIterator = typename std::vector<T*>::const_iterator;
57 
60  {}
61 
67  PointerVector(const PointerVector& other) : m_Vector(deepCopyUnsafe(other.m_Vector))
68  {}
69 
72  PointerVector(PointerVector&& other) noexcept : m_Vector(std::move(other.m_Vector))
73  {
74  other.m_Vector.clear();
75  }
76 
79  {
80  freeVectorUnsafe(m_Vector);
81  }
82 
88  {
89  // Saves a copy of the old pointer to defer cleanup.
90  auto oldValues = m_Vector;
91  try
92  {
93  m_Vector = deepCopyUnsafe(other.m_Vector);
94  }
95  // If an exception is thrown during the copy operation, restore old values and rethrow.
96  catch (const std::exception&)
97  {
98  m_Vector = std::move(oldValues);
99  throw;
100  }
101  // Free old values as the new ones have been successfully assigned.
102  freeVectorUnsafe(oldValues);
103  return *this;
104  }
105 
111  {
112  // Releases all current elements.
113  clear();
114  // Moves the elements of the other vector.
115  m_Vector = std::move(other.m_Vector);
116  // Explicitly clear the other vector as the standard only guarantees an unspecified valid state after move.
117  other.m_Vector.clear();
118  return *this;
119  }
120 
122  void clear()
123  {
124  freeVectorUnsafe(m_Vector);
125  m_Vector.clear();
126  }
127 
129  void pushBack(std::nullptr_t element, bool freeElementOnError = true) = delete;
130 
136  void pushBack(T* element, bool freeElementOnError = true)
137  {
138  if (element == nullptr)
139  {
140  throw std::invalid_argument("Element is nullptr");
141  }
142 
143  try
144  {
145  m_Vector.push_back(element);
146  }
147  catch (const std::exception&)
148  {
149  if (freeElementOnError)
150  {
151  delete element;
152  }
153  throw;
154  }
155  }
156 
161  void pushBack(std::unique_ptr<T> element)
162  {
163  if (!element)
164  {
165  throw std::invalid_argument("Element is nullptr");
166  }
167 
168  // Release is called after the raw pointer is already inserted into the vector to prevent
169  // a memory leak if push_back throws.
170  // cppcheck-suppress danglingLifetime
171  m_Vector.push_back(element.get());
172  element.release();
173  }
174 
178  {
179  return m_Vector.begin();
180  }
181 
185  {
186  return m_Vector.begin();
187  }
188 
192  {
193  return m_Vector.end();
194  }
195 
199  {
200  return m_Vector.end();
201  }
202 
205  size_t size() const
206  {
207  return m_Vector.size();
208  }
209 
211  T* front()
212  {
213  return m_Vector.front();
214  }
215 
217  T const* front() const
218  {
219  return m_Vector.front();
220  }
221 
223  T* back()
224  {
225  return m_Vector.back();
226  }
227 
229  T const* back() const
230  {
231  return m_Vector.back();
232  }
233 
239  {
240  delete (*position);
241  return m_Vector.erase(position);
242  }
243 
250  PCPP_DEPRECATED("Please use the memory safe 'getAndDetach' instead.")
252  {
253  T* result = *position;
254  position = m_Vector.erase(position);
255  return result;
256  }
257 
261  std::unique_ptr<T> getAndDetach(size_t index)
262  {
263  return getAndDetach(m_Vector.begin() + index);
264  }
265 
270  std::unique_ptr<T> getAndDetach(VectorIterator& position)
271  {
272  std::unique_ptr<T> result(*position);
273  position = m_Vector.erase(position);
274  return result;
275  }
276 
280  std::unique_ptr<T> getAndDetach(VectorIterator const& position)
281  {
282  std::unique_ptr<T> result(*position);
283  m_Vector.erase(position);
284  return result;
285  }
286 
290  T* at(int index)
291  {
292  return m_Vector.at(index);
293  }
294 
298  const T* at(int index) const
299  {
300  return m_Vector.at(index);
301  }
302 
303  private:
307  static std::vector<T*> deepCopyUnsafe(std::vector<T*> const& origin)
308  {
309  std::vector<T*> copyVec;
310  // Allocate the vector initially to ensure no exceptions are thrown during push_back.
311  copyVec.reserve(origin.size());
312 
313  try
314  {
315  for (const auto iter : origin)
316  {
317  std::unique_ptr<T> objCopy = internal::Copier<T>()(*iter);
318  // There shouldn't be a memory leak as the vector is reserved.
319  copyVec.push_back(objCopy.release());
320  }
321  }
322  catch (const std::exception&)
323  {
324  for (auto obj : copyVec)
325  {
326  delete obj;
327  }
328  throw;
329  }
330 
331  return copyVec;
332  }
333 
338  static void freeVectorUnsafe(std::vector<T*> const& origin)
339  {
340  for (auto& obj : origin)
341  {
342  delete obj;
343  }
344  }
345 
346  std::vector<T*> m_Vector;
347  };
348 
349 } // namespace pcpp
Definition: PointerVector.h:50
VectorIterator begin()
Definition: PointerVector.h:177
PointerVector()
A constructor that create an empty instance of this object.
Definition: PointerVector.h:59
ConstVectorIterator end() const
Definition: PointerVector.h:198
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
std::unique_ptr< T > getAndDetach(size_t index)
Definition: PointerVector.h:261
T * getAndRemoveFromVector(VectorIterator &position)
Definition: PointerVector.h:251
void pushBack(std::unique_ptr< T > element)
Definition: PointerVector.h:161
VectorIterator erase(VectorIterator position)
Definition: PointerVector.h:238
PointerVector(const PointerVector &other)
Definition: PointerVector.h:67
PointerVector & operator=(const PointerVector &other)
Definition: PointerVector.h:87
std::unique_ptr< T > getAndDetach(VectorIterator const &position)
Definition: PointerVector.h:280
~PointerVector()
A destructor for this class. The destructor frees all elements that are binded to the vector.
Definition: PointerVector.h:78
T const * front() const
Definition: PointerVector.h:217
void pushBack(T *element, bool freeElementOnError=true)
Definition: PointerVector.h:136
T * back()
Definition: PointerVector.h:223
T * at(int index)
Definition: PointerVector.h:290
size_t size() const
Definition: PointerVector.h:205
const T * at(int index) const
Definition: PointerVector.h:298
T * front()
Definition: PointerVector.h:211
PointerVector(PointerVector &&other) noexcept
Definition: PointerVector.h:72
void pushBack(std::nullptr_t element, bool freeElementOnError=true)=delete
Adding a nullptr to the vector is not allowed.
T const * back() const
Definition: PointerVector.h:229
ConstVectorIterator begin() const
Definition: PointerVector.h:184
typename std::vector< T * >::iterator VectorIterator
Iterator object that is used for iterating all elements in the vector.
Definition: PointerVector.h:53
void clear()
Clears all elements of the vector while freeing them.
Definition: PointerVector.h:122
PointerVector & operator=(PointerVector &&other) noexcept
Definition: PointerVector.h:110
std::unique_ptr< T > getAndDetach(VectorIterator &position)
Definition: PointerVector.h:270
VectorIterator end()
Definition: PointerVector.h:191
The main namespace for the PcapPlusPlus lib.
A helper struct to facilitate the creation of a copy of an object.
Definition: PointerVector.h:25