diff --git a/source/mijin/io/stream.cpp b/source/mijin/io/stream.cpp index dc7856e..57148db 100644 --- a/source/mijin/io/stream.cpp +++ b/source/mijin/io/stream.cpp @@ -290,6 +290,29 @@ mijin::Task Stream::c_readLine(std::string& outString) co_return StreamError::SUCCESS; } +StreamError Stream::copyTo(Stream& other) +{ + MIJIN_ASSERT(getFeatures().read, "Stream must support reading."); + MIJIN_ASSERT(other.getFeatures().write, "Other stream must support writing."); + + static constexpr std::size_t CHUNK_SIZE = 4096; + std::array chunk = {}; + + while (!isAtEnd()) + { + std::size_t bytesRead = 0; + if (const StreamError error = readRaw(chunk, {.partial = true}, &bytesRead); error != StreamError::SUCCESS) + { + return error; + } + if (const StreamError error = other.writeRaw(chunk.data(), bytesRead); error != StreamError::SUCCESS) + { + return error; + } + } + return StreamError::SUCCESS; +} + FileStream::~FileStream() { if (handle) { @@ -441,7 +464,7 @@ StreamFeatures FileStream::getFeatures() if (handle) { return { - .read = (mode == FileOpenMode::READ), + .read = (mode == FileOpenMode::READ || mode == FileOpenMode::READ_WRITE), .write = (mode == FileOpenMode::WRITE || mode == FileOpenMode::APPEND || mode == FileOpenMode::READ_WRITE), .tell = true, .seek = true, diff --git a/source/mijin/io/stream.hpp b/source/mijin/io/stream.hpp index 6ea23db..8893ba0 100644 --- a/source/mijin/io/stream.hpp +++ b/source/mijin/io/stream.hpp @@ -275,6 +275,8 @@ public: StreamError getTotalLength(std::size_t& outLength); + StreamError copyTo(Stream& otherStream); + template typename TAllocator> StreamError readRest(BaseTypelessBuffer& outBuffer); @@ -544,7 +546,7 @@ inline void throwOnError(mijin::StreamError error) if (error == mijin::StreamError::SUCCESS) { return; } - throw std::runtime_error(errorName(error)); + throw Exception(errorName(error)); } inline void throwOnError(mijin::StreamError error, std::string message) @@ -552,7 +554,7 @@ inline void throwOnError(mijin::StreamError error, std::string message) if (error == mijin::StreamError::SUCCESS) { return; } - throw std::runtime_error(message + ": " + errorName(error)); + throw Exception(message + ": " + errorName(error)); } template