blob: f59587327e3768944b2c4e8f8472d7b333cee1ad [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"
12#include "locale.h"
Victor Zverovichfbfedcf2013-01-14 15:16:20 -080013
Victor Zverovich859a4972014-04-30 06:55:21 -070014#include <string.h>
15
Victor Zverovich72f896d2012-12-12 09:17:28 -080016#include <cctype>
Victor Zverovich5d15bdd2014-07-01 16:23:50 -070017#include <cerrno>
Victor Zverovichf28645f2014-04-24 12:37:06 -070018#include <climits>
Victor Zverovich9ff3b972013-09-07 10:15:08 -070019#include <cmath>
Victor Zverovicha684d0c2013-12-27 08:00:10 -080020#include <cstdarg>
vitaut7dcf0512015-11-13 06:52:13 -080021#include <cstddef> // for std::ptrdiff_t
Victor Zverovich9ff3b972013-09-07 10:15:08 -070022
vitaut24c309f2015-06-12 07:15:57 -070023#if defined(_WIN32) && defined(__MINGW32__)
24# include <cstring>
25#endif
26
27#if FMT_USE_WINDOWS_H
Victor Zverovichc753a2a2018-01-28 20:26:25 -080028# if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)
29# define WIN32_LEAN_AND_MEAN
30# endif
vitaut67ce3942015-04-30 07:48:36 -070031# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
32# include <windows.h>
33# else
34# define NOMINMAX
35# include <windows.h>
36# undef NOMINMAX
37# endif
Ryuuke5a9dc8f2015-02-08 16:08:29 +000038#endif
39
Victor Zverovich8b76e972014-10-06 08:30:55 -070040#if FMT_EXCEPTIONS
41# define FMT_TRY try
42# define FMT_CATCH(x) catch (x)
43#else
44# define FMT_TRY if (true)
45# define FMT_CATCH(x) if (false)
46#endif
47
Victor Zverovichb83241f2017-10-19 07:28:17 -070048#ifdef __GNUC__
Victor Zverovich07f8ffc2017-08-21 06:50:57 -070049// Disable the warning about declaration shadowing because it affects too
50// many valid cases.
Victor Zverovichb83241f2017-10-19 07:28:17 -070051# pragma GCC diagnostic ignored "-Wshadow"
52#endif
Victor Zverovich07f8ffc2017-08-21 06:50:57 -070053
Ingo van Lilb4b13ee2015-11-02 12:34:46 +010054#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +000055# pragma warning(push)
Victor Zverovich8b76e972014-10-06 08:30:55 -070056# pragma warning(disable: 4127) // conditional expression is constant
Daniel.Perrybd0067e2014-11-25 18:01:09 -050057# pragma warning(disable: 4702) // unreachable code
vitautdf47d812015-03-16 18:53:14 -070058// Disable deprecation warning for strerror. The latter is not called but
59// MSVC fails to detect it.
60# pragma warning(disable: 4996)
jdale88a9862fd2014-03-11 18:56:24 +000061#endif
62
vitaut341b98c2015-03-14 13:39:33 -070063// Dummy implementations of strerror_r and strerror_s called if corresponding
64// system functions are not available.
Victor Zverovich6cb68f92018-02-10 06:28:33 -080065inline fmt::internal::null<> strerror_r(int, char *, ...) {
Victor Zverovichc333dca2017-02-19 08:41:38 -080066 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070067}
Victor Zverovich6cb68f92018-02-10 06:28:33 -080068inline fmt::internal::null<> strerror_s(char *, std::size_t, ...) {
Victor Zverovichc333dca2017-02-19 08:41:38 -080069 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070070}
71
vitaut8725d072015-06-12 07:56:58 -070072namespace fmt {
Victor Zverovichb26e76e2016-06-14 08:11:33 -070073
Victor Zverovich9bb213e2016-08-25 08:38:07 -070074FMT_FUNC format_error::~format_error() throw() {}
Victor Zverovich3da71d52018-03-21 07:50:59 -070075FMT_FUNC system_error::~system_error() FMT_DTOR_NOEXCEPT {}
Victor Zverovichb26e76e2016-06-14 08:11:33 -070076
Victor Zverovich9ff3b972013-09-07 10:15:08 -070077namespace {
78
79#ifndef _MSC_VER
Victor Zverovichb9a568b2014-09-19 07:51:42 -070080# define FMT_SNPRINTF snprintf
Victor Zverovicha684d0c2013-12-27 08:00:10 -080081#else // _MSC_VER
Victor Zverovich406c6122014-08-19 08:47:38 -070082inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -080083 va_list args;
84 va_start(args, format);
85 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
86 va_end(args);
87 return result;
88}
Victor Zverovichb9a568b2014-09-19 07:51:42 -070089# define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -070090#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -080091
cstamford55836ca2015-03-10 07:04:31 +000092#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
93# define FMT_SWPRINTF snwprintf
94#else
95# define FMT_SWPRINTF swprintf
96#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
97
Victor Zverovich7004d1e2015-02-08 19:54:39 -080098const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -070099
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800100typedef void (*FormatFunc)(internal::buffer &, int, string_view);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700101
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700102// Portable thread-safe version of strerror.
103// Sets buffer to point to a string describing the error code.
104// This can be either a pointer to a string stored in buffer,
105// or a pointer to some static immutable string.
106// Returns one of the following values:
107// 0 - success
108// ERANGE - buffer is not large enough to store the error message
109// other - failure
110// Buffer should be at least of size 1.
111int safe_strerror(
Carter Lie2583ab2015-02-14 09:58:29 +0800112 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
Victor Zverovich92a250f2018-02-07 07:16:00 -0800113 FMT_ASSERT(buffer != FMT_NULL && buffer_size != 0, "invalid buffer");
vitaut341b98c2015-03-14 13:39:33 -0700114
vitaut341b98c2015-03-14 13:39:33 -0700115 class StrError {
116 private:
117 int error_code_;
118 char *&buffer_;
119 std::size_t buffer_size_;
120
vitautda052ae2015-03-21 07:53:39 -0700121 // A noop assignment operator to avoid bogus warnings.
122 void operator=(const StrError &) {}
123
vitaut341b98c2015-03-14 13:39:33 -0700124 // Handle the result of XSI-compliant version of strerror_r.
125 int handle(int result) {
vitaute1776ac2015-03-14 14:05:02 -0700126 // glibc versions before 2.13 return result in errno.
127 return result == -1 ? errno : result;
vitaut341b98c2015-03-14 13:39:33 -0700128 }
129
130 // Handle the result of GNU-specific version of strerror_r.
131 int handle(char *message) {
132 // If the buffer is full then the message is probably truncated.
133 if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
134 return ERANGE;
135 buffer_ = message;
136 return 0;
137 }
138
139 // Handle the case when strerror_r is not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800140 int handle(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700141 return fallback(strerror_s(buffer_, buffer_size_, error_code_));
142 }
143
144 // Fallback to strerror_s when strerror_r is not available.
145 int fallback(int result) {
146 // If the buffer is full then the message is probably truncated.
147 return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
148 ERANGE : result;
149 }
150
151 // Fallback to strerror if strerror_r and strerror_s are not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800152 int fallback(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700153 errno = 0;
154 buffer_ = strerror(error_code_);
155 return errno;
156 }
157
158 public:
Radu Popescu0affb232015-08-04 12:52:44 +0200159 StrError(int err_code, char *&buf, std::size_t buf_size)
160 : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
vitaut341b98c2015-03-14 13:39:33 -0700161
vitaut63f6c102015-06-14 09:36:23 -0700162 int run() {
vitaut63f6c102015-06-14 09:36:23 -0700163 return handle(strerror_r(error_code_, buffer_, buffer_size_));
164 }
vitaut341b98c2015-03-14 13:39:33 -0700165 };
166 return StrError(error_code, buffer, buffer_size).run();
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700167}
168
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800169void format_error_code(internal::buffer &out, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800170 string_view message) FMT_NOEXCEPT {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700171 // Report error code making sure that the output fits into
Victor Zverovichf1ede632018-03-04 10:33:42 -0800172 // inline_buffer_size to avoid dynamic memory allocation and potential
Victor Zverovich22f75d82014-09-03 08:03:05 -0700173 // bad_alloc.
Victor Zverovichf423e462017-03-11 07:43:26 -0800174 out.resize(0);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700175 static const char SEP[] = ": ";
vitaut1addec92015-03-21 20:16:36 -0700176 static const char ERROR_STR[] = "error ";
vitaut1addec92015-03-21 20:16:36 -0700177 // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
178 std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800179 typedef internal::int_traits<int>::main_type main_type;
180 main_type abs_value = static_cast<main_type>(error_code);
vitaut9d577ca2016-03-02 07:01:21 -0800181 if (internal::is_negative(error_code)) {
182 abs_value = 0 - abs_value;
183 ++error_code_size;
184 }
vitautbfdca8b2016-04-20 09:11:33 -0700185 error_code_size += internal::count_digits(abs_value);
Victor Zverovich217e7c72018-01-14 07:19:23 -0800186 writer w(out);
Victor Zverovichf1ede632018-03-04 10:33:42 -0800187 if (message.size() <= inline_buffer_size - error_code_size) {
Victor Zverovichfefaf072017-02-14 16:29:47 -0500188 w.write(message);
189 w.write(SEP);
Victor Zverovichec15ef72017-01-22 07:40:21 -0800190 }
Victor Zverovichfefaf072017-02-14 16:29:47 -0500191 w.write(ERROR_STR);
192 w.write(error_code);
Victor Zverovichf1ede632018-03-04 10:33:42 -0800193 assert(out.size() <= inline_buffer_size);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700194}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700195
vitautbfdca8b2016-04-20 09:11:33 -0700196void report_error(FormatFunc func, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800197 string_view message) FMT_NOEXCEPT {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800198 memory_buffer full_message;
Victor Zverovich88e0db82014-09-05 08:04:26 -0700199 func(full_message, error_code, message);
200 // Use Writer::data instead of Writer::c_str to avoid potential memory
201 // allocation.
202 std::fwrite(full_message.data(), full_message.size(), 1, stderr);
203 std::fputc('\n', stderr);
Victor Zverovichb605b392013-09-09 22:21:40 -0700204}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700205} // namespace
vitaut270069b2015-06-16 07:36:32 -0700206
Victor Zverovich7f351de2017-12-03 09:18:06 -0800207template <typename Char>
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800208FMT_FUNC Char internal::thousands_sep(locale_provider *lp) {
209 std::locale loc = lp ? lp->locale().get() : std::locale();
210 return std::use_facet<std::numpunct<Char>>(loc).thousands_sep();
Victor Zverovich7f351de2017-12-03 09:18:06 -0800211}
212
Victor Zverovichc333dca2017-02-19 08:41:38 -0800213FMT_FUNC void system_error::init(
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800214 int err_code, string_view format_str, format_args args) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800215 error_code_ = err_code;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800216 memory_buffer buffer;
217 format_system_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700218 std::runtime_error &base = *this;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800219 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700220}
221
Victor Zverovichb605b392013-09-09 22:21:40 -0700222template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800223int internal::char_traits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700224 char *buffer, std::size_t size, const char *format,
225 unsigned width, int precision, T value) {
226 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700227 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700228 FMT_SNPRINTF(buffer, size, format, value) :
229 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700230 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700231 return precision < 0 ?
232 FMT_SNPRINTF(buffer, size, format, width, value) :
233 FMT_SNPRINTF(buffer, size, format, width, precision, value);
234}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700235
Victor Zverovichb605b392013-09-09 22:21:40 -0700236template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800237int internal::char_traits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700238 wchar_t *buffer, std::size_t size, const wchar_t *format,
239 unsigned width, int precision, T value) {
240 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700241 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000242 FMT_SWPRINTF(buffer, size, format, value) :
243 FMT_SWPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700244 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700245 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000246 FMT_SWPRINTF(buffer, size, format, width, value) :
247 FMT_SWPRINTF(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700248}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800249
Victor Zverovich311251e2014-11-29 06:58:00 -0800250template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800251const char internal::basic_data<T>::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800252 "0001020304050607080910111213141516171819"
253 "2021222324252627282930313233343536373839"
254 "4041424344454647484950515253545556575859"
255 "6061626364656667686970717273747576777879"
256 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800257
Victor Zverovichf1d85162014-02-19 13:02:22 -0800258#define FMT_POWERS_OF_10(factor) \
259 factor * 10, \
260 factor * 100, \
261 factor * 1000, \
262 factor * 10000, \
263 factor * 100000, \
264 factor * 1000000, \
265 factor * 10000000, \
266 factor * 100000000, \
267 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800268
Victor Zverovich311251e2014-11-29 06:58:00 -0800269template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800270const uint32_t internal::basic_data<T>::POWERS_OF_10_32[] = {
Victor Zverovich311251e2014-11-29 06:58:00 -0800271 0, FMT_POWERS_OF_10(1)
272};
273
274template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800275const uint64_t internal::basic_data<T>::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800276 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800277 FMT_POWERS_OF_10(1),
Victor Zverovich016aceb2017-08-26 09:09:43 -0700278 FMT_POWERS_OF_10(1000000000ull),
279 10000000000000000000ull
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800280};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800281
vitaut24c309f2015-06-12 07:15:57 -0700282#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700283
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800284FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
Victor Zverovichdff21372014-12-16 07:01:01 -0800285 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
vitautc3ba6152015-08-07 07:34:58 -0700286 if (s.size() > INT_MAX)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800287 FMT_THROW(windows_error(ERROR_INVALID_PARAMETER, ERROR_MSG));
vitautc3ba6152015-08-07 07:34:58 -0700288 int s_size = static_cast<int>(s.size());
Vasili Galkaacb469a2018-03-12 14:43:29 +0200289 if (s_size == 0) {
290 // MultiByteToWideChar does not support zero length, handle separately.
291 buffer_.resize(1);
292 buffer_[0] = 0;
293 return;
294 }
295
vitautc3ba6152015-08-07 07:34:58 -0700296 int length = MultiByteToWideChar(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800297 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700298 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800299 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700300 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700301 length = MultiByteToWideChar(
vitautc3ba6152015-08-07 07:34:58 -0700302 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700303 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800304 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700305 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700306}
307
Victor Zverovichc333dca2017-02-19 08:41:38 -0800308FMT_FUNC internal::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700309 if (int error_code = convert(s)) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800310 FMT_THROW(windows_error(error_code,
Victor Zverovich8b76e972014-10-06 08:30:55 -0700311 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700312 }
313}
314
Victor Zverovichc333dca2017-02-19 08:41:38 -0800315FMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) {
vitautca747812015-08-07 07:08:46 -0700316 if (s.size() > INT_MAX)
317 return ERROR_INVALID_PARAMETER;
318 int s_size = static_cast<int>(s.size());
Vasili Galkaacb469a2018-03-12 14:43:29 +0200319 if (s_size == 0) {
320 // WideCharToMultiByte does not support zero length, handle separately.
321 buffer_.resize(1);
322 buffer_[0] = 0;
323 return 0;
324 }
325
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800326 int length = WideCharToMultiByte(
327 CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700328 if (length == 0)
329 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700330 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700331 length = WideCharToMultiByte(
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800332 CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700333 if (length == 0)
334 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700335 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700336 return 0;
337}
338
Victor Zverovichc333dca2017-02-19 08:41:38 -0800339FMT_FUNC void windows_error::init(
Victor Zverovich7f351de2017-12-03 09:18:06 -0800340 int err_code, string_view format_str, format_args args) {
Carter Li3f574c12015-02-17 10:11:42 +0800341 error_code_ = err_code;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800342 memory_buffer buffer;
Victor Zveroviche022c212017-02-17 06:38:53 -0800343 internal::format_windows_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700344 std::runtime_error &base = *this;
Victor Zveroviche022c212017-02-17 06:38:53 -0800345 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700346}
347
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700348FMT_FUNC void internal::format_windows_error(
Victor Zverovichf6fd38b2018-01-15 08:22:31 -0800349 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700350 FMT_TRY {
Victor Zverovichc0954452018-01-06 09:09:50 -0800351 wmemory_buffer buf;
Victor Zverovichf1ede632018-03-04 10:33:42 -0800352 buf.resize(inline_buffer_size);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800353 for (;;) {
Victor Zverovichc0954452018-01-06 09:09:50 -0800354 wchar_t *system_message = &buf[0];
Victor Zverovichf85d5f42016-10-22 08:04:20 -0700355 int result = FormatMessageW(
356 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
Victor Zverovichd8c25a12018-01-20 18:37:57 -0800357 FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
358 system_message, static_cast<uint32_t>(buf.size()), FMT_NULL);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800359 if (result != 0) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800360 utf16_to_utf8 utf8_message;
Michael Winterberg2a05a872016-03-02 17:35:34 -0800361 if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800362 writer w(out);
Victor Zveroviche022c212017-02-17 06:38:53 -0800363 w.write(message);
364 w.write(": ");
365 w.write(utf8_message);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800366 return;
367 }
368 break;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700369 }
Michael Winterberg2a05a872016-03-02 17:35:34 -0800370 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
371 break; // Can't get error message, report error code instead.
Victor Zverovichc0954452018-01-06 09:09:50 -0800372 buf.resize(buf.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700373 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700374 } FMT_CATCH(...) {}
Victor Zverovichc0954452018-01-06 09:09:50 -0800375 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700376}
vitaut24c309f2015-06-12 07:15:57 -0700377
378#endif // FMT_USE_WINDOWS_H
379
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700380FMT_FUNC void format_system_error(
Victor Zverovichc2fecb92018-01-14 14:15:59 -0800381 internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
vitaut24c309f2015-06-12 07:15:57 -0700382 FMT_TRY {
Victor Zverovich36634142017-12-26 09:00:22 -0800383 memory_buffer buf;
Victor Zverovichf1ede632018-03-04 10:33:42 -0800384 buf.resize(inline_buffer_size);
vitaut24c309f2015-06-12 07:15:57 -0700385 for (;;) {
Victor Zverovich36634142017-12-26 09:00:22 -0800386 char *system_message = &buf[0];
387 int result = safe_strerror(error_code, system_message, buf.size());
vitaut24c309f2015-06-12 07:15:57 -0700388 if (result == 0) {
Victor Zverovich217e7c72018-01-14 07:19:23 -0800389 writer w(out);
Victor Zverovichfefaf072017-02-14 16:29:47 -0500390 w.write(message);
391 w.write(": ");
392 w.write(system_message);
vitaut24c309f2015-06-12 07:15:57 -0700393 return;
394 }
395 if (result != ERANGE)
396 break; // Can't get error message, report error code instead.
Victor Zverovich36634142017-12-26 09:00:22 -0800397 buf.resize(buf.size() * 2);
vitaut24c309f2015-06-12 07:15:57 -0700398 }
399 } FMT_CATCH(...) {}
Victor Zverovichf164e4c2018-02-01 16:49:47 -0800400 format_error_code(out, error_code, message);
vitaut24c309f2015-06-12 07:15:57 -0700401}
Victor Zverovich53b4c312014-04-30 15:00:41 -0700402
jamboree7487bde2015-06-10 09:32:59 +0800403template <typename Char>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800404void basic_fixed_buffer<Char>::grow(std::size_t) {
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800405 FMT_THROW(std::runtime_error("buffer overflow"));
406}
407
Abdó Roig-Marangesaf0f21d2017-12-09 16:50:53 +0100408FMT_FUNC void internal::error_handler::on_error(const char *message) {
Victor Zverovich94edb1a2017-12-06 07:42:42 -0800409 FMT_THROW(format_error(message));
410}
411
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700412FMT_FUNC void report_system_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800413 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700414 report_error(format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700415}
416
vitaut24c309f2015-06-12 07:15:57 -0700417#if FMT_USE_WINDOWS_H
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700418FMT_FUNC void report_windows_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800419 int error_code, fmt::string_view message) FMT_NOEXCEPT {
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700420 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700421}
Victor Zverovich400812a2014-04-30 12:38:17 -0700422#endif
Victor Zverovichf7939862014-04-30 10:18:11 -0700423
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800424FMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800425 memory_buffer buffer;
Victor Zverovichfefaf072017-02-14 16:29:47 -0500426 vformat_to(buffer, format_str, args);
427 std::fwrite(buffer.data(), 1, buffer.size(), f);
Victor Zverovichd5b81962014-06-28 21:56:40 -0700428}
429
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800430FMT_FUNC void vprint(string_view format_str, format_args args) {
Victor Zverovich0028ce52016-08-26 17:23:13 -0700431 vprint(stdout, format_str, args);
Victor Zverovich163178e2014-09-25 07:08:25 -0700432}
433
Victor Zverovichbb471092018-03-04 11:25:40 -0800434FMT_FUNC void vprint_colored(color c, string_view format, format_args args) {
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700435 char escape[] = "\x1b[30m";
Ingo van Lilf4d88842015-11-02 19:14:47 +0100436 escape[3] = static_cast<char>('0' + c);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700437 std::fputs(escape, stdout);
Victor Zverovich0028ce52016-08-26 17:23:13 -0700438 vprint(format, args);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700439 std::fputs(RESET_COLOR, stdout);
440}
441
Victor Zverovichd165d9c2017-12-26 17:22:07 -0800442FMT_FUNC locale locale_provider::locale() { return fmt::locale(); }
443
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700444} // namespace fmt
445
Ingo van Lilb4b13ee2015-11-02 12:34:46 +0100446#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +0000447# pragma warning(pop)
448#endif
Victor Zverovich3da71d52018-03-21 07:50:59 -0700449
450#endif // FMT_FORMAT_INL_H_