Add vendor/fmt
[lttng-tools.git] / src / vendor / fmt / os.h
CommitLineData
05aa7e19
JG
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 <cerrno>
12#include <clocale> // locale_t
13#include <cstddef>
14#include <cstdio>
15#include <cstdlib> // strtod_l
16#include <system_error> // std::system_error
17
18#if defined __APPLE__ || defined(__FreeBSD__)
19# include <xlocale.h> // for LC_NUMERIC_MASK on OS X
20#endif
21
22#include "format.h"
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# include <fcntl.h> // for O_RDONLY
34# define FMT_USE_FCNTL 1
35# else
36# define FMT_USE_FCNTL 0
37# endif
38#endif
39
40#ifndef FMT_POSIX
41# if defined(_WIN32) && !defined(__MINGW32__)
42// Fix warnings about deprecated symbols.
43# define FMT_POSIX(call) _##call
44# else
45# define FMT_POSIX(call) call
46# endif
47#endif
48
49// Calls to system functions are wrapped in FMT_SYSTEM for testability.
50#ifdef FMT_SYSTEM
51# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
52#else
53# define FMT_SYSTEM(call) ::call
54# ifdef _WIN32
55// Fix warnings about deprecated symbols.
56# define FMT_POSIX_CALL(call) ::_##call
57# else
58# define FMT_POSIX_CALL(call) ::call
59# endif
60#endif
61
62// Retries the expression while it evaluates to error_result and errno
63// equals to EINTR.
64#ifndef _WIN32
65# define FMT_RETRY_VAL(result, expression, error_result) \
66 do { \
67 (result) = (expression); \
68 } while ((result) == (error_result) && errno == EINTR)
69#else
70# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
71#endif
72
73#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
74
75FMT_BEGIN_NAMESPACE
76FMT_MODULE_EXPORT_BEGIN
77
78/**
79 \rst
80 A reference to a null-terminated string. It can be constructed from a C
81 string or ``std::string``.
82
83 You can use one of the following type aliases for common character types:
84
85 +---------------+-----------------------------+
86 | Type | Definition |
87 +===============+=============================+
88 | cstring_view | basic_cstring_view<char> |
89 +---------------+-----------------------------+
90 | wcstring_view | basic_cstring_view<wchar_t> |
91 +---------------+-----------------------------+
92
93 This class is most useful as a parameter type to allow passing
94 different types of strings to a function, for example::
95
96 template <typename... Args>
97 std::string format(cstring_view format_str, const Args & ... args);
98
99 format("{}", 42);
100 format(std::string("{}"), 42);
101 \endrst
102 */
103template <typename Char> class basic_cstring_view {
104 private:
105 const Char* data_;
106
107 public:
108 /** Constructs a string reference object from a C string. */
109 basic_cstring_view(const Char* s) : data_(s) {}
110
111 /**
112 \rst
113 Constructs a string reference from an ``std::string`` object.
114 \endrst
115 */
116 basic_cstring_view(const std::basic_string<Char>& s) : data_(s.c_str()) {}
117
118 /** Returns the pointer to a C string. */
119 const Char* c_str() const { return data_; }
120};
121
122using cstring_view = basic_cstring_view<char>;
123using wcstring_view = basic_cstring_view<wchar_t>;
124
125template <typename Char> struct formatter<std::error_code, Char> {
126 template <typename ParseContext>
127 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
128 return ctx.begin();
129 }
130
131 template <typename FormatContext>
132 FMT_CONSTEXPR auto format(const std::error_code& ec, FormatContext& ctx) const
133 -> decltype(ctx.out()) {
134 auto out = ctx.out();
135 out = detail::write_bytes(out, ec.category().name(),
136 basic_format_specs<Char>());
137 out = detail::write<Char>(out, Char(':'));
138 out = detail::write<Char>(out, ec.value());
139 return out;
140 }
141};
142
143#ifdef _WIN32
144FMT_API const std::error_category& system_category() FMT_NOEXCEPT;
145
146FMT_BEGIN_DETAIL_NAMESPACE
147// A converter from UTF-16 to UTF-8.
148// It is only provided for Windows since other systems support UTF-8 natively.
149class utf16_to_utf8 {
150 private:
151 memory_buffer buffer_;
152
153 public:
154 utf16_to_utf8() {}
155 FMT_API explicit utf16_to_utf8(basic_string_view<wchar_t> s);
156 operator string_view() const { return string_view(&buffer_[0], size()); }
157 size_t size() const { return buffer_.size() - 1; }
158 const char* c_str() const { return &buffer_[0]; }
159 std::string str() const { return std::string(&buffer_[0], size()); }
160
161 // Performs conversion returning a system error code instead of
162 // throwing exception on conversion error. This method may still throw
163 // in case of memory allocation error.
164 FMT_API int convert(basic_string_view<wchar_t> s);
165};
166
167FMT_API void format_windows_error(buffer<char>& out, int error_code,
168 const char* message) FMT_NOEXCEPT;
169FMT_END_DETAIL_NAMESPACE
170
171FMT_API std::system_error vwindows_error(int error_code, string_view format_str,
172 format_args args);
173
174/**
175 \rst
176 Constructs a :class:`std::system_error` object with the description
177 of the form
178
179 .. parsed-literal::
180 *<message>*: *<system-message>*
181
182 where *<message>* is the formatted message and *<system-message>* is the
183 system message corresponding to the error code.
184 *error_code* is a Windows error code as given by ``GetLastError``.
185 If *error_code* is not a valid error code such as -1, the system message
186 will look like "error -1".
187
188 **Example**::
189
190 // This throws a system_error with the description
191 // cannot open file 'madeup': The system cannot find the file specified.
192 // or similar (system message may vary).
193 const char *filename = "madeup";
194 LPOFSTRUCT of = LPOFSTRUCT();
195 HFILE file = OpenFile(filename, &of, OF_READ);
196 if (file == HFILE_ERROR) {
197 throw fmt::windows_error(GetLastError(),
198 "cannot open file '{}'", filename);
199 }
200 \endrst
201*/
202template <typename... Args>
203std::system_error windows_error(int error_code, string_view message,
204 const Args&... args) {
205 return vwindows_error(error_code, message, fmt::make_format_args(args...));
206}
207
208// Reports a Windows error without throwing an exception.
209// Can be used to report errors from destructors.
210FMT_API void report_windows_error(int error_code,
211 const char* message) FMT_NOEXCEPT;
212#else
213inline const std::error_category& system_category() FMT_NOEXCEPT {
214 return std::system_category();
215}
216#endif // _WIN32
217
218// std::system is not available on some platforms such as iOS (#2248).
219#ifdef __OSX__
220template <typename S, typename... Args, typename Char = char_t<S>>
221void say(const S& format_str, Args&&... args) {
222 std::system(format("say \"{}\"", format(format_str, args...)).c_str());
223}
224#endif
225
226// A buffered file.
227class buffered_file {
228 private:
229 FILE* file_;
230
231 friend class file;
232
233 explicit buffered_file(FILE* f) : file_(f) {}
234
235 public:
236 buffered_file(const buffered_file&) = delete;
237 void operator=(const buffered_file&) = delete;
238
239 // Constructs a buffered_file object which doesn't represent any file.
240 buffered_file() FMT_NOEXCEPT : file_(nullptr) {}
241
242 // Destroys the object closing the file it represents if any.
243 FMT_API ~buffered_file() FMT_NOEXCEPT;
244
245 public:
246 buffered_file(buffered_file&& other) FMT_NOEXCEPT : file_(other.file_) {
247 other.file_ = nullptr;
248 }
249
250 buffered_file& operator=(buffered_file&& other) {
251 close();
252 file_ = other.file_;
253 other.file_ = nullptr;
254 return *this;
255 }
256
257 // Opens a file.
258 FMT_API buffered_file(cstring_view filename, cstring_view mode);
259
260 // Closes the file.
261 FMT_API void close();
262
263 // Returns the pointer to a FILE object representing this file.
264 FILE* get() const FMT_NOEXCEPT { return file_; }
265
266 // We place parentheses around fileno to workaround a bug in some versions
267 // of MinGW that define fileno as a macro.
268 FMT_API int(fileno)() const;
269
270 void vprint(string_view format_str, format_args args) {
271 fmt::vprint(file_, format_str, args);
272 }
273
274 template <typename... Args>
275 inline void print(string_view format_str, const Args&... args) {
276 vprint(format_str, fmt::make_format_args(args...));
277 }
278};
279
280#if FMT_USE_FCNTL
281// A file. Closed file is represented by a file object with descriptor -1.
282// Methods that are not declared with FMT_NOEXCEPT may throw
283// fmt::system_error in case of failure. Note that some errors such as
284// closing the file multiple times will cause a crash on Windows rather
285// than an exception. You can get standard behavior by overriding the
286// invalid parameter handler with _set_invalid_parameter_handler.
287class file {
288 private:
289 int fd_; // File descriptor.
290
291 // Constructs a file object with a given descriptor.
292 explicit file(int fd) : fd_(fd) {}
293
294 public:
295 // Possible values for the oflag argument to the constructor.
296 enum {
297 RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
298 WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
299 RDWR = FMT_POSIX(O_RDWR), // Open for reading and writing.
300 CREATE = FMT_POSIX(O_CREAT), // Create if the file doesn't exist.
301 APPEND = FMT_POSIX(O_APPEND), // Open in append mode.
302 TRUNC = FMT_POSIX(O_TRUNC) // Truncate the content of the file.
303 };
304
305 // Constructs a file object which doesn't represent any file.
306 file() FMT_NOEXCEPT : fd_(-1) {}
307
308 // Opens a file and constructs a file object representing this file.
309 FMT_API file(cstring_view path, int oflag);
310
311 public:
312 file(const file&) = delete;
313 void operator=(const file&) = delete;
314
315 file(file&& other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; }
316
317 // Move assignment is not noexcept because close may throw.
318 file& operator=(file&& other) {
319 close();
320 fd_ = other.fd_;
321 other.fd_ = -1;
322 return *this;
323 }
324
325 // Destroys the object closing the file it represents if any.
326 FMT_API ~file() FMT_NOEXCEPT;
327
328 // Returns the file descriptor.
329 int descriptor() const FMT_NOEXCEPT { return fd_; }
330
331 // Closes the file.
332 FMT_API void close();
333
334 // Returns the file size. The size has signed type for consistency with
335 // stat::st_size.
336 FMT_API long long size() const;
337
338 // Attempts to read count bytes from the file into the specified buffer.
339 FMT_API size_t read(void* buffer, size_t count);
340
341 // Attempts to write count bytes from the specified buffer to the file.
342 FMT_API size_t write(const void* buffer, size_t count);
343
344 // Duplicates a file descriptor with the dup function and returns
345 // the duplicate as a file object.
346 FMT_API static file dup(int fd);
347
348 // Makes fd be the copy of this file descriptor, closing fd first if
349 // necessary.
350 FMT_API void dup2(int fd);
351
352 // Makes fd be the copy of this file descriptor, closing fd first if
353 // necessary.
354 FMT_API void dup2(int fd, std::error_code& ec) FMT_NOEXCEPT;
355
356 // Creates a pipe setting up read_end and write_end file objects for reading
357 // and writing respectively.
358 FMT_API static void pipe(file& read_end, file& write_end);
359
360 // Creates a buffered_file object associated with this file and detaches
361 // this file object from the file.
362 FMT_API buffered_file fdopen(const char* mode);
363};
364
365// Returns the memory page size.
366long getpagesize();
367
368FMT_BEGIN_DETAIL_NAMESPACE
369
370struct buffer_size {
371 buffer_size() = default;
372 size_t value = 0;
373 buffer_size operator=(size_t val) const {
374 auto bs = buffer_size();
375 bs.value = val;
376 return bs;
377 }
378};
379
380struct ostream_params {
381 int oflag = file::WRONLY | file::CREATE | file::TRUNC;
382 size_t buffer_size = BUFSIZ > 32768 ? BUFSIZ : 32768;
383
384 ostream_params() {}
385
386 template <typename... T>
387 ostream_params(T... params, int new_oflag) : ostream_params(params...) {
388 oflag = new_oflag;
389 }
390
391 template <typename... T>
392 ostream_params(T... params, detail::buffer_size bs)
393 : ostream_params(params...) {
394 this->buffer_size = bs.value;
395 }
396
397// Intel has a bug that results in failure to deduce a constructor
398// for empty parameter packs.
399# if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 2000
400 ostream_params(int new_oflag) : oflag(new_oflag) {}
401 ostream_params(detail::buffer_size bs) : buffer_size(bs.value) {}
402# endif
403};
404
405FMT_END_DETAIL_NAMESPACE
406
407// Added {} below to work around default constructor error known to
408// occur in Xcode versions 7.2.1 and 8.2.1.
409constexpr detail::buffer_size buffer_size{};
410
411/** A fast output stream which is not thread-safe. */
412class FMT_API ostream final : private detail::buffer<char> {
413 private:
414 file file_;
415
416 void grow(size_t) override;
417
418 ostream(cstring_view path, const detail::ostream_params& params)
419 : file_(path, params.oflag) {
420 set(new char[params.buffer_size], params.buffer_size);
421 }
422
423 public:
424 ostream(ostream&& other)
425 : detail::buffer<char>(other.data(), other.size(), other.capacity()),
426 file_(std::move(other.file_)) {
427 other.clear();
428 other.set(nullptr, 0);
429 }
430 ~ostream() {
431 flush();
432 delete[] data();
433 }
434
435 void flush() {
436 if (size() == 0) return;
437 file_.write(data(), size());
438 clear();
439 }
440
441 template <typename... T>
442 friend ostream output_file(cstring_view path, T... params);
443
444 void close() {
445 flush();
446 file_.close();
447 }
448
449 /**
450 Formats ``args`` according to specifications in ``fmt`` and writes the
451 output to the file.
452 */
453 template <typename... T> void print(format_string<T...> fmt, T&&... args) {
454 vformat_to(detail::buffer_appender<char>(*this), fmt,
455 fmt::make_format_args(args...));
456 }
457};
458
459/**
460 \rst
461 Opens a file for writing. Supported parameters passed in *params*:
462
463 * ``<integer>``: Flags passed to `open
464 <https://pubs.opengroup.org/onlinepubs/007904875/functions/open.html>`_
465 (``file::WRONLY | file::CREATE`` by default)
466 * ``buffer_size=<integer>``: Output buffer size
467
468 **Example**::
469
470 auto out = fmt::output_file("guide.txt");
471 out.print("Don't {}", "Panic");
472 \endrst
473 */
474template <typename... T>
475inline ostream output_file(cstring_view path, T... params) {
476 return {path, detail::ostream_params(params...)};
477}
478#endif // FMT_USE_FCNTL
479
480#ifdef FMT_LOCALE
481// A "C" numeric locale.
482class locale {
483 private:
484# ifdef _WIN32
485 using locale_t = _locale_t;
486
487 static void freelocale(locale_t loc) { _free_locale(loc); }
488
489 static double strtod_l(const char* nptr, char** endptr, _locale_t loc) {
490 return _strtod_l(nptr, endptr, loc);
491 }
492# endif
493
494 locale_t locale_;
495
496 public:
497 using type = locale_t;
498 locale(const locale&) = delete;
499 void operator=(const locale&) = delete;
500
501 locale() {
502# ifndef _WIN32
503 locale_ = FMT_SYSTEM(newlocale(LC_NUMERIC_MASK, "C", nullptr));
504# else
505 locale_ = _create_locale(LC_NUMERIC, "C");
506# endif
507 if (!locale_) FMT_THROW(system_error(errno, "cannot create locale"));
508 }
509 ~locale() { freelocale(locale_); }
510
511 type get() const { return locale_; }
512
513 // Converts string to floating-point number and advances str past the end
514 // of the parsed input.
515 FMT_DEPRECATED double strtod(const char*& str) const {
516 char* end = nullptr;
517 double result = strtod_l(str, &end, locale_);
518 str = end;
519 return result;
520 }
521};
522using Locale FMT_DEPRECATED_ALIAS = locale;
523#endif // FMT_LOCALE
524FMT_MODULE_EXPORT_END
525FMT_END_NAMESPACE
526
527#endif // FMT_OS_H_
This page took 0.040234 seconds and 4 git commands to generate.