blob: 524b229a262a0b58282434746dfa13a94e197972 [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 Zverovich3da71d52018-03-21 07:50:59 -07008#ifndef FMT_FORMAT_INL_H_
9#define FMT_FORMAT_INL_H_
10
Victor Zverovichf853d942018-01-20 10:28:10 -080011#include "format.h"
Victor Zverovichfbfedcf2013-01-14 15:16:20 -080012
Victor Zverovich859a4972014-04-30 06:55:21 -070013#include <string.h>
14
Victor Zverovich72f896d2012-12-12 09:17:28 -080015#include <cctype>
Victor Zverovich5d15bdd2014-07-01 16:23:50 -070016#include <cerrno>
Victor Zverovichf28645f2014-04-24 12:37:06 -070017#include <climits>
Victor Zverovich9ff3b972013-09-07 10:15:08 -070018#include <cmath>
Victor Zverovicha684d0c2013-12-27 08:00:10 -080019#include <cstdarg>
vitaut7dcf0512015-11-13 06:52:13 -080020#include <cstddef> // for std::ptrdiff_t
Victor Zverovich0de44a42018-08-26 08:12:35 -070021#include <cstring> // for std::memmove
Thomas Bernardabde38b2018-08-17 11:22:56 +020022#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
23# include <locale>
24#endif
Victor Zverovich9ff3b972013-09-07 10:15:08 -070025
vitaut24c309f2015-06-12 07:15:57 -070026#if FMT_USE_WINDOWS_H
Victor Zverovichc753a2a2018-01-28 20:26:25 -080027# if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)
28# define WIN32_LEAN_AND_MEAN
29# endif
vitaut67ce3942015-04-30 07:48:36 -070030# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
31# include <windows.h>
32# else
33# define NOMINMAX
34# include <windows.h>
35# undef NOMINMAX
36# endif
Ryuuke5a9dc8f2015-02-08 16:08:29 +000037#endif
38
Victor Zverovich8b76e972014-10-06 08:30:55 -070039#if FMT_EXCEPTIONS
40# define FMT_TRY try
41# define FMT_CATCH(x) catch (x)
42#else
43# define FMT_TRY if (true)
44# define FMT_CATCH(x) if (false)
45#endif
46
Ingo van Lilb4b13ee2015-11-02 12:34:46 +010047#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +000048# pragma warning(push)
Victor Zverovich8b76e972014-10-06 08:30:55 -070049# pragma warning(disable: 4127) // conditional expression is constant
Daniel.Perrybd0067e2014-11-25 18:01:09 -050050# pragma warning(disable: 4702) // unreachable code
vitautdf47d812015-03-16 18:53:14 -070051// Disable deprecation warning for strerror. The latter is not called but
52// MSVC fails to detect it.
53# pragma warning(disable: 4996)
jdale88a9862fd2014-03-11 18:56:24 +000054#endif
55
vitaut341b98c2015-03-14 13:39:33 -070056// Dummy implementations of strerror_r and strerror_s called if corresponding
57// system functions are not available.
Victor Zverovich6cb68f92018-02-10 06:28:33 -080058inline fmt::internal::null<> strerror_r(int, char *, ...) {
Victor Zverovichc333dca2017-02-19 08:41:38 -080059 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070060}
Victor Zverovich6cb68f92018-02-10 06:28:33 -080061inline fmt::internal::null<> strerror_s(char *, std::size_t, ...) {
Victor Zverovichc333dca2017-02-19 08:41:38 -080062 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070063}
64
Victor Zverovich838400d2018-05-12 08:33:51 -070065FMT_BEGIN_NAMESPACE
Victor Zverovichb26e76e2016-06-14 08:11:33 -070066
Victor Zverovich9ff3b972013-09-07 10:15:08 -070067namespace {
68
69#ifndef _MSC_VER
Victor Zverovichb9a568b2014-09-19 07:51:42 -070070# define FMT_SNPRINTF snprintf
Victor Zverovicha684d0c2013-12-27 08:00:10 -080071#else // _MSC_VER
Victor Zverovich406c6122014-08-19 08:47:38 -070072inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -080073 va_list args;
74 va_start(args, format);
75 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
76 va_end(args);
77 return result;
78}
Victor Zverovichb9a568b2014-09-19 07:51:42 -070079# define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -070080#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -080081
cstamford55836ca2015-03-10 07:04:31 +000082#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
83# define FMT_SWPRINTF snwprintf
84#else
85# define FMT_SWPRINTF swprintf
86#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
87
Victor Zverovichc2fecb92018-01-14 14:15:59 -080088typedef void (*FormatFunc)(internal::buffer &, int, string_view);
Victor Zverovich22f75d82014-09-03 08:03:05 -070089
Victor Zverovichf2c9df82014-09-05 08:44:41 -070090// Portable thread-safe version of strerror.
91// Sets buffer to point to a string describing the error code.
92// This can be either a pointer to a string stored in buffer,
93// or a pointer to some static immutable string.
94// Returns one of the following values:
95// 0 - success
96// ERANGE - buffer is not large enough to store the error message
97// other - failure
98// Buffer should be at least of size 1.
99int safe_strerror(
Carter Lie2583ab2015-02-14 09:58:29 +0800100 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
Victor Zverovich92a250f2018-02-07 07:16:00 -0800101 FMT_ASSERT(buffer != FMT_NULL && buffer_size != 0, "invalid buffer");
vitaut341b98c2015-03-14 13:39:33 -0700102
Victor Zverovich69823bf2018-05-19 08:57:31 -0700103 class dispatcher {
vitaut341b98c2015-03-14 13:39:33 -0700104 private:
105 int error_code_;
106 char *&buffer_;
107 std::size_t buffer_size_;
108
vitautda052ae2015-03-21 07:53:39 -0700109 // A noop assignment operator to avoid bogus warnings.
Victor Zverovich69823bf2018-05-19 08:57:31 -0700110 void operator=(const dispatcher &) {}
vitautda052ae2015-03-21 07:53:39 -0700111
vitaut341b98c2015-03-14 13:39:33 -0700112 // Handle the result of XSI-compliant version of strerror_r.
113 int handle(int result) {
vitaute1776ac2015-03-14 14:05:02 -0700114 // glibc versions before 2.13 return result in errno.
115 return result == -1 ? errno : result;
vitaut341b98c2015-03-14 13:39:33 -0700116 }
117
118 // Handle the result of GNU-specific version of strerror_r.
119 int handle(char *message) {
120 // If the buffer is full then the message is probably truncated.
121 if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
122 return ERANGE;
123 buffer_ = message;
124 return 0;
125 }
126
127 // Handle the case when strerror_r is not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800128 int handle(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700129 return fallback(strerror_s(buffer_, buffer_size_, error_code_));
130 }
131
132 // Fallback to strerror_s when strerror_r is not available.
133 int fallback(int result) {
134 // If the buffer is full then the message is probably truncated.
135 return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
136 ERANGE : result;
137 }
138
139 // Fallback to strerror if strerror_r and strerror_s are not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800140 int fallback(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700141 errno = 0;
142 buffer_ = strerror(error_code_);
143 return errno;
144 }
145
146 public:
Victor Zverovich69823bf2018-05-19 08:57:31 -0700147 dispatcher(int err_code, char *&buf, std::size_t buf_size)
Radu Popescu0affb232015-08-04 12:52:44 +0200148 : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
vitaut341b98c2015-03-14 13:39:33 -0700149
vitaut63f6c102015-06-14 09:36:23 -0700150 int run() {
vitaut63f6c102015-06-14 09:36:23 -0700151 return handle(strerror_r(error_code_, buffer_, buffer_size_));
152 }
vitaut341b98c2015-03-14 13:39:33 -0700153 };
Victor Zverovich69823bf2018-05-19 08:57:31 -0700154 return dispatcher(error_code, buffer, buffer_size).run();
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700155}
156
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800157void format_error_code(internal::buffer &out, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800158 string_view message) FMT_NOEXCEPT {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700159 // Report error code making sure that the output fits into
Victor Zverovichf1ede632018-03-04 10:33:42 -0800160 // inline_buffer_size to avoid dynamic memory allocation and potential
Victor Zverovich22f75d82014-09-03 08:03:05 -0700161 // bad_alloc.
Victor Zverovichf423e462017-03-11 07:43:26 -0800162 out.resize(0);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700163 static const char SEP[] = ": ";
vitaut1addec92015-03-21 20:16:36 -0700164 static const char ERROR_STR[] = "error ";
vitaut1addec92015-03-21 20:16:36 -0700165 // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
166 std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800167 typedef internal::int_traits<int>::main_type main_type;
168 main_type abs_value = static_cast<main_type>(error_code);
vitaut9d577ca2016-03-02 07:01:21 -0800169 if (internal::is_negative(error_code)) {
170 abs_value = 0 - abs_value;
171 ++error_code_size;
172 }
vitautbfdca8b2016-04-20 09:11:33 -0700173 error_code_size += internal::count_digits(abs_value);
Victor Zverovich217e7c72018-01-14 07:19:23 -0800174 writer w(out);
Victor Zverovichf1ede632018-03-04 10:33:42 -0800175 if (message.size() <= inline_buffer_size - error_code_size) {
Victor Zverovichfefaf072017-02-14 16:29:47 -0500176 w.write(message);
177 w.write(SEP);
Victor Zverovichec15ef72017-01-22 07:40:21 -0800178 }
Victor Zverovichfefaf072017-02-14 16:29:47 -0500179 w.write(ERROR_STR);
180 w.write(error_code);
Victor Zverovichf1ede632018-03-04 10:33:42 -0800181 assert(out.size() <= inline_buffer_size);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700182}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700183
vitautbfdca8b2016-04-20 09:11:33 -0700184void report_error(FormatFunc func, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800185 string_view message) FMT_NOEXCEPT {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800186 memory_buffer full_message;
Victor Zverovich88e0db82014-09-05 08:04:26 -0700187 func(full_message, error_code, message);
188 // Use Writer::data instead of Writer::c_str to avoid potential memory
189 // allocation.
190 std::fwrite(full_message.data(), full_message.size(), 1, stderr);
191 std::fputc('\n', stderr);
Victor Zverovichb605b392013-09-09 22:21:40 -0700192}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700193} // namespace
vitaut270069b2015-06-16 07:36:32 -0700194
Victor Zverovich38325242018-10-03 18:22:26 -0700195FMT_FUNC size_t internal::count_code_points(basic_string_view<char8_t> s) {
Victor Zverovichf8027412018-09-30 11:39:20 -0700196 const char8_t *data = s.data();
197 size_t num_code_points = 0;
198 for (size_t i = 0, size = s.size(); i != size; ++i) {
199 if ((data[i] & 0xc0) != 0x80)
200 ++num_code_points;
201 }
202 return num_code_points;
203}
204
Thomas Bernardabde38b2018-08-17 11:22:56 +0200205#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
Victor Zverovich6ebc1a92018-05-20 17:16:34 -0700206class locale {
207 private:
208 std::locale locale_;
209
210 public:
211 explicit locale(std::locale loc = std::locale()) : locale_(loc) {}
212 std::locale get() { return locale_; }
213};
214
Victor Zverovichf8027412018-09-30 11:39:20 -0700215namespace internal {
Victor Zverovich7f351de2017-12-03 09:18:06 -0800216template <typename Char>
Victor Zverovichf8027412018-09-30 11:39:20 -0700217FMT_FUNC Char thousands_sep(locale_provider *lp) {
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800218 std::locale loc = lp ? lp->locale().get() : std::locale();
219 return std::use_facet<std::numpunct<Char>>(loc).thousands_sep();
Victor Zverovich7f351de2017-12-03 09:18:06 -0800220}
Victor Zverovichf8027412018-09-30 11:39:20 -0700221template <> FMT_FUNC char8_t thousands_sep<char8_t>(locale_provider *) {
222 return static_cast<char8_t>(',');
223}
224}
Thomas Bernardabde38b2018-08-17 11:22:56 +0200225#else
226template <typename Char>
227FMT_FUNC Char internal::thousands_sep(locale_provider *lp) {
228 return FMT_STATIC_THOUSANDS_SEPARATOR;
229}
230#endif
Victor Zverovich7f351de2017-12-03 09:18:06 -0800231
Victor Zverovichc333dca2017-02-19 08:41:38 -0800232FMT_FUNC void system_error::init(
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800233 int err_code, string_view format_str, format_args args) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800234 error_code_ = err_code;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800235 memory_buffer buffer;
236 format_system_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700237 std::runtime_error &base = *this;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800238 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700239}
240
Victor Zverovichcd900972018-04-21 17:26:24 -0700241namespace internal {
Victor Zverovichb605b392013-09-09 22:21:40 -0700242template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700243int char_traits<char>::format_float(
Victor Zverovichb60a5c52018-05-28 20:16:30 -0700244 char *buffer, std::size_t size, const char *format, int precision, T value) {
Victor Zverovichb605b392013-09-09 22:21:40 -0700245 return precision < 0 ?
Victor Zverovichb60a5c52018-05-28 20:16:30 -0700246 FMT_SNPRINTF(buffer, size, format, value) :
247 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovichb605b392013-09-09 22:21:40 -0700248}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700249
Victor Zverovichb605b392013-09-09 22:21:40 -0700250template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700251int char_traits<wchar_t>::format_float(
Victor Zverovichb60a5c52018-05-28 20:16:30 -0700252 wchar_t *buffer, std::size_t size, const wchar_t *format, int precision,
253 T value) {
Victor Zverovichb605b392013-09-09 22:21:40 -0700254 return precision < 0 ?
Victor Zverovichb60a5c52018-05-28 20:16:30 -0700255 FMT_SWPRINTF(buffer, size, format, value) :
256 FMT_SWPRINTF(buffer, size, format, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700257}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800258
Victor Zverovich311251e2014-11-29 06:58:00 -0800259template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700260const char basic_data<T>::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800261 "0001020304050607080910111213141516171819"
262 "2021222324252627282930313233343536373839"
263 "4041424344454647484950515253545556575859"
264 "6061626364656667686970717273747576777879"
265 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800266
Victor Zverovichf1d85162014-02-19 13:02:22 -0800267#define FMT_POWERS_OF_10(factor) \
268 factor * 10, \
269 factor * 100, \
270 factor * 1000, \
271 factor * 10000, \
272 factor * 100000, \
273 factor * 1000000, \
274 factor * 10000000, \
275 factor * 100000000, \
276 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800277
Victor Zverovich311251e2014-11-29 06:58:00 -0800278template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700279const uint32_t basic_data<T>::POWERS_OF_10_32[] = {
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700280 1, FMT_POWERS_OF_10(1)
281};
282
283template <typename T>
284const uint32_t basic_data<T>::ZERO_OR_POWERS_OF_10_32[] = {
Victor Zverovich311251e2014-11-29 06:58:00 -0800285 0, FMT_POWERS_OF_10(1)
286};
287
288template <typename T>
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700289const uint64_t basic_data<T>::ZERO_OR_POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800290 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800291 FMT_POWERS_OF_10(1),
Victor Zverovich016aceb2017-08-26 09:09:43 -0700292 FMT_POWERS_OF_10(1000000000ull),
293 10000000000000000000ull
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800294};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800295
Victor Zverovich2768af22018-04-29 06:33:05 -0700296// Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.
297// These are generated by support/compute-powers.py.
298template <typename T>
299const uint64_t basic_data<T>::POW10_SIGNIFICANDS[] = {
Victor Zverovich9de31212018-08-15 06:54:43 -0700300 0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76,
301 0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df,
302 0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c,
303 0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5,
304 0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57,
305 0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7,
306 0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e,
307 0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996,
308 0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126,
309 0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053,
310 0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f,
311 0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b,
312 0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06,
313 0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb,
314 0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000,
315 0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984,
316 0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068,
317 0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8,
318 0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758,
319 0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85,
320 0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d,
321 0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25,
322 0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2,
323 0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a,
324 0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410,
325 0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129,
326 0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85,
327 0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841,
328 0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b,
Victor Zverovich2768af22018-04-29 06:33:05 -0700329};
330
331// Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding
332// to significands above.
333template <typename T>
334const int16_t basic_data<T>::POW10_EXPONENTS[] = {
335 -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954,
336 -927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661,
337 -635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369,
338 -343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77,
339 -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216,
340 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508,
341 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800,
342 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066
343};
344
Daniela Engert73c53d72018-09-17 18:21:24 +0200345template <typename T> const char basic_data<T>::FOREGROUND_COLOR[] = "\x1b[38;2;";
346template <typename T> const char basic_data<T>::BACKGROUND_COLOR[] = "\x1b[48;2;";
Dhruv Paranjapeec218a32018-06-28 10:43:00 +0530347template <typename T> const char basic_data<T>::RESET_COLOR[] = "\x1b[0m";
348template <typename T> const wchar_t basic_data<T>::WRESET_COLOR[] = L"\x1b[0m";
349
Victor Zverovichdd8c5ce2018-08-29 09:34:57 -0700350// A handmade floating-point number f * pow(2, e).
351class fp {
352 private:
353 typedef uint64_t significand_type;
354
355 // All sizes are in bits.
356 static FMT_CONSTEXPR_DECL const int char_size =
357 std::numeric_limits<unsigned char>::digits;
358 // Subtract 1 to account for an implicit most significant bit in the
359 // normalized form.
360 static FMT_CONSTEXPR_DECL const int double_significand_size =
361 std::numeric_limits<double>::digits - 1;
362 static FMT_CONSTEXPR_DECL const uint64_t implicit_bit =
363 1ull << double_significand_size;
364
365 public:
366 significand_type f;
367 int e;
368
369 static FMT_CONSTEXPR_DECL const int significand_size =
370 sizeof(significand_type) * char_size;
371
372 fp(): f(0), e(0) {}
373 fp(uint64_t f, int e): f(f), e(e) {}
374
375 // Constructs fp from an IEEE754 double. It is a template to prevent compile
376 // errors on platforms where double is not IEEE754.
377 template <typename Double>
378 explicit fp(Double d) {
379 // Assume double is in the format [sign][exponent][significand].
380 typedef std::numeric_limits<Double> limits;
medithe8cbfb6e2018-09-11 15:14:39 +0200381 const int double_size = static_cast<int>(sizeof(Double) * char_size);
Victor Zverovichdd8c5ce2018-08-29 09:34:57 -0700382 const int exponent_size =
383 double_size - double_significand_size - 1; // -1 for sign
384 const uint64_t significand_mask = implicit_bit - 1;
385 const uint64_t exponent_mask = (~0ull >> 1) & ~significand_mask;
386 const int exponent_bias = (1 << exponent_size) - limits::max_exponent - 1;
387 auto u = bit_cast<uint64_t>(d);
388 auto biased_e = (u & exponent_mask) >> double_significand_size;
389 f = u & significand_mask;
390 if (biased_e != 0)
391 f += implicit_bit;
392 else
393 biased_e = 1; // Subnormals use biased exponent 1 (min exponent).
394 e = static_cast<int>(biased_e - exponent_bias - double_significand_size);
395 }
396
397 // Normalizes the value converted from double and multiplied by (1 << SHIFT).
398 template <int SHIFT = 0>
399 void normalize() {
400 // Handle subnormals.
401 auto shifted_implicit_bit = implicit_bit << SHIFT;
402 while ((f & shifted_implicit_bit) == 0) {
403 f <<= 1;
404 --e;
405 }
406 // Subtract 1 to account for hidden bit.
407 auto offset = significand_size - double_significand_size - SHIFT - 1;
408 f <<= offset;
409 e -= offset;
410 }
411
412 // Compute lower and upper boundaries (m^- and m^+ in the Grisu paper), where
413 // a boundary is a value half way between the number and its predecessor
414 // (lower) or successor (upper). The upper boundary is normalized and lower
415 // has the same exponent but may be not normalized.
416 void compute_boundaries(fp &lower, fp &upper) const {
417 lower = f == implicit_bit ?
418 fp((f << 2) - 1, e - 2) : fp((f << 1) - 1, e - 1);
419 upper = fp((f << 1) + 1, e - 1);
420 upper.normalize<1>(); // 1 is to account for the exponent shift above.
421 lower.f <<= lower.e - upper.e;
422 lower.e = upper.e;
423 }
424};
425
426// Returns an fp number representing x - y. Result may not be normalized.
427inline fp operator-(fp x, fp y) {
428 FMT_ASSERT(x.f >= y.f && x.e == y.e, "invalid operands");
429 return fp(x.f - y.f, x.e);
430}
431
432// Computes an fp number r with r.f = x.f * y.f / pow(2, 64) rounded to nearest
433// with half-up tie breaking, r.e = x.e + y.e + 64. Result may not be normalized.
434FMT_API fp operator*(fp x, fp y);
435
436// Returns cached power (of 10) c_k = c_k.f * pow(2, c_k.e) such that its
437// (binary) exponent satisfies min_exponent <= c_k.e <= min_exponent + 3.
438FMT_API fp get_cached_power(int min_exponent, int &pow10_exponent);
439
Victor Zverovichcd900972018-04-21 17:26:24 -0700440FMT_FUNC fp operator*(fp x, fp y) {
441 // Multiply 32-bit parts of significands.
442 uint64_t mask = (1ULL << 32) - 1;
443 uint64_t a = x.f >> 32, b = x.f & mask;
444 uint64_t c = y.f >> 32, d = y.f & mask;
445 uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d;
446 // Compute mid 64-bit of result and round.
447 uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
Daniela Engert6cd66612018-04-30 10:07:43 +0200448 return fp(ac + (ad >> 32) + (bc >> 32) + (mid >> 32), x.e + y.e + 64);
Victor Zverovichcd900972018-04-21 17:26:24 -0700449}
Victor Zverovich468c2432018-05-27 10:57:26 -0700450
451FMT_FUNC fp get_cached_power(int min_exponent, int &pow10_exponent) {
452 const double one_over_log2_10 = 0.30102999566398114; // 1 / log2(10)
453 int index = static_cast<int>(std::ceil(
Victor Zverovich4e4b8572018-05-28 11:25:07 -0700454 (min_exponent + fp::significand_size - 1) * one_over_log2_10));
Victor Zverovich468c2432018-05-27 10:57:26 -0700455 // Decimal exponent of the first (smallest) cached power of 10.
456 const int first_dec_exp = -348;
Victor Zverovich9de31212018-08-15 06:54:43 -0700457 // Difference between 2 consecutive decimal exponents in cached powers of 10.
Victor Zverovich468c2432018-05-27 10:57:26 -0700458 const int dec_exp_step = 8;
459 index = (index - first_dec_exp - 1) / dec_exp_step + 1;
460 pow10_exponent = first_dec_exp + index * dec_exp_step;
461 return fp(data::POW10_SIGNIFICANDS[index], data::POW10_EXPONENTS[index]);
462}
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700463
Victor Zverovich50b18a32018-10-13 22:14:36 -0700464FMT_FUNC bool grisu2_round(
465 char *buffer, size_t &size, size_t max_digits, uint64_t delta,
466 uint64_t remainder, uint64_t exp, uint64_t diff, int &exp10) {
Victor Zverovich69929752018-10-13 07:44:34 -0700467 while (remainder < diff && delta - remainder >= exp &&
468 (remainder + exp < diff || diff - remainder > remainder + exp - diff)) {
469 --buffer[size - 1];
470 remainder += exp;
471 }
Victor Zverovich50b18a32018-10-13 22:14:36 -0700472 if (size > max_digits) {
473 --size;
474 ++exp10;
475 if (buffer[size] >= '5')
476 return false;
477 }
478 return true;
Victor Zverovich69929752018-10-13 07:44:34 -0700479}
480
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700481// Generates output using Grisu2 digit-gen algorithm.
Victor Zverovich50b18a32018-10-13 22:14:36 -0700482FMT_FUNC bool grisu2_gen_digits(
483 char *buffer, size_t &size, uint32_t hi, uint64_t lo, int &exp,
484 uint64_t delta, const fp &one, const fp &diff, size_t max_digits) {
Victor Zverovich69929752018-10-13 07:44:34 -0700485 // Generate digits for the most significant part (hi).
Victor Zverovich0de44a42018-08-26 08:12:35 -0700486 while (exp > 0) {
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700487 uint32_t digit = 0;
488 // This optimization by miloyip reduces the number of integer divisions by
489 // one per iteration.
Victor Zverovich0de44a42018-08-26 08:12:35 -0700490 switch (exp) {
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700491 case 10: digit = hi / 1000000000; hi %= 1000000000; break;
492 case 9: digit = hi / 100000000; hi %= 100000000; break;
493 case 8: digit = hi / 10000000; hi %= 10000000; break;
494 case 7: digit = hi / 1000000; hi %= 1000000; break;
495 case 6: digit = hi / 100000; hi %= 100000; break;
496 case 5: digit = hi / 10000; hi %= 10000; break;
497 case 4: digit = hi / 1000; hi %= 1000; break;
498 case 3: digit = hi / 100; hi %= 100; break;
499 case 2: digit = hi / 10; hi %= 10; break;
500 case 1: digit = hi; hi = 0; break;
501 default:
502 FMT_ASSERT(false, "invalid number of digits");
503 }
504 if (digit != 0 || size != 0)
medithe95a71892018-08-29 15:38:56 +0200505 buffer[size++] = static_cast<char>('0' + digit);
Victor Zverovich0de44a42018-08-26 08:12:35 -0700506 --exp;
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700507 uint64_t remainder = (static_cast<uint64_t>(hi) << -one.e) + lo;
Victor Zverovich50b18a32018-10-13 22:14:36 -0700508 if (remainder <= delta || size > max_digits) {
509 return grisu2_round(
510 buffer, size, max_digits, delta, remainder,
511 static_cast<uint64_t>(data::POWERS_OF_10_32[exp]) << -one.e,
512 diff.f, exp);
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700513 }
514 }
Victor Zverovich69929752018-10-13 07:44:34 -0700515 // Generate digits for the least significant part (lo).
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700516 for (;;) {
517 lo *= 10;
518 delta *= 10;
519 char digit = static_cast<char>(lo >> -one.e);
520 if (digit != 0 || size != 0)
medithe95a71892018-08-29 15:38:56 +0200521 buffer[size++] = static_cast<char>('0' + digit);
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700522 lo &= one.f - 1;
Victor Zverovich0de44a42018-08-26 08:12:35 -0700523 --exp;
Victor Zverovich50b18a32018-10-13 22:14:36 -0700524 if (lo < delta || size > max_digits) {
525 return grisu2_round(buffer, size, max_digits, delta, lo, one.f,
526 diff.f * data::POWERS_OF_10_32[-exp], exp);
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700527 }
528 }
529}
530
Victor Zverovich69929752018-10-13 07:44:34 -0700531// Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700532FMT_FUNC char *write_exponent(char *buffer, int exp) {
533 FMT_ASSERT(-1000 < exp && exp < 1000, "exponent out of range");
534 if (exp < 0) {
535 *buffer++ = '-';
536 exp = -exp;
537 } else {
538 *buffer++ = '+';
539 }
540 if (exp >= 100) {
541 *buffer++ = static_cast<char>('0' + exp / 100);
542 exp %= 100;
543 const char *d = data::DIGITS + exp * 2;
544 *buffer++ = d[0];
545 *buffer++ = d[1];
546 } else {
547 const char *d = data::DIGITS + exp * 2;
548 *buffer++ = d[0];
549 *buffer++ = d[1];
550 }
551 return buffer;
552}
553
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700554#if FMT_CLANG_VERSION
555# define FMT_FALLTHROUGH [[clang::fallthrough]];
medithe981797f2018-09-07 17:53:15 +0200556#elif FMT_GCC_VERSION >= 700
557# define FMT_FALLTHROUGH [[gnu::fallthrough]];
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700558#else
559# define FMT_FALLTHROUGH
560#endif
Victor Zveroviche483a012018-08-26 09:51:49 -0700561
Victor Zverovich50b18a32018-10-13 22:14:36 -0700562struct gen_digits_params {
563 unsigned min_digits;
564 unsigned max_digits;
565 bool fixed;
566 bool upper;
567 bool trailing_zeros;
568
569 // Creates digit generation parameters from format specifiers for a number in
570 // the range [pow(10, exp - 1), pow(10, exp) or 0 if exp == 1.
571 gen_digits_params(const grisu2_specs &specs, int exp)
572 : min_digits(specs.precision >= 0 ? to_unsigned(specs.precision) : 6),
573 fixed(false), upper(false), trailing_zeros(false) {
574 switch (specs.type) {
575 case 'G':
576 upper = true;
577 FMT_FALLTHROUGH
578 case '\0': case 'g':
579 trailing_zeros = (specs.flags & HASH_FLAG) != 0;
580 if (-4 <= exp && exp < static_cast<int>(min_digits) + 1) {
581 fixed = true;
582 if (!specs.type && trailing_zeros && exp >= 0)
583 min_digits = to_unsigned(exp) + 1;
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700584 }
Victor Zverovich50b18a32018-10-13 22:14:36 -0700585 break;
586 case 'F':
587 upper = true;
588 FMT_FALLTHROUGH
589 case 'f': {
590 fixed = true;
591 trailing_zeros = true;
592 int adjusted_min_digits = static_cast<int>(min_digits) + exp;
593 if (adjusted_min_digits > 0)
594 min_digits = to_unsigned(adjusted_min_digits);
595 break;
Victor Zverovichdd8c5ce2018-08-29 09:34:57 -0700596 }
Victor Zverovich50b18a32018-10-13 22:14:36 -0700597 case 'E':
598 upper = true;
599 FMT_FALLTHROUGH
600 case 'e':
601 ++min_digits;
602 break;
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700603 }
Victor Zverovich50b18a32018-10-13 22:14:36 -0700604 max_digits = min_digits;
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700605 }
Victor Zverovich50b18a32018-10-13 22:14:36 -0700606};
607
608// The number is given as v = buffer * pow(10, exp).
609FMT_FUNC void format_float(char *buffer, size_t &size, int exp,
610 const gen_digits_params &params) {
611 if (!params.fixed) {
612 // Insert a decimal point after the first digit and add an exponent.
613 std::memmove(buffer + 2, buffer + 1, size - 1);
614 buffer[1] = '.';
615 exp += static_cast<int>(size) - 1;
616 if (size < params.min_digits) {
617 std::uninitialized_fill_n(buffer + size + 1,
618 params.min_digits - size, '0');
619 size = params.min_digits;
620 }
621 char *p = buffer + size + 1;
622 *p++ = params.upper ? 'E' : 'e';
623 size = to_unsigned(write_exponent(p, exp) - buffer);
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700624 return;
625 }
Victor Zverovich50b18a32018-10-13 22:14:36 -0700626 // pow(10, full_exp - 1) <= v <= pow(10, full_exp).
627 int int_size = static_cast<int>(size);
628 int full_exp = int_size + exp;
629 const int exp_threshold = 21;
630 if (int_size <= full_exp && full_exp <= exp_threshold) {
631 // 1234e7 -> 12340000000[.0+]
632 std::uninitialized_fill_n(buffer + int_size, full_exp - int_size, '0');
633 char *p = buffer + full_exp;
634 int num_zeros = static_cast<int>(params.min_digits) - full_exp;
635 if (num_zeros > 0 && params.trailing_zeros) {
636 *p++ = '.';
637 std::uninitialized_fill_n(p, num_zeros, '0');
638 p += num_zeros;
639 }
640 size = to_unsigned(p - buffer);
641 } else if (full_exp > 0) {
642 // 1234e-2 -> 12.34[0+]
643 int fractional_size = -exp;
644 std::memmove(buffer + full_exp + 1, buffer + full_exp,
645 to_unsigned(fractional_size));
646 buffer[full_exp] = '.';
647 ++size;
648 if (!params.trailing_zeros) {
649 // Remove trailing zeros.
650 while (buffer[size - 1] == '0') --size;
651 } else if (params.min_digits >= size) {
652 // Add trailing zeros.
653 size_t num_zeros = params.min_digits - size + 1;
654 std::uninitialized_fill_n(buffer + size, num_zeros, '0');
655 size += to_unsigned(num_zeros);
656 }
657 } else {
658 // 1234e-6 -> 0.001234
659 int offset = 2 - full_exp;
660 std::memmove(buffer + offset, buffer, size);
661 buffer[0] = '0';
662 buffer[1] = '.';
663 std::uninitialized_fill_n(buffer + 2, -full_exp, '0');
664 size = to_unsigned(int_size + offset);
665 }
666}
667
668template <typename Double>
669FMT_FUNC typename std::enable_if<sizeof(Double) == sizeof(uint64_t), bool>::type
670 grisu2_format(Double value, char *buffer, size_t &size,
671 grisu2_specs specs) {
672 FMT_ASSERT(value >= 0, "value is negative");
673 if (value == 0) {
674 gen_digits_params params(specs, 1);
675 *buffer = '0';
676 size = 1;
677 format_float(buffer, size, 0, params);
678 return true;
679 }
680
681 fp fp_value(value);
682 fp lower, upper; // w^- and w^+ in the Grisu paper.
683 fp_value.compute_boundaries(lower, upper);
684
685 // Find a cached power of 10 close to 1 / upper and use it to scale upper.
686 const int min_exp = -60; // alpha in Grisu.
687 int cached_exp = 0; // K in Grisu.
688 auto cached_pow = get_cached_power( // \tilde{c}_{-k} in Grisu.
689 min_exp - (upper.e + fp::significand_size), cached_exp);
690 cached_exp = -cached_exp;
691 upper = upper * cached_pow; // \tilde{M}^+ in Grisu.
692 --upper.f; // \tilde{M}^+ - 1 ulp -> M^+_{\downarrow}.
693 fp one(1ull << -upper.e, upper.e);
694 // hi (p1 in Grisu) contains the most significant digits of scaled_upper.
695 // hi = floor(upper / one).
696 uint32_t hi = static_cast<uint32_t>(upper.f >> -one.e);
697 int exp = static_cast<int>(count_digits(hi)); // kappa in Grisu.
698 gen_digits_params params(specs, cached_exp + exp);
699 fp_value.normalize();
700 fp scaled_value = fp_value * cached_pow;
701 lower = lower * cached_pow; // \tilde{M}^- in Grisu.
702 ++lower.f; // \tilde{M}^- + 1 ulp -> M^-_{\uparrow}.
703 uint64_t delta = upper.f - lower.f;
704 fp diff = upper - scaled_value; // wp_w in Grisu.
705 // lo (p2 in Grisu) contains the least significants digits of scaled_upper.
706 // lo = supper % one.
707 uint64_t lo = upper.f & (one.f - 1);
708 size = 0;
709 if (!grisu2_gen_digits(buffer, size, hi, lo, exp, delta, one, diff,
710 params.max_digits)) {
711 return false;
712 }
713 format_float(buffer, size, cached_exp + exp, params);
714 return true;
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700715}
Victor Zverovichcd900972018-04-21 17:26:24 -0700716} // namespace internal
717
vitaut24c309f2015-06-12 07:15:57 -0700718#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700719
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800720FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
Victor Zverovichdff21372014-12-16 07:01:01 -0800721 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
vitautc3ba6152015-08-07 07:34:58 -0700722 if (s.size() > INT_MAX)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800723 FMT_THROW(windows_error(ERROR_INVALID_PARAMETER, ERROR_MSG));
vitautc3ba6152015-08-07 07:34:58 -0700724 int s_size = static_cast<int>(s.size());
Vasili Galkaacb469a2018-03-12 14:43:29 +0200725 if (s_size == 0) {
726 // MultiByteToWideChar does not support zero length, handle separately.
727 buffer_.resize(1);
728 buffer_[0] = 0;
729 return;
730 }
731
vitautc3ba6152015-08-07 07:34:58 -0700732 int length = MultiByteToWideChar(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800733 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700734 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800735 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700736 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700737 length = MultiByteToWideChar(
vitautc3ba6152015-08-07 07:34:58 -0700738 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700739 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800740 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700741 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700742}
743
Victor Zverovichc333dca2017-02-19 08:41:38 -0800744FMT_FUNC internal::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700745 if (int error_code = convert(s)) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800746 FMT_THROW(windows_error(error_code,
Victor Zverovich8b76e972014-10-06 08:30:55 -0700747 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700748 }
749}
750
Victor Zverovichc333dca2017-02-19 08:41:38 -0800751FMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) {
vitautca747812015-08-07 07:08:46 -0700752 if (s.size() > INT_MAX)
753 return ERROR_INVALID_PARAMETER;
754 int s_size = static_cast<int>(s.size());
Vasili Galkaacb469a2018-03-12 14:43:29 +0200755 if (s_size == 0) {
756 // WideCharToMultiByte does not support zero length, handle separately.
757 buffer_.resize(1);
758 buffer_[0] = 0;
759 return 0;
760 }
761
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800762 int length = WideCharToMultiByte(
763 CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700764 if (length == 0)
765 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700766 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700767 length = WideCharToMultiByte(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800768 CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700769 if (length == 0)
770 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700771 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700772 return 0;
773}
774
Victor Zverovichc333dca2017-02-19 08:41:38 -0800775FMT_FUNC void windows_error::init(
Victor Zverovich7f351de2017-12-03 09:18:06 -0800776 int err_code, string_view format_str, format_args args) {
Carter Li3f574c12015-02-17 10:11:42 +0800777 error_code_ = err_code;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800778 memory_buffer buffer;
Victor Zveroviche022c212017-02-17 06:38:53 -0800779 internal::format_windows_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700780 std::runtime_error &base = *this;
Victor Zveroviche022c212017-02-17 06:38:53 -0800781 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700782}
783
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700784FMT_FUNC void internal::format_windows_error(
Victor Zverovichf6fd38b2018-01-15 08:22:31 -0800785 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700786 FMT_TRY {
Victor Zverovichc0954452018-01-06 09:09:50 -0800787 wmemory_buffer buf;
Victor Zverovichf1ede632018-03-04 10:33:42 -0800788 buf.resize(inline_buffer_size);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800789 for (;;) {
Victor Zverovichc0954452018-01-06 09:09:50 -0800790 wchar_t *system_message = &buf[0];
Victor Zverovichf85d5f42016-10-22 08:04:20 -0700791 int result = FormatMessageW(
792 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800793 FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
794 system_message, static_cast<uint32_t>(buf.size()), FMT_NULL);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800795 if (result != 0) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800796 utf16_to_utf8 utf8_message;
Michael Winterberg2a05a872016-03-02 17:35:34 -0800797 if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800798 writer w(out);
Victor Zveroviche022c212017-02-17 06:38:53 -0800799 w.write(message);
800 w.write(": ");
801 w.write(utf8_message);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800802 return;
803 }
804 break;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700805 }
Michael Winterberg2a05a872016-03-02 17:35:34 -0800806 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
807 break; // Can't get error message, report error code instead.
Victor Zverovichc0954452018-01-06 09:09:50 -0800808 buf.resize(buf.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700809 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700810 } FMT_CATCH(...) {}
Victor Zverovichc0954452018-01-06 09:09:50 -0800811 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700812}
vitaut24c309f2015-06-12 07:15:57 -0700813
814#endif // FMT_USE_WINDOWS_H
815
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700816FMT_FUNC void format_system_error(
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800817 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
vitaut24c309f2015-06-12 07:15:57 -0700818 FMT_TRY {
Victor Zverovich36634142017-12-26 09:00:22 -0800819 memory_buffer buf;
Victor Zverovichf1ede632018-03-04 10:33:42 -0800820 buf.resize(inline_buffer_size);
vitaut24c309f2015-06-12 07:15:57 -0700821 for (;;) {
Victor Zverovich36634142017-12-26 09:00:22 -0800822 char *system_message = &buf[0];
823 int result = safe_strerror(error_code, system_message, buf.size());
vitaut24c309f2015-06-12 07:15:57 -0700824 if (result == 0) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800825 writer w(out);
Victor Zverovichfefaf072017-02-14 16:29:47 -0500826 w.write(message);
827 w.write(": ");
828 w.write(system_message);
vitaut24c309f2015-06-12 07:15:57 -0700829 return;
830 }
831 if (result != ERANGE)
832 break; // Can't get error message, report error code instead.
Victor Zverovich36634142017-12-26 09:00:22 -0800833 buf.resize(buf.size() * 2);
vitaut24c309f2015-06-12 07:15:57 -0700834 }
835 } FMT_CATCH(...) {}
Victor Zverovichf164e4c2018-02-01 16:49:47 -0800836 format_error_code(out, error_code, message);
vitaut24c309f2015-06-12 07:15:57 -0700837}
Victor Zverovich53b4c312014-04-30 15:00:41 -0700838
Abdó Roig-Marangesaf0f21d2017-12-09 16:50:53 +0100839FMT_FUNC void internal::error_handler::on_error(const char *message) {
Victor Zverovich94edb1a2017-12-06 07:42:42 -0800840 FMT_THROW(format_error(message));
841}
842
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700843FMT_FUNC void report_system_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800844 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700845 report_error(format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700846}
847
vitaut24c309f2015-06-12 07:15:57 -0700848#if FMT_USE_WINDOWS_H
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700849FMT_FUNC void report_windows_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800850 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700851 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700852}
Victor Zverovich400812a2014-04-30 12:38:17 -0700853#endif
Victor Zverovichf7939862014-04-30 10:18:11 -0700854
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800855FMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800856 memory_buffer buffer;
Victor Zverovich38325242018-10-03 18:22:26 -0700857 vformat_to(buffer, format_str,
858 basic_format_args<buffer_context<char>::type>(args));
Victor Zverovichfefaf072017-02-14 16:29:47 -0500859 std::fwrite(buffer.data(), 1, buffer.size(), f);
Victor Zverovichd5b81962014-06-28 21:56:40 -0700860}
861
Daniela Engert2570f1a2018-04-26 20:32:14 +0200862FMT_FUNC void vprint(std::FILE *f, wstring_view format_str, wformat_args args) {
863 wmemory_buffer buffer;
864 vformat_to(buffer, format_str, args);
865 std::fwrite(buffer.data(), sizeof(wchar_t), buffer.size(), f);
866}
867
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800868FMT_FUNC void vprint(string_view format_str, format_args args) {
Victor Zverovich0028ce52016-08-26 17:23:13 -0700869 vprint(stdout, format_str, args);
Victor Zverovich163178e2014-09-25 07:08:25 -0700870}
871
Daniela Engert2570f1a2018-04-26 20:32:14 +0200872FMT_FUNC void vprint(wstring_view format_str, wformat_args args) {
873 vprint(stdout, format_str, args);
874}
875
Thomas Bernardabde38b2018-08-17 11:22:56 +0200876#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800877FMT_FUNC locale locale_provider::locale() { return fmt::locale(); }
Thomas Bernardabde38b2018-08-17 11:22:56 +0200878#endif
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800879
Victor Zverovich838400d2018-05-12 08:33:51 -0700880FMT_END_NAMESPACE
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700881
Ingo van Lilb4b13ee2015-11-02 12:34:46 +0100882#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +0000883# pragma warning(pop)
884#endif
Victor Zverovich3da71d52018-03-21 07:50:59 -0700885
886#endif // FMT_FORMAT_INL_H_