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