os.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
  2. // Formatting library for C++ - optional OS-specific functionality
  3. //
  4. // Copyright (c) 2012 - present, Victor Zverovich
  5. // All rights reserved.
  6. //
  7. // For the license information refer to format.h.
  8. #ifndef FMT_OS_H_
  9. #define FMT_OS_H_
  10. #include "format.h"
  11. #ifndef FMT_MODULE
  12. # include <cerrno>
  13. # include <cstddef>
  14. # include <cstdio>
  15. # include <system_error> // std::system_error
  16. # if FMT_HAS_INCLUDE(<xlocale.h>)
  17. # include <xlocale.h> // LC_NUMERIC_MASK on macOS
  18. # endif
  19. #endif // FMT_MODULE
  20. #ifndef FMT_USE_FCNTL
  21. // UWP doesn't provide _pipe.
  22. # if FMT_HAS_INCLUDE("winapifamily.h")
  23. # include <winapifamily.h>
  24. # endif
  25. # if (FMT_HAS_INCLUDE(<fcntl.h>) || defined(__APPLE__) || \
  26. defined(__linux__)) && \
  27. (!defined(WINAPI_FAMILY) || \
  28. (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)) && \
  29. !defined(__wasm__)
  30. # include <fcntl.h> // for O_RDONLY
  31. # define FMT_USE_FCNTL 1
  32. # else
  33. # define FMT_USE_FCNTL 0
  34. # endif
  35. #endif
  36. #ifndef FMT_POSIX
  37. # if defined(_WIN32) && !defined(__MINGW32__)
  38. // Fix warnings about deprecated symbols.
  39. # define FMT_POSIX(call) _##call
  40. # else
  41. # define FMT_POSIX(call) call
  42. # endif
  43. #endif
  44. // Calls to system functions are wrapped in FMT_SYSTEM for testability.
  45. #ifdef FMT_SYSTEM
  46. # define FMT_HAS_SYSTEM
  47. # define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
  48. #else
  49. # define FMT_SYSTEM(call) ::call
  50. # ifdef _WIN32
  51. // Fix warnings about deprecated symbols.
  52. # define FMT_POSIX_CALL(call) ::_##call
  53. # else
  54. # define FMT_POSIX_CALL(call) ::call
  55. # endif
  56. #endif
  57. // Retries the expression while it evaluates to error_result and errno
  58. // equals to EINTR.
  59. #ifndef _WIN32
  60. # define FMT_RETRY_VAL(result, expression, error_result) \
  61. do { \
  62. (result) = (expression); \
  63. } while ((result) == (error_result) && errno == EINTR)
  64. #else
  65. # define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
  66. #endif
  67. #define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
  68. FMT_BEGIN_NAMESPACE
  69. FMT_BEGIN_EXPORT
  70. /**
  71. * A reference to a null-terminated string. It can be constructed from a C
  72. * string or `std::string`.
  73. *
  74. * You can use one of the following type aliases for common character types:
  75. *
  76. * +---------------+-----------------------------+
  77. * | Type | Definition |
  78. * +===============+=============================+
  79. * | cstring_view | basic_cstring_view<char> |
  80. * +---------------+-----------------------------+
  81. * | wcstring_view | basic_cstring_view<wchar_t> |
  82. * +---------------+-----------------------------+
  83. *
  84. * This class is most useful as a parameter type for functions that wrap C APIs.
  85. */
  86. template <typename Char> class basic_cstring_view {
  87. private:
  88. const Char* data_;
  89. public:
  90. /// Constructs a string reference object from a C string.
  91. basic_cstring_view(const Char* s) : data_(s) {}
  92. /// Constructs a string reference from an `std::string` object.
  93. basic_cstring_view(const std::basic_string<Char>& s) : data_(s.c_str()) {}
  94. /// Returns the pointer to a C string.
  95. auto c_str() const -> const Char* { return data_; }
  96. };
  97. using cstring_view = basic_cstring_view<char>;
  98. using wcstring_view = basic_cstring_view<wchar_t>;
  99. #ifdef _WIN32
  100. FMT_API const std::error_category& system_category() noexcept;
  101. namespace detail {
  102. FMT_API void format_windows_error(buffer<char>& out, int error_code,
  103. const char* message) noexcept;
  104. }
  105. FMT_API std::system_error vwindows_error(int error_code, string_view fmt,
  106. format_args args);
  107. /**
  108. * Constructs a `std::system_error` object with the description of the form
  109. *
  110. * <message>: <system-message>
  111. *
  112. * where `<message>` is the formatted message and `<system-message>` is the
  113. * system message corresponding to the error code.
  114. * `error_code` is a Windows error code as given by `GetLastError`.
  115. * If `error_code` is not a valid error code such as -1, the system message
  116. * will look like "error -1".
  117. *
  118. * **Example**:
  119. *
  120. * // This throws a system_error with the description
  121. * // cannot open file 'foo': The system cannot find the file specified.
  122. * // or similar (system message may vary) if the file doesn't exist.
  123. * const char *filename = "foo";
  124. * LPOFSTRUCT of = LPOFSTRUCT();
  125. * HFILE file = OpenFile(filename, &of, OF_READ);
  126. * if (file == HFILE_ERROR) {
  127. * throw fmt::windows_error(GetLastError(),
  128. * "cannot open file '{}'", filename);
  129. * }
  130. */
  131. template <typename... T>
  132. auto windows_error(int error_code, string_view message, const T&... args)
  133. -> std::system_error {
  134. return vwindows_error(error_code, message, vargs<T...>{{args...}});
  135. }
  136. // Reports a Windows error without throwing an exception.
  137. // Can be used to report errors from destructors.
  138. FMT_API void report_windows_error(int error_code, const char* message) noexcept;
  139. #else
  140. inline auto system_category() noexcept -> const std::error_category& {
  141. return std::system_category();
  142. }
  143. #endif // _WIN32
  144. // std::system is not available on some platforms such as iOS (#2248).
  145. #ifdef __OSX__
  146. template <typename S, typename... Args, typename Char = char_t<S>>
  147. void say(const S& fmt, Args&&... args) {
  148. std::system(format("say \"{}\"", format(fmt, args...)).c_str());
  149. }
  150. #endif
  151. // A buffered file.
  152. class buffered_file {
  153. private:
  154. FILE* file_;
  155. friend class file;
  156. inline explicit buffered_file(FILE* f) : file_(f) {}
  157. public:
  158. buffered_file(const buffered_file&) = delete;
  159. void operator=(const buffered_file&) = delete;
  160. // Constructs a buffered_file object which doesn't represent any file.
  161. inline buffered_file() noexcept : file_(nullptr) {}
  162. // Destroys the object closing the file it represents if any.
  163. FMT_API ~buffered_file() noexcept;
  164. public:
  165. inline buffered_file(buffered_file&& other) noexcept : file_(other.file_) {
  166. other.file_ = nullptr;
  167. }
  168. inline auto operator=(buffered_file&& other) -> buffered_file& {
  169. close();
  170. file_ = other.file_;
  171. other.file_ = nullptr;
  172. return *this;
  173. }
  174. // Opens a file.
  175. FMT_API buffered_file(cstring_view filename, cstring_view mode);
  176. // Closes the file.
  177. FMT_API void close();
  178. // Returns the pointer to a FILE object representing this file.
  179. inline auto get() const noexcept -> FILE* { return file_; }
  180. FMT_API auto descriptor() const -> int;
  181. template <typename... T>
  182. inline void print(string_view fmt, const T&... args) {
  183. fmt::vargs<T...> vargs = {{args...}};
  184. detail::is_locking<T...>() ? fmt::vprint_buffered(file_, fmt, vargs)
  185. : fmt::vprint(file_, fmt, vargs);
  186. }
  187. };
  188. #if FMT_USE_FCNTL
  189. // A file. Closed file is represented by a file object with descriptor -1.
  190. // Methods that are not declared with noexcept may throw
  191. // fmt::system_error in case of failure. Note that some errors such as
  192. // closing the file multiple times will cause a crash on Windows rather
  193. // than an exception. You can get standard behavior by overriding the
  194. // invalid parameter handler with _set_invalid_parameter_handler.
  195. class FMT_API file {
  196. private:
  197. int fd_; // File descriptor.
  198. // Constructs a file object with a given descriptor.
  199. explicit file(int fd) : fd_(fd) {}
  200. friend struct pipe;
  201. public:
  202. // Possible values for the oflag argument to the constructor.
  203. enum {
  204. RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
  205. WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
  206. RDWR = FMT_POSIX(O_RDWR), // Open for reading and writing.
  207. CREATE = FMT_POSIX(O_CREAT), // Create if the file doesn't exist.
  208. APPEND = FMT_POSIX(O_APPEND), // Open in append mode.
  209. TRUNC = FMT_POSIX(O_TRUNC) // Truncate the content of the file.
  210. };
  211. // Constructs a file object which doesn't represent any file.
  212. inline file() noexcept : fd_(-1) {}
  213. // Opens a file and constructs a file object representing this file.
  214. file(cstring_view path, int oflag);
  215. public:
  216. file(const file&) = delete;
  217. void operator=(const file&) = delete;
  218. inline file(file&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; }
  219. // Move assignment is not noexcept because close may throw.
  220. inline auto operator=(file&& other) -> file& {
  221. close();
  222. fd_ = other.fd_;
  223. other.fd_ = -1;
  224. return *this;
  225. }
  226. // Destroys the object closing the file it represents if any.
  227. ~file() noexcept;
  228. // Returns the file descriptor.
  229. inline auto descriptor() const noexcept -> int { return fd_; }
  230. // Closes the file.
  231. void close();
  232. // Returns the file size. The size has signed type for consistency with
  233. // stat::st_size.
  234. auto size() const -> long long;
  235. // Attempts to read count bytes from the file into the specified buffer.
  236. auto read(void* buffer, size_t count) -> size_t;
  237. // Attempts to write count bytes from the specified buffer to the file.
  238. auto write(const void* buffer, size_t count) -> size_t;
  239. // Duplicates a file descriptor with the dup function and returns
  240. // the duplicate as a file object.
  241. static auto dup(int fd) -> file;
  242. // Makes fd be the copy of this file descriptor, closing fd first if
  243. // necessary.
  244. void dup2(int fd);
  245. // Makes fd be the copy of this file descriptor, closing fd first if
  246. // necessary.
  247. void dup2(int fd, std::error_code& ec) noexcept;
  248. // Creates a buffered_file object associated with this file and detaches
  249. // this file object from the file.
  250. auto fdopen(const char* mode) -> buffered_file;
  251. # if defined(_WIN32) && !defined(__MINGW32__)
  252. // Opens a file and constructs a file object representing this file by
  253. // wcstring_view filename. Windows only.
  254. static file open_windows_file(wcstring_view path, int oflag);
  255. # endif
  256. };
  257. struct FMT_API pipe {
  258. file read_end;
  259. file write_end;
  260. // Creates a pipe setting up read_end and write_end file objects for reading
  261. // and writing respectively.
  262. pipe();
  263. };
  264. // Returns the memory page size.
  265. auto getpagesize() -> long;
  266. namespace detail {
  267. struct buffer_size {
  268. constexpr buffer_size() = default;
  269. size_t value = 0;
  270. FMT_CONSTEXPR auto operator=(size_t val) const -> buffer_size {
  271. auto bs = buffer_size();
  272. bs.value = val;
  273. return bs;
  274. }
  275. };
  276. struct ostream_params {
  277. int oflag = file::WRONLY | file::CREATE | file::TRUNC;
  278. size_t buffer_size = BUFSIZ > 32768 ? BUFSIZ : 32768;
  279. constexpr ostream_params() {}
  280. template <typename... T>
  281. ostream_params(T... params, int new_oflag) : ostream_params(params...) {
  282. oflag = new_oflag;
  283. }
  284. template <typename... T>
  285. ostream_params(T... params, detail::buffer_size bs)
  286. : ostream_params(params...) {
  287. this->buffer_size = bs.value;
  288. }
  289. // Intel has a bug that results in failure to deduce a constructor
  290. // for empty parameter packs.
  291. # if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 2000
  292. ostream_params(int new_oflag) : oflag(new_oflag) {}
  293. ostream_params(detail::buffer_size bs) : buffer_size(bs.value) {}
  294. # endif
  295. };
  296. } // namespace detail
  297. FMT_INLINE_VARIABLE constexpr auto buffer_size = detail::buffer_size();
  298. /// A fast buffered output stream for writing from a single thread. Writing from
  299. /// multiple threads without external synchronization may result in a data race.
  300. class ostream : private detail::buffer<char> {
  301. private:
  302. file file_;
  303. FMT_API ostream(cstring_view path, const detail::ostream_params& params);
  304. FMT_API static void grow(buffer<char>& buf, size_t);
  305. public:
  306. FMT_API ostream(ostream&& other) noexcept;
  307. FMT_API ~ostream();
  308. operator writer() {
  309. detail::buffer<char>& buf = *this;
  310. return buf;
  311. }
  312. inline void flush() {
  313. if (size() == 0) return;
  314. file_.write(data(), size() * sizeof(data()[0]));
  315. clear();
  316. }
  317. template <typename... T>
  318. friend auto output_file(cstring_view path, T... params) -> ostream;
  319. inline void close() {
  320. flush();
  321. file_.close();
  322. }
  323. /// Formats `args` according to specifications in `fmt` and writes the
  324. /// output to the file.
  325. template <typename... T> void print(format_string<T...> fmt, T&&... args) {
  326. vformat_to(appender(*this), fmt.str, vargs<T...>{{args...}});
  327. }
  328. };
  329. /**
  330. * Opens a file for writing. Supported parameters passed in `params`:
  331. *
  332. * - `<integer>`: Flags passed to [open](
  333. * https://pubs.opengroup.org/onlinepubs/007904875/functions/open.html)
  334. * (`file::WRONLY | file::CREATE | file::TRUNC` by default)
  335. * - `buffer_size=<integer>`: Output buffer size
  336. *
  337. * **Example**:
  338. *
  339. * auto out = fmt::output_file("guide.txt");
  340. * out.print("Don't {}", "Panic");
  341. */
  342. template <typename... T>
  343. inline auto output_file(cstring_view path, T... params) -> ostream {
  344. return {path, detail::ostream_params(params...)};
  345. }
  346. #endif // FMT_USE_FCNTL
  347. FMT_END_EXPORT
  348. FMT_END_NAMESPACE
  349. #endif // FMT_OS_H_
  350. #else
  351. #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
  352. #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)