13namespace fs = std::filesystem;
17 fs::path ToFsPath(
const DotNetDupe::System::String& sPath) {
29 struct FileStream::Impl {
34 static std::ios_base::openmode
DetermineOpenMode(
int iMode,
const String& sPath,
bool& bCanRead,
bool& bCanWrite,
bool& bCanSeek) {
37 if (iMode == 0 && fs::exists(ToFsPath(sPath)))
throw IOException(
"File already exists.");
41 bCanRead =
false; bCanWrite =
true; bCanSeek =
false;
42 return std::ios_base::binary | std::ios_base::out | std::ios_base::app;
46 bCanRead =
true; bCanWrite =
true; bCanSeek =
true;
47 std::ios_base::openmode m = std::ios_base::binary | std::ios_base::in | std::ios_base::out;
48 if (iMode == 0 || iMode == 1 || iMode == 4) m |= std::ios_base::trunc;
54 std::ios_base::openmode openMode =
DetermineOpenMode(iMode, sPath, m_bCanRead, m_bCanWrite, m_bCanSeek);
57 m_pImpl->fs.open(ToFsPath(sPath), openMode);
58 if (!m_pImpl->fs.is_open())
throw IOException(
"Could not open file.");
85 throw IOException(
"Stream does not support seeking.");
89 auto& mutableStream = m_pImpl->fs;
90 long iCurrentPos =
static_cast<long>(mutableStream.tellg());
91 mutableStream.seekg(0, std::ios_base::end);
92 long iLength =
static_cast<long>(mutableStream.tellg());
93 mutableStream.seekg(iCurrentPos);
100 throw IOException(
"Stream does not support seeking.");
104 return static_cast<long>(m_pImpl->fs.tellg());
110 throw IOException(
"Stream does not support seeking.");
114 m_pImpl->fs.seekg(llValue);
119 if (!m_pImpl)
return;
123 if (m_pImpl->fs.bad()) {
131 throw IOException(
"Stream does not support reading.");
135 m_pImpl->fs.read(pBuffer + iOffset, nCount);
136 if (m_pImpl->fs.bad()) {
141 if (m_pImpl->fs.eof()) {
145 return static_cast<int>(m_pImpl->fs.gcount());
151 throw IOException(
"Stream does not support seeking.");
155 std::ios_base::seekdir dir;
157 dir = std::ios_base::beg;
158 }
else if (iOrigin == 1) {
159 dir = std::ios_base::cur;
160 }
else if (iOrigin == 2) {
161 dir = std::ios_base::end;
167 m_pImpl->fs.seekg(llOffset, dir);
168 return static_cast<long>(m_pImpl->fs.tellg());
178 throw IOException(
"Stream does not support writing.");
182 m_pImpl->fs.write(pBuffer + iOffset, nCount);
183 if (m_pImpl->fs.bad() || m_pImpl->fs.fail()) {
190 if (m_pImpl && m_pImpl->fs.is_open()) {
Defines the exception thrown when an invalid argument is provided to a method.
Defines the exception thrown when an argument value is outside the acceptable range of values.
The exception that is thrown when an I/O error occurs.
ArgumentException(const String &sMessage)
Initializes a new instance of the ArgumentException class with a specified error message.
int Read(char *pBuffer, int iOffset, int nCount) override
Reads a block of bytes from the stream and writes the data in a given buffer.
bool CanSeek() const override
Gets a value indicating whether the current stream supports seeking.
void Write(const char *pBuffer, int iOffset, int nCount) override
Writes a block of bytes to the file stream.
long Seek(long llOffset, int iOrigin) override
Sets the current position of this stream to the given value.
bool CanRead() const override
Gets a value indicating whether the current stream supports reading.
void SetPosition(long llValue) override
Sets the current position within the stream.
~FileStream() override
Destructor releasing encapsulated native stream resources.
long GetLength() const override
Gets the length in bytes of the stream.
void Flush() override
Clears buffers for this stream and causes any unwritten data to be written to the file.
long GetPosition() const override
Gets the current position within the stream.
void SetLength(long llValue) override
Sets the length of this stream to the given value.
void Dispose() override
Releases all unmanaged resources used by the FileStream.
bool CanWrite() const override
Gets a value indicating whether the current stream supports writing.
FileStream(const String &sPath, int iMode)
Initializes a new instance of the FileStream class with the specified path and creation mode.
IOException()
Initializes a new instance of the IOException class with a default message.
static std::wstring Utf8ToWChar(const char *pUtf8Str)
Represents text as a sequence of UTF-8 code units with culture-invariant operations.
const char * GetRawString() const
static std::ios_base::openmode DetermineOpenMode(int iMode, const String &sPath, bool &bCanRead, bool &bCanWrite, bool &bCanSeek)
Determine stream openmode and capability flags from FileMode.