diff --git a/include/system.hpp b/include/system.hpp index 3f85fc8e..84e957fb 100644 --- a/include/system.hpp +++ b/include/system.hpp @@ -111,18 +111,35 @@ Examples: */ std::string getExtension(const std::string& path); +// File read/write + +/** Reads an entire file into a memory buffer. +Throws on error. +*/ +std::vector readFile(const std::string& path); + +/** Writes a memory buffer to a file, overwriting if already exists. +Throws on error. +*/ +void writeFile(const std::string& path, const std::vector& data); + /** Compresses the contents of a directory (recursively) to an archive. Uses the Unix Standard TAR + Zstandard format (.tar.zst). An equivalent shell command is ZSTD_CLEVEL=1 tar -cf archivePath --zstd -C dirPath . + +Throws on error. */ void archiveDirectory(const std::string& archivePath, const std::string& dirPath, int compressionLevel = 1); std::vector archiveDirectory(const std::string& dirPath, int compressionLevel = 1); + /** Extracts an archive into a directory. An equivalent shell command is tar -xf archivePath --zstd -C dirPath + +Throws on error. */ void unarchiveToDirectory(const std::string& archivePath, const std::string& dirPath); void unarchiveToDirectory(const std::vector& archiveData, const std::string& dirPath); diff --git a/src/system.cpp b/src/system.cpp index 9004048c..a1b53520 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -272,6 +272,38 @@ std::string getExtension(const std::string& path) { } +std::vector readFile(const std::string& path) { + std::vector data; + FILE* f = std::fopen(path.c_str(), "rb"); + if (!f) + throw Exception("Cannot read file %s", path.c_str()); + DEFER({ + std::fclose(f); + }); + + // Get file size so we can make a single allocation + std::fseek(f, 0, SEEK_END); + size_t len = std::ftell(f); + std::fseek(f, 0, SEEK_SET); + + data.resize(len); + std::fread(data.data(), 1, len, f); + return data; +} + + +void writeFile(const std::string& path, const std::vector& data) { + FILE* f = std::fopen(path.c_str(), "wb"); + if (!f) + throw Exception("Cannot create file %s", path.c_str()); + DEFER({ + std::fclose(f); + }); + + std::fwrite(data.data(), 1, data.size(), f); +} + + /** Returns `p` in relative path form, relative to `base` Limitation: `p` must be a descendant of `base`. Doesn't support adding `../` to the return path. */