Electroneum
epee::net_utils::buffer Class Reference

#include <buffer.h>

Public Member Functions

 buffer (size_t reserve=0)
 
void append (const void *data, size_t sz)
 
void erase (size_t sz)
 
epee::span< const uint8_tspan (size_t sz) const
 
epee::span< const uint8_tcarve (size_t sz)
 
size_t size () const
 

Detailed Description

Definition at line 45 of file buffer.h.

Constructor & Destructor Documentation

◆ buffer()

epee::net_utils::buffer::buffer ( size_t  reserve = 0)
inline

Definition at line 48 of file buffer.h.

48 : offset(0) { storage.reserve(reserve); }

Member Function Documentation

◆ append()

void epee::net_utils::buffer::append ( const void *  data,
size_t  sz 
)

Definition at line 40 of file buffer.cpp.

41 {
42  const size_t capacity = storage.capacity();
43  const size_t avail = capacity - storage.size();
44 
45  CHECK_AND_ASSERT_THROW_MES(storage.size() < std::numeric_limits<size_t>::max() - sz, "Too much data to append");
46 
47  // decide when to move
48  if (sz > avail)
49  {
50  // we have to reallocate or move
51  const bool move = size() + sz <= capacity;
52  if (move)
53  {
54  const size_t bytes = storage.size() - offset;
55  NET_BUFFER_LOG("appending " << sz << " from " << size() << " by moving " << bytes << " from offset " << offset << " first (forced)");
56  memmove(storage.data(), storage.data() + offset, bytes);
57  storage.resize(bytes);
58  offset = 0;
59  }
60  else
61  {
62  NET_BUFFER_LOG("appending " << sz << " from " << size() << " by reallocating");
63  std::vector<uint8_t> new_storage;
64  size_t reserve = (((size() + sz) * 3 / 2) + 4095) & ~4095;
65  new_storage.reserve(reserve);
66  new_storage.resize(size());
67  if (size() > 0)
68  memcpy(new_storage.data(), storage.data() + offset, storage.size() - offset);
69  offset = 0;
70  std::swap(storage, new_storage);
71  }
72  }
73  else
74  {
75  // we have space already
76  if (size() <= 4096 && offset > 4096 * 16 && offset >= capacity / 2)
77  {
78  // we have little to move, and we're far enough into the buffer that it's probably a win to move anyway
79  const size_t pos = storage.size() - offset;
80  NET_BUFFER_LOG("appending " << sz << " from " << size() << " by moving " << pos << " from offset " << offset << " first (unforced)");
81  memmove(storage.data(), storage.data() + offset, storage.size() - offset);
82  storage.resize(pos);
83  offset = 0;
84  }
85  else
86  {
87  NET_BUFFER_LOG("appending " << sz << " from " << size() << " by writing to existing capacity");
88  }
89  }
90 
91  // add the new data
92  storage.insert(storage.end(), (const uint8_t*)data, (const uint8_t*)data + sz);
93 
94  NET_BUFFER_LOG("storage now " << offset << "/" << storage.size() << "/" << storage.capacity());
95 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
#define NET_BUFFER_LOG(x)
Definition: buffer.h:39
unsigned char uint8_t
Definition: stdint.h:124
size_t size() const
Definition: buffer.h:55
const T & move(const T &t)
Definition: gtest-port.h:1317
void * memcpy(void *a, const void *b, size_t c)
void * memmove(void *a, const void *b, size_t c)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ carve()

epee::span<const uint8_t> epee::net_utils::buffer::carve ( size_t  sz)
inline

Definition at line 54 of file buffer.h.

54 { CHECK_AND_ASSERT_THROW_MES(sz <= size(), "span is too large"); offset += sz; return epee::span<const uint8_t>(storage.data() + offset - sz, sz); }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
Non-owning sequence of data. Does not deep copy.
Definition: span.h:56
size_t size() const
Definition: buffer.h:55
Here is the call graph for this function:
Here is the caller graph for this function:

◆ erase()

void epee::net_utils::buffer::erase ( size_t  sz)
inline

Definition at line 51 of file buffer.h.

51 { NET_BUFFER_LOG("erasing " << sz << "/" << size()); CHECK_AND_ASSERT_THROW_MES(offset + sz <= storage.size(), "erase: sz too large"); offset += sz; if (offset == storage.size()) { storage.resize(0); offset = 0; } }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
#define NET_BUFFER_LOG(x)
Definition: buffer.h:39
size_t size() const
Definition: buffer.h:55
Here is the call graph for this function:
Here is the caller graph for this function:

◆ size()

size_t epee::net_utils::buffer::size ( ) const
inline

Definition at line 55 of file buffer.h.

55 { return storage.size() - offset; }
Here is the caller graph for this function:

◆ span()

epee::span<const uint8_t> epee::net_utils::buffer::span ( size_t  sz) const
inline

Definition at line 52 of file buffer.h.

52 { CHECK_AND_ASSERT_THROW_MES(sz <= size(), "span is too large"); return epee::span<const uint8_t>(storage.data() + offset, sz); }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
Non-owning sequence of data. Does not deep copy.
Definition: span.h:56
size_t size() const
Definition: buffer.h:55
Here is the call graph for this function:
Here is the caller graph for this function:

The documentation for this class was generated from the following files: