2021-12-10 19:15:48 +08:00
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
|
|
|
|
// client application.
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/*
|
|
|
|
The MIT License (MIT)
|
|
|
|
|
2023-01-01 17:36:38 +08:00
|
|
|
Copyright (c) 2012-2023 HALX99
|
2021-12-10 19:15:48 +08:00
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
|
|
copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
SOFTWARE.
|
|
|
|
|
2022-10-13 22:00:06 +08:00
|
|
|
Version: 3.39.5
|
|
|
|
|
2021-12-11 13:02:56 +08:00
|
|
|
The byte_buffer concepts:
|
2021-12-10 19:15:48 +08:00
|
|
|
a. The memory model is similar to to std::vector<char>, std::string
|
2022-10-13 22:00:06 +08:00
|
|
|
b. Support resize fit
|
|
|
|
c. By default resize without fill (uninitialized and for overwrite)
|
|
|
|
d. Support release internal buffer ownership with `release_pointer`
|
|
|
|
e. Since 3.39.5, default allocator use new/delete instead `malloc/free`
|
|
|
|
- yasio::default_bytes_allocator (new/delete)
|
|
|
|
- yasio::crt_bytes_allocator (malloc/free)
|
2021-12-10 19:15:48 +08:00
|
|
|
*/
|
2021-12-11 13:02:56 +08:00
|
|
|
#ifndef YASIO__BYTE_BUFFER_HPP
|
|
|
|
#define YASIO__BYTE_BUFFER_HPP
|
2021-12-10 19:15:48 +08:00
|
|
|
#include <stddef.h>
|
|
|
|
#include <string.h>
|
2022-10-13 22:00:06 +08:00
|
|
|
#include <stdint.h>
|
2021-12-12 10:20:34 +08:00
|
|
|
#include <utility>
|
2021-12-10 19:15:48 +08:00
|
|
|
#include <memory>
|
2021-12-12 10:20:34 +08:00
|
|
|
#include <iterator>
|
2021-12-18 15:17:46 +08:00
|
|
|
#include <limits>
|
2021-12-12 10:20:34 +08:00
|
|
|
#include <algorithm>
|
2021-12-11 13:02:56 +08:00
|
|
|
#include <type_traits>
|
2021-12-11 20:15:29 +08:00
|
|
|
#include <stdexcept>
|
2022-07-03 17:24:10 +08:00
|
|
|
#include <initializer_list>
|
2022-07-07 14:49:26 +08:00
|
|
|
#include <type_traits>
|
2021-12-11 13:02:56 +08:00
|
|
|
#include "yasio/compiler/feature_test.hpp"
|
2021-12-10 19:15:48 +08:00
|
|
|
|
|
|
|
namespace yasio
|
|
|
|
{
|
2022-07-07 09:31:34 +08:00
|
|
|
#define _YASIO_VERIFY_RANGE(cond, mesg) \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
if (cond) \
|
|
|
|
; /* contextually convertible to bool paranoia */ \
|
|
|
|
else \
|
|
|
|
{ \
|
|
|
|
throw std::out_of_range(mesg); \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
} while (false)
|
|
|
|
|
2022-07-07 14:49:26 +08:00
|
|
|
template <bool _Test, class _Ty = void>
|
|
|
|
using enable_if_t = typename ::std::enable_if<_Test, _Ty>::type;
|
|
|
|
|
2022-10-13 22:00:06 +08:00
|
|
|
template <typename _Elem>
|
|
|
|
struct is_byte_type {
|
|
|
|
static const bool value =
|
|
|
|
std::is_same<_Elem, char>::value || std::is_same<_Elem, unsigned char>::value;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename _Elem, enable_if_t<is_byte_type<_Elem>::value, int> = 0>
|
|
|
|
struct default_byte_allocator {
|
|
|
|
static _Elem* allocate(size_t count) { return new _Elem[count]; }
|
|
|
|
static void deallocate(_Elem* pBlock, size_t) { delete[] pBlock; }
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename _Elem, enable_if_t<is_byte_type<_Elem>::value, int> = 0>
|
|
|
|
struct crt_byte_allocator {
|
|
|
|
static _Elem* allocate(size_t count) { return malloc(count); }
|
|
|
|
static void deallocate(_Elem* pBlock, size_t) { free(pBlock); }
|
2021-12-11 20:15:29 +08:00
|
|
|
};
|
2022-07-03 17:24:10 +08:00
|
|
|
|
2022-10-13 22:00:06 +08:00
|
|
|
template <typename _Elem, typename _Alloc = default_byte_allocator<_Elem>,
|
|
|
|
enable_if_t<is_byte_type<_Elem>::value, int> = 0>
|
|
|
|
class basic_byte_buffer {
|
2021-12-10 19:15:48 +08:00
|
|
|
public:
|
2022-07-07 14:49:26 +08:00
|
|
|
using pointer = _Elem*;
|
|
|
|
using const_pointer = const _Elem*;
|
|
|
|
using reference = _Elem&;
|
|
|
|
using const_reference = const _Elem&;
|
|
|
|
using size_type = size_t;
|
|
|
|
using value_type = _Elem;
|
|
|
|
using iterator = _Elem*; // byte_buffer only needs transparent iterator
|
|
|
|
using const_iterator = const _Elem*;
|
|
|
|
using allocator_type = _Alloc;
|
2021-12-10 19:15:48 +08:00
|
|
|
basic_byte_buffer() {}
|
2022-10-13 22:00:06 +08:00
|
|
|
explicit basic_byte_buffer(size_type count) { resize(count); }
|
|
|
|
basic_byte_buffer(size_type count, std::true_type /*fit*/) { resize_fit(count); }
|
|
|
|
basic_byte_buffer(size_type count, const_reference val) { resize(count, val); }
|
|
|
|
basic_byte_buffer(size_type count, const_reference val, std::true_type /*fit*/)
|
2022-07-07 14:49:26 +08:00
|
|
|
{
|
|
|
|
resize_fit(count, val);
|
|
|
|
}
|
2022-07-04 09:13:06 +08:00
|
|
|
template <typename _Iter>
|
|
|
|
basic_byte_buffer(_Iter first, _Iter last)
|
|
|
|
{
|
|
|
|
assign(first, last);
|
|
|
|
}
|
|
|
|
template <typename _Iter>
|
|
|
|
basic_byte_buffer(_Iter first, _Iter last, std::true_type /*fit*/)
|
|
|
|
{
|
|
|
|
assign(first, last, std::true_type{});
|
|
|
|
}
|
2022-07-03 17:24:10 +08:00
|
|
|
basic_byte_buffer(const basic_byte_buffer& rhs) { assign(rhs); };
|
2022-07-07 09:31:34 +08:00
|
|
|
basic_byte_buffer(const basic_byte_buffer& rhs, std::true_type /*fit*/)
|
|
|
|
{
|
|
|
|
assign(rhs, std::true_type{});
|
2022-07-07 14:49:26 +08:00
|
|
|
}
|
2022-10-13 22:00:06 +08:00
|
|
|
basic_byte_buffer(basic_byte_buffer&& rhs) YASIO__NOEXCEPT { assign(std::move(rhs)); }
|
2022-07-07 14:49:26 +08:00
|
|
|
template <typename _Ty, enable_if_t<std::is_integral<_Ty>::value, int> = 0>
|
2022-07-04 09:13:06 +08:00
|
|
|
basic_byte_buffer(std::initializer_list<_Ty> rhs)
|
|
|
|
{
|
|
|
|
assign(rhs);
|
|
|
|
}
|
2022-07-07 14:49:26 +08:00
|
|
|
template <typename _Ty, enable_if_t<std::is_integral<_Ty>::value, int> = 0>
|
2022-07-04 09:13:06 +08:00
|
|
|
basic_byte_buffer(std::initializer_list<_Ty> rhs, std::true_type /*fit*/)
|
|
|
|
{
|
|
|
|
assign(rhs, std::true_type{});
|
|
|
|
}
|
2022-10-13 22:00:06 +08:00
|
|
|
~basic_byte_buffer() { _Tidy(); }
|
2022-07-03 17:24:10 +08:00
|
|
|
basic_byte_buffer& operator=(const basic_byte_buffer& rhs)
|
2021-12-10 19:15:48 +08:00
|
|
|
{
|
2022-07-03 17:24:10 +08:00
|
|
|
assign(rhs);
|
2021-12-10 19:15:48 +08:00
|
|
|
return *this;
|
|
|
|
}
|
2022-10-13 22:00:06 +08:00
|
|
|
basic_byte_buffer& operator=(basic_byte_buffer&& rhs) YASIO__NOEXCEPT
|
2022-07-04 09:13:06 +08:00
|
|
|
{
|
|
|
|
this->swap(rhs);
|
|
|
|
return *this;
|
|
|
|
}
|
2022-07-06 16:56:57 +08:00
|
|
|
template <typename _Cont>
|
|
|
|
basic_byte_buffer& operator+=(const _Cont& rhs)
|
|
|
|
{
|
|
|
|
return this->append(std::begin(rhs), std::end(rhs));
|
|
|
|
}
|
2022-07-07 14:49:26 +08:00
|
|
|
basic_byte_buffer& operator+=(const_reference rhs)
|
2022-07-06 16:56:57 +08:00
|
|
|
{
|
|
|
|
this->push_back(rhs);
|
|
|
|
return *this;
|
|
|
|
}
|
2022-07-04 09:13:06 +08:00
|
|
|
template <typename _Iter>
|
|
|
|
void assign(const _Iter first, const _Iter last)
|
|
|
|
{
|
|
|
|
_Assign_range(first, last);
|
|
|
|
}
|
|
|
|
template <typename _Iter>
|
|
|
|
void assign(const _Iter first, const _Iter last, std::true_type /*fit*/)
|
|
|
|
{
|
|
|
|
_Assign_range(first, last, std::true_type{});
|
|
|
|
}
|
2022-07-03 17:24:10 +08:00
|
|
|
void assign(const basic_byte_buffer& rhs) { _Assign_range(rhs.begin(), rhs.end()); }
|
2022-07-07 09:31:34 +08:00
|
|
|
void assign(const basic_byte_buffer& rhs, std::true_type)
|
|
|
|
{
|
|
|
|
_Assign_range(rhs.begin(), rhs.end(), std::true_type{});
|
|
|
|
}
|
2022-07-03 17:24:10 +08:00
|
|
|
void assign(basic_byte_buffer&& rhs) { _Assign_rv(std::move(rhs)); }
|
2022-07-07 14:49:26 +08:00
|
|
|
template <typename _Ty, enable_if_t<std::is_integral<_Ty>::value, int> = 0>
|
2022-07-04 09:13:06 +08:00
|
|
|
void assign(std::initializer_list<_Ty> rhs)
|
|
|
|
{
|
2022-07-07 14:49:26 +08:00
|
|
|
_Assign_range((iterator)rhs.begin(), (iterator)rhs.end());
|
2022-07-04 09:13:06 +08:00
|
|
|
}
|
2022-07-07 14:49:26 +08:00
|
|
|
template <typename _Ty, enable_if_t<std::is_integral<_Ty>::value, int> = 0>
|
2022-07-04 09:13:06 +08:00
|
|
|
void assign(std::initializer_list<_Ty> rhs, std::true_type /*fit*/)
|
2022-07-03 17:24:10 +08:00
|
|
|
{
|
2022-07-07 14:49:26 +08:00
|
|
|
_Assign_range((iterator)rhs.begin(), (iterator)rhs.end(), std::true_type{});
|
2022-07-03 17:24:10 +08:00
|
|
|
}
|
2022-10-13 22:00:06 +08:00
|
|
|
void swap(basic_byte_buffer& rhs) YASIO__NOEXCEPT
|
2021-12-10 19:15:48 +08:00
|
|
|
{
|
2022-10-13 22:00:06 +08:00
|
|
|
std::swap(_Myfirst, rhs._Myfirst);
|
|
|
|
std::swap(_Mylast, rhs._Mylast);
|
|
|
|
std::swap(_Myend, rhs._Myend);
|
2021-12-10 19:15:48 +08:00
|
|
|
}
|
2022-07-04 09:13:06 +08:00
|
|
|
template <typename _Iter>
|
2022-07-07 09:31:34 +08:00
|
|
|
iterator insert(iterator _Where, _Iter first, const _Iter last)
|
2021-12-10 19:15:48 +08:00
|
|
|
{
|
2022-07-07 09:31:34 +08:00
|
|
|
_YASIO_VERIFY_RANGE(_Where >= _Myfirst && _Where <= _Mylast && first <= last,
|
|
|
|
"byte_buffer: out of range!");
|
2022-07-18 15:33:05 +08:00
|
|
|
if (first != last)
|
2021-12-10 19:15:48 +08:00
|
|
|
{
|
2022-07-18 15:33:05 +08:00
|
|
|
auto ifirst = (iterator)std::addressof(*first);
|
|
|
|
auto ilast = (iterator)(std::addressof(*first) + std::distance(first, last));
|
|
|
|
auto count = std::distance(ifirst, ilast);
|
2022-07-11 09:12:40 +08:00
|
|
|
auto insertion_pos = std::distance(_Myfirst, _Where);
|
|
|
|
if (_Where == _Mylast)
|
|
|
|
{
|
|
|
|
if (count > 1)
|
|
|
|
{
|
|
|
|
auto old_size = _Mylast - _Myfirst;
|
2022-10-13 22:00:06 +08:00
|
|
|
resize(old_size + count);
|
|
|
|
std::copy_n(ifirst, count, _Myfirst + old_size);
|
2022-07-11 09:12:40 +08:00
|
|
|
}
|
|
|
|
else if (count == 1)
|
|
|
|
push_back(static_cast<value_type>(*ifirst));
|
|
|
|
}
|
|
|
|
else
|
2021-12-10 19:15:48 +08:00
|
|
|
{
|
2022-07-11 09:12:40 +08:00
|
|
|
if (insertion_pos >= 0)
|
|
|
|
{
|
|
|
|
auto old_size = _Mylast - _Myfirst;
|
2022-10-13 22:00:06 +08:00
|
|
|
resize(old_size + count);
|
|
|
|
_Where = _Myfirst + insertion_pos;
|
|
|
|
auto move_to = _Where + count;
|
2022-07-11 09:12:40 +08:00
|
|
|
std::copy_n(_Where, _Mylast - move_to, move_to);
|
|
|
|
std::copy_n(ifirst, count, _Where);
|
|
|
|
}
|
2021-12-10 19:15:48 +08:00
|
|
|
}
|
2022-07-11 09:12:40 +08:00
|
|
|
return _Myfirst + insertion_pos;
|
2021-12-10 19:15:48 +08:00
|
|
|
}
|
2022-07-11 09:12:40 +08:00
|
|
|
return _Where;
|
2021-12-10 19:15:48 +08:00
|
|
|
}
|
2022-07-04 09:13:06 +08:00
|
|
|
template <typename _Iter>
|
2022-07-06 16:56:57 +08:00
|
|
|
basic_byte_buffer& append(_Iter first, const _Iter last)
|
2022-07-04 09:13:06 +08:00
|
|
|
{
|
2022-07-11 09:12:40 +08:00
|
|
|
insert(end(), first, last);
|
2022-07-06 16:56:57 +08:00
|
|
|
return *this;
|
2021-12-12 10:20:34 +08:00
|
|
|
}
|
2022-07-07 14:49:26 +08:00
|
|
|
void push_back(value_type v)
|
2021-12-10 19:15:48 +08:00
|
|
|
{
|
2021-12-11 13:02:56 +08:00
|
|
|
resize(this->size() + 1);
|
|
|
|
*(_Mylast - 1) = v;
|
2021-12-10 19:15:48 +08:00
|
|
|
}
|
2022-07-07 09:31:34 +08:00
|
|
|
iterator erase(iterator _Where)
|
|
|
|
{
|
|
|
|
_YASIO_VERIFY_RANGE(_Where >= _Myfirst && _Where < _Mylast, "byte_buffer: out of range!");
|
|
|
|
_Mylast = std::move(_Where + 1, _Mylast, _Where);
|
|
|
|
return _Where;
|
|
|
|
}
|
|
|
|
iterator erase(iterator first, iterator last)
|
2022-07-06 16:56:57 +08:00
|
|
|
{
|
2022-07-07 09:31:34 +08:00
|
|
|
_YASIO_VERIFY_RANGE((first <= last) && first >= _Myfirst && last <= _Mylast,
|
|
|
|
"byte_buffer: out of range!");
|
2022-07-06 16:56:57 +08:00
|
|
|
_Mylast = std::move(last, _Mylast, first);
|
2022-07-07 09:31:34 +08:00
|
|
|
return first;
|
2022-07-06 16:56:57 +08:00
|
|
|
}
|
2022-07-07 14:49:26 +08:00
|
|
|
value_type& front()
|
2021-12-10 19:15:48 +08:00
|
|
|
{
|
2022-07-07 09:31:34 +08:00
|
|
|
_YASIO_VERIFY_RANGE(_Myfirst < _Mylast, "byte_buffer: out of range!");
|
|
|
|
return *_Myfirst;
|
2021-12-10 19:15:48 +08:00
|
|
|
}
|
2022-07-07 14:49:26 +08:00
|
|
|
value_type& back()
|
2021-12-11 13:02:56 +08:00
|
|
|
{
|
2022-07-07 09:31:34 +08:00
|
|
|
_YASIO_VERIFY_RANGE(_Myfirst < _Mylast, "byte_buffer: out of range!");
|
|
|
|
return *(_Mylast - 1);
|
2021-12-11 13:02:56 +08:00
|
|
|
}
|
2022-10-13 22:00:06 +08:00
|
|
|
static YASIO__CONSTEXPR size_type max_size() YASIO__NOEXCEPT
|
|
|
|
{
|
|
|
|
return (std::numeric_limits<ptrdiff_t>::max)();
|
|
|
|
}
|
|
|
|
iterator begin() YASIO__NOEXCEPT { return _Myfirst; }
|
|
|
|
iterator end() YASIO__NOEXCEPT { return _Mylast; }
|
|
|
|
const_iterator begin() const YASIO__NOEXCEPT { return _Myfirst; }
|
|
|
|
const_iterator end() const YASIO__NOEXCEPT { return _Mylast; }
|
|
|
|
pointer data() YASIO__NOEXCEPT { return _Myfirst; }
|
|
|
|
const_pointer data() const YASIO__NOEXCEPT { return _Myfirst; }
|
|
|
|
size_type capacity() const YASIO__NOEXCEPT { return static_cast<size_type>(_Myend - _Myfirst); }
|
|
|
|
size_type size() const YASIO__NOEXCEPT { return static_cast<size_type>(_Mylast - _Myfirst); }
|
|
|
|
void clear() YASIO__NOEXCEPT { _Mylast = _Myfirst; }
|
|
|
|
bool empty() const YASIO__NOEXCEPT { return _Mylast == _Myfirst; }
|
|
|
|
|
|
|
|
const_reference operator[](size_type index) const { return this->at(index); }
|
|
|
|
reference operator[](size_type index) { return this->at(index); }
|
|
|
|
const_reference at(size_type index) const
|
|
|
|
{
|
|
|
|
_YASIO_VERIFY_RANGE(index < this->size(), "byte_buffer: out of range!");
|
|
|
|
return _Myfirst[index];
|
|
|
|
}
|
|
|
|
reference at(size_type index)
|
|
|
|
{
|
|
|
|
_YASIO_VERIFY_RANGE(index < this->size(), "byte_buffer: out of range!");
|
|
|
|
return _Myfirst[index];
|
|
|
|
}
|
|
|
|
void resize(size_type new_size, const_reference val)
|
2021-12-10 19:15:48 +08:00
|
|
|
{
|
2021-12-11 13:02:56 +08:00
|
|
|
auto old_size = this->size();
|
|
|
|
resize(new_size);
|
|
|
|
if (old_size < new_size)
|
|
|
|
memset(_Myfirst + old_size, val, new_size - old_size);
|
2021-12-10 19:15:48 +08:00
|
|
|
}
|
2022-10-13 22:00:06 +08:00
|
|
|
void resize(size_type new_size)
|
2021-12-10 19:15:48 +08:00
|
|
|
{
|
2021-12-12 10:20:34 +08:00
|
|
|
auto old_cap = this->capacity();
|
|
|
|
if (old_cap < new_size)
|
2022-10-13 22:00:06 +08:00
|
|
|
_Reallocate_exactly(_Calculate_growth(new_size), new_size);
|
|
|
|
else
|
|
|
|
_Mylast = _Myfirst + new_size;
|
2021-12-10 19:15:48 +08:00
|
|
|
}
|
2022-10-13 22:00:06 +08:00
|
|
|
void resize_fit(size_type new_size, const_reference val)
|
2021-12-11 20:15:29 +08:00
|
|
|
{
|
|
|
|
auto old_size = this->size();
|
|
|
|
resize_fit(new_size);
|
|
|
|
if (old_size < new_size)
|
|
|
|
memset(_Myfirst + old_size, val, new_size - old_size);
|
|
|
|
}
|
2022-10-13 22:00:06 +08:00
|
|
|
void resize_fit(size_type new_size)
|
2021-12-10 19:15:48 +08:00
|
|
|
{
|
2021-12-11 13:02:56 +08:00
|
|
|
if (this->capacity() < new_size)
|
2022-10-13 22:00:06 +08:00
|
|
|
_Reallocate_exactly(new_size, new_size);
|
|
|
|
else
|
|
|
|
_Mylast = _Myfirst + new_size;
|
2021-12-10 19:15:48 +08:00
|
|
|
}
|
2022-10-13 22:00:06 +08:00
|
|
|
void reserve(size_type new_cap)
|
2021-12-11 13:02:56 +08:00
|
|
|
{
|
|
|
|
if (this->capacity() < new_cap)
|
2022-10-13 22:00:06 +08:00
|
|
|
_Reallocate_exactly(new_cap, this->size());
|
|
|
|
}
|
|
|
|
void shrink_to_fit()
|
|
|
|
{ // reduce capacity to size, provide strong guarantee
|
|
|
|
const pointer _Oldlast = _Mylast;
|
|
|
|
if (_Oldlast != _Myend)
|
|
|
|
{ // something to do
|
|
|
|
const pointer _Oldfirst = _Myfirst;
|
|
|
|
if (_Oldfirst == _Oldlast)
|
|
|
|
_Tidy();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const auto _OldSize = static_cast<size_type>(_Oldlast - _Oldfirst);
|
|
|
|
_Reallocate_exactly(_OldSize, _OldSize);
|
|
|
|
}
|
2021-12-10 19:15:48 +08:00
|
|
|
}
|
|
|
|
}
|
2022-10-13 22:00:06 +08:00
|
|
|
/** Release internal buffer ownership
|
|
|
|
* Note: this is a unsafe operation, after take the internal buffer, you are responsible for
|
|
|
|
* destroy it once you don't need it, i.e:
|
|
|
|
* yasio::byte_buffer buf;
|
|
|
|
* buf.push_back('I');
|
|
|
|
* auto rawbufCapacity = buf.capacity();
|
|
|
|
* auto rawbufLen = buf.size();
|
|
|
|
* auto rawbuf = buf.release_pointer();
|
|
|
|
* // use rawbuf to do something
|
|
|
|
* // ...
|
|
|
|
* // done, destroy the memory
|
|
|
|
* yasio::byte_buffer::allocator_type::deallocate(rawbuf, rawbufCapacity);
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
pointer release_pointer() YASIO__NOEXCEPT
|
2021-12-10 19:15:48 +08:00
|
|
|
{
|
|
|
|
auto ptr = _Myfirst;
|
2022-10-13 22:00:06 +08:00
|
|
|
_Myfirst = nullptr;
|
|
|
|
_Mylast = nullptr;
|
|
|
|
_Myend = nullptr;
|
2021-12-10 19:15:48 +08:00
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2022-07-04 09:13:06 +08:00
|
|
|
template <typename _Iter>
|
|
|
|
void _Assign_range(_Iter first, _Iter last)
|
2021-12-12 10:20:34 +08:00
|
|
|
{
|
2022-07-03 17:24:10 +08:00
|
|
|
_Mylast = _Myfirst;
|
2021-12-12 10:20:34 +08:00
|
|
|
if (last > first)
|
2022-07-11 09:12:40 +08:00
|
|
|
{
|
|
|
|
auto ifirst = (iterator)std::addressof(*first);
|
|
|
|
auto ilast = (iterator)std::addressof(*last);
|
2022-10-13 22:00:06 +08:00
|
|
|
resize(std::distance(ifirst, ilast));
|
|
|
|
std::copy(ifirst, ilast, _Myfirst);
|
2022-07-11 09:12:40 +08:00
|
|
|
}
|
2021-12-12 10:20:34 +08:00
|
|
|
}
|
2022-07-04 09:13:06 +08:00
|
|
|
template <typename _Iter>
|
|
|
|
void _Assign_range(_Iter first, _Iter last, std::true_type)
|
2021-12-12 10:20:34 +08:00
|
|
|
{
|
2022-07-03 17:24:10 +08:00
|
|
|
_Mylast = _Myfirst;
|
2021-12-12 10:20:34 +08:00
|
|
|
if (last > first)
|
2022-10-13 22:00:06 +08:00
|
|
|
{
|
|
|
|
resize_fit(std::distance(first, last));
|
|
|
|
std::copy(first, last, _Myfirst);
|
|
|
|
}
|
2021-12-12 10:20:34 +08:00
|
|
|
}
|
|
|
|
void _Assign_rv(basic_byte_buffer&& rhs)
|
|
|
|
{
|
|
|
|
memcpy(this, &rhs, sizeof(rhs));
|
|
|
|
memset(&rhs, 0, sizeof(rhs));
|
|
|
|
}
|
2022-10-13 22:00:06 +08:00
|
|
|
void _Reallocate_exactly(size_type new_cap, size_type new_size)
|
2021-12-10 19:15:48 +08:00
|
|
|
{
|
2022-10-13 22:00:06 +08:00
|
|
|
const pointer _Newvec = _Alloc::allocate(new_cap);
|
|
|
|
if (_Myfirst)
|
2021-12-12 10:20:34 +08:00
|
|
|
{
|
2022-10-13 22:00:06 +08:00
|
|
|
std::copy(_Myfirst, _Mylast, _Newvec);
|
|
|
|
_Alloc::deallocate(_Myfirst, static_cast<size_type>(_Myend - _Myfirst));
|
2021-12-12 10:20:34 +08:00
|
|
|
}
|
2022-10-13 22:00:06 +08:00
|
|
|
_Myfirst = _Newvec;
|
|
|
|
_Mylast = _Newvec + new_size;
|
|
|
|
_Myend = _Newvec + new_cap;
|
2021-12-10 19:15:48 +08:00
|
|
|
}
|
2022-10-13 22:00:06 +08:00
|
|
|
size_type _Calculate_growth(const size_type _Newsize) const
|
|
|
|
{
|
|
|
|
// given _Oldcapacity and _Newsize, calculate geometric growth
|
|
|
|
const size_type _Oldcapacity = capacity();
|
|
|
|
YASIO__CONSTEXPR auto _Max = max_size();
|
|
|
|
|
|
|
|
if (_Oldcapacity > _Max - _Oldcapacity / 2)
|
|
|
|
return _Max; // geometric growth would overflow
|
|
|
|
|
|
|
|
const size_type _Geometric = _Oldcapacity + (_Oldcapacity >> 1);
|
|
|
|
|
|
|
|
if (_Geometric < _Newsize)
|
|
|
|
return _Newsize; // geometric growth would be insufficient
|
|
|
|
|
|
|
|
return _Geometric; // geometric growth is sufficient
|
|
|
|
}
|
|
|
|
void _Tidy() YASIO__NOEXCEPT
|
|
|
|
{ // free all storage
|
|
|
|
if (_Myfirst)
|
|
|
|
{ // destroy and deallocate old array
|
|
|
|
_Alloc::deallocate(_Myfirst, static_cast<size_type>(_Myend - _Myfirst));
|
|
|
|
|
|
|
|
_Myfirst = nullptr;
|
|
|
|
_Mylast = nullptr;
|
|
|
|
_Myend = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-07 14:49:26 +08:00
|
|
|
pointer _Myfirst = nullptr;
|
|
|
|
pointer _Mylast = nullptr;
|
|
|
|
pointer _Myend = nullptr;
|
2021-12-10 19:15:48 +08:00
|
|
|
};
|
|
|
|
using sbyte_buffer = basic_byte_buffer<char>;
|
2021-12-12 10:20:34 +08:00
|
|
|
using byte_buffer = basic_byte_buffer<unsigned char>;
|
2021-12-10 19:15:48 +08:00
|
|
|
} // namespace yasio
|
2021-12-11 13:02:56 +08:00
|
|
|
#endif
|