util/*FifoBuffer: migrate from WritableBuffer to std::span

This commit is contained in:
Max Kellermann 2022-05-10 17:26:41 +02:00 committed by Max Kellermann
parent 570755f05a
commit bb7be9a4cd
23 changed files with 114 additions and 129 deletions

View File

@ -53,13 +53,13 @@ Response::VFmt(fmt::string_view format_str, fmt::format_args args) noexcept
}
bool
Response::WriteBinary(ConstBuffer<void> payload) noexcept
Response::WriteBinary(std::span<const std::byte> payload) noexcept
{
assert(payload.size <= client.binary_limit);
assert(payload.size() <= client.binary_limit);
return
Fmt("binary: {}\n", payload.size) &&
Write(payload.data, payload.size) &&
Fmt("binary: {}\n", payload.size()) &&
Write(payload.data(), payload.size()) &&
Write("\n");
}

View File

@ -28,8 +28,8 @@
#endif
#include <cstddef>
#include <span>
template<typename T> struct ConstBuffer;
class Client;
class TagMask;
@ -99,7 +99,7 @@ public:
*
* @return true on success
*/
bool WriteBinary(ConstBuffer<void> payload) noexcept;
bool WriteBinary(std::span<const std::byte> payload) noexcept;
void Error(enum ack code, const char *msg) noexcept;

View File

