blob: b147b771dd0ec3d59d35766bef9eaab92e2800fb [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
Ingo van Lilb4b13ee2015-11-02 12:34:46 +010048#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +000049# pragma warning(push)
Victor Zverovich8b76e972014-10-06 08:30:55 -070050# pragma warning(disable: 4127) // conditional expression is constant
Daniel.Perrybd0067e2014-11-25 18:01:09 -050051# pragma warning(disable: 4702) // unreachable code
vitautdf47d812015-03-16 18:53:14 -070052// Disable deprecation warning for strerror. The latter is not called but
53// MSVC fails to detect it.
54# pragma warning(disable: 4996)
jdale88a9862fd2014-03-11 18:56:24 +000055#endif
56
vitaut341b98c2015-03-14 13:39:33 -070057// Dummy implementations of strerror_r and strerror_s called if corresponding
58// system functions are not available.
Victor Zverovich6cb68f92018-02-10 06:28:33 -080059inline fmt::internal::null<> strerror_r(int, char *, ...) {
Victor Zverovichc333dca2017-02-19 08:41:38 -080060 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070061}
Victor Zverovich6cb68f92018-02-10 06:28:33 -080062inline fmt::internal::null<> strerror_s(char *, std::size_t, ...) {
Victor Zverovichc333dca2017-02-19 08:41:38 -080063 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070064}
65
Victor Zverovich838400d2018-05-12 08:33:51 -070066FMT_BEGIN_NAMESPACE
Victor Zverovichb26e76e2016-06-14 08:11:33 -070067
Victor Zverovich9ff3b972013-09-07 10:15:08 -070068namespace {
69
70#ifndef _MSC_VER
Victor Zverovichb9a568b2014-09-19 07:51:42 -070071# define FMT_SNPRINTF snprintf
Victor Zverovicha684d0c2013-12-27 08:00:10 -080072#else // _MSC_VER
Victor Zverovich406c6122014-08-19 08:47:38 -070073inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -080074 va_list args;
75 va_start(args, format);
76 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
77 va_end(args);
78 return result;
79}
Victor Zverovichb9a568b2014-09-19 07:51:42 -070080# define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -070081#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -080082
cstamford55836ca2015-03-10 07:04:31 +000083#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
84# define FMT_SWPRINTF snwprintf
85#else
86# define FMT_SWPRINTF swprintf
87#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
88
Victor Zverovichc2fecb92018-01-14 14:15:59 -080089typedef void (*FormatFunc)(internal::buffer &, int, string_view);
Victor Zverovich22f75d82014-09-03 08:03:05 -070090
Victor Zverovichf2c9df82014-09-05 08:44:41 -070091// Portable thread-safe version of strerror.
92// Sets buffer to point to a string describing the error code.
93// This can be either a pointer to a string stored in buffer,
94// or a pointer to some static immutable string.
95// Returns one of the following values:
96// 0 - success
97// ERANGE - buffer is not large enough to store the error message
98// other - failure
99// Buffer should be at least of size 1.
100int safe_strerror(
Carter Lie2583ab2015-02-14 09:58:29 +0800101 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
Victor Zverovich92a250f2018-02-07 07:16:00 -0800102 FMT_ASSERT(buffer != FMT_NULL && buffer_size != 0, "invalid buffer");
vitaut341b98c2015-03-14 13:39:33 -0700103
Victor Zverovich69823bf2018-05-19 08:57:31 -0700104 class dispatcher {
vitaut341b98c2015-03-14 13:39:33 -0700105 private:
106 int error_code_;
107 char *&buffer_;
108 std::size_t buffer_size_;
109
vitautda052ae2015-03-21 07:53:39 -0700110 // A noop assignment operator to avoid bogus warnings.
Victor Zverovich69823bf2018-05-19 08:57:31 -0700111 void operator=(const dispatcher &) {}
vitautda052ae2015-03-21 07:53:39 -0700112
vitaut341b98c2015-03-14 13:39:33 -0700113 // Handle the result of XSI-compliant version of strerror_r.
114 int handle(int result) {
vitaute1776ac2015-03-14 14:05:02 -0700115 // glibc versions before 2.13 return result in errno.
116 return result == -1 ? errno : result;
vitaut341b98c2015-03-14 13:39:33 -0700117 }
118
119 // Handle the result of GNU-specific version of strerror_r.
120 int handle(char *message) {
121 // If the buffer is full then the message is probably truncated.
122 if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
123 return ERANGE;
124 buffer_ = message;
125 return 0;
126 }
127
128 // Handle the case when strerror_r is not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800129 int handle(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700130 return fallback(strerror_s(buffer_, buffer_size_, error_code_));
131 }
132
133 // Fallback to strerror_s when strerror_r is not available.
134 int fallback(int result) {
135 // If the buffer is full then the message is probably truncated.
136 return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
137 ERANGE : result;
138 }
139
140 // Fallback to strerror if strerror_r and strerror_s are not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800141 int fallback(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700142 errno = 0;
143 buffer_ = strerror(error_code_);
144 return errno;
145 }
146
147 public:
Victor Zverovich69823bf2018-05-19 08:57:31 -0700148 dispatcher(int err_code, char *&buf, std::size_t buf_size)
Radu Popescu0affb232015-08-04 12:52:44 +0200149 : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
vitaut341b98c2015-03-14 13:39:33 -0700150
vitaut63f6c102015-06-14 09:36:23 -0700151 int run() {
vitaut63f6c102015-06-14 09:36:23 -0700152 return handle(strerror_r(error_code_, buffer_, buffer_size_));
153 }
vitaut341b98c2015-03-14 13:39:33 -0700154 };
Victor Zverovich69823bf2018-05-19 08:57:31 -0700155 return dispatcher(error_code, buffer, buffer_size).run();
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700156}
157
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800158void format_error_code(internal::buffer &out, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800159 string_view message) FMT_NOEXCEPT {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700160 // Report error code making sure that the output fits into
Victor Zverovichf1ede632018-03-04 10:33:42 -0800161 // inline_buffer_size to avoid dynamic memory allocation and potential
Victor Zverovich22f75d82014-09-03 08:03:05 -0700162 // bad_alloc.
Victor Zverovichf423e462017-03-11 07:43:26 -0800163 out.resize(0);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700164 static const char SEP[] = ": ";
vitaut1addec92015-03-21 20:16:36 -0700165 static const char ERROR_STR[] = "error ";
vitaut1addec92015-03-21 20:16:36 -0700166 // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
167 std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800168 typedef internal::int_traits<int>::main_type main_type;
169 main_type abs_value = static_cast<main_type>(error_code);
vitaut9d577ca2016-03-02 07:01:21 -0800170 if (internal::is_negative(error_code)) {
171 abs_value = 0 - abs_value;
172 ++error_code_size;
173 }
vitautbfdca8b2016-04-20 09:11:33 -0700174 error_code_size += internal::count_digits(abs_value);
Victor Zverovich217e7c72018-01-14 07:19:23 -0800175 writer w(out);
Victor Zverovichf1ede632018-03-04 10:33:42 -0800176 if (message.size() <= inline_buffer_size - error_code_size) {
Victor Zverovichfefaf072017-02-14 16:29:47 -0500177 w.write(message);
178 w.write(SEP);
Victor Zverovichec15ef72017-01-22 07:40:21 -0800179 }
Victor Zverovichfefaf072017-02-14 16:29:47 -0500180 w.write(ERROR_STR);
181 w.write(error_code);
Victor Zverovichf1ede632018-03-04 10:33:42 -0800182 assert(out.size() <= inline_buffer_size);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700183}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700184
vitautbfdca8b2016-04-20 09:11:33 -0700185void report_error(FormatFunc func, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800186 string_view message) FMT_NOEXCEPT {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800187 memory_buffer full_message;
Victor Zverovich88e0db82014-09-05 08:04:26 -0700188 func(full_message, error_code, message);
189 // Use Writer::data instead of Writer::c_str to avoid potential memory
190 // allocation.
191 std::fwrite(full_message.data(), full_message.size(), 1, stderr);
192 std::fputc('\n', stderr);
Victor Zverovichb605b392013-09-09 22:21:40 -0700193}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700194} // namespace
vitaut270069b2015-06-16 07:36:32 -0700195
Victor Zverovich6ebc1a92018-05-20 17:16:34 -0700196class locale {
197 private:
198 std::locale locale_;
199
200 public:
201 explicit locale(std::locale loc = std::locale()) : locale_(loc) {}
202 std::locale get() { return locale_; }
203};
204
Victor Zverovich2a4e9482018-07-21 09:13:21 -0700205FMT_FUNC size_t internal::count_code_points(u8string_view s) {
206 const char8_t *data = s.data();
207 int num_code_points = 0;
208 for (size_t i = 0, size = s.size(); i != size; ++i) {
209 if ((data[i].value & 0xc0) != 0x80)
210 ++num_code_points;
211 }
212 return num_code_points;
213}
214
Victor Zverovich7f351de2017-12-03 09:18:06 -0800215template <typename Char>
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800216FMT_FUNC Char internal::thousands_sep(locale_provider *lp) {
217 std::locale loc = lp ? lp->locale().get() : std::locale();
218 return std::use_facet<std::numpunct<Char>>(loc).thousands_sep();
Victor Zverovich7f351de2017-12-03 09:18:06 -0800219}
220
Victor Zverovichc333dca2017-02-19 08:41:38 -0800221FMT_FUNC void system_error::init(
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800222 int err_code, string_view format_str, format_args args) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800223 error_code_ = err_code;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800224 memory_buffer buffer;
225 format_system_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700226 std::runtime_error &base = *this;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800227 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700228}
229
Victor Zverovichcd900972018-04-21 17:26:24 -0700230namespace internal {
Victor Zverovichb605b392013-09-09 22:21:40 -0700231template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700232int char_traits<char>::format_float(
Victor Zverovichb60a5c52018-05-28 20:16:30 -0700233 char *buffer, std::size_t size, const char *format, int precision, T value) {
Victor Zverovichb605b392013-09-09 22:21:40 -0700234 return precision < 0 ?
Victor Zverovichb60a5c52018-05-28 20:16:30 -0700235 FMT_SNPRINTF(buffer, size, format, value) :
236 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovichb605b392013-09-09 22:21:40 -0700237}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700238
Victor Zverovichb605b392013-09-09 22:21:40 -0700239template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700240int char_traits<wchar_t>::format_float(
Victor Zverovichb60a5c52018-05-28 20:16:30 -0700241 wchar_t *buffer, std::size_t size, const wchar_t *format, int precision,
242 T value) {
Victor Zverovichb605b392013-09-09 22:21:40 -0700243 return precision < 0 ?
Victor Zverovichb60a5c52018-05-28 20:16:30 -0700244 FMT_SWPRINTF(buffer, size, format, value) :
245 FMT_SWPRINTF(buffer, size, format, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700246}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800247
Victor Zverovich311251e2014-11-29 06:58:00 -0800248template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700249const char basic_data<T>::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800250 "0001020304050607080910111213141516171819"
251 "2021222324252627282930313233343536373839"
252 "4041424344454647484950515253545556575859"
253 "6061626364656667686970717273747576777879"
254 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800255
Victor Zverovichf1d85162014-02-19 13:02:22 -0800256#define FMT_POWERS_OF_10(factor) \
257 factor * 10, \
258 factor * 100, \
259 factor * 1000, \
260 factor * 10000, \
261 factor * 100000, \
262 factor * 1000000, \
263 factor * 10000000, \
264 factor * 100000000, \
265 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800266
Victor Zverovich311251e2014-11-29 06:58:00 -0800267template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700268const uint32_t basic_data<T>::POWERS_OF_10_32[] = {
Victor Zverovich311251e2014-11-29 06:58:00 -0800269 0, FMT_POWERS_OF_10(1)
270};
271
272template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700273const uint64_t basic_data<T>::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800274 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800275 FMT_POWERS_OF_10(1),
Victor Zverovich016aceb2017-08-26 09:09:43 -0700276 FMT_POWERS_OF_10(1000000000ull),
277 10000000000000000000ull
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800278};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800279
Victor Zverovich2768af22018-04-29 06:33:05 -0700280// Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.
281// These are generated by support/compute-powers.py.
282template <typename T>
283const uint64_t basic_data<T>::POW10_SIGNIFICANDS[] = {
Victor Zverovich9de31212018-08-15 06:54:43 -0700284 0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76,
285 0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df,
286 0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c,
287 0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5,
288 0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57,
289 0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7,
290 0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e,
291 0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996,
292 0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126,
293 0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053,
294 0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f,
295 0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b,
296 0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06,
297 0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb,
298 0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000,
299 0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984,
300 0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068,
301 0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8,
302 0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758,
303 0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85,
304 0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d,
305 0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25,
306 0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2,
307 0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a,
308 0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410,
309 0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129,
310 0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85,
311 0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841,
312 0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b,
Victor Zverovich2768af22018-04-29 06:33:05 -0700313};
314
315// Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding
316// to significands above.
317template <typename T>
318const int16_t basic_data<T>::POW10_EXPONENTS[] = {
319 -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954,
320 -927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661,
321 -635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369,
322 -343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77,
323 -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216,
324 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508,
325 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800,
326 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066
327};
328
Dhruv Paranjapeec218a32018-06-28 10:43:00 +0530329template <typename T> const char basic_data<T>::RESET_COLOR[] = "\x1b[0m";
330template <typename T> const wchar_t basic_data<T>::WRESET_COLOR[] = L"\x1b[0m";
331
Victor Zverovichcd900972018-04-21 17:26:24 -0700332FMT_FUNC fp operator*(fp x, fp y) {
333 // Multiply 32-bit parts of significands.
334 uint64_t mask = (1ULL << 32) - 1;
335 uint64_t a = x.f >> 32, b = x.f & mask;
336 uint64_t c = y.f >> 32, d = y.f & mask;
337 uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d;
338 // Compute mid 64-bit of result and round.
339 uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
Daniela Engert6cd66612018-04-30 10:07:43 +0200340 return fp(ac + (ad >> 32) + (bc >> 32) + (mid >> 32), x.e + y.e + 64);
Victor Zverovichcd900972018-04-21 17:26:24 -0700341}
Victor Zverovich468c2432018-05-27 10:57:26 -0700342
343FMT_FUNC fp get_cached_power(int min_exponent, int &pow10_exponent) {
344 const double one_over_log2_10 = 0.30102999566398114; // 1 / log2(10)
345 int index = static_cast<int>(std::ceil(
Victor Zverovich4e4b8572018-05-28 11:25:07 -0700346 (min_exponent + fp::significand_size - 1) * one_over_log2_10));
Victor Zverovich468c2432018-05-27 10:57:26 -0700347 // Decimal exponent of the first (smallest) cached power of 10.
348 const int first_dec_exp = -348;
Victor Zverovich9de31212018-08-15 06:54:43 -0700349 // Difference between 2 consecutive decimal exponents in cached powers of 10.
Victor Zverovich468c2432018-05-27 10:57:26 -0700350 const int dec_exp_step = 8;
351 index = (index - first_dec_exp - 1) / dec_exp_step + 1;
352 pow10_exponent = first_dec_exp + index * dec_exp_step;
353 return fp(data::POW10_SIGNIFICANDS[index], data::POW10_EXPONENTS[index]);
354}
Victor Zverovichcd900972018-04-21 17:26:24 -0700355} // namespace internal
356
vitaut24c309f2015-06-12 07:15:57 -0700357#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700358
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800359FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
Victor Zverovichdff21372014-12-16 07:01:01 -0800360 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
vitautc3ba6152015-08-07 07:34:58 -0700361 if (s.size() > INT_MAX)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800362 FMT_THROW(windows_error(ERROR_INVALID_PARAMETER, ERROR_MSG));
vitautc3ba6152015-08-07 07:34:58 -0700363 int s_size = static_cast<int>(s.size());
Vasili Galkaacb469a2018-03-12 14:43:29 +0200364 if (s_size == 0) {
365 // MultiByteToWideChar does not support zero length, handle separately.
366 buffer_.resize(1);
367 buffer_[0] = 0;
368 return;
369 }
370
vitautc3ba6152015-08-07 07:34:58 -0700371 int length = MultiByteToWideChar(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800372 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700373 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800374 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700375 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700376 length = MultiByteToWideChar(
vitautc3ba6152015-08-07 07:34:58 -0700377 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700378 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800379 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700380 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700381}
382
Victor Zverovichc333dca2017-02-19 08:41:38 -0800383FMT_FUNC internal::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700384 if (int error_code = convert(s)) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800385 FMT_THROW(windows_error(error_code,
Victor Zverovich8b76e972014-10-06 08:30:55 -0700386 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700387 }
388}
389
Victor Zverovichc333dca2017-02-19 08:41:38 -0800390FMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) {
vitautca747812015-08-07 07:08:46 -0700391 if (s.size() > INT_MAX)
392 return ERROR_INVALID_PARAMETER;
393 int s_size = static_cast<int>(s.size());
Vasili Galkaacb469a2018-03-12 14:43:29 +0200394 if (s_size == 0) {
395 // WideCharToMultiByte does not support zero length, handle separately.
396 buffer_.resize(1);
397 buffer_[0] = 0;
398 return 0;
399 }
400
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800401 int length = WideCharToMultiByte(
402 CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700403 if (length == 0)
404 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700405 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700406 length = WideCharToMultiByte(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800407 CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700408 if (length == 0)
409 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700410 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700411 return 0;
412}
413
Victor Zverovichc333dca2017-02-19 08:41:38 -0800414FMT_FUNC void windows_error::init(
Victor Zverovich7f351de2017-12-03 09:18:06 -0800415 int err_code, string_view format_str, format_args args) {
Carter Li3f574c12015-02-17 10:11:42 +0800416 error_code_ = err_code;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800417 memory_buffer buffer;
Victor Zveroviche022c212017-02-17 06:38:53 -0800418 internal::format_windows_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700419 std::runtime_error &base = *this;
Victor Zveroviche022c212017-02-17 06:38:53 -0800420 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700421}
422
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700423FMT_FUNC void internal::format_windows_error(
Victor Zverovichf6fd38b2018-01-15 08:22:31 -0800424 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700425 FMT_TRY {
Victor Zverovichc0954452018-01-06 09:09:50 -0800426 wmemory_buffer buf;
Victor Zverovichf1ede632018-03-04 10:33:42 -0800427 buf.resize(inline_buffer_size);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800428 for (;;) {
Victor Zverovichc0954452018-01-06 09:09:50 -0800429 wchar_t *system_message = &buf[0];
Victor Zverovichf85d5f42016-10-22 08:04:20 -0700430 int result = FormatMessageW(
431 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800432 FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
433 system_message, static_cast<uint32_t>(buf.size()), FMT_NULL);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800434 if (result != 0) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800435 utf16_to_utf8 utf8_message;
Michael Winterberg2a05a872016-03-02 17:35:34 -0800436 if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800437 writer w(out);
Victor Zveroviche022c212017-02-17 06:38:53 -0800438 w.write(message);
439 w.write(": ");
440 w.write(utf8_message);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800441 return;
442 }
443 break;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700444 }
Michael Winterberg2a05a872016-03-02 17:35:34 -0800445 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
446 break; // Can't get error message, report error code instead.
Victor Zverovichc0954452018-01-06 09:09:50 -0800447 buf.resize(buf.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700448 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700449 } FMT_CATCH(...) {}
Victor Zverovichc0954452018-01-06 09:09:50 -0800450 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700451}
vitaut24c309f2015-06-12 07:15:57 -0700452
453#endif // FMT_USE_WINDOWS_H
454
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700455FMT_FUNC void format_system_error(
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800456 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
vitaut24c309f2015-06-12 07:15:57 -0700457 FMT_TRY {
Victor Zverovich36634142017-12-26 09:00:22 -0800458 memory_buffer buf;
Victor Zverovichf1ede632018-03-04 10:33:42 -0800459 buf.resize(inline_buffer_size);
vitaut24c309f2015-06-12 07:15:57 -0700460 for (;;) {
Victor Zverovich36634142017-12-26 09:00:22 -0800461 char *system_message = &buf[0];
462 int result = safe_strerror(error_code, system_message, buf.size());
vitaut24c309f2015-06-12 07:15:57 -0700463 if (result == 0) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800464 writer w(out);
Victor Zverovichfefaf072017-02-14 16:29:47 -0500465 w.write(message);
466 w.write(": ");
467 w.write(system_message);
vitaut24c309f2015-06-12 07:15:57 -0700468 return;
469 }
470 if (result != ERANGE)
471 break; // Can't get error message, report error code instead.
Victor Zverovich36634142017-12-26 09:00:22 -0800472 buf.resize(buf.size() * 2);
vitaut24c309f2015-06-12 07:15:57 -0700473 }
474 } FMT_CATCH(...) {}
Victor Zverovichf164e4c2018-02-01 16:49:47 -0800475 format_error_code(out, error_code, message);
vitaut24c309f2015-06-12 07:15:57 -0700476}
Victor Zverovich53b4c312014-04-30 15:00:41 -0700477
jamboree7487bde2015-06-10 09:32:59 +0800478template <typename Char>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800479void basic_fixed_buffer<Char>::grow(std::size_t) {
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800480 FMT_THROW(std::runtime_error("buffer overflow"));
481}
482
Abdó Roig-Marangesaf0f21d2017-12-09 16:50:53 +0100483FMT_FUNC void internal::error_handler::on_error(const char *message) {
Victor Zverovich94edb1a2017-12-06 07:42:42 -0800484 FMT_THROW(format_error(message));
485}
486
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700487FMT_FUNC void report_system_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800488 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700489 report_error(format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700490}
491
vitaut24c309f2015-06-12 07:15:57 -0700492#if FMT_USE_WINDOWS_H
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700493FMT_FUNC void report_windows_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800494 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700495 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700496}
Victor Zverovich400812a2014-04-30 12:38:17 -0700497#endif
Victor Zverovichf7939862014-04-30 10:18:11 -0700498
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800499FMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800500 memory_buffer buffer;
Victor Zverovichfefaf072017-02-14 16:29:47 -0500501 vformat_to(buffer, format_str, args);
502 std::fwrite(buffer.data(), 1, buffer.size(), f);
Victor Zverovichd5b81962014-06-28 21:56:40 -0700503}
504
Daniela Engert2570f1a2018-04-26 20:32:14 +0200505FMT_FUNC void vprint(std::FILE *f, wstring_view format_str, wformat_args args) {
506 wmemory_buffer buffer;
507 vformat_to(buffer, format_str, args);
508 std::fwrite(buffer.data(), sizeof(wchar_t), buffer.size(), f);
509}
510
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800511FMT_FUNC void vprint(string_view format_str, format_args args) {
Victor Zverovich0028ce52016-08-26 17:23:13 -0700512 vprint(stdout, format_str, args);
Victor Zverovich163178e2014-09-25 07:08:25 -0700513}
514
Daniela Engert2570f1a2018-04-26 20:32:14 +0200515FMT_FUNC void vprint(wstring_view format_str, wformat_args args) {
516 vprint(stdout, format_str, args);
517}
518
Remotionce500632018-06-09 00:33:39 +0200519#ifndef FMT_EXTENDED_COLORS
Victor Zverovichbb471092018-03-04 11:25:40 -0800520FMT_FUNC void vprint_colored(color c, string_view format, format_args args) {
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700521 char escape[] = "\x1b[30m";
Ingo van Lilf4d88842015-11-02 19:14:47 +0100522 escape[3] = static_cast<char>('0' + c);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700523 std::fputs(escape, stdout);
Victor Zverovich0028ce52016-08-26 17:23:13 -0700524 vprint(format, args);
Dhruv Paranjapeec218a32018-06-28 10:43:00 +0530525 std::fputs(internal::data::RESET_COLOR, stdout);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700526}
527
Daniela Engert2570f1a2018-04-26 20:32:14 +0200528FMT_FUNC void vprint_colored(color c, wstring_view format, wformat_args args) {
529 wchar_t escape[] = L"\x1b[30m";
530 escape[3] = static_cast<wchar_t>('0' + c);
531 std::fputws(escape, stdout);
532 vprint(format, args);
Dhruv Paranjapeec218a32018-06-28 10:43:00 +0530533 std::fputws(internal::data::WRESET_COLOR, stdout);
Daniela Engert2570f1a2018-04-26 20:32:14 +0200534}
Remotionce500632018-06-09 00:33:39 +0200535#else
536namespace internal {
537FMT_CONSTEXPR void to_esc(uint8_t c, char out[], int offset) {
538 out[offset + 0] = static_cast<char>('0' + c / 100);
539 out[offset + 1] = static_cast<char>('0' + c / 10 % 10);
540 out[offset + 2] = static_cast<char>('0' + c % 10);
541}
542} // namespace internal
543
544FMT_FUNC void vprint_rgb(rgb fd, string_view format, format_args args) {
545 char escape_fd[] = "\x1b[38;2;000;000;000m";
Remotionce500632018-06-09 00:33:39 +0200546 internal::to_esc(fd.r, escape_fd, 7);
547 internal::to_esc(fd.g, escape_fd, 11);
548 internal::to_esc(fd.b, escape_fd, 15);
549
550 std::fputs(escape_fd, stdout);
551 vprint(format, args);
Dhruv Paranjapeec218a32018-06-28 10:43:00 +0530552 std::fputs(internal::data::RESET_COLOR, stdout);
Remotionce500632018-06-09 00:33:39 +0200553}
554
555FMT_FUNC void vprint_rgb(rgb fd, rgb bg, string_view format, format_args args) {
556 char escape_fd[] = "\x1b[38;2;000;000;000m"; // foreground color
557 char escape_bg[] = "\x1b[48;2;000;000;000m"; // background color
Remotionce500632018-06-09 00:33:39 +0200558 internal::to_esc(fd.r, escape_fd, 7);
559 internal::to_esc(fd.g, escape_fd, 11);
560 internal::to_esc(fd.b, escape_fd, 15);
561
562 internal::to_esc(bg.r, escape_bg, 7);
563 internal::to_esc(bg.g, escape_bg, 11);
564 internal::to_esc(bg.b, escape_bg, 15);
565
566 std::fputs(escape_fd, stdout);
567 std::fputs(escape_bg, stdout);
568 vprint(format, args);
Dhruv Paranjapeec218a32018-06-28 10:43:00 +0530569 std::fputs(internal::data::RESET_COLOR, stdout);
Remotionce500632018-06-09 00:33:39 +0200570}
571#endif
Daniela Engert2570f1a2018-04-26 20:32:14 +0200572
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800573FMT_FUNC locale locale_provider::locale() { return fmt::locale(); }
574
Victor Zverovich838400d2018-05-12 08:33:51 -0700575FMT_END_NAMESPACE
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700576
Ingo van Lilb4b13ee2015-11-02 12:34:46 +0100577#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +0000578# pragma warning(pop)
579#endif
Victor Zverovich3da71d52018-03-21 07:50:59 -0700580
581#endif // FMT_FORMAT_INL_H_