blob: 4eaf91a868d28d761987a6c5da9552422ae88204 [file] [log] [blame]
Victor Zverovichc0954452018-01-06 09:09:50 -08001// Formatting library for C++
2//
3// Copyright (c) 2012 - 2016, Victor Zverovich
4// All rights reserved.
5//
6// For the license information refer to format.h.
Victor Zverovichb076df42012-12-07 08:31:09 -08007
Victor Zverovichf853d942018-01-20 10:28:10 -08008#include "format.h"
9#include "locale.h"
Victor Zverovichfbfedcf2013-01-14 15:16:20 -080010
Victor Zverovich859a4972014-04-30 06:55:21 -070011#include <string.h>
12
Victor Zverovich72f896d2012-12-12 09:17:28 -080013#include <cctype>
Victor Zverovich5d15bdd2014-07-01 16:23:50 -070014#include <cerrno>
Victor Zverovichf28645f2014-04-24 12:37:06 -070015#include <climits>
Victor Zverovich9ff3b972013-09-07 10:15:08 -070016#include <cmath>
Victor Zverovicha684d0c2013-12-27 08:00:10 -080017#include <cstdarg>
vitaut7dcf0512015-11-13 06:52:13 -080018#include <cstddef> // for std::ptrdiff_t
Victor Zverovich9ff3b972013-09-07 10:15:08 -070019
vitaut24c309f2015-06-12 07:15:57 -070020#if defined(_WIN32) && defined(__MINGW32__)
21# include <cstring>
22#endif
23
24#if FMT_USE_WINDOWS_H
Victor Zverovichc753a2a2018-01-28 20:26:25 -080025# if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)
26# define WIN32_LEAN_AND_MEAN
27# endif
vitaut67ce3942015-04-30 07:48:36 -070028# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
29# include <windows.h>
30# else
31# define NOMINMAX
32# include <windows.h>
33# undef NOMINMAX
34# endif
Ryuuke5a9dc8f2015-02-08 16:08:29 +000035#endif
36
Victor Zverovich8b76e972014-10-06 08:30:55 -070037#if FMT_EXCEPTIONS
38# define FMT_TRY try
39# define FMT_CATCH(x) catch (x)
40#else
41# define FMT_TRY if (true)
42# define FMT_CATCH(x) if (false)
43#endif
44
Victor Zverovichb83241f2017-10-19 07:28:17 -070045#ifdef __GNUC__
Victor Zverovich07f8ffc2017-08-21 06:50:57 -070046// Disable the warning about declaration shadowing because it affects too
47// many valid cases.
Victor Zverovichb83241f2017-10-19 07:28:17 -070048# pragma GCC diagnostic ignored "-Wshadow"
49#endif
Victor Zverovich07f8ffc2017-08-21 06:50:57 -070050
Ingo van Lilb4b13ee2015-11-02 12:34:46 +010051#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +000052# pragma warning(push)
Victor Zverovich8b76e972014-10-06 08:30:55 -070053# pragma warning(disable: 4127) // conditional expression is constant
Daniel.Perrybd0067e2014-11-25 18:01:09 -050054# pragma warning(disable: 4702) // unreachable code
vitautdf47d812015-03-16 18:53:14 -070055// Disable deprecation warning for strerror. The latter is not called but
56// MSVC fails to detect it.
57# pragma warning(disable: 4996)
jdale88a9862fd2014-03-11 18:56:24 +000058#endif
59
vitaut341b98c2015-03-14 13:39:33 -070060// Dummy implementations of strerror_r and strerror_s called if corresponding
61// system functions are not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -080062static inline fmt::internal::null<> strerror_r(int, char *, ...) {
63 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070064}
Victor Zverovichc333dca2017-02-19 08:41:38 -080065static inline fmt::internal::null<> strerror_s(char *, std::size_t, ...) {
66 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070067}
68
vitaut8725d072015-06-12 07:56:58 -070069namespace fmt {
Victor Zverovichb26e76e2016-06-14 08:11:33 -070070
Victor Zverovich9bb213e2016-08-25 08:38:07 -070071FMT_FUNC format_error::~format_error() throw() {}
Victor Zverovichc333dca2017-02-19 08:41:38 -080072FMT_FUNC system_error::~system_error() throw() {}
Victor Zverovichb26e76e2016-06-14 08:11:33 -070073
Victor Zverovich9ff3b972013-09-07 10:15:08 -070074namespace {
75
76#ifndef _MSC_VER
Victor Zverovichb9a568b2014-09-19 07:51:42 -070077# define FMT_SNPRINTF snprintf
Victor Zverovicha684d0c2013-12-27 08:00:10 -080078#else // _MSC_VER
Victor Zverovich406c6122014-08-19 08:47:38 -070079inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -080080 va_list args;
81 va_start(args, format);
82 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
83 va_end(args);
84 return result;
85}
Victor Zverovichb9a568b2014-09-19 07:51:42 -070086# define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -070087#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -080088
cstamford55836ca2015-03-10 07:04:31 +000089#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
90# define FMT_SWPRINTF snwprintf
91#else
92# define FMT_SWPRINTF swprintf
93#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
94
Victor Zverovich7004d1e2015-02-08 19:54:39 -080095const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -070096
Victor Zverovichc2fecb92018-01-14 14:15:59 -080097typedef void (*FormatFunc)(internal::buffer &, int, string_view);
Victor Zverovich22f75d82014-09-03 08:03:05 -070098
Victor Zverovichf2c9df82014-09-05 08:44:41 -070099// Portable thread-safe version of strerror.
100// Sets buffer to point to a string describing the error code.
101// This can be either a pointer to a string stored in buffer,
102// or a pointer to some static immutable string.
103// Returns one of the following values:
104// 0 - success
105// ERANGE - buffer is not large enough to store the error message
106// other - failure
107// Buffer should be at least of size 1.
108int safe_strerror(
Carter Lie2583ab2015-02-14 09:58:29 +0800109 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
Victor Zverovich92a250f2018-02-07 07:16:00 -0800110 FMT_ASSERT(buffer != FMT_NULL && buffer_size != 0, "invalid buffer");
vitaut341b98c2015-03-14 13:39:33 -0700111
vitaut341b98c2015-03-14 13:39:33 -0700112 class StrError {
113 private:
114 int error_code_;
115 char *&buffer_;
116 std::size_t buffer_size_;
117
vitautda052ae2015-03-21 07:53:39 -0700118 // A noop assignment operator to avoid bogus warnings.
119 void operator=(const StrError &) {}
120
vitaut341b98c2015-03-14 13:39:33 -0700121 // Handle the result of XSI-compliant version of strerror_r.
122 int handle(int result) {
vitaute1776ac2015-03-14 14:05:02 -0700123 // glibc versions before 2.13 return result in errno.
124 return result == -1 ? errno : result;
vitaut341b98c2015-03-14 13:39:33 -0700125 }
126
127 // Handle the result of GNU-specific version of strerror_r.
128 int handle(char *message) {
129 // If the buffer is full then the message is probably truncated.
130 if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
131 return ERANGE;
132 buffer_ = message;
133 return 0;
134 }
135
136 // Handle the case when strerror_r is not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800137 int handle(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700138 return fallback(strerror_s(buffer_, buffer_size_, error_code_));
139 }
140
141 // Fallback to strerror_s when strerror_r is not available.
142 int fallback(int result) {
143 // If the buffer is full then the message is probably truncated.
144 return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
145 ERANGE : result;
146 }
147
148 // Fallback to strerror if strerror_r and strerror_s are not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800149 int fallback(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700150 errno = 0;
151 buffer_ = strerror(error_code_);
152 return errno;
153 }
154
155 public:
Radu Popescu0affb232015-08-04 12:52:44 +0200156 StrError(int err_code, char *&buf, std::size_t buf_size)
157 : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
vitaut341b98c2015-03-14 13:39:33 -0700158
vitaut63f6c102015-06-14 09:36:23 -0700159 int run() {
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800160 // Suppress a warning about unused strerror_r.
161 strerror_r(0, FMT_NULL, "");
vitaut63f6c102015-06-14 09:36:23 -0700162 return handle(strerror_r(error_code_, buffer_, buffer_size_));
163 }
vitaut341b98c2015-03-14 13:39:33 -0700164 };
165 return StrError(error_code, buffer, buffer_size).run();
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700166}
167
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800168void format_error_code(internal::buffer &out, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800169 string_view message) FMT_NOEXCEPT {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700170 // Report error code making sure that the output fits into
171 // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
172 // bad_alloc.
Victor Zverovichf423e462017-03-11 07:43:26 -0800173 out.resize(0);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700174 static const char SEP[] = ": ";
vitaut1addec92015-03-21 20:16:36 -0700175 static const char ERROR_STR[] = "error ";
vitaut1addec92015-03-21 20:16:36 -0700176 // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
177 std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800178 typedef internal::int_traits<int>::main_type main_type;
179 main_type abs_value = static_cast<main_type>(error_code);
vitaut9d577ca2016-03-02 07:01:21 -0800180 if (internal::is_negative(error_code)) {
181 abs_value = 0 - abs_value;
182 ++error_code_size;
183 }
vitautbfdca8b2016-04-20 09:11:33 -0700184 error_code_size += internal::count_digits(abs_value);
Victor Zverovich217e7c72018-01-14 07:19:23 -0800185 writer w(out);
Victor Zverovichec15ef72017-01-22 07:40:21 -0800186 if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) {
Victor Zverovichfefaf072017-02-14 16:29:47 -0500187 w.write(message);
188 w.write(SEP);
Victor Zverovichec15ef72017-01-22 07:40:21 -0800189 }
Victor Zverovichfefaf072017-02-14 16:29:47 -0500190 w.write(ERROR_STR);
191 w.write(error_code);
vitautbfdca8b2016-04-20 09:11:33 -0700192 assert(out.size() <= internal::INLINE_BUFFER_SIZE);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700193}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700194
vitautbfdca8b2016-04-20 09:11:33 -0700195void report_error(FormatFunc func, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800196 string_view message) FMT_NOEXCEPT {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800197 memory_buffer full_message;
Victor Zverovich88e0db82014-09-05 08:04:26 -0700198 func(full_message, error_code, message);
199 // Use Writer::data instead of Writer::c_str to avoid potential memory
200 // allocation.
201 std::fwrite(full_message.data(), full_message.size(), 1, stderr);
202 std::fputc('\n', stderr);
Victor Zverovichb605b392013-09-09 22:21:40 -0700203}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700204} // namespace
vitaut270069b2015-06-16 07:36:32 -0700205
Victor Zverovich7f351de2017-12-03 09:18:06 -0800206template <typename Char>
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800207FMT_FUNC Char internal::thousands_sep(locale_provider *lp) {
208 std::locale loc = lp ? lp->locale().get() : std::locale();
209 return std::use_facet<std::numpunct<Char>>(loc).thousands_sep();
Victor Zverovich7f351de2017-12-03 09:18:06 -0800210}
211
Victor Zverovichc333dca2017-02-19 08:41:38 -0800212FMT_FUNC void system_error::init(
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800213 int err_code, string_view format_str, format_args args) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800214 error_code_ = err_code;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800215 memory_buffer buffer;
216 format_system_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700217 std::runtime_error &base = *this;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800218 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700219}
220
Victor Zverovichb605b392013-09-09 22:21:40 -0700221template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800222int internal::char_traits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700223 char *buffer, std::size_t size, const char *format,
224 unsigned width, int precision, T value) {
225 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700226 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700227 FMT_SNPRINTF(buffer, size, format, value) :
228 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700229 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700230 return precision < 0 ?
231 FMT_SNPRINTF(buffer, size, format, width, value) :
232 FMT_SNPRINTF(buffer, size, format, width, precision, value);
233}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700234
Victor Zverovichb605b392013-09-09 22:21:40 -0700235template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800236int internal::char_traits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700237 wchar_t *buffer, std::size_t size, const wchar_t *format,
238 unsigned width, int precision, T value) {
239 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700240 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000241 FMT_SWPRINTF(buffer, size, format, value) :
242 FMT_SWPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700243 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700244 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000245 FMT_SWPRINTF(buffer, size, format, width, value) :
246 FMT_SWPRINTF(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700247}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800248
Victor Zverovich311251e2014-11-29 06:58:00 -0800249template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800250const char internal::basic_data<T>::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800251 "0001020304050607080910111213141516171819"
252 "2021222324252627282930313233343536373839"
253 "4041424344454647484950515253545556575859"
254 "6061626364656667686970717273747576777879"
255 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800256
Victor Zverovichf1d85162014-02-19 13:02:22 -0800257#define FMT_POWERS_OF_10(factor) \
258 factor * 10, \
259 factor * 100, \
260 factor * 1000, \
261 factor * 10000, \
262 factor * 100000, \
263 factor * 1000000, \
264 factor * 10000000, \
265 factor * 100000000, \
266 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800267
Victor Zverovich311251e2014-11-29 06:58:00 -0800268template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800269const uint32_t internal::basic_data<T>::POWERS_OF_10_32[] = {
Victor Zverovich311251e2014-11-29 06:58:00 -0800270 0, FMT_POWERS_OF_10(1)
271};
272
273template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800274const uint64_t internal::basic_data<T>::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800275 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800276 FMT_POWERS_OF_10(1),
Victor Zverovich016aceb2017-08-26 09:09:43 -0700277 FMT_POWERS_OF_10(1000000000ull),
278 10000000000000000000ull
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800279};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800280
vitaut24c309f2015-06-12 07:15:57 -0700281#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700282
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800283FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
Victor Zverovichdff21372014-12-16 07:01:01 -0800284 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
vitautc3ba6152015-08-07 07:34:58 -0700285 if (s.size() > INT_MAX)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800286 FMT_THROW(windows_error(ERROR_INVALID_PARAMETER, ERROR_MSG));
vitautc3ba6152015-08-07 07:34:58 -0700287 int s_size = static_cast<int>(s.size());
288 int length = MultiByteToWideChar(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800289 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700290 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800291 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700292 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700293 length = MultiByteToWideChar(
vitautc3ba6152015-08-07 07:34:58 -0700294 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700295 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800296 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700297 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700298}
299
Victor Zverovichc333dca2017-02-19 08:41:38 -0800300FMT_FUNC internal::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700301 if (int error_code = convert(s)) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800302 FMT_THROW(windows_error(error_code,
Victor Zverovich8b76e972014-10-06 08:30:55 -0700303 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700304 }
305}
306
Victor Zverovichc333dca2017-02-19 08:41:38 -0800307FMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) {
vitautca747812015-08-07 07:08:46 -0700308 if (s.size() > INT_MAX)
309 return ERROR_INVALID_PARAMETER;
310 int s_size = static_cast<int>(s.size());
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800311 int length = WideCharToMultiByte(
312 CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700313 if (length == 0)
314 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700315 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700316 length = WideCharToMultiByte(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800317 CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700318 if (length == 0)
319 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700320 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700321 return 0;
322}
323
Victor Zverovichc333dca2017-02-19 08:41:38 -0800324FMT_FUNC void windows_error::init(
Victor Zverovich7f351de2017-12-03 09:18:06 -0800325 int err_code, string_view format_str, format_args args) {
Carter Li3f574c12015-02-17 10:11:42 +0800326 error_code_ = err_code;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800327 memory_buffer buffer;
Victor Zveroviche022c212017-02-17 06:38:53 -0800328 internal::format_windows_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700329 std::runtime_error &base = *this;
Victor Zveroviche022c212017-02-17 06:38:53 -0800330 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700331}
332
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700333FMT_FUNC void internal::format_windows_error(
Victor Zverovichf6fd38b2018-01-15 08:22:31 -0800334 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700335 FMT_TRY {
Victor Zverovichc0954452018-01-06 09:09:50 -0800336 wmemory_buffer buf;
337 buf.resize(INLINE_BUFFER_SIZE);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800338 for (;;) {
Victor Zverovichc0954452018-01-06 09:09:50 -0800339 wchar_t *system_message = &buf[0];
Victor Zverovichf85d5f42016-10-22 08:04:20 -0700340 int result = FormatMessageW(
341 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800342 FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
343 system_message, static_cast<uint32_t>(buf.size()), FMT_NULL);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800344 if (result != 0) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800345 utf16_to_utf8 utf8_message;
Michael Winterberg2a05a872016-03-02 17:35:34 -0800346 if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800347 writer w(out);
Victor Zveroviche022c212017-02-17 06:38:53 -0800348 w.write(message);
349 w.write(": ");
350 w.write(utf8_message);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800351 return;
352 }
353 break;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700354 }
Michael Winterberg2a05a872016-03-02 17:35:34 -0800355 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
356 break; // Can't get error message, report error code instead.
Victor Zverovichc0954452018-01-06 09:09:50 -0800357 buf.resize(buf.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700358 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700359 } FMT_CATCH(...) {}
Victor Zverovichc0954452018-01-06 09:09:50 -0800360 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700361}
vitaut24c309f2015-06-12 07:15:57 -0700362
363#endif // FMT_USE_WINDOWS_H
364
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700365FMT_FUNC void format_system_error(
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800366 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
vitaut24c309f2015-06-12 07:15:57 -0700367 FMT_TRY {
Victor Zverovich36634142017-12-26 09:00:22 -0800368 memory_buffer buf;
369 buf.resize(internal::INLINE_BUFFER_SIZE);
vitaut24c309f2015-06-12 07:15:57 -0700370 for (;;) {
Victor Zverovich36634142017-12-26 09:00:22 -0800371 char *system_message = &buf[0];
372 int result = safe_strerror(error_code, system_message, buf.size());
vitaut24c309f2015-06-12 07:15:57 -0700373 if (result == 0) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800374 writer w(out);
Victor Zverovichfefaf072017-02-14 16:29:47 -0500375 w.write(message);
376 w.write(": ");
377 w.write(system_message);
vitaut24c309f2015-06-12 07:15:57 -0700378 return;
379 }
380 if (result != ERANGE)
381 break; // Can't get error message, report error code instead.
Victor Zverovich36634142017-12-26 09:00:22 -0800382 buf.resize(buf.size() * 2);
vitaut24c309f2015-06-12 07:15:57 -0700383 }
384 } FMT_CATCH(...) {}
Victor Zverovichf164e4c2018-02-01 16:49:47 -0800385 format_error_code(out, error_code, message);
vitaut24c309f2015-06-12 07:15:57 -0700386}
Victor Zverovich53b4c312014-04-30 15:00:41 -0700387
jamboree7487bde2015-06-10 09:32:59 +0800388template <typename Char>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800389void basic_fixed_buffer<Char>::grow(std::size_t) {
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800390 FMT_THROW(std::runtime_error("buffer overflow"));
391}
392
Abdó Roig-Marangesaf0f21d2017-12-09 16:50:53 +0100393FMT_FUNC void internal::error_handler::on_error(const char *message) {
Victor Zverovich94edb1a2017-12-06 07:42:42 -0800394 FMT_THROW(format_error(message));
395}
396
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700397FMT_FUNC void report_system_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800398 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700399 report_error(format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700400}
401
vitaut24c309f2015-06-12 07:15:57 -0700402#if FMT_USE_WINDOWS_H
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700403FMT_FUNC void report_windows_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800404 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700405 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700406}
Victor Zverovich400812a2014-04-30 12:38:17 -0700407#endif
Victor Zverovichf7939862014-04-30 10:18:11 -0700408
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800409FMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800410 memory_buffer buffer;
Victor Zverovichfefaf072017-02-14 16:29:47 -0500411 vformat_to(buffer, format_str, args);
412 std::fwrite(buffer.data(), 1, buffer.size(), f);
Victor Zverovichd5b81962014-06-28 21:56:40 -0700413}
414
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800415FMT_FUNC void vprint(string_view format_str, format_args args) {
Victor Zverovich0028ce52016-08-26 17:23:13 -0700416 vprint(stdout, format_str, args);
Victor Zverovich163178e2014-09-25 07:08:25 -0700417}
418
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800419FMT_FUNC void vprint_colored(Color c, string_view format, format_args args) {
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700420 char escape[] = "\x1b[30m";
Ingo van Lilf4d88842015-11-02 19:14:47 +0100421 escape[3] = static_cast<char>('0' + c);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700422 std::fputs(escape, stdout);
Victor Zverovich0028ce52016-08-26 17:23:13 -0700423 vprint(format, args);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700424 std::fputs(RESET_COLOR, stdout);
425}
426
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800427FMT_FUNC locale locale_provider::locale() { return fmt::locale(); }
428
Victor Zverovichc09c42f2015-03-01 09:43:33 -0800429#ifndef FMT_HEADER_ONLY
430
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800431template struct internal::basic_data<void>;
vitaut804a74c2015-05-14 12:58:42 -0700432
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700433// Explicit instantiations for char.
434
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800435template char internal::thousands_sep(locale_provider *lp);
Victor Zverovich7f351de2017-12-03 09:18:06 -0800436
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800437template void basic_fixed_buffer<char>::grow(std::size_t);
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800438
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800439template void internal::arg_map<context>::init(const format_args &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700440
Victor Zverovichf9fa7c42018-01-27 17:15:14 -0800441template FMT_API int internal::char_traits<char>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700442 char *buffer, std::size_t size, const char *format,
443 unsigned width, int precision, double value);
444
Victor Zverovichf9fa7c42018-01-27 17:15:14 -0800445template FMT_API int internal::char_traits<char>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700446 char *buffer, std::size_t size, const char *format,
447 unsigned width, int precision, long double value);
448
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700449// Explicit instantiations for wchar_t.
450
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800451template wchar_t internal::thousands_sep(locale_provider *lp);
Victor Zverovich7f351de2017-12-03 09:18:06 -0800452
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800453template void basic_fixed_buffer<wchar_t>::grow(std::size_t);
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800454
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800455template void internal::arg_map<wcontext>::init(const wformat_args &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700456
Victor Zverovichf9fa7c42018-01-27 17:15:14 -0800457template FMT_API int internal::char_traits<wchar_t>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700458 wchar_t *buffer, std::size_t size, const wchar_t *format,
459 unsigned width, int precision, double value);
460
Victor Zverovichf9fa7c42018-01-27 17:15:14 -0800461template FMT_API int internal::char_traits<wchar_t>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700462 wchar_t *buffer, std::size_t size, const wchar_t *format,
463 unsigned width, int precision, long double value);
464
Victor Zverovichc09c42f2015-03-01 09:43:33 -0800465#endif // FMT_HEADER_ONLY
466
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700467} // namespace fmt
468
Ingo van Lilb4b13ee2015-11-02 12:34:46 +0100469#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +0000470# pragma warning(pop)
471#endif