blob: edecd87dc9d9d12a93437a2c0cef2e51f95422f6 [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 Zverovich6cb68f92018-02-10 06:28:33 -080062inline fmt::internal::null<> strerror_r(int, char *, ...) {
Victor Zverovichc333dca2017-02-19 08:41:38 -080063 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070064}
Victor Zverovich6cb68f92018-02-10 06:28:33 -080065inline fmt::internal::null<> strerror_s(char *, std::size_t, ...) {
Victor Zverovichc333dca2017-02-19 08:41:38 -080066 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() {
vitaut63f6c102015-06-14 09:36:23 -0700160 return handle(strerror_r(error_code_, buffer_, buffer_size_));
161 }
vitaut341b98c2015-03-14 13:39:33 -0700162 };
163 return StrError(error_code, buffer, buffer_size).run();
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700164}
165
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800166void format_error_code(internal::buffer &out, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800167 string_view message) FMT_NOEXCEPT {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700168 // Report error code making sure that the output fits into
169 // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
170 // bad_alloc.
Victor Zverovichf423e462017-03-11 07:43:26 -0800171 out.resize(0);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700172 static const char SEP[] = ": ";
vitaut1addec92015-03-21 20:16:36 -0700173 static const char ERROR_STR[] = "error ";
vitaut1addec92015-03-21 20:16:36 -0700174 // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
175 std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800176 typedef internal::int_traits<int>::main_type main_type;
177 main_type abs_value = static_cast<main_type>(error_code);
vitaut9d577ca2016-03-02 07:01:21 -0800178 if (internal::is_negative(error_code)) {
179 abs_value = 0 - abs_value;
180 ++error_code_size;
181 }
vitautbfdca8b2016-04-20 09:11:33 -0700182 error_code_size += internal::count_digits(abs_value);
Victor Zverovich217e7c72018-01-14 07:19:23 -0800183 writer w(out);
Victor Zverovichec15ef72017-01-22 07:40:21 -0800184 if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) {
Victor Zverovichfefaf072017-02-14 16:29:47 -0500185 w.write(message);
186 w.write(SEP);
Victor Zverovichec15ef72017-01-22 07:40:21 -0800187 }
Victor Zverovichfefaf072017-02-14 16:29:47 -0500188 w.write(ERROR_STR);
189 w.write(error_code);
vitautbfdca8b2016-04-20 09:11:33 -0700190 assert(out.size() <= internal::INLINE_BUFFER_SIZE);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700191}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700192
vitautbfdca8b2016-04-20 09:11:33 -0700193void report_error(FormatFunc func, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800194 string_view message) FMT_NOEXCEPT {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800195 memory_buffer full_message;
Victor Zverovich88e0db82014-09-05 08:04:26 -0700196 func(full_message, error_code, message);
197 // Use Writer::data instead of Writer::c_str to avoid potential memory
198 // allocation.
199 std::fwrite(full_message.data(), full_message.size(), 1, stderr);
200 std::fputc('\n', stderr);
Victor Zverovichb605b392013-09-09 22:21:40 -0700201}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700202} // namespace
vitaut270069b2015-06-16 07:36:32 -0700203
Victor Zverovich7f351de2017-12-03 09:18:06 -0800204template <typename Char>
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800205FMT_FUNC Char internal::thousands_sep(locale_provider *lp) {
206 std::locale loc = lp ? lp->locale().get() : std::locale();
207 return std::use_facet<std::numpunct<Char>>(loc).thousands_sep();
Victor Zverovich7f351de2017-12-03 09:18:06 -0800208}
209
Victor Zverovichc333dca2017-02-19 08:41:38 -0800210FMT_FUNC void system_error::init(
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800211 int err_code, string_view format_str, format_args args) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800212 error_code_ = err_code;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800213 memory_buffer buffer;
214 format_system_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700215 std::runtime_error &base = *this;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800216 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700217}
218
Victor Zverovichb605b392013-09-09 22:21:40 -0700219template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800220int internal::char_traits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700221 char *buffer, std::size_t size, const char *format,
222 unsigned width, int precision, T value) {
223 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700224 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700225 FMT_SNPRINTF(buffer, size, format, value) :
226 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700227 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700228 return precision < 0 ?
229 FMT_SNPRINTF(buffer, size, format, width, value) :
230 FMT_SNPRINTF(buffer, size, format, width, precision, value);
231}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700232
Victor Zverovichb605b392013-09-09 22:21:40 -0700233template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800234int internal::char_traits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700235 wchar_t *buffer, std::size_t size, const wchar_t *format,
236 unsigned width, int precision, T value) {
237 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700238 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000239 FMT_SWPRINTF(buffer, size, format, value) :
240 FMT_SWPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700241 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700242 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000243 FMT_SWPRINTF(buffer, size, format, width, value) :
244 FMT_SWPRINTF(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700245}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800246
Victor Zverovich311251e2014-11-29 06:58:00 -0800247template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800248const char internal::basic_data<T>::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800249 "0001020304050607080910111213141516171819"
250 "2021222324252627282930313233343536373839"
251 "4041424344454647484950515253545556575859"
252 "6061626364656667686970717273747576777879"
253 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800254
Victor Zverovichf1d85162014-02-19 13:02:22 -0800255#define FMT_POWERS_OF_10(factor) \
256 factor * 10, \
257 factor * 100, \
258 factor * 1000, \
259 factor * 10000, \
260 factor * 100000, \
261 factor * 1000000, \
262 factor * 10000000, \
263 factor * 100000000, \
264 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800265
Victor Zverovich311251e2014-11-29 06:58:00 -0800266template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800267const uint32_t internal::basic_data<T>::POWERS_OF_10_32[] = {
Victor Zverovich311251e2014-11-29 06:58:00 -0800268 0, FMT_POWERS_OF_10(1)
269};
270
271template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800272const uint64_t internal::basic_data<T>::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800273 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800274 FMT_POWERS_OF_10(1),
Victor Zverovich016aceb2017-08-26 09:09:43 -0700275 FMT_POWERS_OF_10(1000000000ull),
276 10000000000000000000ull
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800277};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800278
vitaut24c309f2015-06-12 07:15:57 -0700279#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700280
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800281FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
Victor Zverovichdff21372014-12-16 07:01:01 -0800282 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
vitautc3ba6152015-08-07 07:34:58 -0700283 if (s.size() > INT_MAX)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800284 FMT_THROW(windows_error(ERROR_INVALID_PARAMETER, ERROR_MSG));
vitautc3ba6152015-08-07 07:34:58 -0700285 int s_size = static_cast<int>(s.size());
286 int length = MultiByteToWideChar(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800287 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700288 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800289 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700290 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700291 length = MultiByteToWideChar(
vitautc3ba6152015-08-07 07:34:58 -0700292 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700293 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800294 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700295 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700296}
297
Victor Zverovichc333dca2017-02-19 08:41:38 -0800298FMT_FUNC internal::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700299 if (int error_code = convert(s)) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800300 FMT_THROW(windows_error(error_code,
Victor Zverovich8b76e972014-10-06 08:30:55 -0700301 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700302 }
303}
304
Victor Zverovichc333dca2017-02-19 08:41:38 -0800305FMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) {
vitautca747812015-08-07 07:08:46 -0700306 if (s.size() > INT_MAX)
307 return ERROR_INVALID_PARAMETER;
308 int s_size = static_cast<int>(s.size());
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800309 int length = WideCharToMultiByte(
310 CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700311 if (length == 0)
312 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700313 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700314 length = WideCharToMultiByte(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800315 CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700316 if (length == 0)
317 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700318 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700319 return 0;
320}
321
Victor Zverovichc333dca2017-02-19 08:41:38 -0800322FMT_FUNC void windows_error::init(
Victor Zverovich7f351de2017-12-03 09:18:06 -0800323 int err_code, string_view format_str, format_args args) {
Carter Li3f574c12015-02-17 10:11:42 +0800324 error_code_ = err_code;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800325 memory_buffer buffer;
Victor Zveroviche022c212017-02-17 06:38:53 -0800326 internal::format_windows_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700327 std::runtime_error &base = *this;
Victor Zveroviche022c212017-02-17 06:38:53 -0800328 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700329}
330
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700331FMT_FUNC void internal::format_windows_error(
Victor Zverovichf6fd38b2018-01-15 08:22:31 -0800332 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700333 FMT_TRY {
Victor Zverovichc0954452018-01-06 09:09:50 -0800334 wmemory_buffer buf;
335 buf.resize(INLINE_BUFFER_SIZE);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800336 for (;;) {
Victor Zverovichc0954452018-01-06 09:09:50 -0800337 wchar_t *system_message = &buf[0];
Victor Zverovichf85d5f42016-10-22 08:04:20 -0700338 int result = FormatMessageW(
339 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800340 FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
341 system_message, static_cast<uint32_t>(buf.size()), FMT_NULL);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800342 if (result != 0) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800343 utf16_to_utf8 utf8_message;
Michael Winterberg2a05a872016-03-02 17:35:34 -0800344 if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800345 writer w(out);
Victor Zveroviche022c212017-02-17 06:38:53 -0800346 w.write(message);
347 w.write(": ");
348 w.write(utf8_message);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800349 return;
350 }
351 break;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700352 }
Michael Winterberg2a05a872016-03-02 17:35:34 -0800353 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
354 break; // Can't get error message, report error code instead.
Victor Zverovichc0954452018-01-06 09:09:50 -0800355 buf.resize(buf.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700356 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700357 } FMT_CATCH(...) {}
Victor Zverovichc0954452018-01-06 09:09:50 -0800358 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700359}
vitaut24c309f2015-06-12 07:15:57 -0700360
361#endif // FMT_USE_WINDOWS_H
362
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700363FMT_FUNC void format_system_error(
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800364 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
vitaut24c309f2015-06-12 07:15:57 -0700365 FMT_TRY {
Victor Zverovich36634142017-12-26 09:00:22 -0800366 memory_buffer buf;
367 buf.resize(internal::INLINE_BUFFER_SIZE);
vitaut24c309f2015-06-12 07:15:57 -0700368 for (;;) {
Victor Zverovich36634142017-12-26 09:00:22 -0800369 char *system_message = &buf[0];
370 int result = safe_strerror(error_code, system_message, buf.size());
vitaut24c309f2015-06-12 07:15:57 -0700371 if (result == 0) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800372 writer w(out);
Victor Zverovichfefaf072017-02-14 16:29:47 -0500373 w.write(message);
374 w.write(": ");
375 w.write(system_message);
vitaut24c309f2015-06-12 07:15:57 -0700376 return;
377 }
378 if (result != ERANGE)
379 break; // Can't get error message, report error code instead.
Victor Zverovich36634142017-12-26 09:00:22 -0800380 buf.resize(buf.size() * 2);
vitaut24c309f2015-06-12 07:15:57 -0700381 }
382 } FMT_CATCH(...) {}
Victor Zverovichf164e4c2018-02-01 16:49:47 -0800383 format_error_code(out, error_code, message);
vitaut24c309f2015-06-12 07:15:57 -0700384}
Victor Zverovich53b4c312014-04-30 15:00:41 -0700385
jamboree7487bde2015-06-10 09:32:59 +0800386template <typename Char>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800387void basic_fixed_buffer<Char>::grow(std::size_t) {
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800388 FMT_THROW(std::runtime_error("buffer overflow"));
389}
390
Abdó Roig-Marangesaf0f21d2017-12-09 16:50:53 +0100391FMT_FUNC void internal::error_handler::on_error(const char *message) {
Victor Zverovich94edb1a2017-12-06 07:42:42 -0800392 FMT_THROW(format_error(message));
393}
394
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700395FMT_FUNC void report_system_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800396 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700397 report_error(format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700398}
399
vitaut24c309f2015-06-12 07:15:57 -0700400#if FMT_USE_WINDOWS_H
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700401FMT_FUNC void report_windows_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800402 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700403 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700404}
Victor Zverovich400812a2014-04-30 12:38:17 -0700405#endif
Victor Zverovichf7939862014-04-30 10:18:11 -0700406
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800407FMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800408 memory_buffer buffer;
Victor Zverovichfefaf072017-02-14 16:29:47 -0500409 vformat_to(buffer, format_str, args);
410 std::fwrite(buffer.data(), 1, buffer.size(), f);
Victor Zverovichd5b81962014-06-28 21:56:40 -0700411}
412
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800413FMT_FUNC void vprint(string_view format_str, format_args args) {
Victor Zverovich0028ce52016-08-26 17:23:13 -0700414 vprint(stdout, format_str, args);
Victor Zverovich163178e2014-09-25 07:08:25 -0700415}
416
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800417FMT_FUNC void vprint_colored(Color c, string_view format, format_args args) {
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700418 char escape[] = "\x1b[30m";
Ingo van Lilf4d88842015-11-02 19:14:47 +0100419 escape[3] = static_cast<char>('0' + c);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700420 std::fputs(escape, stdout);
Victor Zverovich0028ce52016-08-26 17:23:13 -0700421 vprint(format, args);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700422 std::fputs(RESET_COLOR, stdout);
423}
424
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800425FMT_FUNC locale locale_provider::locale() { return fmt::locale(); }
426
Victor Zverovichc09c42f2015-03-01 09:43:33 -0800427#ifndef FMT_HEADER_ONLY
428
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800429template struct internal::basic_data<void>;
vitaut804a74c2015-05-14 12:58:42 -0700430
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700431// Explicit instantiations for char.
432
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800433template char internal::thousands_sep(locale_provider *lp);
Victor Zverovich7f351de2017-12-03 09:18:06 -0800434
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800435template void basic_fixed_buffer<char>::grow(std::size_t);
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800436
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800437template void internal::arg_map<context>::init(const format_args &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700438
Victor Zverovichf9fa7c42018-01-27 17:15:14 -0800439template FMT_API int internal::char_traits<char>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700440 char *buffer, std::size_t size, const char *format,
441 unsigned width, int precision, double value);
442
Victor Zverovichf9fa7c42018-01-27 17:15:14 -0800443template FMT_API int internal::char_traits<char>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700444 char *buffer, std::size_t size, const char *format,
445 unsigned width, int precision, long double value);
446
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700447// Explicit instantiations for wchar_t.
448
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800449template wchar_t internal::thousands_sep(locale_provider *lp);
Victor Zverovich7f351de2017-12-03 09:18:06 -0800450
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800451template void basic_fixed_buffer<wchar_t>::grow(std::size_t);
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800452
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800453template void internal::arg_map<wcontext>::init(const wformat_args &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700454
Victor Zverovichf9fa7c42018-01-27 17:15:14 -0800455template FMT_API int internal::char_traits<wchar_t>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700456 wchar_t *buffer, std::size_t size, const wchar_t *format,
457 unsigned width, int precision, double value);
458
Victor Zverovichf9fa7c42018-01-27 17:15:14 -0800459template FMT_API int internal::char_traits<wchar_t>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700460 wchar_t *buffer, std::size_t size, const wchar_t *format,
461 unsigned width, int precision, long double value);
462
Victor Zverovichc09c42f2015-03-01 09:43:33 -0800463#endif // FMT_HEADER_ONLY
464
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700465} // namespace fmt
466
Ingo van Lilb4b13ee2015-11-02 12:34:46 +0100467#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +0000468# pragma warning(pop)
469#endif