blob: e759084b4fcaa0e38804bc9edaa12379d77f3af7 [file] [log] [blame]
Victor Zverovichb076df42012-12-07 08:31:09 -08001/*
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07002 Formatting library for C++
Victor Zverovichfaccb4c2012-12-12 07:44:41 -08003
Victor Zverovich408c84c2016-05-04 06:27:03 -07004 Copyright (c) 2012 - 2016, Victor Zverovich
Victor Zverovichfaccb4c2012-12-12 07:44:41 -08005 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 1. Redistributions of source code must retain the above copyright notice, this
11 list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Victor Zverovichb076df42012-12-07 08:31:09 -080026 */
27
Victor Zveroviche160c2b2016-05-22 16:07:50 -070028#include "fmt/format.h"
Victor Zverovichfbfedcf2013-01-14 15:16:20 -080029
Victor Zverovich859a4972014-04-30 06:55:21 -070030#include <string.h>
31
Victor Zverovich72f896d2012-12-12 09:17:28 -080032#include <cctype>
Victor Zverovich5d15bdd2014-07-01 16:23:50 -070033#include <cerrno>
Victor Zverovichf28645f2014-04-24 12:37:06 -070034#include <climits>
Victor Zverovich9ff3b972013-09-07 10:15:08 -070035#include <cmath>
Victor Zverovicha684d0c2013-12-27 08:00:10 -080036#include <cstdarg>
vitaut7dcf0512015-11-13 06:52:13 -080037#include <cstddef> // for std::ptrdiff_t
Victor Zverovich9ff3b972013-09-07 10:15:08 -070038
vitaut24c309f2015-06-12 07:15:57 -070039#if defined(_WIN32) && defined(__MINGW32__)
40# include <cstring>
41#endif
42
43#if FMT_USE_WINDOWS_H
vitaut67ce3942015-04-30 07:48:36 -070044# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
45# include <windows.h>
46# else
47# define NOMINMAX
48# include <windows.h>
49# undef NOMINMAX
50# endif
Ryuuke5a9dc8f2015-02-08 16:08:29 +000051#endif
52
Victor Zverovich8b76e972014-10-06 08:30:55 -070053#if FMT_EXCEPTIONS
54# define FMT_TRY try
55# define FMT_CATCH(x) catch (x)
56#else
57# define FMT_TRY if (true)
58# define FMT_CATCH(x) if (false)
59#endif
60
Victor Zverovich07f8ffc2017-08-21 06:50:57 -070061// Disable the warning about declaration shadowing because it affects too
62// many valid cases.
63#pragma GCC diagnostic ignored "-Wshadow"
64
Ingo van Lilb4b13ee2015-11-02 12:34:46 +010065#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +000066# pragma warning(push)
Victor Zverovich8b76e972014-10-06 08:30:55 -070067# pragma warning(disable: 4127) // conditional expression is constant
Daniel.Perrybd0067e2014-11-25 18:01:09 -050068# pragma warning(disable: 4702) // unreachable code
vitautdf47d812015-03-16 18:53:14 -070069// Disable deprecation warning for strerror. The latter is not called but
70// MSVC fails to detect it.
71# pragma warning(disable: 4996)
jdale88a9862fd2014-03-11 18:56:24 +000072#endif
73
vitaut341b98c2015-03-14 13:39:33 -070074// Dummy implementations of strerror_r and strerror_s called if corresponding
75// system functions are not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -080076static inline fmt::internal::null<> strerror_r(int, char *, ...) {
77 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070078}
Victor Zverovichc333dca2017-02-19 08:41:38 -080079static inline fmt::internal::null<> strerror_s(char *, std::size_t, ...) {
80 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070081}
82
vitaut8725d072015-06-12 07:56:58 -070083namespace fmt {
Victor Zverovichb26e76e2016-06-14 08:11:33 -070084
Victor Zverovich9bb213e2016-08-25 08:38:07 -070085FMT_FUNC format_error::~format_error() throw() {}
Victor Zverovichc333dca2017-02-19 08:41:38 -080086FMT_FUNC system_error::~system_error() throw() {}
Victor Zverovichb26e76e2016-06-14 08:11:33 -070087
Victor Zverovich9ff3b972013-09-07 10:15:08 -070088namespace {
89
90#ifndef _MSC_VER
Victor Zverovichb9a568b2014-09-19 07:51:42 -070091# define FMT_SNPRINTF snprintf
Victor Zverovicha684d0c2013-12-27 08:00:10 -080092#else // _MSC_VER
Victor Zverovich406c6122014-08-19 08:47:38 -070093inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -080094 va_list args;
95 va_start(args, format);
96 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
97 va_end(args);
98 return result;
99}
Victor Zverovichb9a568b2014-09-19 07:51:42 -0700100# define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700101#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -0800102
cstamford55836ca2015-03-10 07:04:31 +0000103#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
104# define FMT_SWPRINTF snwprintf
105#else
106# define FMT_SWPRINTF swprintf
107#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
108
Victor Zverovich7004d1e2015-02-08 19:54:39 -0800109const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700110
Victor Zverovich50e71672017-02-18 06:52:52 -0800111typedef void (*FormatFunc)(buffer &, int, string_view);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700112
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700113// Portable thread-safe version of strerror.
114// Sets buffer to point to a string describing the error code.
115// This can be either a pointer to a string stored in buffer,
116// or a pointer to some static immutable string.
117// Returns one of the following values:
118// 0 - success
119// ERANGE - buffer is not large enough to store the error message
120// other - failure
121// Buffer should be at least of size 1.
122int safe_strerror(
Carter Lie2583ab2015-02-14 09:58:29 +0800123 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
vitaut8ab665a2015-06-22 08:17:23 -0700124 FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
vitaut341b98c2015-03-14 13:39:33 -0700125
vitaut341b98c2015-03-14 13:39:33 -0700126 class StrError {
127 private:
128 int error_code_;
129 char *&buffer_;
130 std::size_t buffer_size_;
131
vitautda052ae2015-03-21 07:53:39 -0700132 // A noop assignment operator to avoid bogus warnings.
133 void operator=(const StrError &) {}
134
vitaut341b98c2015-03-14 13:39:33 -0700135 // Handle the result of XSI-compliant version of strerror_r.
136 int handle(int result) {
vitaute1776ac2015-03-14 14:05:02 -0700137 // glibc versions before 2.13 return result in errno.
138 return result == -1 ? errno : result;
vitaut341b98c2015-03-14 13:39:33 -0700139 }
140
141 // Handle the result of GNU-specific version of strerror_r.
142 int handle(char *message) {
143 // If the buffer is full then the message is probably truncated.
144 if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
145 return ERANGE;
146 buffer_ = message;
147 return 0;
148 }
149
150 // Handle the case when strerror_r is not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800151 int handle(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700152 return fallback(strerror_s(buffer_, buffer_size_, error_code_));
153 }
154
155 // Fallback to strerror_s when strerror_r is not available.
156 int fallback(int result) {
157 // If the buffer is full then the message is probably truncated.
158 return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
159 ERANGE : result;
160 }
161
162 // Fallback to strerror if strerror_r and strerror_s are not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800163 int fallback(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700164 errno = 0;
165 buffer_ = strerror(error_code_);
166 return errno;
167 }
168
169 public:
Radu Popescu0affb232015-08-04 12:52:44 +0200170 StrError(int err_code, char *&buf, std::size_t buf_size)
171 : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
vitaut341b98c2015-03-14 13:39:33 -0700172
vitaut63f6c102015-06-14 09:36:23 -0700173 int run() {
174 strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r.
175 return handle(strerror_r(error_code_, buffer_, buffer_size_));
176 }
vitaut341b98c2015-03-14 13:39:33 -0700177 };
178 return StrError(error_code, buffer, buffer_size).run();
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700179}
180
Victor Zverovichfefaf072017-02-14 16:29:47 -0500181void format_error_code(buffer &out, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800182 string_view message) FMT_NOEXCEPT {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700183 // Report error code making sure that the output fits into
184 // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
185 // bad_alloc.
Victor Zverovichf423e462017-03-11 07:43:26 -0800186 out.resize(0);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700187 static const char SEP[] = ": ";
vitaut1addec92015-03-21 20:16:36 -0700188 static const char ERROR_STR[] = "error ";
vitaut1addec92015-03-21 20:16:36 -0700189 // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
190 std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800191 typedef internal::int_traits<int>::main_type main_type;
192 main_type abs_value = static_cast<main_type>(error_code);
vitaut9d577ca2016-03-02 07:01:21 -0800193 if (internal::is_negative(error_code)) {
194 abs_value = 0 - abs_value;
195 ++error_code_size;
196 }
vitautbfdca8b2016-04-20 09:11:33 -0700197 error_code_size += internal::count_digits(abs_value);
Victor Zverovichfefaf072017-02-14 16:29:47 -0500198 basic_writer<char> w(out);
Victor Zverovichec15ef72017-01-22 07:40:21 -0800199 if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) {
Victor Zverovichfefaf072017-02-14 16:29:47 -0500200 w.write(message);
201 w.write(SEP);
Victor Zverovichec15ef72017-01-22 07:40:21 -0800202 }
Victor Zverovichfefaf072017-02-14 16:29:47 -0500203 w.write(ERROR_STR);
204 w.write(error_code);
vitautbfdca8b2016-04-20 09:11:33 -0700205 assert(out.size() <= internal::INLINE_BUFFER_SIZE);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700206}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700207
vitautbfdca8b2016-04-20 09:11:33 -0700208void report_error(FormatFunc func, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800209 string_view message) FMT_NOEXCEPT {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800210 memory_buffer full_message;
Victor Zverovich88e0db82014-09-05 08:04:26 -0700211 func(full_message, error_code, message);
212 // Use Writer::data instead of Writer::c_str to avoid potential memory
213 // allocation.
214 std::fwrite(full_message.data(), full_message.size(), 1, stderr);
215 std::fputc('\n', stderr);
Victor Zverovichb605b392013-09-09 22:21:40 -0700216}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700217} // namespace
vitaut270069b2015-06-16 07:36:32 -0700218
Victor Zverovichc333dca2017-02-19 08:41:38 -0800219FMT_FUNC void system_error::init(
Victor Zverovich2f4f49f2017-07-18 19:40:48 -0700220 int err_code, string_view format_str, args args) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800221 error_code_ = err_code;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800222 memory_buffer buffer;
223 format_system_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700224 std::runtime_error &base = *this;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800225 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700226}
227
Victor Zverovichb605b392013-09-09 22:21:40 -0700228template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800229int internal::char_traits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700230 char *buffer, std::size_t size, const char *format,
231 unsigned width, int precision, T value) {
232 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700233 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700234 FMT_SNPRINTF(buffer, size, format, value) :
235 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700236 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700237 return precision < 0 ?
238 FMT_SNPRINTF(buffer, size, format, width, value) :
239 FMT_SNPRINTF(buffer, size, format, width, precision, value);
240}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700241
Victor Zverovichb605b392013-09-09 22:21:40 -0700242template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800243int internal::char_traits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700244 wchar_t *buffer, std::size_t size, const wchar_t *format,
245 unsigned width, int precision, T value) {
246 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700247 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000248 FMT_SWPRINTF(buffer, size, format, value) :
249 FMT_SWPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700250 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700251 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000252 FMT_SWPRINTF(buffer, size, format, width, value) :
253 FMT_SWPRINTF(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700254}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800255
Victor Zverovich311251e2014-11-29 06:58:00 -0800256template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800257const char internal::basic_data<T>::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800258 "0001020304050607080910111213141516171819"
259 "2021222324252627282930313233343536373839"
260 "4041424344454647484950515253545556575859"
261 "6061626364656667686970717273747576777879"
262 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800263
Victor Zverovichf1d85162014-02-19 13:02:22 -0800264#define FMT_POWERS_OF_10(factor) \
265 factor * 10, \
266 factor * 100, \
267 factor * 1000, \
268 factor * 10000, \
269 factor * 100000, \
270 factor * 1000000, \
271 factor * 10000000, \
272 factor * 100000000, \
273 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800274
Victor Zverovich311251e2014-11-29 06:58:00 -0800275template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800276const uint32_t internal::basic_data<T>::POWERS_OF_10_32[] = {
Victor Zverovich311251e2014-11-29 06:58:00 -0800277 0, FMT_POWERS_OF_10(1)
278};
279
280template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800281const uint64_t internal::basic_data<T>::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800282 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800283 FMT_POWERS_OF_10(1),
Victor Zverovich016aceb2017-08-26 09:09:43 -0700284 FMT_POWERS_OF_10(1000000000ull),
285 10000000000000000000ull
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800286};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800287
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700288FMT_FUNC void internal::report_unknown_type(char code, const char *type) {
Carter Li2d4631a2015-03-14 14:54:37 +0800289 (void)type;
Victor Zverovich877abaf2013-01-08 09:56:05 -0800290 if (std::isprint(static_cast<unsigned char>(code))) {
Victor Zverovich9bb213e2016-08-25 08:38:07 -0700291 FMT_THROW(format_error(
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700292 format("unknown format code '{}' for {}", code, type)));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800293 }
Victor Zverovich9bb213e2016-08-25 08:38:07 -0700294 FMT_THROW(format_error(
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700295 format("unknown format code '\\x{:02x}' for {}",
Victor Zverovich8b76e972014-10-06 08:30:55 -0700296 static_cast<unsigned>(code), type)));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800297}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700298
vitaut24c309f2015-06-12 07:15:57 -0700299#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700300
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800301FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
Victor Zverovichdff21372014-12-16 07:01:01 -0800302 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
vitautc3ba6152015-08-07 07:34:58 -0700303 if (s.size() > INT_MAX)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800304 FMT_THROW(windows_error(ERROR_INVALID_PARAMETER, ERROR_MSG));
vitautc3ba6152015-08-07 07:34:58 -0700305 int s_size = static_cast<int>(s.size());
306 int length = MultiByteToWideChar(
307 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700308 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800309 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700310 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700311 length = MultiByteToWideChar(
vitautc3ba6152015-08-07 07:34:58 -0700312 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700313 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800314 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700315 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700316}
317
Victor Zverovichc333dca2017-02-19 08:41:38 -0800318FMT_FUNC internal::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700319 if (int error_code = convert(s)) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800320 FMT_THROW(windows_error(error_code,
Victor Zverovich8b76e972014-10-06 08:30:55 -0700321 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700322 }
323}
324
Victor Zverovichc333dca2017-02-19 08:41:38 -0800325FMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) {
vitautca747812015-08-07 07:08:46 -0700326 if (s.size() > INT_MAX)
327 return ERROR_INVALID_PARAMETER;
328 int s_size = static_cast<int>(s.size());
329 int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700330 if (length == 0)
331 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700332 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700333 length = WideCharToMultiByte(
vitautca747812015-08-07 07:08:46 -0700334 CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700335 if (length == 0)
336 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700337 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700338 return 0;
339}
340
Victor Zverovichc333dca2017-02-19 08:41:38 -0800341FMT_FUNC void windows_error::init(
Victor Zverovich2f4f49f2017-07-18 19:40:48 -0700342 int err_code, string_view format_str, args args) {
Carter Li3f574c12015-02-17 10:11:42 +0800343 error_code_ = err_code;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800344 memory_buffer buffer;
Victor Zveroviche022c212017-02-17 06:38:53 -0800345 internal::format_windows_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700346 std::runtime_error &base = *this;
Victor Zveroviche022c212017-02-17 06:38:53 -0800347 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700348}
349
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700350FMT_FUNC void internal::format_windows_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800351 buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700352 FMT_TRY {
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800353 wmemory_buffer buffer;
Michael Winterberg2a05a872016-03-02 17:35:34 -0800354 buffer.resize(INLINE_BUFFER_SIZE);
355 for (;;) {
356 wchar_t *system_message = &buffer[0];
Victor Zverovichf85d5f42016-10-22 08:04:20 -0700357 int result = FormatMessageW(
358 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
359 0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
360 system_message, static_cast<uint32_t>(buffer.size()), 0);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800361 if (result != 0) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800362 utf16_to_utf8 utf8_message;
Michael Winterberg2a05a872016-03-02 17:35:34 -0800363 if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
Victor Zveroviche022c212017-02-17 06:38:53 -0800364 basic_writer<char> w(out);
365 w.write(message);
366 w.write(": ");
367 w.write(utf8_message);
Michael Winterberg2a05a872016-03-02 17:35:34 -0800368 return;
369 }
370 break;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700371 }
Michael Winterberg2a05a872016-03-02 17:35:34 -0800372 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
373 break; // Can't get error message, report error code instead.
374 buffer.resize(buffer.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700375 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700376 } FMT_CATCH(...) {}
vitaut66069712015-11-18 08:42:09 -0800377 fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
Victor Zverovich53b4c312014-04-30 15:00:41 -0700378}
vitaut24c309f2015-06-12 07:15:57 -0700379
380#endif // FMT_USE_WINDOWS_H
381
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700382FMT_FUNC void format_system_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800383 buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
vitaut24c309f2015-06-12 07:15:57 -0700384 FMT_TRY {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800385 memory_buffer buffer;
Victor Zverovichcc9b0512016-05-11 21:36:22 -0600386 buffer.resize(internal::INLINE_BUFFER_SIZE);
vitaut24c309f2015-06-12 07:15:57 -0700387 for (;;) {
388 char *system_message = &buffer[0];
389 int result = safe_strerror(error_code, system_message, buffer.size());
390 if (result == 0) {
Victor Zverovichfefaf072017-02-14 16:29:47 -0500391 basic_writer<char> w(out);
392 w.write(message);
393 w.write(": ");
394 w.write(system_message);
vitaut24c309f2015-06-12 07:15:57 -0700395 return;
396 }
397 if (result != ERANGE)
398 break; // Can't get error message, report error code instead.
399 buffer.resize(buffer.size() * 2);
400 }
401 } FMT_CATCH(...) {}
vitaut66069712015-11-18 08:42:09 -0800402 fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
vitaut24c309f2015-06-12 07:15:57 -0700403}
Victor Zverovich53b4c312014-04-30 15:00:41 -0700404
jamboree7487bde2015-06-10 09:32:59 +0800405template <typename Char>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800406void basic_fixed_buffer<Char>::grow(std::size_t) {
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800407 FMT_THROW(std::runtime_error("buffer overflow"));
408}
409
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700410FMT_FUNC void report_system_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800411 int error_code, fmt::string_view message) FMT_NOEXCEPT {
vitaute5d59982015-11-20 07:56:16 -0800412 // 'fmt::' is for bcc32.
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700413 report_error(format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700414}
415
vitaut24c309f2015-06-12 07:15:57 -0700416#if FMT_USE_WINDOWS_H
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700417FMT_FUNC void report_windows_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800418 int error_code, fmt::string_view message) FMT_NOEXCEPT {
vitaute5d59982015-11-20 07:56:16 -0800419 // 'fmt::' is for bcc32.
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 Zverovich2f4f49f2017-07-18 19:40:48 -0700424FMT_FUNC void vprint(std::FILE *f, string_view format_str, 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 Zverovich2f4f49f2017-07-18 19:40:48 -0700430FMT_FUNC void vprint(string_view format_str, 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 Zverovich2f4f49f2017-07-18 19:40:48 -0700434FMT_FUNC void vprint_colored(Color c, string_view 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 Zverovichc09c42f2015-03-01 09:43:33 -0800442#ifndef FMT_HEADER_ONLY
443
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800444template struct internal::basic_data<void>;
vitaut804a74c2015-05-14 12:58:42 -0700445
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700446// Explicit instantiations for char.
447
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800448template void basic_fixed_buffer<char>::grow(std::size_t);
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800449
Victor Zverovichc333dca2017-02-19 08:41:38 -0800450template void internal::arg_map<context>::init(const args &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700451
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800452template int internal::char_traits<char>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700453 char *buffer, std::size_t size, const char *format,
454 unsigned width, int precision, double value);
455
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800456template int internal::char_traits<char>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700457 char *buffer, std::size_t size, const char *format,
458 unsigned width, int precision, long double value);
459
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700460// Explicit instantiations for wchar_t.
461
Victor Zverovich624c5862017-02-05 06:41:39 -0800462template class basic_context<wchar_t>;
Victor Zverovichd705d512016-12-29 09:07:39 -0800463
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800464template void basic_fixed_buffer<wchar_t>::grow(std::size_t);
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800465
Victor Zverovichc333dca2017-02-19 08:41:38 -0800466template void internal::arg_map<wcontext>::init(const wargs &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700467
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800468template int internal::char_traits<wchar_t>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700469 wchar_t *buffer, std::size_t size, const wchar_t *format,
470 unsigned width, int precision, double value);
471
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800472template int internal::char_traits<wchar_t>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700473 wchar_t *buffer, std::size_t size, const wchar_t *format,
474 unsigned width, int precision, long double value);
475
Victor Zverovichc09c42f2015-03-01 09:43:33 -0800476#endif // FMT_HEADER_ONLY
477
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700478} // namespace fmt
479
Ingo van Lilb4b13ee2015-11-02 12:34:46 +0100480#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +0000481# pragma warning(pop)
482#endif