blob: 98b0f4ba7bf2b751514111139cb830fca3e09b85 [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 Zverovich24d6baa2014-07-29 07:49:34 -070078#ifdef isinf
Victor Zverovichd4412a02014-08-13 08:01:51 -070079inline int isinfinity(double x) { return isinf(x); }
80inline int isinfinity(long double x) { return isinf(x); }
Victor Zverovich24d6baa2014-07-29 07:49:34 -070081#else
Victor Zverovichd4412a02014-08-13 08:01:51 -070082inline int isinfinity(double x) { return std::isinf(x); }
83inline int isinfinity(long double x) { return std::isinf(x); }
Victor Zverovich9ff3b972013-09-07 10:15:08 -070084#endif
Victor Zverovich1a0c76a2014-08-13 07:51:02 -070085
Victor Zverovich9ff3b972013-09-07 10:15:08 -070086#define FMT_SNPRINTF snprintf
87
Victor Zverovicha684d0c2013-12-27 08:00:10 -080088#else // _MSC_VER
Victor Zverovich9ff3b972013-09-07 10:15:08 -070089
Victor Zverovichbe785a82014-07-29 09:14:07 -070090inline int getsign(double value) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -070091 if (value < 0) return 1;
92 if (value == value) return 0;
93 int dec = 0, sign = 0;
94 char buffer[2]; // The buffer size must be >= 2 or _ecvt_s will fail.
95 _ecvt_s(buffer, sizeof(buffer), value, 0, &dec, &sign);
96 return sign;
97}
98
Victor Zverovichbf5b2462014-07-29 08:22:52 -070099inline int isinfinity(double x) { return !_finite(x); }
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700100
Victor Zverovich406c6122014-08-19 08:47:38 -0700101inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -0800102 va_list args;
103 va_start(args, format);
104 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
105 va_end(args);
106 return result;
107}
Victor Zverovich406c6122014-08-19 08:47:38 -0700108#define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700109
110#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -0800111
Victor Zverovichfb321612014-08-15 08:40:03 -0700112template <typename T>
113struct IsLongDouble { enum {VALUE = 0}; };
114
115template <>
116struct IsLongDouble<long double> { enum {VALUE = 1}; };
117
Victor Zverovichadce0242014-08-17 07:53:55 -0700118// Checks if a value fits in int - used to avoid warnings about comparing
119// signed and unsigned integers.
120template <bool IsSigned>
121struct IntChecker {
122 template <typename T>
123 static bool fits_in_int(T value) {
124 unsigned max = INT_MAX;
125 return value <= max;
126 }
127};
128
129template <>
130struct IntChecker<true> {
131 template <typename T>
132 static bool fits_in_int(T value) {
133 return value >= INT_MIN && value <= INT_MAX;
134 }
135};
136
Victor Zverovich43fe1002014-02-19 14:20:26 -0800137const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700138
139typedef void (*FormatFunc)(fmt::Writer &, int , fmt::StringRef);
140
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700141void report_error(FormatFunc func,
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700142 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
143 try {
144 fmt::Writer full_message;
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700145 func(full_message, error_code, message); // TODO: make sure this doesn't throw
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700146 std::fwrite(full_message.c_str(), full_message.size(), 1, stderr);
147 std::fputc('\n', stderr);
148 } catch (...) {}
Victor Zverovichb605b392013-09-09 22:21:40 -0700149}
Victor Zverovichd29e5052014-06-30 07:12:09 -0700150
Victor Zverovich366e8522014-08-15 16:35:41 -0700151const Arg DUMMY_ARG = {Arg::INT, {0}};
Victor Zverovichd29e5052014-06-30 07:12:09 -0700152
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700153// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
154class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> {
155 public:
156 template <typename T>
157 bool visit_any_int(T value) { return value == 0; }
158};
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700159
160// Parses an unsigned integer advancing s to the end of the parsed input.
161// This function assumes that the first character of s is a digit.
162template <typename Char>
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700163int parse_nonnegative_int(
164 const Char *&s, const char *&error) FMT_NOEXCEPT(true) {
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700165 assert('0' <= *s && *s <= '9');
166 unsigned value = 0;
167 do {
168 unsigned new_value = value * 10 + (*s++ - '0');
169 // Check if value wrapped around.
170 value = new_value >= value ? new_value : UINT_MAX;
171 } while ('0' <= *s && *s <= '9');
172 if (value > INT_MAX) {
173 if (!error)
174 error = "number is too big in format";
175 return 0;
176 }
177 return value;
178}
Victor Zveroviche8251562014-07-08 16:20:33 -0700179
180template <typename Char>
181const Char *find_closing_brace(const Char *s, int num_open_braces = 1) {
182 for (int n = num_open_braces; *s; ++s) {
183 if (*s == '{') {
184 ++n;
185 } else if (*s == '}') {
186 if (--n == 0)
187 return s;
188 }
189 }
190 throw fmt::FormatError("unmatched '{' in format");
191}
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700192
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700193// Checks if an argument is a valid printf width specifier and sets
194// left alignment if it is negative.
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700195class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700196 private:
197 fmt::FormatSpec &spec_;
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700198
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700199 public:
200 explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700201
Victor Zverovich9d74f952014-07-16 07:27:54 -0700202 unsigned visit_unhandled_arg() {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700203 throw fmt::FormatError("width is not integer");
204 }
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700205
Victor Zverovich9d74f952014-07-16 07:27:54 -0700206 template <typename T>
207 unsigned visit_any_int(T value) {
208 typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType;
209 UnsignedType width = value;
210 if (fmt::internal::is_negative(value)) {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700211 spec_.align_ = fmt::ALIGN_LEFT;
212 width = 0 - width;
213 }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700214 if (width > INT_MAX)
215 throw fmt::FormatError("number is too big in format");
216 return static_cast<unsigned>(width);
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700217 }
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700218};
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700219
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700220class PrecisionHandler :
221 public fmt::internal::ArgVisitor<PrecisionHandler, int> {
222 public:
223 unsigned visit_unhandled_arg() {
224 throw fmt::FormatError("precision is not integer");
225 }
226
227 template <typename T>
228 int visit_any_int(T value) {
Victor Zverovichadce0242014-08-17 07:53:55 -0700229 if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700230 throw fmt::FormatError("number is too big in format");
231 return static_cast<int>(value);
232 }
233};
234
Victor Zverovicheeca2232014-07-30 07:37:16 -0700235// Converts an integer argument to type T.
236template <typename T>
237class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
238 private:
239 fmt::internal::Arg &arg_;
Victor Zveroviche22d6572014-08-08 06:51:09 -0700240 wchar_t type_;
Victor Zverovicheeca2232014-07-30 07:37:16 -0700241
242 public:
Victor Zveroviche22d6572014-08-08 06:51:09 -0700243 ArgConverter(fmt::internal::Arg &arg, wchar_t type)
244 : arg_(arg), type_(type) {}
Victor Zverovicheeca2232014-07-30 07:37:16 -0700245
246 template <typename U>
247 void visit_any_int(U value) {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700248 bool is_signed = type_ == 'd' || type_ == 'i';
249 using fmt::internal::Arg;
250 if (sizeof(T) <= sizeof(int)) {
251 if (is_signed) {
252 arg_.type = Arg::INT;
Victor Zverovichbb016332014-08-15 09:03:59 -0700253 arg_.int_value = static_cast<int>(static_cast<T>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700254 } else {
255 arg_.type = Arg::UINT;
Victor Zverovich186734c2014-08-18 07:03:12 -0700256 arg_.uint_value = static_cast<unsigned>(
257 static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700258 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700259 } else {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700260 if (is_signed) {
261 arg_.type = Arg::LONG_LONG;
Victor Zverovicha259c942014-08-01 07:15:27 -0700262 arg_.long_long_value =
263 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700264 } else {
265 arg_.type = Arg::ULONG_LONG;
266 arg_.ulong_long_value =
Victor Zverovicha259c942014-08-01 07:15:27 -0700267 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700268 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700269 }
270 }
271};
272
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700273// Converts an integer argument to char.
274class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
275 private:
276 fmt::internal::Arg &arg_;
277
278 public:
279 explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
280
281 template <typename T>
282 void visit_any_int(T value) {
283 arg_.type = Arg::CHAR;
284 arg_.int_value = static_cast<char>(value);
285 }
286};
287
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700288// This function template is used to prevent compile errors when handling
289// incompatible string arguments, e.g. handling a wide string in a narrow
290// string formatter.
291template <typename Char>
292Arg::StringValue<Char> ignore_incompatible_str(Arg::StringValue<wchar_t>);
293
294template <>
295inline Arg::StringValue<char> ignore_incompatible_str(
296 Arg::StringValue<wchar_t>) { return Arg::StringValue<char>(); }
297
298template <>
299inline Arg::StringValue<wchar_t> ignore_incompatible_str(
300 Arg::StringValue<wchar_t> s) { return s; }
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700301} // namespace
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700302
Victor Zverovich53201032014-06-30 14:26:29 -0700303void fmt::SystemError::init(
304 int error_code, StringRef format_str, const ArgList &args) {
305 error_code_ = error_code;
306 Writer w;
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700307 internal::format_system_error(w, error_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700308 std::runtime_error &base = *this;
309 base = std::runtime_error(w.str());
310}
311
Victor Zverovichb605b392013-09-09 22:21:40 -0700312template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700313int fmt::internal::CharTraits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700314 char *buffer, std::size_t size, const char *format,
315 unsigned width, int precision, T value) {
316 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700317 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700318 FMT_SNPRINTF(buffer, size, format, value) :
319 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700320 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700321 return precision < 0 ?
322 FMT_SNPRINTF(buffer, size, format, width, value) :
323 FMT_SNPRINTF(buffer, size, format, width, precision, value);
324}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700325
Victor Zverovichb605b392013-09-09 22:21:40 -0700326template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700327int fmt::internal::CharTraits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700328 wchar_t *buffer, std::size_t size, const wchar_t *format,
329 unsigned width, int precision, T value) {
330 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700331 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700332 swprintf(buffer, size, format, value) :
333 swprintf(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700334 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700335 return precision < 0 ?
336 swprintf(buffer, size, format, width, value) :
337 swprintf(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700338}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800339
Victor Zverovich65d47e52013-09-09 06:51:03 -0700340const char fmt::internal::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800341 "0001020304050607080910111213141516171819"
342 "2021222324252627282930313233343536373839"
343 "4041424344454647484950515253545556575859"
344 "6061626364656667686970717273747576777879"
345 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800346
Victor Zverovichf1d85162014-02-19 13:02:22 -0800347#define FMT_POWERS_OF_10(factor) \
348 factor * 10, \
349 factor * 100, \
350 factor * 1000, \
351 factor * 10000, \
352 factor * 100000, \
353 factor * 1000000, \
354 factor * 10000000, \
355 factor * 100000000, \
356 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800357
Victor Zverovichf1d85162014-02-19 13:02:22 -0800358const uint32_t fmt::internal::POWERS_OF_10_32[] = {0, FMT_POWERS_OF_10(1)};
Victor Zveroviche9b21912014-02-19 12:43:55 -0800359const uint64_t fmt::internal::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800360 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800361 FMT_POWERS_OF_10(1),
362 FMT_POWERS_OF_10(ULongLong(1000000000)),
Victor Zverovich406c6122014-08-19 08:47:38 -0700363 // Multiply several constants instead of using a single long long constant
Victor Zverovichf1d85162014-02-19 13:02:22 -0800364 // to avoid warnings about C++98 not supporting long long.
Victor Zverovich6f6fe512014-02-15 11:16:44 -0800365 ULongLong(1000000000) * ULongLong(1000000000) * 10
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800366};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800367
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700368void fmt::internal::report_unknown_type(char code, const char *type) {
Victor Zverovich877abaf2013-01-08 09:56:05 -0800369 if (std::isprint(static_cast<unsigned char>(code))) {
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700370 throw fmt::FormatError(
371 fmt::format("unknown format code '{}' for {}", code, type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800372 }
373 throw fmt::FormatError(
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700374 fmt::format("unknown format code '\\x{:02x}' for {}",
375 static_cast<unsigned>(code), type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800376}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700377
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700378#ifdef _WIN32
379
380fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
381 int length = MultiByteToWideChar(
382 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, 0, 0);
383 static const char ERROR[] = "cannot convert string from UTF-8 to UTF-16";
384 if (length == 0)
Victor Zverovichf4208772014-06-30 17:32:08 -0700385 throw WindowsError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700386 buffer_.resize(length);
387 length = MultiByteToWideChar(
388 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, &buffer_[0], length);
389 if (length == 0)
Victor Zverovichf4208772014-06-30 17:32:08 -0700390 throw WindowsError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700391}
392
393fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700394 if (int error_code = convert(s)) {
Victor Zverovich8321d0e2014-07-09 08:39:01 -0700395 throw WindowsError(error_code,
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700396 "cannot convert string from UTF-16 to UTF-8");
397 }
398}
399
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700400int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700401 int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, 0, 0, 0, 0);
402 if (length == 0)
403 return GetLastError();
404 buffer_.resize(length);
405 length = WideCharToMultiByte(
406 CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, 0, 0);
407 if (length == 0)
408 return GetLastError();
409 return 0;
410}
411
Victor Zverovich53201032014-06-30 14:26:29 -0700412void fmt::WindowsError::init(
413 int error_code, StringRef format_str, const ArgList &args) {
414 error_code_ = error_code;
415 Writer w;
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700416 internal::format_windows_error(w, error_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700417 std::runtime_error &base = *this;
418 base = std::runtime_error(w.str());
419}
420
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700421#endif
422
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700423int fmt::internal::safe_strerror(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700424 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT(true) {
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700425 assert(buffer != 0 && buffer_size != 0);
Victor Zverovich99e61122014-04-30 11:20:41 -0700426 int result = 0;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700427#ifdef _GNU_SOURCE
428 char *message = strerror_r(error_code, buffer, buffer_size);
Victor Zverovich99e61122014-04-30 11:20:41 -0700429 // If the buffer is full then the message is probably truncated.
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700430 if (message == buffer && strlen(buffer) == buffer_size - 1)
Victor Zverovich99e61122014-04-30 11:20:41 -0700431 result = ERANGE;
432 buffer = message;
Victor Zverovich9c47f3e2014-07-09 09:45:18 -0700433#elif __MINGW32__
434 errno = 0;
435 (void)buffer_size;
436 buffer = strerror(error_code);
437 result = errno;
438#elif _WIN32
Victor Zverovich99e61122014-04-30 11:20:41 -0700439 result = strerror_s(buffer, buffer_size, error_code);
440 // If the buffer is full then the message is probably truncated.
441 if (result == 0 && std::strlen(buffer) == buffer_size - 1)
442 result = ERANGE;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700443#else
Victor Zverovich99e61122014-04-30 11:20:41 -0700444 result = strerror_r(error_code, buffer, buffer_size);
445 if (result == -1)
446 result = errno; // glibc versions before 2.13 return result in errno.
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700447#endif
Victor Zverovich99e61122014-04-30 11:20:41 -0700448 return result;
Victor Zverovich859a4972014-04-30 06:55:21 -0700449}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700450
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700451void fmt::internal::format_system_error(
Victor Zverovich53b4c312014-04-30 15:00:41 -0700452 fmt::Writer &out, int error_code, fmt::StringRef message) {
453 Array<char, INLINE_BUFFER_SIZE> buffer;
454 buffer.resize(INLINE_BUFFER_SIZE);
455 char *system_message = 0;
456 for (;;) {
457 system_message = &buffer[0];
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700458 int result = safe_strerror(error_code, system_message, buffer.size());
Victor Zverovich53b4c312014-04-30 15:00:41 -0700459 if (result == 0)
460 break;
461 if (result != ERANGE) {
462 // Can't get error message, report error code instead.
463 out << message << ": error code = " << error_code;
464 return;
465 }
466 buffer.resize(buffer.size() * 2);
467 }
468 out << message << ": " << system_message;
469}
470
471#ifdef _WIN32
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700472void fmt::internal::format_windows_error(
Victor Zverovich53b4c312014-04-30 15:00:41 -0700473 fmt::Writer &out, int error_code, fmt::StringRef message) {
474 class String {
475 private:
476 LPWSTR str_;
477
478 public:
479 String() : str_() {}
480 ~String() { LocalFree(str_); }
481 LPWSTR *ptr() { return &str_; }
482 LPCWSTR c_str() const { return str_; }
483 };
484 String system_message;
485 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
486 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
487 error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
488 reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
489 UTF16ToUTF8 utf8_message;
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700490 if (!utf8_message.convert(system_message.c_str())) {
Victor Zverovicheb034a02014-06-30 17:40:53 -0700491 out << message << ": " << utf8_message;
Victor Zverovich53b4c312014-04-30 15:00:41 -0700492 return;
493 }
494 }
495 // Can't get error message, report error code instead.
496 out << message << ": error code = " << error_code;
497}
498#endif
499
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700500// An argument formatter.
501template <typename Char>
502class fmt::internal::ArgFormatter :
503 public fmt::internal::ArgVisitor<fmt::internal::ArgFormatter<Char>, void> {
504 private:
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700505 fmt::BasicFormatter<Char> &formatter_;
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700506 fmt::BasicWriter<Char> &writer_;
507 fmt::FormatSpec &spec_;
508 const Char *format_;
509
510 public:
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700511 ArgFormatter(
512 fmt::BasicFormatter<Char> &f,fmt::FormatSpec &s, const Char *fmt)
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700513 : formatter_(f), writer_(f.writer()), spec_(s), format_(fmt) {}
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700514
Victor Zverovich9d74f952014-07-16 07:27:54 -0700515 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700516 void visit_any_int(T value) { writer_.write_int(value, spec_); }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700517
518 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700519 void visit_any_double(T value) { writer_.write_double(value, spec_); }
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700520
521 void visit_char(int value) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700522 if (spec_.type_ && spec_.type_ != 'c') {
Victor Zverovichd699c2a2014-07-25 08:24:27 -0700523 spec_.flags_ |= CHAR_FLAG;
524 writer_.write_int(value, spec_);
525 return;
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700526 }
527 if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
528 throw FormatError("invalid format specifier for char");
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700529 typedef typename fmt::BasicWriter<Char>::CharPtr CharPtr;
530 CharPtr out = CharPtr();
531 if (spec_.width_ > 1) {
532 Char fill = static_cast<Char>(spec_.fill());
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700533 out = writer_.grow_buffer(spec_.width_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700534 if (spec_.align_ == fmt::ALIGN_RIGHT) {
535 std::fill_n(out, spec_.width_ - 1, fill);
536 out += spec_.width_ - 1;
537 } else if (spec_.align_ == fmt::ALIGN_CENTER) {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700538 out = writer_.fill_padding(out, spec_.width_, 1, fill);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700539 } else {
540 std::fill_n(out + 1, spec_.width_ - 1, fill);
541 }
542 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700543 out = writer_.grow_buffer(1);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700544 }
545 *out = static_cast<Char>(value);
546 }
547
548 void visit_string(Arg::StringValue<char> value) {
549 writer_.write_str(value, spec_);
550 }
551 void visit_wstring(Arg::StringValue<wchar_t> value) {
552 writer_.write_str(ignore_incompatible_str<Char>(value), spec_);
553 }
554
555 void visit_pointer(const void *value) {
556 if (spec_.type_ && spec_.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700557 fmt::internal::report_unknown_type(spec_.type_, "pointer");
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700558 spec_.flags_ = fmt::HASH_FLAG;
559 spec_.type_ = 'x';
Victor Zverovichc1db2932014-07-24 08:53:27 -0700560 writer_.write_int(reinterpret_cast<uintptr_t>(value), spec_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700561 }
562
563 void visit_custom(Arg::CustomValue c) {
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700564 c.format(&formatter_, c.value, format_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700565 }
566};
567
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700568template <typename Char>
569void fmt::internal::FormatErrorReporter<Char>::operator()(
570 const Char *s, fmt::StringRef message) const {
Victor Zveroviche8251562014-07-08 16:20:33 -0700571 if (find_closing_brace(s, num_open_braces))
572 throw fmt::FormatError(message);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700573}
574
Victor Zverovich7cae7632013-09-06 20:23:42 -0700575// Fills the padding around the content and returns the pointer to the
576// content area.
577template <typename Char>
Victor Zverovich93e41252013-09-08 13:07:04 -0700578typename fmt::BasicWriter<Char>::CharPtr
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700579 fmt::BasicWriter<Char>::fill_padding(CharPtr buffer,
Victor Zverovich93e41252013-09-08 13:07:04 -0700580 unsigned total_size, std::size_t content_size, wchar_t fill) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700581 std::size_t padding = total_size - content_size;
582 std::size_t left_padding = padding / 2;
Victor Zverovich563a5752013-09-08 13:47:06 -0700583 Char fill_char = static_cast<Char>(fill);
584 std::fill_n(buffer, left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700585 buffer += left_padding;
586 CharPtr content = buffer;
Victor Zverovich563a5752013-09-08 13:47:06 -0700587 std::fill_n(buffer + content_size, padding - left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700588 return content;
589}
590
591template <typename Char>
Victor Zverovich7cae7632013-09-06 20:23:42 -0700592template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700593void fmt::BasicWriter<Char>::write_double(T value, const FormatSpec &spec) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700594 // Check type.
595 char type = spec.type();
596 bool upper = false;
597 switch (type) {
598 case 0:
599 type = 'g';
600 break;
Victor Zverovich03776dd2014-06-10 07:03:49 -0700601 case 'e': case 'f': case 'g': case 'a':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700602 break;
603 case 'F':
604#ifdef _MSC_VER
605 // MSVC's printf doesn't support 'F'.
606 type = 'f';
607#endif
608 // Fall through.
Victor Zverovich03776dd2014-06-10 07:03:49 -0700609 case 'E': case 'G': case 'A':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700610 upper = true;
611 break;
612 default:
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700613 internal::report_unknown_type(type, "double");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700614 break;
615 }
616
617 char sign = 0;
Victor Zverovichbe785a82014-07-29 09:14:07 -0700618 // Use getsign instead of value < 0 because the latter is always
Victor Zverovich7cae7632013-09-06 20:23:42 -0700619 // false for NaN.
Victor Zverovichbe785a82014-07-29 09:14:07 -0700620 if (getsign(static_cast<double>(value))) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700621 sign = '-';
622 value = -value;
Victor Zverovichd142e3b2014-07-25 08:29:06 -0700623 } else if (spec.flag(SIGN_FLAG)) {
624 sign = spec.flag(PLUS_FLAG) ? '+' : ' ';
Victor Zverovich7cae7632013-09-06 20:23:42 -0700625 }
626
627 if (value != value) {
628 // Format NaN ourselves because sprintf's output is not consistent
629 // across platforms.
630 std::size_t size = 4;
631 const char *nan = upper ? " NAN" : " nan";
632 if (!sign) {
633 --size;
634 ++nan;
635 }
Victor Zverovich53201032014-06-30 14:26:29 -0700636 CharPtr out = write_str(nan, size, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700637 if (sign)
638 *out = sign;
639 return;
640 }
641
Victor Zverovich1a0c76a2014-08-13 07:51:02 -0700642 if (isinfinity(value)) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700643 // Format infinity ourselves because sprintf's output is not consistent
644 // across platforms.
645 std::size_t size = 4;
646 const char *inf = upper ? " INF" : " inf";
647 if (!sign) {
648 --size;
649 ++inf;
650 }
Victor Zverovich53201032014-06-30 14:26:29 -0700651 CharPtr out = write_str(inf, size, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700652 if (sign)
653 *out = sign;
654 return;
655 }
656
657 std::size_t offset = buffer_.size();
658 unsigned width = spec.width();
659 if (sign) {
660 buffer_.reserve(buffer_.size() + (std::max)(width, 1u));
661 if (width > 0)
662 --width;
663 ++offset;
664 }
665
666 // Build format string.
667 enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg
668 Char format[MAX_FORMAT_SIZE];
669 Char *format_ptr = format;
670 *format_ptr++ = '%';
671 unsigned width_for_sprintf = width;
Victor Zverovichd142e3b2014-07-25 08:29:06 -0700672 if (spec.flag(HASH_FLAG))
Victor Zverovich7cae7632013-09-06 20:23:42 -0700673 *format_ptr++ = '#';
674 if (spec.align() == ALIGN_CENTER) {
675 width_for_sprintf = 0;
676 } else {
677 if (spec.align() == ALIGN_LEFT)
678 *format_ptr++ = '-';
679 if (width != 0)
680 *format_ptr++ = '*';
681 }
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700682 if (spec.precision() >= 0) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700683 *format_ptr++ = '.';
684 *format_ptr++ = '*';
685 }
Victor Zverovichfb321612014-08-15 08:40:03 -0700686 if (IsLongDouble<T>::VALUE)
Victor Zverovich7cae7632013-09-06 20:23:42 -0700687 *format_ptr++ = 'L';
688 *format_ptr++ = type;
689 *format_ptr = '\0';
690
691 // Format using snprintf.
Victor Zverovich88972f42013-09-08 13:30:14 -0700692 Char fill = static_cast<Char>(spec.fill());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700693 for (;;) {
694 std::size_t size = buffer_.capacity() - offset;
Victor Zverovich33baa8f2014-04-23 18:37:08 -0700695#if _MSC_VER
696 // MSVC's vsnprintf_s doesn't work with zero size, so reserve
697 // space for at least one extra character to make the size non-zero.
698 // Note that the buffer's capacity will increase by more than 1.
699 if (size == 0) {
700 buffer_.reserve(offset + 1);
701 size = buffer_.capacity() - offset;
702 }
703#endif
Victor Zverovich7cae7632013-09-06 20:23:42 -0700704 Char *start = &buffer_[offset];
Victor Zverovichb498ba02014-07-26 08:03:03 -0700705 int n = internal::CharTraits<Char>::format_float(
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700706 start, size, format, width_for_sprintf, spec.precision(), value);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700707 if (n >= 0 && offset + n < buffer_.capacity()) {
708 if (sign) {
709 if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) ||
710 *start != ' ') {
711 *(start - 1) = sign;
712 sign = 0;
713 } else {
Victor Zverovich88972f42013-09-08 13:30:14 -0700714 *(start - 1) = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700715 }
716 ++n;
717 }
718 if (spec.align() == ALIGN_CENTER &&
719 spec.width() > static_cast<unsigned>(n)) {
720 unsigned width = spec.width();
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700721 CharPtr p = grow_buffer(width);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700722 std::copy(p, p + n, p + (width - n) / 2);
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700723 fill_padding(p, spec.width(), n, fill);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700724 return;
725 }
726 if (spec.fill() != ' ' || sign) {
727 while (*start == ' ')
Victor Zverovich88972f42013-09-08 13:30:14 -0700728 *start++ = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700729 if (sign)
730 *(start - 1) = sign;
731 }
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700732 grow_buffer(n);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700733 return;
734 }
Victor Zverovichcfeba452014-04-23 18:37:49 -0700735 // If n is negative we ask to increase the capacity by at least 1,
736 // but as std::vector, the buffer grows exponentially.
737 buffer_.reserve(n >= 0 ? offset + n + 1 : buffer_.capacity() + 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700738 }
739}
740
Victor Zverovich7cae7632013-09-06 20:23:42 -0700741template <typename Char>
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700742template <typename StrChar>
Victor Zverovich53201032014-06-30 14:26:29 -0700743void fmt::BasicWriter<Char>::write_str(
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700744 const Arg::StringValue<StrChar> &str, const FormatSpec &spec) {
745 // Check if StrChar is convertible to Char.
746 internal::CharTraits<Char>::convert(StrChar());
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700747 if (spec.type_ && spec.type_ != 's')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700748 internal::report_unknown_type(spec.type_, "string");
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700749 const StrChar *s = str.value;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700750 std::size_t size = str.size;
751 if (size == 0) {
752 if (!s)
753 throw FormatError("string pointer is null");
754 if (*s)
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700755 size = std::char_traits<StrChar>::length(s);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700756 }
Victor Zverovich53201032014-06-30 14:26:29 -0700757 write_str(s, size, spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700758}
759
760template <typename Char>
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700761inline const Arg
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700762 &fmt::BasicFormatter<Char>::parse_arg_index(const Char *&s) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700763 unsigned arg_index = 0;
764 if (*s < '0' || *s > '9') {
765 if (*s != '}' && *s != ':')
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700766 report_error_(s, "invalid argument index in format string");
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700767 const Arg &arg = next_arg();
768 if (error_)
769 report_error_(s, error_);
770 return arg;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700771 }
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700772 if (next_arg_index_ > 0) {
773 report_error_(s,
774 "cannot switch from automatic to manual argument indexing");
775 }
776 next_arg_index_ = -1;
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700777 arg_index = parse_nonnegative_int(s, error_);
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700778 if (error_)
779 report_error_(s, error_); // TODO: don't use report_error_
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700780 if (arg_index >= args_.size())
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700781 report_error_(s, "argument index is out of range in format");
Victor Zverovich656a8372014-04-22 08:58:54 -0700782 return args_[arg_index];
Victor Zverovich7cae7632013-09-06 20:23:42 -0700783}
784
785template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700786void fmt::BasicFormatter<Char>::check_sign(
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700787 const Char *&s, const Arg &arg) {
Victor Zverovichcc6af502013-12-10 08:01:08 -0800788 char sign = static_cast<char>(*s);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700789 if (arg.type > Arg::LAST_NUMERIC_TYPE) {
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700790 report_error_(s, fmt::format(
791 "format specifier '{}' requires numeric argument", sign).c_str());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700792 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700793 if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700794 report_error_(s, fmt::format(
795 "format specifier '{}' requires signed argument", sign).c_str());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700796 }
797 ++s;
798}
799
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700800const Arg &fmt::internal::FormatterBase::next_arg() {
801 if (next_arg_index_ < 0) {
802 if (!error_)
803 error_ = "cannot switch from manual to automatic argument indexing";
804 return DUMMY_ARG;
805 }
806 unsigned arg_index = next_arg_index_++;
807 if (arg_index < args_.size())
808 return args_[arg_index];
809 if (!error_)
810 error_ = "argument index is out of range in format";
811 return DUMMY_ARG;
812}
813
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700814const Arg &fmt::internal::FormatterBase::handle_arg_index(unsigned arg_index) {
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700815 if (arg_index != UINT_MAX) {
816 if (next_arg_index_ <= 0) {
817 next_arg_index_ = -1;
818 --arg_index;
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700819 } else if (!error_) {
820 error_ = "cannot switch from automatic to manual argument indexing";
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700821 }
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700822 if (arg_index < args_.size())
823 return args_[arg_index];
824 if (!error_)
825 error_ = "argument index is out of range in format";
826 return DUMMY_ARG;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700827 }
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700828 return next_arg();
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700829}
830
Victor Zverovich7cae7632013-09-06 20:23:42 -0700831template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700832void fmt::internal::PrintfFormatter<Char>::parse_flags(
Victor Zverovichcb743c02014-06-19 07:40:35 -0700833 FormatSpec &spec, const Char *&s) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700834 for (;;) {
Victor Zverovich1b801482014-06-07 08:57:55 -0700835 switch (*s++) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700836 case '-':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700837 spec.align_ = ALIGN_LEFT;
838 break;
839 case '+':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700840 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
841 break;
842 case '0':
843 spec.fill_ = '0';
Victor Zverovich1b801482014-06-07 08:57:55 -0700844 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700845 case ' ':
Victor Zverovich1b801482014-06-07 08:57:55 -0700846 spec.flags_ |= SIGN_FLAG;
847 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700848 case '#':
Victor Zverovichcb743c02014-06-19 07:40:35 -0700849 spec.flags_ |= HASH_FLAG;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700850 break;
851 default:
Victor Zverovich1b801482014-06-07 08:57:55 -0700852 --s;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700853 return;
854 }
855 }
856}
857
Victor Zverovichcb743c02014-06-19 07:40:35 -0700858template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700859unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700860 const Char *&s, FormatSpec &spec) {
Victor Zverovichcb743c02014-06-19 07:40:35 -0700861 unsigned arg_index = UINT_MAX;
862 Char c = *s;
863 if (c >= '0' && c <= '9') {
864 // Parse an argument index (if followed by '$') or a width possibly
Victor Zverovich879838a2014-06-20 07:34:02 -0700865 // preceded with '0' flag(s).
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700866 unsigned value = parse_nonnegative_int(s, error_);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700867 if (*s == '$') { // value is an argument index
868 ++s;
869 arg_index = value;
870 } else {
871 if (c == '0')
872 spec.fill_ = '0';
873 if (value != 0) {
874 // Nonzero value means that we parsed width and don't need to
875 // parse it or flags again, so return now.
876 spec.width_ = value;
877 return arg_index;
878 }
879 }
880 }
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700881 parse_flags(spec, s);
Victor Zverovich4099a122014-06-23 08:10:50 -0700882 // Parse width.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700883 if (*s >= '0' && *s <= '9') {
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700884 spec.width_ = parse_nonnegative_int(s, error_);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700885 } else if (*s == '*') {
886 ++s;
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700887 spec.width_ = WidthHandler(spec).visit(handle_arg_index(UINT_MAX));
Victor Zverovichcb743c02014-06-19 07:40:35 -0700888 }
889 return arg_index;
890}
891
Victor Zverovich1f19b982014-06-16 07:49:30 -0700892template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700893void fmt::internal::PrintfFormatter<Char>::format(
Victor Zveroviche78904b2014-04-23 08:27:50 -0700894 BasicWriter<Char> &writer, BasicStringRef<Char> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700895 const ArgList &args) {
Victor Zveroviche78904b2014-04-23 08:27:50 -0700896 const Char *start = format.c_str();
Victor Zveroviche78904b2014-04-23 08:27:50 -0700897 args_ = args;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700898 next_arg_index_ = 0;
899 const Char *s = start;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700900 while (*s) {
Victor Zverovich0fc73162013-09-07 12:52:52 -0700901 Char c = *s++;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700902 if (c != '%') continue;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700903 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -0700904 write(writer, start, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700905 start = ++s;
906 continue;
907 }
Victor Zverovichc1db2932014-07-24 08:53:27 -0700908 write(writer, start, s - 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700909
Victor Zverovichcb743c02014-06-19 07:40:35 -0700910 FormatSpec spec;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700911 spec.align_ = ALIGN_RIGHT;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700912
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700913 // Reporting errors is delayed till the format specification is
914 // completely parsed. This is done to avoid potentially confusing
915 // error messages for incomplete format strings. For example, in
916 // sprintf("%2$", 42);
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700917 // the format specification is incomplete. In a naive approach we
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700918 // would parse 2 as an argument index and report an error that the
919 // index is out of range which would be rather confusing if the
920 // use meant "%2d$" rather than "%2$d". If we delay an error, the
921 // user will get an error that the format string is invalid which
922 // is OK for both cases.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700923
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700924 // Parse argument index, flags and width.
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700925 unsigned arg_index = parse_header(s, spec);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700926
927 // Parse precision.
928 if (*s == '.') {
929 ++s;
930 if ('0' <= *s && *s <= '9') {
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700931 spec.precision_ = parse_nonnegative_int(s, error_);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700932 } else if (*s == '*') {
933 ++s;
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700934 spec.precision_ = PrecisionHandler().visit(handle_arg_index(UINT_MAX));
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700935 }
936 }
937
Victor Zverovicheeca2232014-07-30 07:37:16 -0700938 Arg arg = handle_arg_index(arg_index);
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700939 if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
Victor Zverovichcb743c02014-06-19 07:40:35 -0700940 spec.flags_ &= ~HASH_FLAG;
941 if (spec.fill_ == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700942 if (arg.type <= Arg::LAST_NUMERIC_TYPE)
Victor Zverovichcb743c02014-06-19 07:40:35 -0700943 spec.align_ = ALIGN_NUMERIC;
944 else
945 spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700946 }
947
Victor Zverovichf4156b52014-07-30 08:39:07 -0700948 // Parse length and convert the argument to the required type.
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700949 switch (*s++) {
950 case 'h':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700951 if (*s == 'h')
952 ArgConverter<signed char>(arg, *++s).visit(arg);
Victor Zverovich39b09302014-07-30 08:08:08 -0700953 else
Victor Zverovichf4156b52014-07-30 08:39:07 -0700954 ArgConverter<short>(arg, *s).visit(arg);
Victor Zverovicheeca2232014-07-30 07:37:16 -0700955 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700956 case 'l':
Victor Zverovichd3a70392014-08-12 08:36:19 -0700957 if (*s == 'l')
Victor Zveroviche488a282014-08-13 06:53:43 -0700958 ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
Victor Zverovichd3a70392014-08-12 08:36:19 -0700959 else
960 ArgConverter<long>(arg, *s).visit(arg);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700961 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700962 case 'j':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700963 ArgConverter<intmax_t>(arg, *s).visit(arg);
964 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700965 case 'z':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700966 ArgConverter<size_t>(arg, *s).visit(arg);
967 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700968 case 't':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700969 ArgConverter<ptrdiff_t>(arg, *s).visit(arg);
970 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700971 case 'L':
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700972 // printf produces garbage when 'L' is omitted for long double, no
973 // need to do the same.
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700974 break;
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700975 default:
976 --s;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700977 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700978
979 // Parse type.
980 if (!*s)
981 throw FormatError("invalid format string");
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700982 if (error_)
983 throw FormatError(error_);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700984 spec.type_ = static_cast<char>(*s++);
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700985 if (arg.type <= Arg::LAST_INTEGER_TYPE) {
986 // Normalize type.
987 switch (spec.type_) {
988 case 'i': case 'u':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700989 spec.type_ = 'd';
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700990 break;
991 case 'c':
992 // TODO: handle wchar_t
993 CharConverter(arg).visit(arg);
994 break;
995 }
Victor Zverovichf4156b52014-07-30 08:39:07 -0700996 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700997
998 start = s;
999
1000 // Format argument.
Victor Zverovichcb743c02014-06-19 07:40:35 -07001001 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001002 case Arg::INT:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001003 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001004 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001005 case Arg::UINT:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001006 writer.write_int(arg.uint_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001007 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001008 case Arg::LONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001009 writer.write_int(arg.long_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001010 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001011 case Arg::ULONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001012 writer.write_int(arg.ulong_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001013 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001014 case Arg::CHAR: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001015 if (spec.type_ && spec.type_ != 'c')
Victor Zverovichc1db2932014-07-24 08:53:27 -07001016 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001017 typedef typename BasicWriter<Char>::CharPtr CharPtr;
1018 CharPtr out = CharPtr();
1019 if (spec.width_ > 1) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001020 Char fill = ' ';
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001021 out = writer.grow_buffer(spec.width_);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001022 if (spec.align_ != ALIGN_LEFT) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001023 std::fill_n(out, spec.width_ - 1, fill);
1024 out += spec.width_ - 1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001025 } else {
1026 std::fill_n(out + 1, spec.width_ - 1, fill);
1027 }
1028 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001029 out = writer.grow_buffer(1);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001030 }
Victor Zverovichcb743c02014-06-19 07:40:35 -07001031 *out = static_cast<Char>(arg.int_value);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001032 break;
1033 }
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001034 case Arg::DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001035 writer.write_double(arg.double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001036 break;
1037 case Arg::LONG_DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001038 writer.write_double(arg.long_double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001039 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001040 case Arg::STRING:
Victor Zverovich53201032014-06-30 14:26:29 -07001041 writer.write_str(arg.string, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001042 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001043 case Arg::WSTRING:
Victor Zverovich512e2ce2014-07-14 08:47:03 -07001044 writer.write_str(ignore_incompatible_str<Char>(arg.wstring), spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001045 break;
1046 case Arg::POINTER:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001047 if (spec.type_ && spec.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001048 internal::report_unknown_type(spec.type_, "pointer");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001049 spec.flags_= HASH_FLAG;
1050 spec.type_ = 'x';
Victor Zverovichc1db2932014-07-24 08:53:27 -07001051 writer.write_int(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001052 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001053 case Arg::CUSTOM:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001054 if (spec.type_)
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001055 internal::report_unknown_type(spec.type_, "object");
Victor Zveroviche8251562014-07-08 16:20:33 -07001056 arg.custom.format(&writer, arg.custom.value, "s");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001057 break;
1058 default:
1059 assert(false);
1060 break;
1061 }
1062 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001063 write(writer, start, s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001064}
1065
1066template <typename Char>
Victor Zverovichb9a06ba2014-07-08 16:38:50 -07001067const Char *fmt::BasicFormatter<Char>::format(
Victor Zverovich512e2ce2014-07-14 08:47:03 -07001068 const Char *format_str, const Arg &arg) {
Victor Zveroviche8251562014-07-08 16:20:33 -07001069 const Char *s = format_str;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001070 const char *error = 0;
Victor Zveroviche8251562014-07-08 16:20:33 -07001071 FormatSpec spec;
1072 if (*s == ':') {
1073 if (arg.type == Arg::CUSTOM) {
1074 arg.custom.format(this, arg.custom.value, s);
1075 return find_closing_brace(s) + 1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001076 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001077 ++s;
1078 // Parse fill and alignment.
1079 if (Char c = *s) {
1080 const Char *p = s + 1;
1081 spec.align_ = ALIGN_DEFAULT;
1082 do {
1083 switch (*p) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001084 case '<':
1085 spec.align_ = ALIGN_LEFT;
1086 break;
1087 case '>':
1088 spec.align_ = ALIGN_RIGHT;
1089 break;
1090 case '=':
1091 spec.align_ = ALIGN_NUMERIC;
1092 break;
1093 case '^':
1094 spec.align_ = ALIGN_CENTER;
1095 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001096 }
1097 if (spec.align_ != ALIGN_DEFAULT) {
1098 if (p != s) {
1099 if (c == '}') break;
1100 if (c == '{')
1101 report_error_(s, "invalid fill character '{'");
1102 s += 2;
1103 spec.fill_ = c;
1104 } else ++s;
1105 if (spec.align_ == ALIGN_NUMERIC && arg.type > Arg::LAST_NUMERIC_TYPE)
1106 report_error_(s, "format specifier '=' requires numeric argument");
1107 break;
1108 }
1109 } while (--p >= s);
1110 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001111
Victor Zveroviche8251562014-07-08 16:20:33 -07001112 // Parse sign.
1113 switch (*s) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001114 case '+':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001115 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001116 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
1117 break;
1118 case '-':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001119 check_sign(s, arg);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001120 spec.flags_ |= MINUS_FLAG;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001121 break;
1122 case ' ':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001123 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001124 spec.flags_ |= SIGN_FLAG;
1125 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001126 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001127
Victor Zveroviche8251562014-07-08 16:20:33 -07001128 if (*s == '#') {
1129 if (arg.type > Arg::LAST_NUMERIC_TYPE)
1130 report_error_(s, "format specifier '#' requires numeric argument");
1131 spec.flags_ |= HASH_FLAG;
1132 ++s;
1133 }
1134
1135 // Parse width and zero flag.
1136 if ('0' <= *s && *s <= '9') {
1137 if (*s == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001138 if (arg.type > Arg::LAST_NUMERIC_TYPE)
Victor Zveroviche8251562014-07-08 16:20:33 -07001139 report_error_(s, "format specifier '0' requires numeric argument");
1140 spec.align_ = ALIGN_NUMERIC;
1141 spec.fill_ = '0';
Victor Zverovich7cae7632013-09-06 20:23:42 -07001142 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001143 // Zero may be parsed again as a part of the width, but it is simpler
1144 // and more efficient than checking if the next char is a digit.
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001145 spec.width_ = parse_nonnegative_int(s, error);
Victor Zveroviche8251562014-07-08 16:20:33 -07001146 if (error)
1147 report_error_(s, error);
1148 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001149
Victor Zveroviche8251562014-07-08 16:20:33 -07001150 // Parse precision.
1151 if (*s == '.') {
1152 ++s;
1153 spec.precision_ = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001154 if ('0' <= *s && *s <= '9') {
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001155 spec.precision_ = parse_nonnegative_int(s, error);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001156 if (error)
1157 report_error_(s, error);
Victor Zveroviche8251562014-07-08 16:20:33 -07001158 } else if (*s == '{') {
Victor Zverovich7cae7632013-09-06 20:23:42 -07001159 ++s;
Victor Zveroviche8251562014-07-08 16:20:33 -07001160 ++report_error_.num_open_braces;
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001161 const Arg &precision_arg = parse_arg_index(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001162 ULongLong value = 0;
1163 switch (precision_arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001164 case Arg::INT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001165 if (precision_arg.int_value < 0)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001166 report_error_(s, "negative precision in format");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001167 value = precision_arg.int_value;
1168 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001169 case Arg::UINT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001170 value = precision_arg.uint_value;
1171 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001172 case Arg::LONG_LONG:
Victor Zverovich56f12b72013-11-22 07:45:43 -08001173 if (precision_arg.long_long_value < 0)
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001174 report_error_(s, "negative precision in format");
Victor Zverovich56f12b72013-11-22 07:45:43 -08001175 value = precision_arg.long_long_value;
1176 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001177 case Arg::ULONG_LONG:
Gregory Czajkowskia65542b2013-11-18 22:58:39 -08001178 value = precision_arg.ulong_long_value;
Victor Zverovicha4e72b42013-11-21 09:11:58 -08001179 break;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001180 default:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001181 report_error_(s, "precision is not integer");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001182 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001183 if (value > INT_MAX)
1184 report_error_(s, "number is too big in format");
1185 spec.precision_ = static_cast<int>(value);
1186 if (*s++ != '}')
1187 throw FormatError("unmatched '{' in format");
1188 --report_error_.num_open_braces;
1189 } else {
1190 report_error_(s, "missing precision in format");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001191 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001192 if (arg.type != Arg::DOUBLE && arg.type != Arg::LONG_DOUBLE) {
1193 report_error_(s,
1194 "precision specifier requires floating-point argument");
1195 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001196 }
1197
Victor Zveroviche8251562014-07-08 16:20:33 -07001198 // Parse type.
1199 if (*s != '}' && *s)
1200 spec.type_ = static_cast<char>(*s++);
1201 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001202
Victor Zveroviche8251562014-07-08 16:20:33 -07001203 if (*s++ != '}')
1204 throw FormatError("unmatched '{' in format");
1205 start_ = s;
1206
1207 // Format argument.
Victor Zverovich4edc88f2014-07-16 08:38:15 -07001208 internal::ArgFormatter<Char>(*this, spec, s - 1).visit(arg);
Victor Zveroviche8251562014-07-08 16:20:33 -07001209 return s;
1210}
1211
1212template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001213void fmt::BasicFormatter<Char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001214 BasicStringRef<Char> format_str, const ArgList &args) {
1215 const Char *s = start_ = format_str.c_str();
1216 args_ = args;
1217 next_arg_index_ = 0;
1218 while (*s) {
1219 Char c = *s++;
1220 if (c != '{' && c != '}') continue;
1221 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -07001222 write(writer_, start_, s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001223 start_ = ++s;
1224 continue;
1225 }
1226 if (c == '}')
1227 throw FormatError("unmatched '}' in format");
1228 report_error_.num_open_braces = 1;
Victor Zverovichc1db2932014-07-24 08:53:27 -07001229 write(writer_, start_, s - 1);
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001230 Arg arg = parse_arg_index(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001231 s = format(s, arg);
1232 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001233 write(writer_, start_, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001234}
1235
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001236void fmt::report_system_error(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001237 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
Victor Zverovich75b5eb42014-07-27 15:09:05 -07001238 // FIXME: format_system_error may throw
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001239 report_error(internal::format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001240}
1241
Victor Zverovich400812a2014-04-30 12:38:17 -07001242#ifdef _WIN32
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001243void fmt::report_windows_error(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001244 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
Victor Zverovich75b5eb42014-07-27 15:09:05 -07001245 // FIXME: format_windows_error may throw
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001246 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001247}
Victor Zverovich400812a2014-04-30 12:38:17 -07001248#endif
Victor Zverovichf7939862014-04-30 10:18:11 -07001249
Victor Zverovich2e039632014-06-28 19:44:39 -07001250void fmt::print(StringRef format, const ArgList &args) {
1251 Writer w;
Victor Zverovicha1264922014-06-29 11:51:10 -07001252 w.write(format, args);
Victor Zverovich2e039632014-06-28 19:44:39 -07001253 std::fwrite(w.data(), 1, w.size(), stdout);
1254}
1255
Victor Zverovichd5b81962014-06-28 21:56:40 -07001256void fmt::print(std::FILE *f, StringRef format, const ArgList &args) {
1257 Writer w;
Victor Zverovicha1264922014-06-29 11:51:10 -07001258 w.write(format, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001259 std::fwrite(w.data(), 1, w.size(), f);
1260}
1261
Victor Zveroviche3a44c12014-07-09 06:56:36 -07001262void fmt::print(std::ostream &os, StringRef format, const ArgList &args) {
1263 Writer w;
1264 w.write(format, args);
1265 os.write(w.data(), w.size());
1266}
1267
Victor Zverovich2dc108b2014-07-01 09:10:43 -07001268void fmt::print_colored(Color c, StringRef format, const ArgList &args) {
1269 char escape[] = "\x1b[30m";
1270 escape[3] = '0' + static_cast<char>(c);
1271 std::fputs(escape, stdout);
1272 print(format, args);
1273 std::fputs(RESET_COLOR, stdout);
1274}
1275
Victor Zverovichd5b81962014-06-28 21:56:40 -07001276void fmt::printf(StringRef format, const ArgList &args) {
1277 Writer w;
Victor Zverovich21111cc2014-06-29 19:52:26 -07001278 printf(w, format, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001279 std::fwrite(w.data(), 1, w.size(), stdout);
1280}
1281
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001282// Explicit instantiations for char.
1283
Victor Zverovich93e41252013-09-08 13:07:04 -07001284template fmt::BasicWriter<char>::CharPtr
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001285 fmt::BasicWriter<char>::fill_padding(CharPtr buffer,
Victor Zverovich93e41252013-09-08 13:07:04 -07001286 unsigned total_size, std::size_t content_size, wchar_t fill);
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001287
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001288template void fmt::BasicFormatter<char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001289 BasicStringRef<char> format, const ArgList &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001290
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001291template void fmt::internal::PrintfFormatter<char>::format(
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001292 BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001293
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001294// Explicit instantiations for wchar_t.
1295
Victor Zverovich7cae7632013-09-06 20:23:42 -07001296template fmt::BasicWriter<wchar_t>::CharPtr
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001297 fmt::BasicWriter<wchar_t>::fill_padding(CharPtr buffer,
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001298 unsigned total_size, std::size_t content_size, wchar_t fill);
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001299
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001300template void fmt::BasicFormatter<wchar_t>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001301 BasicStringRef<wchar_t> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001302
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001303template void fmt::internal::PrintfFormatter<wchar_t>::format(
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001304 BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001305 const ArgList &args);
jdale88a9862fd2014-03-11 18:56:24 +00001306
1307#if _MSC_VER
1308# pragma warning(pop)
1309#endif