diff --git a/include/tmp/file b/include/tmp/file index b5839e2..986235f 100644 --- a/include/tmp/file +++ b/include/tmp/file @@ -72,6 +72,17 @@ public: std::string_view label = "", std::string_view extension = ""); + /// Returns the size of this file + /// @returns the size of this file, in bytes + /// @throws std::filesystem::filesystem_error if cannot get a file size + std::uintmax_t size() const; + + /// Returns the size of this file + /// @param[out] ec Parameter for error reporting + /// @returns the size of this file, in bytes + /// @throws std::filesystem::filesystem_error if cannot get a file size + std::uintmax_t size(std::error_code& ec) const; + /// Reads the entire contents of this file /// @returns A string with this file contents /// @throws std::filesystem::filesystem_error if cannot read the file contents diff --git a/src/file.cpp b/src/file.cpp index d67bc4c..7ab3d17 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -19,6 +19,7 @@ #include #else #include +#include #include #endif @@ -131,6 +132,37 @@ file file::copy(const fs::path& path, std::string_view label, return tmpfile; } +std::uintmax_t file::size() const { + std::error_code ec; + std::uintmax_t result = size(ec); + + if (ec) { + throw fs::filesystem_error("Cannot get a temporary file size", path(), ec); + } + + return result; +} + +std::uintmax_t file::size(std::error_code& ec) const { +#ifdef _WIN32 + LARGE_INTERGER size; + if (!GetFileSize(native_handle(), &size)) { + ec = std::error_code(GetLastError(), std::system_category()); + return static_cast(-1); + } + + return size; +#else + struct stat stat; + if (fstat(native_handle(), &stat) == -1) { + ec = std::error_code(errno, std::system_category()); + return static_cast(-1); + } + + return stat.st_size; +#endif +} + std::string file::read() const { std::error_code ec; std::string content = read(ec); diff --git a/tests/file.cpp b/tests/file.cpp index dc1de7d..211d863 100644 --- a/tests/file.cpp +++ b/tests/file.cpp @@ -110,6 +110,18 @@ TEST(file, copy_directory) { EXPECT_THROW(file::copy(tmpdir), fs::filesystem_error); } +/// Tests getting a file size +TEST(file, size) { + file empty = file(); + EXPECT_EQ(empty.size(), 0); + + std::string_view content = "Hello, world!"; + + file nonempty = file(); + nonempty.write(content); + EXPECT_EQ(nonempty.size(), content.size()); +} + /// Tests binary file reading TEST(file, read_binary) { file tmpfile = file();