// Copyright 2024 The DMBMX2Tools Authors // SPDX-License-Identifier: MIT #pragma once #include #include namespace dmtools::io { enum class StreamSeekDirection : u8 { Beg, Cur, End }; using StreamDiff = i64; // TODO: Communicate error conditions using ErrorOr<> instead of // -1 values. /// A abstract stream of bytes. We use a custom implementation /// instead of C++ IO streams mostly for control reasons, and /// also to avoid exceptions (we'll use ErrorOr for errors later on) struct Stream { Stream() = default; virtual ~Stream() = default; Stream(const Stream&) = delete; Stream(Stream&&) = delete; virtual void Flush() { return; } virtual StreamDiff ReadSome(u8* buffer, usize length) = 0; StreamDiff ReadSome(std::vector& buffer); virtual StreamDiff WriteSome(const u8* buffer, usize length) { // Default implementation disallows writes. Can be changed return -1; } StreamDiff WriteSome(const std::vector& buffer); /// Reads a single POD type from stream template inline bool ReadObject(T& obj) { auto sz = ReadSome(std::bit_cast(&obj), sizeof(T)); if(sz != sizeof(T)) return false; return true; } template inline bool WriteObject(const T& obj) { auto sz = WriteSome(std::bit_cast(&obj), sizeof(T)); if(sz != sizeof(T)) return false; return true; } virtual StreamDiff Seek(StreamDiff where, StreamSeekDirection dir) = 0; virtual StreamDiff Tell() const = 0; virtual bool Ok() const = 0; virtual bool Eof() const = 0; inline operator bool() const { return Ok() && !Eof(); } }; } // namespace dmtools