blob: e71207ba57adfda6068c8999ae6c4e97a9f68793 [file] [log] [blame]
Victor Zverovichb076df42012-12-07 08:31:09 -08001/*
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07002 Formatting library for C++
Victor Zverovichfaccb4c2012-12-12 07:44:41 -08003
Victor Zveroviche3a44c12014-07-09 06:56:36 -07004 Copyright (c) 2012 - 2014, Victor Zverovich
Victor Zverovichfaccb4c2012-12-12 07:44:41 -08005 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 1. Redistributions of source code must retain the above copyright notice, this
11 list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Victor Zverovichb076df42012-12-07 08:31:09 -080026 */
27
Victor 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 Zverovich5d15bdd2014-07-01 16:23:50 -070039#include <cerrno>
Victor Zverovichf28645f2014-04-24 12:37:06 -070040#include <climits>
Victor Zverovich9ff3b972013-09-07 10:15:08 -070041#include <cmath>
Victor Zverovicha684d0c2013-12-27 08:00:10 -080042#include <cstdarg>
Victor Zverovich9ff3b972013-09-07 10:15:08 -070043
Victor Zverovich859a4972014-04-30 06:55:21 -070044#ifdef _WIN32
Victor Zverovichdcd039d2014-05-01 07:09:42 -070045# define WIN32_LEAN_AND_MEAN
Constantine Tarasenkov6aace692014-06-11 02:38:57 +040046# ifdef __MINGW32__
47# include <cstring>
48# endif
Victor Zverovich859a4972014-04-30 06:55:21 -070049# include <windows.h>
Victor Zveroviched2bdba2014-04-30 07:41:54 -070050# undef ERROR
Victor Zverovich859a4972014-04-30 06:55:21 -070051#endif
52
Victor Zverovich591ad0a2014-07-14 06:55:29 -070053using fmt::LongLong;
Victor Zverovich447e02c2014-02-15 10:48:34 -080054using fmt::ULongLong;
Victor Zverovich6e5551e2014-07-02 06:33:25 -070055using fmt::internal::Arg;
Victor Zverovich447e02c2014-02-15 10:48:34 -080056
jdale88a9862fd2014-03-11 18:56:24 +000057#if _MSC_VER
58# pragma warning(push)
59# pragma warning(disable: 4127) // conditional expression is constant
60#endif
61
Victor Zverovich9ff3b972013-09-07 10:15:08 -070062namespace {
63
64#ifndef _MSC_VER
65
66inline int SignBit(double value) {
67 // When compiled in C++11 mode signbit is no longer a macro but a function
68 // defined in namespace std and the macro is undefined.
Victor Zverovichf2e06802014-04-10 10:49:55 -070069#ifdef signbit
Victor Zverovich9ff3b972013-09-07 10:15:08 -070070 return signbit(value);
Victor Zverovichf2e06802014-04-10 10:49:55 -070071#else
72 return std::signbit(value);
73#endif
Victor Zverovich9ff3b972013-09-07 10:15:08 -070074}
75
76inline int IsInf(double x) {
77#ifdef isinf
78 return isinf(x);
79#else
80 return std::isinf(x);
81#endif
82}
83
84#define FMT_SNPRINTF snprintf
85
Victor Zverovicha684d0c2013-12-27 08:00:10 -080086#else // _MSC_VER
Victor Zverovich9ff3b972013-09-07 10:15:08 -070087
88inline int SignBit(double value) {
89 if (value < 0) return 1;
90 if (value == value) return 0;
91 int dec = 0, sign = 0;
92 char buffer[2]; // The buffer size must be >= 2 or _ecvt_s will fail.
93 _ecvt_s(buffer, sizeof(buffer), value, 0, &dec, &sign);
94 return sign;
95}
96
97inline int IsInf(double x) { return !_finite(x); }
98
Victor Zverovicha684d0c2013-12-27 08:00:10 -080099inline int FMT_SNPRINTF(char *buffer, size_t size, const char *format, ...) {
100 va_list args;
101 va_start(args, format);
102 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
103 va_end(args);
104 return result;
105}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700106
107#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -0800108
109const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700110
111typedef void (*FormatFunc)(fmt::Writer &, int , fmt::StringRef);
112
113void ReportError(FormatFunc func,
114 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
115 try {
116 fmt::Writer full_message;
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700117 func(full_message, error_code, message); // TODO: make sure this doesn't throw
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700118 std::fwrite(full_message.c_str(), full_message.size(), 1, stderr);
119 std::fputc('\n', stderr);
120 } catch (...) {}
Victor Zverovichb605b392013-09-09 22:21:40 -0700121}
Victor Zverovichd29e5052014-06-30 07:12:09 -0700122
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700123const Arg DUMMY_ARG = {Arg::INT, 0};
Victor Zverovichd29e5052014-06-30 07:12:09 -0700124
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700125fmt::ULongLong GetIntValue(const Arg &arg) {
Victor Zverovichd29e5052014-06-30 07:12:09 -0700126 switch (arg.type) {
127 case Arg::INT:
128 return arg.int_value;
129 case Arg::UINT:
130 return arg.uint_value;
131 case Arg::LONG_LONG:
132 return arg.long_long_value;
133 case Arg::ULONG_LONG:
134 return arg.ulong_long_value;
135 default:
136 return -1;
137 }
138}
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700139
140// Parses an unsigned integer advancing s to the end of the parsed input.
141// This function assumes that the first character of s is a digit.
142template <typename Char>
143int ParseNonnegativeInt(const Char *&s, const char *&error) FMT_NOEXCEPT(true) {
144 assert('0' <= *s && *s <= '9');
145 unsigned value = 0;
146 do {
147 unsigned new_value = value * 10 + (*s++ - '0');
148 // Check if value wrapped around.
149 value = new_value >= value ? new_value : UINT_MAX;
150 } while ('0' <= *s && *s <= '9');
151 if (value > INT_MAX) {
152 if (!error)
153 error = "number is too big in format";
154 return 0;
155 }
156 return value;
157}
Victor Zveroviche8251562014-07-08 16:20:33 -0700158
159template <typename Char>
160const Char *find_closing_brace(const Char *s, int num_open_braces = 1) {
161 for (int n = num_open_braces; *s; ++s) {
162 if (*s == '{') {
163 ++n;
164 } else if (*s == '}') {
165 if (--n == 0)
166 return s;
167 }
168 }
169 throw fmt::FormatError("unmatched '{' in format");
170}
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700171
172// Handles width specifier.
173struct WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, ULongLong> {
174 private:
175 fmt::FormatSpec &spec_;
176 public:
177 explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
178 ULongLong visit_unhandled_arg() {
179 throw fmt::FormatError("width is not integer");
180 }
181 ULongLong visit_any_int(fmt::LongLong value) {
182 ULongLong width = value;
183 if (value < 0) {
184 spec_.align_ = fmt::ALIGN_LEFT;
185 width = 0 - width;
186 }
187 return width;
188 }
189 ULongLong visit_any_uint(ULongLong value) { return value; }
190};
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700191} // namespace
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700192
Victor Zverovich302b8f42014-06-24 10:46:01 -0700193int fmt::internal::SignBitNoInline(double value) { return SignBit(value); }
194
Victor Zverovich53201032014-06-30 14:26:29 -0700195void fmt::SystemError::init(
196 int error_code, StringRef format_str, const ArgList &args) {
197 error_code_ = error_code;
198 Writer w;
199 internal::FormatSystemErrorMessage(w, error_code, format(format_str, args));
200 std::runtime_error &base = *this;
201 base = std::runtime_error(w.str());
202}
203
Victor Zverovichb605b392013-09-09 22:21:40 -0700204template <typename T>
205int fmt::internal::CharTraits<char>::FormatFloat(
206 char *buffer, std::size_t size, const char *format,
207 unsigned width, int precision, T value) {
208 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700209 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700210 FMT_SNPRINTF(buffer, size, format, value) :
211 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700212 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700213 return precision < 0 ?
214 FMT_SNPRINTF(buffer, size, format, width, value) :
215 FMT_SNPRINTF(buffer, size, format, width, precision, value);
216}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700217
Victor Zverovichb605b392013-09-09 22:21:40 -0700218template <typename T>
219int fmt::internal::CharTraits<wchar_t>::FormatFloat(
220 wchar_t *buffer, std::size_t size, const wchar_t *format,
221 unsigned width, int precision, T value) {
222 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700223 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700224 swprintf(buffer, size, format, value) :
225 swprintf(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700226 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700227 return precision < 0 ?
228 swprintf(buffer, size, format, width, value) :
229 swprintf(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700230}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800231
Victor Zverovich65d47e52013-09-09 06:51:03 -0700232const char fmt::internal::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800233 "0001020304050607080910111213141516171819"
234 "2021222324252627282930313233343536373839"
235 "4041424344454647484950515253545556575859"
236 "6061626364656667686970717273747576777879"
237 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800238
Victor Zverovichf1d85162014-02-19 13:02:22 -0800239#define FMT_POWERS_OF_10(factor) \
240 factor * 10, \
241 factor * 100, \
242 factor * 1000, \
243 factor * 10000, \
244 factor * 100000, \
245 factor * 1000000, \
246 factor * 10000000, \
247 factor * 100000000, \
248 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800249
Victor Zverovichf1d85162014-02-19 13:02:22 -0800250const uint32_t fmt::internal::POWERS_OF_10_32[] = {0, FMT_POWERS_OF_10(1)};
Victor Zveroviche9b21912014-02-19 12:43:55 -0800251const uint64_t fmt::internal::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800252 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800253 FMT_POWERS_OF_10(1),
254 FMT_POWERS_OF_10(ULongLong(1000000000)),
255 // Multiply several constants instead of using a single long long constants
256 // to avoid warnings about C++98 not supporting long long.
Victor Zverovich6f6fe512014-02-15 11:16:44 -0800257 ULongLong(1000000000) * ULongLong(1000000000) * 10
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800258};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800259
Victor Zverovich687301c2013-01-26 16:07:28 -0800260void fmt::internal::ReportUnknownType(char code, const char *type) {
Victor Zverovich877abaf2013-01-08 09:56:05 -0800261 if (std::isprint(static_cast<unsigned char>(code))) {
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700262 throw fmt::FormatError(
263 fmt::format("unknown format code '{}' for {}", code, type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800264 }
265 throw fmt::FormatError(
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700266 fmt::format("unknown format code '\\x{:02x}' for {}",
267 static_cast<unsigned>(code), type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800268}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700269
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700270#ifdef _WIN32
271
272fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
273 int length = MultiByteToWideChar(
274 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, 0, 0);
275 static const char ERROR[] = "cannot convert string from UTF-8 to UTF-16";
276 if (length == 0)
Victor Zverovichf4208772014-06-30 17:32:08 -0700277 throw WindowsError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700278 buffer_.resize(length);
279 length = MultiByteToWideChar(
280 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, &buffer_[0], length);
281 if (length == 0)
Victor Zverovichf4208772014-06-30 17:32:08 -0700282 throw WindowsError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700283}
284
285fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
286 if (int error_code = Convert(s)) {
Victor Zverovich8321d0e2014-07-09 08:39:01 -0700287 throw WindowsError(error_code,
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700288 "cannot convert string from UTF-16 to UTF-8");
289 }
290}
291
292int fmt::internal::UTF16ToUTF8::Convert(fmt::WStringRef s) {
293 int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, 0, 0, 0, 0);
294 if (length == 0)
295 return GetLastError();
296 buffer_.resize(length);
297 length = WideCharToMultiByte(
298 CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, 0, 0);
299 if (length == 0)
300 return GetLastError();
301 return 0;
302}
303
Victor Zverovich53201032014-06-30 14:26:29 -0700304void fmt::WindowsError::init(
305 int error_code, StringRef format_str, const ArgList &args) {
306 error_code_ = error_code;
307 Writer w;
308 internal::FormatWinErrorMessage(w, error_code, format(format_str, args));
309 std::runtime_error &base = *this;
310 base = std::runtime_error(w.str());
311}
312
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700313#endif
314
Victor Zverovich99e61122014-04-30 11:20:41 -0700315int fmt::internal::StrError(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700316 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT(true) {
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700317 assert(buffer != 0 && buffer_size != 0);
Victor Zverovich99e61122014-04-30 11:20:41 -0700318 int result = 0;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700319#ifdef _GNU_SOURCE
320 char *message = strerror_r(error_code, buffer, buffer_size);
Victor Zverovich99e61122014-04-30 11:20:41 -0700321 // If the buffer is full then the message is probably truncated.
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700322 if (message == buffer && strlen(buffer) == buffer_size - 1)
Victor Zverovich99e61122014-04-30 11:20:41 -0700323 result = ERANGE;
324 buffer = message;
Victor Zverovich9c47f3e2014-07-09 09:45:18 -0700325#elif __MINGW32__
326 errno = 0;
327 (void)buffer_size;
328 buffer = strerror(error_code);
329 result = errno;
330#elif _WIN32
Victor Zverovich99e61122014-04-30 11:20:41 -0700331 result = strerror_s(buffer, buffer_size, error_code);
332 // If the buffer is full then the message is probably truncated.
333 if (result == 0 && std::strlen(buffer) == buffer_size - 1)
334 result = ERANGE;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700335#else
Victor Zverovich99e61122014-04-30 11:20:41 -0700336 result = strerror_r(error_code, buffer, buffer_size);
337 if (result == -1)
338 result = errno; // glibc versions before 2.13 return result in errno.
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700339#endif
Victor Zverovich99e61122014-04-30 11:20:41 -0700340 return result;
Victor Zverovich859a4972014-04-30 06:55:21 -0700341}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700342
Victor Zverovich53b4c312014-04-30 15:00:41 -0700343void fmt::internal::FormatSystemErrorMessage(
344 fmt::Writer &out, int error_code, fmt::StringRef message) {
345 Array<char, INLINE_BUFFER_SIZE> buffer;
346 buffer.resize(INLINE_BUFFER_SIZE);
347 char *system_message = 0;
348 for (;;) {
349 system_message = &buffer[0];
350 int result = StrError(error_code, system_message, buffer.size());
351 if (result == 0)
352 break;
353 if (result != ERANGE) {
354 // Can't get error message, report error code instead.
355 out << message << ": error code = " << error_code;
356 return;
357 }
358 buffer.resize(buffer.size() * 2);
359 }
360 out << message << ": " << system_message;
361}
362
363#ifdef _WIN32
364void fmt::internal::FormatWinErrorMessage(
365 fmt::Writer &out, int error_code, fmt::StringRef message) {
366 class String {
367 private:
368 LPWSTR str_;
369
370 public:
371 String() : str_() {}
372 ~String() { LocalFree(str_); }
373 LPWSTR *ptr() { return &str_; }
374 LPCWSTR c_str() const { return str_; }
375 };
376 String system_message;
377 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
378 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
379 error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
380 reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
381 UTF16ToUTF8 utf8_message;
382 if (!utf8_message.Convert(system_message.c_str())) {
Victor Zverovicheb034a02014-06-30 17:40:53 -0700383 out << message << ": " << utf8_message;
Victor Zverovich53b4c312014-04-30 15:00:41 -0700384 return;
385 }
386 }
387 // Can't get error message, report error code instead.
388 out << message << ": error code = " << error_code;
389}
390#endif
391
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700392template <typename Char>
393void fmt::internal::FormatErrorReporter<Char>::operator()(
394 const Char *s, fmt::StringRef message) const {
Victor Zveroviche8251562014-07-08 16:20:33 -0700395 if (find_closing_brace(s, num_open_braces))
396 throw fmt::FormatError(message);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700397}
398
Victor Zverovich7cae7632013-09-06 20:23:42 -0700399// Fills the padding around the content and returns the pointer to the
400// content area.
401template <typename Char>
Victor Zverovich93e41252013-09-08 13:07:04 -0700402typename fmt::BasicWriter<Char>::CharPtr
403 fmt::BasicWriter<Char>::FillPadding(CharPtr buffer,
404 unsigned total_size, std::size_t content_size, wchar_t fill) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700405 std::size_t padding = total_size - content_size;
406 std::size_t left_padding = padding / 2;
Victor Zverovich563a5752013-09-08 13:47:06 -0700407 Char fill_char = static_cast<Char>(fill);
408 std::fill_n(buffer, left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700409 buffer += left_padding;
410 CharPtr content = buffer;
Victor Zverovich563a5752013-09-08 13:47:06 -0700411 std::fill_n(buffer + content_size, padding - left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700412 return content;
413}
414
415template <typename Char>
Victor Zverovich7cae7632013-09-06 20:23:42 -0700416template <typename T>
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700417void fmt::BasicWriter<Char>::FormatDouble(T value, const FormatSpec &spec) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700418 // Check type.
419 char type = spec.type();
420 bool upper = false;
421 switch (type) {
422 case 0:
423 type = 'g';
424 break;
Victor Zverovich03776dd2014-06-10 07:03:49 -0700425 case 'e': case 'f': case 'g': case 'a':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700426 break;
427 case 'F':
428#ifdef _MSC_VER
429 // MSVC's printf doesn't support 'F'.
430 type = 'f';
431#endif
432 // Fall through.
Victor Zverovich03776dd2014-06-10 07:03:49 -0700433 case 'E': case 'G': case 'A':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700434 upper = true;
435 break;
436 default:
437 internal::ReportUnknownType(type, "double");
438 break;
439 }
440
441 char sign = 0;
442 // Use SignBit instead of value < 0 because the latter is always
443 // false for NaN.
jdale88a9862fd2014-03-11 18:56:24 +0000444 if (SignBit(static_cast<double>(value))) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700445 sign = '-';
446 value = -value;
447 } else if (spec.sign_flag()) {
448 sign = spec.plus_flag() ? '+' : ' ';
449 }
450
451 if (value != value) {
452 // Format NaN ourselves because sprintf's output is not consistent
453 // across platforms.
454 std::size_t size = 4;
455 const char *nan = upper ? " NAN" : " nan";
456 if (!sign) {
457 --size;
458 ++nan;
459 }
Victor Zverovich53201032014-06-30 14:26:29 -0700460 CharPtr out = write_str(nan, size, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700461 if (sign)
462 *out = sign;
463 return;
464 }
465
jdale88a9862fd2014-03-11 18:56:24 +0000466 if (IsInf(static_cast<double>(value))) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700467 // Format infinity ourselves because sprintf's output is not consistent
468 // across platforms.
469 std::size_t size = 4;
470 const char *inf = upper ? " INF" : " inf";
471 if (!sign) {
472 --size;
473 ++inf;
474 }
Victor Zverovich53201032014-06-30 14:26:29 -0700475 CharPtr out = write_str(inf, size, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700476 if (sign)
477 *out = sign;
478 return;
479 }
480
481 std::size_t offset = buffer_.size();
482 unsigned width = spec.width();
483 if (sign) {
484 buffer_.reserve(buffer_.size() + (std::max)(width, 1u));
485 if (width > 0)
486 --width;
487 ++offset;
488 }
489
490 // Build format string.
491 enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg
492 Char format[MAX_FORMAT_SIZE];
493 Char *format_ptr = format;
494 *format_ptr++ = '%';
495 unsigned width_for_sprintf = width;
496 if (spec.hash_flag())
497 *format_ptr++ = '#';
498 if (spec.align() == ALIGN_CENTER) {
499 width_for_sprintf = 0;
500 } else {
501 if (spec.align() == ALIGN_LEFT)
502 *format_ptr++ = '-';
503 if (width != 0)
504 *format_ptr++ = '*';
505 }
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700506 if (spec.precision() >= 0) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700507 *format_ptr++ = '.';
508 *format_ptr++ = '*';
509 }
510 if (internal::IsLongDouble<T>::VALUE)
511 *format_ptr++ = 'L';
512 *format_ptr++ = type;
513 *format_ptr = '\0';
514
515 // Format using snprintf.
Victor Zverovich88972f42013-09-08 13:30:14 -0700516 Char fill = static_cast<Char>(spec.fill());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700517 for (;;) {
518 std::size_t size = buffer_.capacity() - offset;
Victor Zverovich33baa8f2014-04-23 18:37:08 -0700519#if _MSC_VER
520 // MSVC's vsnprintf_s doesn't work with zero size, so reserve
521 // space for at least one extra character to make the size non-zero.
522 // Note that the buffer's capacity will increase by more than 1.
523 if (size == 0) {
524 buffer_.reserve(offset + 1);
525 size = buffer_.capacity() - offset;
526 }
527#endif
Victor Zverovich7cae7632013-09-06 20:23:42 -0700528 Char *start = &buffer_[offset];
Victor Zverovichb605b392013-09-09 22:21:40 -0700529 int n = internal::CharTraits<Char>::FormatFloat(
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700530 start, size, format, width_for_sprintf, spec.precision(), value);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700531 if (n >= 0 && offset + n < buffer_.capacity()) {
532 if (sign) {
533 if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) ||
534 *start != ' ') {
535 *(start - 1) = sign;
536 sign = 0;
537 } else {
Victor Zverovich88972f42013-09-08 13:30:14 -0700538 *(start - 1) = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700539 }
540 ++n;
541 }
542 if (spec.align() == ALIGN_CENTER &&
543 spec.width() > static_cast<unsigned>(n)) {
544 unsigned width = spec.width();
545 CharPtr p = GrowBuffer(width);
546 std::copy(p, p + n, p + (width - n) / 2);
Victor Zverovich88972f42013-09-08 13:30:14 -0700547 FillPadding(p, spec.width(), n, fill);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700548 return;
549 }
550 if (spec.fill() != ' ' || sign) {
551 while (*start == ' ')
Victor Zverovich88972f42013-09-08 13:30:14 -0700552 *start++ = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700553 if (sign)
554 *(start - 1) = sign;
555 }
556 GrowBuffer(n);
557 return;
558 }
Victor Zverovichcfeba452014-04-23 18:37:49 -0700559 // If n is negative we ask to increase the capacity by at least 1,
560 // but as std::vector, the buffer grows exponentially.
561 buffer_.reserve(n >= 0 ? offset + n + 1 : buffer_.capacity() + 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700562 }
563}
564
Victor Zverovich7cae7632013-09-06 20:23:42 -0700565template <typename Char>
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700566template <typename StringChar>
Victor Zverovich53201032014-06-30 14:26:29 -0700567void fmt::BasicWriter<Char>::write_str(
Victor Zverovich537c6c42014-07-01 06:21:51 -0700568 const internal::StringValue<StringChar> &str, const FormatSpec &spec) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700569 if (spec.type_ && spec.type_ != 's')
570 internal::ReportUnknownType(spec.type_, "string");
571 const StringChar *s = str.value;
572 std::size_t size = str.size;
573 if (size == 0) {
574 if (!s)
575 throw FormatError("string pointer is null");
576 if (*s)
577 size = std::char_traits<StringChar>::length(s);
578 }
Victor Zverovich53201032014-06-30 14:26:29 -0700579 write_str(s, size, spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700580}
581
582template <typename Char>
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700583inline const Arg
Victor Zverovichb9a06ba2014-07-08 16:38:50 -0700584 &fmt::BasicFormatter<Char>::ParseArgIndex(const Char *&s) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700585 unsigned arg_index = 0;
586 if (*s < '0' || *s > '9') {
587 if (*s != '}' && *s != ':')
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700588 report_error_(s, "invalid argument index in format string");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700589 if (next_arg_index_ < 0) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700590 report_error_(s,
Victor Zverovich7cae7632013-09-06 20:23:42 -0700591 "cannot switch from manual to automatic argument indexing");
592 }
593 arg_index = next_arg_index_++;
594 } else {
595 if (next_arg_index_ > 0) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700596 report_error_(s,
Victor Zverovich7cae7632013-09-06 20:23:42 -0700597 "cannot switch from automatic to manual argument indexing");
598 }
599 next_arg_index_ = -1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700600 const char *error = 0;
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700601 arg_index = ParseNonnegativeInt(s, error);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700602 if (error)
603 report_error_(s, error); // TODO
Victor Zverovich7cae7632013-09-06 20:23:42 -0700604 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700605 if (arg_index >= args_.size())
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700606 report_error_(s, "argument index is out of range in format");
Victor Zverovich656a8372014-04-22 08:58:54 -0700607 return args_[arg_index];
Victor Zverovich7cae7632013-09-06 20:23:42 -0700608}
609
610template <typename Char>
Victor Zverovichb9a06ba2014-07-08 16:38:50 -0700611void fmt::BasicFormatter<Char>::CheckSign(
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700612 const Char *&s, const Arg &arg) {
Victor Zverovichcc6af502013-12-10 08:01:08 -0800613 char sign = static_cast<char>(*s);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700614 if (arg.type > Arg::LAST_NUMERIC_TYPE) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700615 report_error_(s,
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700616 fmt::format("format specifier '{}' requires numeric argument", sign).c_str());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700617 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700618 if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700619 report_error_(s,
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700620 fmt::format("format specifier '{}' requires signed argument", sign).c_str());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700621 }
622 ++s;
623}
624
625template <typename Char>
Victor Zverovichd29e5052014-06-30 07:12:09 -0700626void fmt::internal::PrintfParser<Char>::ParseFlags(
Victor Zverovichcb743c02014-06-19 07:40:35 -0700627 FormatSpec &spec, const Char *&s) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700628 for (;;) {
Victor Zverovich1b801482014-06-07 08:57:55 -0700629 switch (*s++) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700630 case '-':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700631 spec.align_ = ALIGN_LEFT;
632 break;
633 case '+':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700634 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
635 break;
636 case '0':
637 spec.fill_ = '0';
Victor Zverovich1b801482014-06-07 08:57:55 -0700638 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700639 case ' ':
Victor Zverovich1b801482014-06-07 08:57:55 -0700640 spec.flags_ |= SIGN_FLAG;
641 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700642 case '#':
Victor Zverovichcb743c02014-06-19 07:40:35 -0700643 spec.flags_ |= HASH_FLAG;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700644 break;
645 default:
Victor Zverovich1b801482014-06-07 08:57:55 -0700646 --s;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700647 return;
648 }
649 }
650}
651
Victor Zverovichcb743c02014-06-19 07:40:35 -0700652template <typename Char>
Victor Zverovichd29e5052014-06-30 07:12:09 -0700653unsigned fmt::internal::PrintfParser<Char>::ParseHeader(
Victor Zverovichcb743c02014-06-19 07:40:35 -0700654 const Char *&s, FormatSpec &spec, const char *&error) {
655 unsigned arg_index = UINT_MAX;
656 Char c = *s;
657 if (c >= '0' && c <= '9') {
658 // Parse an argument index (if followed by '$') or a width possibly
Victor Zverovich879838a2014-06-20 07:34:02 -0700659 // preceded with '0' flag(s).
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700660 unsigned value = ParseNonnegativeInt(s, error);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700661 if (*s == '$') { // value is an argument index
662 ++s;
663 arg_index = value;
664 } else {
665 if (c == '0')
666 spec.fill_ = '0';
667 if (value != 0) {
668 // Nonzero value means that we parsed width and don't need to
669 // parse it or flags again, so return now.
670 spec.width_ = value;
671 return arg_index;
672 }
673 }
674 }
Victor Zverovichcb743c02014-06-19 07:40:35 -0700675 ParseFlags(spec, s);
Victor Zverovich4099a122014-06-23 08:10:50 -0700676 // Parse width.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700677 if (*s >= '0' && *s <= '9') {
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700678 spec.width_ = ParseNonnegativeInt(s, error);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700679 } else if (*s == '*') {
680 ++s;
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700681 ULongLong width = WidthHandler(spec).visit(HandleArgIndex(UINT_MAX, error));
Victor Zverovich4099a122014-06-23 08:10:50 -0700682 if (width <= INT_MAX)
683 spec.width_ = static_cast<unsigned>(width);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700684 else if (!error)
Victor Zverovich4099a122014-06-23 08:10:50 -0700685 error = "number is too big in format";
Victor Zverovichcb743c02014-06-19 07:40:35 -0700686 }
687 return arg_index;
688}
689
Victor Zverovich879838a2014-06-20 07:34:02 -0700690// TODO: move to a base class that doesn't depend on template argument
Victor Zverovichbf790d22014-06-07 07:31:25 -0700691template <typename Char>
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700692const Arg &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') {
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700753 spec.precision_ = ParseNonnegativeInt(s, error);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700754 } 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 Zverovicheb034a02014-06-30 17:40:53 -0700758 spec.precision_ = static_cast<int>(GetIntValue(arg)); // TODO: check for overflow
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700759 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 Zverovichcff1c792014-07-01 06:27:15 -0700843 writer.write_str(internal::CharTraits<Char>::convert(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 Zveroviche8251562014-07-08 16:20:33 -0700855 arg.custom.format(&writer, arg.custom.value, "s");
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>
Victor Zverovichb9a06ba2014-07-08 16:38:50 -0700866const Char *fmt::BasicFormatter<Char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -0700867 const Char *format_str, const internal::Arg &arg) {
868 const Char *s = format_str;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700869 const char *error = 0;
Victor Zveroviche8251562014-07-08 16:20:33 -0700870 FormatSpec spec;
871 if (*s == ':') {
872 if (arg.type == Arg::CUSTOM) {
873 arg.custom.format(this, arg.custom.value, s);
874 return find_closing_brace(s) + 1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700875 }
Victor Zveroviche8251562014-07-08 16:20:33 -0700876 ++s;
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) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700883 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;
Victor Zveroviche8251562014-07-08 16:20:33 -0700895 }
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;
904 if (spec.align_ == ALIGN_NUMERIC && arg.type > Arg::LAST_NUMERIC_TYPE)
905 report_error_(s, "format specifier '=' requires numeric argument");
906 break;
907 }
908 } while (--p >= s);
909 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700910
Victor Zveroviche8251562014-07-08 16:20:33 -0700911 // Parse sign.
912 switch (*s) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700913 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;
Victor Zveroviche8251562014-07-08 16:20:33 -0700924 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700925
Victor Zveroviche8251562014-07-08 16:20:33 -0700926 if (*s == '#') {
927 if (arg.type > Arg::LAST_NUMERIC_TYPE)
928 report_error_(s, "format specifier '#' requires numeric argument");
929 spec.flags_ |= HASH_FLAG;
930 ++s;
931 }
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 Zveroviche8251562014-07-08 16:20:33 -0700937 report_error_(s, "format specifier '0' requires numeric argument");
938 spec.align_ = ALIGN_NUMERIC;
939 spec.fill_ = '0';
Victor Zverovich7cae7632013-09-06 20:23:42 -0700940 }
Victor Zveroviche8251562014-07-08 16:20:33 -0700941 // 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.
943 spec.width_ = ParseNonnegativeInt(s, error);
944 if (error)
945 report_error_(s, error);
946 }
Victor Zverovich7cae7632013-09-06 20:23:42 -0700947
Victor Zveroviche8251562014-07-08 16:20:33 -0700948 // Parse precision.
949 if (*s == '.') {
950 ++s;
951 spec.precision_ = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700952 if ('0' <= *s && *s <= '9') {
Victor Zveroviche8251562014-07-08 16:20:33 -0700953 spec.precision_ = ParseNonnegativeInt(s, error);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700954 if (error)
955 report_error_(s, error);
Victor Zveroviche8251562014-07-08 16:20:33 -0700956 } else if (*s == '{') {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700957 ++s;
Victor Zveroviche8251562014-07-08 16:20:33 -0700958 ++report_error_.num_open_braces;
959 const Arg &precision_arg = ParseArgIndex(s);
960 ULongLong value = 0;
961 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 }
Victor Zveroviche8251562014-07-08 16:20:33 -0700981 if (value > INT_MAX)
982 report_error_(s, "number is too big in format");
983 spec.precision_ = static_cast<int>(value);
984 if (*s++ != '}')
985 throw FormatError("unmatched '{' in format");
986 --report_error_.num_open_braces;
987 } else {
988 report_error_(s, "missing precision in format");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700989 }
Victor Zveroviche8251562014-07-08 16:20:33 -0700990 if (arg.type != Arg::DOUBLE && arg.type != Arg::LONG_DOUBLE) {
991 report_error_(s,
992 "precision specifier requires floating-point argument");
993 }
Victor Zverovich7cae7632013-09-06 20:23:42 -0700994 }
995
Victor Zveroviche8251562014-07-08 16:20:33 -0700996 // Parse type.
997 if (*s != '}' && *s)
998 spec.type_ = static_cast<char>(*s++);
999 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001000
Victor Zveroviche8251562014-07-08 16:20:33 -07001001 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 Zveroviche8251562014-07-08 16:20:33 -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 Zveroviche8251562014-07-08 16:20:33 -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 Zveroviche8251562014-07-08 16:20:33 -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 Zveroviche8251562014-07-08 16:20:33 -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 Zveroviche8251562014-07-08 16:20:33 -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 Zveroviche8251562014-07-08 16:20:33 -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 Zveroviche8251562014-07-08 16:20:33 -07001032 out = writer_.GrowBuffer(spec.width_);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001033 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 Zveroviche8251562014-07-08 16:20:33 -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 {
Victor Zveroviche8251562014-07-08 16:20:33 -07001042 out = writer_.GrowBuffer(1);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001043 }
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:
Victor Zveroviche8251562014-07-08 16:20:33 -07001048 writer_.write_str(arg.string, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001049 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001050 case Arg::WSTRING:
Victor Zveroviche8251562014-07-08 16:20:33 -07001051 writer_.write_str(internal::CharTraits<Char>::convert(arg.wstring), spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001052 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 Zveroviche8251562014-07-08 16:20:33 -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 Zveroviche8251562014-07-08 16:20:33 -07001061 arg.custom.format(this, arg.custom.value, s - 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001062 break;
1063 default:
1064 assert(false);
1065 break;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001066 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001067 return s;
1068}
1069
1070template <typename Char>
Victor Zverovichb9a06ba2014-07-08 16:38:50 -07001071void fmt::BasicFormatter<Char>::Format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001072 BasicStringRef<Char> format_str, const ArgList &args) {
1073 const Char *s = start_ = format_str.c_str();
1074 args_ = args;
1075 next_arg_index_ = 0;
1076 while (*s) {
1077 Char c = *s++;
1078 if (c != '{' && c != '}') continue;
1079 if (*s == c) {
1080 writer_.buffer_.append(start_, s);
1081 start_ = ++s;
1082 continue;
1083 }
1084 if (c == '}')
1085 throw FormatError("unmatched '}' in format");
1086 report_error_.num_open_braces = 1;
1087 writer_.buffer_.append(start_, s - 1);
1088 Arg arg = ParseArgIndex(s);
1089 s = format(s, arg);
1090 }
1091 writer_.buffer_.append(start_, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001092}
1093
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001094void fmt::ReportSystemError(
1095 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
1096 // FIXME: FormatSystemErrorMessage may throw
1097 ReportError(internal::FormatSystemErrorMessage, error_code, message);
1098}
1099
Victor Zverovich400812a2014-04-30 12:38:17 -07001100#ifdef _WIN32
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001101void fmt::ReportWinError(
1102 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
1103 // FIXME: FormatWinErrorMessage may throw
1104 ReportError(internal::FormatWinErrorMessage, error_code, message);
1105}
Victor Zverovich400812a2014-04-30 12:38:17 -07001106#endif
Victor Zverovichf7939862014-04-30 10:18:11 -07001107
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
Victor Zveroviche3a44c12014-07-09 06:56:36 -07001120void fmt::print(std::ostream &os, StringRef format, const ArgList &args) {
1121 Writer w;
1122 w.write(format, args);
1123 os.write(w.data(), w.size());
1124}
1125
Victor Zverovich2dc108b2014-07-01 09:10:43 -07001126void fmt::print_colored(Color c, StringRef format, const ArgList &args) {
1127 char escape[] = "\x1b[30m";
1128 escape[3] = '0' + static_cast<char>(c);
1129 std::fputs(escape, stdout);
1130 print(format, args);
1131 std::fputs(RESET_COLOR, stdout);
1132}
1133
Victor Zverovichd5b81962014-06-28 21:56:40 -07001134void fmt::printf(StringRef format, const ArgList &args) {
1135 Writer w;
Victor Zverovich21111cc2014-06-29 19:52:26 -07001136 printf(w, format, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001137 std::fwrite(w.data(), 1, w.size(), stdout);
1138}
1139
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001140// Explicit instantiations for char.
1141
Victor Zverovich93e41252013-09-08 13:07:04 -07001142template fmt::BasicWriter<char>::CharPtr
1143 fmt::BasicWriter<char>::FillPadding(CharPtr buffer,
1144 unsigned total_size, std::size_t content_size, wchar_t fill);
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001145
Victor Zverovichb9a06ba2014-07-08 16:38:50 -07001146template void fmt::BasicFormatter<char>::Format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001147 BasicStringRef<char> format, const ArgList &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001148
Victor Zverovichd29e5052014-06-30 07:12:09 -07001149template void fmt::internal::PrintfParser<char>::Format(
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001150 BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001151
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001152// Explicit instantiations for wchar_t.
1153
Victor Zverovich7cae7632013-09-06 20:23:42 -07001154template fmt::BasicWriter<wchar_t>::CharPtr
Victor Zverovich93e41252013-09-08 13:07:04 -07001155 fmt::BasicWriter<wchar_t>::FillPadding(CharPtr buffer,
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001156 unsigned total_size, std::size_t content_size, wchar_t fill);
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001157
Victor Zverovichb9a06ba2014-07-08 16:38:50 -07001158template void fmt::BasicFormatter<wchar_t>::Format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001159 BasicStringRef<wchar_t> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001160
Victor Zverovichd29e5052014-06-30 07:12:09 -07001161template void fmt::internal::PrintfParser<wchar_t>::Format(
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001162 BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001163 const ArgList &args);
jdale88a9862fd2014-03-11 18:56:24 +00001164
1165#if _MSC_VER
1166# pragma warning(pop)
1167#endif