io/OutputStream: use std::span

This commit is contained in:
Max Kellermann 2023-05-15 11:00:21 +02:00
parent e72d27566c
commit 8ba68fdb47
12 changed files with 40 additions and 42 deletions

View File

@ -18,6 +18,6 @@ EncoderToOutputStream(OutputStream &os, Encoder &encoder)
/* write everything to the stream */
os.Write(r.data(), r.size());
os.Write(r);
}
}

View File

@ -3,6 +3,7 @@
#include "BufferedOutputStream.hxx"
#include "OutputStream.hxx"
#include "util/SpanCast.hxx"
#include <fmt/format.h>
@ -16,33 +17,33 @@
#endif
bool
BufferedOutputStream::AppendToBuffer(const void *data, std::size_t size) noexcept
BufferedOutputStream::AppendToBuffer(std::span<const std::byte> src) noexcept
{
auto r = buffer.Write();
if (r.size() < size)
auto w = buffer.Write();
if (w.size() < src.size())
return false;
memcpy(r.data(), data, size);
buffer.Append(size);
std::copy(src.begin(), src.end(), w.begin());
buffer.Append(src.size());
return true;
}
void
BufferedOutputStream::Write(const void *data, std::size_t size)
BufferedOutputStream::Write(std::span<const std::byte> src)
{
/* try to append to the current buffer */
if (AppendToBuffer(data, size))
if (AppendToBuffer(src))
return;
/* not enough room in the buffer - flush it */
Flush();
/* see if there's now enough room */
if (AppendToBuffer(data, size))
if (AppendToBuffer(src))
return;
/* too large for the buffer: direct write */
os.Write(data, size);
os.Write(src);
}
void
@ -56,7 +57,7 @@ BufferedOutputStream::VFmt(fmt::string_view format_str, fmt::format_args args)
#else
fmt::vformat_to(b, format_str, args);
#endif
return Write(b.data(), b.size());
return Write(std::as_bytes(std::span{b.data(), b.size()}));
}
#ifdef _UNICODE
@ -107,6 +108,6 @@ BufferedOutputStream::Flush()
if (r.empty())
return;
os.Write(r.data(), r.size());
os.Write(r);
buffer.Consume(r.size());
}

View File

@ -43,11 +43,7 @@ public:
/**
* Write the contents of a buffer.
*/
void Write(const void *data, std::size_t size);
void Write(std::span<const std::byte> src) {
Write(src.data(), src.size());
}
void Write(std::span<const std::byte> src);
/**
* Write the given object. Note that this is only safe with
@ -55,7 +51,7 @@ public:
*/
template<typename T>
void WriteT(const T &value) {
Write(&value, sizeof(value));
Write(std::as_bytes(std::span{&value, 1}));
}
/**
@ -115,7 +111,7 @@ public:
}
private:
bool AppendToBuffer(const void *data, std::size_t size) noexcept;
bool AppendToBuffer(std::span<const std::byte> src) noexcept;
#ifdef _UNICODE
void WriteWideToUTF8(std::wstring_view src);

View File

@ -114,15 +114,15 @@ FileOutputStream::Tell() const noexcept
}
void
FileOutputStream::Write(const void *data, size_t size)
FileOutputStream::Write(std::span<const std::byte> src)
{
assert(IsDefined());
DWORD nbytes;
if (!WriteFile(handle, data, size, &nbytes, nullptr))
if (!WriteFile(handle, src.data(), src.size(), &nbytes, nullptr))
throw FmtLastError("Failed to write to {}", GetPath());
if (size_t(nbytes) != size)
if (size_t(nbytes) != src.size())
throw FmtLastError(DWORD{ERROR_DISK_FULL},
"Failed to write to {}",
GetPath());
@ -246,14 +246,14 @@ FileOutputStream::Tell() const noexcept
}
void
FileOutputStream::Write(const void *data, size_t size)
FileOutputStream::Write(std::span<const std::byte> src)
{
assert(IsDefined());
ssize_t nbytes = fd.Write(data, size);
ssize_t nbytes = fd.Write(src.data(), src.size());
if (nbytes < 0)
throw FmtErrno("Failed to write to {}", GetPath());
else if ((size_t)nbytes < size)
else if ((size_t)nbytes < src.size())
throw FmtErrno(ENOSPC, "Failed to write to {}", GetPath());
}

View File

@ -127,7 +127,7 @@ public:
uint64_t Tell() const noexcept;
/* virtual methods from class OutputStream */
void Write(const void *data, size_t size) override;
void Write(std::span<const std::byte> src) override;
/**
* Flush all data written to this object to disk (but does not

View File

@ -5,6 +5,7 @@
#define OUTPUT_STREAM_HXX
#include <cstddef>
#include <span>
class OutputStream {
public:
@ -14,7 +15,7 @@ public:
/**
* Throws std::exception on error.
*/
virtual void Write(const void *data, std::size_t size) = 0;
virtual void Write(std::span<const std::byte> src) = 0;
};
#endif

