/* * 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_string.hpp" #include "fud_result.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 ""; } } enum class FileStatus { Success, PartialSuccess, InvalidName, InvalidArgument, InvalidState, NullPointer, Error, }; static inline const char* FileStatusToString(FileStatus status) { switch (status) { case FileStatus::Success: return "Success"; case FileStatus::PartialSuccess: return "PartialSuccess"; case FileStatus::InvalidName: return "InvalidName"; case FileStatus::InvalidArgument: return "InvalidArgument"; case FileStatus::InvalidState: return "InvalidState"; case FileStatus::NullPointer: return "NullPointer"; case FileStatus::Error: return "Error"; default: return "Unknown"; } } struct [[nodiscard]] ReadResult { size_t bytesRead{0}; FileStatus status{FileStatus::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; FileStatus 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); } private: FileStatus reset() const; const String m_filename; String m_extraFlags{}; String m_mode; CFileMode m_modeFlags; FILE* m_file{nullptr}; }; } // namespace fud #endif