1 // Formatting library for C++ - optional OS-specific functionality
3 // Copyright (c) 2012 - present, Victor Zverovich
4 // All rights reserved.
6 // For the license information refer to format.h.
12 #include <clocale> // locale_t
15 #include <cstdlib> // strtod_l
16 #include <system_error> // std::system_error
18 #if defined __APPLE__ || defined(__FreeBSD__)
19 # include <xlocale.h> // for LC_NUMERIC_MASK on OS X
25 // UWP doesn't provide _pipe.
26 # if FMT_HAS_INCLUDE("winapifamily.h")
27 # include <winapifamily.h>
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
36 # define FMT_USE_FCNTL 0
41 # if defined(_WIN32) && !defined(__MINGW32__)
42 // Fix warnings about deprecated symbols.
43 # define FMT_POSIX(call) _##call
45 # define FMT_POSIX(call) call
49 // Calls to system functions are wrapped in FMT_SYSTEM for testability.
51 # define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
53 # define FMT_SYSTEM(call) ::call
55 // Fix warnings about deprecated symbols.
56 # define FMT_POSIX_CALL(call) ::_##call
58 # define FMT_POSIX_CALL(call) ::call
62 // Retries the expression while it evaluates to error_result and errno
65 # define FMT_RETRY_VAL(result, expression, error_result) \
67 (result) = (expression); \
68 } while ((result) == (error_result) && errno == EINTR)
70 # define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
73 #define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
76 FMT_MODULE_EXPORT_BEGIN
80 A reference to a null-terminated string. It can be constructed from a C
81 string or ``std::string``.
83 You can use one of the following type aliases for common character types:
85 +---------------+-----------------------------+
87 +===============+=============================+
88 | cstring_view | basic_cstring_view<char> |
89 +---------------+-----------------------------+
90 | wcstring_view | basic_cstring_view<wchar_t> |
91 +---------------+-----------------------------+
93 This class is most useful as a parameter type to allow passing
94 different types of strings to a function, for example::
96 template <typename... Args>
97 std::string format(cstring_view format_str, const Args & ... args);
100 format(std::string("{}"), 42);
103 template <typename Char
> class basic_cstring_view
{
108 /** Constructs a string reference object from a C string. */
109 basic_cstring_view(const Char
* s
) : data_(s
) {}
113 Constructs a string reference from an ``std::string`` object.
116 basic_cstring_view(const std::basic_string
<Char
>& s
) : data_(s
.c_str()) {}
118 /** Returns the pointer to a C string. */
119 const Char
* c_str() const { return data_
; }
122 using cstring_view
= basic_cstring_view
<char>;
123 using wcstring_view
= basic_cstring_view
<wchar_t>;
125 template <typename Char
> struct formatter
<std::error_code
, Char
> {
126 template <typename ParseContext
>
127 FMT_CONSTEXPR
auto parse(ParseContext
& ctx
) -> decltype(ctx
.begin()) {
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());
144 FMT_API
const std::error_category
& system_category() FMT_NOEXCEPT
;
146 FMT_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.
149 class utf16_to_utf8
{
151 memory_buffer buffer_
;
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()); }
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
);
167 FMT_API
void format_windows_error(buffer
<char>& out
, int error_code
,
168 const char* message
) FMT_NOEXCEPT
;
169 FMT_END_DETAIL_NAMESPACE
171 FMT_API
std::system_error
vwindows_error(int error_code
, string_view format_str
,
176 Constructs a :class:`std::system_error` object with the description
180 *<message>*: *<system-message>*
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".
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);
202 template <typename
... Args
>
203 std::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
...));
208 // Reports a Windows error without throwing an exception.
209 // Can be used to report errors from destructors.
210 FMT_API
void report_windows_error(int error_code
,
211 const char* message
) FMT_NOEXCEPT
;
213 inline const std::error_category
& system_category() FMT_NOEXCEPT
{
214 return std::system_category();
218 // std::system is not available on some platforms such as iOS (#2248).
220 template <typename S
, typename
... Args
, typename Char
= char_t
<S
>>
221 void say(const S
& format_str
, Args
&&... args
) {
222 std::system(format("say \"{}\"", format(format_str
, args
...)).c_str());
227 class buffered_file
{
233 explicit buffered_file(FILE* f
) : file_(f
) {}
236 buffered_file(const buffered_file
&) = delete;
237 void operator=(const buffered_file
&) = delete;
239 // Constructs a buffered_file object which doesn't represent any file.
240 buffered_file() FMT_NOEXCEPT
: file_(nullptr) {}
242 // Destroys the object closing the file it represents if any.
243 FMT_API
~buffered_file() FMT_NOEXCEPT
;
246 buffered_file(buffered_file
&& other
) FMT_NOEXCEPT
: file_(other
.file_
) {
247 other
.file_
= nullptr;
250 buffered_file
& operator=(buffered_file
&& other
) {
253 other
.file_
= nullptr;
258 FMT_API
buffered_file(cstring_view filename
, cstring_view mode
);
261 FMT_API
void close();
263 // Returns the pointer to a FILE object representing this file.
264 FILE* get() const FMT_NOEXCEPT
{ return file_
; }
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;
270 void vprint(string_view format_str
, format_args args
) {
271 fmt::vprint(file_
, format_str
, args
);
274 template <typename
... Args
>
275 inline void print(string_view format_str
, const Args
&... args
) {
276 vprint(format_str
, fmt::make_format_args(args
...));
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.
289 int fd_
; // File descriptor.
291 // Constructs a file object with a given descriptor.
292 explicit file(int fd
) : fd_(fd
) {}
295 // Possible values for the oflag argument to the constructor.
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.
305 // Constructs a file object which doesn't represent any file.
306 file() FMT_NOEXCEPT
: fd_(-1) {}
308 // Opens a file and constructs a file object representing this file.
309 FMT_API
file(cstring_view path
, int oflag
);
312 file(const file
&) = delete;
313 void operator=(const file
&) = delete;
315 file(file
&& other
) FMT_NOEXCEPT
: fd_(other
.fd_
) { other
.fd_
= -1; }
317 // Move assignment is not noexcept because close may throw.
318 file
& operator=(file
&& other
) {
325 // Destroys the object closing the file it represents if any.
326 FMT_API
~file() FMT_NOEXCEPT
;
328 // Returns the file descriptor.
329 int descriptor() const FMT_NOEXCEPT
{ return fd_
; }
332 FMT_API
void close();
334 // Returns the file size. The size has signed type for consistency with
336 FMT_API
long long size() const;
338 // Attempts to read count bytes from the file into the specified buffer.
339 FMT_API
size_t read(void* buffer
, size_t count
);
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
);
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
);
348 // Makes fd be the copy of this file descriptor, closing fd first if
350 FMT_API
void dup2(int fd
);
352 // Makes fd be the copy of this file descriptor, closing fd first if
354 FMT_API
void dup2(int fd
, std::error_code
& ec
) FMT_NOEXCEPT
;
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
);
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
);
365 // Returns the memory page size.
368 FMT_BEGIN_DETAIL_NAMESPACE
371 buffer_size() = default;
373 buffer_size
operator=(size_t val
) const {
374 auto bs
= buffer_size();
380 struct ostream_params
{
381 int oflag
= file::WRONLY
| file::CREATE
| file::TRUNC
;
382 size_t buffer_size
= BUFSIZ
> 32768 ? BUFSIZ
: 32768;
386 template <typename
... T
>
387 ostream_params(T
... params
, int new_oflag
) : ostream_params(params
...) {
391 template <typename
... T
>
392 ostream_params(T
... params
, detail::buffer_size bs
)
393 : ostream_params(params
...) {
394 this->buffer_size
= bs
.value
;
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
) {}
405 FMT_END_DETAIL_NAMESPACE
407 // Added {} below to work around default constructor error known to
408 // occur in Xcode versions 7.2.1 and 8.2.1.
409 constexpr detail::buffer_size buffer_size
{};
411 /** A fast output stream which is not thread-safe. */
412 class FMT_API ostream final
: private detail::buffer
<char> {
416 void grow(size_t) override
;
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
);
424 ostream(ostream
&& other
)
425 : detail::buffer
<char>(other
.data(), other
.size(), other
.capacity()),
426 file_(std::move(other
.file_
)) {
428 other
.set(nullptr, 0);
436 if (size() == 0) return;
437 file_
.write(data(), size());
441 template <typename
... T
>
442 friend ostream
output_file(cstring_view path
, T
... params
);
450 Formats ``args`` according to specifications in ``fmt`` and writes the
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
...));
461 Opens a file for writing. Supported parameters passed in *params*:
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
470 auto out = fmt::output_file("guide.txt");
471 out.print("Don't {}", "Panic");
474 template <typename
... T
>
475 inline ostream
output_file(cstring_view path
, T
... params
) {
476 return {path
, detail::ostream_params(params
...)};
478 #endif // FMT_USE_FCNTL
481 // A "C" numeric locale.
485 using locale_t
= _locale_t
;
487 static void freelocale(locale_t loc
) { _free_locale(loc
); }
489 static double strtod_l(const char* nptr
, char** endptr
, _locale_t loc
) {
490 return _strtod_l(nptr
, endptr
, loc
);
497 using type
= locale_t
;
498 locale(const locale
&) = delete;
499 void operator=(const locale
&) = delete;
503 locale_
= FMT_SYSTEM(newlocale(LC_NUMERIC_MASK
, "C", nullptr));
505 locale_
= _create_locale(LC_NUMERIC
, "C");
507 if (!locale_
) FMT_THROW(system_error(errno
, "cannot create locale"));
509 ~locale() { freelocale(locale_
); }
511 type
get() const { return locale_
; }
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 {
517 double result
= strtod_l(str
, &end
, locale_
);
522 using Locale FMT_DEPRECATED_ALIAS
= locale
;
524 FMT_MODULE_EXPORT_END