blob: 9c1f80aff455b40e7607326af23ab5ee68ca630a [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 Zverovich1a2d7be2014-05-03 09:48:54 -0700119} // namespace
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700120
Victor Zverovich302b8f42014-06-24 10:46:01 -0700121int fmt::internal::SignBitNoInline(double value) { return SignBit(value); }
122
Victor Zverovichb605b392013-09-09 22:21:40 -0700123template <typename T>
124int fmt::internal::CharTraits<char>::FormatFloat(
125 char *buffer, std::size_t size, const char *format,
126 unsigned width, int precision, T value) {
127 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700128 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700129 FMT_SNPRINTF(buffer, size, format, value) :
130 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700131 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700132 return precision < 0 ?
133 FMT_SNPRINTF(buffer, size, format, width, value) :
134 FMT_SNPRINTF(buffer, size, format, width, precision, value);
135}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700136
Victor Zverovichb605b392013-09-09 22:21:40 -0700137template <typename T>
138int fmt::internal::CharTraits<wchar_t>::FormatFloat(
139 wchar_t *buffer, std::size_t size, const wchar_t *format,
140 unsigned width, int precision, T value) {
141 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700142 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700143 swprintf(buffer, size, format, value) :
144 swprintf(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700145 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700146 return precision < 0 ?
147 swprintf(buffer, size, format, width, value) :
148 swprintf(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700149}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800150
Victor Zverovich65d47e52013-09-09 06:51:03 -0700151const char fmt::internal::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800152 "0001020304050607080910111213141516171819"
153 "2021222324252627282930313233343536373839"
154 "4041424344454647484950515253545556575859"
155 "6061626364656667686970717273747576777879"
156 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800157
Victor Zverovichf1d85162014-02-19 13:02:22 -0800158#define FMT_POWERS_OF_10(factor) \
159 factor * 10, \
160 factor * 100, \
161 factor * 1000, \
162 factor * 10000, \
163 factor * 100000, \
164 factor * 1000000, \
165 factor * 10000000, \
166 factor * 100000000, \
167 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800168
Victor Zverovichf1d85162014-02-19 13:02:22 -0800169const uint32_t fmt::internal::POWERS_OF_10_32[] = {0, FMT_POWERS_OF_10(1)};
Victor Zveroviche9b21912014-02-19 12:43:55 -0800170const uint64_t fmt::internal::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800171 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800172 FMT_POWERS_OF_10(1),
173 FMT_POWERS_OF_10(ULongLong(1000000000)),
174 // Multiply several constants instead of using a single long long constants
175 // to avoid warnings about C++98 not supporting long long.
Victor Zverovich6f6fe512014-02-15 11:16:44 -0800176 ULongLong(1000000000) * ULongLong(1000000000) * 10
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800177};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800178
Victor Zverovich687301c2013-01-26 16:07:28 -0800179void fmt::internal::ReportUnknownType(char code, const char *type) {
Victor Zverovich877abaf2013-01-08 09:56:05 -0800180 if (std::isprint(static_cast<unsigned char>(code))) {
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700181 throw fmt::FormatError(
182 fmt::format("unknown format code '{}' for {}", code, type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800183 }
184 throw fmt::FormatError(
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700185 fmt::format("unknown format code '\\x{:02x}' for {}",
186 static_cast<unsigned>(code), type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800187}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700188
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700189#ifdef _WIN32
190
191fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
192 int length = MultiByteToWideChar(
193 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, 0, 0);
194 static const char ERROR[] = "cannot convert string from UTF-8 to UTF-16";
195 if (length == 0)
Victor Zverovich9830c522014-05-01 07:20:38 -0700196 ThrowWinError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700197 buffer_.resize(length);
198 length = MultiByteToWideChar(
199 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, &buffer_[0], length);
200 if (length == 0)
Victor Zverovich9830c522014-05-01 07:20:38 -0700201 ThrowWinError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700202}
203
204fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
205 if (int error_code = Convert(s)) {
Victor Zverovich42764e52014-05-01 07:09:08 -0700206 ThrowWinError(GetLastError(),
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700207 "cannot convert string from UTF-16 to UTF-8");
208 }
209}
210
211int fmt::internal::UTF16ToUTF8::Convert(fmt::WStringRef s) {
212 int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, 0, 0, 0, 0);
213 if (length == 0)
214 return GetLastError();
215 buffer_.resize(length);
216 length = WideCharToMultiByte(
217 CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, 0, 0);
218 if (length == 0)
219 return GetLastError();
220 return 0;
221}
222
223#endif
224
Victor Zverovich99e61122014-04-30 11:20:41 -0700225int fmt::internal::StrError(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700226 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT(true) {
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700227 assert(buffer != 0 && buffer_size != 0);
Victor Zverovich99e61122014-04-30 11:20:41 -0700228 int result = 0;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700229#ifdef _GNU_SOURCE
230 char *message = strerror_r(error_code, buffer, buffer_size);
Victor Zverovich99e61122014-04-30 11:20:41 -0700231 // If the buffer is full then the message is probably truncated.
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700232 if (message == buffer && strlen(buffer) == buffer_size - 1)
Victor Zverovich99e61122014-04-30 11:20:41 -0700233 result = ERANGE;
234 buffer = message;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700235#elif _WIN32
Constantine Tarasenkov6aace692014-06-11 02:38:57 +0400236# ifdef __MINGW32__
237 strerror(result);
238# else
Victor Zverovich99e61122014-04-30 11:20:41 -0700239 result = strerror_s(buffer, buffer_size, error_code);
Constantine Tarasenkov6aace692014-06-11 02:38:57 +0400240# endif
Victor Zverovich99e61122014-04-30 11:20:41 -0700241 // If the buffer is full then the message is probably truncated.
242 if (result == 0 && std::strlen(buffer) == buffer_size - 1)
243 result = ERANGE;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700244#else
Victor Zverovich99e61122014-04-30 11:20:41 -0700245 result = strerror_r(error_code, buffer, buffer_size);
246 if (result == -1)
247 result = errno; // glibc versions before 2.13 return result in errno.
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700248#endif
Victor Zverovich99e61122014-04-30 11:20:41 -0700249 return result;
Victor Zverovich859a4972014-04-30 06:55:21 -0700250}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700251
Victor Zverovich53b4c312014-04-30 15:00:41 -0700252void fmt::internal::FormatSystemErrorMessage(
253 fmt::Writer &out, int error_code, fmt::StringRef message) {
254 Array<char, INLINE_BUFFER_SIZE> buffer;
255 buffer.resize(INLINE_BUFFER_SIZE);
256 char *system_message = 0;
257 for (;;) {
258 system_message = &buffer[0];
259 int result = StrError(error_code, system_message, buffer.size());
260 if (result == 0)
261 break;
262 if (result != ERANGE) {
263 // Can't get error message, report error code instead.
264 out << message << ": error code = " << error_code;
265 return;
266 }
267 buffer.resize(buffer.size() * 2);
268 }
269 out << message << ": " << system_message;
270}
271
272#ifdef _WIN32
273void fmt::internal::FormatWinErrorMessage(
274 fmt::Writer &out, int error_code, fmt::StringRef message) {
275 class String {
276 private:
277 LPWSTR str_;
278
279 public:
280 String() : str_() {}
281 ~String() { LocalFree(str_); }
282 LPWSTR *ptr() { return &str_; }
283 LPCWSTR c_str() const { return str_; }
284 };
285 String system_message;
286 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
287 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
288 error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
289 reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
290 UTF16ToUTF8 utf8_message;
291 if (!utf8_message.Convert(system_message.c_str())) {
292 out << message << ": " << c_str(utf8_message);
293 return;
294 }
295 }
296 // Can't get error message, report error code instead.
297 out << message << ": error code = " << error_code;
298}
299#endif
300
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700301template <typename Char>
302void fmt::internal::FormatErrorReporter<Char>::operator()(
303 const Char *s, fmt::StringRef message) const {
304 for (int n = num_open_braces; *s; ++s) {
305 if (*s == '{') {
306 ++n;
307 } else if (*s == '}') {
308 if (--n == 0)
309 throw fmt::FormatError(message);
310 }
311 }
312 throw fmt::FormatError("unmatched '{' in format");
313}
314
315// Parses an unsigned integer advancing s to the end of the parsed input.
316// This function assumes that the first character of s is a digit.
317template <typename Char>
318int fmt::internal::ParseNonnegativeInt(
319 const Char *&s, const char *&error) FMT_NOEXCEPT(true) {
320 assert('0' <= *s && *s <= '9');
321 unsigned value = 0;
322 do {
323 unsigned new_value = value * 10 + (*s++ - '0');
324 // Check if value wrapped around.
325 value = new_value >= value ? new_value : UINT_MAX;
326 } while ('0' <= *s && *s <= '9');
327 if (value > INT_MAX) {
328 if (!error)
329 error = "number is too big in format";
330 return 0;
331 }
332 return value;
333}
334
335template <typename Char>
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700336const typename fmt::internal::ArgInfo
337 fmt::BasicWriter<Char>::DUMMY_ARG = {fmt::internal::ArgInfo::INT, 0};
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700338
Victor Zverovich7cae7632013-09-06 20:23:42 -0700339// Fills the padding around the content and returns the pointer to the
340// content area.
341template <typename Char>
Victor Zverovich93e41252013-09-08 13:07:04 -0700342typename fmt::BasicWriter<Char>::CharPtr
343 fmt::BasicWriter<Char>::FillPadding(CharPtr buffer,
344 unsigned total_size, std::size_t content_size, wchar_t fill) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700345 std::size_t padding = total_size - content_size;
346 std::size_t left_padding = padding / 2;
Victor Zverovich563a5752013-09-08 13:47:06 -0700347 Char fill_char = static_cast<Char>(fill);
348 std::fill_n(buffer, left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700349 buffer += left_padding;
350 CharPtr content = buffer;
Victor Zverovich563a5752013-09-08 13:47:06 -0700351 std::fill_n(buffer + content_size, padding - left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700352 return content;
353}
354
355template <typename Char>
Victor Zverovich7cae7632013-09-06 20:23:42 -0700356template <typename T>
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700357void fmt::BasicWriter<Char>::FormatDouble(T value, const FormatSpec &spec) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700358 // Check type.
359 char type = spec.type();
360 bool upper = false;
361 switch (type) {
362 case 0:
363 type = 'g';
364 break;
Victor Zverovich03776dd2014-06-10 07:03:49 -0700365 case 'e': case 'f': case 'g': case 'a':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700366 break;
367 case 'F':
368#ifdef _MSC_VER
369 // MSVC's printf doesn't support 'F'.
370 type = 'f';
371#endif
372 // Fall through.
Victor Zverovich03776dd2014-06-10 07:03:49 -0700373 case 'E': case 'G': case 'A':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700374 upper = true;
375 break;
376 default:
377 internal::ReportUnknownType(type, "double");
378 break;
379 }
380
381 char sign = 0;
382 // Use SignBit instead of value < 0 because the latter is always
383 // false for NaN.
jdale88a9862fd2014-03-11 18:56:24 +0000384 if (SignBit(static_cast<double>(value))) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700385 sign = '-';
386 value = -value;
387 } else if (spec.sign_flag()) {
388 sign = spec.plus_flag() ? '+' : ' ';
389 }
390
391 if (value != value) {
392 // Format NaN ourselves because sprintf's output is not consistent
393 // across platforms.
394 std::size_t size = 4;
395 const char *nan = upper ? " NAN" : " nan";
396 if (!sign) {
397 --size;
398 ++nan;
399 }
400 CharPtr out = FormatString(nan, size, spec);
401 if (sign)
402 *out = sign;
403 return;
404 }
405
jdale88a9862fd2014-03-11 18:56:24 +0000406 if (IsInf(static_cast<double>(value))) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700407 // Format infinity ourselves because sprintf's output is not consistent
408 // across platforms.
409 std::size_t size = 4;
410 const char *inf = upper ? " INF" : " inf";
411 if (!sign) {
412 --size;
413 ++inf;
414 }
415 CharPtr out = FormatString(inf, size, spec);
416 if (sign)
417 *out = sign;
418 return;
419 }
420
421 std::size_t offset = buffer_.size();
422 unsigned width = spec.width();
423 if (sign) {
424 buffer_.reserve(buffer_.size() + (std::max)(width, 1u));
425 if (width > 0)
426 --width;
427 ++offset;
428 }
429
430 // Build format string.
431 enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg
432 Char format[MAX_FORMAT_SIZE];
433 Char *format_ptr = format;
434 *format_ptr++ = '%';
435 unsigned width_for_sprintf = width;
436 if (spec.hash_flag())
437 *format_ptr++ = '#';
438 if (spec.align() == ALIGN_CENTER) {
439 width_for_sprintf = 0;
440 } else {
441 if (spec.align() == ALIGN_LEFT)
442 *format_ptr++ = '-';
443 if (width != 0)
444 *format_ptr++ = '*';
445 }
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700446 if (spec.precision() >= 0) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700447 *format_ptr++ = '.';
448 *format_ptr++ = '*';
449 }
450 if (internal::IsLongDouble<T>::VALUE)
451 *format_ptr++ = 'L';
452 *format_ptr++ = type;
453 *format_ptr = '\0';
454
455 // Format using snprintf.
Victor Zverovich88972f42013-09-08 13:30:14 -0700456 Char fill = static_cast<Char>(spec.fill());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700457 for (;;) {
458 std::size_t size = buffer_.capacity() - offset;
Victor Zverovich33baa8f2014-04-23 18:37:08 -0700459#if _MSC_VER
460 // MSVC's vsnprintf_s doesn't work with zero size, so reserve
461 // space for at least one extra character to make the size non-zero.
462 // Note that the buffer's capacity will increase by more than 1.
463 if (size == 0) {
464 buffer_.reserve(offset + 1);
465 size = buffer_.capacity() - offset;
466 }
467#endif
Victor Zverovich7cae7632013-09-06 20:23:42 -0700468 Char *start = &buffer_[offset];
Victor Zverovichb605b392013-09-09 22:21:40 -0700469 int n = internal::CharTraits<Char>::FormatFloat(
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700470 start, size, format, width_for_sprintf, spec.precision(), value);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700471 if (n >= 0 && offset + n < buffer_.capacity()) {
472 if (sign) {
473 if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) ||
474 *start != ' ') {
475 *(start - 1) = sign;
476 sign = 0;
477 } else {
Victor Zverovich88972f42013-09-08 13:30:14 -0700478 *(start - 1) = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700479 }
480 ++n;
481 }
482 if (spec.align() == ALIGN_CENTER &&
483 spec.width() > static_cast<unsigned>(n)) {
484 unsigned width = spec.width();
485 CharPtr p = GrowBuffer(width);
486 std::copy(p, p + n, p + (width - n) / 2);
Victor Zverovich88972f42013-09-08 13:30:14 -0700487 FillPadding(p, spec.width(), n, fill);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700488 return;
489 }
490 if (spec.fill() != ' ' || sign) {
491 while (*start == ' ')
Victor Zverovich88972f42013-09-08 13:30:14 -0700492 *start++ = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700493 if (sign)
494 *(start - 1) = sign;
495 }
496 GrowBuffer(n);
497 return;
498 }
Victor Zverovichcfeba452014-04-23 18:37:49 -0700499 // If n is negative we ask to increase the capacity by at least 1,
500 // but as std::vector, the buffer grows exponentially.
501 buffer_.reserve(n >= 0 ? offset + n + 1 : buffer_.capacity() + 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700502 }
503}
504
Victor Zverovich7cae7632013-09-06 20:23:42 -0700505template <typename Char>
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700506fmt::ULongLong fmt::BasicWriter<Char>::GetIntValue(const Arg &arg) {
Victor Zverovich1b801482014-06-07 08:57:55 -0700507 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700508 case Arg::INT:
Victor Zverovich1b801482014-06-07 08:57:55 -0700509 return arg.int_value;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700510 case Arg::UINT:
Victor Zverovich1b801482014-06-07 08:57:55 -0700511 return arg.uint_value;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700512 case Arg::LONG_LONG:
Victor Zverovich1b801482014-06-07 08:57:55 -0700513 return arg.long_long_value;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700514 case Arg::ULONG_LONG:
Victor Zverovich1b801482014-06-07 08:57:55 -0700515 return arg.ulong_long_value;
516 default:
517 return -1;
518 }
519}
520
521template <typename Char>
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700522template <typename StringChar>
523void fmt::BasicWriter<Char>::FormatString(
524 const Arg::StringValue<StringChar> &str, const FormatSpec &spec) {
525 if (spec.type_ && spec.type_ != 's')
526 internal::ReportUnknownType(spec.type_, "string");
527 const StringChar *s = str.value;
528 std::size_t size = str.size;
529 if (size == 0) {
530 if (!s)
531 throw FormatError("string pointer is null");
532 if (*s)
533 size = std::char_traits<StringChar>::length(s);
534 }
535 FormatString(s, size, spec);
536}
537
538template <typename Char>
539inline const typename fmt::BasicWriter<Char>::Arg
Victor Zveroviche78904b2014-04-23 08:27:50 -0700540 &fmt::BasicWriter<Char>::FormatParser::ParseArgIndex(const Char *&s) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700541 unsigned arg_index = 0;
542 if (*s < '0' || *s > '9') {
543 if (*s != '}' && *s != ':')
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700544 report_error_(s, "invalid argument index in format string");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700545 if (next_arg_index_ < 0) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700546 report_error_(s,
Victor Zverovich7cae7632013-09-06 20:23:42 -0700547 "cannot switch from manual to automatic argument indexing");
548 }
549 arg_index = next_arg_index_++;
550 } else {
551 if (next_arg_index_ > 0) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700552 report_error_(s,
Victor Zverovich7cae7632013-09-06 20:23:42 -0700553 "cannot switch from automatic to manual argument indexing");
554 }
555 next_arg_index_ = -1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700556 const char *error = 0;
557 arg_index = internal::ParseNonnegativeInt(s, error);
558 if (error)
559 report_error_(s, error); // TODO
Victor Zverovich7cae7632013-09-06 20:23:42 -0700560 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700561 if (arg_index >= args_.size())
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700562 report_error_(s, "argument index is out of range in format");
Victor Zverovich656a8372014-04-22 08:58:54 -0700563 return args_[arg_index];
Victor Zverovich7cae7632013-09-06 20:23:42 -0700564}
565
566template <typename Char>
Victor Zveroviche78904b2014-04-23 08:27:50 -0700567void fmt::BasicWriter<Char>::FormatParser::CheckSign(
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700568 const Char *&s, const Arg &arg) {
Victor Zverovichcc6af502013-12-10 08:01:08 -0800569 char sign = static_cast<char>(*s);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700570 if (arg.type > Arg::LAST_NUMERIC_TYPE) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700571 report_error_(s,
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700572 fmt::format("format specifier '{}' requires numeric argument", sign).c_str());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700573 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700574 if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700575 report_error_(s,
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700576 fmt::format("format specifier '{}' requires signed argument", sign).c_str());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700577 }
578 ++s;
579}
580
581template <typename Char>
Victor Zverovichbf790d22014-06-07 07:31:25 -0700582void fmt::BasicWriter<Char>::PrintfParser::ParseFlags(
Victor Zverovichcb743c02014-06-19 07:40:35 -0700583 FormatSpec &spec, const Char *&s) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700584 for (;;) {
Victor Zverovich1b801482014-06-07 08:57:55 -0700585 switch (*s++) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700586 case '-':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700587 spec.align_ = ALIGN_LEFT;
588 break;
589 case '+':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700590 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
591 break;
592 case '0':
593 spec.fill_ = '0';
Victor Zverovich1b801482014-06-07 08:57:55 -0700594 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700595 case ' ':
Victor Zverovich1b801482014-06-07 08:57:55 -0700596 spec.flags_ |= SIGN_FLAG;
597 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700598 case '#':
Victor Zverovichcb743c02014-06-19 07:40:35 -0700599 spec.flags_ |= HASH_FLAG;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700600 break;
601 default:
Victor Zverovich1b801482014-06-07 08:57:55 -0700602 --s;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700603 return;
604 }
605 }
606}
607
Victor Zverovichcb743c02014-06-19 07:40:35 -0700608template <typename Char>
609unsigned fmt::BasicWriter<Char>::PrintfParser::ParseHeader(
610 const Char *&s, FormatSpec &spec, const char *&error) {
611 unsigned arg_index = UINT_MAX;
612 Char c = *s;
613 if (c >= '0' && c <= '9') {
614 // Parse an argument index (if followed by '$') or a width possibly
Victor Zverovich879838a2014-06-20 07:34:02 -0700615 // preceded with '0' flag(s).
Victor Zverovichcb743c02014-06-19 07:40:35 -0700616 unsigned value = internal::ParseNonnegativeInt(s, error);
617 if (*s == '$') { // value is an argument index
618 ++s;
619 arg_index = value;
620 } else {
621 if (c == '0')
622 spec.fill_ = '0';
623 if (value != 0) {
624 // Nonzero value means that we parsed width and don't need to
625 // parse it or flags again, so return now.
626 spec.width_ = value;
627 return arg_index;
628 }
629 }
630 }
Victor Zverovichcb743c02014-06-19 07:40:35 -0700631 ParseFlags(spec, s);
Victor Zverovich4099a122014-06-23 08:10:50 -0700632 // Parse width.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700633 if (*s >= '0' && *s <= '9') {
634 spec.width_ = internal::ParseNonnegativeInt(s, error);
635 } else if (*s == '*') {
636 ++s;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700637 const Arg &arg = HandleArgIndex(UINT_MAX, error);
638 // TODO: use ArgVisitor
Victor Zverovich4099a122014-06-23 08:10:50 -0700639 ULongLong width = 0;
640 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700641 case Arg::INT:
Victor Zverovich4099a122014-06-23 08:10:50 -0700642 width = arg.int_value;
643 if (arg.int_value < 0) {
644 spec.align_ = ALIGN_LEFT;
Victor Zverovich3e53ac22014-06-23 08:48:42 -0700645 width = 0 - width;
Victor Zverovich4099a122014-06-23 08:10:50 -0700646 }
647 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700648 case Arg::UINT:
Victor Zverovich4099a122014-06-23 08:10:50 -0700649 width = arg.uint_value;
650 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700651 case Arg::LONG_LONG:
Victor Zverovich4099a122014-06-23 08:10:50 -0700652 width = arg.long_long_value;
653 if (arg.long_long_value < 0) {
654 spec.align_ = ALIGN_LEFT;
Victor Zverovich3e53ac22014-06-23 08:48:42 -0700655 width = 0 - width;
Victor Zverovich4099a122014-06-23 08:10:50 -0700656 }
657 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700658 case Arg::ULONG_LONG:
Victor Zverovich4099a122014-06-23 08:10:50 -0700659 width = arg.ulong_long_value;
660 break;
661 default:
662 if (!error)
663 error = "width is not integer";
664 }
665 if (width <= INT_MAX)
666 spec.width_ = static_cast<unsigned>(width);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700667 else if (!error)
Victor Zverovich4099a122014-06-23 08:10:50 -0700668 error = "number is too big in format";
Victor Zverovichcb743c02014-06-19 07:40:35 -0700669 }
670 return arg_index;
671}
672
Victor Zverovich879838a2014-06-20 07:34:02 -0700673// TODO: move to a base class that doesn't depend on template argument
Victor Zverovichbf790d22014-06-07 07:31:25 -0700674template <typename Char>
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700675const typename fmt::BasicWriter<Char>::Arg
Victor Zverovichcb743c02014-06-19 07:40:35 -0700676 &fmt::BasicWriter<Char>::PrintfParser::HandleArgIndex(
Victor Zverovich12759232014-06-17 06:53:48 -0700677 unsigned arg_index, const char *&error) {
678 if (arg_index != UINT_MAX) {
679 if (next_arg_index_ <= 0) {
680 next_arg_index_ = -1;
Victor Zverovichcb743c02014-06-19 07:40:35 -0700681 --arg_index;
682 } else if (!error) {
Victor Zverovich12759232014-06-17 06:53:48 -0700683 error = "cannot switch from automatic to manual argument indexing";
Victor Zverovichcb743c02014-06-19 07:40:35 -0700684 }
685 } else if (next_arg_index_ >= 0) {
686 arg_index = next_arg_index_++;
687 } else if (!error) {
688 error = "cannot switch from manual to automatic argument indexing";
Victor Zverovich1f19b982014-06-16 07:49:30 -0700689 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700690 if (arg_index < args_.size())
Victor Zverovichcb743c02014-06-19 07:40:35 -0700691 return args_[arg_index];
692 if (!error)
693 error = "argument index is out of range in format";
694 return DUMMY_ARG;
Victor Zverovich1f19b982014-06-16 07:49:30 -0700695}
696
697template <typename Char>
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700698void fmt::BasicWriter<Char>::PrintfParser::Format(
Victor Zveroviche78904b2014-04-23 08:27:50 -0700699 BasicWriter<Char> &writer, BasicStringRef<Char> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700700 const ArgList &args) {
Victor Zveroviche78904b2014-04-23 08:27:50 -0700701 const Char *start = format.c_str();
Victor Zveroviche78904b2014-04-23 08:27:50 -0700702 args_ = args;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700703 next_arg_index_ = 0;
704 const Char *s = start;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700705 while (*s) {
Victor Zverovich0fc73162013-09-07 12:52:52 -0700706 Char c = *s++;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700707 if (c != '%') continue;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700708 if (*s == c) {
709 writer.buffer_.append(start, s);
710 start = ++s;
711 continue;
712 }
Victor Zverovich7cae7632013-09-06 20:23:42 -0700713 writer.buffer_.append(start, s - 1);
714
Victor Zverovichcb743c02014-06-19 07:40:35 -0700715 FormatSpec spec;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700716 spec.align_ = ALIGN_RIGHT;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700717
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700718 // Reporting errors is delayed till the format specification is
719 // completely parsed. This is done to avoid potentially confusing
720 // error messages for incomplete format strings. For example, in
721 // sprintf("%2$", 42);
722 // the format specification is incomplete. In naive approach we
723 // would parse 2 as an argument index and report an error that the
724 // index is out of range which would be rather confusing if the
725 // use meant "%2d$" rather than "%2$d". If we delay an error, the
726 // user will get an error that the format string is invalid which
727 // is OK for both cases.
728 const char *error = 0;
729
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700730 // Parse argument index, flags and width.
731 unsigned arg_index = ParseHeader(s, spec, error);
732
733 // Parse precision.
734 if (*s == '.') {
735 ++s;
736 if ('0' <= *s && *s <= '9') {
737 spec.precision_ = internal::ParseNonnegativeInt(s, error);
738 } else if (*s == '*') {
739 ++s;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700740 const Arg &arg = HandleArgIndex(UINT_MAX, error);
741 if (arg.type <= Arg::LAST_INTEGER_TYPE)
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700742 spec.precision_ = GetIntValue(arg);
743 else if (!error)
744 error = "precision is not integer";
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700745 }
746 }
747
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700748 const Arg &arg = HandleArgIndex(arg_index, error);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700749 if (spec.hash_flag() && GetIntValue(arg) == 0)
750 spec.flags_ &= ~HASH_FLAG;
751 if (spec.fill_ == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700752 if (arg.type <= Arg::LAST_NUMERIC_TYPE)
Victor Zverovichcb743c02014-06-19 07:40:35 -0700753 spec.align_ = ALIGN_NUMERIC;
754 else
755 spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700756 }
757
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700758 // Parse length.
759 switch (*s) {
760 case 'h':
761 // TODO: convert to short
762 case 'l':
763 case 'j':
764 case 'z':
765 case 't':
766 case 'L':
767 // TODO: handle length
768 ++s;
769 break;
770 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700771
772 // Parse type.
773 if (!*s)
774 throw FormatError("invalid format string");
775 if (error)
776 throw FormatError(error);
777 spec.type_ = static_cast<char>(*s++);
778
779 start = s;
780
781 // Format argument.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700782 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700783 case Arg::INT:
Victor Zverovichcb743c02014-06-19 07:40:35 -0700784 writer.FormatInt(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700785 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700786 case Arg::UINT:
Victor Zverovichcb743c02014-06-19 07:40:35 -0700787 writer.FormatInt(arg.uint_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700788 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700789 case Arg::LONG_LONG:
Victor Zverovichcb743c02014-06-19 07:40:35 -0700790 writer.FormatInt(arg.long_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700791 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700792 case Arg::ULONG_LONG:
Victor Zverovichcb743c02014-06-19 07:40:35 -0700793 writer.FormatInt(arg.ulong_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700794 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700795 case Arg::DOUBLE:
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700796 writer.FormatDouble(arg.double_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700797 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700798 case Arg::LONG_DOUBLE:
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700799 writer.FormatDouble(arg.long_double_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700800 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700801 case Arg::CHAR: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700802 if (spec.type_ && spec.type_ != 'c')
803 internal::ReportUnknownType(spec.type_, "char");
804 typedef typename BasicWriter<Char>::CharPtr CharPtr;
805 CharPtr out = CharPtr();
806 if (spec.width_ > 1) {
807 Char fill = static_cast<Char>(spec.fill());
808 out = writer.GrowBuffer(spec.width_);
809 if (spec.align_ == ALIGN_RIGHT) {
810 std::fill_n(out, spec.width_ - 1, fill);
811 out += spec.width_ - 1;
812 } else if (spec.align_ == ALIGN_CENTER) {
813 out = writer.FillPadding(out, spec.width_, 1, fill);
814 } else {
815 std::fill_n(out + 1, spec.width_ - 1, fill);
816 }
817 } else {
818 out = writer.GrowBuffer(1);
819 }
Victor Zverovichcb743c02014-06-19 07:40:35 -0700820 *out = static_cast<Char>(arg.int_value);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700821 break;
822 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700823 case Arg::STRING:
824 writer.FormatString(arg.string, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700825 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700826 case Arg::WSTRING:
827 writer.FormatString(arg.wstring, spec);
828 break;
829 case Arg::POINTER:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700830 if (spec.type_ && spec.type_ != 'p')
831 internal::ReportUnknownType(spec.type_, "pointer");
832 spec.flags_= HASH_FLAG;
833 spec.type_ = 'x';
Victor Zverovichcb743c02014-06-19 07:40:35 -0700834 writer.FormatInt(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700835 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700836 case Arg::CUSTOM:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700837 if (spec.type_)
838 internal::ReportUnknownType(spec.type_, "object");
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700839 arg.custom.format(&writer, arg.custom.value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700840 break;
841 default:
842 assert(false);
843 break;
844 }
845 }
846 writer.buffer_.append(start, s);
847}
848
849template <typename Char>
850void fmt::BasicWriter<Char>::FormatParser::Format(
851 BasicWriter<Char> &writer, BasicStringRef<Char> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700852 const ArgList &args) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700853 const char *error = 0;
854 const Char *start = format.c_str();
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700855 args_ = args;
856 next_arg_index_ = 0;
857 const Char *s = start;
858 while (*s) {
859 Char c = *s++;
860 if (c != '{' && c != '}') continue;
861 if (*s == c) {
862 writer.buffer_.append(start, s);
863 start = ++s;
864 continue;
865 }
866 if (c == '}')
867 throw FormatError("unmatched '}' in format");
868 report_error_.num_open_braces = 1;
869 writer.buffer_.append(start, s - 1);
870
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700871 const Arg &arg = ParseArgIndex(s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700872
873 FormatSpec spec;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700874 if (*s == ':') {
875 ++s;
876
877 // Parse fill and alignment.
878 if (Char c = *s) {
879 const Char *p = s + 1;
880 spec.align_ = ALIGN_DEFAULT;
881 do {
882 switch (*p) {
883 case '<':
884 spec.align_ = ALIGN_LEFT;
885 break;
886 case '>':
887 spec.align_ = ALIGN_RIGHT;
888 break;
889 case '=':
890 spec.align_ = ALIGN_NUMERIC;
891 break;
892 case '^':
893 spec.align_ = ALIGN_CENTER;
894 break;
895 }
896 if (spec.align_ != ALIGN_DEFAULT) {
897 if (p != s) {
898 if (c == '}') break;
899 if (c == '{')
900 report_error_(s, "invalid fill character '{'");
901 s += 2;
902 spec.fill_ = c;
903 } else ++s;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700904 if (spec.align_ == ALIGN_NUMERIC && arg.type > Arg::LAST_NUMERIC_TYPE)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700905 report_error_(s, "format specifier '=' requires numeric argument");
906 break;
907 }
908 } while (--p >= s);
909 }
910
911 // Parse sign.
912 switch (*s) {
913 case '+':
914 CheckSign(s, arg);
915 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
916 break;
917 case '-':
918 CheckSign(s, arg);
919 break;
920 case ' ':
921 CheckSign(s, arg);
922 spec.flags_ |= SIGN_FLAG;
923 break;
924 }
925
926 if (*s == '#') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700927 if (arg.type > Arg::LAST_NUMERIC_TYPE)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700928 report_error_(s, "format specifier '#' requires numeric argument");
929 spec.flags_ |= HASH_FLAG;
930 ++s;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700931 }
932
933 // Parse width and zero flag.
934 if ('0' <= *s && *s <= '9') {
935 if (*s == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700936 if (arg.type > Arg::LAST_NUMERIC_TYPE)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700937 report_error_(s, "format specifier '0' requires numeric argument");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700938 spec.align_ = ALIGN_NUMERIC;
939 spec.fill_ = '0';
940 }
941 // Zero may be parsed again as a part of the width, but it is simpler
942 // and more efficient than checking if the next char is a digit.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700943 spec.width_ = internal::ParseNonnegativeInt(s, error);
944 if (error)
945 report_error_(s, error);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700946 }
947
948 // Parse precision.
949 if (*s == '.') {
950 ++s;
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700951 spec.precision_ = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700952 if ('0' <= *s && *s <= '9') {
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700953 spec.precision_ = internal::ParseNonnegativeInt(s, error);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700954 if (error)
955 report_error_(s, error);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700956 } else if (*s == '{') {
957 ++s;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700958 ++report_error_.num_open_braces;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700959 const Arg &precision_arg = ParseArgIndex(s);
Victor Zverovichf406a422013-12-06 07:12:38 -0800960 ULongLong value = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700961 switch (precision_arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700962 case Arg::INT:
Victor Zverovich7cae7632013-09-06 20:23:42 -0700963 if (precision_arg.int_value < 0)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700964 report_error_(s, "negative precision in format");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700965 value = precision_arg.int_value;
966 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700967 case Arg::UINT:
Victor Zverovich7cae7632013-09-06 20:23:42 -0700968 value = precision_arg.uint_value;
969 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700970 case Arg::LONG_LONG:
Victor Zverovich56f12b72013-11-22 07:45:43 -0800971 if (precision_arg.long_long_value < 0)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700972 report_error_(s, "negative precision in format");
Victor Zverovich56f12b72013-11-22 07:45:43 -0800973 value = precision_arg.long_long_value;
974 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700975 case Arg::ULONG_LONG:
Gregory Czajkowskia65542b2013-11-18 22:58:39 -0800976 value = precision_arg.ulong_long_value;
Victor Zverovicha4e72b42013-11-21 09:11:58 -0800977 break;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700978 default:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700979 report_error_(s, "precision is not integer");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700980 }
981 if (value > INT_MAX)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700982 report_error_(s, "number is too big in format");
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700983 spec.precision_ = static_cast<int>(value);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700984 if (*s++ != '}')
985 throw FormatError("unmatched '{' in format");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700986 --report_error_.num_open_braces;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700987 } else {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700988 report_error_(s, "missing precision in format");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700989 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700990 if (arg.type != Arg::DOUBLE && arg.type != Arg::LONG_DOUBLE) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700991 report_error_(s,
Victor Zverovich7cae7632013-09-06 20:23:42 -0700992 "precision specifier requires floating-point argument");
993 }
994 }
995
996 // Parse type.
997 if (*s != '}' && *s)
Victor Zverovich0fc73162013-09-07 12:52:52 -0700998 spec.type_ = static_cast<char>(*s++);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700999 }
1000
1001 if (*s++ != '}')
1002 throw FormatError("unmatched '{' in format");
1003 start = s;
1004
1005 // Format argument.
1006 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001007 case Arg::INT:
Victor Zverovich03f68852014-04-20 08:46:09 -07001008 writer.FormatInt(arg.int_value, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001009 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001010 case Arg::UINT:
Victor Zverovich03f68852014-04-20 08:46:09 -07001011 writer.FormatInt(arg.uint_value, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001012 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001013 case Arg::LONG_LONG:
Victor Zverovich03f68852014-04-20 08:46:09 -07001014 writer.FormatInt(arg.long_long_value, spec);
Victor Zverovich56f12b72013-11-22 07:45:43 -08001015 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001016 case Arg::ULONG_LONG:
Victor Zverovich03f68852014-04-20 08:46:09 -07001017 writer.FormatInt(arg.ulong_long_value, spec);
Victor Zverovicha4e72b42013-11-21 09:11:58 -08001018 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001019 case Arg::DOUBLE:
Victor Zverovichb1bbc902014-06-21 08:32:00 -07001020 writer.FormatDouble(arg.double_value, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001021 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001022 case Arg::LONG_DOUBLE:
Victor Zverovichb1bbc902014-06-21 08:32:00 -07001023 writer.FormatDouble(arg.long_double_value, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001024 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001025 case Arg::CHAR: {
Victor Zverovich7cae7632013-09-06 20:23:42 -07001026 if (spec.type_ && spec.type_ != 'c')
1027 internal::ReportUnknownType(spec.type_, "char");
1028 typedef typename BasicWriter<Char>::CharPtr CharPtr;
1029 CharPtr out = CharPtr();
1030 if (spec.width_ > 1) {
Victor Zverovichc62c4752013-09-08 14:25:22 -07001031 Char fill = static_cast<Char>(spec.fill());
Victor Zverovich7cae7632013-09-06 20:23:42 -07001032 out = writer.GrowBuffer(spec.width_);
1033 if (spec.align_ == ALIGN_RIGHT) {
Victor Zverovichc62c4752013-09-08 14:25:22 -07001034 std::fill_n(out, spec.width_ - 1, fill);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001035 out += spec.width_ - 1;
1036 } else if (spec.align_ == ALIGN_CENTER) {
Victor Zverovichc62c4752013-09-08 14:25:22 -07001037 out = writer.FillPadding(out, spec.width_, 1, fill);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001038 } else {
Victor Zverovichc62c4752013-09-08 14:25:22 -07001039 std::fill_n(out + 1, spec.width_ - 1, fill);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001040 }
1041 } else {
1042 out = writer.GrowBuffer(1);
1043 }
jdale884cabe162014-03-11 19:03:26 +00001044 *out = static_cast<Char>(arg.int_value);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001045 break;
1046 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001047 case Arg::STRING:
1048 writer.FormatString(arg.string, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001049 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001050 case Arg::WSTRING:
1051 writer.FormatString(arg.wstring, spec);
1052 break;
1053 case Arg::POINTER:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001054 if (spec.type_ && spec.type_ != 'p')
1055 internal::ReportUnknownType(spec.type_, "pointer");
1056 spec.flags_= HASH_FLAG;
1057 spec.type_ = 'x';
Victor Zverovich03f68852014-04-20 08:46:09 -07001058 writer.FormatInt(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001059 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001060 case Arg::CUSTOM:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001061 if (spec.type_)
1062 internal::ReportUnknownType(spec.type_, "object");
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001063 arg.custom.format(&writer, arg.custom.value, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001064 break;
1065 default:
1066 assert(false);
1067 break;
1068 }
1069 }
1070 writer.buffer_.append(start, s);
1071}
1072
Victor Zverovich859a4972014-04-30 06:55:21 -07001073void fmt::SystemErrorSink::operator()(const fmt::Writer &w) const {
1074 Writer message;
Victor Zverovich53b4c312014-04-30 15:00:41 -07001075 internal::FormatSystemErrorMessage(message, error_code_, w.c_str());
Victor Zverovich859a4972014-04-30 06:55:21 -07001076 throw SystemError(message.c_str(), error_code_);
1077}
1078
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001079void fmt::ReportSystemError(
1080 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
1081 // FIXME: FormatSystemErrorMessage may throw
1082 ReportError(internal::FormatSystemErrorMessage, error_code, message);
1083}
1084
Victor Zverovich400812a2014-04-30 12:38:17 -07001085#ifdef _WIN32
1086void fmt::WinErrorSink::operator()(const Writer &w) const {
Victor Zverovichf7939862014-04-30 10:18:11 -07001087 Writer message;
Victor Zverovich53b4c312014-04-30 15:00:41 -07001088 internal::FormatWinErrorMessage(message, error_code_, w.c_str());
Victor Zverovichf7939862014-04-30 10:18:11 -07001089 throw SystemError(message.c_str(), error_code_);
1090}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001091
1092void fmt::ReportWinError(
1093 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
1094 // FIXME: FormatWinErrorMessage may throw
1095 ReportError(internal::FormatWinErrorMessage, error_code, message);
1096}
Victor Zverovich400812a2014-04-30 12:38:17 -07001097#endif
Victor Zverovichf7939862014-04-30 10:18:11 -07001098
Victor Zverovichd9db8982014-04-28 08:59:29 -07001099void fmt::ANSITerminalSink::operator()(
1100 const fmt::BasicWriter<char> &w) const {
Victor Zverovich43fe1002014-02-19 14:20:26 -08001101 char escape[] = "\x1b[30m";
jdale88a9862fd2014-03-11 18:56:24 +00001102 escape[3] = '0' + static_cast<char>(color_);
Victor Zverovichd9db8982014-04-28 08:59:29 -07001103 std::fputs(escape, file_);
1104 std::fwrite(w.data(), 1, w.size(), file_);
1105 std::fputs(RESET_COLOR, file_);
Victor Zverovich43fe1002014-02-19 14:20:26 -08001106}
Victor Zverovich6968ef32014-02-19 13:51:23 -08001107
Victor Zverovich2e039632014-06-28 19:44:39 -07001108void fmt::print(StringRef format, const ArgList &args) {
1109 Writer w;
Victor Zverovicha1264922014-06-29 11:51:10 -07001110 w.write(format, args);
Victor Zverovich2e039632014-06-28 19:44:39 -07001111 std::fwrite(w.data(), 1, w.size(), stdout);
1112}
1113
Victor Zverovichd5b81962014-06-28 21:56:40 -07001114void fmt::print(std::FILE *f, StringRef format, const ArgList &args) {
1115 Writer w;
Victor Zverovicha1264922014-06-29 11:51:10 -07001116 w.write(format, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001117 std::fwrite(w.data(), 1, w.size(), f);
1118}
1119
1120void fmt::printf(StringRef format, const ArgList &args) {
1121 Writer w;
Victor Zverovich21111cc2014-06-29 19:52:26 -07001122 printf(w, format, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001123 std::fwrite(w.data(), 1, w.size(), stdout);
1124}
1125
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001126// Explicit instantiations for char.
1127
Victor Zverovich93e41252013-09-08 13:07:04 -07001128template fmt::BasicWriter<char>::CharPtr
1129 fmt::BasicWriter<char>::FillPadding(CharPtr buffer,
1130 unsigned total_size, std::size_t content_size, wchar_t fill);
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001131
Victor Zveroviche78904b2014-04-23 08:27:50 -07001132template void fmt::BasicWriter<char>::FormatParser::Format(
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001133 BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001134
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001135template void fmt::BasicWriter<char>::PrintfParser::Format(
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001136 BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001137
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001138// Explicit instantiations for wchar_t.
1139
Victor Zverovich7cae7632013-09-06 20:23:42 -07001140template fmt::BasicWriter<wchar_t>::CharPtr
Victor Zverovich93e41252013-09-08 13:07:04 -07001141 fmt::BasicWriter<wchar_t>::FillPadding(CharPtr buffer,
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001142 unsigned total_size, std::size_t content_size, wchar_t fill);
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001143
Victor Zveroviche78904b2014-04-23 08:27:50 -07001144template void fmt::BasicWriter<wchar_t>::FormatParser::Format(
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001145 BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001146 const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001147
1148template void fmt::BasicWriter<wchar_t>::PrintfParser::Format(
1149 BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001150 const ArgList &args);
jdale88a9862fd2014-03-11 18:56:24 +00001151
1152#if _MSC_VER
1153# pragma warning(pop)
1154#endif