blob: e66bbb7a2ca65782bdc7abcf0a5ace1ac5bca7ef [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 Zverovich7f351de2017-12-03 09:18:06 -0800205template <typename Char>
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800206FMT_FUNC Char internal::thousands_sep(locale_provider *lp) {
207 std::locale loc = lp ? lp->locale().get() : std::locale();
208 return std::use_facet<std::numpunct<Char>>(loc).thousands_sep();
Victor Zverovich7f351de2017-12-03 09:18:06 -0800209}
210
Victor Zverovichc333dca2017-02-19 08:41:38 -0800211FMT_FUNC void system_error::init(
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800212 int err_code, string_view format_str, format_args args) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800213 error_code_ = err_code;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800214 memory_buffer buffer;
215 format_system_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700216 std::runtime_error &base = *this;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800217 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700218}
219
Victor Zverovichcd900972018-04-21 17:26:24 -0700220namespace internal {
Victor Zverovichb605b392013-09-09 22:21:40 -0700221template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700222int char_traits<char>::format_float(
Victor Zverovichb60a5c52018-05-28 20:16:30 -0700223 char *buffer, std::size_t size, const char *format, int precision, T value) {
Victor Zverovichb605b392013-09-09 22:21:40 -0700224 return precision < 0 ?
Victor Zverovichb60a5c52018-05-28 20:16:30 -0700225 FMT_SNPRINTF(buffer, size, format, value) :
226 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovichb605b392013-09-09 22:21:40 -0700227}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700228
Victor Zverovichb605b392013-09-09 22:21:40 -0700229template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700230int char_traits<wchar_t>::format_float(
Victor Zverovichb60a5c52018-05-28 20:16:30 -0700231 wchar_t *buffer, std::size_t size, const wchar_t *format, int precision,
232 T value) {
Victor Zverovichb605b392013-09-09 22:21:40 -0700233 return precision < 0 ?
Victor Zverovichb60a5c52018-05-28 20:16:30 -0700234 FMT_SWPRINTF(buffer, size, format, value) :
235 FMT_SWPRINTF(buffer, size, format, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700236}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800237
Victor Zverovich311251e2014-11-29 06:58:00 -0800238template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700239const char basic_data<T>::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800240 "0001020304050607080910111213141516171819"
241 "2021222324252627282930313233343536373839"
242 "4041424344454647484950515253545556575859"
243 "6061626364656667686970717273747576777879"
244 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800245
Victor Zverovichf1d85162014-02-19 13:02:22 -0800246#define FMT_POWERS_OF_10(factor) \
247 factor * 10, \
248 factor * 100, \
249 factor * 1000, \
250 factor * 10000, \
251 factor * 100000, \
252 factor * 1000000, \
253 factor * 10000000, \
254 factor * 100000000, \
255 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800256
Victor Zverovich311251e2014-11-29 06:58:00 -0800257template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700258const uint32_t basic_data<T>::POWERS_OF_10_32[] = {
Victor Zverovich311251e2014-11-29 06:58:00 -0800259 0, FMT_POWERS_OF_10(1)
260};
261
262template <typename T>
Victor Zverovichcd900972018-04-21 17:26:24 -0700263const uint64_t basic_data<T>::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800264 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800265 FMT_POWERS_OF_10(1),
Victor Zverovich016aceb2017-08-26 09:09:43 -0700266 FMT_POWERS_OF_10(1000000000ull),
267 10000000000000000000ull
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800268};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800269
Victor Zverovich2768af22018-04-29 06:33:05 -0700270// Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.
271// These are generated by support/compute-powers.py.
272template <typename T>
273const uint64_t basic_data<T>::POW10_SIGNIFICANDS[] = {
Victor Zverovich2f257b72018-05-27 08:04:30 -0700274 0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76, 0xcf42894a5dce35ea,
275 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df, 0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f,
276 0xbe5691ef416bd60c, 0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5,
277 0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57, 0xc21094364dfb5637,
278 0x9096ea6f3848984f, 0xd77485cb25823ac7, 0xa086cfcd97bf97f4, 0xef340a98172aace5,
279 0xb23867fb2a35b28e, 0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996,
280 0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126, 0xb5b5ada8aaff80b8,
281 0x87625f056c7c4a8b, 0xc9bcff6034c13053, 0x964e858c91ba2655, 0xdff9772470297ebd,
282 0xa6dfbd9fb8e5b88f, 0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b,
283 0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06, 0xaa242499697392d3,
284 0xfd87b5f28300ca0e, 0xbce5086492111aeb, 0x8cbccc096f5088cc, 0xd1b71758e219652c,
285 0x9c40000000000000, 0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984,
286 0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068, 0x9f4f2726179a2245,
287 0xed63a231d4c4fb27, 0xb0de65388cc8ada8, 0x83c7088e1aab65db, 0xc45d1df942711d9a,
288 0x924d692ca61be758, 0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85,
289 0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d, 0x952ab45cfa97a0b3,
290 0xde469fbd99a05fe3, 0xa59bc234db398c25, 0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece,
291 0x88fcf317f22241e2, 0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a,
292 0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410, 0x8bab8eefb6409c1a,
293 0xd01fef10a657842c, 0x9b10a4e5e9913129, 0xe7109bfba19c0c9d, 0xac2820d9623bf429,
294 0x80444b5e7aa7cf85, 0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841,
295 0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b
Victor Zverovich2768af22018-04-29 06:33:05 -0700296};
297
298// Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding
299// to significands above.
300template <typename T>
301const int16_t basic_data<T>::POW10_EXPONENTS[] = {
302 -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954,
303 -927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661,
304 -635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369,
305 -343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77,
306 -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216,
307 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508,
308 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800,
309 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066
310};
311
Dhruv Paranjapeec218a32018-06-28 10:43:00 +0530312template <typename T> const char basic_data<T>::RESET_COLOR[] = "\x1b[0m";
313template <typename T> const wchar_t basic_data<T>::WRESET_COLOR[] = L"\x1b[0m";
314
Victor Zverovichcd900972018-04-21 17:26:24 -0700315FMT_FUNC fp operator*(fp x, fp y) {
316 // Multiply 32-bit parts of significands.
317 uint64_t mask = (1ULL << 32) - 1;
318 uint64_t a = x.f >> 32, b = x.f & mask;
319 uint64_t c = y.f >> 32, d = y.f & mask;
320 uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d;
321 // Compute mid 64-bit of result and round.
322 uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
Daniela Engert6cd66612018-04-30 10:07:43 +0200323 return fp(ac + (ad >> 32) + (bc >> 32) + (mid >> 32), x.e + y.e + 64);
Victor Zverovichcd900972018-04-21 17:26:24 -0700324}
Victor Zverovich468c2432018-05-27 10:57:26 -0700325
326FMT_FUNC fp get_cached_power(int min_exponent, int &pow10_exponent) {
327 const double one_over_log2_10 = 0.30102999566398114; // 1 / log2(10)
328 int index = static_cast<int>(std::ceil(
Victor Zverovich4e4b8572018-05-28 11:25:07 -0700329 (min_exponent + fp::significand_size - 1) * one_over_log2_10));
Victor Zverovich468c2432018-05-27 10:57:26 -0700330 // Decimal exponent of the first (smallest) cached power of 10.
331 const int first_dec_exp = -348;
332 // Difference between two consecutive decimal exponents in cached powers of 10.
333 const int dec_exp_step = 8;
334 index = (index - first_dec_exp - 1) / dec_exp_step + 1;
335 pow10_exponent = first_dec_exp + index * dec_exp_step;
336 return fp(data::POW10_SIGNIFICANDS[index], data::POW10_EXPONENTS[index]);
337}
Victor Zverovichcd900972018-04-21 17:26:24 -0700338} // namespace internal
339
vitaut24c309f2015-06-12 07:15:57 -0700340#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700341
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800342FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
Victor Zverovichdff21372014-12-16 07:01:01 -0800343 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
vitautc3ba6152015-08-07 07:34:58 -0700344 if (s.size() > INT_MAX)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800345 FMT_THROW(windows_error(ERROR_INVALID_PARAMETER, ERROR_MSG));
vitautc3ba6152015-08-07 07:34:58 -0700346 int s_size = static_cast<int>(s.size());
Vasili Galkaacb469a2018-03-12 14:43:29 +0200347 if (s_size == 0) {
348 // MultiByteToWideChar does not support zero length, handle separately.
349 buffer_.resize(1);
350 buffer_[0] = 0;
351 return;
352 }
353
vitautc3ba6152015-08-07 07:34:58 -0700354 int length = MultiByteToWideChar(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800355 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700356 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800357 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700358 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700359 length = MultiByteToWideChar(
vitautc3ba6152015-08-07 07:34:58 -0700360 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700361 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800362 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700363 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700364}
365
Victor Zverovichc333dca2017-02-19 08:41:38 -0800366FMT_FUNC internal::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700367 if (int error_code = convert(s)) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800368 FMT_THROW(windows_error(error_code,
Victor Zverovich8b76e972014-10-06 08:30:55 -0700369 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700370 }
371}
372
Victor Zverovichc333dca2017-02-19 08:41:38 -0800373FMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) {
vitautca747812015-08-07 07:08:46 -0700374 if (s.size() > INT_MAX)
375 return ERROR_INVALID_PARAMETER;
376 int s_size = static_cast<int>(s.size());
Vasili Galkaacb469a2018-03-12 14:43:29 +0200377 if (s_size == 0) {
378 // WideCharToMultiByte does not support zero length, handle separately.
379 buffer_.resize(1);
380 buffer_[0] = 0;
381 return 0;
382 }
383
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800384 int length = WideCharToMultiByte(
385 CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700386 if (length == 0)
387 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700388 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700389 length = WideCharToMultiByte(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800390 CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700391 if (length == 0)
392 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700393 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700394 return 0;
395}
396
Victor Zverovichc333dca2017-02-19 08:41:38 -0800397FMT_FUNC void windows_error::init(
Victor Zverovich7f351de2017-12-03 09:18:06 -0800398 int err_code, string_view format_str, format_args args) {
Carter Li3f574c12015-02-17 10:11:42 +0800399 error_code_ = err_code;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800400 memory_buffer buffer;
Victor Zveroviche022c212017-02-17 06:38:53 -0800401 internal::format_windows_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700402 std::runtime_error &base = *this;
Victor Zveroviche022c212017-02-17 06:38:53 -0800403 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700404}
405
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700406FMT_FUNC void internal::format_windows_error(
Victor Zverovichf6fd38b2018-01-15 08:22:31 -0800407 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700408 FMT_TRY {
Victor Zverovichc0954452018-01-06 09:09:50 -0800409 wmemory_buffer buf;
Victor Zverovichf1ede632018-03-04 10:33:42 -0800410 buf.resize(inline_buffer_size);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800411 for (;;) {
Victor Zverovichc0954452018-01-06 09:09:50 -0800412 wchar_t *system_message = &buf[0];
Victor Zverovichf85d5f42016-10-22 08:04:20 -0700413 int result = FormatMessageW(
414 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800415 FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
416 system_message, static_cast<uint32_t>(buf.size()), FMT_NULL);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800417 if (result != 0) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800418 utf16_to_utf8 utf8_message;
Michael Winterberg2a05a872016-03-02 17:35:34 -0800419 if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800420 writer w(out);
Victor Zveroviche022c212017-02-17 06:38:53 -0800421 w.write(message);
422 w.write(": ");
423 w.write(utf8_message);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800424 return;
425 }
426 break;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700427 }
Michael Winterberg2a05a872016-03-02 17:35:34 -0800428 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
429 break; // Can't get error message, report error code instead.
Victor Zverovichc0954452018-01-06 09:09:50 -0800430 buf.resize(buf.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700431 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700432 } FMT_CATCH(...) {}
Victor Zverovichc0954452018-01-06 09:09:50 -0800433 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700434}
vitaut24c309f2015-06-12 07:15:57 -0700435
436#endif // FMT_USE_WINDOWS_H
437
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700438FMT_FUNC void format_system_error(
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800439 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
vitaut24c309f2015-06-12 07:15:57 -0700440 FMT_TRY {
Victor Zverovich36634142017-12-26 09:00:22 -0800441 memory_buffer buf;
Victor Zverovichf1ede632018-03-04 10:33:42 -0800442 buf.resize(inline_buffer_size);
vitaut24c309f2015-06-12 07:15:57 -0700443 for (;;) {
Victor Zverovich36634142017-12-26 09:00:22 -0800444 char *system_message = &buf[0];
445 int result = safe_strerror(error_code, system_message, buf.size());
vitaut24c309f2015-06-12 07:15:57 -0700446 if (result == 0) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800447 writer w(out);
Victor Zverovichfefaf072017-02-14 16:29:47 -0500448 w.write(message);
449 w.write(": ");
450 w.write(system_message);
vitaut24c309f2015-06-12 07:15:57 -0700451 return;
452 }
453 if (result != ERANGE)
454 break; // Can't get error message, report error code instead.
Victor Zverovich36634142017-12-26 09:00:22 -0800455 buf.resize(buf.size() * 2);
vitaut24c309f2015-06-12 07:15:57 -0700456 }
457 } FMT_CATCH(...) {}
Victor Zverovichf164e4c2018-02-01 16:49:47 -0800458 format_error_code(out, error_code, message);
vitaut24c309f2015-06-12 07:15:57 -0700459}
Victor Zverovich53b4c312014-04-30 15:00:41 -0700460
jamboree7487bde2015-06-10 09:32:59 +0800461template <typename Char>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800462void basic_fixed_buffer<Char>::grow(std::size_t) {
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800463 FMT_THROW(std::runtime_error("buffer overflow"));
464}
465
Abdó Roig-Marangesaf0f21d2017-12-09 16:50:53 +0100466FMT_FUNC void internal::error_handler::on_error(const char *message) {
Victor Zverovich94edb1a2017-12-06 07:42:42 -0800467 FMT_THROW(format_error(message));
468}
469
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700470FMT_FUNC void report_system_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800471 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700472 report_error(format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700473}
474
vitaut24c309f2015-06-12 07:15:57 -0700475#if FMT_USE_WINDOWS_H
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700476FMT_FUNC void report_windows_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800477 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700478 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700479}
Victor Zverovich400812a2014-04-30 12:38:17 -0700480#endif
Victor Zverovichf7939862014-04-30 10:18:11 -0700481
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800482FMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800483 memory_buffer buffer;
Victor Zverovichfefaf072017-02-14 16:29:47 -0500484 vformat_to(buffer, format_str, args);
485 std::fwrite(buffer.data(), 1, buffer.size(), f);
Victor Zverovichd5b81962014-06-28 21:56:40 -0700486}
487
Daniela Engert2570f1a2018-04-26 20:32:14 +0200488FMT_FUNC void vprint(std::FILE *f, wstring_view format_str, wformat_args args) {
489 wmemory_buffer buffer;
490 vformat_to(buffer, format_str, args);
491 std::fwrite(buffer.data(), sizeof(wchar_t), buffer.size(), f);
492}
493
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800494FMT_FUNC void vprint(string_view format_str, format_args args) {
Victor Zverovich0028ce52016-08-26 17:23:13 -0700495 vprint(stdout, format_str, args);
Victor Zverovich163178e2014-09-25 07:08:25 -0700496}
497
Daniela Engert2570f1a2018-04-26 20:32:14 +0200498FMT_FUNC void vprint(wstring_view format_str, wformat_args args) {
499 vprint(stdout, format_str, args);
500}
501
Remotionce500632018-06-09 00:33:39 +0200502#ifndef FMT_EXTENDED_COLORS
Victor Zverovichbb471092018-03-04 11:25:40 -0800503FMT_FUNC void vprint_colored(color c, string_view format, format_args args) {
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700504 char escape[] = "\x1b[30m";
Ingo van Lilf4d88842015-11-02 19:14:47 +0100505 escape[3] = static_cast<char>('0' + c);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700506 std::fputs(escape, stdout);
Victor Zverovich0028ce52016-08-26 17:23:13 -0700507 vprint(format, args);
Dhruv Paranjapeec218a32018-06-28 10:43:00 +0530508 std::fputs(internal::data::RESET_COLOR, stdout);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700509}
510
Daniela Engert2570f1a2018-04-26 20:32:14 +0200511FMT_FUNC void vprint_colored(color c, wstring_view format, wformat_args args) {
512 wchar_t escape[] = L"\x1b[30m";
513 escape[3] = static_cast<wchar_t>('0' + c);
514 std::fputws(escape, stdout);
515 vprint(format, args);
Dhruv Paranjapeec218a32018-06-28 10:43:00 +0530516 std::fputws(internal::data::WRESET_COLOR, stdout);
Daniela Engert2570f1a2018-04-26 20:32:14 +0200517}
Remotionce500632018-06-09 00:33:39 +0200518#else
519namespace internal {
520FMT_CONSTEXPR void to_esc(uint8_t c, char out[], int offset) {
521 out[offset + 0] = static_cast<char>('0' + c / 100);
522 out[offset + 1] = static_cast<char>('0' + c / 10 % 10);
523 out[offset + 2] = static_cast<char>('0' + c % 10);
524}
525} // namespace internal
526
527FMT_FUNC void vprint_rgb(rgb fd, string_view format, format_args args) {
528 char escape_fd[] = "\x1b[38;2;000;000;000m";
Remotionce500632018-06-09 00:33:39 +0200529 internal::to_esc(fd.r, escape_fd, 7);
530 internal::to_esc(fd.g, escape_fd, 11);
531 internal::to_esc(fd.b, escape_fd, 15);
532
533 std::fputs(escape_fd, stdout);
534 vprint(format, args);
Dhruv Paranjapeec218a32018-06-28 10:43:00 +0530535 std::fputs(internal::data::RESET_COLOR, stdout);
Remotionce500632018-06-09 00:33:39 +0200536}
537
538FMT_FUNC void vprint_rgb(rgb fd, rgb bg, string_view format, format_args args) {
539 char escape_fd[] = "\x1b[38;2;000;000;000m"; // foreground color
540 char escape_bg[] = "\x1b[48;2;000;000;000m"; // background color
Remotionce500632018-06-09 00:33:39 +0200541 internal::to_esc(fd.r, escape_fd, 7);
542 internal::to_esc(fd.g, escape_fd, 11);
543 internal::to_esc(fd.b, escape_fd, 15);
544
545 internal::to_esc(bg.r, escape_bg, 7);
546 internal::to_esc(bg.g, escape_bg, 11);
547 internal::to_esc(bg.b, escape_bg, 15);
548
549 std::fputs(escape_fd, stdout);
550 std::fputs(escape_bg, 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#endif
Daniela Engert2570f1a2018-04-26 20:32:14 +0200555
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800556FMT_FUNC locale locale_provider::locale() { return fmt::locale(); }
557
Victor Zverovich838400d2018-05-12 08:33:51 -0700558FMT_END_NAMESPACE
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700559
Ingo van Lilb4b13ee2015-11-02 12:34:46 +0100560#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +0000561# pragma warning(pop)
562#endif
Victor Zverovich3da71d52018-03-21 07:50:59 -0700563
564#endif // FMT_FORMAT_INL_H_