blob: 38f899c85e13aaf135c00b4b97bd4850384135bc [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
Victor Zverovich22f75d82014-09-03 08:03:05 -0700139typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
140
141// TODO: test
142void format_error_code(fmt::Writer &out, int error_code,
143 fmt::StringRef message) FMT_NOEXCEPT(true) {
144 // Report error code making sure that the output fits into
145 // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
146 // bad_alloc.
147 out.clear();
148 static const char SEP[] = ": ";
149 static const char ERROR[] = "error ";
150 // SEP and ERROR add two terminating null characters, so subtract 1 as
151 // we need only one.
152 fmt::internal::IntTraits<int>::MainType ec_value = error_code;
153 std::size_t error_code_size =
154 sizeof(SEP) + sizeof(ERROR) + fmt::internal::count_digits(ec_value) - 1;
155 if (message.size() < fmt::internal::INLINE_BUFFER_SIZE - error_code_size)
156 out << message << SEP;
157 out << ERROR << error_code;
158 assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE);
159}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700160
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700161void report_error(FormatFunc func,
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700162 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
163 try {
164 fmt::Writer full_message;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700165 func(full_message, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700166 std::fwrite(full_message.c_str(), full_message.size(), 1, stderr);
167 std::fputc('\n', stderr);
168 } catch (...) {}
Victor Zverovichb605b392013-09-09 22:21:40 -0700169}
Victor Zverovichd29e5052014-06-30 07:12:09 -0700170
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700171// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
172class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> {
173 public:
174 template <typename T>
175 bool visit_any_int(T value) { return value == 0; }
176};
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700177
178// Parses an unsigned integer advancing s to the end of the parsed input.
179// This function assumes that the first character of s is a digit.
180template <typename Char>
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700181int parse_nonnegative_int(const Char *&s) {
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700182 assert('0' <= *s && *s <= '9');
183 unsigned value = 0;
184 do {
185 unsigned new_value = value * 10 + (*s++ - '0');
186 // Check if value wrapped around.
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700187 if (new_value < value) {
188 value = UINT_MAX;
189 break;
190 }
191 value = new_value;
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700192 } while ('0' <= *s && *s <= '9');
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700193 if (value > INT_MAX)
Victor Zverovich279c7a62014-08-28 06:50:52 -0700194 throw fmt::FormatError("number is too big");
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700195 return value;
196}
Victor Zveroviche8251562014-07-08 16:20:33 -0700197
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700198inline void require_numeric_argument(const Arg &arg, char spec) {
199 if (arg.type > Arg::LAST_NUMERIC_TYPE) {
200 throw fmt::FormatError(
201 fmt::format("format specifier '{}' requires numeric argument", spec));
202 }
203}
204
Victor Zveroviche8251562014-07-08 16:20:33 -0700205template <typename Char>
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700206void check_sign(const Char *&s, const Arg &arg) {
207 char sign = static_cast<char>(*s);
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700208 require_numeric_argument(arg, sign);
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700209 if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
210 throw fmt::FormatError(fmt::format(
211 "format specifier '{}' requires signed argument", sign));
212 }
213 ++s;
214}
215
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700216// Checks if an argument is a valid printf width specifier and sets
217// left alignment if it is negative.
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700218class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700219 private:
220 fmt::FormatSpec &spec_;
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700221
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700222 public:
223 explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700224
Victor Zverovich9d74f952014-07-16 07:27:54 -0700225 unsigned visit_unhandled_arg() {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700226 throw fmt::FormatError("width is not integer");
227 }
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700228
Victor Zverovich9d74f952014-07-16 07:27:54 -0700229 template <typename T>
230 unsigned visit_any_int(T value) {
231 typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType;
232 UnsignedType width = value;
233 if (fmt::internal::is_negative(value)) {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700234 spec_.align_ = fmt::ALIGN_LEFT;
235 width = 0 - width;
236 }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700237 if (width > INT_MAX)
Victor Zverovich279c7a62014-08-28 06:50:52 -0700238 throw fmt::FormatError("number is too big");
Victor Zverovich9d74f952014-07-16 07:27:54 -0700239 return static_cast<unsigned>(width);
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700240 }
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700241};
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700242
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700243class PrecisionHandler :
244 public fmt::internal::ArgVisitor<PrecisionHandler, int> {
245 public:
246 unsigned visit_unhandled_arg() {
247 throw fmt::FormatError("precision is not integer");
248 }
249
250 template <typename T>
251 int visit_any_int(T value) {
Victor Zverovichadce0242014-08-17 07:53:55 -0700252 if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
Victor Zverovich279c7a62014-08-28 06:50:52 -0700253 throw fmt::FormatError("number is too big");
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700254 return static_cast<int>(value);
255 }
256};
257
Victor Zverovich32344d92014-08-28 08:11:21 -0700258// Converts an integer argument to an integral type T for printf.
Victor Zverovicheeca2232014-07-30 07:37:16 -0700259template <typename T>
260class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
261 private:
262 fmt::internal::Arg &arg_;
Victor Zveroviche22d6572014-08-08 06:51:09 -0700263 wchar_t type_;
Victor Zverovicheeca2232014-07-30 07:37:16 -0700264
265 public:
Victor Zveroviche22d6572014-08-08 06:51:09 -0700266 ArgConverter(fmt::internal::Arg &arg, wchar_t type)
267 : arg_(arg), type_(type) {}
Victor Zverovicheeca2232014-07-30 07:37:16 -0700268
269 template <typename U>
270 void visit_any_int(U value) {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700271 bool is_signed = type_ == 'd' || type_ == 'i';
272 using fmt::internal::Arg;
273 if (sizeof(T) <= sizeof(int)) {
Victor Zverovich32344d92014-08-28 08:11:21 -0700274 // Extra casts are used to silence warnings.
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700275 if (is_signed) {
276 arg_.type = Arg::INT;
Victor Zverovichbb016332014-08-15 09:03:59 -0700277 arg_.int_value = static_cast<int>(static_cast<T>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700278 } else {
279 arg_.type = Arg::UINT;
Victor Zverovich186734c2014-08-18 07:03:12 -0700280 arg_.uint_value = static_cast<unsigned>(
281 static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700282 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700283 } else {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700284 if (is_signed) {
285 arg_.type = Arg::LONG_LONG;
Victor Zverovicha259c942014-08-01 07:15:27 -0700286 arg_.long_long_value =
287 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700288 } else {
289 arg_.type = Arg::ULONG_LONG;
290 arg_.ulong_long_value =
Victor Zverovicha259c942014-08-01 07:15:27 -0700291 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700292 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700293 }
294 }
295};
296
Victor Zverovich32344d92014-08-28 08:11:21 -0700297// Converts an integer argument to char for printf.
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700298class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
299 private:
300 fmt::internal::Arg &arg_;
301
302 public:
303 explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
304
305 template <typename T>
306 void visit_any_int(T value) {
307 arg_.type = Arg::CHAR;
308 arg_.int_value = static_cast<char>(value);
309 }
310};
311
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700312// This function template is used to prevent compile errors when handling
313// incompatible string arguments, e.g. handling a wide string in a narrow
314// string formatter.
315template <typename Char>
316Arg::StringValue<Char> ignore_incompatible_str(Arg::StringValue<wchar_t>);
317
318template <>
319inline Arg::StringValue<char> ignore_incompatible_str(
320 Arg::StringValue<wchar_t>) { return Arg::StringValue<char>(); }
321
322template <>
323inline Arg::StringValue<wchar_t> ignore_incompatible_str(
324 Arg::StringValue<wchar_t> s) { return s; }
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700325} // namespace
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700326
Victor Zverovich53201032014-06-30 14:26:29 -0700327void fmt::SystemError::init(
328 int error_code, StringRef format_str, const ArgList &args) {
329 error_code_ = error_code;
330 Writer w;
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700331 internal::format_system_error(w, error_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700332 std::runtime_error &base = *this;
333 base = std::runtime_error(w.str());
334}
335
Victor Zverovichb605b392013-09-09 22:21:40 -0700336template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700337int fmt::internal::CharTraits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700338 char *buffer, std::size_t size, const char *format,
339 unsigned width, int precision, T value) {
340 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700341 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700342 FMT_SNPRINTF(buffer, size, format, value) :
343 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700344 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700345 return precision < 0 ?
346 FMT_SNPRINTF(buffer, size, format, width, value) :
347 FMT_SNPRINTF(buffer, size, format, width, precision, value);
348}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700349
Victor Zverovichb605b392013-09-09 22:21:40 -0700350template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700351int fmt::internal::CharTraits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700352 wchar_t *buffer, std::size_t size, const wchar_t *format,
353 unsigned width, int precision, T value) {
354 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700355 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700356 swprintf(buffer, size, format, value) :
357 swprintf(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700358 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700359 return precision < 0 ?
360 swprintf(buffer, size, format, width, value) :
361 swprintf(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700362}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800363
Victor Zverovich65d47e52013-09-09 06:51:03 -0700364const char fmt::internal::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800365 "0001020304050607080910111213141516171819"
366 "2021222324252627282930313233343536373839"
367 "4041424344454647484950515253545556575859"
368 "6061626364656667686970717273747576777879"
369 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800370
Victor Zverovichf1d85162014-02-19 13:02:22 -0800371#define FMT_POWERS_OF_10(factor) \
372 factor * 10, \
373 factor * 100, \
374 factor * 1000, \
375 factor * 10000, \
376 factor * 100000, \
377 factor * 1000000, \
378 factor * 10000000, \
379 factor * 100000000, \
380 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800381
Victor Zverovichf1d85162014-02-19 13:02:22 -0800382const uint32_t fmt::internal::POWERS_OF_10_32[] = {0, FMT_POWERS_OF_10(1)};
Victor Zveroviche9b21912014-02-19 12:43:55 -0800383const uint64_t fmt::internal::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800384 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800385 FMT_POWERS_OF_10(1),
386 FMT_POWERS_OF_10(ULongLong(1000000000)),
Victor Zverovich406c6122014-08-19 08:47:38 -0700387 // Multiply several constants instead of using a single long long constant
Victor Zverovichf1d85162014-02-19 13:02:22 -0800388 // to avoid warnings about C++98 not supporting long long.
Victor Zverovich6f6fe512014-02-15 11:16:44 -0800389 ULongLong(1000000000) * ULongLong(1000000000) * 10
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800390};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800391
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700392void fmt::internal::report_unknown_type(char code, const char *type) {
Victor Zverovich877abaf2013-01-08 09:56:05 -0800393 if (std::isprint(static_cast<unsigned char>(code))) {
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700394 throw fmt::FormatError(
395 fmt::format("unknown format code '{}' for {}", code, type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800396 }
397 throw fmt::FormatError(
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700398 fmt::format("unknown format code '\\x{:02x}' for {}",
399 static_cast<unsigned>(code), type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800400}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700401
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700402#ifdef _WIN32
403
404fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
405 int length = MultiByteToWideChar(
406 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, 0, 0);
407 static const char ERROR[] = "cannot convert string from UTF-8 to UTF-16";
408 if (length == 0)
Victor Zverovichf4208772014-06-30 17:32:08 -0700409 throw WindowsError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700410 buffer_.resize(length);
411 length = MultiByteToWideChar(
412 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, &buffer_[0], length);
413 if (length == 0)
Victor Zverovichf4208772014-06-30 17:32:08 -0700414 throw WindowsError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700415}
416
417fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700418 if (int error_code = convert(s)) {
Victor Zverovich8321d0e2014-07-09 08:39:01 -0700419 throw WindowsError(error_code,
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700420 "cannot convert string from UTF-16 to UTF-8");
421 }
422}
423
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700424int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700425 int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, 0, 0, 0, 0);
426 if (length == 0)
427 return GetLastError();
428 buffer_.resize(length);
429 length = WideCharToMultiByte(
430 CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, 0, 0);
431 if (length == 0)
432 return GetLastError();
433 return 0;
434}
435
Victor Zverovich53201032014-06-30 14:26:29 -0700436void fmt::WindowsError::init(
437 int error_code, StringRef format_str, const ArgList &args) {
438 error_code_ = error_code;
439 Writer w;
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700440 internal::format_windows_error(w, error_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700441 std::runtime_error &base = *this;
442 base = std::runtime_error(w.str());
443}
444
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700445#endif
446
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700447int fmt::internal::safe_strerror(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700448 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT(true) {
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700449 assert(buffer != 0 && buffer_size != 0);
Victor Zverovich99e61122014-04-30 11:20:41 -0700450 int result = 0;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700451#ifdef _GNU_SOURCE
452 char *message = strerror_r(error_code, buffer, buffer_size);
Victor Zverovich99e61122014-04-30 11:20:41 -0700453 // If the buffer is full then the message is probably truncated.
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700454 if (message == buffer && strlen(buffer) == buffer_size - 1)
Victor Zverovich99e61122014-04-30 11:20:41 -0700455 result = ERANGE;
456 buffer = message;
Victor Zverovich9c47f3e2014-07-09 09:45:18 -0700457#elif __MINGW32__
458 errno = 0;
459 (void)buffer_size;
460 buffer = strerror(error_code);
461 result = errno;
462#elif _WIN32
Victor Zverovich99e61122014-04-30 11:20:41 -0700463 result = strerror_s(buffer, buffer_size, error_code);
464 // If the buffer is full then the message is probably truncated.
465 if (result == 0 && std::strlen(buffer) == buffer_size - 1)
466 result = ERANGE;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700467#else
Victor Zverovich99e61122014-04-30 11:20:41 -0700468 result = strerror_r(error_code, buffer, buffer_size);
469 if (result == -1)
470 result = errno; // glibc versions before 2.13 return result in errno.
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700471#endif
Victor Zverovich99e61122014-04-30 11:20:41 -0700472 return result;
Victor Zverovich859a4972014-04-30 06:55:21 -0700473}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700474
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700475void fmt::internal::format_system_error(
Victor Zverovich22f75d82014-09-03 08:03:05 -0700476 fmt::Writer &out, int error_code,
477 fmt::StringRef message) FMT_NOEXCEPT(true) {
478 try {
479 Array<char, INLINE_BUFFER_SIZE> buffer;
480 buffer.resize(INLINE_BUFFER_SIZE);
481 char *system_message = 0;
482 for (;;) {
483 system_message = &buffer[0];
484 int result = safe_strerror(error_code, system_message, buffer.size());
485 if (result == 0) {
486 out << message << ": " << system_message;
487 return;
488 }
489 if (result != ERANGE)
490 break; // Can't get error message, report error code instead.
491 buffer.resize(buffer.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700492 }
Victor Zverovich22f75d82014-09-03 08:03:05 -0700493 } catch (...) {}
494 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700495}
496
497#ifdef _WIN32
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700498void fmt::internal::format_windows_error(
Victor Zverovich22f75d82014-09-03 08:03:05 -0700499 fmt::Writer &out, int error_code,
500 fmt::StringRef message) FMT_NOEXCEPT(true) {
Victor Zverovich53b4c312014-04-30 15:00:41 -0700501 class String {
502 private:
503 LPWSTR str_;
504
505 public:
506 String() : str_() {}
507 ~String() { LocalFree(str_); }
508 LPWSTR *ptr() { return &str_; }
509 LPCWSTR c_str() const { return str_; }
510 };
Victor Zverovich22f75d82014-09-03 08:03:05 -0700511 try {
512 String system_message;
513 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
514 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
515 error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
516 reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
517 UTF16ToUTF8 utf8_message;
518 if (utf8_message.convert(system_message.c_str()) == ERROR_SUCCESS) {
519 out << message << ": " << utf8_message;
520 return;
521 }
Victor Zverovich53b4c312014-04-30 15:00:41 -0700522 }
Victor Zverovich22f75d82014-09-03 08:03:05 -0700523 } catch (...) {}
524 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700525}
526#endif
527
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700528// An argument formatter.
529template <typename Char>
530class fmt::internal::ArgFormatter :
531 public fmt::internal::ArgVisitor<fmt::internal::ArgFormatter<Char>, void> {
532 private:
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700533 fmt::BasicFormatter<Char> &formatter_;
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700534 fmt::BasicWriter<Char> &writer_;
535 fmt::FormatSpec &spec_;
536 const Char *format_;
537
538 public:
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700539 ArgFormatter(
540 fmt::BasicFormatter<Char> &f,fmt::FormatSpec &s, const Char *fmt)
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700541 : formatter_(f), writer_(f.writer()), spec_(s), format_(fmt) {}
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700542
Victor Zverovich9d74f952014-07-16 07:27:54 -0700543 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700544 void visit_any_int(T value) { writer_.write_int(value, spec_); }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700545
546 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700547 void visit_any_double(T value) { writer_.write_double(value, spec_); }
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700548
549 void visit_char(int value) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700550 if (spec_.type_ && spec_.type_ != 'c') {
Victor Zverovichd699c2a2014-07-25 08:24:27 -0700551 spec_.flags_ |= CHAR_FLAG;
552 writer_.write_int(value, spec_);
553 return;
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700554 }
555 if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
556 throw FormatError("invalid format specifier for char");
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700557 typedef typename fmt::BasicWriter<Char>::CharPtr CharPtr;
558 CharPtr out = CharPtr();
559 if (spec_.width_ > 1) {
560 Char fill = static_cast<Char>(spec_.fill());
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700561 out = writer_.grow_buffer(spec_.width_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700562 if (spec_.align_ == fmt::ALIGN_RIGHT) {
563 std::fill_n(out, spec_.width_ - 1, fill);
564 out += spec_.width_ - 1;
565 } else if (spec_.align_ == fmt::ALIGN_CENTER) {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700566 out = writer_.fill_padding(out, spec_.width_, 1, fill);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700567 } else {
568 std::fill_n(out + 1, spec_.width_ - 1, fill);
569 }
570 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700571 out = writer_.grow_buffer(1);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700572 }
573 *out = static_cast<Char>(value);
574 }
575
576 void visit_string(Arg::StringValue<char> value) {
577 writer_.write_str(value, spec_);
578 }
579 void visit_wstring(Arg::StringValue<wchar_t> value) {
580 writer_.write_str(ignore_incompatible_str<Char>(value), spec_);
581 }
582
583 void visit_pointer(const void *value) {
584 if (spec_.type_ && spec_.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700585 fmt::internal::report_unknown_type(spec_.type_, "pointer");
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700586 spec_.flags_ = fmt::HASH_FLAG;
587 spec_.type_ = 'x';
Victor Zverovichc1db2932014-07-24 08:53:27 -0700588 writer_.write_int(reinterpret_cast<uintptr_t>(value), spec_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700589 }
590
591 void visit_custom(Arg::CustomValue c) {
Victor Zverovich271fa8c2014-08-29 07:23:54 -0700592 c.format(&formatter_, c.value, &format_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700593 }
594};
595
Victor Zverovich7cae7632013-09-06 20:23:42 -0700596// Fills the padding around the content and returns the pointer to the
597// content area.
598template <typename Char>
Victor Zverovich93e41252013-09-08 13:07:04 -0700599typename fmt::BasicWriter<Char>::CharPtr
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700600 fmt::BasicWriter<Char>::fill_padding(CharPtr buffer,
Victor Zverovich93e41252013-09-08 13:07:04 -0700601 unsigned total_size, std::size_t content_size, wchar_t fill) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700602 std::size_t padding = total_size - content_size;
603 std::size_t left_padding = padding / 2;
Victor Zverovich563a5752013-09-08 13:47:06 -0700604 Char fill_char = static_cast<Char>(fill);
605 std::fill_n(buffer, left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700606 buffer += left_padding;
607 CharPtr content = buffer;
Victor Zverovich563a5752013-09-08 13:47:06 -0700608 std::fill_n(buffer + content_size, padding - left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700609 return content;
610}
611
612template <typename Char>
Victor Zverovich7cae7632013-09-06 20:23:42 -0700613template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700614void fmt::BasicWriter<Char>::write_double(T value, const FormatSpec &spec) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700615 // Check type.
616 char type = spec.type();
617 bool upper = false;
618 switch (type) {
619 case 0:
620 type = 'g';
621 break;
Victor Zverovich03776dd2014-06-10 07:03:49 -0700622 case 'e': case 'f': case 'g': case 'a':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700623 break;
624 case 'F':
625#ifdef _MSC_VER
626 // MSVC's printf doesn't support 'F'.
627 type = 'f';
628#endif
629 // Fall through.
Victor Zverovich03776dd2014-06-10 07:03:49 -0700630 case 'E': case 'G': case 'A':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700631 upper = true;
632 break;
633 default:
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700634 internal::report_unknown_type(type, "double");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700635 break;
636 }
637
638 char sign = 0;
Victor Zverovichbe785a82014-07-29 09:14:07 -0700639 // Use getsign instead of value < 0 because the latter is always
Victor Zverovich7cae7632013-09-06 20:23:42 -0700640 // false for NaN.
Victor Zverovichbe785a82014-07-29 09:14:07 -0700641 if (getsign(static_cast<double>(value))) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700642 sign = '-';
643 value = -value;
Victor Zverovichd142e3b2014-07-25 08:29:06 -0700644 } else if (spec.flag(SIGN_FLAG)) {
645 sign = spec.flag(PLUS_FLAG) ? '+' : ' ';
Victor Zverovich7cae7632013-09-06 20:23:42 -0700646 }
647
648 if (value != value) {
649 // Format NaN ourselves because sprintf's output is not consistent
650 // across platforms.
651 std::size_t size = 4;
652 const char *nan = upper ? " NAN" : " nan";
653 if (!sign) {
654 --size;
655 ++nan;
656 }
Victor Zverovich53201032014-06-30 14:26:29 -0700657 CharPtr out = write_str(nan, size, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700658 if (sign)
659 *out = sign;
660 return;
661 }
662
Victor Zverovich1a0c76a2014-08-13 07:51:02 -0700663 if (isinfinity(value)) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700664 // Format infinity ourselves because sprintf's output is not consistent
665 // across platforms.
666 std::size_t size = 4;
667 const char *inf = upper ? " INF" : " inf";
668 if (!sign) {
669 --size;
670 ++inf;
671 }
Victor Zverovich53201032014-06-30 14:26:29 -0700672 CharPtr out = write_str(inf, size, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700673 if (sign)
674 *out = sign;
675 return;
676 }
677
678 std::size_t offset = buffer_.size();
679 unsigned width = spec.width();
680 if (sign) {
681 buffer_.reserve(buffer_.size() + (std::max)(width, 1u));
682 if (width > 0)
683 --width;
684 ++offset;
685 }
686
687 // Build format string.
688 enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg
689 Char format[MAX_FORMAT_SIZE];
690 Char *format_ptr = format;
691 *format_ptr++ = '%';
692 unsigned width_for_sprintf = width;
Victor Zverovichd142e3b2014-07-25 08:29:06 -0700693 if (spec.flag(HASH_FLAG))
Victor Zverovich7cae7632013-09-06 20:23:42 -0700694 *format_ptr++ = '#';
695 if (spec.align() == ALIGN_CENTER) {
696 width_for_sprintf = 0;
697 } else {
698 if (spec.align() == ALIGN_LEFT)
699 *format_ptr++ = '-';
700 if (width != 0)
701 *format_ptr++ = '*';
702 }
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700703 if (spec.precision() >= 0) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700704 *format_ptr++ = '.';
705 *format_ptr++ = '*';
706 }
Victor Zverovichfb321612014-08-15 08:40:03 -0700707 if (IsLongDouble<T>::VALUE)
Victor Zverovich7cae7632013-09-06 20:23:42 -0700708 *format_ptr++ = 'L';
709 *format_ptr++ = type;
710 *format_ptr = '\0';
711
712 // Format using snprintf.
Victor Zverovich88972f42013-09-08 13:30:14 -0700713 Char fill = static_cast<Char>(spec.fill());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700714 for (;;) {
715 std::size_t size = buffer_.capacity() - offset;
Victor Zverovich33baa8f2014-04-23 18:37:08 -0700716#if _MSC_VER
717 // MSVC's vsnprintf_s doesn't work with zero size, so reserve
718 // space for at least one extra character to make the size non-zero.
719 // Note that the buffer's capacity will increase by more than 1.
720 if (size == 0) {
721 buffer_.reserve(offset + 1);
722 size = buffer_.capacity() - offset;
723 }
724#endif
Victor Zverovich7cae7632013-09-06 20:23:42 -0700725 Char *start = &buffer_[offset];
Victor Zverovichb498ba02014-07-26 08:03:03 -0700726 int n = internal::CharTraits<Char>::format_float(
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700727 start, size, format, width_for_sprintf, spec.precision(), value);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700728 if (n >= 0 && offset + n < buffer_.capacity()) {
729 if (sign) {
730 if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) ||
731 *start != ' ') {
732 *(start - 1) = sign;
733 sign = 0;
734 } else {
Victor Zverovich88972f42013-09-08 13:30:14 -0700735 *(start - 1) = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700736 }
737 ++n;
738 }
739 if (spec.align() == ALIGN_CENTER &&
740 spec.width() > static_cast<unsigned>(n)) {
741 unsigned width = spec.width();
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700742 CharPtr p = grow_buffer(width);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700743 std::copy(p, p + n, p + (width - n) / 2);
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700744 fill_padding(p, spec.width(), n, fill);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700745 return;
746 }
747 if (spec.fill() != ' ' || sign) {
748 while (*start == ' ')
Victor Zverovich88972f42013-09-08 13:30:14 -0700749 *start++ = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700750 if (sign)
751 *(start - 1) = sign;
752 }
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700753 grow_buffer(n);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700754 return;
755 }
Victor Zverovichcfeba452014-04-23 18:37:49 -0700756 // If n is negative we ask to increase the capacity by at least 1,
757 // but as std::vector, the buffer grows exponentially.
758 buffer_.reserve(n >= 0 ? offset + n + 1 : buffer_.capacity() + 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700759 }
760}
761
Victor Zverovich7cae7632013-09-06 20:23:42 -0700762template <typename Char>
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700763template <typename StrChar>
Victor Zverovich53201032014-06-30 14:26:29 -0700764void fmt::BasicWriter<Char>::write_str(
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700765 const Arg::StringValue<StrChar> &str, const FormatSpec &spec) {
766 // Check if StrChar is convertible to Char.
767 internal::CharTraits<Char>::convert(StrChar());
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700768 if (spec.type_ && spec.type_ != 's')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700769 internal::report_unknown_type(spec.type_, "string");
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700770 const StrChar *s = str.value;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700771 std::size_t size = str.size;
772 if (size == 0) {
773 if (!s)
774 throw FormatError("string pointer is null");
775 if (*s)
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700776 size = std::char_traits<StrChar>::length(s);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700777 }
Victor Zverovich53201032014-06-30 14:26:29 -0700778 write_str(s, size, spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700779}
780
781template <typename Char>
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700782inline const Arg &fmt::BasicFormatter<Char>::parse_arg_index(const Char *&s) {
Victor Zverovich9646e382014-08-27 09:13:42 -0700783 const char *error = 0;
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700784 const Arg *arg = *s < '0' || *s > '9' ?
785 next_arg(error) : get_arg(parse_nonnegative_int(s), error);
Victor Zverovich9646e382014-08-27 09:13:42 -0700786 if (error)
787 throw FormatError(*s != '}' && *s != ':' ? "invalid format string" : error);
Victor Zverovichda0f7c02014-08-27 09:04:51 -0700788 return *arg;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700789}
790
Victor Zverovich605d2602014-08-29 07:45:55 -0700791const Arg *fmt::internal::FormatterBase::do_get_arg(
792 unsigned arg_index, const char *&error) {
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700793 if (arg_index < args_.size())
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700794 return &args_[arg_index];
Victor Zverovich605d2602014-08-29 07:45:55 -0700795 error = "argument index out of range";
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700796 return 0;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700797}
798
Victor Zverovich605d2602014-08-29 07:45:55 -0700799inline const Arg *fmt::internal::FormatterBase::next_arg(const char *&error) {
800 if (next_arg_index_ >= 0)
801 return do_get_arg(next_arg_index_++, error);
802 error = "cannot switch from manual to automatic argument indexing";
803 return 0;
804}
805
806inline const Arg *fmt::internal::FormatterBase::get_arg(
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700807 unsigned arg_index, const char *&error) {
Victor Zverovich605d2602014-08-29 07:45:55 -0700808 if (next_arg_index_ <= 0) {
809 next_arg_index_ = -1;
810 return do_get_arg(arg_index, error);
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700811 }
Victor Zverovich605d2602014-08-29 07:45:55 -0700812 error = "cannot switch from automatic to manual argument indexing";
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700813 return 0;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700814}
815
Victor Zverovich7cae7632013-09-06 20:23:42 -0700816template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700817void fmt::internal::PrintfFormatter<Char>::parse_flags(
Victor Zverovichcb743c02014-06-19 07:40:35 -0700818 FormatSpec &spec, const Char *&s) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700819 for (;;) {
Victor Zverovich1b801482014-06-07 08:57:55 -0700820 switch (*s++) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700821 case '-':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700822 spec.align_ = ALIGN_LEFT;
823 break;
824 case '+':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700825 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
826 break;
827 case '0':
828 spec.fill_ = '0';
Victor Zverovich1b801482014-06-07 08:57:55 -0700829 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700830 case ' ':
Victor Zverovich1b801482014-06-07 08:57:55 -0700831 spec.flags_ |= SIGN_FLAG;
832 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700833 case '#':
Victor Zverovichcb743c02014-06-19 07:40:35 -0700834 spec.flags_ |= HASH_FLAG;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700835 break;
836 default:
Victor Zverovich1b801482014-06-07 08:57:55 -0700837 --s;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700838 return;
839 }
840 }
841}
842
Victor Zverovichcb743c02014-06-19 07:40:35 -0700843template <typename Char>
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700844const Arg &fmt::internal::PrintfFormatter<Char>::get_arg(
845 const Char *s, unsigned arg_index) {
846 const char *error = 0;
847 const Arg *arg = arg_index == UINT_MAX ?
848 next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
849 if (error)
850 throw FormatError(!*s ? "invalid format string" : error);
851 return *arg;
852}
853
854template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700855unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700856 const Char *&s, FormatSpec &spec) {
Victor Zverovichcb743c02014-06-19 07:40:35 -0700857 unsigned arg_index = UINT_MAX;
858 Char c = *s;
859 if (c >= '0' && c <= '9') {
860 // Parse an argument index (if followed by '$') or a width possibly
Victor Zverovich879838a2014-06-20 07:34:02 -0700861 // preceded with '0' flag(s).
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700862 unsigned value = parse_nonnegative_int(s);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700863 if (*s == '$') { // value is an argument index
864 ++s;
865 arg_index = value;
866 } else {
867 if (c == '0')
868 spec.fill_ = '0';
869 if (value != 0) {
870 // Nonzero value means that we parsed width and don't need to
871 // parse it or flags again, so return now.
872 spec.width_ = value;
873 return arg_index;
874 }
875 }
876 }
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700877 parse_flags(spec, s);
Victor Zverovich4099a122014-06-23 08:10:50 -0700878 // Parse width.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700879 if (*s >= '0' && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700880 spec.width_ = parse_nonnegative_int(s);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700881 } else if (*s == '*') {
882 ++s;
Victor Zverovich56fc5252014-08-28 07:48:55 -0700883 spec.width_ = WidthHandler(spec).visit(get_arg(s));
Victor Zverovichcb743c02014-06-19 07:40:35 -0700884 }
885 return arg_index;
886}
887
Victor Zverovich1f19b982014-06-16 07:49:30 -0700888template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700889void fmt::internal::PrintfFormatter<Char>::format(
Victor Zveroviche78904b2014-04-23 08:27:50 -0700890 BasicWriter<Char> &writer, BasicStringRef<Char> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700891 const ArgList &args) {
Victor Zveroviche78904b2014-04-23 08:27:50 -0700892 const Char *start = format.c_str();
Victor Zverovich605d2602014-08-29 07:45:55 -0700893 set_args(args);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700894 const Char *s = start;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700895 while (*s) {
Victor Zverovich0fc73162013-09-07 12:52:52 -0700896 Char c = *s++;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700897 if (c != '%') continue;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700898 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -0700899 write(writer, start, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700900 start = ++s;
901 continue;
902 }
Victor Zverovichc1db2932014-07-24 08:53:27 -0700903 write(writer, start, s - 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700904
Victor Zverovichcb743c02014-06-19 07:40:35 -0700905 FormatSpec spec;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700906 spec.align_ = ALIGN_RIGHT;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700907
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700908 // Parse argument index, flags and width.
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700909 unsigned arg_index = parse_header(s, spec);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700910
911 // Parse precision.
912 if (*s == '.') {
913 ++s;
914 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700915 spec.precision_ = parse_nonnegative_int(s);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700916 } else if (*s == '*') {
917 ++s;
Victor Zverovich56fc5252014-08-28 07:48:55 -0700918 spec.precision_ = PrecisionHandler().visit(get_arg(s));
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700919 }
920 }
921
Victor Zverovich56fc5252014-08-28 07:48:55 -0700922 Arg arg = get_arg(s, arg_index);
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700923 if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
Victor Zverovichcb743c02014-06-19 07:40:35 -0700924 spec.flags_ &= ~HASH_FLAG;
925 if (spec.fill_ == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700926 if (arg.type <= Arg::LAST_NUMERIC_TYPE)
Victor Zverovichcb743c02014-06-19 07:40:35 -0700927 spec.align_ = ALIGN_NUMERIC;
928 else
929 spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700930 }
931
Victor Zverovichf4156b52014-07-30 08:39:07 -0700932 // Parse length and convert the argument to the required type.
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700933 switch (*s++) {
934 case 'h':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700935 if (*s == 'h')
936 ArgConverter<signed char>(arg, *++s).visit(arg);
Victor Zverovich39b09302014-07-30 08:08:08 -0700937 else
Victor Zverovichf4156b52014-07-30 08:39:07 -0700938 ArgConverter<short>(arg, *s).visit(arg);
Victor Zverovicheeca2232014-07-30 07:37:16 -0700939 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700940 case 'l':
Victor Zverovichd3a70392014-08-12 08:36:19 -0700941 if (*s == 'l')
Victor Zveroviche488a282014-08-13 06:53:43 -0700942 ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
Victor Zverovichd3a70392014-08-12 08:36:19 -0700943 else
944 ArgConverter<long>(arg, *s).visit(arg);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700945 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700946 case 'j':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700947 ArgConverter<intmax_t>(arg, *s).visit(arg);
948 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700949 case 'z':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700950 ArgConverter<size_t>(arg, *s).visit(arg);
951 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700952 case 't':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700953 ArgConverter<ptrdiff_t>(arg, *s).visit(arg);
954 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700955 case 'L':
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700956 // printf produces garbage when 'L' is omitted for long double, no
957 // need to do the same.
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700958 break;
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700959 default:
960 --s;
Victor Zverovichbe00d8b2014-08-19 08:49:10 -0700961 ArgConverter<int>(arg, *s).visit(arg);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700962 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700963
964 // Parse type.
965 if (!*s)
966 throw FormatError("invalid format string");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700967 spec.type_ = static_cast<char>(*s++);
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700968 if (arg.type <= Arg::LAST_INTEGER_TYPE) {
969 // Normalize type.
970 switch (spec.type_) {
971 case 'i': case 'u':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700972 spec.type_ = 'd';
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700973 break;
974 case 'c':
975 // TODO: handle wchar_t
976 CharConverter(arg).visit(arg);
977 break;
978 }
Victor Zverovichf4156b52014-07-30 08:39:07 -0700979 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700980
981 start = s;
982
983 // Format argument.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700984 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700985 case Arg::INT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700986 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700987 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700988 case Arg::UINT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700989 writer.write_int(arg.uint_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700990 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700991 case Arg::LONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700992 writer.write_int(arg.long_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700993 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700994 case Arg::ULONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700995 writer.write_int(arg.ulong_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700996 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700997 case Arg::CHAR: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700998 if (spec.type_ && spec.type_ != 'c')
Victor Zverovichc1db2932014-07-24 08:53:27 -0700999 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001000 typedef typename BasicWriter<Char>::CharPtr CharPtr;
1001 CharPtr out = CharPtr();
1002 if (spec.width_ > 1) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001003 Char fill = ' ';
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001004 out = writer.grow_buffer(spec.width_);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001005 if (spec.align_ != ALIGN_LEFT) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001006 std::fill_n(out, spec.width_ - 1, fill);
1007 out += spec.width_ - 1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001008 } else {
1009 std::fill_n(out + 1, spec.width_ - 1, fill);
1010 }
1011 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001012 out = writer.grow_buffer(1);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001013 }
Victor Zverovichcb743c02014-06-19 07:40:35 -07001014 *out = static_cast<Char>(arg.int_value);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001015 break;
1016 }
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001017 case Arg::DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001018 writer.write_double(arg.double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001019 break;
1020 case Arg::LONG_DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001021 writer.write_double(arg.long_double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001022 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001023 case Arg::STRING:
Victor Zverovich53201032014-06-30 14:26:29 -07001024 writer.write_str(arg.string, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001025 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001026 case Arg::WSTRING:
Victor Zverovich512e2ce2014-07-14 08:47:03 -07001027 writer.write_str(ignore_incompatible_str<Char>(arg.wstring), spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001028 break;
1029 case Arg::POINTER:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001030 if (spec.type_ && spec.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001031 internal::report_unknown_type(spec.type_, "pointer");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001032 spec.flags_= HASH_FLAG;
1033 spec.type_ = 'x';
Victor Zverovichc1db2932014-07-24 08:53:27 -07001034 writer.write_int(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001035 break;
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001036 case Arg::CUSTOM: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001037 if (spec.type_)
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001038 internal::report_unknown_type(spec.type_, "object");
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001039 const void *s = "s";
1040 arg.custom.format(&writer, arg.custom.value, &s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001041 break;
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001042 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001043 default:
1044 assert(false);
1045 break;
1046 }
1047 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001048 write(writer, start, s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001049}
1050
1051template <typename Char>
Victor Zverovichb9a06ba2014-07-08 16:38:50 -07001052const Char *fmt::BasicFormatter<Char>::format(
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001053 const Char *&format_str, const Arg &arg) {
Victor Zveroviche8251562014-07-08 16:20:33 -07001054 const Char *s = format_str;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001055 const char *error = 0;
Victor Zveroviche8251562014-07-08 16:20:33 -07001056 FormatSpec spec;
1057 if (*s == ':') {
1058 if (arg.type == Arg::CUSTOM) {
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001059 arg.custom.format(this, arg.custom.value, &s);
1060 return s;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001061 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001062 ++s;
1063 // Parse fill and alignment.
1064 if (Char c = *s) {
1065 const Char *p = s + 1;
1066 spec.align_ = ALIGN_DEFAULT;
1067 do {
1068 switch (*p) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001069 case '<':
1070 spec.align_ = ALIGN_LEFT;
1071 break;
1072 case '>':
1073 spec.align_ = ALIGN_RIGHT;
1074 break;
1075 case '=':
1076 spec.align_ = ALIGN_NUMERIC;
1077 break;
1078 case '^':
1079 spec.align_ = ALIGN_CENTER;
1080 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001081 }
1082 if (spec.align_ != ALIGN_DEFAULT) {
1083 if (p != s) {
1084 if (c == '}') break;
1085 if (c == '{')
Victor Zverovich42de4f12014-08-27 08:24:31 -07001086 throw FormatError("invalid fill character '{'");
Victor Zveroviche8251562014-07-08 16:20:33 -07001087 s += 2;
1088 spec.fill_ = c;
1089 } else ++s;
Victor Zverovich5debb2a2014-08-29 08:16:10 -07001090 if (spec.align_ == ALIGN_NUMERIC)
1091 require_numeric_argument(arg, '=');
Victor Zveroviche8251562014-07-08 16:20:33 -07001092 break;
1093 }
1094 } while (--p >= s);
1095 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001096
Victor Zveroviche8251562014-07-08 16:20:33 -07001097 // Parse sign.
1098 switch (*s) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001099 case '+':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001100 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001101 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
1102 break;
1103 case '-':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001104 check_sign(s, arg);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001105 spec.flags_ |= MINUS_FLAG;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001106 break;
1107 case ' ':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001108 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001109 spec.flags_ |= SIGN_FLAG;
1110 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001111 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001112
Victor Zveroviche8251562014-07-08 16:20:33 -07001113 if (*s == '#') {
Victor Zverovich5debb2a2014-08-29 08:16:10 -07001114 require_numeric_argument(arg, '#');
Victor Zveroviche8251562014-07-08 16:20:33 -07001115 spec.flags_ |= HASH_FLAG;
1116 ++s;
1117 }
1118
1119 // Parse width and zero flag.
1120 if ('0' <= *s && *s <= '9') {
1121 if (*s == '0') {
Victor Zverovich5debb2a2014-08-29 08:16:10 -07001122 require_numeric_argument(arg, '0');
Victor Zveroviche8251562014-07-08 16:20:33 -07001123 spec.align_ = ALIGN_NUMERIC;
1124 spec.fill_ = '0';
Victor Zverovich7cae7632013-09-06 20:23:42 -07001125 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001126 // Zero may be parsed again as a part of the width, but it is simpler
1127 // and more efficient than checking if the next char is a digit.
Victor Zverovich526b7fc2014-08-28 06:42:59 -07001128 spec.width_ = parse_nonnegative_int(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001129 if (error)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001130 throw FormatError(error);
Victor Zveroviche8251562014-07-08 16:20:33 -07001131 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001132
Victor Zveroviche8251562014-07-08 16:20:33 -07001133 // Parse precision.
1134 if (*s == '.') {
1135 ++s;
1136 spec.precision_ = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001137 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -07001138 spec.precision_ = parse_nonnegative_int(s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001139 if (error)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001140 throw FormatError(error);
Victor Zveroviche8251562014-07-08 16:20:33 -07001141 } else if (*s == '{') {
Victor Zverovich7cae7632013-09-06 20:23:42 -07001142 ++s;
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001143 const Arg &precision_arg = parse_arg_index(s);
Victor Zverovich42de4f12014-08-27 08:24:31 -07001144 if (*s++ != '}')
Victor Zverovich605d2602014-08-29 07:45:55 -07001145 throw FormatError("invalid format string");
Victor Zveroviche8251562014-07-08 16:20:33 -07001146 ULongLong value = 0;
1147 switch (precision_arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001148 case Arg::INT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001149 if (precision_arg.int_value < 0)
Victor Zverovich605d2602014-08-29 07:45:55 -07001150 throw FormatError("negative precision");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001151 value = precision_arg.int_value;
1152 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001153 case Arg::UINT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001154 value = precision_arg.uint_value;
1155 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001156 case Arg::LONG_LONG:
Victor Zverovich56f12b72013-11-22 07:45:43 -08001157 if (precision_arg.long_long_value < 0)
Victor Zverovich605d2602014-08-29 07:45:55 -07001158 throw FormatError("negative precision");
Victor Zverovich56f12b72013-11-22 07:45:43 -08001159 value = precision_arg.long_long_value;
1160 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001161 case Arg::ULONG_LONG:
Gregory Czajkowskia65542b2013-11-18 22:58:39 -08001162 value = precision_arg.ulong_long_value;
Victor Zverovicha4e72b42013-11-21 09:11:58 -08001163 break;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001164 default:
Victor Zverovich42de4f12014-08-27 08:24:31 -07001165 throw FormatError("precision is not integer");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001166 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001167 if (value > INT_MAX)
Victor Zverovich279c7a62014-08-28 06:50:52 -07001168 throw FormatError("number is too big");
Victor Zveroviche8251562014-07-08 16:20:33 -07001169 spec.precision_ = static_cast<int>(value);
Victor Zveroviche8251562014-07-08 16:20:33 -07001170 } else {
Victor Zverovich605d2602014-08-29 07:45:55 -07001171 throw FormatError("missing precision specifier");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001172 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001173 if (arg.type != Arg::DOUBLE && arg.type != Arg::LONG_DOUBLE) {
Victor Zverovich42de4f12014-08-27 08:24:31 -07001174 throw FormatError(
Victor Zveroviche8251562014-07-08 16:20:33 -07001175 "precision specifier requires floating-point argument");
1176 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001177 }
1178
Victor Zveroviche8251562014-07-08 16:20:33 -07001179 // Parse type.
1180 if (*s != '}' && *s)
1181 spec.type_ = static_cast<char>(*s++);
1182 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001183
Victor Zveroviche8251562014-07-08 16:20:33 -07001184 if (*s++ != '}')
Victor Zverovich605d2602014-08-29 07:45:55 -07001185 throw FormatError("missing '}' in format string");
Victor Zveroviche8251562014-07-08 16:20:33 -07001186 start_ = s;
1187
1188 // Format argument.
Victor Zverovich4edc88f2014-07-16 08:38:15 -07001189 internal::ArgFormatter<Char>(*this, spec, s - 1).visit(arg);
Victor Zveroviche8251562014-07-08 16:20:33 -07001190 return s;
1191}
1192
1193template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001194void fmt::BasicFormatter<Char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001195 BasicStringRef<Char> format_str, const ArgList &args) {
1196 const Char *s = start_ = format_str.c_str();
Victor Zverovich605d2602014-08-29 07:45:55 -07001197 set_args(args);
Victor Zveroviche8251562014-07-08 16:20:33 -07001198 while (*s) {
1199 Char c = *s++;
1200 if (c != '{' && c != '}') continue;
1201 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -07001202 write(writer_, start_, s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001203 start_ = ++s;
1204 continue;
1205 }
1206 if (c == '}')
Victor Zverovich605d2602014-08-29 07:45:55 -07001207 throw FormatError("unmatched '}' in format string");
Victor Zverovichc1db2932014-07-24 08:53:27 -07001208 write(writer_, start_, s - 1);
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001209 Arg arg = parse_arg_index(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001210 s = format(s, arg);
1211 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001212 write(writer_, start_, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001213}
1214
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001215void fmt::report_system_error(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001216 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001217 report_error(internal::format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001218}
1219
Victor Zverovich400812a2014-04-30 12:38:17 -07001220#ifdef _WIN32
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001221void fmt::report_windows_error(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001222 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001223 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001224}
Victor Zverovich400812a2014-04-30 12:38:17 -07001225#endif
Victor Zverovichf7939862014-04-30 10:18:11 -07001226
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001227void fmt::print(std::FILE *f, StringRef format_str, const ArgList &args) {
Victor Zverovich2e039632014-06-28 19:44:39 -07001228 Writer w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001229 w.write(format_str, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001230 std::fwrite(w.data(), 1, w.size(), f);
1231}
1232
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001233void fmt::print(std::ostream &os, StringRef format_str, const ArgList &args) {
Victor Zveroviche3a44c12014-07-09 06:56:36 -07001234 Writer w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001235 w.write(format_str, args);
Victor Zveroviche3a44c12014-07-09 06:56:36 -07001236 os.write(w.data(), w.size());
1237}
1238
Victor Zverovich2dc108b2014-07-01 09:10:43 -07001239void fmt::print_colored(Color c, StringRef format, const ArgList &args) {
1240 char escape[] = "\x1b[30m";
1241 escape[3] = '0' + static_cast<char>(c);
1242 std::fputs(escape, stdout);
1243 print(format, args);
1244 std::fputs(RESET_COLOR, stdout);
1245}
1246
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001247int fmt::fprintf(std::FILE *f, StringRef format, const ArgList &args) {
Victor Zverovichd5b81962014-06-28 21:56:40 -07001248 Writer w;
Victor Zverovich21111cc2014-06-29 19:52:26 -07001249 printf(w, format, args);
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001250 return std::fwrite(w.data(), 1, w.size(), f);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001251}
1252
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001253// Explicit instantiations for char.
1254
Victor Zverovich93e41252013-09-08 13:07:04 -07001255template fmt::BasicWriter<char>::CharPtr
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001256 fmt::BasicWriter<char>::fill_padding(CharPtr buffer,
Victor Zverovich93e41252013-09-08 13:07:04 -07001257 unsigned total_size, std::size_t content_size, wchar_t fill);
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001258
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001259template void fmt::BasicFormatter<char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001260 BasicStringRef<char> format, const ArgList &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001261
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001262template void fmt::internal::PrintfFormatter<char>::format(
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001263 BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001264
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001265// Explicit instantiations for wchar_t.
1266
Victor Zverovich7cae7632013-09-06 20:23:42 -07001267template fmt::BasicWriter<wchar_t>::CharPtr
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001268 fmt::BasicWriter<wchar_t>::fill_padding(CharPtr buffer,
Victor Zverovichbf8b29f2014-06-06 06:38:37 -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<wchar_t>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001272 BasicStringRef<wchar_t> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001273
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001274template void fmt::internal::PrintfFormatter<wchar_t>::format(
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001275 BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001276 const ArgList &args);
jdale88a9862fd2014-03-11 18:56:24 +00001277
1278#if _MSC_VER
1279# pragma warning(pop)
1280#endif