util/file.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // SPDX-License-Identifier: BSD-3-Clause | ||
| 2 | /// @file file.h | ||
| 3 | /// @brief Files on disk: whole-file reads, lookups by name, and read-only memory mapping. | ||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "ernie/export.h" | ||
| 7 | |||
| 8 | #include <cstddef> | ||
| 9 | #include <filesystem> | ||
| 10 | #include <span> | ||
| 11 | #include <string> | ||
| 12 | #include <string_view> | ||
| 13 | |||
| 14 | namespace ernie { | ||
| 15 | |||
| 16 | /// @brief Reads a whole file as text. | ||
| 17 | /// @param path The file. | ||
| 18 | /// @return Its bytes. | ||
| 19 | /// @throws std::runtime_error If it cannot be read. | ||
| 20 | ERNIE_API std::string ReadTextFile(const std::filesystem::path& path); | ||
| 21 | |||
| 22 | /// @brief Writes text to a file, replacing it, and makes the directories it goes in. | ||
| 23 | /// @throws std::runtime_error If it cannot be written. | ||
| 24 | ERNIE_API void WriteTextFile(const std::filesystem::path& path, std::string_view text); | ||
| 25 | |||
| 26 | /// @brief Writes bytes to a file, replacing it, and makes the directories it goes in. | ||
| 27 | /// @throws std::runtime_error If it cannot be written. | ||
| 28 | ERNIE_API void WriteBinaryFile(const std::filesystem::path& path, std::span<const std::byte> bytes); | ||
| 29 | |||
| 30 | /// @brief Finds a file by name in any case, as archives named in capitals often unpack in small | ||
| 31 | /// letters. | ||
| 32 | /// @param directory The directory to look in. | ||
| 33 | /// @param name The file's name. | ||
| 34 | /// @return The file with that name, exactly if there is one, else in any case; `directory / name` | ||
| 35 | /// if there is neither. | ||
| 36 | ERNIE_API std::filesystem::path FindFileAnyCase(const std::filesystem::path& directory, | ||
| 37 | const std::string& name); | ||
| 38 | |||
| 39 | /// @brief A file mapped read-only into memory. | ||
| 40 | /// Pages load on first touch, so files larger than memory can be read in parts. The file may be | ||
| 41 | /// deleted or replaced while mapped, on every platform; the view stays valid until destroyed. | ||
| 42 | class ERNIE_API MappedFile { | ||
| 43 | public: | ||
| 44 | /// @brief Maps a file. | ||
| 45 | /// @param path The file to map. | ||
| 46 | /// @throws std::runtime_error If it cannot be opened or mapped. | ||
| 47 | explicit MappedFile(const std::filesystem::path& path); | ||
| 48 | ~MappedFile(); | ||
| 49 | MappedFile(const MappedFile&) = delete; | ||
| 50 | MappedFile& operator=(const MappedFile&) = delete; | ||
| 51 | |||
| 52 | /// @return The file's bytes; empty for an empty file. | ||
| 53 | 331 | std::span<const std::byte> Bytes() const { | |
| 54 | 331 | return {static_cast<const std::byte*>(data_), size_}; | |
| 55 | } | ||
| 56 | |||
| 57 | private: | ||
| 58 | void* data_ = nullptr; | ||
| 59 | std::size_t size_ = 0; | ||
| 60 | #ifdef _WIN32 | ||
| 61 | void* file_ = nullptr; | ||
| 62 | void* mapping_ = nullptr; | ||
| 63 | #endif | ||
| 64 | }; | ||
| 65 | |||
| 66 | } // namespace ernie | ||
| 67 |