osb/source/core/StarIODevice.hpp
2024-02-25 15:46:47 +01:00

131 lines
3.6 KiB
C++

#pragma once
#include "StarByteArray.hpp"
#include "StarString.hpp"
namespace Star {
STAR_CLASS(IODevice);
STAR_EXCEPTION(EofException, IOException);
enum class IOMode : uint8_t {
Closed = 0x0,
Read = 0x1,
Write = 0x2,
ReadWrite = 0x3,
Append = 0x4,
Truncate = 0x8,
};
IOMode operator|(IOMode a, IOMode b);
bool operator&(IOMode a, IOMode b);
// Should match SEEK_SET, SEEK_CUR, AND SEEK_END
enum IOSeek : uint8_t {
Absolute = 0,
Relative = 1,
End = 2
};
// Abstract Interface to a random access I/O device.
class IODevice {
public:
IODevice(IOMode mode = IOMode::Closed);
virtual ~IODevice();
// Do a read or write that may result in less data read or written than
// requested.
virtual size_t read(char* data, size_t len) = 0;
virtual size_t write(char const* data, size_t len) = 0;
virtual StreamOffset pos() = 0;
virtual void seek(StreamOffset pos, IOSeek mode = IOSeek::Absolute) = 0;
// Default implementation throws unsupported exception.
virtual void resize(StreamOffset size);
// Read / write from an absolute offset in the file without modifying the
// current file position. Default implementation stores the file position,
// then seeks and calls read/write partial, then restores the file position,
// and is not thread safe.
virtual size_t readAbsolute(StreamOffset readPosition, char* data, size_t len);
virtual size_t writeAbsolute(StreamOffset writePosition, char const* data, size_t len);
// Read and write fully, and throw an exception in every other case. The
// default implementations here will call the normal read or write, and if
// the full amount is not read will throw an exception.
virtual void readFull(char* data, size_t len);
virtual void writeFull(char const* data, size_t len);
virtual void readFullAbsolute(StreamOffset readPosition, char* data, size_t len);
virtual void writeFullAbsolute(StreamOffset writePosition, char const* data, size_t len);
// Default implementation throws exception if opening in a different mode
// than the current mode.
virtual void open(IOMode mode);
// Default implementation sets mode equal to Closed
virtual void close();
// Default implementation is a no-op
virtual void sync();
// Default implementation just prints address of generic IODevice
virtual String deviceName() const;
// Is the file position at the end of the file and there is no more to read?
// This is not the same as feof, which returns true after an unsuccesful read
// past the end, it should return true after succesfully reading the final
// byte. Default implementation returns pos() >= size();
virtual bool atEnd();
// Default is to store position, seek end, then restore position.
virtual StreamOffset size();
IOMode mode() const;
bool isOpen() const;
bool isReadable() const;
bool isWritable() const;
ByteArray readBytes(size_t size);
void writeBytes(ByteArray const& p);
ByteArray readBytesAbsolute(StreamOffset readPosition, size_t size);
void writeBytesAbsolute(StreamOffset writePosition, ByteArray const& p);
protected:
void setMode(IOMode mode);
IODevice(IODevice const&);
IODevice& operator=(IODevice const&);
private:
atomic<IOMode> m_mode;
};
inline IOMode operator|(IOMode a, IOMode b) {
return (IOMode)((uint8_t)a | (uint8_t)b);
}
inline bool operator&(IOMode a, IOMode b) {
return (uint8_t)a & (uint8_t)b;
}
inline IOMode IODevice::mode() const {
return m_mode;
}
inline bool IODevice::isOpen() const {
return m_mode != IOMode::Closed;
}
inline bool IODevice::isReadable() const {
return m_mode & IOMode::Read;
}
inline bool IODevice::isWritable() const {
return m_mode & IOMode::Write;
}
}