From 5f0e6e9726824b53a730585486255209a0c3d179 Mon Sep 17 00:00:00 2001 From: Patrick Wuttke Date: Fri, 29 Nov 2024 01:37:50 +0100 Subject: [PATCH] Added STLStream that wraps STL stream types for usage with functions that expect a Mijin stream. --- source/mijin/io/stlstream.hpp | 128 ++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/source/mijin/io/stlstream.hpp b/source/mijin/io/stlstream.hpp index e84aac7..db4b595 100644 --- a/source/mijin/io/stlstream.hpp +++ b/source/mijin/io/stlstream.hpp @@ -88,6 +88,134 @@ public: }; using IOStreamAdapter = BasicIOStreamAdapter; + +template> +class BasicSTLStream : public Stream +{ +private: + std::basic_istream* istream_ = nullptr; + std::basic_ostream* ostream_ = nullptr; +public: + explicit BasicSTLStream(std::basic_istream& istream) : istream_(&istream) {} + explicit BasicSTLStream(std::basic_ostream& ostream) : ostream_(&ostream) {} + explicit BasicSTLStream(std::basic_iostream& iostream) : istream_(&iostream), ostream_(&ostream_) {} + StreamError readRaw(std::span buffer, const ReadOptions& options = {}, std::size_t* outBytesRead = nullptr) override + { + (void) options; + + if (istream_ != nullptr) + { + if (buffer.size() % sizeof(TChar) != 0) + { + // buffer size must be divisible by character size + return StreamError::IO_ERROR; + } + + istream_->read(std::bit_cast(buffer.data()), buffer.size() / sizeof(TChar)); + if (!istream_->good()) + { + return StreamError::IO_ERROR; + } + if (outBytesRead != nullptr) + { + *outBytesRead = buffer.size(); + } + return StreamError::SUCCESS; + } + return StreamError::NOT_SUPPORTED; + } + + StreamError writeRaw(std::span buffer) override + { + if (ostream_ != nullptr) + { + if (buffer.size() % sizeof(TChar) != 0) + { + // buffer size must be divisible by character size + return StreamError::IO_ERROR; + } + + ostream_->write(std::bit_cast(buffer.data()), buffer.size() / sizeof(TChar)); + return StreamError::SUCCESS; + } + return StreamError::NOT_SUPPORTED; + } + + std::size_t tell() override + { + // kind of weird case, since the streams can have different positions + // this is fine, I guess + if (istream_ != nullptr) + { + return istream_->tellg(); + } + if (ostream_ != nullptr) + { + return ostream_->tellp(); + } + return 0; + } + + StreamError seek(std::intptr_t pos, mijin::SeekMode seekMode = SeekMode::ABSOLUTE) override + { + std::ios_base::seekdir seekDir = std::ios_base::beg; + switch (seekMode) + { + case mijin::SeekMode::ABSOLUTE: + break; + case mijin::SeekMode::RELATIVE: + seekDir = std::ios_base::cur; + break; + case mijin::SeekMode::RELATIVE_TO_END: + seekDir = std::ios_base::end; + break; + } + if (istream_ != nullptr) + { + istream_->seekg(pos, seekDir); + if (!istream_->good()) + { + return StreamError::IO_ERROR; + } + } + if (ostream_ != nullptr) + { + ostream_->seekp(pos, seekDir); + if (!ostream_->good()) + { + return StreamError::IO_ERROR; + } + } + return StreamError::SUCCESS; + } + + bool isAtEnd() override + { + if (istream_ != nullptr) + { + return istream_->peek() == TTraits::eof(); + } + return false; + } + + StreamFeatures getFeatures() override + { + return { + .read = istream_ != nullptr, + .write = ostream_ != nullptr, + .tell = istream_ != nullptr || ostream_ != nullptr, + .seek = istream_ != nullptr || ostream_ != nullptr, + .async = false, + .readOptions = { + .partial = false, + .peek = false, + .noBlock = false + } + }; + } +}; + +using STLStream = BasicSTLStream; } // namespace mijin #endif // !defined(MIJIN_IO_STLSTREAM_HPP_INCLUDED)