blob: 00c97c3fc3b4aa7558720a763a5dd415255dc61b [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}
Victor Zverovich468c2432018-05-27 10:57:26 -0700345
346FMT_FUNC fp get_cached_power(int min_exponent, int &pow10_exponent) {
347 const double one_over_log2_10 = 0.30102999566398114; // 1 / log2(10)
348 int index = static_cast<int>(std::ceil(
349 (min_exponent + fp::fp_significand_size - 1) * one_over_log2_10));
350 // Decimal exponent of the first (smallest) cached power of 10.
351 const int first_dec_exp = -348;
352 // Difference between two consecutive decimal exponents in cached powers of 10.
353 const int dec_exp_step = 8;
354 index = (index - first_dec_exp - 1) / dec_exp_step + 1;
355 pow10_exponent = first_dec_exp + index * dec_exp_step;
356 return fp(data::POW10_SIGNIFICANDS[index], data::POW10_EXPONENTS[index]);
357}
Victor Zverovichcd900972018-04-21 17:26:24 -0700358} // namespace internal
359
vitaut24c309f2015-06-12 07:15:57 -0700360#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700361
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800362FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
Victor Zverovichdff21372014-12-16 07:01:01 -0800363 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
vitautc3ba6152015-08-07 07:34:58 -0700364 if (s.size() > INT_MAX)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800365 FMT_THROW(windows_error(ERROR_INVALID_PARAMETER, ERROR_MSG));
vitautc3ba6152015-08-07 07:34:58 -0700366 int s_size = static_cast<int>(s.size());
Vasili Galkaacb469a2018-03-12 14:43:29 +0200367 if (s_size == 0) {
368 // MultiByteToWideChar does not support zero length, handle separately.
369 buffer_.resize(1);
370 buffer_[0] = 0;
371 return;
372 }
373
vitautc3ba6152015-08-07 07:34:58 -0700374 int length = MultiByteToWideChar(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800375 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700376 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800377 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700378 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700379 length = MultiByteToWideChar(
vitautc3ba6152015-08-07 07:34:58 -0700380 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700381 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800382 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700383 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700384}
385
Victor Zverovichc333dca2017-02-19 08:41:38 -0800386FMT_FUNC internal::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700387 if (int error_code = convert(s)) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800388 FMT_THROW(windows_error(error_code,
Victor Zverovich8b76e972014-10-06 08:30:55 -0700389 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700390 }
391}
392
Victor Zverovichc333dca2017-02-19 08:41:38 -0800393FMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) {
vitautca747812015-08-07 07:08:46 -0700394 if (s.size() > INT_MAX)
395 return ERROR_INVALID_PARAMETER;
396 int s_size = static_cast<int>(s.size());
Vasili Galkaacb469a2018-03-12 14:43:29 +0200397 if (s_size == 0) {
398 // WideCharToMultiByte does not support zero length, handle separately.
399 buffer_.resize(1);
400 buffer_[0] = 0;
401 return 0;
402 }
403
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800404 int length = WideCharToMultiByte(
405 CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700406 if (length == 0)
407 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700408 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700409 length = WideCharToMultiByte(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800410 CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700411 if (length == 0)
412 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700413 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700414 return 0;
415}
416
Victor Zverovichc333dca2017-02-19 08:41:38 -0800417FMT_FUNC void windows_error::init(
Victor Zverovich7f351de2017-12-03 09:18:06 -0800418 int err_code, string_view format_str, format_args args) {
Carter Li3f574c12015-02-17 10:11:42 +0800419 error_code_ = err_code;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800420 memory_buffer buffer;
Victor Zveroviche022c212017-02-17 06:38:53 -0800421 internal::format_windows_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700422 std::runtime_error &base = *this;
Victor Zveroviche022c212017-02-17 06:38:53 -0800423 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700424}
425
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700426FMT_FUNC void internal::format_windows_error(
Victor Zverovichf6fd38b2018-01-15 08:22:31 -0800427 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700428 FMT_TRY {
Victor Zverovichc0954452018-01-06 09:09:50 -0800429 wmemory_buffer buf;
Victor Zverovichf1ede632018-03-04 10:33:42 -0800430 buf.resize(inline_buffer_size);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800431 for (;;) {
Victor Zverovichc0954452018-01-06 09:09:50 -0800432 wchar_t *system_message = &buf[0];
Victor Zverovichf85d5f42016-10-22 08:04:20 -0700433 int result = FormatMessageW(
434 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800435 FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
436 system_message, static_cast<uint32_t>(buf.size()), FMT_NULL);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800437 if (result != 0) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800438 utf16_to_utf8 utf8_message;
Michael Winterberg2a05a872016-03-02 17:35:34 -0800439 if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800440 writer w(out);
Victor Zveroviche022c212017-02-17 06:38:53 -0800441 w.write(message);
442 w.write(": ");
443 w.write(utf8_message);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800444 return;
445 }
446 break;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700447 }
Michael Winterberg2a05a872016-03-02 17:35:34 -0800448 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
449 break; // Can't get error message, report error code instead.
Victor Zverovichc0954452018-01-06 09:09:50 -0800450 buf.resize(buf.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700451 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700452 } FMT_CATCH(...) {}
Victor Zverovichc0954452018-01-06 09:09:50 -0800453 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700454}
vitaut24c309f2015-06-12 07:15:57 -0700455
456#endif // FMT_USE_WINDOWS_H
457
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700458FMT_FUNC void format_system_error(
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800459 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
vitaut24c309f2015-06-12 07:15:57 -0700460 FMT_TRY {
Victor Zverovich36634142017-12-26 09:00:22 -0800461 memory_buffer buf;
Victor Zverovichf1ede632018-03-04 10:33:42 -0800462 buf.resize(inline_buffer_size);
vitaut24c309f2015-06-12 07:15:57 -0700463 for (;;) {
Victor Zverovich36634142017-12-26 09:00:22 -0800464 char *system_message = &buf[0];
465 int result = safe_strerror(error_code, system_message, buf.size());
vitaut24c309f2015-06-12 07:15:57 -0700466 if (result == 0) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800467 writer w(out);
Victor Zverovichfefaf072017-02-14 16:29:47 -0500468 w.write(message);
469 w.write(": ");
470 w.write(system_message);
vitaut24c309f2015-06-12 07:15:57 -0700471 return;
472 }
473 if (result != ERANGE)
474 break; // Can't get error message, report error code instead.
Victor Zverovich36634142017-12-26 09:00:22 -0800475 buf.resize(buf.size() * 2);
vitaut24c309f2015-06-12 07:15:57 -0700476 }
477 } FMT_CATCH(...) {}
Victor Zverovichf164e4c2018-02-01 16:49:47 -0800478 format_error_code(out, error_code, message);
vitaut24c309f2015-06-12 07:15:57 -0700479}
Victor Zverovich53b4c312014-04-30 15:00:41 -0700480
jamboree7487bde2015-06-10 09:32:59 +0800481template <typename Char>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800482void basic_fixed_buffer<Char>::grow(std::size_t) {
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800483 FMT_THROW(std::runtime_error("buffer overflow"));
484}
485
Abdó Roig-Marangesaf0f21d2017-12-09 16:50:53 +0100486FMT_FUNC void internal::error_handler::on_error(const char *message) {
Victor Zverovich94edb1a2017-12-06 07:42:42 -0800487 FMT_THROW(format_error(message));
488}
489
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700490FMT_FUNC void report_system_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800491 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700492 report_error(format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700493}
494
vitaut24c309f2015-06-12 07:15:57 -0700495#if FMT_USE_WINDOWS_H
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700496FMT_FUNC void report_windows_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800497 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700498 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700499}
Victor Zverovich400812a2014-04-30 12:38:17 -0700500#endif
Victor Zverovichf7939862014-04-30 10:18:11 -0700501
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800502FMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800503 memory_buffer buffer;
Victor Zverovichfefaf072017-02-14 16:29:47 -0500504 vformat_to(buffer, format_str, args);
505 std::fwrite(buffer.data(), 1, buffer.size(), f);
Victor Zverovichd5b81962014-06-28 21:56:40 -0700506}
507
Daniela Engert2570f1a2018-04-26 20:32:14 +0200508FMT_FUNC void vprint(std::FILE *f, wstring_view format_str, wformat_args args) {
509 wmemory_buffer buffer;
510 vformat_to(buffer, format_str, args);
511 std::fwrite(buffer.data(), sizeof(wchar_t), buffer.size(), f);
512}
513
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800514FMT_FUNC void vprint(string_view format_str, format_args args) {
Victor Zverovich0028ce52016-08-26 17:23:13 -0700515 vprint(stdout, format_str, args);
Victor Zverovich163178e2014-09-25 07:08:25 -0700516}
517
Daniela Engert2570f1a2018-04-26 20:32:14 +0200518FMT_FUNC void vprint(wstring_view format_str, wformat_args args) {
519 vprint(stdout, format_str, args);
520}
521
Victor Zverovichbb471092018-03-04 11:25:40 -0800522FMT_FUNC void vprint_colored(color c, string_view format, format_args args) {
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700523 char escape[] = "\x1b[30m";
Ingo van Lilf4d88842015-11-02 19:14:47 +0100524 escape[3] = static_cast<char>('0' + c);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700525 std::fputs(escape, stdout);
Victor Zverovich0028ce52016-08-26 17:23:13 -0700526 vprint(format, args);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700527 std::fputs(RESET_COLOR, stdout);
528}
529
Daniela Engert2570f1a2018-04-26 20:32:14 +0200530FMT_FUNC void vprint_colored(color c, wstring_view format, wformat_args args) {
531 wchar_t escape[] = L"\x1b[30m";
532 escape[3] = static_cast<wchar_t>('0' + c);
533 std::fputws(escape, stdout);
534 vprint(format, args);
535 std::fputws(WRESET_COLOR, stdout);
536}
537
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800538FMT_FUNC locale locale_provider::locale() { return fmt::locale(); }
539
Victor Zverovich838400d2018-05-12 08:33:51 -0700540FMT_END_NAMESPACE
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700541
Ingo van Lilb4b13ee2015-11-02 12:34:46 +0100542#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +0000543# pragma warning(pop)
544#endif
Victor Zverovich3da71d52018-03-21 07:50:59 -0700545
546#endif // FMT_FORMAT_INL_H_