blob: e9b590a5e0254ebed94be17a962d359d08525ba4 [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 Zverovich7f351de2017-12-03 09:18:06 -080029#include "fmt/locale.h"
Victor Zverovichfbfedcf2013-01-14 15:16:20 -080030
Victor Zverovich859a4972014-04-30 06:55:21 -070031#include <string.h>
32
Victor Zverovich72f896d2012-12-12 09:17:28 -080033#include <cctype>
Victor Zverovich5d15bdd2014-07-01 16:23:50 -070034#include <cerrno>
Victor Zverovichf28645f2014-04-24 12:37:06 -070035#include <climits>
Victor Zverovich9ff3b972013-09-07 10:15:08 -070036#include <cmath>
Victor Zverovicha684d0c2013-12-27 08:00:10 -080037#include <cstdarg>
vitaut7dcf0512015-11-13 06:52:13 -080038#include <cstddef> // for std::ptrdiff_t
Victor Zverovich9ff3b972013-09-07 10:15:08 -070039
vitaut24c309f2015-06-12 07:15:57 -070040#if defined(_WIN32) && defined(__MINGW32__)
41# include <cstring>
42#endif
43
44#if FMT_USE_WINDOWS_H
vitaut67ce3942015-04-30 07:48:36 -070045# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
46# include <windows.h>
47# else
48# define NOMINMAX
49# include <windows.h>
50# undef NOMINMAX
51# endif
Ryuuke5a9dc8f2015-02-08 16:08:29 +000052#endif
53
Victor Zverovich8b76e972014-10-06 08:30:55 -070054#if FMT_EXCEPTIONS
55# define FMT_TRY try
56# define FMT_CATCH(x) catch (x)
57#else
58# define FMT_TRY if (true)
59# define FMT_CATCH(x) if (false)
60#endif
61
Victor Zverovichb83241f2017-10-19 07:28:17 -070062#ifdef __GNUC__
Victor Zverovich07f8ffc2017-08-21 06:50:57 -070063// Disable the warning about declaration shadowing because it affects too
64// many valid cases.
Victor Zverovichb83241f2017-10-19 07:28:17 -070065# pragma GCC diagnostic ignored "-Wshadow"
66#endif
Victor Zverovich07f8ffc2017-08-21 06:50:57 -070067
Ingo van Lilb4b13ee2015-11-02 12:34:46 +010068#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +000069# pragma warning(push)
Victor Zverovich8b76e972014-10-06 08:30:55 -070070# pragma warning(disable: 4127) // conditional expression is constant
Daniel.Perrybd0067e2014-11-25 18:01:09 -050071# pragma warning(disable: 4702) // unreachable code
vitautdf47d812015-03-16 18:53:14 -070072// Disable deprecation warning for strerror. The latter is not called but
73// MSVC fails to detect it.
74# pragma warning(disable: 4996)
jdale88a9862fd2014-03-11 18:56:24 +000075#endif
76
vitaut341b98c2015-03-14 13:39:33 -070077// Dummy implementations of strerror_r and strerror_s called if corresponding
78// system functions are not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -080079static inline fmt::internal::null<> strerror_r(int, char *, ...) {
80 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070081}
Victor Zverovichc333dca2017-02-19 08:41:38 -080082static inline fmt::internal::null<> strerror_s(char *, std::size_t, ...) {
83 return fmt::internal::null<>();
vitaut341b98c2015-03-14 13:39:33 -070084}
85
vitaut8725d072015-06-12 07:56:58 -070086namespace fmt {
Victor Zverovichb26e76e2016-06-14 08:11:33 -070087
Victor Zverovich9bb213e2016-08-25 08:38:07 -070088FMT_FUNC format_error::~format_error() throw() {}
Victor Zverovichc333dca2017-02-19 08:41:38 -080089FMT_FUNC system_error::~system_error() throw() {}
Victor Zverovichb26e76e2016-06-14 08:11:33 -070090
Victor Zverovich9ff3b972013-09-07 10:15:08 -070091namespace {
92
93#ifndef _MSC_VER
Victor Zverovichb9a568b2014-09-19 07:51:42 -070094# define FMT_SNPRINTF snprintf
Victor Zverovicha684d0c2013-12-27 08:00:10 -080095#else // _MSC_VER
Victor Zverovich406c6122014-08-19 08:47:38 -070096inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -080097 va_list args;
98 va_start(args, format);
99 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
100 va_end(args);
101 return result;
102}
Victor Zverovichb9a568b2014-09-19 07:51:42 -0700103# define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700104#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -0800105
cstamford55836ca2015-03-10 07:04:31 +0000106#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
107# define FMT_SWPRINTF snwprintf
108#else
109# define FMT_SWPRINTF swprintf
110#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
111
Victor Zverovich7004d1e2015-02-08 19:54:39 -0800112const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700113
Victor Zverovich50e71672017-02-18 06:52:52 -0800114typedef void (*FormatFunc)(buffer &, int, string_view);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700115
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700116// Portable thread-safe version of strerror.
117// Sets buffer to point to a string describing the error code.
118// This can be either a pointer to a string stored in buffer,
119// or a pointer to some static immutable string.
120// Returns one of the following values:
121// 0 - success
122// ERANGE - buffer is not large enough to store the error message
123// other - failure
124// Buffer should be at least of size 1.
125int safe_strerror(
Carter Lie2583ab2015-02-14 09:58:29 +0800126 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
vitaut8ab665a2015-06-22 08:17:23 -0700127 FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
vitaut341b98c2015-03-14 13:39:33 -0700128
vitaut341b98c2015-03-14 13:39:33 -0700129 class StrError {
130 private:
131 int error_code_;
132 char *&buffer_;
133 std::size_t buffer_size_;
134
vitautda052ae2015-03-21 07:53:39 -0700135 // A noop assignment operator to avoid bogus warnings.
136 void operator=(const StrError &) {}
137
vitaut341b98c2015-03-14 13:39:33 -0700138 // Handle the result of XSI-compliant version of strerror_r.
139 int handle(int result) {
vitaute1776ac2015-03-14 14:05:02 -0700140 // glibc versions before 2.13 return result in errno.
141 return result == -1 ? errno : result;
vitaut341b98c2015-03-14 13:39:33 -0700142 }
143
144 // Handle the result of GNU-specific version of strerror_r.
145 int handle(char *message) {
146 // If the buffer is full then the message is probably truncated.
147 if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
148 return ERANGE;
149 buffer_ = message;
150 return 0;
151 }
152
153 // Handle the case when strerror_r is not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800154 int handle(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700155 return fallback(strerror_s(buffer_, buffer_size_, error_code_));
156 }
157
158 // Fallback to strerror_s when strerror_r is not available.
159 int fallback(int result) {
160 // If the buffer is full then the message is probably truncated.
161 return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
162 ERANGE : result;
163 }
164
165 // Fallback to strerror if strerror_r and strerror_s are not available.
Victor Zverovichc333dca2017-02-19 08:41:38 -0800166 int fallback(internal::null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700167 errno = 0;
168 buffer_ = strerror(error_code_);
169 return errno;
170 }
171
172 public:
Radu Popescu0affb232015-08-04 12:52:44 +0200173 StrError(int err_code, char *&buf, std::size_t buf_size)
174 : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
vitaut341b98c2015-03-14 13:39:33 -0700175
vitaut63f6c102015-06-14 09:36:23 -0700176 int run() {
177 strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r.
178 return handle(strerror_r(error_code_, buffer_, buffer_size_));
179 }
vitaut341b98c2015-03-14 13:39:33 -0700180 };
181 return StrError(error_code, buffer, buffer_size).run();
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700182}
183
Victor Zverovichfefaf072017-02-14 16:29:47 -0500184void format_error_code(buffer &out, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800185 string_view message) FMT_NOEXCEPT {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700186 // Report error code making sure that the output fits into
187 // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
188 // bad_alloc.
Victor Zverovichf423e462017-03-11 07:43:26 -0800189 out.resize(0);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700190 static const char SEP[] = ": ";
vitaut1addec92015-03-21 20:16:36 -0700191 static const char ERROR_STR[] = "error ";
vitaut1addec92015-03-21 20:16:36 -0700192 // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
193 std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800194 typedef internal::int_traits<int>::main_type main_type;
195 main_type abs_value = static_cast<main_type>(error_code);
vitaut9d577ca2016-03-02 07:01:21 -0800196 if (internal::is_negative(error_code)) {
197 abs_value = 0 - abs_value;
198 ++error_code_size;
199 }
vitautbfdca8b2016-04-20 09:11:33 -0700200 error_code_size += internal::count_digits(abs_value);
Victor Zverovichfefaf072017-02-14 16:29:47 -0500201 basic_writer<char> w(out);
Victor Zverovichec15ef72017-01-22 07:40:21 -0800202 if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) {
Victor Zverovichfefaf072017-02-14 16:29:47 -0500203 w.write(message);
204 w.write(SEP);
Victor Zverovichec15ef72017-01-22 07:40:21 -0800205 }
Victor Zverovichfefaf072017-02-14 16:29:47 -0500206 w.write(ERROR_STR);
207 w.write(error_code);
vitautbfdca8b2016-04-20 09:11:33 -0700208 assert(out.size() <= internal::INLINE_BUFFER_SIZE);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700209}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700210
vitautbfdca8b2016-04-20 09:11:33 -0700211void report_error(FormatFunc func, int error_code,
Victor Zverovich50e71672017-02-18 06:52:52 -0800212 string_view message) FMT_NOEXCEPT {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800213 memory_buffer full_message;
Victor Zverovich88e0db82014-09-05 08:04:26 -0700214 func(full_message, error_code, message);
215 // Use Writer::data instead of Writer::c_str to avoid potential memory
216 // allocation.
217 std::fwrite(full_message.data(), full_message.size(), 1, stderr);
218 std::fputc('\n', stderr);
Victor Zverovichb605b392013-09-09 22:21:40 -0700219}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700220} // namespace
vitaut270069b2015-06-16 07:36:32 -0700221
Victor Zverovich7f351de2017-12-03 09:18:06 -0800222template <typename Char>
223FMT_FUNC Char internal::thousands_sep(const basic_buffer<Char>& buf) {
224 return std::use_facet<std::numpunct<Char>>(buf.locale().get())
225 .thousands_sep();
226}
227
Victor Zverovichc333dca2017-02-19 08:41:38 -0800228FMT_FUNC void system_error::init(
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800229 int err_code, string_view format_str, format_args args) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800230 error_code_ = err_code;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800231 memory_buffer buffer;
232 format_system_error(buffer, err_code, vformat(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700233 std::runtime_error &base = *this;
Victor Zverovicheedfd072017-02-18 09:13:12 -0800234 base = std::runtime_error(to_string(buffer));
Victor Zverovich53201032014-06-30 14:26:29 -0700235}
236
Victor Zverovichb605b392013-09-09 22:21:40 -0700237template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800238int internal::char_traits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700239 char *buffer, std::size_t size, const char *format,
240 unsigned width, int precision, T value) {
241 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700242 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700243 FMT_SNPRINTF(buffer, size, format, value) :
244 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700245 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700246 return precision < 0 ?
247 FMT_SNPRINTF(buffer, size, format, width, value) :
248 FMT_SNPRINTF(buffer, size, format, width, precision, value);
249}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700250
Victor Zverovichb605b392013-09-09 22:21:40 -0700251template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800252int internal::char_traits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700253 wchar_t *buffer, std::size_t size, const wchar_t *format,
254 unsigned width, int precision, T value) {
255 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700256 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000257 FMT_SWPRINTF(buffer, size, format, value) :
258 FMT_SWPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700259 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700260 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000261 FMT_SWPRINTF(buffer, size, format, width, value) :
262 FMT_SWPRINTF(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700263}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800264
Victor Zverovich311251e2014-11-29 06:58:00 -0800265template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800266const char internal::basic_data<T>::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800267 "0001020304050607080910111213141516171819"
268 "2021222324252627282930313233343536373839"
269 "4041424344454647484950515253545556575859"
270 "6061626364656667686970717273747576777879"
271 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800272
Victor Zverovichf1d85162014-02-19 13:02:22 -0800273#define FMT_POWERS_OF_10(factor) \
274 factor * 10, \
275 factor * 100, \
276 factor * 1000, \
277 factor * 10000, \
278 factor * 100000, \
279 factor * 1000000, \
280 factor * 10000000, \
281 factor * 100000000, \
282 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800283
Victor Zverovich311251e2014-11-29 06:58:00 -0800284template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800285const uint32_t internal::basic_data<T>::POWERS_OF_10_32[] = {
Victor Zverovich311251e2014-11-29 06:58:00 -0800286 0, FMT_POWERS_OF_10(1)
287};
288
289template <typename T>
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800290const uint64_t internal::basic_data<T>::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800291 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800292 FMT_POWERS_OF_10(1),
Victor Zverovich016aceb2017-08-26 09:09:43 -0700293 FMT_POWERS_OF_10(1000000000ull),
294 10000000000000000000ull
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800295};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800296
vitaut24c309f2015-06-12 07:15:57 -0700297#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700298
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800299FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
Victor Zverovichdff21372014-12-16 07:01:01 -0800300 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
vitautc3ba6152015-08-07 07:34:58 -0700301 if (s.size() > INT_MAX)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800302 FMT_THROW(windows_error(ERROR_INVALID_PARAMETER, ERROR_MSG));
vitautc3ba6152015-08-07 07:34:58 -0700303 int s_size = static_cast<int>(s.size());
304 int length = MultiByteToWideChar(
305 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700306 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800307 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700308 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700309 length = MultiByteToWideChar(
vitautc3ba6152015-08-07 07:34:58 -0700310 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700311 if (length == 0)
Victor Zverovichc333dca2017-02-19 08:41:38 -0800312 FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700313 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700314}
315
Victor Zverovichc333dca2017-02-19 08:41:38 -0800316FMT_FUNC internal::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700317 if (int error_code = convert(s)) {
Victor Zverovichc333dca2017-02-19 08:41:38 -0800318 FMT_THROW(windows_error(error_code,
Victor Zverovich8b76e972014-10-06 08:30:55 -0700319 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700320 }
321}
322
Victor Zverovichc333dca2017-02-19 08:41:38 -0800323FMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) {
vitautca747812015-08-07 07:08:46 -0700324 if (s.size() > INT_MAX)
325 return ERROR_INVALID_PARAMETER;
326 int s_size = static_cast<int>(s.size());
327 int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
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(
vitautca747812015-08-07 07:08:46 -0700332 CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
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 Zverovich50e71672017-02-18 06:52:52 -0800349 buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700350 FMT_TRY {
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800351 wmemory_buffer buffer;
Michael Winterberg2a05a872016-03-02 17:35:34 -0800352 buffer.resize(INLINE_BUFFER_SIZE);
353 for (;;) {
354 wchar_t *system_message = &buffer[0];
Victor Zverovichf85d5f42016-10-22 08:04:20 -0700355 int result = FormatMessageW(
356 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
357 0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
358 system_message, static_cast<uint32_t>(buffer.size()), 0);
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 Zveroviche022c212017-02-17 06:38:53 -0800362 basic_writer<char> w(out);
363 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.
372 buffer.resize(buffer.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700373 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700374 } FMT_CATCH(...) {}
vitaut66069712015-11-18 08:42:09 -0800375 fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
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 Zverovich50e71672017-02-18 06:52:52 -0800381 buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
vitaut24c309f2015-06-12 07:15:57 -0700382 FMT_TRY {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800383 memory_buffer buffer;
Victor Zverovichcc9b0512016-05-11 21:36:22 -0600384 buffer.resize(internal::INLINE_BUFFER_SIZE);
vitaut24c309f2015-06-12 07:15:57 -0700385 for (;;) {
386 char *system_message = &buffer[0];
387 int result = safe_strerror(error_code, system_message, buffer.size());
388 if (result == 0) {
Victor Zverovichfefaf072017-02-14 16:29:47 -0500389 basic_writer<char> w(out);
390 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.
397 buffer.resize(buffer.size() * 2);
398 }
399 } FMT_CATCH(...) {}
vitaut66069712015-11-18 08:42:09 -0800400 fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
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 {
vitaute5d59982015-11-20 07:56:16 -0800414 // 'fmt::' is for bcc32.
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700415 report_error(format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700416}
417
vitaut24c309f2015-06-12 07:15:57 -0700418#if FMT_USE_WINDOWS_H
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700419FMT_FUNC void report_windows_error(
Victor Zverovich50e71672017-02-18 06:52:52 -0800420 int error_code, fmt::string_view message) FMT_NOEXCEPT {
vitaute5d59982015-11-20 07:56:16 -0800421 // 'fmt::' is for bcc32.
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700422 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700423}
Victor Zverovich400812a2014-04-30 12:38:17 -0700424#endif
Victor Zverovichf7939862014-04-30 10:18:11 -0700425
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800426FMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {
Victor Zverovicheedfd072017-02-18 09:13:12 -0800427 memory_buffer buffer;
Victor Zverovichfefaf072017-02-14 16:29:47 -0500428 vformat_to(buffer, format_str, args);
429 std::fwrite(buffer.data(), 1, buffer.size(), f);
Victor Zverovichd5b81962014-06-28 21:56:40 -0700430}
431
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800432FMT_FUNC void vprint(string_view format_str, format_args args) {
Victor Zverovich0028ce52016-08-26 17:23:13 -0700433 vprint(stdout, format_str, args);
Victor Zverovich163178e2014-09-25 07:08:25 -0700434}
435
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800436FMT_FUNC void vprint_colored(Color c, string_view format, format_args args) {
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700437 char escape[] = "\x1b[30m";
Ingo van Lilf4d88842015-11-02 19:14:47 +0100438 escape[3] = static_cast<char>('0' + c);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700439 std::fputs(escape, stdout);
Victor Zverovich0028ce52016-08-26 17:23:13 -0700440 vprint(format, args);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700441 std::fputs(RESET_COLOR, stdout);
442}
443
Victor Zverovichc09c42f2015-03-01 09:43:33 -0800444#ifndef FMT_HEADER_ONLY
445
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800446template struct internal::basic_data<void>;
vitaut804a74c2015-05-14 12:58:42 -0700447
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700448// Explicit instantiations for char.
449
Victor Zverovich7f351de2017-12-03 09:18:06 -0800450template locale basic_buffer<char>::locale() const;
451
452template char internal::thousands_sep(const basic_buffer<char>& buf);
453
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800454template void basic_fixed_buffer<char>::grow(std::size_t);
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800455
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800456template void internal::arg_map<context>::init(const format_args &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700457
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800458template int internal::char_traits<char>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700459 char *buffer, std::size_t size, const char *format,
460 unsigned width, int precision, double value);
461
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800462template int internal::char_traits<char>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700463 char *buffer, std::size_t size, const char *format,
464 unsigned width, int precision, long double value);
465
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700466// Explicit instantiations for wchar_t.
467
Victor Zverovich7f351de2017-12-03 09:18:06 -0800468template locale basic_buffer<wchar_t>::locale() const;
469
470template wchar_t internal::thousands_sep(const basic_buffer<wchar_t>& buf);
471
Victor Zverovich624c5862017-02-05 06:41:39 -0800472template class basic_context<wchar_t>;
Victor Zverovichd705d512016-12-29 09:07:39 -0800473
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800474template void basic_fixed_buffer<wchar_t>::grow(std::size_t);
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800475
Victor Zverovich81bd9e82017-12-03 07:32:04 -0800476template void internal::arg_map<wcontext>::init(const wformat_args &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700477
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800478template int internal::char_traits<wchar_t>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700479 wchar_t *buffer, std::size_t size, const wchar_t *format,
480 unsigned width, int precision, double value);
481
Victor Zverovich6a2ff282017-02-19 06:46:51 -0800482template int internal::char_traits<wchar_t>::format_float(
Victor Zverovich14f25772014-09-19 08:45:05 -0700483 wchar_t *buffer, std::size_t size, const wchar_t *format,
484 unsigned width, int precision, long double value);
485
Victor Zverovichc09c42f2015-03-01 09:43:33 -0800486#endif // FMT_HEADER_ONLY
487
Victor Zverovich0d5ef5c2016-07-12 06:59:35 -0700488} // namespace fmt
489
Ingo van Lilb4b13ee2015-11-02 12:34:46 +0100490#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +0000491# pragma warning(pop)
492#endif