blob: 64499ad788c82dff44ddd1a96cdad1969784c3e8 [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"
Glen Stark72d51e02016-06-08 01:23:32 +020029#include "fmt/printf.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 Zverovich6e5551e2014-07-02 06:33:25 -070054using fmt::internal::Arg;
Victor Zverovich447e02c2014-02-15 10:48:34 -080055
Victor Zverovich8b76e972014-10-06 08:30:55 -070056#if FMT_EXCEPTIONS
57# define FMT_TRY try
58# define FMT_CATCH(x) catch (x)
59#else
60# define FMT_TRY if (true)
61# define FMT_CATCH(x) if (false)
62#endif
63
Ingo van Lilb4b13ee2015-11-02 12:34:46 +010064#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +000065# pragma warning(push)
Victor Zverovich8b76e972014-10-06 08:30:55 -070066# pragma warning(disable: 4127) // conditional expression is constant
Daniel.Perrybd0067e2014-11-25 18:01:09 -050067# pragma warning(disable: 4702) // unreachable code
vitautdf47d812015-03-16 18:53:14 -070068// Disable deprecation warning for strerror. The latter is not called but
69// MSVC fails to detect it.
70# pragma warning(disable: 4996)
jdale88a9862fd2014-03-11 18:56:24 +000071#endif
72
vitaut341b98c2015-03-14 13:39:33 -070073// Dummy implementations of strerror_r and strerror_s called if corresponding
74// system functions are not available.
vitautc669cbe2015-07-07 07:05:17 -070075static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
76 return fmt::internal::Null<>();
vitaut341b98c2015-03-14 13:39:33 -070077}
vitautc669cbe2015-07-07 07:05:17 -070078static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
79 return fmt::internal::Null<>();
vitaut341b98c2015-03-14 13:39:33 -070080}
81
vitaut8725d072015-06-12 07:56:58 -070082namespace fmt {
Victor Zverovich9ff3b972013-09-07 10:15:08 -070083namespace {
84
85#ifndef _MSC_VER
Victor Zverovichb9a568b2014-09-19 07:51:42 -070086# define FMT_SNPRINTF snprintf
Victor Zverovicha684d0c2013-12-27 08:00:10 -080087#else // _MSC_VER
Victor Zverovich406c6122014-08-19 08:47:38 -070088inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -080089 va_list args;
90 va_start(args, format);
91 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
92 va_end(args);
93 return result;
94}
Victor Zverovichb9a568b2014-09-19 07:51:42 -070095# define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -070096#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -080097
cstamford55836ca2015-03-10 07:04:31 +000098#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
99# define FMT_SWPRINTF snwprintf
100#else
101# define FMT_SWPRINTF swprintf
102#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
103
Victor Zverovich7004d1e2015-02-08 19:54:39 -0800104const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700105
vitautbfdca8b2016-04-20 09:11:33 -0700106typedef void (*FormatFunc)(Writer &, int, StringRef);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700107
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700108// Portable thread-safe version of strerror.
109// Sets buffer to point to a string describing the error code.
110// This can be either a pointer to a string stored in buffer,
111// or a pointer to some static immutable string.
112// Returns one of the following values:
113// 0 - success
114// ERANGE - buffer is not large enough to store the error message
115// other - failure
116// Buffer should be at least of size 1.
117int safe_strerror(
Carter Lie2583ab2015-02-14 09:58:29 +0800118 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
vitaut8ab665a2015-06-22 08:17:23 -0700119 FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
vitaut341b98c2015-03-14 13:39:33 -0700120
vitaut341b98c2015-03-14 13:39:33 -0700121 class StrError {
122 private:
123 int error_code_;
124 char *&buffer_;
125 std::size_t buffer_size_;
126
vitautda052ae2015-03-21 07:53:39 -0700127 // A noop assignment operator to avoid bogus warnings.
128 void operator=(const StrError &) {}
129
vitaut341b98c2015-03-14 13:39:33 -0700130 // Handle the result of XSI-compliant version of strerror_r.
131 int handle(int result) {
vitaute1776ac2015-03-14 14:05:02 -0700132 // glibc versions before 2.13 return result in errno.
133 return result == -1 ? errno : result;
vitaut341b98c2015-03-14 13:39:33 -0700134 }
135
136 // Handle the result of GNU-specific version of strerror_r.
137 int handle(char *message) {
138 // If the buffer is full then the message is probably truncated.
139 if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
140 return ERANGE;
141 buffer_ = message;
142 return 0;
143 }
144
145 // Handle the case when strerror_r is not available.
vitautbfdca8b2016-04-20 09:11:33 -0700146 int handle(internal::Null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700147 return fallback(strerror_s(buffer_, buffer_size_, error_code_));
148 }
149
150 // Fallback to strerror_s when strerror_r is not available.
151 int fallback(int result) {
152 // If the buffer is full then the message is probably truncated.
153 return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
154 ERANGE : result;
155 }
156
157 // Fallback to strerror if strerror_r and strerror_s are not available.
vitautbfdca8b2016-04-20 09:11:33 -0700158 int fallback(internal::Null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700159 errno = 0;
160 buffer_ = strerror(error_code_);
161 return errno;
162 }
163
164 public:
Radu Popescu0affb232015-08-04 12:52:44 +0200165 StrError(int err_code, char *&buf, std::size_t buf_size)
166 : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
vitaut341b98c2015-03-14 13:39:33 -0700167
vitaut63f6c102015-06-14 09:36:23 -0700168 int run() {
169 strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r.
170 return handle(strerror_r(error_code_, buffer_, buffer_size_));
171 }
vitaut341b98c2015-03-14 13:39:33 -0700172 };
173 return StrError(error_code, buffer, buffer_size).run();
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700174}
175
vitautbfdca8b2016-04-20 09:11:33 -0700176void format_error_code(Writer &out, int error_code,
177 StringRef message) FMT_NOEXCEPT {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700178 // Report error code making sure that the output fits into
179 // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
180 // bad_alloc.
181 out.clear();
182 static const char SEP[] = ": ";
vitaut1addec92015-03-21 20:16:36 -0700183 static const char ERROR_STR[] = "error ";
vitaut1addec92015-03-21 20:16:36 -0700184 // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
185 std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
vitautbfdca8b2016-04-20 09:11:33 -0700186 typedef internal::IntTraits<int>::MainType MainType;
vitaut9d577ca2016-03-02 07:01:21 -0800187 MainType abs_value = static_cast<MainType>(error_code);
188 if (internal::is_negative(error_code)) {
189 abs_value = 0 - abs_value;
190 ++error_code_size;
191 }
vitautbfdca8b2016-04-20 09:11:33 -0700192 error_code_size += internal::count_digits(abs_value);
193 if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size)
Victor Zverovich22f75d82014-09-03 08:03:05 -0700194 out << message << SEP;
vitaut1addec92015-03-21 20:16:36 -0700195 out << ERROR_STR << error_code;
vitautbfdca8b2016-04-20 09:11:33 -0700196 assert(out.size() <= internal::INLINE_BUFFER_SIZE);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700197}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700198
vitautbfdca8b2016-04-20 09:11:33 -0700199void report_error(FormatFunc func, int error_code,
200 StringRef message) FMT_NOEXCEPT {
201 MemoryWriter full_message;
Victor Zverovich88e0db82014-09-05 08:04:26 -0700202 func(full_message, error_code, message);
203 // Use Writer::data instead of Writer::c_str to avoid potential memory
204 // allocation.
205 std::fwrite(full_message.data(), full_message.size(), 1, stderr);
206 std::fputc('\n', stderr);
Victor Zverovichb605b392013-09-09 22:21:40 -0700207}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700208} // namespace
vitaut270069b2015-06-16 07:36:32 -0700209
210namespace internal {
211
Victor Zverovichcc9b0512016-05-11 21:36:22 -0600212// This method is used to preserve binary compatibility with fmt 3.0.
213// It can be removed in 4.0.
214FMT_FUNC void format_system_error(
215 Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
216 fmt::format_system_error(out, error_code, message);
217}
vitaut270069b2015-06-16 07:36:32 -0700218} // namespace internal
vitaut8725d072015-06-12 07:56:58 -0700219} // namespace fmt
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700220
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800221FMT_FUNC void fmt::SystemError::init(
vitaut438bd9b2015-06-26 07:43:54 -0700222 int err_code, CStringRef format_str, ArgList args) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800223 error_code_ = err_code;
Victor Zverovichd1ded562014-09-29 08:48:16 -0700224 MemoryWriter w;
Victor Zverovichcc9b0512016-05-11 21:36:22 -0600225 format_system_error(w, err_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700226 std::runtime_error &base = *this;
227 base = std::runtime_error(w.str());
228}
229
Victor Zverovichb605b392013-09-09 22:21:40 -0700230template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700231int fmt::internal::CharTraits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700232 char *buffer, std::size_t size, const char *format,
233 unsigned width, int precision, T value) {
234 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700235 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700236 FMT_SNPRINTF(buffer, size, format, value) :
237 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700238 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700239 return precision < 0 ?
240 FMT_SNPRINTF(buffer, size, format, width, value) :
241 FMT_SNPRINTF(buffer, size, format, width, precision, value);
242}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700243
Victor Zverovichb605b392013-09-09 22:21:40 -0700244template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700245int fmt::internal::CharTraits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700246 wchar_t *buffer, std::size_t size, const wchar_t *format,
247 unsigned width, int precision, T value) {
248 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700249 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000250 FMT_SWPRINTF(buffer, size, format, value) :
251 FMT_SWPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700252 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700253 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000254 FMT_SWPRINTF(buffer, size, format, width, value) :
255 FMT_SWPRINTF(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700256}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800257
Victor Zverovich311251e2014-11-29 06:58:00 -0800258template <typename T>
259const char fmt::internal::BasicData<T>::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800260 "0001020304050607080910111213141516171819"
261 "2021222324252627282930313233343536373839"
262 "4041424344454647484950515253545556575859"
263 "6061626364656667686970717273747576777879"
264 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800265
Victor Zverovichf1d85162014-02-19 13:02:22 -0800266#define FMT_POWERS_OF_10(factor) \
267 factor * 10, \
268 factor * 100, \
269 factor * 1000, \
270 factor * 10000, \
271 factor * 100000, \
272 factor * 1000000, \
273 factor * 10000000, \
274 factor * 100000000, \
275 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800276
Victor Zverovich311251e2014-11-29 06:58:00 -0800277template <typename T>
278const uint32_t fmt::internal::BasicData<T>::POWERS_OF_10_32[] = {
279 0, FMT_POWERS_OF_10(1)
280};
281
282template <typename T>
283const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800284 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800285 FMT_POWERS_OF_10(1),
Victor Zverovichecd2b802014-12-17 06:42:26 -0800286 FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
Victor Zverovich406c6122014-08-19 08:47:38 -0700287 // Multiply several constants instead of using a single long long constant
Victor Zverovichf1d85162014-02-19 13:02:22 -0800288 // to avoid warnings about C++98 not supporting long long.
Victor Zverovichecd2b802014-12-17 06:42:26 -0800289 fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800290};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800291
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800292FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
Carter Li2d4631a2015-03-14 14:54:37 +0800293 (void)type;
Victor Zverovich877abaf2013-01-08 09:56:05 -0800294 if (std::isprint(static_cast<unsigned char>(code))) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700295 FMT_THROW(fmt::FormatError(
296 fmt::format("unknown format code '{}' for {}", code, type)));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800297 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700298 FMT_THROW(fmt::FormatError(
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700299 fmt::format("unknown format code '\\x{:02x}' for {}",
Victor Zverovich8b76e972014-10-06 08:30:55 -0700300 static_cast<unsigned>(code), type)));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800301}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700302
vitaut24c309f2015-06-12 07:15:57 -0700303#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700304
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800305FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
Victor Zverovichdff21372014-12-16 07:01:01 -0800306 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
vitautc3ba6152015-08-07 07:34:58 -0700307 if (s.size() > INT_MAX)
308 FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
309 int s_size = static_cast<int>(s.size());
310 int length = MultiByteToWideChar(
311 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700312 if (length == 0)
Victor Zverovichdff21372014-12-16 07:01:01 -0800313 FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700314 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700315 length = MultiByteToWideChar(
vitautc3ba6152015-08-07 07:34:58 -0700316 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700317 if (length == 0)
Victor Zverovichdff21372014-12-16 07:01:01 -0800318 FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700319 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700320}
321
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800322FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700323 if (int error_code = convert(s)) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700324 FMT_THROW(WindowsError(error_code,
325 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700326 }
327}
328
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800329FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
vitautca747812015-08-07 07:08:46 -0700330 if (s.size() > INT_MAX)
331 return ERROR_INVALID_PARAMETER;
332 int s_size = static_cast<int>(s.size());
333 int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700334 if (length == 0)
335 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700336 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700337 length = WideCharToMultiByte(
vitautca747812015-08-07 07:08:46 -0700338 CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700339 if (length == 0)
340 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700341 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700342 return 0;
343}
344
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800345FMT_FUNC void fmt::WindowsError::init(
vitautba09c1b2015-06-26 09:23:11 -0700346 int err_code, CStringRef format_str, ArgList args) {
Carter Li3f574c12015-02-17 10:11:42 +0800347 error_code_ = err_code;
Victor Zverovich8c4db502014-09-29 09:17:02 -0700348 MemoryWriter w;
Carter Li3f574c12015-02-17 10:11:42 +0800349 internal::format_windows_error(w, err_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700350 std::runtime_error &base = *this;
351 base = std::runtime_error(w.str());
352}
353
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800354FMT_FUNC void fmt::internal::format_windows_error(
Victor Zverovich22f75d82014-09-03 08:03:05 -0700355 fmt::Writer &out, int error_code,
Carter Lie2583ab2015-02-14 09:58:29 +0800356 fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700357 FMT_TRY {
Michael Winterberg2a05a872016-03-02 17:35:34 -0800358 MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer;
359 buffer.resize(INLINE_BUFFER_SIZE);
360 for (;;) {
361 wchar_t *system_message = &buffer[0];
362 int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
363 0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
364 system_message, static_cast<uint32_t>(buffer.size()), 0);
365 if (result != 0) {
366 UTF16ToUTF8 utf8_message;
367 if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
368 out << message << ": " << utf8_message;
369 return;
370 }
371 break;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700372 }
Michael Winterberg2a05a872016-03-02 17:35:34 -0800373 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
374 break; // Can't get error message, report error code instead.
375 buffer.resize(buffer.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700376 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700377 } FMT_CATCH(...) {}
vitaut66069712015-11-18 08:42:09 -0800378 fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
Victor Zverovich53b4c312014-04-30 15:00:41 -0700379}
vitaut24c309f2015-06-12 07:15:57 -0700380
381#endif // FMT_USE_WINDOWS_H
382
Victor Zverovichcc9b0512016-05-11 21:36:22 -0600383FMT_FUNC void fmt::format_system_error(
vitaut24c309f2015-06-12 07:15:57 -0700384 fmt::Writer &out, int error_code,
385 fmt::StringRef message) FMT_NOEXCEPT {
386 FMT_TRY {
Victor Zverovichcc9b0512016-05-11 21:36:22 -0600387 internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> buffer;
388 buffer.resize(internal::INLINE_BUFFER_SIZE);
vitaut24c309f2015-06-12 07:15:57 -0700389 for (;;) {
390 char *system_message = &buffer[0];
391 int result = safe_strerror(error_code, system_message, buffer.size());
392 if (result == 0) {
393 out << message << ": " << system_message;
394 return;
395 }
396 if (result != ERANGE)
397 break; // Can't get error message, report error code instead.
398 buffer.resize(buffer.size() * 2);
399 }
400 } FMT_CATCH(...) {}
vitaut66069712015-11-18 08:42:09 -0800401 fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
vitaut24c309f2015-06-12 07:15:57 -0700402}
Victor Zverovich53b4c312014-04-30 15:00:41 -0700403
jamboree7487bde2015-06-10 09:32:59 +0800404template <typename Char>
vitauta98583d2015-06-10 08:49:22 -0700405void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
jamboree7487bde2015-06-10 09:32:59 +0800406 if (!map_.empty())
407 return;
vitauta98583d2015-06-10 08:49:22 -0700408 typedef internal::NamedArg<Char> NamedArg;
vitautfccff7b2015-06-11 07:19:00 -0700409 const NamedArg *named_arg = 0;
vitauta98583d2015-06-10 08:49:22 -0700410 bool use_values =
411 args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
jamboree7487bde2015-06-10 09:32:59 +0800412 if (use_values) {
413 for (unsigned i = 0;/*nothing*/; ++i) {
414 internal::Arg::Type arg_type = args.type(i);
415 switch (arg_type) {
416 case internal::Arg::NONE:
417 return;
418 case internal::Arg::NAMED_ARG:
vitauta98583d2015-06-10 08:49:22 -0700419 named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
Michael Winterberg4af764d2016-01-10 15:30:34 -0800420 map_.push_back(Pair(named_arg->name, *named_arg));
jamboree7487bde2015-06-10 09:32:59 +0800421 break;
422 default:
423 /*nothing*/;
424 }
425 }
426 return;
427 }
vitauta98583d2015-06-10 08:49:22 -0700428 for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
jamboree7487bde2015-06-10 09:32:59 +0800429 internal::Arg::Type arg_type = args.type(i);
430 if (arg_type == internal::Arg::NAMED_ARG) {
vitauta98583d2015-06-10 08:49:22 -0700431 named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
Michael Winterberg4af764d2016-01-10 15:30:34 -0800432 map_.push_back(Pair(named_arg->name, *named_arg));
jamboree7487bde2015-06-10 09:32:59 +0800433 }
434 }
vitauta98583d2015-06-10 08:49:22 -0700435 for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
jamboree7487bde2015-06-10 09:32:59 +0800436 switch (args.args_[i].type) {
437 case internal::Arg::NONE:
438 return;
439 case internal::Arg::NAMED_ARG:
vitauta98583d2015-06-10 08:49:22 -0700440 named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
Michael Winterberg4af764d2016-01-10 15:30:34 -0800441 map_.push_back(Pair(named_arg->name, *named_arg));
jamboree7487bde2015-06-10 09:32:59 +0800442 break;
443 default:
444 /*nothing*/;
445 }
446 }
447}
448
Victor Zverovichd1ded562014-09-29 08:48:16 -0700449template <typename Char>
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800450void fmt::internal::FixedBuffer<Char>::grow(std::size_t) {
451 FMT_THROW(std::runtime_error("buffer overflow"));
452}
453
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800454FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
Victor Zverovich605d2602014-08-29 07:45:55 -0700455 unsigned arg_index, const char *&error) {
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700456 Arg arg = args_[arg_index];
jamboree7487bde2015-06-10 09:32:59 +0800457 switch (arg.type) {
458 case Arg::NONE:
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700459 error = "argument index out of range";
jamboree7487bde2015-06-10 09:32:59 +0800460 break;
461 case Arg::NAMED_ARG:
462 arg = *static_cast<const internal::Arg*>(arg.pointer);
Patrik Weiskircher6178bc62016-02-23 12:59:26 -0500463 break;
jamboree7487bde2015-06-10 09:32:59 +0800464 default:
465 /*nothing*/;
466 }
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700467 return arg;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700468}
469
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800470FMT_FUNC void fmt::report_system_error(
Carter Lie2583ab2015-02-14 09:58:29 +0800471 int error_code, fmt::StringRef message) FMT_NOEXCEPT {
vitaute5d59982015-11-20 07:56:16 -0800472 // 'fmt::' is for bcc32.
Victor Zverovichcc9b0512016-05-11 21:36:22 -0600473 fmt::report_error(format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700474}
475
vitaut24c309f2015-06-12 07:15:57 -0700476#if FMT_USE_WINDOWS_H
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800477FMT_FUNC void fmt::report_windows_error(
Carter Lie2583ab2015-02-14 09:58:29 +0800478 int error_code, fmt::StringRef message) FMT_NOEXCEPT {
vitaute5d59982015-11-20 07:56:16 -0800479 // 'fmt::' is for bcc32.
480 fmt::report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700481}
Victor Zverovich400812a2014-04-30 12:38:17 -0700482#endif
Victor Zverovichf7939862014-04-30 10:18:11 -0700483
vitaut438bd9b2015-06-26 07:43:54 -0700484FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args) {
Victor Zverovichd1ded562014-09-29 08:48:16 -0700485 MemoryWriter w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -0700486 w.write(format_str, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -0700487 std::fwrite(w.data(), 1, w.size(), f);
488}
489
vitaut438bd9b2015-06-26 07:43:54 -0700490FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) {
Victor Zverovich163178e2014-09-25 07:08:25 -0700491 print(stdout, format_str, args);
492}
493
vitaut438bd9b2015-06-26 07:43:54 -0700494FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700495 char escape[] = "\x1b[30m";
Ingo van Lilf4d88842015-11-02 19:14:47 +0100496 escape[3] = static_cast<char>('0' + c);
Victor Zverovich2dc108b2014-07-01 09:10:43 -0700497 std::fputs(escape, stdout);
498 print(format, args);
499 std::fputs(RESET_COLOR, stdout);
500}
501
vitaut438bd9b2015-06-26 07:43:54 -0700502FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) {
Victor Zverovichd1ded562014-09-29 08:48:16 -0700503 MemoryWriter w;
Victor Zverovich21111cc2014-06-29 19:52:26 -0700504 printf(w, format, args);
Victor Zverovich615c1ee2014-11-14 09:40:01 -0800505 std::size_t size = w.size();
506 return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
Victor Zverovichd5b81962014-06-28 21:56:40 -0700507}
508
Victor Zverovichc09c42f2015-03-01 09:43:33 -0800509#ifndef FMT_HEADER_ONLY
510
vitaut9ca1ce22015-05-23 08:04:06 -0700511template struct fmt::internal::BasicData<void>;
vitaut804a74c2015-05-14 12:58:42 -0700512
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700513// Explicit instantiations for char.
514
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800515template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
516
vitaut535dbdd2015-12-03 09:38:06 -0800517template void fmt::internal::ArgMap<char>::init(const fmt::ArgList &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700518
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700519template void fmt::internal::PrintfFormatter<char>::format(
vitaut20003762015-07-28 08:09:29 -0700520 BasicWriter<char> &writer, CStringRef format);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700521
Victor Zverovich14f25772014-09-19 08:45:05 -0700522template int fmt::internal::CharTraits<char>::format_float(
523 char *buffer, std::size_t size, const char *format,
524 unsigned width, int precision, double value);
525
526template int fmt::internal::CharTraits<char>::format_float(
527 char *buffer, std::size_t size, const char *format,
528 unsigned width, int precision, long double value);
529
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700530// Explicit instantiations for wchar_t.
531
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800532template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
533
vitaut535dbdd2015-12-03 09:38:06 -0800534template void fmt::internal::ArgMap<wchar_t>::init(const fmt::ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700535
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700536template void fmt::internal::PrintfFormatter<wchar_t>::format(
vitaut20003762015-07-28 08:09:29 -0700537 BasicWriter<wchar_t> &writer, WCStringRef format);
jdale88a9862fd2014-03-11 18:56:24 +0000538
Victor Zverovich14f25772014-09-19 08:45:05 -0700539template int fmt::internal::CharTraits<wchar_t>::format_float(
540 wchar_t *buffer, std::size_t size, const wchar_t *format,
541 unsigned width, int precision, double value);
542
543template int fmt::internal::CharTraits<wchar_t>::format_float(
544 wchar_t *buffer, std::size_t size, const wchar_t *format,
545 unsigned width, int precision, long double value);
546
Victor Zverovichc09c42f2015-03-01 09:43:33 -0800547#endif // FMT_HEADER_ONLY
548
Ingo van Lilb4b13ee2015-11-02 12:34:46 +0100549#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +0000550# pragma warning(pop)
551#endif