blob: 32975ca107ca38730369296266357fef94d0613e [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 Zveroviche160c2b2016-05-22 16:07:50 -07008#include "fmt/format.h"
Victor Zverovich7f351de2017-12-03 09:18:06 -08009#include "fmt/locale.h"
Victor Zverovichfbfedcf2013-01-14 15:16:20 -080010
Victor Zverovich859a4972014-04-30 06:55:21 -070011#include <string.h>
12
Victor Zverovich72f896d2012-12-12 09:17:28 -080013#include <cctype>
Victor Zverovich5d15bdd2014-07-01 16:23:50 -070014#include <cerrno>
Victor Zverovichf28645f2014-04-24 12:37:06 -070015#include <climits>
Victor Zverovich9ff3b972013-09-07 10:15:08 -070016#include <cmath>
Victor Zverovicha684d0c2013-12-27 08:00:10 -080017#include <cstdarg>
vitaut7dcf0512015-11-13 06:52:13 -080018#include <cstddef> // for std::ptrdiff_t
Victor Zverovich9ff3b972013-09-07 10:15:08 -070019
vitaut24c309f2015-06-12 07:15:57 -070020#if defined(_WIN32) && defined(__MINGW32__)
21# include <cstring>
22#endif
23
24#if FMT_USE_WINDOWS_H
vitaut67ce3942015-04-30 07:48:36 -070025# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
26# include <windows.h>
27# else
28# define NOMINMAX
29# include <windows.h>
30# undef NOMINMAX
31# endif
Ryuuke5a9dc8f2015-02-08 16:08:29 +000032#endif
33
Victor Zverovich8b76e972014-10-06 08:30:55 -070034#if FMT_EXCEPTIONS
35# define FMT_TRY try
36# define FMT_CATCH(x) catch (x)
37#else
38# define FMT_TRY if (true)
39# define FMT_CATCH(x) if (false)
40#endif
41
Victor Zverovichb83241f2017-10-19 07:28:17 -070042#ifdef __GNUC__
Victor Zverovich07f8ffc2017-08-21 06:50:57 -070043// Disable the warning about declaration shadowing because it affects too
44// many valid cases.
Victor Zverovichb83241f2017-10-19 07:28:17 -070045# pragma GCC diagnostic ignored "-Wshadow"
46#endif
Victor Zverovich07f8ffc2017-08-21 06:50:57 -070047
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 Zverovichc333dca2017-02-19 08:41:38 -080059static inline fmt::internal::null<> strerror_r(int, char *, ...) {
60 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070061}
Victor Zverovichc333dca2017-02-19 08:41:38 -080062static inline fmt::internal::null<> strerror_s(char *, std::size_t, ...) {
63 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070064}
65
vitaut8725d072015-06-12 07:56:58 -070066namespace fmt {
Victor Zverovichb26e76e2016-06-14 08:11:33 -070067
Victor Zverovich9bb213e2016-08-25 08:38:07 -070068FMT_FUNC format_error::~format_error() throw() {}
Victor Zverovichc333dca2017-02-19 08:41:38 -080069FMT_FUNC system_error::~system_error() throw() {}
Victor Zverovichb26e76e2016-06-14 08:11:33 -070070
Victor Zverovich9ff3b972013-09-07 10:15:08 -070071namespace {
72
73#ifndef _MSC_VER
Victor Zverovichb9a568b2014-09-19 07:51:42 -070074# define FMT_SNPRINTF snprintf
Victor Zverovicha684d0c2013-12-27 08:00:10 -080075#else // _MSC_VER
Victor Zverovich406c6122014-08-19 08:47:38 -070076inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -080077 va_list args;
78 va_start(args, format);
79 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
80 va_end(args);
81 return result;
82}
Victor Zverovichb9a568b2014-09-19 07:51:42 -070083# define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -070084#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -080085
cstamford55836ca2015-03-10 07:04:31 +000086#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
87# define FMT_SWPRINTF snwprintf
88#else
89# define FMT_SWPRINTF swprintf
90#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
91
Victor Zverovich7004d1e2015-02-08 19:54:39 -080092const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -070093
Victor Zverovich50e71672017-02-18 06:52:52 -080094typedef void (*FormatFunc)(buffer &, int, string_view);
Victor Zverovich22f75d82014-09-03 08:03:05 -070095
Victor Zverovichf2c9df82014-09-05 08:44:41 -070096// Portable thread-safe version of strerror.
97// Sets buffer to point to a string describing the error code.
98// This can be either a pointer to a string stored in buffer,
99// or a pointer to some static immutable string.
100// Returns one of the following values:
101// 0 - success
102// ERANGE - buffer is not large enough to store the error message
103// other - failure
104// Buffer should be at least of size 1.
105int safe_strerror(
Carter Lie2583ab2015-02-14 09:58:29 +0800106 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
vitaut8ab665a2015-06-22 08:17:23 -0700107 FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
vitaut341b98c2015-03-14 13:39:33 -0700108
vitaut341b98c2015-03-14 13:39:33 -0700109 class StrError {
110 private:
111 int error_code_;
112 char *&buffer_;
113 std::size_t buffer_size_;
114
vitautda052ae2015-03-21 07:53:39 -0700115 // A noop assignment operator to avoid bogus warnings.
116 void operator=(const StrError &) {}
117
vitaut341b98c2015-03-14 13:39:33 -0700118 // Handle the result of XSI-compliant version of strerror_r.
119 int handle(int result) {
vitaute1776ac2015-03-14 14:05:02 -0700120 // glibc versions before 2.13 return result in errno.
121 return result == -1 ? errno : result;
vitaut341b98c2015-03-14 13:39:33 -0700122 }
123
124 // Handle the result of GNU-specific version of strerror_r.
125 int handle(char *message) {
126 // If the buffer is full then the message is probably truncated.
127 if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
128 return ERANGE;
129 buffer_ = message;
130 return 0;
131 }
132
133 // Handle the case when strerror_r is not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800134 int handle(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700135 return fallback(strerror_s(buffer_, buffer_size_, error_code_));
136 }
137
138 // Fallback to strerror_s when strerror_r is not available.
139 int fallback(int result) {
140 // If the buffer is full then the message is probably truncated.
141 return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
142 ERANGE : result;
143 }
144
145 // Fallback to strerror if strerror_r and strerror_s are not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800146 int fallback(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700147 errno = 0;
148 buffer_ = strerror(error_code_);
149 return errno;
150 }
151
152 public:
Radu Popescu0affb232015-08-04 12:52:44 +0200153 StrError(int err_code, char *&buf, std::size_t buf_size)
154 : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
vitaut341b98c2015-03-14 13:39:33 -0700155
vitaut63f6c102015-06-14 09:36:23 -0700156 int run() {
157 strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r.
158 return handle(strerror_r(error_code_, buffer_, buffer_size_));
159 }
vitaut341b98c2015-03-14 13:39:33 -0700160 };
161 return StrError(error_code, buffer, buffer_size).run();
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700162}
163
Victor Zverovichfefaf072017-02-14 16:29:47 -0500164void format_error_code(buffer &out, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800165 string_view message) FMT_NOEXCEPT {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700166 // Report error code making sure that the output fits into
167 // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
168 // bad_alloc.
Victor Zverovichf423e462017-03-11 07:43:26 -0800169 out.resize(0);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700170 static const char SEP[] = ": ";
vitaut1addec92015-03-21 20:16:36 -0700171 static const char ERROR_STR[] = "error ";
vitaut1addec92015-03-21 20:16:36 -0700172 // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
173 std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800174 typedef internal::int_traits<int>::main_type main_type;
175 main_type abs_value = static_cast<main_type>(error_code);
vitaut9d577ca2016-03-02 07:01:21 -0800176 if (internal::is_negative(error_code)) {
177 abs_value = 0 - abs_value;
178 ++error_code_size;
179 }
vitautbfdca8b2016-04-20 09:11:33 -0700180 error_code_size += internal::count_digits(abs_value);
Victor Zverovich36634142017-12-26 09:00:22 -0800181 basic_writer<buffer> w(out);
Victor Zverovichec15ef72017-01-22 07:40:21 -0800182 if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) {
Victor Zverovichfefaf072017-02-14 16:29:47 -0500183 w.write(message);
184 w.write(SEP);
Victor Zverovichec15ef72017-01-22 07:40:21 -0800185 }
Victor Zverovichfefaf072017-02-14 16:29:47 -0500186 w.write(ERROR_STR);
187 w.write(error_code);
vitautbfdca8b2016-04-20 09:11:33 -0700188 assert(out.size() <= internal::INLINE_BUFFER_SIZE);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700189}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700190
vitautbfdca8b2016-04-20 09:11:33 -0700191void report_error(FormatFunc func, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800192 string_view message) FMT_NOEXCEPT {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800193 memory_buffer full_message;
Victor Zverovich88e0db82014-09-05 08:04:26 -0700194 func(full_message, error_code, message);
195 // Use Writer::data instead of Writer::c_str to avoid potential memory
196 // allocation.
197 std::fwrite(full_message.data(), full_message.size(), 1, stderr);
198 std::fputc('\n', stderr);
Victor Zverovichb605b392013-09-09 22:21:40 -0700199}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700200} // namespace
vitaut270069b2015-06-16 07:36:32 -0700201
Victor Zverovich7f351de2017-12-03 09:18:06 -0800202template <typename Char>
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800203FMT_FUNC Char internal::thousands_sep(locale_provider *lp) {
204 std::locale loc = lp ? lp->locale().get() : std::locale();
205 return std::use_facet<std::numpunct<Char>>(loc).thousands_sep();
Victor Zverovich7f351de2017-12-03 09:18:06 -0800206}
207
Victor Zverovichc333dca2017-02-19 08:41:38 -0800208FMT_FUNC void system_error::init(
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800209 int err_code, string_view format_str, format_args args) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800210 error_code_ = err_code;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800211 memory_buffer buffer;
212 format_system_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700213 std::runtime_error &base = *this;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800214 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700215}
216
Victor Zverovichb605b392013-09-09 22:21:40 -0700217template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800218int internal::char_traits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700219 char *buffer, std::size_t size, const char *format,
220 unsigned width, int precision, T value) {
221 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700222 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700223 FMT_SNPRINTF(buffer, size, format, value) :
224 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700225 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700226 return precision < 0 ?
227 FMT_SNPRINTF(buffer, size, format, width, value) :
228 FMT_SNPRINTF(buffer, size, format, width, precision, value);
229}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700230
Victor Zverovichb605b392013-09-09 22:21:40 -0700231template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800232int internal::char_traits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700233 wchar_t *buffer, std::size_t size, const wchar_t *format,
234 unsigned width, int precision, T value) {
235 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700236 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000237 FMT_SWPRINTF(buffer, size, format, value) :
238 FMT_SWPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700239 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700240 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000241 FMT_SWPRINTF(buffer, size, format, width, value) :
242 FMT_SWPRINTF(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700243}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800244
Victor Zverovich311251e2014-11-29 06:58:00 -0800245template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800246const char internal::basic_data<T>::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800247 "0001020304050607080910111213141516171819"
248 "2021222324252627282930313233343536373839"
249 "4041424344454647484950515253545556575859"
250 "6061626364656667686970717273747576777879"
251 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800252
Victor Zverovichf1d85162014-02-19 13:02:22 -0800253#define FMT_POWERS_OF_10(factor) \
254 factor * 10, \
255 factor * 100, \
256 factor * 1000, \
257 factor * 10000, \
258 factor * 100000, \
259 factor * 1000000, \
260 factor * 10000000, \
261 factor * 100000000, \
262 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800263
Victor Zverovich311251e2014-11-29 06:58:00 -0800264template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800265const uint32_t internal::basic_data<T>::POWERS_OF_10_32[] = {
Victor Zverovich311251e2014-11-29 06:58:00 -0800266 0, FMT_POWERS_OF_10(1)
267};
268
269template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800270const uint64_t internal::basic_data<T>::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800271 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800272 FMT_POWERS_OF_10(1),
Victor Zverovich016aceb2017-08-26 09:09:43 -0700273 FMT_POWERS_OF_10(1000000000ull),
274 10000000000000000000ull
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800275};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800276
vitaut24c309f2015-06-12 07:15:57 -0700277#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700278
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800279FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
Victor Zverovichdff21372014-12-16 07:01:01 -0800280 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
vitautc3ba6152015-08-07 07:34:58 -0700281 if (s.size() > INT_MAX)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800282 FMT_THROW(windows_error(ERROR_INVALID_PARAMETER, ERROR_MSG));
vitautc3ba6152015-08-07 07:34:58 -0700283 int s_size = static_cast<int>(s.size());
284 int length = MultiByteToWideChar(
285 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700286 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800287 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700288 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700289 length = MultiByteToWideChar(
vitautc3ba6152015-08-07 07:34:58 -0700290 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700291 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800292 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700293 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700294}
295
Victor Zverovichc333dca2017-02-19 08:41:38 -0800296FMT_FUNC internal::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700297 if (int error_code = convert(s)) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800298 FMT_THROW(windows_error(error_code,
Victor Zverovich8b76e972014-10-06 08:30:55 -0700299 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700300 }
301}
302
Victor Zverovichc333dca2017-02-19 08:41:38 -0800303FMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) {
vitautca747812015-08-07 07:08:46 -0700304 if (s.size() > INT_MAX)
305 return ERROR_INVALID_PARAMETER;
306 int s_size = static_cast<int>(s.size());
307 int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700308 if (length == 0)
309 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700310 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700311 length = WideCharToMultiByte(
vitautca747812015-08-07 07:08:46 -0700312 CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700313 if (length == 0)
314 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700315 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700316 return 0;
317}
318
Victor Zverovichc333dca2017-02-19 08:41:38 -0800319FMT_FUNC void windows_error::init(
Victor Zverovich7f351de2017-12-03 09:18:06 -0800320 int err_code, string_view format_str, format_args args) {
Carter Li3f574c12015-02-17 10:11:42 +0800321 error_code_ = err_code;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800322 memory_buffer buffer;
Victor Zveroviche022c212017-02-17 06:38:53 -0800323 internal::format_windows_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700324 std::runtime_error &base = *this;
Victor Zveroviche022c212017-02-17 06:38:53 -0800325 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700326}
327
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700328FMT_FUNC void internal::format_windows_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800329 buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700330 FMT_TRY {
Victor Zverovichc0954452018-01-06 09:09:50 -0800331 wmemory_buffer buf;
332 buf.resize(INLINE_BUFFER_SIZE);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800333 for (;;) {
Victor Zverovichc0954452018-01-06 09:09:50 -0800334 wchar_t *system_message = &buf[0];
Victor Zverovichf85d5f42016-10-22 08:04:20 -0700335 int result = FormatMessageW(
336 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
337 0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
Victor Zverovichc0954452018-01-06 09:09:50 -0800338 system_message, static_cast<uint32_t>(buf.size()), 0);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800339 if (result != 0) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800340 utf16_to_utf8 utf8_message;
Michael Winterberg2a05a872016-03-02 17:35:34 -0800341 if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
Victor Zverovichc0954452018-01-06 09:09:50 -0800342 basic_writer<buffer> w(out);
Victor Zveroviche022c212017-02-17 06:38:53 -0800343 w.write(message);
344 w.write(": ");
345 w.write(utf8_message);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800346 return;
347 }
348 break;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700349 }
Michael Winterberg2a05a872016-03-02 17:35:34 -0800350 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
351 break; // Can't get error message, report error code instead.
Victor Zverovichc0954452018-01-06 09:09:50 -0800352 buf.resize(buf.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700353 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700354 } FMT_CATCH(...) {}
Victor Zverovichc0954452018-01-06 09:09:50 -0800355 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700356}
vitaut24c309f2015-06-12 07:15:57 -0700357
358#endif // FMT_USE_WINDOWS_H
359
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700360FMT_FUNC void format_system_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800361 buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
vitaut24c309f2015-06-12 07:15:57 -0700362 FMT_TRY {
Victor Zverovich36634142017-12-26 09:00:22 -0800363 memory_buffer buf;
364 buf.resize(internal::INLINE_BUFFER_SIZE);
vitaut24c309f2015-06-12 07:15:57 -0700365 for (;;) {
Victor Zverovich36634142017-12-26 09:00:22 -0800366 char *system_message = &buf[0];
367 int result = safe_strerror(error_code, system_message, buf.size());
vitaut24c309f2015-06-12 07:15:57 -0700368 if (result == 0) {
Victor Zverovich36634142017-12-26 09:00:22 -0800369 basic_writer<buffer> w(out);
Victor Zverovichfefaf072017-02-14 16:29:47 -0500370 w.write(message);
371 w.write(": ");
372 w.write(system_message);
vitaut24c309f2015-06-12 07:15:57 -0700373 return;
374 }
375 if (result != ERANGE)
376 break; // Can't get error message, report error code instead.
Victor Zverovich36634142017-12-26 09:00:22 -0800377 buf.resize(buf.size() * 2);
vitaut24c309f2015-06-12 07:15:57 -0700378 }
379 } FMT_CATCH(...) {}
vitaut66069712015-11-18 08:42:09 -0800380 fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
vitaut24c309f2015-06-12 07:15:57 -0700381}
Victor Zverovich53b4c312014-04-30 15:00:41 -0700382
jamboree7487bde2015-06-10 09:32:59 +0800383template <typename Char>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800384void basic_fixed_buffer<Char>::grow(std::size_t) {
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800385 FMT_THROW(std::runtime_error("buffer overflow"));
386}
387
Abdó Roig-Marangesaf0f21d2017-12-09 16:50:53 +0100388FMT_FUNC void internal::error_handler::on_error(const char *message) {
Victor Zverovich94edb1a2017-12-06 07:42:42 -0800389 FMT_THROW(format_error(message));
390}
391
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700392FMT_FUNC void report_system_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800393 int error_code, fmt::string_view message) FMT_NOEXCEPT {
vitaute5d59982015-11-20 07:56:16 -0800394 // 'fmt::' is for bcc32.
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700395 report_error(format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700396}
397
vitaut24c309f2015-06-12 07:15:57 -0700398#if FMT_USE_WINDOWS_H
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700399FMT_FUNC void report_windows_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800400 int error_code, fmt::string_view message) FMT_NOEXCEPT {
vitaute5d59982015-11-20 07:56:16 -0800401 // 'fmt::' is for bcc32.
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700402 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700403}
Victor Zverovich400812a2014-04-30 12:38:17 -0700404#endif
Victor Zverovichf7939862014-04-30 10:18:11 -0700405
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800406FMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800407 memory_buffer buffer;
Victor Zverovichfefaf072017-02-14 16:29:47 -0500408 vformat_to(buffer, format_str, args);
409 std::fwrite(buffer.data(), 1, buffer.size(), f);
Victor Zverovichd5b81962014-06-28 21:56:40 -0700410}
411
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800412FMT_FUNC void vprint(string_view format_str, format_args args) {
Victor Zverovich0028ce52016-08-26 17:23:13 -0700413 vprint(stdout, format_str, args);
Victor Zverovich163178e2014-09-25 07:08:25 -0700414}
415
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800416FMT_FUNC void vprint_colored(Color c, string_view format, format_args args) {
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700417 char escape[] = "\x1b[30m";
Ingo van Lilf4d88842015-11-02 19:14:47 +0100418 escape[3] = static_cast<char>('0' + c);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700419 std::fputs(escape, stdout);
Victor Zverovich0028ce52016-08-26 17:23:13 -0700420 vprint(format, args);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700421 std::fputs(RESET_COLOR, stdout);
422}
423
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800424FMT_FUNC locale locale_provider::locale() { return fmt::locale(); }
425
Victor Zverovichc09c42f2015-03-01 09:43:33 -0800426#ifndef FMT_HEADER_ONLY
427
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800428template struct internal::basic_data<void>;
vitaut804a74c2015-05-14 12:58:42 -0700429
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700430// Explicit instantiations for char.
431
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800432template char internal::thousands_sep(locale_provider *lp);
Victor Zverovich7f351de2017-12-03 09:18:06 -0800433
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800434template void basic_fixed_buffer<char>::grow(std::size_t);
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800435
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800436template void internal::arg_map<context>::init(const format_args &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700437
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800438template int internal::char_traits<char>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700439 char *buffer, std::size_t size, const char *format,
440 unsigned width, int precision, double value);
441
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800442template int internal::char_traits<char>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700443 char *buffer, std::size_t size, const char *format,
444 unsigned width, int precision, long double value);
445
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700446// Explicit instantiations for wchar_t.
447
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800448template wchar_t internal::thousands_sep(locale_provider *lp);
Victor Zverovich7f351de2017-12-03 09:18:06 -0800449
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800450template void basic_fixed_buffer<wchar_t>::grow(std::size_t);
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800451
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800452template void internal::arg_map<wcontext>::init(const wformat_args &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700453
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800454template int internal::char_traits<wchar_t>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700455 wchar_t *buffer, std::size_t size, const wchar_t *format,
456 unsigned width, int precision, double value);
457
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800458template int internal::char_traits<wchar_t>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700459 wchar_t *buffer, std::size_t size, const wchar_t *format,
460 unsigned width, int precision, long double value);
461
Victor Zverovichc09c42f2015-03-01 09:43:33 -0800462#endif // FMT_HEADER_ONLY
463
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700464} // namespace fmt
465
Ingo van Lilb4b13ee2015-11-02 12:34:46 +0100466#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +0000467# pragma warning(pop)
468#endif