diff options
Diffstat (limited to 'source/fud_c_file.cpp')
-rw-r--r-- | source/fud_c_file.cpp | 91 |
1 files changed, 89 insertions, 2 deletions
diff --git a/source/fud_c_file.cpp b/source/fud_c_file.cpp index 24186bf..3d15431 100644 --- a/source/fud_c_file.cpp +++ b/source/fud_c_file.cpp @@ -38,10 +38,13 @@ CBinaryFile::~CBinaryFile() { close(); } -FileResult CBinaryFile::open() +FileStatus CBinaryFile::open() { + if (!m_filename.valid()) { + return FileStatus::InvalidName; + } m_file = fopen(m_filename.c_str(), m_mode.c_str()); - return m_file != nullptr ? FileResult::Success : FileResult::Error; + return m_file != nullptr ? FileStatus::Success : FileStatus::Error; } void CBinaryFile::close() @@ -62,4 +65,88 @@ FILE* CBinaryFile::file() return m_file; } +bool CBinaryFile::isOpen() const +{ + return m_file != nullptr; +} + +Result<size_t, FileStatus> CBinaryFile::size() const +{ + using RetType = Result<size_t, FileStatus>; + if (!isOpen()) { + return RetType::error(FileStatus::InvalidState); + } + + auto seekStatus = fseek(m_file, 0, SEEK_END); + if (seekStatus != 0) { + return RetType::error(FileStatus::Error); + } + + auto fileSizeResult = ftell(m_file); + if (fileSizeResult < 0) { + return RetType::error(FileStatus::Error); + } + + auto fileSize = static_cast<size_t>(fileSizeResult); + + auto resetStatus = reset(); + if (resetStatus != FileStatus::Success) { + return RetType::error(resetStatus); + } + + return RetType::okay(fileSize); +} + +FileStatus CBinaryFile::read(void* destination, size_t destinationSize, size_t length) +{ + return read(destination, destinationSize, length, 0); +} + +FileStatus CBinaryFile::read(void* destination, size_t destinationSize, size_t length, size_t offset) +{ + if (length == 0) { + return FileStatus::Success; + } + + if (destination == nullptr) { + return FileStatus::NullPointer; + } + + if (offset > LONG_MAX || SIZE_MAX - offset < length || destinationSize < length) { + return FileStatus::InvalidArgument; + } + + auto fileSizeResult = size(); + if (fileSizeResult.isError()) { + return fileSizeResult.getError(); + } + + auto fileSize = fileSizeResult.getOkay(); + if (offset + length > fileSize) { + return FileStatus::InvalidArgument; + } + + auto seekResult = fseek(m_file, static_cast<long>(offset), SEEK_SET); + if (seekResult != 0) { + return FileStatus::Error; + } + + auto* destPtr = static_cast<char*>(destination); + auto readResult = fread(destPtr, length, 1, m_file); + if (readResult != 1) { + static_cast<void>(reset()); + return FileStatus::Error; + } + + return FileStatus::Success; +} + +FileStatus CBinaryFile::reset() const { + if (!isOpen()) { + return FileStatus::InvalidState; + } + auto result = fseek(m_file, 0, SEEK_SET); + return result == 0 ? FileStatus::Success : FileStatus::Error; +} + } // namespace fud |