util/AllocatedArray: migrate from {Const,Writable}Buffer to std::span
This commit is contained in:
parent
23dd613ff9
commit
5fb97b81d1
|
@ -51,8 +51,8 @@ mod_loadfile(const Domain *domain, DecoderClient *client, InputStream &is)
|
|||
|
||||
auto buffer = AllocatedArray<std::byte>(buffer_size);
|
||||
|
||||
std::byte *const end = buffer.end();
|
||||
std::byte *p = buffer.begin();
|
||||
std::byte *p = buffer.data();
|
||||
std::byte *const end = p + buffer.size();
|
||||
|
||||
while (true) {
|
||||
size_t ret = decoder_read(client, is, p, end - p);
|
||||
|
|
|
@ -73,7 +73,7 @@ static ModPlugFile *
|
|||
LoadModPlugFile(DecoderClient *client, InputStream &is)
|
||||
{
|
||||
const auto buffer = mod_loadfile(&modplug_domain, client, is);
|
||||
if (buffer.IsNull()) {
|
||||
if (buffer == nullptr) {
|
||||
LogWarning(modplug_domain, "could not load stream");
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ mod_decode(DecoderClient &client, InputStream &is)
|
|||
char audio_buffer[OPENMPT_FRAME_SIZE];
|
||||
|
||||
const auto buffer = mod_loadfile(&openmpt_domain, &client, is);
|
||||
if (buffer.IsNull()) {
|
||||
if (buffer == nullptr) {
|
||||
LogWarning(openmpt_domain, "could not load stream");
|
||||
return;
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ static bool
|
|||
openmpt_scan_stream(InputStream &is, TagHandler &handler) noexcept
|
||||
try {
|
||||
const auto buffer = mod_loadfile(&openmpt_domain, nullptr, is);
|
||||
if (buffer.IsNull()) {
|
||||
if (buffer == nullptr) {
|
||||
LogWarning(openmpt_domain, "could not load stream");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -43,21 +43,21 @@ IcuCaseFold(std::string_view src) noexcept
|
|||
try {
|
||||
#ifdef HAVE_ICU
|
||||
const auto u = UCharFromUTF8(src);
|
||||
if (u.IsNull())
|
||||
if (u.data() == nullptr)
|
||||
return {src};
|
||||
|
||||
AllocatedArray<UChar> folded(u.size() * 2U);
|
||||
|
||||
UErrorCode error_code = U_ZERO_ERROR;
|
||||
size_t folded_length = u_strFoldCase(folded.begin(), folded.size(),
|
||||
u.begin(), u.size(),
|
||||
size_t folded_length = u_strFoldCase(folded.data(), folded.size(),
|
||||
u.data(), u.size(),
|
||||
U_FOLD_CASE_DEFAULT,
|
||||
&error_code);
|
||||
if (folded_length == 0 || error_code != U_ZERO_ERROR)
|
||||
return {src};
|
||||
|
||||
folded.SetSize(folded_length);
|
||||
return UCharToUTF8({folded.begin(), folded.size()});
|
||||
return UCharToUTF8(std::basic_string_view{folded.data(), folded.size()});
|
||||
|
||||
#else
|
||||
#error not implemented
|
||||
|
|
|
@ -141,11 +141,11 @@ IcuConverter::FromUTF8(std::string_view s) const
|
|||
|
||||
// TODO: dynamic buffer?
|
||||
char buffer[4096], *target = buffer;
|
||||
const UChar *source = u.begin();
|
||||
const UChar *source = u.data();
|
||||
UErrorCode code = U_ZERO_ERROR;
|
||||
|
||||
ucnv_fromUnicode(converter, &target, buffer + std::size(buffer),
|
||||
&source, u.end(),
|
||||
&source, u.data() + u.size(),
|
||||
nullptr, true, &code);
|
||||
|
||||
if (code != U_ZERO_ERROR)
|
||||
|
|
|
@ -38,7 +38,7 @@ UCharFromUTF8(std::string_view src)
|
|||
|
||||
UErrorCode error_code = U_ZERO_ERROR;
|
||||
int32_t dest_length;
|
||||
u_strFromUTF8(dest.begin(), dest_capacity, &dest_length,
|
||||
u_strFromUTF8(dest.data(), dest_capacity, &dest_length,
|
||||
src.data(), src.size(),
|
||||
&error_code);
|
||||
if (U_FAILURE(error_code))
|
||||
|
|
|
@ -760,7 +760,7 @@ Play_44_1_Silence(snd_pcm_t *pcm)
|
|||
throw Alsa::MakeError(err, "snd_pcm_prepare() failed");
|
||||
|
||||
AllocatedArray<int16_t> buffer{channels * period_size};
|
||||
buffer = {};
|
||||
buffer = std::span<const int16_t>{};
|
||||
|
||||
/* play at least 250ms of silence */
|
||||
for (snd_pcm_uframes_t remaining_frames = rate / 4;;) {
|
||||
|
|
|
@ -172,7 +172,7 @@ HttpdOutput::ReadPage()
|
|||
if (size == 0)
|
||||
return nullptr;
|
||||
|
||||
return std::make_shared<Page>(ConstBuffer{buffer, size});
|
||||
return std::make_shared<Page>(std::span{buffer, size});
|
||||
}
|
||||
|
||||
inline void
|
||||
|
|
|
@ -114,5 +114,5 @@ icy_server_metadata_page(const Tag &tag, const TagType *types) noexcept
|
|||
if (icy_string == nullptr)
|
||||
return nullptr;
|
||||
|
||||
return std::make_shared<Page>(ConstBuffer<std::byte>{(const std::byte *)icy_string.c_str(), uint8_t(icy_string[0]) * 16U + 1U});
|
||||
return std::make_shared<Page>(std::span{(const std::byte *)icy_string.c_str(), uint8_t(icy_string[0]) * 16U + 1U});
|
||||
}
|
||||
|
|
|
@ -95,8 +95,8 @@ SnapcastClient::OnSocketReady(unsigned flags) noexcept
|
|||
/* discard old chunks */
|
||||
continue;
|
||||
|
||||
const ConstBuffer<std::byte> payload = chunk->payload;
|
||||
if (!SendWireChunk(payload.ToVoid(), chunk->time)) {
|
||||
const std::span payload = chunk->payload;
|
||||
if (!SendWireChunk(payload, chunk->time)) {
|
||||
// TODO: handle EAGAIN
|
||||
LockClose();
|
||||
return;
|
||||
|
@ -110,23 +110,23 @@ SnapcastClient::OnSocketReady(unsigned flags) noexcept
|
|||
}
|
||||
|
||||
static bool
|
||||
Send(SocketDescriptor s, ConstBuffer<void> buffer) noexcept
|
||||
Send(SocketDescriptor s, std::span<const std::byte> buffer) noexcept
|
||||
{
|
||||
auto nbytes = s.Write(buffer.data, buffer.size);
|
||||
return nbytes == ssize_t(buffer.size);
|
||||
auto nbytes = s.Write(buffer.data(), buffer.size());
|
||||
return nbytes == ssize_t(buffer.size());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static bool
|
||||
SendT(SocketDescriptor s, const T &buffer) noexcept
|
||||
{
|
||||
return Send(s, ConstBuffer<T>{&buffer, 1}.ToVoid());
|
||||
return Send(s, std::as_bytes(std::span{&buffer, 1}));
|
||||
}
|
||||
|
||||
static bool
|
||||
Send(SocketDescriptor s, StringView buffer) noexcept
|
||||
Send(SocketDescriptor s, std::string_view buffer) noexcept
|
||||
{
|
||||
return Send(s, buffer.ToVoid());
|
||||
return Send(s, std::as_bytes(std::span{buffer}));
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -158,10 +158,10 @@ static bool
|
|||
SendCodecHeader(SocketDescriptor s, const PackedBE16 id,
|
||||
const SnapcastBase &request,
|
||||
const StringView codec,
|
||||
const ConstBuffer<void> payload) noexcept
|
||||
const std::span<const std::byte> payload) noexcept
|
||||
{
|
||||
const PackedLE32 codec_size = codec.size;
|
||||
const PackedLE32 payload_size = payload.size;
|
||||
const PackedLE32 payload_size = payload.size();
|
||||
|
||||
SnapcastBase base{};
|
||||
base.type = uint16_t(SnapcastMessageType::CODEC_HEADER);
|
||||
|
@ -169,7 +169,7 @@ SendCodecHeader(SocketDescriptor s, const PackedBE16 id,
|
|||
base.refers_to = request.id;
|
||||
base.sent = ToSnapcastTimestamp(std::chrono::steady_clock::now());
|
||||
base.size = sizeof(codec_size) + codec.size +
|
||||
sizeof(payload_size) + payload.size;
|
||||
sizeof(payload_size) + payload.size();
|
||||
|
||||
return SendT(s, base) &&
|
||||
SendT(s, codec_size) && Send(s, codec) &&
|
||||
|
@ -212,25 +212,25 @@ SnapcastClient::SendTime(const SnapcastBase &request_header,
|
|||
|
||||
static bool
|
||||
SendWireChunk(SocketDescriptor s, const PackedBE16 id,
|
||||
const ConstBuffer<void> payload,
|
||||
const std::span<const std::byte> payload,
|
||||
std::chrono::steady_clock::time_point t) noexcept
|
||||
{
|
||||
SnapcastWireChunk hdr{};
|
||||
hdr.timestamp = ToSnapcastTimestamp(t);
|
||||
hdr.size = payload.size;
|
||||
hdr.size = payload.size();
|
||||
|
||||
SnapcastBase base{};
|
||||
base.type = uint16_t(SnapcastMessageType::WIRE_CHUNK);
|
||||
base.id = id;
|
||||
base.sent = ToSnapcastTimestamp(std::chrono::steady_clock::now());
|
||||
base.size = sizeof(hdr) + payload.size;
|
||||
base.size = sizeof(hdr) + payload.size();
|
||||
|
||||
// TODO: no blocking send()
|
||||
return SendT(s, base) && SendT(s, hdr) && Send(s, payload);
|
||||
}
|
||||
|
||||
bool
|
||||
SnapcastClient::SendWireChunk(ConstBuffer<void> payload,
|
||||
SnapcastClient::SendWireChunk(std::span<const std::byte> payload,
|
||||
std::chrono::steady_clock::time_point t) noexcept
|
||||
{
|
||||
return ::SendWireChunk(GetSocket(), next_id++, payload, t);
|
||||
|
@ -238,21 +238,21 @@ SnapcastClient::SendWireChunk(ConstBuffer<void> payload,
|
|||
|
||||
static bool
|
||||
SendStreamTags(SocketDescriptor s, const PackedBE16 id,
|
||||
const ConstBuffer<void> payload) noexcept
|
||||
const std::span<const std::byte> payload) noexcept
|
||||
{
|
||||
const PackedLE32 payload_size = payload.size;
|
||||
const PackedLE32 payload_size = payload.size();
|
||||
|
||||
SnapcastBase base{};
|
||||
base.type = uint16_t(SnapcastMessageType::STREAM_TAGS);
|
||||
base.id = id;
|
||||
base.sent = ToSnapcastTimestamp(std::chrono::steady_clock::now());
|
||||
base.size = sizeof(payload_size) + payload.size;
|
||||
base.size = sizeof(payload_size) + payload.size();
|
||||
|
||||
return SendT(s, base) && SendT(s, payload_size) && Send(s, payload);
|
||||
}
|
||||
|
||||
void
|
||||
SnapcastClient::SendStreamTags(ConstBuffer<void> payload) noexcept
|
||||
SnapcastClient::SendStreamTags(std::span<const std::byte> payload) noexcept
|
||||
{
|
||||
::SendStreamTags(GetSocket(), next_id++, payload);
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ SnapcastClient::OnSocketInput(void *data, size_t length) noexcept
|
|||
|
||||
ConsumeInput(sizeof(base) + base.size);
|
||||
|
||||
const ConstBuffer<void> payload{&base + 1, base.size};
|
||||
const std::span<const std::byte> payload{(const std::byte *)(&base + 1), base.size};
|
||||
|
||||
switch (SnapcastMessageType(uint16_t(base.type))) {
|
||||
case SnapcastMessageType::HELLO:
|
||||
|
@ -284,8 +284,8 @@ SnapcastClient::OnSocketInput(void *data, size_t length) noexcept
|
|||
break;
|
||||
|
||||
case SnapcastMessageType::TIME:
|
||||
if (payload.size >= sizeof(SnapcastTime))
|
||||
SendTime(base, *(const SnapcastTime *)payload.data);
|
||||
if (payload.size() >= sizeof(SnapcastTime))
|
||||
SendTime(base, *(const SnapcastTime *)(const void *)payload.data());
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
|
||||
struct SnapcastBase;
|
||||
struct SnapcastTime;
|
||||
|
@ -60,7 +61,7 @@ public:
|
|||
|
||||
void LockClose() noexcept;
|
||||
|
||||
void SendStreamTags(ConstBuffer<void> payload) noexcept;
|
||||
void SendStreamTags(std::span<const std::byte> payload) noexcept;
|
||||
|
||||
/**
|
||||
* Caller must lock the mutex.
|
||||
|
@ -84,7 +85,7 @@ public:
|
|||
private:
|
||||
SnapcastChunkPtr LockPopQueue() noexcept;
|
||||
|
||||
bool SendWireChunk(ConstBuffer<void> payload,
|
||||
bool SendWireChunk(std::span<const std::byte> payload,
|
||||
std::chrono::steady_clock::time_point t) noexcept;
|
||||
|
||||
bool SendServerSettings(const SnapcastBase &request) noexcept;
|
||||
|
|
|
@ -161,9 +161,8 @@ public:
|
|||
return "pcm";
|
||||
}
|
||||
|
||||
ConstBuffer<void> GetCodecHeader() const noexcept {
|
||||
ConstBuffer<std::byte> result(codec_header);
|
||||
return result.ToVoid();
|
||||
std::span<const std::byte> GetCodecHeader() const noexcept {
|
||||
return codec_header;
|
||||
}
|
||||
|
||||
/* virtual methods from class AudioOutput */
|
||||
|
|
|
@ -127,7 +127,7 @@ ReadEncoder(Encoder &encoder)
|
|||
std::byte buffer[4096];
|
||||
|
||||
size_t nbytes = encoder.Read(buffer, sizeof(buffer));
|
||||
const ConstBuffer<std::byte> src(buffer, nbytes);
|
||||
const std::span<const std::byte> src{buffer, nbytes};
|
||||
return AllocatedArray<std::byte>{src};
|
||||
}
|
||||
|
||||
|
@ -181,7 +181,7 @@ SnapcastOutput::Close() noexcept
|
|||
|
||||
ClearQueue(chunks);
|
||||
|
||||
codec_header = nullptr;
|
||||
codec_header = std::span<const std::byte>{};
|
||||
delete encoder;
|
||||
}
|
||||
|
||||
|
@ -294,12 +294,12 @@ SnapcastOutput::SendTag(const Tag &tag)
|
|||
if (json.empty())
|
||||
return;
|
||||
|
||||
const ConstBuffer payload(json.data(), json.size());
|
||||
const auto payload = std::as_bytes(std::span{json});
|
||||
|
||||
const std::scoped_lock<Mutex> protect(mutex);
|
||||
// TODO: enqueue StreamTags, don't send directly
|
||||
for (auto &client : clients)
|
||||
client.SendStreamTags(payload.ToVoid());
|
||||
client.SendStreamTags(payload);
|
||||
#else
|
||||
(void)tag;
|
||||
#endif
|
||||
|
@ -348,7 +348,7 @@ SnapcastOutput::Play(const void *chunk, size_t size)
|
|||
if (chunks.empty())
|
||||
inject_event.Schedule();
|
||||
|
||||
const ConstBuffer payload{buffer, nbytes};
|
||||
const std::span<const std::byte> payload{buffer, nbytes};
|
||||
chunks.push(std::make_shared<SnapcastChunk>(now, AllocatedArray{payload}));
|
||||
}
|
||||
|
||||
|
|
|
@ -216,7 +216,7 @@ TagBuilder::AddItemInternal(TagType type, StringView value) noexcept
|
|||
assert(!value.empty());
|
||||
|
||||
auto f = FixTagString(value);
|
||||
if (!f.IsNull())
|
||||
if (f != nullptr)
|
||||
value = { f.data(), f.size() };
|
||||
|
||||
AddItemUnchecked(type, value);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2010-2019 Max Kellermann <max.kellermann@gmail.com>
|
||||
* Copyright 2010-2022 Max Kellermann <max.kellermann@gmail.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -27,14 +27,11 @@
|
|||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ALLOCATED_ARRAY_HXX
|
||||
#define ALLOCATED_ARRAY_HXX
|
||||
|
||||
#include "ConstBuffer.hxx"
|
||||
#include "WritableBuffer.hxx"
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <span>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
|
@ -42,7 +39,7 @@
|
|||
*/
|
||||
template<class T>
|
||||
class AllocatedArray {
|
||||
typedef WritableBuffer<T> Buffer;
|
||||
using Buffer = std::span<T>;
|
||||
|
||||
public:
|
||||
using size_type = typename Buffer::size_type;
|
||||
|
@ -51,10 +48,10 @@ public:
|
|||
using pointer = typename Buffer::pointer;
|
||||
using const_pointer = typename Buffer::const_pointer;
|
||||
using iterator = typename Buffer::iterator;
|
||||
using const_iterator = typename Buffer::const_iterator;
|
||||
using const_iterator = typename Buffer::iterator;
|
||||
|
||||
protected:
|
||||
Buffer buffer{nullptr};
|
||||
Buffer buffer{};
|
||||
|
||||
public:
|
||||
constexpr AllocatedArray() = default;
|
||||
|
@ -62,16 +59,15 @@ public:
|
|||
explicit AllocatedArray(size_type _size) noexcept
|
||||
:buffer{new T[_size], _size} {}
|
||||
|
||||
explicit AllocatedArray(ConstBuffer<T> src) noexcept {
|
||||
if (src == nullptr)
|
||||
explicit AllocatedArray(std::span<const T> src) noexcept {
|
||||
if (src.data() == nullptr)
|
||||
return;
|
||||
|
||||
buffer = {new T[src.size], src.size};
|
||||
std::copy_n(src.data, src.size, buffer.data);
|
||||
buffer = {new T[src.size()], src.size()};
|
||||
std::copy(src.begin(), src.end(), buffer.begin());
|
||||
}
|
||||
|
||||
AllocatedArray(std::nullptr_t n) noexcept
|
||||
:buffer(n) {}
|
||||
AllocatedArray(std::nullptr_t) noexcept {}
|
||||
|
||||
explicit AllocatedArray(const AllocatedArray &other) noexcept
|
||||
:AllocatedArray(other.buffer) {}
|
||||
|
@ -80,27 +76,28 @@ public:
|
|||
:buffer(other.release()) {}
|
||||
|
||||
~AllocatedArray() noexcept {
|
||||
delete[] buffer.data;
|
||||
delete[] buffer.data();
|
||||
}
|
||||
|
||||
AllocatedArray &operator=(ConstBuffer<T> src) noexcept {
|
||||
assert(size() == 0 || buffer.data != nullptr);
|
||||
assert(src.size == 0 || src.data != nullptr);
|
||||
AllocatedArray &operator=(std::span<const T> src) noexcept {
|
||||
assert(empty() || buffer.data() != nullptr);
|
||||
assert(src.empty() || src.data() != nullptr);
|
||||
|
||||
ResizeDiscard(src.size);
|
||||
std::copy_n(src.data, src.size, buffer.data);
|
||||
ResizeDiscard(src.size());
|
||||
std::copy(src.begin(), src.end(), buffer.begin());
|
||||
return *this;
|
||||
}
|
||||
|
||||
AllocatedArray &operator=(const AllocatedArray &other) noexcept {
|
||||
assert(size() == 0 || buffer.data != nullptr);
|
||||
assert(other.size() == 0 || other.buffer.data != nullptr);
|
||||
assert(empty() || buffer.data() != nullptr);
|
||||
assert(other.empty() || other.buffer.data() != nullptr);
|
||||
|
||||
if (&other == this)
|
||||
return *this;
|
||||
|
||||
ResizeDiscard(other.size());
|
||||
std::copy_n(other.buffer.data, other.buffer.size, buffer.data);
|
||||
std::copy_n(other.buffer.begin(), other.buffer.end(),
|
||||
buffer.begin());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -111,29 +108,25 @@ public:
|
|||
}
|
||||
|
||||
AllocatedArray &operator=(std::nullptr_t n) noexcept {
|
||||
delete[] buffer.data;
|
||||
buffer = n;
|
||||
delete[] buffer.data();
|
||||
buffer = {};
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator ConstBuffer<T>() const noexcept {
|
||||
operator std::span<const T>() const noexcept {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
operator WritableBuffer<T>() noexcept {
|
||||
operator std::span<T>() noexcept {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
constexpr bool IsNull() const noexcept {
|
||||
return buffer.IsNull();
|
||||
}
|
||||
|
||||
constexpr bool operator==(std::nullptr_t) const noexcept {
|
||||
return buffer == nullptr;
|
||||
return buffer.data() == nullptr;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(std::nullptr_t) const noexcept {
|
||||
return buffer != nullptr;
|
||||
return buffer.data() != nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,22 +140,22 @@ public:
|
|||
* Returns the number of allocated elements.
|
||||
*/
|
||||
constexpr size_type size() const noexcept {
|
||||
return buffer.size;
|
||||
return buffer.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of allocated elements.
|
||||
*/
|
||||
constexpr size_type capacity() const noexcept {
|
||||
return buffer.size;
|
||||
return buffer.size();
|
||||
}
|
||||
|
||||
pointer data() noexcept {
|
||||
return buffer.data;
|
||||
return buffer.data();
|
||||
}
|
||||
|
||||
const_pointer data() const noexcept {
|
||||
return buffer.data;
|
||||
return buffer.data();
|
||||
}
|
||||
|
||||
reference front() noexcept {
|
||||
|
@ -200,7 +193,7 @@ public:
|
|||
}
|
||||
|
||||
constexpr const_iterator begin() const noexcept {
|
||||
return buffer.cbegin();
|
||||
return buffer.begin();
|
||||
}
|
||||
|
||||
iterator end() noexcept {
|
||||
|
@ -208,19 +201,18 @@ public:
|
|||
}
|
||||
|
||||
constexpr const_iterator end() const noexcept {
|
||||
return buffer.cend();
|
||||
return buffer.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the array, discarding old data.
|
||||
*/
|
||||
void ResizeDiscard(size_type _size) noexcept {
|
||||
if (_size == buffer.size)
|
||||
if (_size == buffer.size())
|
||||
return;
|
||||
|
||||
delete[] buffer.data;
|
||||
buffer.size = _size;
|
||||
buffer.data = new T[buffer.size];
|
||||
delete[] buffer.data();
|
||||
buffer = {new T[_size], _size};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -229,7 +221,7 @@ public:
|
|||
* avoid expensive heap operations.
|
||||
*/
|
||||
void GrowDiscard(size_type _size) noexcept {
|
||||
if (_size > buffer.size)
|
||||
if (_size > buffer.size())
|
||||
ResizeDiscard(_size);
|
||||
}
|
||||
|
||||
|
@ -238,16 +230,16 @@ public:
|
|||
* range of elements, starting from the beginning.
|
||||
*/
|
||||
void GrowPreserve(size_type _size, size_type preserve) noexcept {
|
||||
if (_size <= buffer.size)
|
||||
if (_size <= buffer.size())
|
||||
return;
|
||||
|
||||
T *new_data = new T[_size];
|
||||
|
||||
std::move(buffer.data, buffer.data + preserve, new_data);
|
||||
std::move(buffer.begin(), std::next(buffer.begin(), preserve),
|
||||
new_data);
|
||||
|
||||
delete[] buffer.data;
|
||||
buffer.data = new_data;
|
||||
buffer.size = _size;
|
||||
delete[] buffer.data();
|
||||
buffer = {new_data, _size};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -256,17 +248,15 @@ public:
|
|||
* they are still allocated).
|
||||
*/
|
||||
void SetSize(size_type _size) noexcept {
|
||||
assert(_size <= buffer.size);
|
||||
assert(_size <= buffer.size());
|
||||
|
||||
buffer.size = _size;
|
||||
buffer = buffer.first(_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Give up ownership of the allocated buffer and return it.
|
||||
*/
|
||||
Buffer release() noexcept {
|
||||
return std::exchange(buffer, nullptr);
|
||||
return std::exchange(buffer, std::span<T>{});
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue