/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #pragma once #include #include #include namespace OpenVulkano { class CFile { static constexpr std::array MODE_STRINGS = { "r", "rb", "w", "wb", "a", "ab", "r+", "rb+", "w+", "wb+", "a+", "ab+" }; static constexpr std::array MODE_STRINGS_W = { L"r", L"rb", L"w", L"wb", L"a", L"ab", L"r+", L"rb+", L"w+", L"wb+", L"a+", L"ab+" }; public: enum Mode { READ = 0, READ_BINARY, WRITE, WRITE_BINARY, APPEND, APPEND_BINARY, READ_WRITE, // Null if file does not exist READ_WRITE_BINARY, // Null if file does not exist WRITE_READ, // Creates file if not exists WRITE_READ_BINARY, // Creates file if not exists APPEND_READ, APPEND_READ_BINARY, }; FILE* f = nullptr; CFile() = default; CFile(const std::filesystem::path& path, const Mode mode) : CFile(path.c_str(), mode) {} template CFile(const T* path, Mode mode) requires std::is_same_v || std::is_same_v : f(FOpen(path, mode)) {} CFile(const CFile&) = delete; CFile& operator=(const CFile&) = delete; CFile(CFile&& other) noexcept : f(other.f) { other.f = nullptr; } CFile& operator=(CFile&& other) noexcept { Close(); f = other.f; other.f = nullptr; return *this; } ~CFile() { Close(); } void Close() { if (f) { fclose(f); f = nullptr; } } void Open(const std::filesystem::path& path, const Mode mode) { Close(); // Close current f = FOpen(path.c_str(), mode); } template void Open(const T* path, const Mode mode) requires std::is_same_v || std::is_same_v { f = FOpen(path, mode); } size_t Read(void* data, const size_t elementSize, const size_t elementCount = 1) const { return fread(data, elementSize, elementCount, f); } size_t Write(const void* data, const size_t elementSize, const size_t elementCount = 1) const { return fwrite(data, elementSize, elementCount, f); } int Put(const char c) const { return fputc(c, f); } void Seek(const long position, const int mode = SEEK_SET) const { fseek(f, position, mode); } [[nodiscard]] long Tell() const { return ftell(f); } FILE* FilePtr() const { return f; } [[nodiscard]] operator bool() const noexcept { return f != nullptr; } [[nodiscard]] operator FILE*() const noexcept { return f; } // Helper function, might be used outside off class template [[nodiscard]] static FILE* FOpen(const T* path, const Mode mode) requires std::is_same_v || std::is_same_v { if constexpr (std::is_same_v) return fopen(path, MODE_STRINGS[mode]); else return _wfopen(path, MODE_STRINGS_W[mode]); } }; }