blob: 68c58b61eac037cfdb8f70c0a860b2fc1ea52fc0 [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
Victor Zverovichbe785a82014-07-29 09:14:07 -070066// Portable version of signbit.
Victor Zverovichd8b9f412014-07-29 06:38:05 -070067// 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 Zverovichbe785a82014-07-29 09:14:07 -070069inline int getsign(double x) {
70#ifdef signbit
71 return signbit(x);
72#else
73 return std::signbit(x);
Victor Zverovichf2e06802014-04-10 10:49:55 -070074#endif
Victor Zverovichbe785a82014-07-29 09:14:07 -070075}
Victor Zverovich9ff3b972013-09-07 10:15:08 -070076
Victor Zverovich24d6baa2014-07-29 07:49:34 -070077// Portable version of isinf.
Victor Zverovichbf5b2462014-07-29 08:22:52 -070078inline int isinfinity(double x) {
Victor Zverovich24d6baa2014-07-29 07:49:34 -070079#ifdef isinf
80 return isinf(x);
81#else
82 return std::isinf(x);
Victor Zverovich9ff3b972013-09-07 10:15:08 -070083#endif
Victor Zverovich24d6baa2014-07-29 07:49:34 -070084}
Victor Zverovich9ff3b972013-09-07 10:15:08 -070085
Victor Zverovich1a0c76a2014-08-13 07:51:02 -070086inline int isinfinity(long double x) {
87#ifdef isinf
88 return isinf(x);
89#else
90 return std::isinf(x);
91#endif
92}
93
Victor Zverovich9ff3b972013-09-07 10:15:08 -070094#define FMT_SNPRINTF snprintf
95
Victor Zverovicha684d0c2013-12-27 08:00:10 -080096#else // _MSC_VER
Victor Zverovich9ff3b972013-09-07 10:15:08 -070097
Victor Zverovichbe785a82014-07-29 09:14:07 -070098inline int getsign(double value) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -070099 if (value < 0) return 1;
100 if (value == value) return 0;
101 int dec = 0, sign = 0;
102 char buffer[2]; // The buffer size must be >= 2 or _ecvt_s will fail.
103 _ecvt_s(buffer, sizeof(buffer), value, 0, &dec, &sign);
104 return sign;
105}
106
Victor Zverovichbf5b2462014-07-29 08:22:52 -0700107inline int isinfinity(double x) { return !_finite(x); }
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700108
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700109inline int safe_printf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -0800110 va_list args;
111 va_start(args, format);
112 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
113 va_end(args);
114 return result;
115}
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700116#define FMT_SNPRINTF safe_printf
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700117
118#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -0800119
120const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700121
122typedef void (*FormatFunc)(fmt::Writer &, int , fmt::StringRef);
123
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700124void report_error(FormatFunc func,
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700125 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
126 try {
127 fmt::Writer full_message;
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700128 func(full_message, error_code, message); // TODO: make sure this doesn't throw
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700129 std::fwrite(full_message.c_str(), full_message.size(), 1, stderr);
130 std::fputc('\n', stderr);
131 } catch (...) {}
Victor Zverovichb605b392013-09-09 22:21:40 -0700132}
Victor Zverovichd29e5052014-06-30 07:12:09 -0700133
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700134const Arg DUMMY_ARG = {Arg::INT, 0};
Victor Zverovichd29e5052014-06-30 07:12:09 -0700135
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700136// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
137class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> {
138 public:
139 template <typename T>
140 bool visit_any_int(T value) { return value == 0; }
141};
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700142
143// Parses an unsigned integer advancing s to the end of the parsed input.
144// This function assumes that the first character of s is a digit.
145template <typename Char>
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700146int parse_nonnegative_int(
147 const Char *&s, const char *&error) FMT_NOEXCEPT(true) {
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700148 assert('0' <= *s && *s <= '9');
149 unsigned value = 0;
150 do {
151 unsigned new_value = value * 10 + (*s++ - '0');
152 // Check if value wrapped around.
153 value = new_value >= value ? new_value : UINT_MAX;
154 } while ('0' <= *s && *s <= '9');
155 if (value > INT_MAX) {
156 if (!error)
157 error = "number is too big in format";
158 return 0;
159 }
160 return value;
161}
Victor Zveroviche8251562014-07-08 16:20:33 -0700162
163template <typename Char>
164const Char *find_closing_brace(const Char *s, int num_open_braces = 1) {
165 for (int n = num_open_braces; *s; ++s) {
166 if (*s == '{') {
167 ++n;
168 } else if (*s == '}') {
169 if (--n == 0)
170 return s;
171 }
172 }
173 throw fmt::FormatError("unmatched '{' in format");
174}
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700175
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700176// Checks if an argument is a valid printf width specifier and sets
177// left alignment if it is negative.
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700178class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700179 private:
180 fmt::FormatSpec &spec_;
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700181
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700182 public:
183 explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700184
Victor Zverovich9d74f952014-07-16 07:27:54 -0700185 unsigned visit_unhandled_arg() {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700186 throw fmt::FormatError("width is not integer");
187 }
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700188
Victor Zverovich9d74f952014-07-16 07:27:54 -0700189 template <typename T>
190 unsigned visit_any_int(T value) {
191 typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType;
192 UnsignedType width = value;
193 if (fmt::internal::is_negative(value)) {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700194 spec_.align_ = fmt::ALIGN_LEFT;
195 width = 0 - width;
196 }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700197 if (width > INT_MAX)
198 throw fmt::FormatError("number is too big in format");
199 return static_cast<unsigned>(width);
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700200 }
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700201};
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700202
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700203class PrecisionHandler :
204 public fmt::internal::ArgVisitor<PrecisionHandler, int> {
205 public:
206 unsigned visit_unhandled_arg() {
207 throw fmt::FormatError("precision is not integer");
208 }
209
210 template <typename T>
211 int visit_any_int(T value) {
212 if (value < INT_MIN || value > INT_MAX)
213 throw fmt::FormatError("number is too big in format");
214 return static_cast<int>(value);
215 }
216};
217
Victor Zverovicheeca2232014-07-30 07:37:16 -0700218// Converts an integer argument to type T.
219template <typename T>
220class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
221 private:
222 fmt::internal::Arg &arg_;
Victor Zveroviche22d6572014-08-08 06:51:09 -0700223 wchar_t type_;
Victor Zverovicheeca2232014-07-30 07:37:16 -0700224
225 public:
Victor Zveroviche22d6572014-08-08 06:51:09 -0700226 ArgConverter(fmt::internal::Arg &arg, wchar_t type)
227 : arg_(arg), type_(type) {}
Victor Zverovicheeca2232014-07-30 07:37:16 -0700228
229 template <typename U>
230 void visit_any_int(U value) {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700231 bool is_signed = type_ == 'd' || type_ == 'i';
232 using fmt::internal::Arg;
233 if (sizeof(T) <= sizeof(int)) {
234 if (is_signed) {
235 arg_.type = Arg::INT;
236 arg_.int_value = static_cast<T>(value);
237 } else {
238 arg_.type = Arg::UINT;
239 arg_.uint_value =
240 static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value);
241 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700242 } else {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700243 if (is_signed) {
244 arg_.type = Arg::LONG_LONG;
Victor Zverovicha259c942014-08-01 07:15:27 -0700245 arg_.long_long_value =
246 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700247 } else {
248 arg_.type = Arg::ULONG_LONG;
249 arg_.ulong_long_value =
Victor Zverovicha259c942014-08-01 07:15:27 -0700250 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700251 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700252 }
253 }
254};
255
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700256// This function template is used to prevent compile errors when handling
257// incompatible string arguments, e.g. handling a wide string in a narrow
258// string formatter.
259template <typename Char>
260Arg::StringValue<Char> ignore_incompatible_str(Arg::StringValue<wchar_t>);
261
262template <>
263inline Arg::StringValue<char> ignore_incompatible_str(
264 Arg::StringValue<wchar_t>) { return Arg::StringValue<char>(); }
265
266template <>
267inline Arg::StringValue<wchar_t> ignore_incompatible_str(
268 Arg::StringValue<wchar_t> s) { return s; }
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700269} // namespace
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700270
Victor Zverovichbe785a82014-07-29 09:14:07 -0700271int fmt::internal::signbit_noinline(double value) { return getsign(value); }
Victor Zverovich302b8f42014-06-24 10:46:01 -0700272
Victor Zverovich53201032014-06-30 14:26:29 -0700273void fmt::SystemError::init(
274 int error_code, StringRef format_str, const ArgList &args) {
275 error_code_ = error_code;
276 Writer w;
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700277 internal::format_system_error(w, error_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700278 std::runtime_error &base = *this;
279 base = std::runtime_error(w.str());
280}
281
Victor Zverovichb605b392013-09-09 22:21:40 -0700282template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700283int fmt::internal::CharTraits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700284 char *buffer, std::size_t size, const char *format,
285 unsigned width, int precision, T value) {
286 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700287 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700288 FMT_SNPRINTF(buffer, size, format, value) :
289 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700290 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700291 return precision < 0 ?
292 FMT_SNPRINTF(buffer, size, format, width, value) :
293 FMT_SNPRINTF(buffer, size, format, width, precision, value);
294}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700295
Victor Zverovichb605b392013-09-09 22:21:40 -0700296template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700297int fmt::internal::CharTraits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700298 wchar_t *buffer, std::size_t size, const wchar_t *format,
299 unsigned width, int precision, T value) {
300 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700301 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700302 swprintf(buffer, size, format, value) :
303 swprintf(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700304 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700305 return precision < 0 ?
306 swprintf(buffer, size, format, width, value) :
307 swprintf(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700308}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800309
Victor Zverovich65d47e52013-09-09 06:51:03 -0700310const char fmt::internal::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800311 "0001020304050607080910111213141516171819"
312 "2021222324252627282930313233343536373839"
313 "4041424344454647484950515253545556575859"
314 "6061626364656667686970717273747576777879"
315 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800316
Victor Zverovichf1d85162014-02-19 13:02:22 -0800317#define FMT_POWERS_OF_10(factor) \
318 factor * 10, \
319 factor * 100, \
320 factor * 1000, \
321 factor * 10000, \
322 factor * 100000, \
323 factor * 1000000, \
324 factor * 10000000, \
325 factor * 100000000, \
326 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800327
Victor Zverovichf1d85162014-02-19 13:02:22 -0800328const uint32_t fmt::internal::POWERS_OF_10_32[] = {0, FMT_POWERS_OF_10(1)};
Victor Zveroviche9b21912014-02-19 12:43:55 -0800329const uint64_t fmt::internal::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800330 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800331 FMT_POWERS_OF_10(1),
332 FMT_POWERS_OF_10(ULongLong(1000000000)),
333 // Multiply several constants instead of using a single long long constants
334 // to avoid warnings about C++98 not supporting long long.
Victor Zverovich6f6fe512014-02-15 11:16:44 -0800335 ULongLong(1000000000) * ULongLong(1000000000) * 10
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800336};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800337
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700338void fmt::internal::report_unknown_type(char code, const char *type) {
Victor Zverovich877abaf2013-01-08 09:56:05 -0800339 if (std::isprint(static_cast<unsigned char>(code))) {
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700340 throw fmt::FormatError(
341 fmt::format("unknown format code '{}' for {}", code, type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800342 }
343 throw fmt::FormatError(
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700344 fmt::format("unknown format code '\\x{:02x}' for {}",
345 static_cast<unsigned>(code), type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800346}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700347
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700348#ifdef _WIN32
349
350fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
351 int length = MultiByteToWideChar(
352 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, 0, 0);
353 static const char ERROR[] = "cannot convert string from UTF-8 to UTF-16";
354 if (length == 0)
Victor Zverovichf4208772014-06-30 17:32:08 -0700355 throw WindowsError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700356 buffer_.resize(length);
357 length = MultiByteToWideChar(
358 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, &buffer_[0], length);
359 if (length == 0)
Victor Zverovichf4208772014-06-30 17:32:08 -0700360 throw WindowsError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700361}
362
363fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700364 if (int error_code = convert(s)) {
Victor Zverovich8321d0e2014-07-09 08:39:01 -0700365 throw WindowsError(error_code,
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700366 "cannot convert string from UTF-16 to UTF-8");
367 }
368}
369
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700370int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700371 int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, 0, 0, 0, 0);
372 if (length == 0)
373 return GetLastError();
374 buffer_.resize(length);
375 length = WideCharToMultiByte(
376 CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, 0, 0);
377 if (length == 0)
378 return GetLastError();
379 return 0;
380}
381
Victor Zverovich53201032014-06-30 14:26:29 -0700382void fmt::WindowsError::init(
383 int error_code, StringRef format_str, const ArgList &args) {
384 error_code_ = error_code;
385 Writer w;
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700386 internal::format_windows_error(w, error_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700387 std::runtime_error &base = *this;
388 base = std::runtime_error(w.str());
389}
390
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700391#endif
392
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700393int fmt::internal::safe_strerror(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700394 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT(true) {
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700395 assert(buffer != 0 && buffer_size != 0);
Victor Zverovich99e61122014-04-30 11:20:41 -0700396 int result = 0;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700397#ifdef _GNU_SOURCE
398 char *message = strerror_r(error_code, buffer, buffer_size);
Victor Zverovich99e61122014-04-30 11:20:41 -0700399 // If the buffer is full then the message is probably truncated.
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700400 if (message == buffer && strlen(buffer) == buffer_size - 1)
Victor Zverovich99e61122014-04-30 11:20:41 -0700401 result = ERANGE;
402 buffer = message;
Victor Zverovich9c47f3e2014-07-09 09:45:18 -0700403#elif __MINGW32__
404 errno = 0;
405 (void)buffer_size;
406 buffer = strerror(error_code);
407 result = errno;
408#elif _WIN32
Victor Zverovich99e61122014-04-30 11:20:41 -0700409 result = strerror_s(buffer, buffer_size, error_code);
410 // If the buffer is full then the message is probably truncated.
411 if (result == 0 && std::strlen(buffer) == buffer_size - 1)
412 result = ERANGE;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700413#else
Victor Zverovich99e61122014-04-30 11:20:41 -0700414 result = strerror_r(error_code, buffer, buffer_size);
415 if (result == -1)
416 result = errno; // glibc versions before 2.13 return result in errno.
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700417#endif
Victor Zverovich99e61122014-04-30 11:20:41 -0700418 return result;
Victor Zverovich859a4972014-04-30 06:55:21 -0700419}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700420
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700421void fmt::internal::format_system_error(
Victor Zverovich53b4c312014-04-30 15:00:41 -0700422 fmt::Writer &out, int error_code, fmt::StringRef message) {
423 Array<char, INLINE_BUFFER_SIZE> buffer;
424 buffer.resize(INLINE_BUFFER_SIZE);
425 char *system_message = 0;
426 for (;;) {
427 system_message = &buffer[0];
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700428 int result = safe_strerror(error_code, system_message, buffer.size());
Victor Zverovich53b4c312014-04-30 15:00:41 -0700429 if (result == 0)
430 break;
431 if (result != ERANGE) {
432 // Can't get error message, report error code instead.
433 out << message << ": error code = " << error_code;
434 return;
435 }
436 buffer.resize(buffer.size() * 2);
437 }
438 out << message << ": " << system_message;
439}
440
441#ifdef _WIN32
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700442void fmt::internal::format_windows_error(
Victor Zverovich53b4c312014-04-30 15:00:41 -0700443 fmt::Writer &out, int error_code, fmt::StringRef message) {
444 class String {
445 private:
446 LPWSTR str_;
447
448 public:
449 String() : str_() {}
450 ~String() { LocalFree(str_); }
451 LPWSTR *ptr() { return &str_; }
452 LPCWSTR c_str() const { return str_; }
453 };
454 String system_message;
455 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
456 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
457 error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
458 reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
459 UTF16ToUTF8 utf8_message;
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700460 if (!utf8_message.convert(system_message.c_str())) {
Victor Zverovicheb034a02014-06-30 17:40:53 -0700461 out << message << ": " << utf8_message;
Victor Zverovich53b4c312014-04-30 15:00:41 -0700462 return;
463 }
464 }
465 // Can't get error message, report error code instead.
466 out << message << ": error code = " << error_code;
467}
468#endif
469
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700470// An argument formatter.
471template <typename Char>
472class fmt::internal::ArgFormatter :
473 public fmt::internal::ArgVisitor<fmt::internal::ArgFormatter<Char>, void> {
474 private:
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700475 fmt::BasicFormatter<Char> &formatter_;
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700476 fmt::BasicWriter<Char> &writer_;
477 fmt::FormatSpec &spec_;
478 const Char *format_;
479
480 public:
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700481 ArgFormatter(
482 fmt::BasicFormatter<Char> &f,fmt::FormatSpec &s, const Char *fmt)
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700483 : formatter_(f), writer_(f.writer()), spec_(s), format_(fmt) {}
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700484
Victor Zverovich9d74f952014-07-16 07:27:54 -0700485 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700486 void visit_any_int(T value) { writer_.write_int(value, spec_); }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700487
488 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700489 void visit_any_double(T value) { writer_.write_double(value, spec_); }
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700490
491 void visit_char(int value) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700492 if (spec_.type_ && spec_.type_ != 'c') {
Victor Zverovichd699c2a2014-07-25 08:24:27 -0700493 spec_.flags_ |= CHAR_FLAG;
494 writer_.write_int(value, spec_);
495 return;
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700496 }
497 if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
498 throw FormatError("invalid format specifier for char");
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700499 typedef typename fmt::BasicWriter<Char>::CharPtr CharPtr;
500 CharPtr out = CharPtr();
501 if (spec_.width_ > 1) {
502 Char fill = static_cast<Char>(spec_.fill());
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700503 out = writer_.grow_buffer(spec_.width_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700504 if (spec_.align_ == fmt::ALIGN_RIGHT) {
505 std::fill_n(out, spec_.width_ - 1, fill);
506 out += spec_.width_ - 1;
507 } else if (spec_.align_ == fmt::ALIGN_CENTER) {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700508 out = writer_.fill_padding(out, spec_.width_, 1, fill);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700509 } else {
510 std::fill_n(out + 1, spec_.width_ - 1, fill);
511 }
512 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700513 out = writer_.grow_buffer(1);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700514 }
515 *out = static_cast<Char>(value);
516 }
517
518 void visit_string(Arg::StringValue<char> value) {
519 writer_.write_str(value, spec_);
520 }
521 void visit_wstring(Arg::StringValue<wchar_t> value) {
522 writer_.write_str(ignore_incompatible_str<Char>(value), spec_);
523 }
524
525 void visit_pointer(const void *value) {
526 if (spec_.type_ && spec_.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700527 fmt::internal::report_unknown_type(spec_.type_, "pointer");
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700528 spec_.flags_ = fmt::HASH_FLAG;
529 spec_.type_ = 'x';
Victor Zverovichc1db2932014-07-24 08:53:27 -0700530 writer_.write_int(reinterpret_cast<uintptr_t>(value), spec_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700531 }
532
533 void visit_custom(Arg::CustomValue c) {
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700534 c.format(&formatter_, c.value, format_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700535 }
536};
537
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700538template <typename Char>
539void fmt::internal::FormatErrorReporter<Char>::operator()(
540 const Char *s, fmt::StringRef message) const {
Victor Zveroviche8251562014-07-08 16:20:33 -0700541 if (find_closing_brace(s, num_open_braces))
542 throw fmt::FormatError(message);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700543}
544
Victor Zverovich7cae7632013-09-06 20:23:42 -0700545// Fills the padding around the content and returns the pointer to the
546// content area.
547template <typename Char>
Victor Zverovich93e41252013-09-08 13:07:04 -0700548typename fmt::BasicWriter<Char>::CharPtr
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700549 fmt::BasicWriter<Char>::fill_padding(CharPtr buffer,
Victor Zverovich93e41252013-09-08 13:07:04 -0700550 unsigned total_size, std::size_t content_size, wchar_t fill) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700551 std::size_t padding = total_size - content_size;
552 std::size_t left_padding = padding / 2;
Victor Zverovich563a5752013-09-08 13:47:06 -0700553 Char fill_char = static_cast<Char>(fill);
554 std::fill_n(buffer, left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700555 buffer += left_padding;
556 CharPtr content = buffer;
Victor Zverovich563a5752013-09-08 13:47:06 -0700557 std::fill_n(buffer + content_size, padding - left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700558 return content;
559}
560
561template <typename Char>
Victor Zverovich7cae7632013-09-06 20:23:42 -0700562template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700563void fmt::BasicWriter<Char>::write_double(T value, const FormatSpec &spec) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700564 // Check type.
565 char type = spec.type();
566 bool upper = false;
567 switch (type) {
568 case 0:
569 type = 'g';
570 break;
Victor Zverovich03776dd2014-06-10 07:03:49 -0700571 case 'e': case 'f': case 'g': case 'a':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700572 break;
573 case 'F':
574#ifdef _MSC_VER
575 // MSVC's printf doesn't support 'F'.
576 type = 'f';
577#endif
578 // Fall through.
Victor Zverovich03776dd2014-06-10 07:03:49 -0700579 case 'E': case 'G': case 'A':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700580 upper = true;
581 break;
582 default:
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700583 internal::report_unknown_type(type, "double");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700584 break;
585 }
586
587 char sign = 0;
Victor Zverovichbe785a82014-07-29 09:14:07 -0700588 // Use getsign instead of value < 0 because the latter is always
Victor Zverovich7cae7632013-09-06 20:23:42 -0700589 // false for NaN.
Victor Zverovichbe785a82014-07-29 09:14:07 -0700590 if (getsign(static_cast<double>(value))) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700591 sign = '-';
592 value = -value;
Victor Zverovichd142e3b2014-07-25 08:29:06 -0700593 } else if (spec.flag(SIGN_FLAG)) {
594 sign = spec.flag(PLUS_FLAG) ? '+' : ' ';
Victor Zverovich7cae7632013-09-06 20:23:42 -0700595 }
596
597 if (value != value) {
598 // Format NaN ourselves because sprintf's output is not consistent
599 // across platforms.
600 std::size_t size = 4;
601 const char *nan = upper ? " NAN" : " nan";
602 if (!sign) {
603 --size;
604 ++nan;
605 }
Victor Zverovich53201032014-06-30 14:26:29 -0700606 CharPtr out = write_str(nan, size, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700607 if (sign)
608 *out = sign;
609 return;
610 }
611
Victor Zverovich1a0c76a2014-08-13 07:51:02 -0700612 if (isinfinity(value)) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700613 // Format infinity ourselves because sprintf's output is not consistent
614 // across platforms.
615 std::size_t size = 4;
616 const char *inf = upper ? " INF" : " inf";
617 if (!sign) {
618 --size;
619 ++inf;
620 }
Victor Zverovich53201032014-06-30 14:26:29 -0700621 CharPtr out = write_str(inf, size, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700622 if (sign)
623 *out = sign;
624 return;
625 }
626
627 std::size_t offset = buffer_.size();
628 unsigned width = spec.width();
629 if (sign) {
630 buffer_.reserve(buffer_.size() + (std::max)(width, 1u));
631 if (width > 0)
632 --width;
633 ++offset;
634 }
635
636 // Build format string.
637 enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg
638 Char format[MAX_FORMAT_SIZE];
639 Char *format_ptr = format;
640 *format_ptr++ = '%';
641 unsigned width_for_sprintf = width;
Victor Zverovichd142e3b2014-07-25 08:29:06 -0700642 if (spec.flag(HASH_FLAG))
Victor Zverovich7cae7632013-09-06 20:23:42 -0700643 *format_ptr++ = '#';
644 if (spec.align() == ALIGN_CENTER) {
645 width_for_sprintf = 0;
646 } else {
647 if (spec.align() == ALIGN_LEFT)
648 *format_ptr++ = '-';
649 if (width != 0)
650 *format_ptr++ = '*';
651 }
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700652 if (spec.precision() >= 0) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700653 *format_ptr++ = '.';
654 *format_ptr++ = '*';
655 }
656 if (internal::IsLongDouble<T>::VALUE)
657 *format_ptr++ = 'L';
658 *format_ptr++ = type;
659 *format_ptr = '\0';
660
661 // Format using snprintf.
Victor Zverovich88972f42013-09-08 13:30:14 -0700662 Char fill = static_cast<Char>(spec.fill());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700663 for (;;) {
664 std::size_t size = buffer_.capacity() - offset;
Victor Zverovich33baa8f2014-04-23 18:37:08 -0700665#if _MSC_VER
666 // MSVC's vsnprintf_s doesn't work with zero size, so reserve
667 // space for at least one extra character to make the size non-zero.
668 // Note that the buffer's capacity will increase by more than 1.
669 if (size == 0) {
670 buffer_.reserve(offset + 1);
671 size = buffer_.capacity() - offset;
672 }
673#endif
Victor Zverovich7cae7632013-09-06 20:23:42 -0700674 Char *start = &buffer_[offset];
Victor Zverovichb498ba02014-07-26 08:03:03 -0700675 int n = internal::CharTraits<Char>::format_float(
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700676 start, size, format, width_for_sprintf, spec.precision(), value);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700677 if (n >= 0 && offset + n < buffer_.capacity()) {
678 if (sign) {
679 if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) ||
680 *start != ' ') {
681 *(start - 1) = sign;
682 sign = 0;
683 } else {
Victor Zverovich88972f42013-09-08 13:30:14 -0700684 *(start - 1) = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700685 }
686 ++n;
687 }
688 if (spec.align() == ALIGN_CENTER &&
689 spec.width() > static_cast<unsigned>(n)) {
690 unsigned width = spec.width();
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700691 CharPtr p = grow_buffer(width);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700692 std::copy(p, p + n, p + (width - n) / 2);
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700693 fill_padding(p, spec.width(), n, fill);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700694 return;
695 }
696 if (spec.fill() != ' ' || sign) {
697 while (*start == ' ')
Victor Zverovich88972f42013-09-08 13:30:14 -0700698 *start++ = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700699 if (sign)
700 *(start - 1) = sign;
701 }
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700702 grow_buffer(n);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700703 return;
704 }
Victor Zverovichcfeba452014-04-23 18:37:49 -0700705 // If n is negative we ask to increase the capacity by at least 1,
706 // but as std::vector, the buffer grows exponentially.
707 buffer_.reserve(n >= 0 ? offset + n + 1 : buffer_.capacity() + 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700708 }
709}
710
Victor Zverovich7cae7632013-09-06 20:23:42 -0700711template <typename Char>
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700712template <typename StrChar>
Victor Zverovich53201032014-06-30 14:26:29 -0700713void fmt::BasicWriter<Char>::write_str(
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700714 const Arg::StringValue<StrChar> &str, const FormatSpec &spec) {
715 // Check if StrChar is convertible to Char.
716 internal::CharTraits<Char>::convert(StrChar());
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700717 if (spec.type_ && spec.type_ != 's')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700718 internal::report_unknown_type(spec.type_, "string");
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700719 const StrChar *s = str.value;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700720 std::size_t size = str.size;
721 if (size == 0) {
722 if (!s)
723 throw FormatError("string pointer is null");
724 if (*s)
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700725 size = std::char_traits<StrChar>::length(s);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700726 }
Victor Zverovich53201032014-06-30 14:26:29 -0700727 write_str(s, size, spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700728}
729
730template <typename Char>
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700731inline const Arg
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700732 &fmt::BasicFormatter<Char>::parse_arg_index(const Char *&s) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700733 unsigned arg_index = 0;
734 if (*s < '0' || *s > '9') {
735 if (*s != '}' && *s != ':')
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700736 report_error_(s, "invalid argument index in format string");
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700737 const Arg &arg = next_arg();
738 if (error_)
739 report_error_(s, error_);
740 return arg;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700741 }
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700742 if (next_arg_index_ > 0) {
743 report_error_(s,
744 "cannot switch from automatic to manual argument indexing");
745 }
746 next_arg_index_ = -1;
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700747 arg_index = parse_nonnegative_int(s, error_);
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700748 if (error_)
749 report_error_(s, error_); // TODO: don't use report_error_
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700750 if (arg_index >= args_.size())
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700751 report_error_(s, "argument index is out of range in format");
Victor Zverovich656a8372014-04-22 08:58:54 -0700752 return args_[arg_index];
Victor Zverovich7cae7632013-09-06 20:23:42 -0700753}
754
755template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700756void fmt::BasicFormatter<Char>::check_sign(
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700757 const Char *&s, const Arg &arg) {
Victor Zverovichcc6af502013-12-10 08:01:08 -0800758 char sign = static_cast<char>(*s);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700759 if (arg.type > Arg::LAST_NUMERIC_TYPE) {
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700760 report_error_(s, fmt::format(
761 "format specifier '{}' requires numeric argument", sign).c_str());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700762 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700763 if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700764 report_error_(s, fmt::format(
765 "format specifier '{}' requires signed argument", sign).c_str());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700766 }
767 ++s;
768}
769
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700770const Arg &fmt::internal::FormatterBase::next_arg() {
771 if (next_arg_index_ < 0) {
772 if (!error_)
773 error_ = "cannot switch from manual to automatic argument indexing";
774 return DUMMY_ARG;
775 }
776 unsigned arg_index = next_arg_index_++;
777 if (arg_index < args_.size())
778 return args_[arg_index];
779 if (!error_)
780 error_ = "argument index is out of range in format";
781 return DUMMY_ARG;
782}
783
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700784const Arg &fmt::internal::FormatterBase::handle_arg_index(unsigned arg_index) {
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700785 if (arg_index != UINT_MAX) {
786 if (next_arg_index_ <= 0) {
787 next_arg_index_ = -1;
788 --arg_index;
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700789 } else if (!error_) {
790 error_ = "cannot switch from automatic to manual argument indexing";
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700791 }
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700792 if (arg_index < args_.size())
793 return args_[arg_index];
794 if (!error_)
795 error_ = "argument index is out of range in format";
796 return DUMMY_ARG;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700797 }
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700798 return next_arg();
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700799}
800
Victor Zverovich7cae7632013-09-06 20:23:42 -0700801template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700802void fmt::internal::PrintfFormatter<Char>::parse_flags(
Victor Zverovichcb743c02014-06-19 07:40:35 -0700803 FormatSpec &spec, const Char *&s) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700804 for (;;) {
Victor Zverovich1b801482014-06-07 08:57:55 -0700805 switch (*s++) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700806 case '-':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700807 spec.align_ = ALIGN_LEFT;
808 break;
809 case '+':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700810 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
811 break;
812 case '0':
813 spec.fill_ = '0';
Victor Zverovich1b801482014-06-07 08:57:55 -0700814 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700815 case ' ':
Victor Zverovich1b801482014-06-07 08:57:55 -0700816 spec.flags_ |= SIGN_FLAG;
817 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700818 case '#':
Victor Zverovichcb743c02014-06-19 07:40:35 -0700819 spec.flags_ |= HASH_FLAG;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700820 break;
821 default:
Victor Zverovich1b801482014-06-07 08:57:55 -0700822 --s;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700823 return;
824 }
825 }
826}
827
Victor Zverovichcb743c02014-06-19 07:40:35 -0700828template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700829unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700830 const Char *&s, FormatSpec &spec) {
Victor Zverovichcb743c02014-06-19 07:40:35 -0700831 unsigned arg_index = UINT_MAX;
832 Char c = *s;
833 if (c >= '0' && c <= '9') {
834 // Parse an argument index (if followed by '$') or a width possibly
Victor Zverovich879838a2014-06-20 07:34:02 -0700835 // preceded with '0' flag(s).
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700836 unsigned value = parse_nonnegative_int(s, error_);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700837 if (*s == '$') { // value is an argument index
838 ++s;
839 arg_index = value;
840 } else {
841 if (c == '0')
842 spec.fill_ = '0';
843 if (value != 0) {
844 // Nonzero value means that we parsed width and don't need to
845 // parse it or flags again, so return now.
846 spec.width_ = value;
847 return arg_index;
848 }
849 }
850 }
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700851 parse_flags(spec, s);
Victor Zverovich4099a122014-06-23 08:10:50 -0700852 // Parse width.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700853 if (*s >= '0' && *s <= '9') {
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700854 spec.width_ = parse_nonnegative_int(s, error_);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700855 } else if (*s == '*') {
856 ++s;
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700857 spec.width_ = WidthHandler(spec).visit(handle_arg_index(UINT_MAX));
Victor Zverovichcb743c02014-06-19 07:40:35 -0700858 }
859 return arg_index;
860}
861
Victor Zverovich1f19b982014-06-16 07:49:30 -0700862template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700863void fmt::internal::PrintfFormatter<Char>::format(
Victor Zveroviche78904b2014-04-23 08:27:50 -0700864 BasicWriter<Char> &writer, BasicStringRef<Char> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700865 const ArgList &args) {
Victor Zveroviche78904b2014-04-23 08:27:50 -0700866 const Char *start = format.c_str();
Victor Zveroviche78904b2014-04-23 08:27:50 -0700867 args_ = args;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700868 next_arg_index_ = 0;
869 const Char *s = start;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700870 while (*s) {
Victor Zverovich0fc73162013-09-07 12:52:52 -0700871 Char c = *s++;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700872 if (c != '%') continue;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700873 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -0700874 write(writer, start, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700875 start = ++s;
876 continue;
877 }
Victor Zverovichc1db2932014-07-24 08:53:27 -0700878 write(writer, start, s - 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700879
Victor Zverovichcb743c02014-06-19 07:40:35 -0700880 FormatSpec spec;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700881 spec.align_ = ALIGN_RIGHT;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700882
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700883 // Reporting errors is delayed till the format specification is
884 // completely parsed. This is done to avoid potentially confusing
885 // error messages for incomplete format strings. For example, in
886 // sprintf("%2$", 42);
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700887 // the format specification is incomplete. In a naive approach we
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700888 // would parse 2 as an argument index and report an error that the
889 // index is out of range which would be rather confusing if the
890 // use meant "%2d$" rather than "%2$d". If we delay an error, the
891 // user will get an error that the format string is invalid which
892 // is OK for both cases.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700893
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700894 // Parse argument index, flags and width.
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700895 unsigned arg_index = parse_header(s, spec);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700896
897 // Parse precision.
898 if (*s == '.') {
899 ++s;
900 if ('0' <= *s && *s <= '9') {
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700901 spec.precision_ = parse_nonnegative_int(s, error_);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700902 } else if (*s == '*') {
903 ++s;
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700904 spec.precision_ = PrecisionHandler().visit(handle_arg_index(UINT_MAX));
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700905 }
906 }
907
Victor Zverovicheeca2232014-07-30 07:37:16 -0700908 Arg arg = handle_arg_index(arg_index);
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700909 if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
Victor Zverovichcb743c02014-06-19 07:40:35 -0700910 spec.flags_ &= ~HASH_FLAG;
911 if (spec.fill_ == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700912 if (arg.type <= Arg::LAST_NUMERIC_TYPE)
Victor Zverovichcb743c02014-06-19 07:40:35 -0700913 spec.align_ = ALIGN_NUMERIC;
914 else
915 spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700916 }
917
Victor Zverovichf4156b52014-07-30 08:39:07 -0700918 // Parse length and convert the argument to the required type.
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700919 switch (*s++) {
920 case 'h':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700921 if (*s == 'h')
922 ArgConverter<signed char>(arg, *++s).visit(arg);
Victor Zverovich39b09302014-07-30 08:08:08 -0700923 else
Victor Zverovichf4156b52014-07-30 08:39:07 -0700924 ArgConverter<short>(arg, *s).visit(arg);
Victor Zverovicheeca2232014-07-30 07:37:16 -0700925 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700926 case 'l':
Victor Zverovichd3a70392014-08-12 08:36:19 -0700927 if (*s == 'l')
Victor Zveroviche488a282014-08-13 06:53:43 -0700928 ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
Victor Zverovichd3a70392014-08-12 08:36:19 -0700929 else
930 ArgConverter<long>(arg, *s).visit(arg);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700931 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700932 case 'j':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700933 ArgConverter<intmax_t>(arg, *s).visit(arg);
934 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700935 case 'z':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700936 ArgConverter<size_t>(arg, *s).visit(arg);
937 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700938 case 't':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700939 ArgConverter<ptrdiff_t>(arg, *s).visit(arg);
940 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700941 case 'L':
942 // TODO: handle length
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700943 break;
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700944 default:
945 --s;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700946 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700947
948 // Parse type.
949 if (!*s)
950 throw FormatError("invalid format string");
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700951 if (error_)
952 throw FormatError(error_);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700953 spec.type_ = static_cast<char>(*s++);
Victor Zverovichf4156b52014-07-30 08:39:07 -0700954 if (arg.type <= Arg::LAST_INTEGER_TYPE &&
955 (spec.type_ == 'i' || spec.type_ == 'u')) {
956 spec.type_ = 'd';
957 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700958
959 start = s;
960
961 // Format argument.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700962 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700963 case Arg::INT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700964 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700965 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700966 case Arg::UINT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700967 writer.write_int(arg.uint_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700968 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700969 case Arg::LONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700970 writer.write_int(arg.long_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700971 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700972 case Arg::ULONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700973 writer.write_int(arg.ulong_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700974 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700975 case Arg::CHAR: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700976 if (spec.type_ && spec.type_ != 'c')
Victor Zverovichc1db2932014-07-24 08:53:27 -0700977 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700978 typedef typename BasicWriter<Char>::CharPtr CharPtr;
979 CharPtr out = CharPtr();
980 if (spec.width_ > 1) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700981 Char fill = ' ';
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700982 out = writer.grow_buffer(spec.width_);
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700983 if (spec.align_ != ALIGN_LEFT) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700984 std::fill_n(out, spec.width_ - 1, fill);
985 out += spec.width_ - 1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700986 } else {
987 std::fill_n(out + 1, spec.width_ - 1, fill);
988 }
989 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700990 out = writer.grow_buffer(1);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700991 }
Victor Zverovichcb743c02014-06-19 07:40:35 -0700992 *out = static_cast<Char>(arg.int_value);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700993 break;
994 }
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700995 case Arg::DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700996 writer.write_double(arg.double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700997 break;
998 case Arg::LONG_DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700999 writer.write_double(arg.long_double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001000 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001001 case Arg::STRING:
Victor Zverovich53201032014-06-30 14:26:29 -07001002 writer.write_str(arg.string, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001003 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001004 case Arg::WSTRING:
Victor Zverovich512e2ce2014-07-14 08:47:03 -07001005 writer.write_str(ignore_incompatible_str<Char>(arg.wstring), spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001006 break;
1007 case Arg::POINTER:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001008 if (spec.type_ && spec.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001009 internal::report_unknown_type(spec.type_, "pointer");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001010 spec.flags_= HASH_FLAG;
1011 spec.type_ = 'x';
Victor Zverovichc1db2932014-07-24 08:53:27 -07001012 writer.write_int(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001013 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001014 case Arg::CUSTOM:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001015 if (spec.type_)
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001016 internal::report_unknown_type(spec.type_, "object");
Victor Zveroviche8251562014-07-08 16:20:33 -07001017 arg.custom.format(&writer, arg.custom.value, "s");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001018 break;
1019 default:
1020 assert(false);
1021 break;
1022 }
1023 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001024 write(writer, start, s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001025}
1026
1027template <typename Char>
Victor Zverovichb9a06ba2014-07-08 16:38:50 -07001028const Char *fmt::BasicFormatter<Char>::format(
Victor Zverovich512e2ce2014-07-14 08:47:03 -07001029 const Char *format_str, const Arg &arg) {
Victor Zveroviche8251562014-07-08 16:20:33 -07001030 const Char *s = format_str;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001031 const char *error = 0;
Victor Zveroviche8251562014-07-08 16:20:33 -07001032 FormatSpec spec;
1033 if (*s == ':') {
1034 if (arg.type == Arg::CUSTOM) {
1035 arg.custom.format(this, arg.custom.value, s);
1036 return find_closing_brace(s) + 1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001037 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001038 ++s;
1039 // Parse fill and alignment.
1040 if (Char c = *s) {
1041 const Char *p = s + 1;
1042 spec.align_ = ALIGN_DEFAULT;
1043 do {
1044 switch (*p) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001045 case '<':
1046 spec.align_ = ALIGN_LEFT;
1047 break;
1048 case '>':
1049 spec.align_ = ALIGN_RIGHT;
1050 break;
1051 case '=':
1052 spec.align_ = ALIGN_NUMERIC;
1053 break;
1054 case '^':
1055 spec.align_ = ALIGN_CENTER;
1056 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001057 }
1058 if (spec.align_ != ALIGN_DEFAULT) {
1059 if (p != s) {
1060 if (c == '}') break;
1061 if (c == '{')
1062 report_error_(s, "invalid fill character '{'");
1063 s += 2;
1064 spec.fill_ = c;
1065 } else ++s;
1066 if (spec.align_ == ALIGN_NUMERIC && arg.type > Arg::LAST_NUMERIC_TYPE)
1067 report_error_(s, "format specifier '=' requires numeric argument");
1068 break;
1069 }
1070 } while (--p >= s);
1071 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001072
Victor Zveroviche8251562014-07-08 16:20:33 -07001073 // Parse sign.
1074 switch (*s) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001075 case '+':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001076 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001077 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
1078 break;
1079 case '-':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001080 check_sign(s, arg);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001081 spec.flags_ |= MINUS_FLAG;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001082 break;
1083 case ' ':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001084 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001085 spec.flags_ |= SIGN_FLAG;
1086 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001087 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001088
Victor Zveroviche8251562014-07-08 16:20:33 -07001089 if (*s == '#') {
1090 if (arg.type > Arg::LAST_NUMERIC_TYPE)
1091 report_error_(s, "format specifier '#' requires numeric argument");
1092 spec.flags_ |= HASH_FLAG;
1093 ++s;
1094 }
1095
1096 // Parse width and zero flag.
1097 if ('0' <= *s && *s <= '9') {
1098 if (*s == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001099 if (arg.type > Arg::LAST_NUMERIC_TYPE)
Victor Zveroviche8251562014-07-08 16:20:33 -07001100 report_error_(s, "format specifier '0' requires numeric argument");
1101 spec.align_ = ALIGN_NUMERIC;
1102 spec.fill_ = '0';
Victor Zverovich7cae7632013-09-06 20:23:42 -07001103 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001104 // Zero may be parsed again as a part of the width, but it is simpler
1105 // and more efficient than checking if the next char is a digit.
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001106 spec.width_ = parse_nonnegative_int(s, error);
Victor Zveroviche8251562014-07-08 16:20:33 -07001107 if (error)
1108 report_error_(s, error);
1109 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001110
Victor Zveroviche8251562014-07-08 16:20:33 -07001111 // Parse precision.
1112 if (*s == '.') {
1113 ++s;
1114 spec.precision_ = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001115 if ('0' <= *s && *s <= '9') {
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001116 spec.precision_ = parse_nonnegative_int(s, error);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001117 if (error)
1118 report_error_(s, error);
Victor Zveroviche8251562014-07-08 16:20:33 -07001119 } else if (*s == '{') {
Victor Zverovich7cae7632013-09-06 20:23:42 -07001120 ++s;
Victor Zveroviche8251562014-07-08 16:20:33 -07001121 ++report_error_.num_open_braces;
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001122 const Arg &precision_arg = parse_arg_index(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001123 ULongLong value = 0;
1124 switch (precision_arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001125 case Arg::INT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001126 if (precision_arg.int_value < 0)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001127 report_error_(s, "negative precision in format");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001128 value = precision_arg.int_value;
1129 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001130 case Arg::UINT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001131 value = precision_arg.uint_value;
1132 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001133 case Arg::LONG_LONG:
Victor Zverovich56f12b72013-11-22 07:45:43 -08001134 if (precision_arg.long_long_value < 0)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001135 report_error_(s, "negative precision in format");
Victor Zverovich56f12b72013-11-22 07:45:43 -08001136 value = precision_arg.long_long_value;
1137 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001138 case Arg::ULONG_LONG:
Gregory Czajkowskia65542b2013-11-18 22:58:39 -08001139 value = precision_arg.ulong_long_value;
Victor Zverovicha4e72b42013-11-21 09:11:58 -08001140 break;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001141 default:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001142 report_error_(s, "precision is not integer");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001143 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001144 if (value > INT_MAX)
1145 report_error_(s, "number is too big in format");
1146 spec.precision_ = static_cast<int>(value);
1147 if (*s++ != '}')
1148 throw FormatError("unmatched '{' in format");
1149 --report_error_.num_open_braces;
1150 } else {
1151 report_error_(s, "missing precision in format");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001152 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001153 if (arg.type != Arg::DOUBLE && arg.type != Arg::LONG_DOUBLE) {
1154 report_error_(s,
1155 "precision specifier requires floating-point argument");
1156 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001157 }
1158
Victor Zveroviche8251562014-07-08 16:20:33 -07001159 // Parse type.
1160 if (*s != '}' && *s)
1161 spec.type_ = static_cast<char>(*s++);
1162 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001163
Victor Zveroviche8251562014-07-08 16:20:33 -07001164 if (*s++ != '}')
1165 throw FormatError("unmatched '{' in format");
1166 start_ = s;
1167
1168 // Format argument.
Victor Zverovich4edc88f2014-07-16 08:38:15 -07001169 internal::ArgFormatter<Char>(*this, spec, s - 1).visit(arg);
Victor Zveroviche8251562014-07-08 16:20:33 -07001170 return s;
1171}
1172
1173template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001174void fmt::BasicFormatter<Char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001175 BasicStringRef<Char> format_str, const ArgList &args) {
1176 const Char *s = start_ = format_str.c_str();
1177 args_ = args;
1178 next_arg_index_ = 0;
1179 while (*s) {
1180 Char c = *s++;
1181 if (c != '{' && c != '}') continue;
1182 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -07001183 write(writer_, start_, s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001184 start_ = ++s;
1185 continue;
1186 }
1187 if (c == '}')
1188 throw FormatError("unmatched '}' in format");
1189 report_error_.num_open_braces = 1;
Victor Zverovichc1db2932014-07-24 08:53:27 -07001190 write(writer_, start_, s - 1);
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001191 Arg arg = parse_arg_index(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001192 s = format(s, arg);
1193 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001194 write(writer_, start_, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001195}
1196
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001197void fmt::report_system_error(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001198 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
Victor Zverovich75b5eb42014-07-27 15:09:05 -07001199 // FIXME: format_system_error may throw
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001200 report_error(internal::format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001201}
1202
Victor Zverovich400812a2014-04-30 12:38:17 -07001203#ifdef _WIN32
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001204void fmt::report_windows_error(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001205 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
Victor Zverovich75b5eb42014-07-27 15:09:05 -07001206 // FIXME: format_windows_error may throw
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001207 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001208}
Victor Zverovich400812a2014-04-30 12:38:17 -07001209#endif
Victor Zverovichf7939862014-04-30 10:18:11 -07001210
Victor Zverovich2e039632014-06-28 19:44:39 -07001211void fmt::print(StringRef format, const ArgList &args) {
1212 Writer w;
Victor Zverovicha1264922014-06-29 11:51:10 -07001213 w.write(format, args);
Victor Zverovich2e039632014-06-28 19:44:39 -07001214 std::fwrite(w.data(), 1, w.size(), stdout);
1215}
1216
Victor Zverovichd5b81962014-06-28 21:56:40 -07001217void fmt::print(std::FILE *f, StringRef format, const ArgList &args) {
1218 Writer w;
Victor Zverovicha1264922014-06-29 11:51:10 -07001219 w.write(format, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001220 std::fwrite(w.data(), 1, w.size(), f);
1221}
1222
Victor Zveroviche3a44c12014-07-09 06:56:36 -07001223void fmt::print(std::ostream &os, StringRef format, const ArgList &args) {
1224 Writer w;
1225 w.write(format, args);
1226 os.write(w.data(), w.size());
1227}
1228
Victor Zverovich2dc108b2014-07-01 09:10:43 -07001229void fmt::print_colored(Color c, StringRef format, const ArgList &args) {
1230 char escape[] = "\x1b[30m";
1231 escape[3] = '0' + static_cast<char>(c);
1232 std::fputs(escape, stdout);
1233 print(format, args);
1234 std::fputs(RESET_COLOR, stdout);
1235}
1236
Victor Zverovichd5b81962014-06-28 21:56:40 -07001237void fmt::printf(StringRef format, const ArgList &args) {
1238 Writer w;
Victor Zverovich21111cc2014-06-29 19:52:26 -07001239 printf(w, format, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001240 std::fwrite(w.data(), 1, w.size(), stdout);
1241}
1242
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001243// Explicit instantiations for char.
1244
Victor Zverovich93e41252013-09-08 13:07:04 -07001245template fmt::BasicWriter<char>::CharPtr
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001246 fmt::BasicWriter<char>::fill_padding(CharPtr buffer,
Victor Zverovich93e41252013-09-08 13:07:04 -07001247 unsigned total_size, std::size_t content_size, wchar_t fill);
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001248
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001249template void fmt::BasicFormatter<char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001250 BasicStringRef<char> format, const ArgList &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001251
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001252template void fmt::internal::PrintfFormatter<char>::format(
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001253 BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001254
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001255// Explicit instantiations for wchar_t.
1256
Victor Zverovich7cae7632013-09-06 20:23:42 -07001257template fmt::BasicWriter<wchar_t>::CharPtr
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001258 fmt::BasicWriter<wchar_t>::fill_padding(CharPtr buffer,
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001259 unsigned total_size, std::size_t content_size, wchar_t fill);
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001260
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001261template void fmt::BasicFormatter<wchar_t>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001262 BasicStringRef<wchar_t> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001263
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001264template void fmt::internal::PrintfFormatter<wchar_t>::format(
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001265 BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001266 const ArgList &args);
jdale88a9862fd2014-03-11 18:56:24 +00001267
1268#if _MSC_VER
1269# pragma warning(pop)
1270#endif