77#define TMP_FILE_H
88
99#include <cstddef>
10+ #include <cstdio>
1011#include <filesystem>
1112#include <fstream>
1213#include <ios>
1314#include <istream>
15+ #include <memory>
1416
1517#ifdef __GLIBCXX__
1618#include <ext/stdio_filebuf.h>
1719#endif
1820
1921namespace tmp {
2022
23+ /// Implementation-defined handle type to the file
24+ #if defined(_WIN32)
25+ using file_native_handle = void*; // HANDLE
26+ #elif __has_include(<unistd.h>)
27+ using file_native_handle = int; // POSIX file descriptor
28+ #else
29+ #error "Target platform not supported"
30+ #endif
31+
32+ extern "C++" std::FILE* create_file();
33+ extern "C++" file_native_handle get_native_handle(std::FILE* file) noexcept;
34+
2135/// tmp::file is a smart handle that manages a binary temporary file, ensuring
2236/// its deletion when the handle goes out of scope
2337///
@@ -53,17 +67,27 @@ namespace tmp {
5367class file : public std::iostream {
5468public:
5569 /// Implementation-defined handle type to the file
56- #if defined(_WIN32)
57- using native_handle_type = void*; // HANDLE
58- #elif __has_include(<unistd.h>)
59- using native_handle_type = int; // POSIX file descriptor
60- #else
61- #error "Target platform not supported"
62- #endif
70+ using native_handle_type = file_native_handle;
6371
6472 /// Creates and opens a binary temporary file as if by POSIX `tmpfile`
6573 /// @throws std::filesystem::filesystem_error if cannot create a file
66- explicit file();
74+ explicit file()
75+ : std::iostream(std::addressof(sb)),
76+ underlying(create_file(), &std::fclose) {
77+ #if defined(_MSC_VER)
78+ sb = std::filebuf(underlying.get());
79+ #elif defined(_LIBCPP_VERSION)
80+ sb.__open(fileno(underlying.get()), binary | in | out);
81+ #else
82+ sb = __gnu_cxx::stdio_filebuf<char>(underlying.get(), binary | in | out);
83+ #endif
84+
85+ if (!sb.is_open()) {
86+ std::error_code ec = std::make_error_code(std::io_errc::stream);
87+ throw std::filesystem::filesystem_error("Cannot create a temporary file",
88+ ec);
89+ }
90+ }
6791
6892 file(const file&) = delete;
6993 file& operator=(const file&) = delete;
@@ -87,7 +111,9 @@ public:
87111
88112 /// Returns an implementation-defined handle to this file
89113 /// @returns The underlying implementation-defined handle
90- native_handle_type native_handle() const noexcept;
114+ native_handle_type native_handle() const noexcept {
115+ return get_native_handle(underlying.get());
116+ }
91117
92118 /// Closes and deletes this file
93119 ~file() noexcept override = default;
0 commit comments