mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-19 19:52:15 +02:00
Move BufferType impl into ConstBufferType
This commit is contained in:
parent
28787e03a1
commit
8443be9f6d
@ -163,6 +163,10 @@ class BufferException : public std::exception
|
||||
|
||||
template <typename T, typename R>
|
||||
class BufferAllocatedType;
|
||||
|
||||
template <typename T>
|
||||
class BufferType;
|
||||
|
||||
template <typename T>
|
||||
class ConstBufferType
|
||||
{
|
||||
@ -171,6 +175,9 @@ class ConstBufferType
|
||||
template <typename, typename>
|
||||
friend class BufferAllocatedType;
|
||||
|
||||
template <typename>
|
||||
friend class BufferType;
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T *type;
|
||||
@ -194,7 +201,8 @@ class ConstBufferType
|
||||
ConstBufferType(const U *data, const size_t size, const bool filled);
|
||||
|
||||
// const index into array
|
||||
const T &operator[](const size_t index) const;
|
||||
auto &operator[](const size_t index) const;
|
||||
auto &operator[](const size_t index);
|
||||
|
||||
void init_headroom(const size_t headroom);
|
||||
void reset_offset(const size_t offset);
|
||||
@ -253,8 +261,8 @@ class ConstBufferType
|
||||
|
||||
void read(NCT *data, const size_t size);
|
||||
void read(void *data, const size_t size);
|
||||
const T *read_alloc(const size_t size);
|
||||
ConstBufferType read_alloc_buf(const size_t size);
|
||||
auto *read_alloc(const size_t size);
|
||||
auto read_alloc_buf(const size_t size);
|
||||
|
||||
// return the maximum allowable size value in T objects given the current offset (without considering resize)
|
||||
size_t max_size() const;
|
||||
@ -277,6 +285,43 @@ class ConstBufferType
|
||||
bool operator==(const ConstBufferType &other) const;
|
||||
bool operator!=(const ConstBufferType &other) const;
|
||||
|
||||
protected:
|
||||
void reserve(const size_t n);
|
||||
T *data();
|
||||
T *data_end();
|
||||
T *data_raw();
|
||||
size_t remaining(const size_t tailroom = 0) const;
|
||||
size_t max_size_tailroom(const size_t tailroom) const;
|
||||
void push_back(const T &value);
|
||||
void push_front(const T &value);
|
||||
void set_trailer(const T &value);
|
||||
void null_terminate();
|
||||
T *index(const size_t index);
|
||||
|
||||
#ifndef OPENVPN_NO_IO
|
||||
openvpn_io::mutable_buffer mutable_buffer(const size_t tailroom = 0);
|
||||
openvpn_io::mutable_buffer mutable_buffer_append(const size_t tailroom = 0);
|
||||
openvpn_io::mutable_buffer mutable_buffer_clamp(const size_t tailroom = 0);
|
||||
openvpn_io::mutable_buffer mutable_buffer_append_clamp(const size_t tailroom = 0);
|
||||
#endif
|
||||
|
||||
void realign(size_t headroom);
|
||||
void write(const T *data, const size_t size);
|
||||
void write(const void *data, const size_t size);
|
||||
void prepend(const T *data, const size_t size);
|
||||
void prepend(const void *data, const size_t size);
|
||||
T *write_alloc(const size_t size);
|
||||
T *prepend_alloc(const size_t size);
|
||||
void reset(const size_t min_capacity, const unsigned int flags);
|
||||
void reset(const size_t headroom, const size_t min_capacity, const unsigned int flags);
|
||||
template <typename B>
|
||||
void append(const B &other);
|
||||
|
||||
virtual void reset_impl(const size_t min_capacity, const unsigned int flags);
|
||||
virtual void resize(const size_t new_capacity);
|
||||
void buffer_full_error(const size_t newcap, const bool allocated) const;
|
||||
|
||||
|
||||
protected:
|
||||
ConstBufferType(T *data, const size_t offset, const size_t size, const size_t capacity);
|
||||
|
||||
@ -334,13 +379,24 @@ ConstBufferType<T>::ConstBufferType(const U *data, const size_t size, const bool
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T &ConstBufferType<T>::operator[](const size_t index) const
|
||||
auto &ConstBufferType<T>::operator[](const size_t index) const
|
||||
{
|
||||
if (index >= size_)
|
||||
OPENVPN_BUFFER_THROW(buffer_const_index);
|
||||
return c_data()[index];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto &ConstBufferType<T>::operator[](const size_t index)
|
||||
{
|
||||
if (index >= size_)
|
||||
OPENVPN_BUFFER_THROW(buffer_const_index);
|
||||
if constexpr (std::is_same_v<ConstBufferType<T>, decltype(*this)>)
|
||||
return c_data()[index];
|
||||
else
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::init_headroom(const size_t headroom)
|
||||
{
|
||||
@ -533,11 +589,16 @@ void ConstBufferType<T>::read(void *data, const size_t size)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T *ConstBufferType<T>::read_alloc(const size_t size)
|
||||
auto *ConstBufferType<T>::read_alloc(const size_t size)
|
||||
{
|
||||
if (size <= size_)
|
||||
{
|
||||
const T *ret = c_data();
|
||||
using retT = std::conditional_t<std::is_same_v<decltype(*this), ConstBufferType<T>>, const value_type, value_type>;
|
||||
retT *ret;
|
||||
if constexpr (std::is_const_v<retT>)
|
||||
ret = c_data();
|
||||
else
|
||||
ret = data();
|
||||
offset_ += size;
|
||||
size_ -= size;
|
||||
return ret;
|
||||
@ -547,11 +608,12 @@ const T *ConstBufferType<T>::read_alloc(const size_t size)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ConstBufferType<T> ConstBufferType<T>::read_alloc_buf(const size_t size)
|
||||
auto ConstBufferType<T>::read_alloc_buf(const size_t size)
|
||||
{
|
||||
if (size <= size_)
|
||||
{
|
||||
ConstBufferType ret(data_, offset_, size, capacity_);
|
||||
using retT = std::conditional_t<std::is_same_v<decltype(*this), ConstBufferType<T>>, ConstBufferType<T>, BufferType<T>>;
|
||||
retT ret(data_, offset_, size, capacity_);
|
||||
offset_ += size;
|
||||
size_ -= size;
|
||||
return ret;
|
||||
@ -629,6 +691,216 @@ ConstBufferType<T>::ConstBufferType(const U *data, const size_t offset, const si
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::reserve(const size_t n)
|
||||
{
|
||||
if (n > capacity_)
|
||||
resize(n);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *ConstBufferType<T>::data()
|
||||
{
|
||||
return data_ + offset_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *ConstBufferType<T>::data_end()
|
||||
{
|
||||
return data_ + offset_ + size_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *ConstBufferType<T>::data_raw()
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t ConstBufferType<T>::remaining(const size_t tailroom) const
|
||||
{
|
||||
const size_t r = capacity_ - (offset_ + size_ + tailroom);
|
||||
return r <= capacity_ ? r : 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t ConstBufferType<T>::max_size_tailroom(const size_t tailroom) const
|
||||
{
|
||||
const size_t r = capacity_ - (offset_ + tailroom);
|
||||
return r <= capacity_ ? r : 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::push_back(const T &value)
|
||||
{
|
||||
if (!remaining())
|
||||
resize(offset_ + size_ + 1);
|
||||
*(data() + size_++) = value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::push_front(const T &value)
|
||||
{
|
||||
if (!offset_)
|
||||
OPENVPN_BUFFER_THROW(buffer_push_front_headroom);
|
||||
--offset_;
|
||||
++size_;
|
||||
*data() = value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::set_trailer(const T &value)
|
||||
{
|
||||
if (!remaining())
|
||||
resize(offset_ + size_ + 1);
|
||||
*(data() + size_) = value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::null_terminate()
|
||||
{
|
||||
if (empty() || back())
|
||||
push_back(0);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *ConstBufferType<T>::index(const size_t index)
|
||||
{
|
||||
if (index >= size_)
|
||||
OPENVPN_BUFFER_THROW(buffer_index);
|
||||
return &data()[index];
|
||||
}
|
||||
|
||||
#ifndef OPENVPN_NO_IO
|
||||
template <typename T>
|
||||
openvpn_io::mutable_buffer ConstBufferType<T>::mutable_buffer(const size_t tailroom)
|
||||
{
|
||||
return openvpn_io::mutable_buffer(data(), max_size_tailroom(tailroom));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
openvpn_io::mutable_buffer ConstBufferType<T>::mutable_buffer_append(const size_t tailroom)
|
||||
{
|
||||
return openvpn_io::mutable_buffer(data_end(), remaining(tailroom));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
openvpn_io::mutable_buffer ConstBufferType<T>::mutable_buffer_clamp(const size_t tailroom)
|
||||
{
|
||||
return openvpn_io::mutable_buffer(data(), buf_clamp_read(max_size_tailroom(tailroom)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
openvpn_io::mutable_buffer ConstBufferType<T>::mutable_buffer_append_clamp(const size_t tailroom)
|
||||
{
|
||||
return openvpn_io::mutable_buffer(data_end(), buf_clamp_read(remaining(tailroom)));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::realign(size_t headroom)
|
||||
{
|
||||
if (headroom != offset_)
|
||||
{
|
||||
if (headroom + size_ > capacity_)
|
||||
OPENVPN_BUFFER_THROW(buffer_headroom);
|
||||
std::memmove(data_ + headroom, data_ + offset_, size_);
|
||||
offset_ = headroom;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::write(const T *data, const size_t size)
|
||||
{
|
||||
std::memcpy(write_alloc(size), data, size * sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::write(const void *data, const size_t size)
|
||||
{
|
||||
write((const T *)data, size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::prepend(const T *data, const size_t size)
|
||||
{
|
||||
std::memcpy(prepend_alloc(size), data, size * sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::prepend(const void *data, const size_t size)
|
||||
{
|
||||
prepend((const T *)data, size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *ConstBufferType<T>::write_alloc(const size_t size)
|
||||
{
|
||||
if (size > remaining())
|
||||
resize(offset_ + size_ + size);
|
||||
T *ret = data() + size_;
|
||||
size_ += size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *ConstBufferType<T>::prepend_alloc(const size_t size)
|
||||
{
|
||||
if (size <= offset_)
|
||||
{
|
||||
offset_ -= size;
|
||||
size_ += size;
|
||||
return data();
|
||||
}
|
||||
else
|
||||
OPENVPN_BUFFER_THROW(buffer_headroom);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::reset(const size_t min_capacity, const unsigned int flags)
|
||||
{
|
||||
if (min_capacity > capacity_)
|
||||
reset_impl(min_capacity, flags);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::reset(const size_t headroom, const size_t min_capacity, const unsigned int flags)
|
||||
{
|
||||
reset(min_capacity, flags);
|
||||
init_headroom(headroom);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename B>
|
||||
void ConstBufferType<T>::append(const B &other)
|
||||
{
|
||||
write(other.c_data(), other.size());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::reset_impl(const size_t min_capacity, const unsigned int flags)
|
||||
{
|
||||
OPENVPN_BUFFER_THROW(buffer_no_reset_impl);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::resize(const size_t new_capacity)
|
||||
{
|
||||
if (new_capacity > capacity_)
|
||||
buffer_full_error(new_capacity, false);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ConstBufferType<T>::buffer_full_error(const size_t newcap, const bool allocated) const
|
||||
{
|
||||
#ifdef OPENVPN_BUFFER_ABORT
|
||||
std::abort();
|
||||
#else
|
||||
throw BufferException(BufferException::buffer_full, "allocated=" + std::to_string(allocated) + " size=" + std::to_string(size_) + " offset=" + std::to_string(offset_) + " capacity=" + std::to_string(capacity_) + " newcap=" + std::to_string(newcap));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class BufferType : public ConstBufferType<T>
|
||||
{
|
||||
@ -637,61 +909,51 @@ class BufferType : public ConstBufferType<T>
|
||||
template <typename, typename>
|
||||
friend class BufferAllocatedType;
|
||||
|
||||
protected:
|
||||
using ConstBufferType<T>::data_;
|
||||
using ConstBufferType<T>::offset_;
|
||||
using ConstBufferType<T>::size_;
|
||||
using ConstBufferType<T>::capacity_;
|
||||
template <typename>
|
||||
friend class ConstBufferType;
|
||||
|
||||
public:
|
||||
using ConstBufferType<T>::empty;
|
||||
using ConstBufferType<T>::capacity;
|
||||
using ConstBufferType<T>::offset;
|
||||
using ConstBufferType<T>::back;
|
||||
using ConstBufferType<T>::init_headroom;
|
||||
using ConstBufferType<T>::operator[];
|
||||
using ConstBufferType<T>::reserve;
|
||||
using ConstBufferType<T>::data;
|
||||
using ConstBufferType<T>::data_end;
|
||||
using ConstBufferType<T>::data_raw;
|
||||
using ConstBufferType<T>::remaining;
|
||||
using ConstBufferType<T>::max_size_tailroom;
|
||||
using ConstBufferType<T>::push_back;
|
||||
using ConstBufferType<T>::push_front;
|
||||
using ConstBufferType<T>::set_trailer;
|
||||
using ConstBufferType<T>::null_terminate;
|
||||
using ConstBufferType<T>::index;
|
||||
#ifndef OPENVPN_NO_IO
|
||||
using ConstBufferType<T>::mutable_buffer;
|
||||
using ConstBufferType<T>::mutable_buffer_append;
|
||||
using ConstBufferType<T>::mutable_buffer_clamp;
|
||||
using ConstBufferType<T>::mutable_buffer_append_clamp;
|
||||
#endif
|
||||
using ConstBufferType<T>::realign;
|
||||
using ConstBufferType<T>::write;
|
||||
using ConstBufferType<T>::prepend;
|
||||
using ConstBufferType<T>::write_alloc;
|
||||
using ConstBufferType<T>::prepend_alloc;
|
||||
using ConstBufferType<T>::reset;
|
||||
using ConstBufferType<T>::append;
|
||||
using ConstBufferType<T>::reset_impl;
|
||||
using ConstBufferType<T>::resize;
|
||||
using ConstBufferType<T>::buffer_full_error;
|
||||
|
||||
|
||||
BufferType();
|
||||
BufferType(void *data, const size_t size, const bool filled);
|
||||
BufferType(T *data, const size_t size, const bool filled);
|
||||
|
||||
void reserve(const size_t n);
|
||||
T *data();
|
||||
T *data_end();
|
||||
T *data_raw();
|
||||
size_t remaining(const size_t tailroom = 0) const;
|
||||
size_t max_size_tailroom(const size_t tailroom) const;
|
||||
void push_back(const T &value);
|
||||
void push_front(const T &value);
|
||||
void set_trailer(const T &value);
|
||||
void null_terminate();
|
||||
T &operator[](const size_t index);
|
||||
T *index(const size_t index);
|
||||
|
||||
#ifndef OPENVPN_NO_IO
|
||||
openvpn_io::mutable_buffer mutable_buffer(const size_t tailroom = 0);
|
||||
openvpn_io::mutable_buffer mutable_buffer_append(const size_t tailroom = 0);
|
||||
openvpn_io::mutable_buffer mutable_buffer_clamp(const size_t tailroom = 0);
|
||||
openvpn_io::mutable_buffer mutable_buffer_append_clamp(const size_t tailroom = 0);
|
||||
#endif
|
||||
|
||||
void realign(size_t headroom);
|
||||
void write(const T *data, const size_t size);
|
||||
void write(const void *data, const size_t size);
|
||||
void prepend(const T *data, const size_t size);
|
||||
void prepend(const void *data, const size_t size);
|
||||
T *write_alloc(const size_t size);
|
||||
T *prepend_alloc(const size_t size);
|
||||
T *read_alloc(const size_t size);
|
||||
BufferType read_alloc_buf(const size_t size);
|
||||
void reset(const size_t min_capacity, const unsigned int flags);
|
||||
void reset(const size_t headroom, const size_t min_capacity, const unsigned int flags);
|
||||
template <typename B>
|
||||
void append(const B &other);
|
||||
|
||||
protected:
|
||||
BufferType(T *data, const size_t offset, const size_t size, const size_t capacity);
|
||||
virtual void reset_impl(const size_t min_capacity, const unsigned int flags);
|
||||
virtual void resize(const size_t new_capacity);
|
||||
void buffer_full_error(const size_t newcap, const bool allocated) const;
|
||||
};
|
||||
|
||||
// Member function definitions
|
||||
@ -713,257 +975,12 @@ BufferType<T>::BufferType(T *data, const size_t size, const bool filled)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BufferType<T>::reserve(const size_t n)
|
||||
{
|
||||
if (n > capacity_)
|
||||
resize(n);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *BufferType<T>::data()
|
||||
{
|
||||
return data_ + offset_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *BufferType<T>::data_end()
|
||||
{
|
||||
return data_ + offset_ + size_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *BufferType<T>::data_raw()
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t BufferType<T>::remaining(const size_t tailroom) const
|
||||
{
|
||||
const size_t r = capacity_ - (offset_ + size_ + tailroom);
|
||||
return r <= capacity_ ? r : 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t BufferType<T>::max_size_tailroom(const size_t tailroom) const
|
||||
{
|
||||
const size_t r = capacity_ - (offset_ + tailroom);
|
||||
return r <= capacity_ ? r : 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BufferType<T>::push_back(const T &value)
|
||||
{
|
||||
if (!remaining())
|
||||
resize(offset_ + size_ + 1);
|
||||
*(data() + size_++) = value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BufferType<T>::push_front(const T &value)
|
||||
{
|
||||
if (!offset_)
|
||||
OPENVPN_BUFFER_THROW(buffer_push_front_headroom);
|
||||
--offset_;
|
||||
++size_;
|
||||
*data() = value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BufferType<T>::set_trailer(const T &value)
|
||||
{
|
||||
if (!remaining())
|
||||
resize(offset_ + size_ + 1);
|
||||
*(data() + size_) = value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BufferType<T>::null_terminate()
|
||||
{
|
||||
if (empty() || back())
|
||||
push_back(0);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T &BufferType<T>::operator[](const size_t index)
|
||||
{
|
||||
if (index >= size_)
|
||||
OPENVPN_BUFFER_THROW(buffer_index);
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *BufferType<T>::index(const size_t index)
|
||||
{
|
||||
if (index >= size_)
|
||||
OPENVPN_BUFFER_THROW(buffer_index);
|
||||
return &data()[index];
|
||||
}
|
||||
|
||||
#ifndef OPENVPN_NO_IO
|
||||
template <typename T>
|
||||
openvpn_io::mutable_buffer BufferType<T>::mutable_buffer(const size_t tailroom)
|
||||
{
|
||||
return openvpn_io::mutable_buffer(data(), max_size_tailroom(tailroom));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
openvpn_io::mutable_buffer BufferType<T>::mutable_buffer_append(const size_t tailroom)
|
||||
{
|
||||
return openvpn_io::mutable_buffer(data_end(), remaining(tailroom));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
openvpn_io::mutable_buffer BufferType<T>::mutable_buffer_clamp(const size_t tailroom)
|
||||
{
|
||||
return openvpn_io::mutable_buffer(data(), buf_clamp_read(max_size_tailroom(tailroom)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
openvpn_io::mutable_buffer BufferType<T>::mutable_buffer_append_clamp(const size_t tailroom)
|
||||
{
|
||||
return openvpn_io::mutable_buffer(data_end(), buf_clamp_read(remaining(tailroom)));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
void BufferType<T>::realign(size_t headroom)
|
||||
{
|
||||
if (headroom != offset_)
|
||||
{
|
||||
if (headroom + size_ > capacity_)
|
||||
OPENVPN_BUFFER_THROW(buffer_headroom);
|
||||
std::memmove(data_ + headroom, data_ + offset_, size_);
|
||||
offset_ = headroom;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BufferType<T>::write(const T *data, const size_t size)
|
||||
{
|
||||
std::memcpy(write_alloc(size), data, size * sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BufferType<T>::write(const void *data, const size_t size)
|
||||
{
|
||||
write((const T *)data, size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BufferType<T>::prepend(const T *data, const size_t size)
|
||||
{
|
||||
std::memcpy(prepend_alloc(size), data, size * sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BufferType<T>::prepend(const void *data, const size_t size)
|
||||
{
|
||||
prepend((const T *)data, size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *BufferType<T>::write_alloc(const size_t size)
|
||||
{
|
||||
if (size > remaining())
|
||||
resize(offset_ + size_ + size);
|
||||
T *ret = data() + size_;
|
||||
size_ += size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *BufferType<T>::prepend_alloc(const size_t size)
|
||||
{
|
||||
if (size <= offset_)
|
||||
{
|
||||
offset_ -= size;
|
||||
size_ += size;
|
||||
return data();
|
||||
}
|
||||
else
|
||||
OPENVPN_BUFFER_THROW(buffer_headroom);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *BufferType<T>::read_alloc(const size_t size)
|
||||
{
|
||||
if (size <= size_)
|
||||
{
|
||||
T *ret = data();
|
||||
offset_ += size;
|
||||
size_ -= size;
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
OPENVPN_BUFFER_THROW(buffer_underflow);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
BufferType<T> BufferType<T>::read_alloc_buf(const size_t size)
|
||||
{
|
||||
if (size <= size_)
|
||||
{
|
||||
BufferType ret(data_, offset_, size, capacity_);
|
||||
offset_ += size;
|
||||
size_ -= size;
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
OPENVPN_BUFFER_THROW(buffer_underflow);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BufferType<T>::reset(const size_t min_capacity, const unsigned int flags)
|
||||
{
|
||||
if (min_capacity > capacity_)
|
||||
reset_impl(min_capacity, flags);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BufferType<T>::reset(const size_t headroom, const size_t min_capacity, const unsigned int flags)
|
||||
{
|
||||
reset(min_capacity, flags);
|
||||
init_headroom(headroom);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename B>
|
||||
void BufferType<T>::append(const B &other)
|
||||
{
|
||||
write(other.c_data(), other.size());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
BufferType<T>::BufferType(T *data, const size_t offset, const size_t size, const size_t capacity)
|
||||
: ConstBufferType<T>(data, offset, size, capacity)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BufferType<T>::reset_impl(const size_t min_capacity, const unsigned int flags)
|
||||
{
|
||||
OPENVPN_BUFFER_THROW(buffer_no_reset_impl);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BufferType<T>::resize(const size_t new_capacity)
|
||||
{
|
||||
if (new_capacity > capacity_)
|
||||
buffer_full_error(new_capacity, false);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BufferType<T>::buffer_full_error(const size_t newcap, const bool allocated) const
|
||||
{
|
||||
#ifdef OPENVPN_BUFFER_ABORT
|
||||
std::abort();
|
||||
#else
|
||||
throw BufferException(BufferException::buffer_full, "allocated=" + std::to_string(allocated) + " size=" + std::to_string(size_) + " offset=" + std::to_string(offset_) + " capacity=" + std::to_string(capacity_) + " newcap=" + std::to_string(newcap));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T, typename R>
|
||||
class BufferAllocatedType : public BufferType<T>, public RC<R>
|
||||
{
|
||||
@ -980,6 +997,14 @@ class BufferAllocatedType : public BufferType<T>, public RC<R>
|
||||
public:
|
||||
using BufferType<T>::init_headroom;
|
||||
using BufferType<T>::buffer_full_error;
|
||||
using BufferType<T>::size;
|
||||
using BufferType<T>::capacity;
|
||||
using BufferType<T>::offset;
|
||||
using BufferType<T>::data_raw;
|
||||
using BufferType<T>::c_data_raw;
|
||||
using BufferType<T>::data;
|
||||
using BufferType<T>::c_data;
|
||||
using BufferType<T>::operator[];
|
||||
|
||||
enum
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user