/* * libfud * Copyright 2024 Dominick Allen * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FUD_C_FILE_HPP #define FUD_C_FILE_HPP #include "fud_status.hpp" #include "fud_result.hpp" #include "fud_string.hpp" #include #include namespace fud { /** \brief Access Modes for */ enum class CFileMode : uint8_t { ReadOnly, ReadWrite, WriteTruncate, ReadWriteTruncate, WriteAppend, ReadWriteAppend, }; constexpr const char* CBinaryFileModeFromFlags(CFileMode mode) { switch (mode) { case CFileMode::ReadOnly: return "rb"; case CFileMode::ReadWrite: return "r+b"; case CFileMode::WriteTruncate: return "wb"; case CFileMode::ReadWriteTruncate: return "w+b"; case CFileMode::WriteAppend: return "ab"; case CFileMode::ReadWriteAppend: return "a+b"; default: return ""; } } constexpr const char* CTextFileModeFromFlags(CFileMode mode) { switch (mode) { case CFileMode::ReadOnly: return "r"; case CFileMode::ReadWrite: return "r+"; case CFileMode::WriteTruncate: return "w"; case CFileMode::ReadWriteTruncate: return "w+"; case CFileMode::WriteAppend: return "a"; case CFileMode::ReadWriteAppend: return "a+"; default: return ""; } } struct [[nodiscard]] ReadResult { size_t bytesRead{0}; FudStatus status{FudStatus::Success}; }; struct [[nodiscard]] WriteResult { size_t bytesWritten{0}; FudStatus status{FudStatus::Success}; }; class CBinaryFile { public: CBinaryFile(const String& filename, CFileMode mode); CBinaryFile(const String& filename, CFileMode mode, const String& extraFlags); CBinaryFile(const CBinaryFile& rhs) = delete; ~CBinaryFile(); CBinaryFile& operator=(const CBinaryFile& rhs) = delete; CBinaryFile& operator=(CBinaryFile&& rhs); FudStatus open(); void close(); const FILE* file() const; [[nodiscard]] FILE* file(); [[nodiscard]] bool isOpen() const; [[nodiscard]] Result size() const; [[nodiscard]] ReadResult read(void* destination, size_t destinationSize, size_t length); [[nodiscard]] ReadResult read(void* destination, size_t destinationSize, size_t length, size_t offset); template [[nodiscard]] ReadResult read(T& destination, size_t length) { return read(destination, length, 0); } template [[nodiscard]] ReadResult read(T& destination, size_t length, size_t offset) { return read(&destination, sizeof(destination), length, offset); } [[nodiscard]] WriteResult write(const void* source, size_t sourceSize, size_t length); [[nodiscard]] WriteResult write(const void* source, size_t sourceSize, size_t length, size_t offset); template [[nodiscard]] WriteResult write(const T& source) { return write(source, sizeof(source), sizeof(source)); } template [[nodiscard]] WriteResult write(const T& source, size_t sourceSize, size_t length) { auto offsetResult = size(); if (offsetResult.isError()) { return WriteResult{0, offsetResult.getError()}; } return write(source, sourceSize, length, offsetResult.getOkay()); } template [[nodiscard]] WriteResult write(const T& source, size_t sourceSize, size_t length, size_t offset) { return write(static_cast(&source), sourceSize, length, offset); } private: FudStatus reset() const; const String m_filename; String m_extraFlags{}; String m_mode; CFileMode m_modeFlags; FILE* m_file{nullptr}; }; } // namespace fud #endif