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 
19 namespace pcpp
20 {
21  namespace internal
22  {
28  template <class T, class Enable = void> struct Copier
29  {
30  std::unique_ptr<T> operator()(const T& obj) const
31  {
32  return std::unique_ptr<T>(new T(obj));
33  }
34  };
35 
40  template <class T> struct Copier<T, typename std::enable_if<std::is_polymorphic<T>::value>::type>
41  {
42  std::unique_ptr<T> operator()(const T& obj) const
43  {
44  // Clone can return unique_ptr or raw pointer.
45  return std::unique_ptr<T>(std::move(obj.clone()));
46  }
47  };
48  } // namespace internal
49 
57  template <typename T> class PointerVector
58  {
59  public:
63  using VectorIterator = typename std::vector<T*>::iterator;
64 
68  using ConstVectorIterator = typename std::vector<T*>::const_iterator;
69 
74  {}
75 
83  PointerVector(const PointerVector& other) : m_Vector(deepCopyUnsafe(other.m_Vector))
84  {}
85 
90  PointerVector(PointerVector&& other) noexcept : m_Vector(std::move(other.m_Vector))
91  {
92  other.m_Vector.clear();
93  }
94 
99  {
100  freeVectorUnsafe(m_Vector);
101  }
102 
110  {
111  // Saves a copy of the old pointer to defer cleanup.
112  auto oldValues = m_Vector;
113  try
114  {
115  m_Vector = deepCopyUnsafe(other.m_Vector);
116  }
117  // If an exception is thrown during the copy operation, restore old values and rethrow.
118  catch (const std::exception&)
119  {
120  m_Vector = std::move(oldValues);
121  throw;
122  }
123  // Free old values as the new ones have been successfully assigned.
124  freeVectorUnsafe(oldValues);
125  return *this;
126  }
127 
135  {
136  // Releases all current elements.
137  clear();
138  // Moves the elements of the other vector.
139  m_Vector = std::move(other.m_Vector);
140  // Explicitly clear the other vector as the standard only guarantees an unspecified valid state after move.
141  other.m_Vector.clear();
142  return *this;
143  }
144 
148  void clear()
149  {
150  freeVectorUnsafe(m_Vector);
151  m_Vector.clear();
152  }
153 
157  void pushBack(std::nullptr_t element, bool freeElementOnError = true) = delete;
158 
165  void pushBack(T* element, bool freeElementOnError = true)
166  {
167  if (element == nullptr)
168  {
169  throw std::invalid_argument("Element is nullptr");
170  }
171 
172  try
173  {
174  m_Vector.push_back(element);
175  }
176  catch (const std::exception&)
177  {
178  if (freeElementOnError)
179  {
180  delete element;
181  }
182  throw;
183  }
184  }
185 
192  void pushBack(std::unique_ptr<T> element)
193  {
194  if (!element)
195  {
196  throw std::invalid_argument("Element is nullptr");
197  }
198 
199  // Release is called after the raw pointer is already inserted into the vector to prevent
200  // a memory leak if push_back throws.
201  // cppcheck-suppress danglingLifetime
202  m_Vector.push_back(element.get());
203  element.release();
204  }
205 
211  {
212  return m_Vector.begin();
213  }
214 
220  {
221  return m_Vector.begin();
222  }
223 
229  {
230  return m_Vector.end();
231  }
232 
238  {
239  return m_Vector.end();
240  }
241 
246  size_t size() const
247  {
248  return m_Vector.size();
249  }
250 
254  T* front()
255  {
256  return m_Vector.front();
257  }
258 
262  T const* front() const
263  {
264  return m_Vector.front();
265  }
266 
270  T* back()
271  {
272  return m_Vector.back();
273  }
274 
275  /*
276  * @return A pointer to the last element in the vector.
277  */
278  T const* back() const
279  {
280  return m_Vector.back();
281  }
282 
290  {
291  delete (*position);
292  return m_Vector.erase(position);
293  }
294 
303  PCPP_DEPRECATED("Please use the memory safe 'getAndDetach' instead.")
305  {
306  T* result = *position;
307  position = m_Vector.erase(position);
308  return result;
309  }
310 
316  std::unique_ptr<T> getAndDetach(size_t index)
317  {
318  return getAndDetach(m_Vector.begin() + index);
319  }
320 
327  std::unique_ptr<T> getAndDetach(VectorIterator& position)
328  {
329  std::unique_ptr<T> result(*position);
330  position = m_Vector.erase(position);
331  return result;
332  }
333 
339  std::unique_ptr<T> getAndDetach(VectorIterator const& position)
340  {
341  std::unique_ptr<T> result(*position);
342  m_Vector.erase(position);
343  return result;
344  }
345 
351  T* at(int index)
352  {
353  return m_Vector.at(index);
354  }
355 
361  const T* at(int index) const
362  {
363  return m_Vector.at(index);
364  }
365 
366  private:
372  static std::vector<T*> deepCopyUnsafe(std::vector<T*> const& origin)
373  {
374  std::vector<T*> copyVec;
375  // Allocate the vector initially to ensure no exceptions are thrown during push_back.
376  copyVec.reserve(origin.size());
377 
378  try
379  {
380  for (const auto iter : origin)
381  {
382  std::unique_ptr<T> objCopy = internal::Copier<T>()(*iter);
383  // There shouldn't be a memory leak as the vector is reserved.
384  copyVec.push_back(objCopy.release());
385  }
386  }
387  catch (const std::exception&)
388  {
389  for (auto obj : copyVec)
390  {
391  delete obj;
392  }
393  throw;
394  }
395 
396  return copyVec;
397  }
398 
405  static void freeVectorUnsafe(std::vector<T*> const& origin)
406  {
407  for (auto& obj : origin)
408  {
409  delete obj;
410  }
411  }
412 
413  std::vector<T*> m_Vector;
414  };
415 
416 } // namespace pcpp
Definition: PointerVector.h:58
VectorIterator begin()
Definition: PointerVector.h:210
PointerVector()
Definition: PointerVector.h:73
ConstVectorIterator end() const
Definition: PointerVector.h:237
typename std::vector< T * >::const_iterator ConstVectorIterator
Definition: PointerVector.h:68
std::unique_ptr< T > getAndDetach(size_t index)
Definition: PointerVector.h:316
T * getAndRemoveFromVector(VectorIterator &position)
Definition: PointerVector.h:304
void pushBack(std::unique_ptr< T > element)
Definition: PointerVector.h:192
VectorIterator erase(VectorIterator position)
Definition: PointerVector.h:289
PointerVector(const PointerVector &other)
Definition: PointerVector.h:83
PointerVector & operator=(const PointerVector &other)
Definition: PointerVector.h:109
std::unique_ptr< T > getAndDetach(VectorIterator const &position)
Definition: PointerVector.h:339
~PointerVector()
Definition: PointerVector.h:98
T const * front() const
Definition: PointerVector.h:262
void pushBack(T *element, bool freeElementOnError=true)
Definition: PointerVector.h:165
T * back()
Definition: PointerVector.h:270
T * at(int index)
Definition: PointerVector.h:351
size_t size() const
Definition: PointerVector.h:246
const T * at(int index) const
Definition: PointerVector.h:361
T * front()
Definition: PointerVector.h:254
PointerVector(PointerVector &&other) noexcept
Definition: PointerVector.h:90
void pushBack(std::nullptr_t element, bool freeElementOnError=true)=delete
ConstVectorIterator begin() const
Definition: PointerVector.h:219
typename std::vector< T * >::iterator VectorIterator
Definition: PointerVector.h:63
void clear()
Definition: PointerVector.h:148
PointerVector & operator=(PointerVector &&other) noexcept
Definition: PointerVector.h:134
std::unique_ptr< T > getAndDetach(VectorIterator &position)
Definition: PointerVector.h:327
VectorIterator end()
Definition: PointerVector.h:228
The main namespace for the PcapPlusPlus lib.
A helper struct to facilitate the creation of a copy of an object.
Definition: PointerVector.h:29