blob: b8f9a2b0b1775e90f00bd1bfd421245012eeeef6 [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 Zverovich6ebc1a92018-05-20 17:16:34 -070021#include <locale>
Victor Zverovich9ff3b972013-09-07 10:15:08 -070022
vitaut24c309f2015-06-12 07:15:57 -070023#if defined(_WIN32) && defined(__MINGW32__)
24# include <cstring>
25#endif
26
27#if FMT_USE_WINDOWS_H
Victor Zverovichc753a2a2018-01-28 20:26:25 -080028# if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)
29# define WIN32_LEAN_AND_MEAN
30# endif
vitaut67ce3942015-04-30 07:48:36 -070031# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
32# include <windows.h>
33# else
34# define NOMINMAX
35# include <windows.h>
36# undef NOMINMAX
37# endif
Ryuuke5a9dc8f2015-02-08 16:08:29 +000038#endif
39
Victor Zverovich8b76e972014-10-06 08:30:55 -070040#if FMT_EXCEPTIONS
41# define FMT_TRY try
42# define FMT_CATCH(x) catch (x)
43#else
44# define FMT_TRY if (true)
45# define FMT_CATCH(x) if (false)
46#endif
47
Victor Zverovichb83241f2017-10-19 07:28:17 -070048#ifdef __GNUC__
Victor Zverovich07f8ffc2017-08-21 06:50:57 -070049// Disable the warning about declaration shadowing because it affects too
50// many valid cases.
Victor Zverovichb83241f2017-10-19 07:28:17 -070051# pragma GCC diagnostic ignored "-Wshadow"
52#endif
Victor Zverovich07f8ffc2017-08-21 06:50:57 -070053
Ingo van Lilb4b13ee2015-11-02 12:34:46 +010054#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +000055# pragma warning(push)
Victor Zverovich8b76e972014-10-06 08:30:55 -070056# pragma warning(disable: 4127) // conditional expression is constant
Daniel.Perrybd0067e2014-11-25 18:01:09 -050057# pragma warning(disable: 4702) // unreachable code
vitautdf47d812015-03-16 18:53:14 -070058// Disable deprecation warning for strerror. The latter is not called but
59// MSVC fails to detect it.
60# pragma warning(disable: 4996)
jdale88a9862fd2014-03-11 18:56:24 +000061#endif
62
vitaut341b98c2015-03-14 13:39:33 -070063// Dummy implementations of strerror_r and strerror_s called if corresponding
64// system functions are not available.
Victor Zverovich6cb68f92018-02-10 06:28:33 -080065inline fmt::internal::null<> strerror_r(int, char *, ...) {
Victor Zverovichc333dca2017-02-19 08:41:38 -080066 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070067}
Victor Zverovich6cb68f92018-02-10 06:28:33 -080068inline fmt::internal::null<> strerror_s(char *, std::size_t, ...) {
Victor Zverovichc333dca2017-02-19 08:41:38 -080069 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070070}
71
Victor Zverovich838400d2018-05-12 08:33:51 -070072FMT_BEGIN_NAMESPACE
Victor Zverovichb26e76e2016-06-14 08:11:33 -070073
Victor Zverovich9bb213e2016-08-25 08:38:07 -070074FMT_FUNC format_error::~format_error() throw() {}
Victor Zverovich3da71d52018-03-21 07:50:59 -070075FMT_FUNC system_error::~system_error() FMT_DTOR_NOEXCEPT {}
Victor Zverovichb26e76e2016-06-14 08:11:33 -070076
Victor Zverovich9ff3b972013-09-07 10:15:08 -070077namespace {
78
79#ifndef _MSC_VER
Victor Zverovichb9a568b2014-09-19 07:51:42 -070080# define FMT_SNPRINTF snprintf
Victor Zverovicha684d0c2013-12-27 08:00:10 -080081#else // _MSC_VER
Victor Zverovich406c6122014-08-19 08:47:38 -070082inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -080083 va_list args;
84 va_start(args, format);
85 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
86 va_end(args);
87 return result;
88}
Victor Zverovichb9a568b2014-09-19 07:51:42 -070089# define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -070090#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -080091
cstamford55836ca2015-03-10 07:04:31 +000092#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
93# define FMT_SWPRINTF snwprintf
94#else
95# define FMT_SWPRINTF swprintf
96#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
97
Victor Zverovich7004d1e2015-02-08 19:54:39 -080098const char RESET_COLOR[] = "\x1b[0m";
Daniela Engert2570f1a2018-04-26 20:32:14 +020099const wchar_t WRESET_COLOR[] = L"\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700100
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800101typedef void (*FormatFunc)(internal::buffer &, int, string_view);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700102
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700103// Portable thread-safe version of strerror.
104// Sets buffer to point to a string describing the error code.
105// This can be either a pointer to a string stored in buffer,
106// or a pointer to some static immutable string.
107// Returns one of the following values:
108// 0 - success
109// ERANGE - buffer is not large enough to store the error message
110// other - failure
111// Buffer should be at least of size 1.
112int safe_strerror(
Carter Lie2583ab2015-02-14 09:58:29 +0800113 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
Victor Zverovich92a250f2018-02-07 07:16:00 -0800114 FMT_ASSERT(buffer != FMT_NULL && buffer_size != 0, "invalid buffer");
vitaut341b98c2015-03-14 13:39:33 -0700115
Victor Zverovich69823bf2018-05-19 08:57:31 -0700116 class dispatcher {
vitaut341b98c2015-03-14 13:39:33 -0700117 private:
118 int error_code_;
119 char *&buffer_;
120 std::size_t buffer_size_;
121
vitautda052ae2015-03-21 07:53:39 -0700122 // A noop assignment operator to avoid bogus warnings.
Victor Zverovich69823bf2018-05-19 08:57:31 -0700123 void operator=(const dispatcher &) {}
vitautda052ae2015-03-21 07:53:39 -0700124
vitaut341b98c2015-03-14 13:39:33 -0700125 // Handle the result of XSI-compliant version of strerror_r.
126 int handle(int result) {
vitaute1776ac2015-03-14 14:05:02 -0700127 // glibc versions before 2.13 return result in errno.
128 return result == -1 ? errno : result;
vitaut341b98c2015-03-14 13:39:33 -0700129 }
130
131 // Handle the result of GNU-specific version of strerror_r.
132 int handle(char *message) {
133 // If the buffer is full then the message is probably truncated.
134 if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
135 return ERANGE;
136 buffer_ = message;
137 return 0;
138 }
139
140 // Handle the case when strerror_r is not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800141 int handle(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700142 return fallback(strerror_s(buffer_, buffer_size_, error_code_));
143 }
144
145 // Fallback to strerror_s when strerror_r is not available.
146 int fallback(int result) {
147 // If the buffer is full then the message is probably truncated.
148 return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
149 ERANGE : result;
150 }
151
152 // Fallback to strerror if strerror_r and strerror_s are not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800153 int fallback(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700154 errno = 0;
155 buffer_ = strerror(error_code_);
156 return errno;
157 }
158
159 public:
Victor Zverovich69823bf2018-05-19 08:57:31 -0700160 dispatcher(int err_code, char *&buf, std::size_t buf_size)
Radu Popescu0affb232015-08-04 12:52:44 +0200161 : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
vitaut341b98c2015-03-14 13:39:33 -0700162
vitaut63f6c102015-06-14 09:36:23 -0700163 int run() {
vitaut63f6c102015-06-14 09:36:23 -0700164 return handle(strerror_r(error_code_, buffer_, buffer_size_));
165 }
vitaut341b98c2015-03-14 13:39:33 -0700166 };
Victor Zverovich69823bf2018-05-19 08:57:31 -0700167 return dispatcher(error_code, buffer, buffer_size).run();
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700168}
169
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800170void format_error_code(internal::buffer &out, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800171 string_view message) FMT_NOEXCEPT {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700172 // Report error code making sure that the output fits into
Victor Zverovichf1ede632018-03-04 10:33:42 -0800173 // inline_buffer_size to avoid dynamic memory allocation and potential
Victor Zverovich22f75d82014-09-03 08:03:05 -0700174 // bad_alloc.
Victor Zverovichf423e462017-03-11 07:43:26 -0800175 out.resize(0);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700176 static const char SEP[] = ": ";
vitaut1addec92015-03-21 20:16:36 -0700177 static const char ERROR_STR[] = "error ";
vitaut1addec92015-03-21 20:16:36 -0700178 // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
179 std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800180 typedef internal::int_traits<int>::main_type main_type;
181 main_type abs_value = static_cast<main_type>(error_code);
vitaut9d577ca2016-03-02 07:01:21 -0800182 if (internal::is_negative(error_code)) {
183 abs_value = 0 - abs_value;
184 ++error_code_size;
185 }
vitautbfdca8b2016-04-20 09:11:33 -0700186 error_code_size += internal::count_digits(abs_value);
Victor Zverovich217e7c72018-01-14 07:19:23 -0800187 writer w(out);
Victor Zverovichf1ede632018-03-04 10:33:42 -0800188 if (message.size() <= inline_buffer_size - error_code_size) {
Victor Zverovichfefaf072017-02-14 16:29:47 -0500189 w.write(message);
190 w.write(SEP);
Victor Zverovichec15ef72017-01-22 07:40:21 -0800191 }
Victor Zverovichfefaf072017-02-14 16:29:47 -0500192 w.write(ERROR_STR);
193 w.write(error_code);
Victor Zverovichf1ede632018-03-04 10:33:42 -0800194 assert(out.size() <= inline_buffer_size);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700195}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700196
vitautbfdca8b2016-04-20 09:11:33 -0700197void report_error(FormatFunc func, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800198 string_view message) FMT_NOEXCEPT {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800199 memory_buffer full_message;
Victor Zverovich88e0db82014-09-05 08:04:26 -0700200 func(full_message, error_code, message);
201 // Use Writer::data instead of Writer::c_str to avoid potential memory
202 // allocation.
203 std::fwrite(full_message.data(), full_message.size(), 1, stderr);
204 std::fputc('\n', stderr);
Victor Zverovichb605b392013-09-09 22:21:40 -0700205}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700206} // namespace
vitaut270069b2015-06-16 07:36:32 -0700207
Victor Zverovich6ebc1a92018-05-20 17:16:34 -0700208class locale {
209 private:
210 std::locale locale_;
211
212 public:
213 explicit locale(std::locale loc = std::locale()) : locale_(loc) {}
214 std::locale get() { return locale_; }
215};
216
Victor Zverovich7f351de2017-12-03 09:18:06 -0800217template <typename Char>
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800218FMT_FUNC Char internal::thousands_sep(locale_provider *lp) {
219 std::locale loc = lp ? lp->locale().get() : std::locale();
220 return std::use_facet<std::numpunct<Char>>(loc).thousands_sep();
Victor Zverovich7f351de2017-12-03 09:18:06 -0800221}
222
Victor Zverovichc333dca2017-02-19 08:41:38 -0800223FMT_FUNC void system_error::init(
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800224 int err_code, string_view format_str, format_args args) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800225 error_code_ = err_code;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800226 memory_buffer buffer;
227 format_system_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700228 std::runtime_error &base = *this;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800229 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700230}
231
Victor Zverovichcd900972018-04-21 17:26:24 -0700232namespace internal {
Victor Zverovichb605b392013-09-09 22:21:40 -0700233template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700234int char_traits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700235 char *buffer, std::size_t size, const char *format,
236 unsigned width, int precision, T value) {
237 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700238 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700239 FMT_SNPRINTF(buffer, size, format, value) :
240 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700241 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700242 return precision < 0 ?
243 FMT_SNPRINTF(buffer, size, format, width, value) :
244 FMT_SNPRINTF(buffer, size, format, width, precision, value);
245}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700246
Victor Zverovichb605b392013-09-09 22:21:40 -0700247template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700248int char_traits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700249 wchar_t *buffer, std::size_t size, const wchar_t *format,
250 unsigned width, int precision, T value) {
251 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700252 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000253 FMT_SWPRINTF(buffer, size, format, value) :
254 FMT_SWPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700255 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700256 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000257 FMT_SWPRINTF(buffer, size, format, width, value) :
258 FMT_SWPRINTF(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700259}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800260
Victor Zverovich311251e2014-11-29 06:58:00 -0800261template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700262const char basic_data<T>::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800263 "0001020304050607080910111213141516171819"
264 "2021222324252627282930313233343536373839"
265 "4041424344454647484950515253545556575859"
266 "6061626364656667686970717273747576777879"
267 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800268
Victor Zverovichf1d85162014-02-19 13:02:22 -0800269#define FMT_POWERS_OF_10(factor) \
270 factor * 10, \
271 factor * 100, \
272 factor * 1000, \
273 factor * 10000, \
274 factor * 100000, \
275 factor * 1000000, \
276 factor * 10000000, \
277 factor * 100000000, \
278 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800279
Victor Zverovich311251e2014-11-29 06:58:00 -0800280template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700281const uint32_t basic_data<T>::POWERS_OF_10_32[] = {
Victor Zverovich311251e2014-11-29 06:58:00 -0800282 0, FMT_POWERS_OF_10(1)
283};
284
285template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700286const uint64_t basic_data<T>::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800287 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800288 FMT_POWERS_OF_10(1),
Victor Zverovich016aceb2017-08-26 09:09:43 -0700289 FMT_POWERS_OF_10(1000000000ull),
290 10000000000000000000ull
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800291};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800292
Victor Zverovich2768af22018-04-29 06:33:05 -0700293// Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.
294// These are generated by support/compute-powers.py.
295template <typename T>
296const uint64_t basic_data<T>::POW10_SIGNIFICANDS[] = {
Victor Zverovich2f257b72018-05-27 08:04:30 -0700297 0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76, 0xcf42894a5dce35ea,
298 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df, 0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f,
299 0xbe5691ef416bd60c, 0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5,
300 0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57, 0xc21094364dfb5637,
301 0x9096ea6f3848984f, 0xd77485cb25823ac7, 0xa086cfcd97bf97f4, 0xef340a98172aace5,
302 0xb23867fb2a35b28e, 0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996,
303 0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126, 0xb5b5ada8aaff80b8,
304 0x87625f056c7c4a8b, 0xc9bcff6034c13053, 0x964e858c91ba2655, 0xdff9772470297ebd,
305 0xa6dfbd9fb8e5b88f, 0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b,
306 0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06, 0xaa242499697392d3,
307 0xfd87b5f28300ca0e, 0xbce5086492111aeb, 0x8cbccc096f5088cc, 0xd1b71758e219652c,
308 0x9c40000000000000, 0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984,
309 0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068, 0x9f4f2726179a2245,
310 0xed63a231d4c4fb27, 0xb0de65388cc8ada8, 0x83c7088e1aab65db, 0xc45d1df942711d9a,
311 0x924d692ca61be758, 0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85,
312 0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d, 0x952ab45cfa97a0b3,
313 0xde469fbd99a05fe3, 0xa59bc234db398c25, 0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece,
314 0x88fcf317f22241e2, 0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a,
315 0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410, 0x8bab8eefb6409c1a,
316 0xd01fef10a657842c, 0x9b10a4e5e9913129, 0xe7109bfba19c0c9d, 0xac2820d9623bf429,
317 0x80444b5e7aa7cf85, 0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841,
318 0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b
Victor Zverovich2768af22018-04-29 06:33:05 -0700319};
320
321// Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding
322// to significands above.
323template <typename T>
324const int16_t basic_data<T>::POW10_EXPONENTS[] = {
325 -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954,
326 -927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661,
327 -635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369,
328 -343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77,
329 -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216,
330 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508,
331 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800,
332 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066
333};
334
Victor Zverovichcd900972018-04-21 17:26:24 -0700335FMT_FUNC fp operator*(fp x, fp y) {
336 // Multiply 32-bit parts of significands.
337 uint64_t mask = (1ULL << 32) - 1;
338 uint64_t a = x.f >> 32, b = x.f & mask;
339 uint64_t c = y.f >> 32, d = y.f & mask;
340 uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d;
341 // Compute mid 64-bit of result and round.
342 uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
Daniela Engert6cd66612018-04-30 10:07:43 +0200343 return fp(ac + (ad >> 32) + (bc >> 32) + (mid >> 32), x.e + y.e + 64);
Victor Zverovichcd900972018-04-21 17:26:24 -0700344}
345} // namespace internal
346
vitaut24c309f2015-06-12 07:15:57 -0700347#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700348
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800349FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
Victor Zverovichdff21372014-12-16 07:01:01 -0800350 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
vitautc3ba6152015-08-07 07:34:58 -0700351 if (s.size() > INT_MAX)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800352 FMT_THROW(windows_error(ERROR_INVALID_PARAMETER, ERROR_MSG));
vitautc3ba6152015-08-07 07:34:58 -0700353 int s_size = static_cast<int>(s.size());
Vasili Galkaacb469a2018-03-12 14:43:29 +0200354 if (s_size == 0) {
355 // MultiByteToWideChar does not support zero length, handle separately.
356 buffer_.resize(1);
357 buffer_[0] = 0;
358 return;
359 }
360
vitautc3ba6152015-08-07 07:34:58 -0700361 int length = MultiByteToWideChar(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800362 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700363 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800364 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700365 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700366 length = MultiByteToWideChar(
vitautc3ba6152015-08-07 07:34:58 -0700367 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700368 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800369 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700370 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700371}
372
Victor Zverovichc333dca2017-02-19 08:41:38 -0800373FMT_FUNC internal::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700374 if (int error_code = convert(s)) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800375 FMT_THROW(windows_error(error_code,
Victor Zverovich8b76e972014-10-06 08:30:55 -0700376 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700377 }
378}
379
Victor Zverovichc333dca2017-02-19 08:41:38 -0800380FMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) {
vitautca747812015-08-07 07:08:46 -0700381 if (s.size() > INT_MAX)
382 return ERROR_INVALID_PARAMETER;
383 int s_size = static_cast<int>(s.size());
Vasili Galkaacb469a2018-03-12 14:43:29 +0200384 if (s_size == 0) {
385 // WideCharToMultiByte does not support zero length, handle separately.
386 buffer_.resize(1);
387 buffer_[0] = 0;
388 return 0;
389 }
390
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800391 int length = WideCharToMultiByte(
392 CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700393 if (length == 0)
394 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700395 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700396 length = WideCharToMultiByte(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800397 CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700398 if (length == 0)
399 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700400 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700401 return 0;
402}
403
Victor Zverovichc333dca2017-02-19 08:41:38 -0800404FMT_FUNC void windows_error::init(
Victor Zverovich7f351de2017-12-03 09:18:06 -0800405 int err_code, string_view format_str, format_args args) {
Carter Li3f574c12015-02-17 10:11:42 +0800406 error_code_ = err_code;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800407 memory_buffer buffer;
Victor Zveroviche022c212017-02-17 06:38:53 -0800408 internal::format_windows_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700409 std::runtime_error &base = *this;
Victor Zveroviche022c212017-02-17 06:38:53 -0800410 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700411}
412
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700413FMT_FUNC void internal::format_windows_error(
Victor Zverovichf6fd38b2018-01-15 08:22:31 -0800414 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700415 FMT_TRY {
Victor Zverovichc0954452018-01-06 09:09:50 -0800416 wmemory_buffer buf;
Victor Zverovichf1ede632018-03-04 10:33:42 -0800417 buf.resize(inline_buffer_size);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800418 for (;;) {
Victor Zverovichc0954452018-01-06 09:09:50 -0800419 wchar_t *system_message = &buf[0];
Victor Zverovichf85d5f42016-10-22 08:04:20 -0700420 int result = FormatMessageW(
421 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800422 FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
423 system_message, static_cast<uint32_t>(buf.size()), FMT_NULL);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800424 if (result != 0) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800425 utf16_to_utf8 utf8_message;
Michael Winterberg2a05a872016-03-02 17:35:34 -0800426 if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800427 writer w(out);
Victor Zveroviche022c212017-02-17 06:38:53 -0800428 w.write(message);
429 w.write(": ");
430 w.write(utf8_message);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800431 return;
432 }
433 break;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700434 }
Michael Winterberg2a05a872016-03-02 17:35:34 -0800435 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
436 break; // Can't get error message, report error code instead.
Victor Zverovichc0954452018-01-06 09:09:50 -0800437 buf.resize(buf.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700438 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700439 } FMT_CATCH(...) {}
Victor Zverovichc0954452018-01-06 09:09:50 -0800440 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700441}
vitaut24c309f2015-06-12 07:15:57 -0700442
443#endif // FMT_USE_WINDOWS_H
444
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700445FMT_FUNC void format_system_error(
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800446 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
vitaut24c309f2015-06-12 07:15:57 -0700447 FMT_TRY {
Victor Zverovich36634142017-12-26 09:00:22 -0800448 memory_buffer buf;
Victor Zverovichf1ede632018-03-04 10:33:42 -0800449 buf.resize(inline_buffer_size);
vitaut24c309f2015-06-12 07:15:57 -0700450 for (;;) {
Victor Zverovich36634142017-12-26 09:00:22 -0800451 char *system_message = &buf[0];
452 int result = safe_strerror(error_code, system_message, buf.size());
vitaut24c309f2015-06-12 07:15:57 -0700453 if (result == 0) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800454 writer w(out);
Victor Zverovichfefaf072017-02-14 16:29:47 -0500455 w.write(message);
456 w.write(": ");
457 w.write(system_message);
vitaut24c309f2015-06-12 07:15:57 -0700458 return;
459 }
460 if (result != ERANGE)
461 break; // Can't get error message, report error code instead.
Victor Zverovich36634142017-12-26 09:00:22 -0800462 buf.resize(buf.size() * 2);
vitaut24c309f2015-06-12 07:15:57 -0700463 }
464 } FMT_CATCH(...) {}
Victor Zverovichf164e4c2018-02-01 16:49:47 -0800465 format_error_code(out, error_code, message);
vitaut24c309f2015-06-12 07:15:57 -0700466}
Victor Zverovich53b4c312014-04-30 15:00:41 -0700467
jamboree7487bde2015-06-10 09:32:59 +0800468template <typename Char>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800469void basic_fixed_buffer<Char>::grow(std::size_t) {
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800470 FMT_THROW(std::runtime_error("buffer overflow"));
471}
472
Abdó Roig-Marangesaf0f21d2017-12-09 16:50:53 +0100473FMT_FUNC void internal::error_handler::on_error(const char *message) {
Victor Zverovich94edb1a2017-12-06 07:42:42 -0800474 FMT_THROW(format_error(message));
475}
476
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700477FMT_FUNC void report_system_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800478 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700479 report_error(format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700480}
481
vitaut24c309f2015-06-12 07:15:57 -0700482#if FMT_USE_WINDOWS_H
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700483FMT_FUNC void report_windows_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800484 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700485 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700486}
Victor Zverovich400812a2014-04-30 12:38:17 -0700487#endif
Victor Zverovichf7939862014-04-30 10:18:11 -0700488
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800489FMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800490 memory_buffer buffer;
Victor Zverovichfefaf072017-02-14 16:29:47 -0500491 vformat_to(buffer, format_str, args);
492 std::fwrite(buffer.data(), 1, buffer.size(), f);
Victor Zverovichd5b81962014-06-28 21:56:40 -0700493}
494
Daniela Engert2570f1a2018-04-26 20:32:14 +0200495FMT_FUNC void vprint(std::FILE *f, wstring_view format_str, wformat_args args) {
496 wmemory_buffer buffer;
497 vformat_to(buffer, format_str, args);
498 std::fwrite(buffer.data(), sizeof(wchar_t), buffer.size(), f);
499}
500
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800501FMT_FUNC void vprint(string_view format_str, format_args args) {
Victor Zverovich0028ce52016-08-26 17:23:13 -0700502 vprint(stdout, format_str, args);
Victor Zverovich163178e2014-09-25 07:08:25 -0700503}
504
Daniela Engert2570f1a2018-04-26 20:32:14 +0200505FMT_FUNC void vprint(wstring_view format_str, wformat_args args) {
506 vprint(stdout, format_str, args);
507}
508
Victor Zverovichbb471092018-03-04 11:25:40 -0800509FMT_FUNC void vprint_colored(color c, string_view format, format_args args) {
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700510 char escape[] = "\x1b[30m";
Ingo van Lilf4d88842015-11-02 19:14:47 +0100511 escape[3] = static_cast<char>('0' + c);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700512 std::fputs(escape, stdout);
Victor Zverovich0028ce52016-08-26 17:23:13 -0700513 vprint(format, args);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700514 std::fputs(RESET_COLOR, stdout);
515}
516
Daniela Engert2570f1a2018-04-26 20:32:14 +0200517FMT_FUNC void vprint_colored(color c, wstring_view format, wformat_args args) {
518 wchar_t escape[] = L"\x1b[30m";
519 escape[3] = static_cast<wchar_t>('0' + c);
520 std::fputws(escape, stdout);
521 vprint(format, args);
522 std::fputws(WRESET_COLOR, stdout);
523}
524
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800525FMT_FUNC locale locale_provider::locale() { return fmt::locale(); }
526
Victor Zverovich838400d2018-05-12 08:33:51 -0700527FMT_END_NAMESPACE
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700528
Ingo van Lilb4b13ee2015-11-02 12:34:46 +0100529#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +0000530# pragma warning(pop)
531#endif
Victor Zverovich3da71d52018-03-21 07:50:59 -0700532
533#endif // FMT_FORMAT_INL_H_