blob: 6a3e2aa2db6855504859838febaf54138d9be49b [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
4 Copyright (c) 2012, Victor Zverovich
5 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 Zverovichd53f2092012-12-16 15:06:31 -080028// Disable useless MSVC warnings.
Victor Zverovichf8c91062012-12-17 15:41:00 -080029#undef _CRT_SECURE_NO_WARNINGS
Victor Zverovichd53f2092012-12-16 15:06:31 -080030#define _CRT_SECURE_NO_WARNINGS
Victor Zverovichc240a122012-12-21 15:02:25 -080031#undef _SCL_SECURE_NO_WARNINGS
32#define _SCL_SECURE_NO_WARNINGS
Victor Zverovichd53f2092012-12-16 15:06:31 -080033
Victor Zverovichfbfedcf2013-01-14 15:16:20 -080034#include "format.h"
35
Victor Zverovich859a4972014-04-30 06:55:21 -070036#include <string.h>
37
Victor Zverovich72f896d2012-12-12 09:17:28 -080038#include <cctype>
Victor Zverovichf28645f2014-04-24 12:37:06 -070039#include <climits>
Victor Zverovich9ff3b972013-09-07 10:15:08 -070040#include <cmath>
Victor Zverovicha684d0c2013-12-27 08:00:10 -080041#include <cstdarg>
Victor Zverovich9ff3b972013-09-07 10:15:08 -070042
Victor Zverovich859a4972014-04-30 06:55:21 -070043#ifdef _WIN32
Victor Zverovichdcd039d2014-05-01 07:09:42 -070044# define WIN32_LEAN_AND_MEAN
Constantine Tarasenkov6aace692014-06-11 02:38:57 +040045# ifdef __MINGW32__
46# include <cstring>
47# endif
Victor Zverovich859a4972014-04-30 06:55:21 -070048# include <windows.h>
Victor Zveroviched2bdba2014-04-30 07:41:54 -070049# undef ERROR
Victor Zverovich859a4972014-04-30 06:55:21 -070050#endif
51
Victor Zverovich447e02c2014-02-15 10:48:34 -080052using fmt::ULongLong;
53
jdale88a9862fd2014-03-11 18:56:24 +000054#if _MSC_VER
55# pragma warning(push)
56# pragma warning(disable: 4127) // conditional expression is constant
57#endif
58
Victor Zverovich9ff3b972013-09-07 10:15:08 -070059namespace {
60
61#ifndef _MSC_VER
62
63inline int SignBit(double value) {
64 // When compiled in C++11 mode signbit is no longer a macro but a function
65 // defined in namespace std and the macro is undefined.
Victor Zverovichf2e06802014-04-10 10:49:55 -070066#ifdef signbit
Victor Zverovich9ff3b972013-09-07 10:15:08 -070067 return signbit(value);
Victor Zverovichf2e06802014-04-10 10:49:55 -070068#else
69 return std::signbit(value);
70#endif
Victor Zverovich9ff3b972013-09-07 10:15:08 -070071}
72
73inline int IsInf(double x) {
74#ifdef isinf
75 return isinf(x);
76#else
77 return std::isinf(x);
78#endif
79}
80
81#define FMT_SNPRINTF snprintf
82
Victor Zverovicha684d0c2013-12-27 08:00:10 -080083#else // _MSC_VER
Victor Zverovich9ff3b972013-09-07 10:15:08 -070084
85inline int SignBit(double value) {
86 if (value < 0) return 1;
87 if (value == value) return 0;
88 int dec = 0, sign = 0;
89 char buffer[2]; // The buffer size must be >= 2 or _ecvt_s will fail.
90 _ecvt_s(buffer, sizeof(buffer), value, 0, &dec, &sign);
91 return sign;
92}
93
94inline int IsInf(double x) { return !_finite(x); }
95
Victor Zverovicha684d0c2013-12-27 08:00:10 -080096inline int FMT_SNPRINTF(char *buffer, size_t size, const char *format, ...) {
97 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 Zverovich9ff3b972013-09-07 10:15:08 -0700103
104#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -0800105
106const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700107
108typedef void (*FormatFunc)(fmt::Writer &, int , fmt::StringRef);
109
110void ReportError(FormatFunc func,
111 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
112 try {
113 fmt::Writer full_message;
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700114 func(full_message, error_code, message); // TODO: make sure this doesn't throw
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700115 std::fwrite(full_message.c_str(), full_message.size(), 1, stderr);
116 std::fputc('\n', stderr);
117 } catch (...) {}
Victor Zverovichb605b392013-09-09 22:21:40 -0700118}
Victor Zverovichd29e5052014-06-30 07:12:09 -0700119
120const fmt::internal::ArgInfo DUMMY_ARG = {fmt::internal::ArgInfo::INT, 0};
121
122fmt::ULongLong GetIntValue(const fmt::internal::ArgInfo &arg) {
123 typedef fmt::internal::ArgInfo Arg;
124 switch (arg.type) {
125 case Arg::INT:
126 return arg.int_value;
127 case Arg::UINT:
128 return arg.uint_value;
129 case Arg::LONG_LONG:
130 return arg.long_long_value;
131 case Arg::ULONG_LONG:
132 return arg.ulong_long_value;
133 default:
134 return -1;
135 }
136}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700137} // namespace
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700138
Victor Zverovich302b8f42014-06-24 10:46:01 -0700139int fmt::internal::SignBitNoInline(double value) { return SignBit(value); }
140
Victor Zverovich53201032014-06-30 14:26:29 -0700141void fmt::SystemError::init(
142 int error_code, StringRef format_str, const ArgList &args) {
143 error_code_ = error_code;
144 Writer w;
145 internal::FormatSystemErrorMessage(w, error_code, format(format_str, args));
146 std::runtime_error &base = *this;
147 base = std::runtime_error(w.str());
148}
149
Victor Zverovichb605b392013-09-09 22:21:40 -0700150template <typename T>
151int fmt::internal::CharTraits<char>::FormatFloat(
152 char *buffer, std::size_t size, const char *format,
153 unsigned width, int precision, T value) {
154 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700155 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700156 FMT_SNPRINTF(buffer, size, format, value) :
157 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700158 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700159 return precision < 0 ?
160 FMT_SNPRINTF(buffer, size, format, width, value) :
161 FMT_SNPRINTF(buffer, size, format, width, precision, value);
162}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700163
Victor Zverovichb605b392013-09-09 22:21:40 -0700164template <typename T>
165int fmt::internal::CharTraits<wchar_t>::FormatFloat(
166 wchar_t *buffer, std::size_t size, const wchar_t *format,
167 unsigned width, int precision, T value) {
168 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700169 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700170 swprintf(buffer, size, format, value) :
171 swprintf(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700172 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700173 return precision < 0 ?
174 swprintf(buffer, size, format, width, value) :
175 swprintf(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700176}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800177
Victor Zverovich65d47e52013-09-09 06:51:03 -0700178const char fmt::internal::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800179 "0001020304050607080910111213141516171819"
180 "2021222324252627282930313233343536373839"
181 "4041424344454647484950515253545556575859"
182 "6061626364656667686970717273747576777879"
183 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800184
Victor Zverovichf1d85162014-02-19 13:02:22 -0800185#define FMT_POWERS_OF_10(factor) \
186 factor * 10, \
187 factor * 100, \
188 factor * 1000, \
189 factor * 10000, \
190 factor * 100000, \
191 factor * 1000000, \
192 factor * 10000000, \
193 factor * 100000000, \
194 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800195
Victor Zverovichf1d85162014-02-19 13:02:22 -0800196const uint32_t fmt::internal::POWERS_OF_10_32[] = {0, FMT_POWERS_OF_10(1)};
Victor Zveroviche9b21912014-02-19 12:43:55 -0800197const uint64_t fmt::internal::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800198 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800199 FMT_POWERS_OF_10(1),
200 FMT_POWERS_OF_10(ULongLong(1000000000)),
201 // Multiply several constants instead of using a single long long constants
202 // to avoid warnings about C++98 not supporting long long.
Victor Zverovich6f6fe512014-02-15 11:16:44 -0800203 ULongLong(1000000000) * ULongLong(1000000000) * 10
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800204};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800205
Victor Zverovich687301c2013-01-26 16:07:28 -0800206void fmt::internal::ReportUnknownType(char code, const char *type) {
Victor Zverovich877abaf2013-01-08 09:56:05 -0800207 if (std::isprint(static_cast<unsigned char>(code))) {
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700208 throw fmt::FormatError(
209 fmt::format("unknown format code '{}' for {}", code, type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800210 }
211 throw fmt::FormatError(
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700212 fmt::format("unknown format code '\\x{:02x}' for {}",
213 static_cast<unsigned>(code), type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800214}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700215
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700216#ifdef _WIN32
217
218fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
219 int length = MultiByteToWideChar(
220 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, 0, 0);
221 static const char ERROR[] = "cannot convert string from UTF-8 to UTF-16";
222 if (length == 0)
Victor Zverovich9830c522014-05-01 07:20:38 -0700223 ThrowWinError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700224 buffer_.resize(length);
225 length = MultiByteToWideChar(
226 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, &buffer_[0], length);
227 if (length == 0)
Victor Zverovich9830c522014-05-01 07:20:38 -0700228 ThrowWinError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700229}
230
231fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
232 if (int error_code = Convert(s)) {
Victor Zverovich42764e52014-05-01 07:09:08 -0700233 ThrowWinError(GetLastError(),
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700234 "cannot convert string from UTF-16 to UTF-8");
235 }
236}
237
238int fmt::internal::UTF16ToUTF8::Convert(fmt::WStringRef s) {
239 int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, 0, 0, 0, 0);
240 if (length == 0)
241 return GetLastError();
242 buffer_.resize(length);
243 length = WideCharToMultiByte(
244 CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, 0, 0);
245 if (length == 0)
246 return GetLastError();
247 return 0;
248}
249
Victor Zverovich53201032014-06-30 14:26:29 -0700250void fmt::WindowsError::init(
251 int error_code, StringRef format_str, const ArgList &args) {
252 error_code_ = error_code;
253 Writer w;
254 internal::FormatWinErrorMessage(w, error_code, format(format_str, args));
255 std::runtime_error &base = *this;
256 base = std::runtime_error(w.str());
257}
258
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700259#endif
260
Victor Zverovich99e61122014-04-30 11:20:41 -0700261int fmt::internal::StrError(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700262 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT(true) {
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700263 assert(buffer != 0 && buffer_size != 0);
Victor Zverovich99e61122014-04-30 11:20:41 -0700264 int result = 0;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700265#ifdef _GNU_SOURCE
266 char *message = strerror_r(error_code, buffer, buffer_size);
Victor Zverovich99e61122014-04-30 11:20:41 -0700267 // If the buffer is full then the message is probably truncated.
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700268 if (message == buffer && strlen(buffer) == buffer_size - 1)
Victor Zverovich99e61122014-04-30 11:20:41 -0700269 result = ERANGE;
270 buffer = message;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700271#elif _WIN32
Constantine Tarasenkov6aace692014-06-11 02:38:57 +0400272# ifdef __MINGW32__
273 strerror(result);
274# else
Victor Zverovich99e61122014-04-30 11:20:41 -0700275 result = strerror_s(buffer, buffer_size, error_code);
Constantine Tarasenkov6aace692014-06-11 02:38:57 +0400276# endif
Victor Zverovich99e61122014-04-30 11:20:41 -0700277 // If the buffer is full then the message is probably truncated.
278 if (result == 0 && std::strlen(buffer) == buffer_size - 1)
279 result = ERANGE;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700280#else
Victor Zverovich99e61122014-04-30 11:20:41 -0700281 result = strerror_r(error_code, buffer, buffer_size);
282 if (result == -1)
283 result = errno; // glibc versions before 2.13 return result in errno.
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700284#endif
Victor Zverovich99e61122014-04-30 11:20:41 -0700285 return result;
Victor Zverovich859a4972014-04-30 06:55:21 -0700286}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700287
Victor Zverovich53b4c312014-04-30 15:00:41 -0700288void fmt::internal::FormatSystemErrorMessage(
289 fmt::Writer &out, int error_code, fmt::StringRef message) {
290 Array<char, INLINE_BUFFER_SIZE> buffer;
291 buffer.resize(INLINE_BUFFER_SIZE);
292 char *system_message = 0;
293 for (;;) {
294 system_message = &buffer[0];
295 int result = StrError(error_code, system_message, buffer.size());
296 if (result == 0)
297 break;
298 if (result != ERANGE) {
299 // Can't get error message, report error code instead.
300 out << message << ": error code = " << error_code;
301 return;
302 }
303 buffer.resize(buffer.size() * 2);
304 }
305 out << message << ": " << system_message;
306}
307
308#ifdef _WIN32
309void fmt::internal::FormatWinErrorMessage(
310 fmt::Writer &out, int error_code, fmt::StringRef message) {
311 class String {
312 private:
313 LPWSTR str_;
314
315 public:
316 String() : str_() {}
317 ~String() { LocalFree(str_); }
318 LPWSTR *ptr() { return &str_; }
319 LPCWSTR c_str() const { return str_; }
320 };
321 String system_message;
322 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
323 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
324 error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
325 reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
326 UTF16ToUTF8 utf8_message;
327 if (!utf8_message.Convert(system_message.c_str())) {
328 out << message << ": " << c_str(utf8_message);
329 return;
330 }
331 }
332 // Can't get error message, report error code instead.
333 out << message << ": error code = " << error_code;
334}
335#endif
336
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700337template <typename Char>
338void fmt::internal::FormatErrorReporter<Char>::operator()(
339 const Char *s, fmt::StringRef message) const {
340 for (int n = num_open_braces; *s; ++s) {
341 if (*s == '{') {
342 ++n;
343 } else if (*s == '}') {
344 if (--n == 0)
345 throw fmt::FormatError(message);
346 }
347 }
348 throw fmt::FormatError("unmatched '{' in format");
349}
350
351// Parses an unsigned integer advancing s to the end of the parsed input.
352// This function assumes that the first character of s is a digit.
353template <typename Char>
354int fmt::internal::ParseNonnegativeInt(
355 const Char *&s, const char *&error) FMT_NOEXCEPT(true) {
356 assert('0' <= *s && *s <= '9');
357 unsigned value = 0;
358 do {
359 unsigned new_value = value * 10 + (*s++ - '0');
360 // Check if value wrapped around.
361 value = new_value >= value ? new_value : UINT_MAX;
362 } while ('0' <= *s && *s <= '9');
363 if (value > INT_MAX) {
364 if (!error)
365 error = "number is too big in format";
366 return 0;
367 }
368 return value;
369}
370
Victor Zverovich7cae7632013-09-06 20:23:42 -0700371// Fills the padding around the content and returns the pointer to the
372// content area.
373template <typename Char>
Victor Zverovich93e41252013-09-08 13:07:04 -0700374typename fmt::BasicWriter<Char>::CharPtr
375 fmt::BasicWriter<Char>::FillPadding(CharPtr buffer,
376 unsigned total_size, std::size_t content_size, wchar_t fill) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700377 std::size_t padding = total_size - content_size;
378 std::size_t left_padding = padding / 2;
Victor Zverovich563a5752013-09-08 13:47:06 -0700379 Char fill_char = static_cast<Char>(fill);
380 std::fill_n(buffer, left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700381 buffer += left_padding;
382 CharPtr content = buffer;
Victor Zverovich563a5752013-09-08 13:47:06 -0700383 std::fill_n(buffer + content_size, padding - left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700384 return content;
385}
386
387template <typename Char>
Victor Zverovich7cae7632013-09-06 20:23:42 -0700388template <typename T>
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700389void fmt::BasicWriter<Char>::FormatDouble(T value, const FormatSpec &spec) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700390 // Check type.
391 char type = spec.type();
392 bool upper = false;
393 switch (type) {
394 case 0:
395 type = 'g';
396 break;
Victor Zverovich03776dd2014-06-10 07:03:49 -0700397 case 'e': case 'f': case 'g': case 'a':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700398 break;
399 case 'F':
400#ifdef _MSC_VER
401 // MSVC's printf doesn't support 'F'.
402 type = 'f';
403#endif
404 // Fall through.
Victor Zverovich03776dd2014-06-10 07:03:49 -0700405 case 'E': case 'G': case 'A':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700406 upper = true;
407 break;
408 default:
409 internal::ReportUnknownType(type, "double");
410 break;
411 }
412
413 char sign = 0;
414 // Use SignBit instead of value < 0 because the latter is always
415 // false for NaN.
jdale88a9862fd2014-03-11 18:56:24 +0000416 if (SignBit(static_cast<double>(value))) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700417 sign = '-';
418 value = -value;
419 } else if (spec.sign_flag()) {
420 sign = spec.plus_flag() ? '+' : ' ';
421 }
422
423 if (value != value) {
424 // Format NaN ourselves because sprintf's output is not consistent
425 // across platforms.
426 std::size_t size = 4;
427 const char *nan = upper ? " NAN" : " nan";
428 if (!sign) {
429 --size;
430 ++nan;
431 }
Victor Zverovich53201032014-06-30 14:26:29 -0700432 CharPtr out = write_str(nan, size, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700433 if (sign)
434 *out = sign;
435 return;
436 }
437
jdale88a9862fd2014-03-11 18:56:24 +0000438 if (IsInf(static_cast<double>(value))) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700439 // Format infinity ourselves because sprintf's output is not consistent
440 // across platforms.
441 std::size_t size = 4;
442 const char *inf = upper ? " INF" : " inf";
443 if (!sign) {
444 --size;
445 ++inf;
446 }
Victor Zverovich53201032014-06-30 14:26:29 -0700447 CharPtr out = write_str(inf, size, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700448 if (sign)
449 *out = sign;
450 return;
451 }
452
453 std::size_t offset = buffer_.size();
454 unsigned width = spec.width();
455 if (sign) {
456 buffer_.reserve(buffer_.size() + (std::max)(width, 1u));
457 if (width > 0)
458 --width;
459 ++offset;
460 }
461
462 // Build format string.
463 enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg
464 Char format[MAX_FORMAT_SIZE];
465 Char *format_ptr = format;
466 *format_ptr++ = '%';
467 unsigned width_for_sprintf = width;
468 if (spec.hash_flag())
469 *format_ptr++ = '#';
470 if (spec.align() == ALIGN_CENTER) {
471 width_for_sprintf = 0;
472 } else {
473 if (spec.align() == ALIGN_LEFT)
474 *format_ptr++ = '-';
475 if (width != 0)
476 *format_ptr++ = '*';
477 }
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700478 if (spec.precision() >= 0) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700479 *format_ptr++ = '.';
480 *format_ptr++ = '*';
481 }
482 if (internal::IsLongDouble<T>::VALUE)
483 *format_ptr++ = 'L';
484 *format_ptr++ = type;
485 *format_ptr = '\0';
486
487 // Format using snprintf.
Victor Zverovich88972f42013-09-08 13:30:14 -0700488 Char fill = static_cast<Char>(spec.fill());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700489 for (;;) {
490 std::size_t size = buffer_.capacity() - offset;
Victor Zverovich33baa8f2014-04-23 18:37:08 -0700491#if _MSC_VER
492 // MSVC's vsnprintf_s doesn't work with zero size, so reserve
493 // space for at least one extra character to make the size non-zero.
494 // Note that the buffer's capacity will increase by more than 1.
495 if (size == 0) {
496 buffer_.reserve(offset + 1);
497 size = buffer_.capacity() - offset;
498 }
499#endif
Victor Zverovich7cae7632013-09-06 20:23:42 -0700500 Char *start = &buffer_[offset];
Victor Zverovichb605b392013-09-09 22:21:40 -0700501 int n = internal::CharTraits<Char>::FormatFloat(
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700502 start, size, format, width_for_sprintf, spec.precision(), value);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700503 if (n >= 0 && offset + n < buffer_.capacity()) {
504 if (sign) {
505 if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) ||
506 *start != ' ') {
507 *(start - 1) = sign;
508 sign = 0;
509 } else {
Victor Zverovich88972f42013-09-08 13:30:14 -0700510 *(start - 1) = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700511 }
512 ++n;
513 }
514 if (spec.align() == ALIGN_CENTER &&
515 spec.width() > static_cast<unsigned>(n)) {
516 unsigned width = spec.width();
517 CharPtr p = GrowBuffer(width);
518 std::copy(p, p + n, p + (width - n) / 2);
Victor Zverovich88972f42013-09-08 13:30:14 -0700519 FillPadding(p, spec.width(), n, fill);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700520 return;
521 }
522 if (spec.fill() != ' ' || sign) {
523 while (*start == ' ')
Victor Zverovich88972f42013-09-08 13:30:14 -0700524 *start++ = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700525 if (sign)
526 *(start - 1) = sign;
527 }
528 GrowBuffer(n);
529 return;
530 }
Victor Zverovichcfeba452014-04-23 18:37:49 -0700531 // If n is negative we ask to increase the capacity by at least 1,
532 // but as std::vector, the buffer grows exponentially.
533 buffer_.reserve(n >= 0 ? offset + n + 1 : buffer_.capacity() + 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700534 }
535}
536
Victor Zverovich7cae7632013-09-06 20:23:42 -0700537template <typename Char>
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700538template <typename StringChar>
Victor Zverovich53201032014-06-30 14:26:29 -0700539void fmt::BasicWriter<Char>::write_str(
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700540 const Arg::StringValue<StringChar> &str, const FormatSpec &spec) {
541 if (spec.type_ && spec.type_ != 's')
542 internal::ReportUnknownType(spec.type_, "string");
543 const StringChar *s = str.value;
544 std::size_t size = str.size;
545 if (size == 0) {
546 if (!s)
547 throw FormatError("string pointer is null");
548 if (*s)
549 size = std::char_traits<StringChar>::length(s);
550 }
Victor Zverovich53201032014-06-30 14:26:29 -0700551 write_str(s, size, spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700552}
553
554template <typename Char>
555inline const typename fmt::BasicWriter<Char>::Arg
Victor Zveroviche78904b2014-04-23 08:27:50 -0700556 &fmt::BasicWriter<Char>::FormatParser::ParseArgIndex(const Char *&s) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700557 unsigned arg_index = 0;
558 if (*s < '0' || *s > '9') {
559 if (*s != '}' && *s != ':')
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700560 report_error_(s, "invalid argument index in format string");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700561 if (next_arg_index_ < 0) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700562 report_error_(s,
Victor Zverovich7cae7632013-09-06 20:23:42 -0700563 "cannot switch from manual to automatic argument indexing");
564 }
565 arg_index = next_arg_index_++;
566 } else {
567 if (next_arg_index_ > 0) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700568 report_error_(s,
Victor Zverovich7cae7632013-09-06 20:23:42 -0700569 "cannot switch from automatic to manual argument indexing");
570 }
571 next_arg_index_ = -1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700572 const char *error = 0;
573 arg_index = internal::ParseNonnegativeInt(s, error);
574 if (error)
575 report_error_(s, error); // TODO
Victor Zverovich7cae7632013-09-06 20:23:42 -0700576 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700577 if (arg_index >= args_.size())
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700578 report_error_(s, "argument index is out of range in format");
Victor Zverovich656a8372014-04-22 08:58:54 -0700579 return args_[arg_index];
Victor Zverovich7cae7632013-09-06 20:23:42 -0700580}
581
582template <typename Char>
Victor Zveroviche78904b2014-04-23 08:27:50 -0700583void fmt::BasicWriter<Char>::FormatParser::CheckSign(
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700584 const Char *&s, const Arg &arg) {
Victor Zverovichcc6af502013-12-10 08:01:08 -0800585 char sign = static_cast<char>(*s);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700586 if (arg.type > Arg::LAST_NUMERIC_TYPE) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700587 report_error_(s,
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700588 fmt::format("format specifier '{}' requires numeric argument", sign).c_str());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700589 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700590 if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700591 report_error_(s,
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700592 fmt::format("format specifier '{}' requires signed argument", sign).c_str());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700593 }
594 ++s;
595}
596
597template <typename Char>
Victor Zverovichd29e5052014-06-30 07:12:09 -0700598void fmt::internal::PrintfParser<Char>::ParseFlags(
Victor Zverovichcb743c02014-06-19 07:40:35 -0700599 FormatSpec &spec, const Char *&s) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700600 for (;;) {
Victor Zverovich1b801482014-06-07 08:57:55 -0700601 switch (*s++) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700602 case '-':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700603 spec.align_ = ALIGN_LEFT;
604 break;
605 case '+':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700606 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
607 break;
608 case '0':
609 spec.fill_ = '0';
Victor Zverovich1b801482014-06-07 08:57:55 -0700610 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700611 case ' ':
Victor Zverovich1b801482014-06-07 08:57:55 -0700612 spec.flags_ |= SIGN_FLAG;
613 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700614 case '#':
Victor Zverovichcb743c02014-06-19 07:40:35 -0700615 spec.flags_ |= HASH_FLAG;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700616 break;
617 default:
Victor Zverovich1b801482014-06-07 08:57:55 -0700618 --s;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700619 return;
620 }
621 }
622}
623
Victor Zverovichcb743c02014-06-19 07:40:35 -0700624template <typename Char>
Victor Zverovichd29e5052014-06-30 07:12:09 -0700625unsigned fmt::internal::PrintfParser<Char>::ParseHeader(
Victor Zverovichcb743c02014-06-19 07:40:35 -0700626 const Char *&s, FormatSpec &spec, const char *&error) {
627 unsigned arg_index = UINT_MAX;
628 Char c = *s;
629 if (c >= '0' && c <= '9') {
630 // Parse an argument index (if followed by '$') or a width possibly
Victor Zverovich879838a2014-06-20 07:34:02 -0700631 // preceded with '0' flag(s).
Victor Zverovichcb743c02014-06-19 07:40:35 -0700632 unsigned value = internal::ParseNonnegativeInt(s, error);
633 if (*s == '$') { // value is an argument index
634 ++s;
635 arg_index = value;
636 } else {
637 if (c == '0')
638 spec.fill_ = '0';
639 if (value != 0) {
640 // Nonzero value means that we parsed width and don't need to
641 // parse it or flags again, so return now.
642 spec.width_ = value;
643 return arg_index;
644 }
645 }
646 }
Victor Zverovichcb743c02014-06-19 07:40:35 -0700647 ParseFlags(spec, s);
Victor Zverovich4099a122014-06-23 08:10:50 -0700648 // Parse width.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700649 if (*s >= '0' && *s <= '9') {
650 spec.width_ = internal::ParseNonnegativeInt(s, error);
651 } else if (*s == '*') {
652 ++s;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700653 const Arg &arg = HandleArgIndex(UINT_MAX, error);
654 // TODO: use ArgVisitor
Victor Zverovich4099a122014-06-23 08:10:50 -0700655 ULongLong width = 0;
656 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700657 case Arg::INT:
Victor Zverovich4099a122014-06-23 08:10:50 -0700658 width = arg.int_value;
659 if (arg.int_value < 0) {
660 spec.align_ = ALIGN_LEFT;
Victor Zverovich3e53ac22014-06-23 08:48:42 -0700661 width = 0 - width;
Victor Zverovich4099a122014-06-23 08:10:50 -0700662 }
663 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700664 case Arg::UINT:
Victor Zverovich4099a122014-06-23 08:10:50 -0700665 width = arg.uint_value;
666 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700667 case Arg::LONG_LONG:
Victor Zverovich4099a122014-06-23 08:10:50 -0700668 width = arg.long_long_value;
669 if (arg.long_long_value < 0) {
670 spec.align_ = ALIGN_LEFT;
Victor Zverovich3e53ac22014-06-23 08:48:42 -0700671 width = 0 - width;
Victor Zverovich4099a122014-06-23 08:10:50 -0700672 }
673 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700674 case Arg::ULONG_LONG:
Victor Zverovich4099a122014-06-23 08:10:50 -0700675 width = arg.ulong_long_value;
676 break;
677 default:
678 if (!error)
679 error = "width is not integer";
680 }
681 if (width <= INT_MAX)
682 spec.width_ = static_cast<unsigned>(width);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700683 else if (!error)
Victor Zverovich4099a122014-06-23 08:10:50 -0700684 error = "number is too big in format";
Victor Zverovichcb743c02014-06-19 07:40:35 -0700685 }
686 return arg_index;
687}
688
Victor Zverovich879838a2014-06-20 07:34:02 -0700689// TODO: move to a base class that doesn't depend on template argument
Victor Zverovichbf790d22014-06-07 07:31:25 -0700690template <typename Char>
Victor Zverovichd29e5052014-06-30 07:12:09 -0700691const fmt::internal::ArgInfo
692 &fmt::internal::PrintfParser<Char>::HandleArgIndex(
Victor Zverovich12759232014-06-17 06:53:48 -0700693 unsigned arg_index, const char *&error) {
694 if (arg_index != UINT_MAX) {
695 if (next_arg_index_ <= 0) {
696 next_arg_index_ = -1;
Victor Zverovichcb743c02014-06-19 07:40:35 -0700697 --arg_index;
698 } else if (!error) {
Victor Zverovich12759232014-06-17 06:53:48 -0700699 error = "cannot switch from automatic to manual argument indexing";
Victor Zverovichcb743c02014-06-19 07:40:35 -0700700 }
701 } else if (next_arg_index_ >= 0) {
702 arg_index = next_arg_index_++;
703 } else if (!error) {
704 error = "cannot switch from manual to automatic argument indexing";
Victor Zverovich1f19b982014-06-16 07:49:30 -0700705 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700706 if (arg_index < args_.size())
Victor Zverovichcb743c02014-06-19 07:40:35 -0700707 return args_[arg_index];
708 if (!error)
709 error = "argument index is out of range in format";
710 return DUMMY_ARG;
Victor Zverovich1f19b982014-06-16 07:49:30 -0700711}
712
713template <typename Char>
Victor Zverovichd29e5052014-06-30 07:12:09 -0700714void fmt::internal::PrintfParser<Char>::Format(
Victor Zveroviche78904b2014-04-23 08:27:50 -0700715 BasicWriter<Char> &writer, BasicStringRef<Char> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700716 const ArgList &args) {
Victor Zveroviche78904b2014-04-23 08:27:50 -0700717 const Char *start = format.c_str();
Victor Zveroviche78904b2014-04-23 08:27:50 -0700718 args_ = args;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700719 next_arg_index_ = 0;
720 const Char *s = start;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700721 while (*s) {
Victor Zverovich0fc73162013-09-07 12:52:52 -0700722 Char c = *s++;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700723 if (c != '%') continue;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700724 if (*s == c) {
725 writer.buffer_.append(start, s);
726 start = ++s;
727 continue;
728 }
Victor Zverovich7cae7632013-09-06 20:23:42 -0700729 writer.buffer_.append(start, s - 1);
730
Victor Zverovichcb743c02014-06-19 07:40:35 -0700731 FormatSpec spec;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700732 spec.align_ = ALIGN_RIGHT;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700733
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700734 // Reporting errors is delayed till the format specification is
735 // completely parsed. This is done to avoid potentially confusing
736 // error messages for incomplete format strings. For example, in
737 // sprintf("%2$", 42);
738 // the format specification is incomplete. In naive approach we
739 // would parse 2 as an argument index and report an error that the
740 // index is out of range which would be rather confusing if the
741 // use meant "%2d$" rather than "%2$d". If we delay an error, the
742 // user will get an error that the format string is invalid which
743 // is OK for both cases.
744 const char *error = 0;
745
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700746 // Parse argument index, flags and width.
747 unsigned arg_index = ParseHeader(s, spec, error);
748
749 // Parse precision.
750 if (*s == '.') {
751 ++s;
752 if ('0' <= *s && *s <= '9') {
753 spec.precision_ = internal::ParseNonnegativeInt(s, error);
754 } else if (*s == '*') {
755 ++s;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700756 const Arg &arg = HandleArgIndex(UINT_MAX, error);
757 if (arg.type <= Arg::LAST_INTEGER_TYPE)
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700758 spec.precision_ = GetIntValue(arg);
759 else if (!error)
760 error = "precision is not integer";
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700761 }
762 }
763
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700764 const Arg &arg = HandleArgIndex(arg_index, error);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700765 if (spec.hash_flag() && GetIntValue(arg) == 0)
766 spec.flags_ &= ~HASH_FLAG;
767 if (spec.fill_ == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700768 if (arg.type <= Arg::LAST_NUMERIC_TYPE)
Victor Zverovichcb743c02014-06-19 07:40:35 -0700769 spec.align_ = ALIGN_NUMERIC;
770 else
771 spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700772 }
773
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700774 // Parse length.
775 switch (*s) {
776 case 'h':
777 // TODO: convert to short
778 case 'l':
779 case 'j':
780 case 'z':
781 case 't':
782 case 'L':
783 // TODO: handle length
784 ++s;
785 break;
786 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700787
788 // Parse type.
789 if (!*s)
790 throw FormatError("invalid format string");
791 if (error)
792 throw FormatError(error);
793 spec.type_ = static_cast<char>(*s++);
794
795 start = s;
796
797 // Format argument.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700798 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700799 case Arg::INT:
Victor Zverovichcb743c02014-06-19 07:40:35 -0700800 writer.FormatInt(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700801 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700802 case Arg::UINT:
Victor Zverovichcb743c02014-06-19 07:40:35 -0700803 writer.FormatInt(arg.uint_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700804 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700805 case Arg::LONG_LONG:
Victor Zverovichcb743c02014-06-19 07:40:35 -0700806 writer.FormatInt(arg.long_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700807 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700808 case Arg::ULONG_LONG:
Victor Zverovichcb743c02014-06-19 07:40:35 -0700809 writer.FormatInt(arg.ulong_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700810 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700811 case Arg::DOUBLE:
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700812 writer.FormatDouble(arg.double_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700813 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700814 case Arg::LONG_DOUBLE:
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700815 writer.FormatDouble(arg.long_double_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700816 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700817 case Arg::CHAR: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700818 if (spec.type_ && spec.type_ != 'c')
819 internal::ReportUnknownType(spec.type_, "char");
820 typedef typename BasicWriter<Char>::CharPtr CharPtr;
821 CharPtr out = CharPtr();
822 if (spec.width_ > 1) {
823 Char fill = static_cast<Char>(spec.fill());
824 out = writer.GrowBuffer(spec.width_);
825 if (spec.align_ == ALIGN_RIGHT) {
826 std::fill_n(out, spec.width_ - 1, fill);
827 out += spec.width_ - 1;
828 } else if (spec.align_ == ALIGN_CENTER) {
829 out = writer.FillPadding(out, spec.width_, 1, fill);
830 } else {
831 std::fill_n(out + 1, spec.width_ - 1, fill);
832 }
833 } else {
834 out = writer.GrowBuffer(1);
835 }
Victor Zverovichcb743c02014-06-19 07:40:35 -0700836 *out = static_cast<Char>(arg.int_value);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700837 break;
838 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700839 case Arg::STRING:
Victor Zverovich53201032014-06-30 14:26:29 -0700840 writer.write_str(arg.string, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700841 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700842 case Arg::WSTRING:
Victor Zverovich53201032014-06-30 14:26:29 -0700843 writer.write_str(arg.wstring, spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700844 break;
845 case Arg::POINTER:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700846 if (spec.type_ && spec.type_ != 'p')
847 internal::ReportUnknownType(spec.type_, "pointer");
848 spec.flags_= HASH_FLAG;
849 spec.type_ = 'x';
Victor Zverovichcb743c02014-06-19 07:40:35 -0700850 writer.FormatInt(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700851 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700852 case Arg::CUSTOM:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700853 if (spec.type_)
854 internal::ReportUnknownType(spec.type_, "object");
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700855 arg.custom.format(&writer, arg.custom.value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700856 break;
857 default:
858 assert(false);
859 break;
860 }
861 }
862 writer.buffer_.append(start, s);
863}
864
865template <typename Char>
866void fmt::BasicWriter<Char>::FormatParser::Format(
867 BasicWriter<Char> &writer, BasicStringRef<Char> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700868 const ArgList &args) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700869 const char *error = 0;
870 const Char *start = format.c_str();
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700871 args_ = args;
872 next_arg_index_ = 0;
873 const Char *s = start;
874 while (*s) {
875 Char c = *s++;
876 if (c != '{' && c != '}') continue;
877 if (*s == c) {
878 writer.buffer_.append(start, s);
879 start = ++s;
880 continue;
881 }
882 if (c == '}')
883 throw FormatError("unmatched '}' in format");
884 report_error_.num_open_braces = 1;
885 writer.buffer_.append(start, s - 1);
886
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700887 const Arg &arg = ParseArgIndex(s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700888
889 FormatSpec spec;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700890 if (*s == ':') {
891 ++s;
892
893 // Parse fill and alignment.
894 if (Char c = *s) {
895 const Char *p = s + 1;
896 spec.align_ = ALIGN_DEFAULT;
897 do {
898 switch (*p) {
899 case '<':
900 spec.align_ = ALIGN_LEFT;
901 break;
902 case '>':
903 spec.align_ = ALIGN_RIGHT;
904 break;
905 case '=':
906 spec.align_ = ALIGN_NUMERIC;
907 break;
908 case '^':
909 spec.align_ = ALIGN_CENTER;
910 break;
911 }
912 if (spec.align_ != ALIGN_DEFAULT) {
913 if (p != s) {
914 if (c == '}') break;
915 if (c == '{')
916 report_error_(s, "invalid fill character '{'");
917 s += 2;
918 spec.fill_ = c;
919 } else ++s;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700920 if (spec.align_ == ALIGN_NUMERIC && arg.type > Arg::LAST_NUMERIC_TYPE)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700921 report_error_(s, "format specifier '=' requires numeric argument");
922 break;
923 }
924 } while (--p >= s);
925 }
926
927 // Parse sign.
928 switch (*s) {
929 case '+':
930 CheckSign(s, arg);
931 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
932 break;
933 case '-':
934 CheckSign(s, arg);
935 break;
936 case ' ':
937 CheckSign(s, arg);
938 spec.flags_ |= SIGN_FLAG;
939 break;
940 }
941
942 if (*s == '#') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700943 if (arg.type > Arg::LAST_NUMERIC_TYPE)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700944 report_error_(s, "format specifier '#' requires numeric argument");
945 spec.flags_ |= HASH_FLAG;
946 ++s;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700947 }
948
949 // Parse width and zero flag.
950 if ('0' <= *s && *s <= '9') {
951 if (*s == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700952 if (arg.type > Arg::LAST_NUMERIC_TYPE)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700953 report_error_(s, "format specifier '0' requires numeric argument");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700954 spec.align_ = ALIGN_NUMERIC;
955 spec.fill_ = '0';
956 }
957 // Zero may be parsed again as a part of the width, but it is simpler
958 // and more efficient than checking if the next char is a digit.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700959 spec.width_ = internal::ParseNonnegativeInt(s, error);
960 if (error)
961 report_error_(s, error);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700962 }
963
964 // Parse precision.
965 if (*s == '.') {
966 ++s;
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700967 spec.precision_ = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700968 if ('0' <= *s && *s <= '9') {
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700969 spec.precision_ = internal::ParseNonnegativeInt(s, error);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700970 if (error)
971 report_error_(s, error);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700972 } else if (*s == '{') {
973 ++s;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700974 ++report_error_.num_open_braces;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700975 const Arg &precision_arg = ParseArgIndex(s);
Victor Zverovichf406a422013-12-06 07:12:38 -0800976 ULongLong value = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700977 switch (precision_arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700978 case Arg::INT:
Victor Zverovich7cae7632013-09-06 20:23:42 -0700979 if (precision_arg.int_value < 0)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700980 report_error_(s, "negative precision in format");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700981 value = precision_arg.int_value;
982 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700983 case Arg::UINT:
Victor Zverovich7cae7632013-09-06 20:23:42 -0700984 value = precision_arg.uint_value;
985 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700986 case Arg::LONG_LONG:
Victor Zverovich56f12b72013-11-22 07:45:43 -0800987 if (precision_arg.long_long_value < 0)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700988 report_error_(s, "negative precision in format");
Victor Zverovich56f12b72013-11-22 07:45:43 -0800989 value = precision_arg.long_long_value;
990 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700991 case Arg::ULONG_LONG:
Gregory Czajkowskia65542b2013-11-18 22:58:39 -0800992 value = precision_arg.ulong_long_value;
Victor Zverovicha4e72b42013-11-21 09:11:58 -0800993 break;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700994 default:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700995 report_error_(s, "precision is not integer");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700996 }
997 if (value > INT_MAX)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700998 report_error_(s, "number is too big in format");
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700999 spec.precision_ = static_cast<int>(value);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001000 if (*s++ != '}')
1001 throw FormatError("unmatched '{' in format");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001002 --report_error_.num_open_braces;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001003 } else {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001004 report_error_(s, "missing precision in format");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001005 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001006 if (arg.type != Arg::DOUBLE && arg.type != Arg::LONG_DOUBLE) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001007 report_error_(s,
Victor Zverovich7cae7632013-09-06 20:23:42 -07001008 "precision specifier requires floating-point argument");
1009 }
1010 }
1011
1012 // Parse type.
1013 if (*s != '}' && *s)
Victor Zverovich0fc73162013-09-07 12:52:52 -07001014 spec.type_ = static_cast<char>(*s++);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001015 }
1016
1017 if (*s++ != '}')
1018 throw FormatError("unmatched '{' in format");
1019 start = s;
1020
1021 // Format argument.
1022 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001023 case Arg::INT:
Victor Zverovich03f68852014-04-20 08:46:09 -07001024 writer.FormatInt(arg.int_value, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001025 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001026 case Arg::UINT:
Victor Zverovich03f68852014-04-20 08:46:09 -07001027 writer.FormatInt(arg.uint_value, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001028 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001029 case Arg::LONG_LONG:
Victor Zverovich03f68852014-04-20 08:46:09 -07001030 writer.FormatInt(arg.long_long_value, spec);
Victor Zverovich56f12b72013-11-22 07:45:43 -08001031 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001032 case Arg::ULONG_LONG:
Victor Zverovich03f68852014-04-20 08:46:09 -07001033 writer.FormatInt(arg.ulong_long_value, spec);
Victor Zverovicha4e72b42013-11-21 09:11:58 -08001034 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001035 case Arg::DOUBLE:
Victor Zverovichb1bbc902014-06-21 08:32:00 -07001036 writer.FormatDouble(arg.double_value, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001037 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001038 case Arg::LONG_DOUBLE:
Victor Zverovichb1bbc902014-06-21 08:32:00 -07001039 writer.FormatDouble(arg.long_double_value, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001040 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001041 case Arg::CHAR: {
Victor Zverovich7cae7632013-09-06 20:23:42 -07001042 if (spec.type_ && spec.type_ != 'c')
1043 internal::ReportUnknownType(spec.type_, "char");
1044 typedef typename BasicWriter<Char>::CharPtr CharPtr;
1045 CharPtr out = CharPtr();
1046 if (spec.width_ > 1) {
Victor Zverovichc62c4752013-09-08 14:25:22 -07001047 Char fill = static_cast<Char>(spec.fill());
Victor Zverovich7cae7632013-09-06 20:23:42 -07001048 out = writer.GrowBuffer(spec.width_);
1049 if (spec.align_ == ALIGN_RIGHT) {
Victor Zverovichc62c4752013-09-08 14:25:22 -07001050 std::fill_n(out, spec.width_ - 1, fill);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001051 out += spec.width_ - 1;
1052 } else if (spec.align_ == ALIGN_CENTER) {
Victor Zverovichc62c4752013-09-08 14:25:22 -07001053 out = writer.FillPadding(out, spec.width_, 1, fill);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001054 } else {
Victor Zverovichc62c4752013-09-08 14:25:22 -07001055 std::fill_n(out + 1, spec.width_ - 1, fill);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001056 }
1057 } else {
1058 out = writer.GrowBuffer(1);
1059 }
jdale884cabe162014-03-11 19:03:26 +00001060 *out = static_cast<Char>(arg.int_value);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001061 break;
1062 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001063 case Arg::STRING:
Victor Zverovich53201032014-06-30 14:26:29 -07001064 writer.write_str(arg.string, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001065 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001066 case Arg::WSTRING:
Victor Zverovich53201032014-06-30 14:26:29 -07001067 writer.write_str(arg.wstring, spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001068 break;
1069 case Arg::POINTER:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001070 if (spec.type_ && spec.type_ != 'p')
1071 internal::ReportUnknownType(spec.type_, "pointer");
1072 spec.flags_= HASH_FLAG;
1073 spec.type_ = 'x';
Victor Zverovich03f68852014-04-20 08:46:09 -07001074 writer.FormatInt(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001075 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001076 case Arg::CUSTOM:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001077 if (spec.type_)
1078 internal::ReportUnknownType(spec.type_, "object");
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001079 arg.custom.format(&writer, arg.custom.value, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001080 break;
1081 default:
1082 assert(false);
1083 break;
1084 }
1085 }
1086 writer.buffer_.append(start, s);
1087}
1088
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001089void fmt::ReportSystemError(
1090 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
1091 // FIXME: FormatSystemErrorMessage may throw
1092 ReportError(internal::FormatSystemErrorMessage, error_code, message);
1093}
1094
Victor Zverovich400812a2014-04-30 12:38:17 -07001095#ifdef _WIN32
1096void fmt::WinErrorSink::operator()(const Writer &w) const {
Victor Zverovichf7939862014-04-30 10:18:11 -07001097 Writer message;
Victor Zverovich53b4c312014-04-30 15:00:41 -07001098 internal::FormatWinErrorMessage(message, error_code_, w.c_str());
Victor Zverovichf7939862014-04-30 10:18:11 -07001099 throw SystemError(message.c_str(), error_code_);
1100}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001101
1102void fmt::ReportWinError(
1103 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
1104 // FIXME: FormatWinErrorMessage may throw
1105 ReportError(internal::FormatWinErrorMessage, error_code, message);
1106}
Victor Zverovich400812a2014-04-30 12:38:17 -07001107#endif
Victor Zverovichf7939862014-04-30 10:18:11 -07001108
Victor Zverovichd9db8982014-04-28 08:59:29 -07001109void fmt::ANSITerminalSink::operator()(
1110 const fmt::BasicWriter<char> &w) const {
Victor Zverovich43fe1002014-02-19 14:20:26 -08001111 char escape[] = "\x1b[30m";
jdale88a9862fd2014-03-11 18:56:24 +00001112 escape[3] = '0' + static_cast<char>(color_);
Victor Zverovichd9db8982014-04-28 08:59:29 -07001113 std::fputs(escape, file_);
1114 std::fwrite(w.data(), 1, w.size(), file_);
1115 std::fputs(RESET_COLOR, file_);
Victor Zverovich43fe1002014-02-19 14:20:26 -08001116}
Victor Zverovich6968ef32014-02-19 13:51:23 -08001117
Victor Zverovich2e039632014-06-28 19:44:39 -07001118void fmt::print(StringRef format, const ArgList &args) {
1119 Writer w;
Victor Zverovicha1264922014-06-29 11:51:10 -07001120 w.write(format, args);
Victor Zverovich2e039632014-06-28 19:44:39 -07001121 std::fwrite(w.data(), 1, w.size(), stdout);
1122}
1123
Victor Zverovichd5b81962014-06-28 21:56:40 -07001124void fmt::print(std::FILE *f, StringRef format, const ArgList &args) {
1125 Writer w;
Victor Zverovicha1264922014-06-29 11:51:10 -07001126 w.write(format, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001127 std::fwrite(w.data(), 1, w.size(), f);
1128}
1129
1130void fmt::printf(StringRef format, const ArgList &args) {
1131 Writer w;
Victor Zverovich21111cc2014-06-29 19:52:26 -07001132 printf(w, format, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001133 std::fwrite(w.data(), 1, w.size(), stdout);
1134}
1135
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001136// Explicit instantiations for char.
1137
Victor Zverovich93e41252013-09-08 13:07:04 -07001138template fmt::BasicWriter<char>::CharPtr
1139 fmt::BasicWriter<char>::FillPadding(CharPtr buffer,
1140 unsigned total_size, std::size_t content_size, wchar_t fill);
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001141
Victor Zveroviche78904b2014-04-23 08:27:50 -07001142template void fmt::BasicWriter<char>::FormatParser::Format(
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001143 BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001144
Victor Zverovichd29e5052014-06-30 07:12:09 -07001145template void fmt::internal::PrintfParser<char>::Format(
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001146 BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001147
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001148// Explicit instantiations for wchar_t.
1149
Victor Zverovich7cae7632013-09-06 20:23:42 -07001150template fmt::BasicWriter<wchar_t>::CharPtr
Victor Zverovich93e41252013-09-08 13:07:04 -07001151 fmt::BasicWriter<wchar_t>::FillPadding(CharPtr buffer,
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001152 unsigned total_size, std::size_t content_size, wchar_t fill);
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001153
Victor Zveroviche78904b2014-04-23 08:27:50 -07001154template void fmt::BasicWriter<wchar_t>::FormatParser::Format(
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001155 BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001156 const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001157
Victor Zverovichd29e5052014-06-30 07:12:09 -07001158template void fmt::internal::PrintfParser<wchar_t>::Format(
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001159 BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001160 const ArgList &args);
jdale88a9862fd2014-03-11 18:56:24 +00001161
1162#if _MSC_VER
1163# pragma warning(pop)
1164#endif