blob: ee2f83de514379e0d24ab235cb72799c91483d88 [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 Zverovich69929752018-10-13 07:44:34 -0700464FMT_FUNC void grisu2_round(char *buffer, size_t size, uint64_t delta,
465 uint64_t remainder, uint64_t exp, uint64_t diff) {
466 while (remainder < diff && delta - remainder >= exp &&
467 (remainder + exp < diff || diff - remainder > remainder + exp - diff)) {
468 --buffer[size - 1];
469 remainder += exp;
470 }
471}
472
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700473// Generates output using Grisu2 digit-gen algorithm.
474FMT_FUNC void grisu2_gen_digits(
475 const fp &scaled_value, const fp &scaled_upper, uint64_t delta,
476 char *buffer, size_t &size, int &dec_exp) {
477 internal::fp one(1ull << -scaled_upper.e, scaled_upper.e);
Victor Zverovich69929752018-10-13 07:44:34 -0700478 internal::fp diff = scaled_upper - scaled_value; // wp_w in Grisu.
Victor Zverovich0de44a42018-08-26 08:12:35 -0700479 // hi (p1 in Grisu) contains the most significant digits of scaled_upper.
480 // hi = floor(scaled_upper / one).
481 uint32_t hi = static_cast<uint32_t>(scaled_upper.f >> -one.e);
482 // lo (p2 in Grisu) contains the least significants digits of scaled_upper.
Victor Zverovich69929752018-10-13 07:44:34 -0700483 // lo = scaled_upper % one.
Victor Zverovich0de44a42018-08-26 08:12:35 -0700484 uint64_t lo = scaled_upper.f & (one.f - 1);
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700485 size = 0;
Victor Zverovich0de44a42018-08-26 08:12:35 -0700486 auto exp = count_digits(hi); // kappa in Grisu.
Victor Zverovich69929752018-10-13 07:44:34 -0700487 // Generate digits for the most significant part (hi).
Victor Zverovich0de44a42018-08-26 08:12:35 -0700488 while (exp > 0) {
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700489 uint32_t digit = 0;
490 // This optimization by miloyip reduces the number of integer divisions by
491 // one per iteration.
Victor Zverovich0de44a42018-08-26 08:12:35 -0700492 switch (exp) {
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700493 case 10: digit = hi / 1000000000; hi %= 1000000000; break;
494 case 9: digit = hi / 100000000; hi %= 100000000; break;
495 case 8: digit = hi / 10000000; hi %= 10000000; break;
496 case 7: digit = hi / 1000000; hi %= 1000000; break;
497 case 6: digit = hi / 100000; hi %= 100000; break;
498 case 5: digit = hi / 10000; hi %= 10000; break;
499 case 4: digit = hi / 1000; hi %= 1000; break;
500 case 3: digit = hi / 100; hi %= 100; break;
501 case 2: digit = hi / 10; hi %= 10; break;
502 case 1: digit = hi; hi = 0; break;
503 default:
504 FMT_ASSERT(false, "invalid number of digits");
505 }
506 if (digit != 0 || size != 0)
medithe95a71892018-08-29 15:38:56 +0200507 buffer[size++] = static_cast<char>('0' + digit);
Victor Zverovich0de44a42018-08-26 08:12:35 -0700508 --exp;
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700509 uint64_t remainder = (static_cast<uint64_t>(hi) << -one.e) + lo;
510 if (remainder <= delta) {
Victor Zverovich0de44a42018-08-26 08:12:35 -0700511 dec_exp += exp;
Victor Zverovich69929752018-10-13 07:44:34 -0700512 grisu2_round(buffer, size, delta, remainder,
513 static_cast<uint64_t>(data::POWERS_OF_10_32[exp]) << -one.e,
514 diff.f);
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700515 return;
516 }
517 }
Victor Zverovich69929752018-10-13 07:44:34 -0700518 // Generate digits for the least significant part (lo).
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700519 for (;;) {
520 lo *= 10;
521 delta *= 10;
522 char digit = static_cast<char>(lo >> -one.e);
523 if (digit != 0 || size != 0)
medithe95a71892018-08-29 15:38:56 +0200524 buffer[size++] = static_cast<char>('0' + digit);
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700525 lo &= one.f - 1;
Victor Zverovich0de44a42018-08-26 08:12:35 -0700526 --exp;
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700527 if (lo < delta) {
Victor Zverovich0de44a42018-08-26 08:12:35 -0700528 dec_exp += exp;
Victor Zverovich69929752018-10-13 07:44:34 -0700529 grisu2_round(buffer, size, delta, lo, one.f,
530 diff.f * data::POWERS_OF_10_32[-exp]);
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700531 return;
532 }
533 }
534}
535
Victor Zverovichd7f17612018-09-26 08:45:34 -0700536template <typename Double>
537FMT_FUNC void grisu2_format_positive(Double value, char *buffer, size_t &size,
Victor Zverovichdd8c5ce2018-08-29 09:34:57 -0700538 int &dec_exp) {
539 FMT_ASSERT(value > 0, "value is nonpositive");
540 fp fp_value(value);
541 fp lower, upper; // w^- and w^+ in the Grisu paper.
542 fp_value.compute_boundaries(lower, upper);
543 // Find a cached power of 10 close to 1 / upper.
544 const int min_exp = -60; // alpha in Grisu.
545 auto dec_pow = get_cached_power( // \tilde{c}_{-k} in Grisu.
546 min_exp - (upper.e + fp::significand_size), dec_exp);
547 dec_exp = -dec_exp;
548 fp_value.normalize();
549 fp scaled_value = fp_value * dec_pow;
550 fp scaled_lower = lower * dec_pow; // \tilde{M}^- in Grisu.
551 fp scaled_upper = upper * dec_pow; // \tilde{M}^+ in Grisu.
552 ++scaled_lower.f; // \tilde{M}^- + 1 ulp -> M^-_{\uparrow}.
553 --scaled_upper.f; // \tilde{M}^+ - 1 ulp -> M^+_{\downarrow}.
554 uint64_t delta = scaled_upper.f - scaled_lower.f;
555 grisu2_gen_digits(scaled_value, scaled_upper, delta, buffer, size, dec_exp);
556}
557
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700558FMT_FUNC void round(char *buffer, size_t &size, int &exp,
559 int digits_to_remove) {
560 size -= to_unsigned(digits_to_remove);
561 exp += digits_to_remove;
562 int digit = buffer[size] - '0';
563 // TODO: proper rounding and carry
564 if (digit > 5 || (digit == 5 && (digits_to_remove > 1 ||
565 (buffer[size - 1] - '0') % 2) != 0)) {
566 ++buffer[size - 1];
567 }
568}
569
Victor Zverovich69929752018-10-13 07:44:34 -0700570// Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700571FMT_FUNC char *write_exponent(char *buffer, int exp) {
572 FMT_ASSERT(-1000 < exp && exp < 1000, "exponent out of range");
573 if (exp < 0) {
574 *buffer++ = '-';
575 exp = -exp;
576 } else {
577 *buffer++ = '+';
578 }
579 if (exp >= 100) {
580 *buffer++ = static_cast<char>('0' + exp / 100);
581 exp %= 100;
582 const char *d = data::DIGITS + exp * 2;
583 *buffer++ = d[0];
584 *buffer++ = d[1];
585 } else {
586 const char *d = data::DIGITS + exp * 2;
587 *buffer++ = d[0];
588 *buffer++ = d[1];
589 }
590 return buffer;
591}
592
593FMT_FUNC void format_exp_notation(
594 char *buffer, size_t &size, int exp, int precision, bool upper) {
595 // Insert a decimal point after the first digit and add an exponent.
596 std::memmove(buffer + 2, buffer + 1, size - 1);
597 buffer[1] = '.';
598 exp += static_cast<int>(size) - 1;
599 int num_digits = precision - static_cast<int>(size) + 1;
600 if (num_digits > 0) {
601 std::uninitialized_fill_n(buffer + size + 1, num_digits, '0');
602 size += to_unsigned(num_digits);
603 } else if (num_digits < 0) {
604 round(buffer, size, exp, -num_digits);
605 }
606 char *p = buffer + size + 1;
607 *p++ = upper ? 'E' : 'e';
608 size = to_unsigned(write_exponent(p, exp) - buffer);
609}
610
Victor Zverovich0de44a42018-08-26 08:12:35 -0700611// Prettifies the output of the Grisu2 algorithm.
612// The number is given as v = buffer * 10^exp.
Victor Zverovichdd8c5ce2018-08-29 09:34:57 -0700613FMT_FUNC void grisu2_prettify(char *buffer, size_t &size, int exp,
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700614 int precision, bool upper) {
Victor Zverovichdd8c5ce2018-08-29 09:34:57 -0700615 // pow(10, full_exp - 1) <= v <= pow(10, full_exp).
Victor Zveroviche483a012018-08-26 09:51:49 -0700616 int int_size = static_cast<int>(size);
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700617 int full_exp = int_size + exp;
Victor Zverovichdd8c5ce2018-08-29 09:34:57 -0700618 const int exp_threshold = 21;
619 if (int_size <= full_exp && full_exp <= exp_threshold) {
620 // 1234e7 -> 12340000000[.0+]
Victor Zveroviche483a012018-08-26 09:51:49 -0700621 std::uninitialized_fill_n(buffer + int_size, full_exp - int_size, '0');
622 char *p = buffer + full_exp;
Victor Zverovichdd8c5ce2018-08-29 09:34:57 -0700623 if (precision > 0) {
Victor Zveroviche483a012018-08-26 09:51:49 -0700624 *p++ = '.';
Victor Zverovichdd8c5ce2018-08-29 09:34:57 -0700625 std::uninitialized_fill_n(p, precision, '0');
626 p += precision;
Victor Zveroviche483a012018-08-26 09:51:49 -0700627 }
628 size = to_unsigned(p - buffer);
Victor Zverovichdd8c5ce2018-08-29 09:34:57 -0700629 } else if (0 < full_exp && full_exp <= exp_threshold) {
630 // 1234e-2 -> 12.34[0+]
631 int fractional_size = -exp;
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700632 std::memmove(buffer + full_exp + 1, buffer + full_exp,
633 to_unsigned(fractional_size));
Victor Zveroviche483a012018-08-26 09:51:49 -0700634 buffer[full_exp] = '.';
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700635 int num_zeros = precision - fractional_size;
636 if (num_zeros > 0) {
Victor Zveroviche483a012018-08-26 09:51:49 -0700637 std::uninitialized_fill_n(buffer + size + 1, num_zeros, '0');
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700638 size += to_unsigned(num_zeros);
Victor Zveroviche483a012018-08-26 09:51:49 -0700639 }
640 ++size;
641 } else if (-6 < full_exp && full_exp <= 0) {
642 // 1234e-6 -> 0.001234
643 int offset = 2 - full_exp;
644 std::memmove(buffer + offset, buffer, size);
645 buffer[0] = '0';
646 buffer[1] = '.';
647 std::uninitialized_fill_n(buffer + 2, -full_exp, '0');
648 size = to_unsigned(int_size + offset);
649 } else {
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700650 format_exp_notation(buffer, size, exp, precision, upper);
Victor Zveroviche483a012018-08-26 09:51:49 -0700651 }
Victor Zverovich0de44a42018-08-26 08:12:35 -0700652}
653
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700654#if FMT_CLANG_VERSION
655# define FMT_FALLTHROUGH [[clang::fallthrough]];
medithe981797f2018-09-07 17:53:15 +0200656#elif FMT_GCC_VERSION >= 700
657# define FMT_FALLTHROUGH [[gnu::fallthrough]];
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700658#else
659# define FMT_FALLTHROUGH
660#endif
Victor Zveroviche483a012018-08-26 09:51:49 -0700661
Victor Zverovichdd8c5ce2018-08-29 09:34:57 -0700662// Formats a nonnegative value using Grisu2 algorithm. Grisu2 doesn't give any
663// guarantees on the shortness of the result.
Victor Zverovichd7f17612018-09-26 08:45:34 -0700664template <typename Double>
665FMT_FUNC typename std::enable_if<sizeof(Double) == sizeof(uint64_t)>::type
666 grisu2_format(Double value, char *buffer, size_t &size, char type,
667 int precision, bool write_decimal_point) {
Victor Zveroviche483a012018-08-26 09:51:49 -0700668 FMT_ASSERT(value >= 0, "value is negative");
669 int dec_exp = 0; // K in Grisu.
670 if (value > 0) {
671 grisu2_format_positive(value, buffer, size, dec_exp);
672 } else {
673 *buffer = '0';
674 size = 1;
675 }
Victor Zverovichdd8c5ce2018-08-29 09:34:57 -0700676 const int default_precision = 6;
677 if (precision < 0)
678 precision = default_precision;
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700679 bool upper = false;
680 switch (type) {
681 case 'G':
682 upper = true;
683 FMT_FALLTHROUGH
684 case '\0': case 'g': {
685 int digits_to_remove = static_cast<int>(size) - precision;
686 if (digits_to_remove > 0) {
687 round(buffer, size, dec_exp, digits_to_remove);
688 // Remove trailing zeros.
689 while (size > 0 && buffer[size - 1] == '0') {
690 --size;
691 ++dec_exp;
692 }
Victor Zverovichdd8c5ce2018-08-29 09:34:57 -0700693 }
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700694 precision = 0;
695 break;
Victor Zveroviche483a012018-08-26 09:51:49 -0700696 }
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700697 case 'F':
698 upper = true;
699 FMT_FALLTHROUGH
700 case 'f': {
701 int digits_to_remove = -dec_exp - precision;
702 if (digits_to_remove > 0) {
703 if (digits_to_remove >= static_cast<int>(size))
704 digits_to_remove = static_cast<int>(size) - 1;
705 round(buffer, size, dec_exp, digits_to_remove);
706 }
707 break;
708 }
709 case 'e': case 'E':
710 format_exp_notation(buffer, size, dec_exp, precision, type == 'E');
711 return;
712 }
713 if (write_decimal_point && precision < 1)
Victor Zverovichdd8c5ce2018-08-29 09:34:57 -0700714 precision = 1;
Victor Zverovich1489d3b2018-08-29 10:07:29 -0700715 grisu2_prettify(buffer, size, dec_exp, precision, upper);
Victor Zverovichf0d0a1e2018-08-25 16:08:32 -0700716}
Victor Zverovichcd900972018-04-21 17:26:24 -0700717} // namespace internal
718
vitaut24c309f2015-06-12 07:15:57 -0700719#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700720
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800721FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
Victor Zverovichdff21372014-12-16 07:01:01 -0800722 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
vitautc3ba6152015-08-07 07:34:58 -0700723 if (s.size() > INT_MAX)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800724 FMT_THROW(windows_error(ERROR_INVALID_PARAMETER, ERROR_MSG));
vitautc3ba6152015-08-07 07:34:58 -0700725 int s_size = static_cast<int>(s.size());
Vasili Galkaacb469a2018-03-12 14:43:29 +0200726 if (s_size == 0) {
727 // MultiByteToWideChar does not support zero length, handle separately.
728 buffer_.resize(1);
729 buffer_[0] = 0;
730 return;
731 }
732
vitautc3ba6152015-08-07 07:34:58 -0700733 int length = MultiByteToWideChar(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800734 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700735 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800736 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700737 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700738 length = MultiByteToWideChar(
vitautc3ba6152015-08-07 07:34:58 -0700739 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700740 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800741 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700742 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700743}
744
Victor Zverovichc333dca2017-02-19 08:41:38 -0800745FMT_FUNC internal::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700746 if (int error_code = convert(s)) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800747 FMT_THROW(windows_error(error_code,
Victor Zverovich8b76e972014-10-06 08:30:55 -0700748 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700749 }
750}
751
Victor Zverovichc333dca2017-02-19 08:41:38 -0800752FMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) {
vitautca747812015-08-07 07:08:46 -0700753 if (s.size() > INT_MAX)
754 return ERROR_INVALID_PARAMETER;
755 int s_size = static_cast<int>(s.size());
Vasili Galkaacb469a2018-03-12 14:43:29 +0200756 if (s_size == 0) {
757 // WideCharToMultiByte does not support zero length, handle separately.
758 buffer_.resize(1);
759 buffer_[0] = 0;
760 return 0;
761 }
762
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800763 int length = WideCharToMultiByte(
764 CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700765 if (length == 0)
766 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700767 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700768 length = WideCharToMultiByte(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800769 CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700770 if (length == 0)
771 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700772 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700773 return 0;
774}
775
Victor Zverovichc333dca2017-02-19 08:41:38 -0800776FMT_FUNC void windows_error::init(
Victor Zverovich7f351de2017-12-03 09:18:06 -0800777 int err_code, string_view format_str, format_args args) {
Carter Li3f574c12015-02-17 10:11:42 +0800778 error_code_ = err_code;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800779 memory_buffer buffer;
Victor Zveroviche022c212017-02-17 06:38:53 -0800780 internal::format_windows_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700781 std::runtime_error &base = *this;
Victor Zveroviche022c212017-02-17 06:38:53 -0800782 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700783}
784
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700785FMT_FUNC void internal::format_windows_error(
Victor Zverovichf6fd38b2018-01-15 08:22:31 -0800786 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700787 FMT_TRY {
Victor Zverovichc0954452018-01-06 09:09:50 -0800788 wmemory_buffer buf;
Victor Zverovichf1ede632018-03-04 10:33:42 -0800789 buf.resize(inline_buffer_size);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800790 for (;;) {
Victor Zverovichc0954452018-01-06 09:09:50 -0800791 wchar_t *system_message = &buf[0];
Victor Zverovichf85d5f42016-10-22 08:04:20 -0700792 int result = FormatMessageW(
793 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800794 FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
795 system_message, static_cast<uint32_t>(buf.size()), FMT_NULL);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800796 if (result != 0) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800797 utf16_to_utf8 utf8_message;
Michael Winterberg2a05a872016-03-02 17:35:34 -0800798 if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800799 writer w(out);
Victor Zveroviche022c212017-02-17 06:38:53 -0800800 w.write(message);
801 w.write(": ");
802 w.write(utf8_message);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800803 return;
804 }
805 break;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700806 }
Michael Winterberg2a05a872016-03-02 17:35:34 -0800807 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
808 break; // Can't get error message, report error code instead.
Victor Zverovichc0954452018-01-06 09:09:50 -0800809 buf.resize(buf.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700810 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700811 } FMT_CATCH(...) {}
Victor Zverovichc0954452018-01-06 09:09:50 -0800812 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700813}
vitaut24c309f2015-06-12 07:15:57 -0700814
815#endif // FMT_USE_WINDOWS_H
816
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700817FMT_FUNC void format_system_error(
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800818 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
vitaut24c309f2015-06-12 07:15:57 -0700819 FMT_TRY {
Victor Zverovich36634142017-12-26 09:00:22 -0800820 memory_buffer buf;
Victor Zverovichf1ede632018-03-04 10:33:42 -0800821 buf.resize(inline_buffer_size);
vitaut24c309f2015-06-12 07:15:57 -0700822 for (;;) {
Victor Zverovich36634142017-12-26 09:00:22 -0800823 char *system_message = &buf[0];
824 int result = safe_strerror(error_code, system_message, buf.size());
vitaut24c309f2015-06-12 07:15:57 -0700825 if (result == 0) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800826 writer w(out);
Victor Zverovichfefaf072017-02-14 16:29:47 -0500827 w.write(message);
828 w.write(": ");
829 w.write(system_message);
vitaut24c309f2015-06-12 07:15:57 -0700830 return;
831 }
832 if (result != ERANGE)
833 break; // Can't get error message, report error code instead.
Victor Zverovich36634142017-12-26 09:00:22 -0800834 buf.resize(buf.size() * 2);
vitaut24c309f2015-06-12 07:15:57 -0700835 }
836 } FMT_CATCH(...) {}
Victor Zverovichf164e4c2018-02-01 16:49:47 -0800837 format_error_code(out, error_code, message);
vitaut24c309f2015-06-12 07:15:57 -0700838}
Victor Zverovich53b4c312014-04-30 15:00:41 -0700839
Abdó Roig-Marangesaf0f21d2017-12-09 16:50:53 +0100840FMT_FUNC void internal::error_handler::on_error(const char *message) {
Victor Zverovich94edb1a2017-12-06 07:42:42 -0800841 FMT_THROW(format_error(message));
842}
843
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700844FMT_FUNC void report_system_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800845 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700846 report_error(format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700847}
848
vitaut24c309f2015-06-12 07:15:57 -0700849#if FMT_USE_WINDOWS_H
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700850FMT_FUNC void report_windows_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800851 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700852 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700853}
Victor Zverovich400812a2014-04-30 12:38:17 -0700854#endif
Victor Zverovichf7939862014-04-30 10:18:11 -0700855
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800856FMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800857 memory_buffer buffer;
Victor Zverovich38325242018-10-03 18:22:26 -0700858 vformat_to(buffer, format_str,
859 basic_format_args<buffer_context<char>::type>(args));
Victor Zverovichfefaf072017-02-14 16:29:47 -0500860 std::fwrite(buffer.data(), 1, buffer.size(), f);
Victor Zverovichd5b81962014-06-28 21:56:40 -0700861}
862
Daniela Engert2570f1a2018-04-26 20:32:14 +0200863FMT_FUNC void vprint(std::FILE *f, wstring_view format_str, wformat_args args) {
864 wmemory_buffer buffer;
865 vformat_to(buffer, format_str, args);
866 std::fwrite(buffer.data(), sizeof(wchar_t), buffer.size(), f);
867}
868
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800869FMT_FUNC void vprint(string_view format_str, format_args args) {
Victor Zverovich0028ce52016-08-26 17:23:13 -0700870 vprint(stdout, format_str, args);
Victor Zverovich163178e2014-09-25 07:08:25 -0700871}
872
Daniela Engert2570f1a2018-04-26 20:32:14 +0200873FMT_FUNC void vprint(wstring_view format_str, wformat_args args) {
874 vprint(stdout, format_str, args);
875}
876
Thomas Bernardabde38b2018-08-17 11:22:56 +0200877#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800878FMT_FUNC locale locale_provider::locale() { return fmt::locale(); }
Thomas Bernardabde38b2018-08-17 11:22:56 +0200879#endif
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800880
Victor Zverovich838400d2018-05-12 08:33:51 -0700881FMT_END_NAMESPACE
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700882
Ingo van Lilb4b13ee2015-11-02 12:34:46 +0100883#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +0000884# pragma warning(pop)
885#endif
Victor Zverovich3da71d52018-03-21 07:50:59 -0700886
887#endif // FMT_FORMAT_INL_H_