View File

@ -15,8 +15,8 @@ public:
explicit StdioOutputStream(FILE *_file) noexcept:file(_file) {}
/* virtual methods from class OutputStream */
void Write(const void *data, size_t size) override {
fwrite(data, 1, size, file);
void Write(std::span<const std::byte> src) override {
fwrite(src.data(), 1, src.size(), file);
/* this class is debug-only and ignores errors */
}

View File

@ -47,7 +47,7 @@ GzipOutputStream::SyncFlush()
if (z.next_out == output)
break;
next.Write(output, z.next_out - output);
next.Write(std::as_bytes(std::span{output}.first(z.next_out - output)));
} while (z.avail_out == 0);
}
@ -65,7 +65,7 @@ GzipOutputStream::Finish()
int result = deflate(&z, Z_FINISH);
if (z.next_out > output)
next.Write(output, z.next_out - output);
next.Write(std::as_bytes(std::span{output}.first(z.next_out - output)));
if (result == Z_STREAM_END)
break;
@ -75,13 +75,13 @@ GzipOutputStream::Finish()
}
void
GzipOutputStream::Write(const void *_data, size_t size)
GzipOutputStream::Write(std::span<const std::byte> src)
{
/* zlib's API requires non-const input pointer */
void *data = const_cast<void *>(_data);
void *data = const_cast<std::byte *>(src.data());
z.next_in = reinterpret_cast<Bytef *>(data);
z.avail_in = size;
z.avail_in = src.size();
while (z.avail_in > 0) {
Bytef output[65536];
@ -93,6 +93,6 @@ GzipOutputStream::Write(const void *_data, size_t size)
throw ZlibError(result);
if (z.next_out > output)
next.Write(output, z.next_out - output);
next.Write(std::as_bytes(std::span{output}.first(z.next_out - output)));
}
}

View File

@ -42,7 +42,7 @@ public:
void Finish();
/* virtual methods from class OutputStream */
void Write(const void *data, size_t size) override;
void Write(std::span<const std::byte> src) override;
};
#endif

View File

@ -17,7 +17,7 @@ static bool
Copy(OutputStream &dest, int src)
{
while (true) {
uint8_t buffer[8192];
std::byte buffer[8192];
ssize_t nbytes = read(src, buffer, sizeof(buffer));
if (nbytes < 0) {
fprintf(stderr, "Failed to read from stdin: %s\n",
@ -28,7 +28,7 @@ Copy(OutputStream &dest, int src)
if (nbytes == 0)
return true;
dest.Write(buffer, nbytes);
dest.Write(std::span{buffer}.first(nbytes));
}
}

View File

@ -15,12 +15,12 @@ static void
Copy(OutputStream &dest, Reader &src)
{
while (true) {
char buffer[4096];
std::byte buffer[4096];
size_t nbytes = src.Read(buffer, sizeof(buffer));
if (nbytes == 0)
break;
dest.Write(buffer, nbytes);
dest.Write(std::span{buffer}.first(nbytes));
}
}

View File

@ -14,7 +14,7 @@ static void
Copy(OutputStream &dest, int src)
{
while (true) {
char buffer[4096];
std::byte buffer[4096];
ssize_t nbytes = read(src, buffer, sizeof(buffer));
if (nbytes <= 0) {
if (nbytes < 0)
@ -23,7 +23,7 @@ Copy(OutputStream &dest, int src)
return;
}
dest.Write(buffer, nbytes);
dest.Write(std::span{buffer}.first(nbytes));
}
}