@ -29,7 +29,7 @@ DecoderBuffer::Fill()
return false;
size_t nbytes = decoder_read(client, is,
w.data, w.size);
w.data(), w.size());
if (nbytes == 0)
/* end of file, I/O error or decoder command
received */
@ -39,16 +39,16 @@ DecoderBuffer::Fill()
return true;
}
ConstBuffer<void>
std::span<const std::byte>
DecoderBuffer::Need(size_t min_size)
{
while (true) {
const auto r = Read();
if (r.size >= min_size)
if (r.size() >= min_size)
return r;
if (!Fill())
return nullptr;
return {};
}
}
@ -56,13 +56,13 @@ bool
DecoderBuffer::Skip(size_t nbytes)
{
const auto r = buffer.Read();
if (r.size >= nbytes) {
if (r.size() >= nbytes) {
buffer.Consume(nbytes);
return true;
}
buffer.Clear();
nbytes -= r.size;
nbytes -= r.size();
return decoder_skip(client, is, nbytes);
}

View File

@ -21,10 +21,6 @@
#define MPD_DECODER_BUFFER_HXX
#include "util/DynamicFifoBuffer.hxx"
#include "util/ConstBuffer.hxx"
#include <cstddef>
#include <cstdint>
class DecoderClient;
class InputStream;
@ -38,7 +34,7 @@ class DecoderBuffer {
DecoderClient *const client;
InputStream &is;
DynamicFifoBuffer<uint8_t> buffer;
DynamicFifoBuffer<std::byte> buffer;
public:
/**
@ -83,16 +79,15 @@ public:
* you have to call Consume() to do that. The returned buffer
* becomes invalid after a Fill() or a Consume() call.
*/
ConstBuffer<void> Read() const noexcept {
auto r = buffer.Read();
return { r.data, r.size };
std::span<const std::byte> Read() const noexcept {
return buffer.Read();
}
/**
* Wait until this number of bytes are available. Returns nullptr on
* error.
*/
ConstBuffer<void> Need(size_t min_size);
std::span<const std::byte> Need(size_t min_size);
/**
* Consume (delete, invalidate) a part of the buffer. The

View File

@ -93,7 +93,7 @@ adts_find_frame(DecoderBuffer &buffer)
continue;
}
if (buffer.Need(frame_length).IsNull()) {
if (buffer.Need(frame_length).empty()) {
/* not enough data; discard this frame to
prevent a possible buffer overflow */
buffer.Clear();

View File

@ -237,11 +237,11 @@ HybridDsdDecode(DecoderClient &client, InputStream &input)
auto w = buffer.Write();
if (!w.empty()) {
if (remaining_bytes < (1<<30ULL) &&
w.size > size_t(remaining_bytes))
w.size = remaining_bytes;
w.size() > size_t(remaining_bytes))
w = w.first(remaining_bytes);
const size_t nbytes = client.Read(input,
w.data, w.size);
w.data(), w.size());
if (nbytes == 0)
return;
@ -251,9 +251,9 @@ HybridDsdDecode(DecoderClient &client, InputStream &input)
/* submit the buffer to our client */
auto r = buffer.Read();
auto n_frames = r.size / frame_size;
auto n_frames = r.size() / frame_size;
if (n_frames > 0) {
cmd = client.SubmitData(input, r.data,
cmd = client.SubmitData(input, r.data(),
n_frames * frame_size,
kbit_rate);
buffer.Consume(n_frames * frame_size);

View File

@ -51,7 +51,7 @@ FillBuffer(DecoderClient &client, InputStream &is, B &buffer)
if (w.empty())
return true;
size_t nbytes = decoder_read(client, is, w.data, w.size);
size_t nbytes = decoder_read(client, is, w.data(), w.size());
if (nbytes == 0 && is.LockIsEOF())
return false;
@ -188,25 +188,28 @@ pcm_stream_decode(DecoderClient &client, InputStream &is)
/* round down to the nearest frame size, because we
must not pass partial frames to
DecoderClient::SubmitData() */
r.size -= r.size % in_frame_size;
buffer.Consume(r.size);
r = r.first(r.size() - r.size() % in_frame_size);
buffer.Consume(r.size());
if (reverse_endian)
/* make sure we deliver samples in host byte order */
reverse_bytes_16((uint16_t *)r.data,
(uint16_t *)r.data,
(uint16_t *)(r.data + r.size));
reverse_bytes_16((uint16_t *)r.data(),
(uint16_t *)r.data(),
(uint16_t *)(r.data() + r.size()));
else if (l24) {
/* convert big-endian packed 24 bit
(audio/L24) to native-endian 24 bit (in 32
bit integers) */
pcm_unpack_24be(unpack_buffer, r.begin(), r.end());
r.data = (uint8_t *)&unpack_buffer[0];
r.size = (r.size / 3) * 4;
pcm_unpack_24be(unpack_buffer,
r.data(), r.data() + r.size());
r = {
(uint8_t *)&unpack_buffer[0],
(r.size() / 3) * 4,
};
}
cmd = !r.empty()
? client.SubmitData(is, r.data, r.size, 0)
? client.SubmitData(is, r.data(), r.size(), 0)
: client.GetCommand();
if (cmd == DecoderCommand::SEEK) {
uint64_t frame = client.GetSeekFrame();

View File

@ -131,8 +131,8 @@ WaveEncoder::WaveEncoder(AudioFormat &audio_format) noexcept
}
auto range = buffer.Write();
assert(range.size >= sizeof(WaveHeader));
auto *header = (WaveHeader *)range.data;
assert(range.size() >= sizeof(WaveHeader));
auto *header = (WaveHeader *)(void *)range.data();
/* create PCM wave header in initial buffer */
*header = MakeWaveHeader(audio_format.channels,

View File

@ -54,7 +54,7 @@ BufferedSocket::ReadToBuffer() noexcept
const auto buffer = input.Write();
assert(!buffer.empty());
const auto nbytes = DirectRead(buffer.data, buffer.size);
const auto nbytes = DirectRead(buffer.data(), buffer.size());
if (nbytes > 0)
input.Append(nbytes);
@ -73,7 +73,7 @@ BufferedSocket::ResumeInput() noexcept
return true;
}
const auto result = OnSocketInput(buffer.data, buffer.size);
const auto result = OnSocketInput(buffer.data(), buffer.size());
switch (result) {
case InputResult::MORE:
if (input.IsFull()) {

View File

@ -58,7 +58,7 @@ FullyBufferedSocket::Flush() noexcept
return true;
}
auto nbytes = DirectWrite(data.data, data.size);
auto nbytes = DirectWrite(data.data(), data.size());
if (gcc_unlikely(nbytes <= 0))
return nbytes == 0;
@ -82,7 +82,7 @@ FullyBufferedSocket::Write(const void *data, size_t length) noexcept
const bool was_empty = output.empty();
if (!output.Append(data, length)) {
if (!output.Append({(const std::byte *)data, length})) {
OnSocketError(std::make_exception_ptr(std::runtime_error("Output buffer is full")));
return false;
}

View File

@ -39,13 +39,13 @@ TextInputStream::ReadLine()
while (true) {
auto dest = buffer.Write();
if (dest.size < 2) {
if (dest.size() < 2) {
/* line too long: terminate the current
line */
assert(!dest.empty());
dest[0] = 0;
line = buffer.Read().data;
line = buffer.Read().data();
buffer.Clear();
return line;
}
@ -53,9 +53,9 @@ TextInputStream::ReadLine()
/* reserve one byte for the null terminator if the
last line is not terminated by a newline
character */
--dest.size;
dest = dest.first(dest.size() - 1);
size_t nbytes = is->LockRead(dest.data, dest.size);
size_t nbytes = is->LockRead(dest.data(), dest.size());
buffer.Append(nbytes);
@ -75,7 +75,7 @@ TextInputStream::ReadLine()
buffer.Clear();
return r.empty()
? nullptr
: r.data;
: r.data();
}
}
}

View File

@ -44,10 +44,10 @@ bool
BufferedOutputStream::AppendToBuffer(const void *data, std::size_t size) noexcept
{
auto r = buffer.Write();
if (r.size < size)
if (r.size() < size)
return false;
memcpy(r.data, data, size);
memcpy(r.data(), data, size);
buffer.Append(size);
return true;
}
@ -88,10 +88,10 @@ BufferedOutputStream::Format(const char *fmt, ...)
/* format into the buffer */
std::va_list ap;
va_start(ap, fmt);
std::size_t size = vsnprintf((char *)r.data, r.size, fmt, ap);
std::size_t size = vsnprintf((char *)r.data(), r.size(), fmt, ap);
va_end(ap);
if (gcc_unlikely(size >= r.size)) {
if (gcc_unlikely(size >= r.size())) {
/* buffer was not large enough; flush it and try
again */
@ -99,20 +99,20 @@ BufferedOutputStream::Format(const char *fmt, ...)
r = buffer.Write();
if (gcc_unlikely(size >= r.size)) {
if (gcc_unlikely(size >= r.size())) {
/* still not enough space: grow the buffer and
try again */
r.size = size + 1;
r.data = buffer.Write(r.size);
++size;
r = {buffer.Write(size), size};
}
/* format into the new buffer */
va_start(ap, fmt);
size = vsnprintf((char *)r.data, r.size, fmt, ap);
size = vsnprintf((char *)r.data(), r.size(), fmt, ap);
va_end(ap);
/* this time, it must fit */
assert(size < r.size);
assert(size < r.size());
}
buffer.Append(size);
@ -140,7 +140,7 @@ BufferedOutputStream::WriteWideToUTF8(const wchar_t *src,
}
int length = WideCharToMultiByte(CP_UTF8, 0, src, src_length,
(char *)r.data, r.size,
(char *)r.data(), r.size(),
nullptr, nullptr);
if (length <= 0) {
const auto error = GetLastError();
@ -173,6 +173,6 @@ BufferedOutputStream::Flush()
if (r.empty())
return;
os.Write(r.data, r.size);
buffer.Consume(r.size);
os.Write(r.data(), r.size());
buffer.Consume(r.size());
}

View File

@ -51,7 +51,7 @@ BufferedReader::Fill(bool need_more)
assert(!w.empty());
}
std::size_t nbytes = reader.Read(w.data, w.size);
std::size_t nbytes = reader.Read(w.data(), w.size());
if (nbytes == 0) {
eof = true;
return !need_more;
@ -122,7 +122,7 @@ BufferedReader::ReadLine()
/* terminate the last line */
w[0] = 0;
char *line = buffer.Read().data;
char *line = buffer.Read().data();
buffer.Clear();
++line_number;
return line;

View File

@ -65,7 +65,7 @@ public:
[[gnu::pure]]
std::span<std::byte> Read() const noexcept {
return buffer.Read().ToVoid();
return std::as_writable_bytes(buffer.Read());
}
/**

View File

@ -50,7 +50,7 @@ GunzipReader::FillBuffer()
auto w = buffer.Write();
assert(!w.empty());
std::size_t nbytes = next.Read(w.data, w.size);
std::size_t nbytes = next.Read(w.data(), w.size());
if (nbytes == 0)
return false;
@ -78,8 +78,8 @@ GunzipReader::Read(void *data, std::size_t size)
flush = Z_FINISH;
}
z.next_in = r.data;
z.avail_in = r.size;
z.next_in = r.data();
z.avail_in = r.size();
int result = inflate(&z, flush);
if (result == Z_STREAM_END) {
@ -88,7 +88,7 @@ GunzipReader::Read(void *data, std::size_t size)
} else if (result != Z_OK)
throw ZlibError(result);
buffer.Consume(r.size - z.avail_in);
buffer.Consume(r.size() - z.avail_in);
if (z.avail_out < size)
return size - z.avail_out;

View File

@ -103,7 +103,7 @@ public:
*/
pointer Write(size_type n) noexcept {
WantWrite(n);
return Write().data;
return Write().data();
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2019 Max Kellermann <max.kellermann@gmail.com>
* Copyright 2003-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,12 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FOREIGN_FIFO_BUFFER_HXX
#define FOREIGN_FIFO_BUFFER_HXX
#include "WritableBuffer.hxx"
#pragma once
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <span>
#include <utility>
/**
@ -50,7 +48,7 @@ template<typename T>
class ForeignFifoBuffer {
public:
using size_type = std::size_t;
using Range = WritableBuffer<T>;
using Range = std::span<T>;
using pointer = typename Range::pointer;
using const_pointer = typename Range::const_pointer;
@ -211,9 +209,9 @@ public:
size_type Read(pointer p, size_type n) noexcept {
auto range = Read();
if (n > range.size)
n = range.size;
std::copy_n(range.data, n, p);
if (n > range.size())
n = range.size();
std::copy_n(range.data(), n, p);
Consume(n);
return n;
}
@ -227,7 +225,7 @@ public:
auto r = src.Read();
auto w = Write();
if (w.size < r.size && head > 0) {
if (w.size() < r.size() && head > 0) {
/* if the source contains more data than we
can append at the tail, try to make more
room by shifting the head to 0 */
@ -235,9 +233,9 @@ public:
w = Write();
}
const auto n = std::min(r.size, w.size);
const auto n = std::min(r.size(), w.size());
std::move(r.data, r.data + n, w.data);
std::move(r.data(), r.data() + n, w.data());
Append(n);
src.Consume(n);
return n;
@ -258,5 +256,3 @@ protected:
head = 0;
}
};
#endif

View File

@ -23,8 +23,6 @@
#include <algorithm>
#include <cassert>
#include <string.h>
PeakBuffer::~PeakBuffer() noexcept
{
delete normal_buffer;
@ -38,22 +36,22 @@ PeakBuffer::empty() const noexcept
(peak_buffer == nullptr || peak_buffer->empty());
}
WritableBuffer<void>
std::span<std::byte>
PeakBuffer::Read() const noexcept
{
if (normal_buffer != nullptr) {
const auto p = normal_buffer->Read();
if (!p.empty())
return p.ToVoid();
return p;
}
if (peak_buffer != nullptr) {
const auto p = peak_buffer->Read();
if (!p.empty())
return p.ToVoid();
return p;
}
return nullptr;
return {};
}
void
@ -77,10 +75,9 @@ PeakBuffer::Consume(std::size_t length) noexcept
static std::size_t
AppendTo(DynamicFifoBuffer<std::byte> &buffer,
const void *data, size_t length) noexcept
std::span<const std::byte> src) noexcept
{
assert(data != nullptr);
assert(length > 0);
assert(!src.empty());
std::size_t total = 0;
@ -89,37 +86,35 @@ AppendTo(DynamicFifoBuffer<std::byte> &buffer,
if (p.empty())
break;
const std::size_t nbytes = std::min(length, p.size);
memcpy(p.data, data, nbytes);
const std::size_t nbytes = std::min(src.size(), p.size());
std::copy_n(src.begin(), nbytes, p.begin());
buffer.Append(nbytes);
data = (const std::byte *)data + nbytes;
length -= nbytes;
src = src.subspan(nbytes);
total += nbytes;
} while (length > 0);
} while (!src.empty());
return total;
}
bool
PeakBuffer::Append(const void *data, std::size_t length)
PeakBuffer::Append(std::span<const std::byte> src)
{
if (length == 0)
if (src.empty())
return true;
if (peak_buffer != nullptr && !peak_buffer->empty()) {
std::size_t nbytes = AppendTo(*peak_buffer, data, length);
return nbytes == length;
std::size_t nbytes = AppendTo(*peak_buffer, src);
return nbytes == src.size();
}
if (normal_buffer == nullptr)
normal_buffer = new DynamicFifoBuffer<std::byte>(normal_size);
std::size_t nbytes = AppendTo(*normal_buffer, data, length);
std::size_t nbytes = AppendTo(*normal_buffer, src);
if (nbytes > 0) {
data = (const std::byte *)data + nbytes;
length -= nbytes;
if (length == 0)
src = src.subspan(nbytes);
if (src.empty())
return true;
}
@ -130,6 +125,6 @@ PeakBuffer::Append(const void *data, std::size_t length)
return false;
}
nbytes = AppendTo(*peak_buffer, data, length);
return nbytes == length;
nbytes = AppendTo(*peak_buffer, src);
return nbytes == src.size();
}

View File

@ -21,8 +21,8 @@
#define MPD_PEAK_BUFFER_HXX
#include <cstddef>
#include <span>
template<typename T> struct WritableBuffer;
template<typename T> class DynamicFifoBuffer;
/**
@ -61,11 +61,11 @@ public:
bool empty() const noexcept;
[[gnu::pure]]
WritableBuffer<void> Read() const noexcept;
std::span<std::byte> Read() const noexcept;
void Consume(std::size_t length) noexcept;
bool Append(const void *data, std::size_t length);
bool Append(std::span<const std::byte> src);
};
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2019 Max Kellermann <max.kellermann@gmail.com>
* Copyright 2003-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,12 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef STATIC_FIFO_BUFFER_HXX
#define STATIC_FIFO_BUFFER_HXX
#include "WritableBuffer.hxx"
#pragma once
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <span>
#include <utility>
/**
@ -46,7 +44,7 @@ template<class T, size_t size>
class StaticFifoBuffer {
public:
using size_type = std::size_t;
using Range = WritableBuffer<T>;
using Range = std::span<T>;
protected:
size_type head = 0, tail = 0;
@ -132,5 +130,3 @@ public:
head += n;
}
};
#endif

View File

@ -37,16 +37,16 @@ char *
ReadBufferedLine(B &buffer)
{
auto r = buffer.Read();
char *newline = reinterpret_cast<char*>(std::memchr(r.data, '\n', r.size));
char *newline = reinterpret_cast<char*>(std::memchr(r.data(), '\n', r.size()));
if (newline == nullptr)
return nullptr;
buffer.Consume(newline + 1 - r.data);
buffer.Consume(newline + 1 - r.data());
if (newline > r.data && newline[-1] == '\r')
if (newline > r.data() && newline[-1] == '\r')
--newline;
*newline = 0;
return r.data;
return r.data();
}
#endif

View File

@ -116,7 +116,7 @@ RunConvert(PcmConvert &convert, size_t in_frame_size,
const auto dest = buffer.Write();
assert(!dest.empty());
ssize_t nbytes = in_fd.Read(dest.data, dest.size);
ssize_t nbytes = in_fd.Read(dest.data(), dest.size());
if (nbytes <= 0)
break;
@ -126,13 +126,13 @@ RunConvert(PcmConvert &convert, size_t in_frame_size,
auto src = buffer.Read();
assert(!src.empty());
src.size -= src.size % in_frame_size;
src = src.first(src.size() - src.size() % in_frame_size);
if (src.empty())
continue;
buffer.Consume(src.size);
buffer.Consume(src.size());
auto output = convert.Convert({src.data, src.size});
auto output = convert.Convert({src.data(), src.size()});
out_fd.FullWrite(output.data, output.size);
}

View File

@ -141,7 +141,7 @@ RunOutput(AudioOutput &ao, AudioFormat audio_format,
const auto dest = buffer.Write();
assert(!dest.empty());
ssize_t nbytes = in_fd.Read(dest.data, dest.size);
ssize_t nbytes = in_fd.Read(dest.data(), dest.size());
if (nbytes <= 0)
break;
@ -151,13 +151,13 @@ RunOutput(AudioOutput &ao, AudioFormat audio_format,
auto src = buffer.Read();
assert(!src.empty());
src.size -= src.size % in_frame_size;
src = src.first(src.size() - src.size() % in_frame_size);
if (src.empty())
continue;
size_t consumed = ao.Play(src.data, src.size);
size_t consumed = ao.Play(src.data(), src.size());
assert(consumed <= src.size);
assert(consumed <= src.size());
assert(consumed % in_frame_size == 0);
buffer.Consume(consumed);