io/OutputStream: use std::span
This commit is contained in:
parent
e72d27566c
commit
8ba68fdb47
|
@ -18,6 +18,6 @@ EncoderToOutputStream(OutputStream &os, Encoder &encoder)
|
||||||
|
|
||||||
/* write everything to the stream */
|
/* write everything to the stream */
|
||||||
|
|
||||||
os.Write(r.data(), r.size());
|
os.Write(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "BufferedOutputStream.hxx"
|
#include "BufferedOutputStream.hxx"
|
||||||
#include "OutputStream.hxx"
|
#include "OutputStream.hxx"
|
||||||
|
#include "util/SpanCast.hxx"
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
@ -16,33 +17,33 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BufferedOutputStream::AppendToBuffer(const void *data, std::size_t size) noexcept
|
BufferedOutputStream::AppendToBuffer(std::span<const std::byte> src) noexcept
|
||||||
{
|
{
|
||||||
auto r = buffer.Write();
|
auto w = buffer.Write();
|
||||||
if (r.size() < size)
|
if (w.size() < src.size())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
memcpy(r.data(), data, size);
|
std::copy(src.begin(), src.end(), w.begin());
|
||||||
buffer.Append(size);
|
buffer.Append(src.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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 */
|
/* try to append to the current buffer */
|
||||||
if (AppendToBuffer(data, size))
|
if (AppendToBuffer(src))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* not enough room in the buffer - flush it */
|
/* not enough room in the buffer - flush it */
|
||||||
Flush();
|
Flush();
|
||||||
|
|
||||||
/* see if there's now enough room */
|
/* see if there's now enough room */
|
||||||
if (AppendToBuffer(data, size))
|
if (AppendToBuffer(src))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* too large for the buffer: direct write */
|
/* too large for the buffer: direct write */
|
||||||
os.Write(data, size);
|
os.Write(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -56,7 +57,7 @@ BufferedOutputStream::VFmt(fmt::string_view format_str, fmt::format_args args)
|
||||||
#else
|
#else
|
||||||
fmt::vformat_to(b, format_str, args);
|
fmt::vformat_to(b, format_str, args);
|
||||||
#endif
|
#endif
|
||||||
return Write(b.data(), b.size());
|
return Write(std::as_bytes(std::span{b.data(), b.size()}));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _UNICODE
|
#ifdef _UNICODE
|
||||||
|
@ -107,6 +108,6 @@ BufferedOutputStream::Flush()
|
||||||
if (r.empty())
|
if (r.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
os.Write(r.data(), r.size());
|
os.Write(r);
|
||||||
buffer.Consume(r.size());
|
buffer.Consume(r.size());
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,11 +43,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Write the contents of a buffer.
|
* Write the contents of a buffer.
|
||||||
*/
|
*/
|
||||||
void Write(const void *data, std::size_t size);
|
void Write(std::span<const std::byte> src);
|
||||||
|
|
||||||
void Write(std::span<const std::byte> src) {
|
|
||||||
Write(src.data(), src.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the given object. Note that this is only safe with
|
* Write the given object. Note that this is only safe with
|
||||||
|
@ -55,7 +51,7 @@ public:
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void WriteT(const T &value) {
|
void WriteT(const T &value) {
|
||||||
Write(&value, sizeof(value));
|
Write(std::as_bytes(std::span{&value, 1}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -115,7 +111,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool AppendToBuffer(const void *data, std::size_t size) noexcept;
|
bool AppendToBuffer(std::span<const std::byte> src) noexcept;
|
||||||
|
|
||||||
#ifdef _UNICODE
|
#ifdef _UNICODE
|
||||||
void WriteWideToUTF8(std::wstring_view src);
|
void WriteWideToUTF8(std::wstring_view src);
|
||||||
|
|
|
@ -114,15 +114,15 @@ FileOutputStream::Tell() const noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FileOutputStream::Write(const void *data, size_t size)
|
FileOutputStream::Write(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
assert(IsDefined());
|
assert(IsDefined());
|
||||||
|
|
||||||
DWORD nbytes;
|
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());
|
throw FmtLastError("Failed to write to {}", GetPath());
|
||||||
|
|
||||||
if (size_t(nbytes) != size)
|
if (size_t(nbytes) != src.size())
|
||||||
throw FmtLastError(DWORD{ERROR_DISK_FULL},
|
throw FmtLastError(DWORD{ERROR_DISK_FULL},
|
||||||
"Failed to write to {}",
|
"Failed to write to {}",
|
||||||
GetPath());
|
GetPath());
|
||||||
|
@ -246,14 +246,14 @@ FileOutputStream::Tell() const noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FileOutputStream::Write(const void *data, size_t size)
|
FileOutputStream::Write(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
assert(IsDefined());
|
assert(IsDefined());
|
||||||
|
|
||||||
ssize_t nbytes = fd.Write(data, size);
|
ssize_t nbytes = fd.Write(src.data(), src.size());
|
||||||
if (nbytes < 0)
|
if (nbytes < 0)
|
||||||
throw FmtErrno("Failed to write to {}", GetPath());
|
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());
|
throw FmtErrno(ENOSPC, "Failed to write to {}", GetPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ public:
|
||||||
uint64_t Tell() const noexcept;
|
uint64_t Tell() const noexcept;
|
||||||
|
|
||||||
/* virtual methods from class OutputStream */
|
/* 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
|
* Flush all data written to this object to disk (but does not
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#define OUTPUT_STREAM_HXX
|
#define OUTPUT_STREAM_HXX
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <span>
|
||||||
|
|
||||||
class OutputStream {
|
class OutputStream {
|
||||||
public:
|
public:
|
||||||
|
@ -14,7 +15,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Throws std::exception on error.
|
* 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
|
#endif
|
||||||
|
|
|
@ -15,8 +15,8 @@ public:
|
||||||
explicit StdioOutputStream(FILE *_file) noexcept:file(_file) {}
|
explicit StdioOutputStream(FILE *_file) noexcept:file(_file) {}
|
||||||
|
|
||||||
/* virtual methods from class OutputStream */
|
/* virtual methods from class OutputStream */
|
||||||
void Write(const void *data, size_t size) override {
|
void Write(std::span<const std::byte> src) override {
|
||||||
fwrite(data, 1, size, file);
|
fwrite(src.data(), 1, src.size(), file);
|
||||||
|
|
||||||
/* this class is debug-only and ignores errors */
|
/* this class is debug-only and ignores errors */
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ GzipOutputStream::SyncFlush()
|
||||||
if (z.next_out == output)
|
if (z.next_out == output)
|
||||||
break;
|
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);
|
} while (z.avail_out == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ GzipOutputStream::Finish()
|
||||||
|
|
||||||
int result = deflate(&z, Z_FINISH);
|
int result = deflate(&z, Z_FINISH);
|
||||||
if (z.next_out > output)
|
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)
|
if (result == Z_STREAM_END)
|
||||||
break;
|
break;
|
||||||
|
@ -75,13 +75,13 @@ GzipOutputStream::Finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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 */
|
/* 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.next_in = reinterpret_cast<Bytef *>(data);
|
||||||
z.avail_in = size;
|
z.avail_in = src.size();
|
||||||
|
|
||||||
while (z.avail_in > 0) {
|
while (z.avail_in > 0) {
|
||||||
Bytef output[65536];
|
Bytef output[65536];
|
||||||
|
@ -93,6 +93,6 @@ GzipOutputStream::Write(const void *_data, size_t size)
|
||||||
throw ZlibError(result);
|
throw ZlibError(result);
|
||||||
|
|
||||||
if (z.next_out > output)
|
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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ public:
|
||||||
void Finish();
|
void Finish();
|
||||||
|
|
||||||
/* virtual methods from class OutputStream */
|
/* virtual methods from class OutputStream */
|
||||||
void Write(const void *data, size_t size) override;
|
void Write(std::span<const std::byte> src) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,7 +17,7 @@ static bool
|
||||||
Copy(OutputStream &dest, int src)
|
Copy(OutputStream &dest, int src)
|
||||||
{
|
{
|
||||||
while (true) {
|
while (true) {
|
||||||
uint8_t buffer[8192];
|
std::byte buffer[8192];
|
||||||
ssize_t nbytes = read(src, buffer, sizeof(buffer));
|
ssize_t nbytes = read(src, buffer, sizeof(buffer));
|
||||||
if (nbytes < 0) {
|
if (nbytes < 0) {
|
||||||
fprintf(stderr, "Failed to read from stdin: %s\n",
|
fprintf(stderr, "Failed to read from stdin: %s\n",
|
||||||
|
@ -28,7 +28,7 @@ Copy(OutputStream &dest, int src)
|
||||||
if (nbytes == 0)
|
if (nbytes == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
dest.Write(buffer, nbytes);
|
dest.Write(std::span{buffer}.first(nbytes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,12 @@ static void
|
||||||
Copy(OutputStream &dest, Reader &src)
|
Copy(OutputStream &dest, Reader &src)
|
||||||
{
|
{
|
||||||
while (true) {
|
while (true) {
|
||||||
char buffer[4096];
|
std::byte buffer[4096];
|
||||||
size_t nbytes = src.Read(buffer, sizeof(buffer));
|
size_t nbytes = src.Read(buffer, sizeof(buffer));
|
||||||
if (nbytes == 0)
|
if (nbytes == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
dest.Write(buffer, nbytes);
|
dest.Write(std::span{buffer}.first(nbytes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ static void
|
||||||
Copy(OutputStream &dest, int src)
|
Copy(OutputStream &dest, int src)
|
||||||
{
|
{
|
||||||
while (true) {
|
while (true) {
|
||||||
char buffer[4096];
|
std::byte buffer[4096];
|
||||||
ssize_t nbytes = read(src, buffer, sizeof(buffer));
|
ssize_t nbytes = read(src, buffer, sizeof(buffer));
|
||||||
if (nbytes <= 0) {
|
if (nbytes <= 0) {
|
||||||
if (nbytes < 0)
|
if (nbytes < 0)
|
||||||
|
@ -23,7 +23,7 @@ Copy(OutputStream &dest, int src)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.Write(buffer, nbytes);
|
dest.Write(std::span{buffer}.first(nbytes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue