blob: f31c70bb06cf84e88959da8078e11b1adf60254c [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 Zverovich7cae7632013-09-06 20:23:42 -0700568// Fills the padding around the content and returns the pointer to the
569// content area.
570template <typename Char>
Victor Zverovich93e41252013-09-08 13:07:04 -0700571typename fmt::BasicWriter<Char>::CharPtr
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700572 fmt::BasicWriter<Char>::fill_padding(CharPtr buffer,
Victor Zverovich93e41252013-09-08 13:07:04 -0700573 unsigned total_size, std::size_t content_size, wchar_t fill) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700574 std::size_t padding = total_size - content_size;
575 std::size_t left_padding = padding / 2;
Victor Zverovich563a5752013-09-08 13:47:06 -0700576 Char fill_char = static_cast<Char>(fill);
577 std::fill_n(buffer, left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700578 buffer += left_padding;
579 CharPtr content = buffer;
Victor Zverovich563a5752013-09-08 13:47:06 -0700580 std::fill_n(buffer + content_size, padding - left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700581 return content;
582}
583
584template <typename Char>
Victor Zverovich7cae7632013-09-06 20:23:42 -0700585template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700586void fmt::BasicWriter<Char>::write_double(T value, const FormatSpec &spec) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700587 // Check type.
588 char type = spec.type();
589 bool upper = false;
590 switch (type) {
591 case 0:
592 type = 'g';
593 break;
Victor Zverovich03776dd2014-06-10 07:03:49 -0700594 case 'e': case 'f': case 'g': case 'a':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700595 break;
596 case 'F':
597#ifdef _MSC_VER
598 // MSVC's printf doesn't support 'F'.
599 type = 'f';
600#endif
601 // Fall through.
Victor Zverovich03776dd2014-06-10 07:03:49 -0700602 case 'E': case 'G': case 'A':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700603 upper = true;
604 break;
605 default:
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700606 internal::report_unknown_type(type, "double");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700607 break;
608 }
609
610 char sign = 0;
Victor Zverovichbe785a82014-07-29 09:14:07 -0700611 // Use getsign instead of value < 0 because the latter is always
Victor Zverovich7cae7632013-09-06 20:23:42 -0700612 // false for NaN.
Victor Zverovichbe785a82014-07-29 09:14:07 -0700613 if (getsign(static_cast<double>(value))) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700614 sign = '-';
615 value = -value;
Victor Zverovichd142e3b2014-07-25 08:29:06 -0700616 } else if (spec.flag(SIGN_FLAG)) {
617 sign = spec.flag(PLUS_FLAG) ? '+' : ' ';
Victor Zverovich7cae7632013-09-06 20:23:42 -0700618 }
619
620 if (value != value) {
621 // Format NaN ourselves because sprintf's output is not consistent
622 // across platforms.
623 std::size_t size = 4;
624 const char *nan = upper ? " NAN" : " nan";
625 if (!sign) {
626 --size;
627 ++nan;
628 }
Victor Zverovich53201032014-06-30 14:26:29 -0700629 CharPtr out = write_str(nan, size, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700630 if (sign)
631 *out = sign;
632 return;
633 }
634
Victor Zverovich1a0c76a2014-08-13 07:51:02 -0700635 if (isinfinity(value)) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700636 // Format infinity ourselves because sprintf's output is not consistent
637 // across platforms.
638 std::size_t size = 4;
639 const char *inf = upper ? " INF" : " inf";
640 if (!sign) {
641 --size;
642 ++inf;
643 }
Victor Zverovich53201032014-06-30 14:26:29 -0700644 CharPtr out = write_str(inf, size, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700645 if (sign)
646 *out = sign;
647 return;
648 }
649
650 std::size_t offset = buffer_.size();
651 unsigned width = spec.width();
652 if (sign) {
653 buffer_.reserve(buffer_.size() + (std::max)(width, 1u));
654 if (width > 0)
655 --width;
656 ++offset;
657 }
658
659 // Build format string.
660 enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg
661 Char format[MAX_FORMAT_SIZE];
662 Char *format_ptr = format;
663 *format_ptr++ = '%';
664 unsigned width_for_sprintf = width;
Victor Zverovichd142e3b2014-07-25 08:29:06 -0700665 if (spec.flag(HASH_FLAG))
Victor Zverovich7cae7632013-09-06 20:23:42 -0700666 *format_ptr++ = '#';
667 if (spec.align() == ALIGN_CENTER) {
668 width_for_sprintf = 0;
669 } else {
670 if (spec.align() == ALIGN_LEFT)
671 *format_ptr++ = '-';
672 if (width != 0)
673 *format_ptr++ = '*';
674 }
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700675 if (spec.precision() >= 0) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700676 *format_ptr++ = '.';
677 *format_ptr++ = '*';
678 }
Victor Zverovichfb321612014-08-15 08:40:03 -0700679 if (IsLongDouble<T>::VALUE)
Victor Zverovich7cae7632013-09-06 20:23:42 -0700680 *format_ptr++ = 'L';
681 *format_ptr++ = type;
682 *format_ptr = '\0';
683
684 // Format using snprintf.
Victor Zverovich88972f42013-09-08 13:30:14 -0700685 Char fill = static_cast<Char>(spec.fill());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700686 for (;;) {
687 std::size_t size = buffer_.capacity() - offset;
Victor Zverovich33baa8f2014-04-23 18:37:08 -0700688#if _MSC_VER
689 // MSVC's vsnprintf_s doesn't work with zero size, so reserve
690 // space for at least one extra character to make the size non-zero.
691 // Note that the buffer's capacity will increase by more than 1.
692 if (size == 0) {
693 buffer_.reserve(offset + 1);
694 size = buffer_.capacity() - offset;
695 }
696#endif
Victor Zverovich7cae7632013-09-06 20:23:42 -0700697 Char *start = &buffer_[offset];
Victor Zverovichb498ba02014-07-26 08:03:03 -0700698 int n = internal::CharTraits<Char>::format_float(
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700699 start, size, format, width_for_sprintf, spec.precision(), value);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700700 if (n >= 0 && offset + n < buffer_.capacity()) {
701 if (sign) {
702 if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) ||
703 *start != ' ') {
704 *(start - 1) = sign;
705 sign = 0;
706 } else {
Victor Zverovich88972f42013-09-08 13:30:14 -0700707 *(start - 1) = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700708 }
709 ++n;
710 }
711 if (spec.align() == ALIGN_CENTER &&
712 spec.width() > static_cast<unsigned>(n)) {
713 unsigned width = spec.width();
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700714 CharPtr p = grow_buffer(width);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700715 std::copy(p, p + n, p + (width - n) / 2);
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700716 fill_padding(p, spec.width(), n, fill);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700717 return;
718 }
719 if (spec.fill() != ' ' || sign) {
720 while (*start == ' ')
Victor Zverovich88972f42013-09-08 13:30:14 -0700721 *start++ = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700722 if (sign)
723 *(start - 1) = sign;
724 }
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700725 grow_buffer(n);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700726 return;
727 }
Victor Zverovichcfeba452014-04-23 18:37:49 -0700728 // If n is negative we ask to increase the capacity by at least 1,
729 // but as std::vector, the buffer grows exponentially.
730 buffer_.reserve(n >= 0 ? offset + n + 1 : buffer_.capacity() + 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700731 }
732}
733
Victor Zverovich7cae7632013-09-06 20:23:42 -0700734template <typename Char>
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700735template <typename StrChar>
Victor Zverovich53201032014-06-30 14:26:29 -0700736void fmt::BasicWriter<Char>::write_str(
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700737 const Arg::StringValue<StrChar> &str, const FormatSpec &spec) {
738 // Check if StrChar is convertible to Char.
739 internal::CharTraits<Char>::convert(StrChar());
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700740 if (spec.type_ && spec.type_ != 's')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700741 internal::report_unknown_type(spec.type_, "string");
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700742 const StrChar *s = str.value;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700743 std::size_t size = str.size;
744 if (size == 0) {
745 if (!s)
746 throw FormatError("string pointer is null");
747 if (*s)
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700748 size = std::char_traits<StrChar>::length(s);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700749 }
Victor Zverovich53201032014-06-30 14:26:29 -0700750 write_str(s, size, spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700751}
752
753template <typename Char>
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700754inline const Arg
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700755 &fmt::BasicFormatter<Char>::parse_arg_index(const Char *&s) {
Victor Zverovichda0f7c02014-08-27 09:04:51 -0700756 const Arg *arg = 0;
Victor Zverovich9646e382014-08-27 09:13:42 -0700757 const char *error = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700758 if (*s < '0' || *s > '9') {
Victor Zverovich9646e382014-08-27 09:13:42 -0700759 arg = &next_arg(error);
Victor Zverovichda0f7c02014-08-27 09:04:51 -0700760 } else {
761 if (next_arg_index_ > 0)
Victor Zverovich9646e382014-08-27 09:13:42 -0700762 error = "cannot switch from automatic to manual argument indexing";
Victor Zverovichda0f7c02014-08-27 09:04:51 -0700763 next_arg_index_ = -1;
Victor Zverovich9646e382014-08-27 09:13:42 -0700764 unsigned arg_index = parse_nonnegative_int(s, error);
Victor Zverovichda0f7c02014-08-27 09:04:51 -0700765 if (arg_index < args_.size())
766 arg = &args_[arg_index];
Victor Zverovich9646e382014-08-27 09:13:42 -0700767 else if (!error)
768 error = "argument index is out of range in format";
Victor Zverovich7cae7632013-09-06 20:23:42 -0700769 }
Victor Zverovich9646e382014-08-27 09:13:42 -0700770 if (error)
771 throw FormatError(*s != '}' && *s != ':' ? "invalid format string" : error);
Victor Zverovichda0f7c02014-08-27 09:04:51 -0700772 return *arg;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700773}
774
775template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700776void fmt::BasicFormatter<Char>::check_sign(
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700777 const Char *&s, const Arg &arg) {
Victor Zverovichcc6af502013-12-10 08:01:08 -0800778 char sign = static_cast<char>(*s);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700779 if (arg.type > Arg::LAST_NUMERIC_TYPE) {
Victor Zverovich42de4f12014-08-27 08:24:31 -0700780 throw FormatError(fmt::format(
781 "format specifier '{}' requires numeric argument", sign));
Victor Zverovich7cae7632013-09-06 20:23:42 -0700782 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700783 if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
Victor Zverovich42de4f12014-08-27 08:24:31 -0700784 throw FormatError(fmt::format(
785 "format specifier '{}' requires signed argument", sign));
Victor Zverovich7cae7632013-09-06 20:23:42 -0700786 }
787 ++s;
788}
789
Victor Zverovich9646e382014-08-27 09:13:42 -0700790const Arg &fmt::internal::FormatterBase::next_arg(const char *&error) {
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700791 if (next_arg_index_ < 0) {
Victor Zverovich9646e382014-08-27 09:13:42 -0700792 error = "cannot switch from manual to automatic argument indexing";
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700793 return DUMMY_ARG;
794 }
795 unsigned arg_index = next_arg_index_++;
796 if (arg_index < args_.size())
797 return args_[arg_index];
Victor Zverovich9646e382014-08-27 09:13:42 -0700798 error = "argument index is out of range in format";
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700799 return DUMMY_ARG;
800}
801
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700802const Arg &fmt::internal::FormatterBase::handle_arg_index(unsigned arg_index) {
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700803 if (arg_index != UINT_MAX) {
804 if (next_arg_index_ <= 0) {
805 next_arg_index_ = -1;
806 --arg_index;
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700807 } else if (!error_) {
808 error_ = "cannot switch from automatic to manual argument indexing";
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700809 }
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700810 if (arg_index < args_.size())
811 return args_[arg_index];
812 if (!error_)
813 error_ = "argument index is out of range in format";
814 return DUMMY_ARG;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700815 }
Victor Zverovich9646e382014-08-27 09:13:42 -0700816 return next_arg(error_);
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700817}
818
Victor Zverovich7cae7632013-09-06 20:23:42 -0700819template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700820void fmt::internal::PrintfFormatter<Char>::parse_flags(
Victor Zverovichcb743c02014-06-19 07:40:35 -0700821 FormatSpec &spec, const Char *&s) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700822 for (;;) {
Victor Zverovich1b801482014-06-07 08:57:55 -0700823 switch (*s++) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700824 case '-':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700825 spec.align_ = ALIGN_LEFT;
826 break;
827 case '+':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700828 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
829 break;
830 case '0':
831 spec.fill_ = '0';
Victor Zverovich1b801482014-06-07 08:57:55 -0700832 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700833 case ' ':
Victor Zverovich1b801482014-06-07 08:57:55 -0700834 spec.flags_ |= SIGN_FLAG;
835 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700836 case '#':
Victor Zverovichcb743c02014-06-19 07:40:35 -0700837 spec.flags_ |= HASH_FLAG;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700838 break;
839 default:
Victor Zverovich1b801482014-06-07 08:57:55 -0700840 --s;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700841 return;
842 }
843 }
844}
845
Victor Zverovichcb743c02014-06-19 07:40:35 -0700846template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700847unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700848 const Char *&s, FormatSpec &spec) {
Victor Zverovichcb743c02014-06-19 07:40:35 -0700849 unsigned arg_index = UINT_MAX;
850 Char c = *s;
851 if (c >= '0' && c <= '9') {
852 // Parse an argument index (if followed by '$') or a width possibly
Victor Zverovich879838a2014-06-20 07:34:02 -0700853 // preceded with '0' flag(s).
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700854 unsigned value = parse_nonnegative_int(s, error_);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700855 if (*s == '$') { // value is an argument index
856 ++s;
857 arg_index = value;
858 } else {
859 if (c == '0')
860 spec.fill_ = '0';
861 if (value != 0) {
862 // Nonzero value means that we parsed width and don't need to
863 // parse it or flags again, so return now.
864 spec.width_ = value;
865 return arg_index;
866 }
867 }
868 }
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700869 parse_flags(spec, s);
Victor Zverovich4099a122014-06-23 08:10:50 -0700870 // Parse width.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700871 if (*s >= '0' && *s <= '9') {
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700872 spec.width_ = parse_nonnegative_int(s, error_);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700873 } else if (*s == '*') {
874 ++s;
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700875 spec.width_ = WidthHandler(spec).visit(handle_arg_index(UINT_MAX));
Victor Zverovichcb743c02014-06-19 07:40:35 -0700876 }
877 return arg_index;
878}
879
Victor Zverovich1f19b982014-06-16 07:49:30 -0700880template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700881void fmt::internal::PrintfFormatter<Char>::format(
Victor Zveroviche78904b2014-04-23 08:27:50 -0700882 BasicWriter<Char> &writer, BasicStringRef<Char> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700883 const ArgList &args) {
Victor Zveroviche78904b2014-04-23 08:27:50 -0700884 const Char *start = format.c_str();
Victor Zveroviche78904b2014-04-23 08:27:50 -0700885 args_ = args;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700886 next_arg_index_ = 0;
887 const Char *s = start;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700888 while (*s) {
Victor Zverovich0fc73162013-09-07 12:52:52 -0700889 Char c = *s++;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700890 if (c != '%') continue;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700891 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -0700892 write(writer, start, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700893 start = ++s;
894 continue;
895 }
Victor Zverovichc1db2932014-07-24 08:53:27 -0700896 write(writer, start, s - 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700897
Victor Zverovichcb743c02014-06-19 07:40:35 -0700898 FormatSpec spec;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700899 spec.align_ = ALIGN_RIGHT;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700900
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700901 // Reporting errors is delayed till the format specification is
902 // completely parsed. This is done to avoid potentially confusing
903 // error messages for incomplete format strings. For example, in
904 // sprintf("%2$", 42);
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700905 // the format specification is incomplete. In a naive approach we
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700906 // would parse 2 as an argument index and report an error that the
907 // index is out of range which would be rather confusing if the
908 // use meant "%2d$" rather than "%2$d". If we delay an error, the
909 // user will get an error that the format string is invalid which
910 // is OK for both cases.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700911
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700912 // Parse argument index, flags and width.
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700913 unsigned arg_index = parse_header(s, spec);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700914
915 // Parse precision.
916 if (*s == '.') {
917 ++s;
918 if ('0' <= *s && *s <= '9') {
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700919 spec.precision_ = parse_nonnegative_int(s, error_);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700920 } else if (*s == '*') {
921 ++s;
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700922 spec.precision_ = PrecisionHandler().visit(handle_arg_index(UINT_MAX));
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700923 }
924 }
925
Victor Zverovicheeca2232014-07-30 07:37:16 -0700926 Arg arg = handle_arg_index(arg_index);
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700927 if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
Victor Zverovichcb743c02014-06-19 07:40:35 -0700928 spec.flags_ &= ~HASH_FLAG;
929 if (spec.fill_ == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700930 if (arg.type <= Arg::LAST_NUMERIC_TYPE)
Victor Zverovichcb743c02014-06-19 07:40:35 -0700931 spec.align_ = ALIGN_NUMERIC;
932 else
933 spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700934 }
935
Victor Zverovichf4156b52014-07-30 08:39:07 -0700936 // Parse length and convert the argument to the required type.
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700937 switch (*s++) {
938 case 'h':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700939 if (*s == 'h')
940 ArgConverter<signed char>(arg, *++s).visit(arg);
Victor Zverovich39b09302014-07-30 08:08:08 -0700941 else
Victor Zverovichf4156b52014-07-30 08:39:07 -0700942 ArgConverter<short>(arg, *s).visit(arg);
Victor Zverovicheeca2232014-07-30 07:37:16 -0700943 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700944 case 'l':
Victor Zverovichd3a70392014-08-12 08:36:19 -0700945 if (*s == 'l')
Victor Zveroviche488a282014-08-13 06:53:43 -0700946 ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
Victor Zverovichd3a70392014-08-12 08:36:19 -0700947 else
948 ArgConverter<long>(arg, *s).visit(arg);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700949 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700950 case 'j':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700951 ArgConverter<intmax_t>(arg, *s).visit(arg);
952 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700953 case 'z':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700954 ArgConverter<size_t>(arg, *s).visit(arg);
955 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700956 case 't':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700957 ArgConverter<ptrdiff_t>(arg, *s).visit(arg);
958 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700959 case 'L':
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700960 // printf produces garbage when 'L' is omitted for long double, no
961 // need to do the same.
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700962 break;
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700963 default:
964 --s;
Victor Zverovichbe00d8b2014-08-19 08:49:10 -0700965 ArgConverter<int>(arg, *s).visit(arg);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700966 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700967
968 // Parse type.
969 if (!*s)
970 throw FormatError("invalid format string");
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700971 if (error_)
972 throw FormatError(error_);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700973 spec.type_ = static_cast<char>(*s++);
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700974 if (arg.type <= Arg::LAST_INTEGER_TYPE) {
975 // Normalize type.
976 switch (spec.type_) {
977 case 'i': case 'u':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700978 spec.type_ = 'd';
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700979 break;
980 case 'c':
981 // TODO: handle wchar_t
982 CharConverter(arg).visit(arg);
983 break;
984 }
Victor Zverovichf4156b52014-07-30 08:39:07 -0700985 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700986
987 start = s;
988
989 // Format argument.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700990 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700991 case Arg::INT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700992 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700993 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700994 case Arg::UINT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700995 writer.write_int(arg.uint_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700996 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700997 case Arg::LONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700998 writer.write_int(arg.long_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700999 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001000 case Arg::ULONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001001 writer.write_int(arg.ulong_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001002 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001003 case Arg::CHAR: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001004 if (spec.type_ && spec.type_ != 'c')
Victor Zverovichc1db2932014-07-24 08:53:27 -07001005 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001006 typedef typename BasicWriter<Char>::CharPtr CharPtr;
1007 CharPtr out = CharPtr();
1008 if (spec.width_ > 1) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001009 Char fill = ' ';
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001010 out = writer.grow_buffer(spec.width_);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001011 if (spec.align_ != ALIGN_LEFT) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001012 std::fill_n(out, spec.width_ - 1, fill);
1013 out += spec.width_ - 1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001014 } else {
1015 std::fill_n(out + 1, spec.width_ - 1, fill);
1016 }
1017 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001018 out = writer.grow_buffer(1);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001019 }
Victor Zverovichcb743c02014-06-19 07:40:35 -07001020 *out = static_cast<Char>(arg.int_value);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001021 break;
1022 }
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001023 case Arg::DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001024 writer.write_double(arg.double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001025 break;
1026 case Arg::LONG_DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001027 writer.write_double(arg.long_double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001028 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001029 case Arg::STRING:
Victor Zverovich53201032014-06-30 14:26:29 -07001030 writer.write_str(arg.string, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001031 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001032 case Arg::WSTRING:
Victor Zverovich512e2ce2014-07-14 08:47:03 -07001033 writer.write_str(ignore_incompatible_str<Char>(arg.wstring), spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001034 break;
1035 case Arg::POINTER:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001036 if (spec.type_ && spec.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001037 internal::report_unknown_type(spec.type_, "pointer");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001038 spec.flags_= HASH_FLAG;
1039 spec.type_ = 'x';
Victor Zverovichc1db2932014-07-24 08:53:27 -07001040 writer.write_int(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001041 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001042 case Arg::CUSTOM:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001043 if (spec.type_)
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001044 internal::report_unknown_type(spec.type_, "object");
Victor Zveroviche8251562014-07-08 16:20:33 -07001045 arg.custom.format(&writer, arg.custom.value, "s");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001046 break;
1047 default:
1048 assert(false);
1049 break;
1050 }
1051 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001052 write(writer, start, s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001053}
1054
1055template <typename Char>
Victor Zverovichb9a06ba2014-07-08 16:38:50 -07001056const Char *fmt::BasicFormatter<Char>::format(
Victor Zverovich512e2ce2014-07-14 08:47:03 -07001057 const Char *format_str, const Arg &arg) {
Victor Zveroviche8251562014-07-08 16:20:33 -07001058 const Char *s = format_str;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001059 const char *error = 0;
Victor Zveroviche8251562014-07-08 16:20:33 -07001060 FormatSpec spec;
1061 if (*s == ':') {
1062 if (arg.type == Arg::CUSTOM) {
1063 arg.custom.format(this, arg.custom.value, s);
1064 return find_closing_brace(s) + 1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001065 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001066 ++s;
1067 // Parse fill and alignment.
1068 if (Char c = *s) {
1069 const Char *p = s + 1;
1070 spec.align_ = ALIGN_DEFAULT;
1071 do {
1072 switch (*p) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001073 case '<':
1074 spec.align_ = ALIGN_LEFT;
1075 break;
1076 case '>':
1077 spec.align_ = ALIGN_RIGHT;
1078 break;
1079 case '=':
1080 spec.align_ = ALIGN_NUMERIC;
1081 break;
1082 case '^':
1083 spec.align_ = ALIGN_CENTER;
1084 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001085 }
1086 if (spec.align_ != ALIGN_DEFAULT) {
1087 if (p != s) {
1088 if (c == '}') break;
1089 if (c == '{')
Victor Zverovich42de4f12014-08-27 08:24:31 -07001090 throw FormatError("invalid fill character '{'");
Victor Zveroviche8251562014-07-08 16:20:33 -07001091 s += 2;
1092 spec.fill_ = c;
1093 } else ++s;
1094 if (spec.align_ == ALIGN_NUMERIC && arg.type > Arg::LAST_NUMERIC_TYPE)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001095 throw FormatError("format specifier '=' requires numeric argument");
Victor Zveroviche8251562014-07-08 16:20:33 -07001096 break;
1097 }
1098 } while (--p >= s);
1099 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001100
Victor Zveroviche8251562014-07-08 16:20:33 -07001101 // Parse sign.
1102 switch (*s) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001103 case '+':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001104 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001105 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
1106 break;
1107 case '-':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001108 check_sign(s, arg);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001109 spec.flags_ |= MINUS_FLAG;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001110 break;
1111 case ' ':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001112 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001113 spec.flags_ |= SIGN_FLAG;
1114 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001115 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001116
Victor Zveroviche8251562014-07-08 16:20:33 -07001117 if (*s == '#') {
1118 if (arg.type > Arg::LAST_NUMERIC_TYPE)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001119 // TODO: make FormatError accept arguments
1120 throw FormatError("format specifier '#' requires numeric argument");
Victor Zveroviche8251562014-07-08 16:20:33 -07001121 spec.flags_ |= HASH_FLAG;
1122 ++s;
1123 }
1124
1125 // Parse width and zero flag.
1126 if ('0' <= *s && *s <= '9') {
1127 if (*s == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001128 if (arg.type > Arg::LAST_NUMERIC_TYPE)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001129 throw FormatError("format specifier '0' requires numeric argument");
Victor Zveroviche8251562014-07-08 16:20:33 -07001130 spec.align_ = ALIGN_NUMERIC;
1131 spec.fill_ = '0';
Victor Zverovich7cae7632013-09-06 20:23:42 -07001132 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001133 // Zero may be parsed again as a part of the width, but it is simpler
1134 // and more efficient than checking if the next char is a digit.
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001135 spec.width_ = parse_nonnegative_int(s, error);
Victor Zveroviche8251562014-07-08 16:20:33 -07001136 if (error)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001137 throw FormatError(error);
Victor Zveroviche8251562014-07-08 16:20:33 -07001138 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001139
Victor Zveroviche8251562014-07-08 16:20:33 -07001140 // Parse precision.
1141 if (*s == '.') {
1142 ++s;
1143 spec.precision_ = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001144 if ('0' <= *s && *s <= '9') {
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001145 spec.precision_ = parse_nonnegative_int(s, error);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001146 if (error)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001147 throw FormatError(error);
Victor Zveroviche8251562014-07-08 16:20:33 -07001148 } else if (*s == '{') {
Victor Zverovich7cae7632013-09-06 20:23:42 -07001149 ++s;
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001150 const Arg &precision_arg = parse_arg_index(s);
Victor Zverovich42de4f12014-08-27 08:24:31 -07001151 if (*s++ != '}')
1152 throw FormatError("unmatched '{' in format");
1153 if (error_)
1154 throw FormatError(error_);
Victor Zveroviche8251562014-07-08 16:20:33 -07001155 ULongLong value = 0;
1156 switch (precision_arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001157 case Arg::INT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001158 if (precision_arg.int_value < 0)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001159 throw FormatError("negative precision in format");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001160 value = precision_arg.int_value;
1161 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001162 case Arg::UINT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001163 value = precision_arg.uint_value;
1164 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001165 case Arg::LONG_LONG:
Victor Zverovich56f12b72013-11-22 07:45:43 -08001166 if (precision_arg.long_long_value < 0)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001167 throw FormatError("negative precision in format");
Victor Zverovich56f12b72013-11-22 07:45:43 -08001168 value = precision_arg.long_long_value;
1169 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001170 case Arg::ULONG_LONG:
Gregory Czajkowskia65542b2013-11-18 22:58:39 -08001171 value = precision_arg.ulong_long_value;
Victor Zverovicha4e72b42013-11-21 09:11:58 -08001172 break;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001173 default:
Victor Zverovich42de4f12014-08-27 08:24:31 -07001174 throw FormatError("precision is not integer");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001175 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001176 if (value > INT_MAX)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001177 throw FormatError("number is too big in format");
Victor Zveroviche8251562014-07-08 16:20:33 -07001178 spec.precision_ = static_cast<int>(value);
Victor Zveroviche8251562014-07-08 16:20:33 -07001179 } else {
Victor Zverovich42de4f12014-08-27 08:24:31 -07001180 throw FormatError("missing precision in format");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001181 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001182 if (arg.type != Arg::DOUBLE && arg.type != Arg::LONG_DOUBLE) {
Victor Zverovich42de4f12014-08-27 08:24:31 -07001183 throw FormatError(
Victor Zveroviche8251562014-07-08 16:20:33 -07001184 "precision specifier requires floating-point argument");
1185 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001186 }
1187
Victor Zveroviche8251562014-07-08 16:20:33 -07001188 // Parse type.
1189 if (*s != '}' && *s)
1190 spec.type_ = static_cast<char>(*s++);
1191 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001192
Victor Zveroviche8251562014-07-08 16:20:33 -07001193 if (*s++ != '}')
1194 throw FormatError("unmatched '{' in format");
1195 start_ = s;
1196
1197 // Format argument.
Victor Zverovich4edc88f2014-07-16 08:38:15 -07001198 internal::ArgFormatter<Char>(*this, spec, s - 1).visit(arg);
Victor Zveroviche8251562014-07-08 16:20:33 -07001199 return s;
1200}
1201
1202template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001203void fmt::BasicFormatter<Char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001204 BasicStringRef<Char> format_str, const ArgList &args) {
1205 const Char *s = start_ = format_str.c_str();
1206 args_ = args;
1207 next_arg_index_ = 0;
1208 while (*s) {
1209 Char c = *s++;
1210 if (c != '{' && c != '}') continue;
1211 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -07001212 write(writer_, start_, s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001213 start_ = ++s;
1214 continue;
1215 }
1216 if (c == '}')
1217 throw FormatError("unmatched '}' in format");
Victor Zverovichc1db2932014-07-24 08:53:27 -07001218 write(writer_, start_, s - 1);
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001219 Arg arg = parse_arg_index(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001220 s = format(s, arg);
1221 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001222 write(writer_, start_, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001223}
1224
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001225void fmt::report_system_error(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001226 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
Victor Zverovich75b5eb42014-07-27 15:09:05 -07001227 // FIXME: format_system_error may throw
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001228 report_error(internal::format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001229}
1230
Victor Zverovich400812a2014-04-30 12:38:17 -07001231#ifdef _WIN32
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001232void fmt::report_windows_error(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001233 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
Victor Zverovich75b5eb42014-07-27 15:09:05 -07001234 // FIXME: format_windows_error may throw
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001235 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001236}
Victor Zverovich400812a2014-04-30 12:38:17 -07001237#endif
Victor Zverovichf7939862014-04-30 10:18:11 -07001238
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001239void fmt::print(std::FILE *f, StringRef format_str, const ArgList &args) {
Victor Zverovich2e039632014-06-28 19:44:39 -07001240 Writer w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001241 w.write(format_str, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001242 std::fwrite(w.data(), 1, w.size(), f);
1243}
1244
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001245void fmt::print(std::ostream &os, StringRef format_str, const ArgList &args) {
Victor Zveroviche3a44c12014-07-09 06:56:36 -07001246 Writer w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001247 w.write(format_str, args);
Victor Zveroviche3a44c12014-07-09 06:56:36 -07001248 os.write(w.data(), w.size());
1249}
1250
Victor Zverovich2dc108b2014-07-01 09:10:43 -07001251void fmt::print_colored(Color c, StringRef format, const ArgList &args) {
1252 char escape[] = "\x1b[30m";
1253 escape[3] = '0' + static_cast<char>(c);
1254 std::fputs(escape, stdout);
1255 print(format, args);
1256 std::fputs(RESET_COLOR, stdout);
1257}
1258
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001259int fmt::fprintf(std::FILE *f, StringRef format, const ArgList &args) {
Victor Zverovichd5b81962014-06-28 21:56:40 -07001260 Writer w;
Victor Zverovich21111cc2014-06-29 19:52:26 -07001261 printf(w, format, args);
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001262 return std::fwrite(w.data(), 1, w.size(), f);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001263}
1264
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001265// Explicit instantiations for char.
1266
Victor Zverovich93e41252013-09-08 13:07:04 -07001267template fmt::BasicWriter<char>::CharPtr
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001268 fmt::BasicWriter<char>::fill_padding(CharPtr buffer,
Victor Zverovich93e41252013-09-08 13:07:04 -07001269 unsigned total_size, std::size_t content_size, wchar_t fill);
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001270
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001271template void fmt::BasicFormatter<char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001272 BasicStringRef<char> format, const ArgList &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001273
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001274template void fmt::internal::PrintfFormatter<char>::format(
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001275 BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001276
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001277// Explicit instantiations for wchar_t.
1278
Victor Zverovich7cae7632013-09-06 20:23:42 -07001279template fmt::BasicWriter<wchar_t>::CharPtr
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001280 fmt::BasicWriter<wchar_t>::fill_padding(CharPtr buffer,
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001281 unsigned total_size, std::size_t content_size, wchar_t fill);
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001282
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001283template void fmt::BasicFormatter<wchar_t>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001284 BasicStringRef<wchar_t> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001285
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001286template void fmt::internal::PrintfFormatter<wchar_t>::format(
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001287 BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001288 const ArgList &args);
jdale88a9862fd2014-03-11 18:56:24 +00001289
1290#if _MSC_VER
1291# pragma warning(pop)
1292#endif