blob: 8ab10960960e7e57b78685932ac32a856c1f7cc1 [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 Zverovich7c0a2332015-03-03 21:04:45 -08004 Copyright (c) 2012 - 2015, 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 Zverovichfbfedcf2013-01-14 15:16:20 -080028#include "format.h"
29
Victor Zverovich859a4972014-04-30 06:55:21 -070030#include <string.h>
31
Victor Zverovich72f896d2012-12-12 09:17:28 -080032#include <cctype>
Victor Zverovich5d15bdd2014-07-01 16:23:50 -070033#include <cerrno>
Victor Zverovichf28645f2014-04-24 12:37:06 -070034#include <climits>
Victor Zverovich9ff3b972013-09-07 10:15:08 -070035#include <cmath>
Victor Zverovicha684d0c2013-12-27 08:00:10 -080036#include <cstdarg>
Victor Zverovich9ff3b972013-09-07 10:15:08 -070037
vitaut24c309f2015-06-12 07:15:57 -070038#if defined(_WIN32) && defined(__MINGW32__)
39# include <cstring>
40#endif
41
42#if FMT_USE_WINDOWS_H
vitaut67ce3942015-04-30 07:48:36 -070043# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
44# include <windows.h>
45# else
46# define NOMINMAX
47# include <windows.h>
48# undef NOMINMAX
49# endif
Ryuuke5a9dc8f2015-02-08 16:08:29 +000050#endif
51
Victor Zverovich6e5551e2014-07-02 06:33:25 -070052using fmt::internal::Arg;
Victor Zverovich447e02c2014-02-15 10:48:34 -080053
Victor Zverovich8b76e972014-10-06 08:30:55 -070054// Check if exceptions are disabled.
55#if __GNUC__ && !__EXCEPTIONS
56# define FMT_EXCEPTIONS 0
57#endif
58#if _MSC_VER && !_HAS_EXCEPTIONS
59# define FMT_EXCEPTIONS 0
60#endif
61#ifndef FMT_EXCEPTIONS
62# define FMT_EXCEPTIONS 1
63#endif
64
65#if FMT_EXCEPTIONS
66# define FMT_TRY try
67# define FMT_CATCH(x) catch (x)
68#else
69# define FMT_TRY if (true)
70# define FMT_CATCH(x) if (false)
71#endif
72
73#ifndef FMT_THROW
74# if FMT_EXCEPTIONS
75# define FMT_THROW(x) throw x
76# else
vitaut66915782015-03-25 07:24:26 -070077# define FMT_THROW(x) assert(false)
Victor Zverovich8b76e972014-10-06 08:30:55 -070078# endif
79#endif
80
Victor Zverovichd9c605c2014-11-28 06:40:57 -080081#ifdef FMT_HEADER_ONLY
82# define FMT_FUNC inline
Victor Zverovichc2a69032014-11-28 15:30:03 -080083#else
84# define FMT_FUNC
Victor Zverovichd9c605c2014-11-28 06:40:57 -080085#endif
86
jdale88a9862fd2014-03-11 18:56:24 +000087#if _MSC_VER
88# pragma warning(push)
Victor Zverovich8b76e972014-10-06 08:30:55 -070089# pragma warning(disable: 4127) // conditional expression is constant
Daniel.Perrybd0067e2014-11-25 18:01:09 -050090# pragma warning(disable: 4702) // unreachable code
vitautdf47d812015-03-16 18:53:14 -070091// Disable deprecation warning for strerror. The latter is not called but
92// MSVC fails to detect it.
93# pragma warning(disable: 4996)
jdale88a9862fd2014-03-11 18:56:24 +000094#endif
95
vitaut341b98c2015-03-14 13:39:33 -070096// Dummy implementations of strerror_r and strerror_s called if corresponding
97// system functions are not available.
vitaut4825fb42015-03-16 08:43:33 -070098static inline fmt::internal::None<> strerror_r(int, char *, ...) {
99 return fmt::internal::None<>();
vitaut341b98c2015-03-14 13:39:33 -0700100}
vitaut4825fb42015-03-16 08:43:33 -0700101static inline fmt::internal::None<> strerror_s(char *, std::size_t, ...) {
102 return fmt::internal::None<>();
vitaut341b98c2015-03-14 13:39:33 -0700103}
104
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700105namespace {
106
107#ifndef _MSC_VER
Victor Zverovichb9a568b2014-09-19 07:51:42 -0700108# define FMT_SNPRINTF snprintf
Victor Zverovicha684d0c2013-12-27 08:00:10 -0800109#else // _MSC_VER
Victor Zverovich406c6122014-08-19 08:47:38 -0700110inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -0800111 va_list args;
112 va_start(args, format);
113 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
114 va_end(args);
115 return result;
116}
Victor Zverovichb9a568b2014-09-19 07:51:42 -0700117# define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700118#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -0800119
cstamford55836ca2015-03-10 07:04:31 +0000120#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
121# define FMT_SWPRINTF snwprintf
122#else
123# define FMT_SWPRINTF swprintf
124#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
125
Victor Zverovichadce0242014-08-17 07:53:55 -0700126// Checks if a value fits in int - used to avoid warnings about comparing
127// signed and unsigned integers.
128template <bool IsSigned>
129struct IntChecker {
130 template <typename T>
131 static bool fits_in_int(T value) {
132 unsigned max = INT_MAX;
133 return value <= max;
134 }
135};
136
137template <>
138struct IntChecker<true> {
139 template <typename T>
140 static bool fits_in_int(T value) {
141 return value >= INT_MIN && value <= INT_MAX;
142 }
143};
144
Victor Zverovich7004d1e2015-02-08 19:54:39 -0800145const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700146
Victor Zverovich22f75d82014-09-03 08:03:05 -0700147typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
148
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700149// Portable thread-safe version of strerror.
150// Sets buffer to point to a string describing the error code.
151// This can be either a pointer to a string stored in buffer,
152// or a pointer to some static immutable string.
153// Returns one of the following values:
154// 0 - success
155// ERANGE - buffer is not large enough to store the error message
156// other - failure
157// Buffer should be at least of size 1.
158int safe_strerror(
Carter Lie2583ab2015-02-14 09:58:29 +0800159 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700160 assert(buffer != 0 && buffer_size != 0);
vitaut341b98c2015-03-14 13:39:33 -0700161
vitaut341b98c2015-03-14 13:39:33 -0700162 class StrError {
163 private:
164 int error_code_;
165 char *&buffer_;
166 std::size_t buffer_size_;
167
vitautda052ae2015-03-21 07:53:39 -0700168 // A noop assignment operator to avoid bogus warnings.
169 void operator=(const StrError &) {}
170
vitaut341b98c2015-03-14 13:39:33 -0700171 // Handle the result of XSI-compliant version of strerror_r.
172 int handle(int result) {
vitaute1776ac2015-03-14 14:05:02 -0700173 // glibc versions before 2.13 return result in errno.
174 return result == -1 ? errno : result;
vitaut341b98c2015-03-14 13:39:33 -0700175 }
176
177 // Handle the result of GNU-specific version of strerror_r.
178 int handle(char *message) {
179 // If the buffer is full then the message is probably truncated.
180 if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
181 return ERANGE;
182 buffer_ = message;
183 return 0;
184 }
185
186 // Handle the case when strerror_r is not available.
vitaut4825fb42015-03-16 08:43:33 -0700187 int handle(fmt::internal::None<>) {
vitaut341b98c2015-03-14 13:39:33 -0700188 return fallback(strerror_s(buffer_, buffer_size_, error_code_));
189 }
190
191 // Fallback to strerror_s when strerror_r is not available.
192 int fallback(int result) {
193 // If the buffer is full then the message is probably truncated.
194 return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
195 ERANGE : result;
196 }
197
198 // Fallback to strerror if strerror_r and strerror_s are not available.
vitaut4825fb42015-03-16 08:43:33 -0700199 int fallback(fmt::internal::None<>) {
vitaut341b98c2015-03-14 13:39:33 -0700200 errno = 0;
201 buffer_ = strerror(error_code_);
202 return errno;
203 }
204
205 public:
206 StrError(int error_code, char *&buffer, std::size_t buffer_size)
207 : error_code_(error_code), buffer_(buffer), buffer_size_(buffer_size) {}
208
209 int run() { return handle(strerror_r(error_code_, buffer_, buffer_size_)); }
210 };
211 return StrError(error_code, buffer, buffer_size).run();
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700212}
213
Victor Zverovich22f75d82014-09-03 08:03:05 -0700214void format_error_code(fmt::Writer &out, int error_code,
Carter Lie2583ab2015-02-14 09:58:29 +0800215 fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700216 // Report error code making sure that the output fits into
217 // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
218 // bad_alloc.
219 out.clear();
220 static const char SEP[] = ": ";
vitaut1addec92015-03-21 20:16:36 -0700221 static const char ERROR_STR[] = "error ";
Victor Zverovich22f75d82014-09-03 08:03:05 -0700222 fmt::internal::IntTraits<int>::MainType ec_value = error_code;
vitaut1addec92015-03-21 20:16:36 -0700223 // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
224 std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
225 error_code_size += fmt::internal::count_digits(ec_value);
Victor Zverovich88e0db82014-09-05 08:04:26 -0700226 if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size)
Victor Zverovich22f75d82014-09-03 08:03:05 -0700227 out << message << SEP;
vitaut1addec92015-03-21 20:16:36 -0700228 out << ERROR_STR << error_code;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700229 assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE);
230}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700231
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700232void report_error(FormatFunc func,
Carter Lie2583ab2015-02-14 09:58:29 +0800233 int error_code, fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovichd1ded562014-09-29 08:48:16 -0700234 fmt::MemoryWriter full_message;
Victor Zverovich88e0db82014-09-05 08:04:26 -0700235 func(full_message, error_code, message);
236 // Use Writer::data instead of Writer::c_str to avoid potential memory
237 // allocation.
238 std::fwrite(full_message.data(), full_message.size(), 1, stderr);
239 std::fputc('\n', stderr);
Victor Zverovichb605b392013-09-09 22:21:40 -0700240}
Victor Zverovichd29e5052014-06-30 07:12:09 -0700241
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700242// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
243class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> {
244 public:
245 template <typename T>
246 bool visit_any_int(T value) { return value == 0; }
247};
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700248
249// Parses an unsigned integer advancing s to the end of the parsed input.
250// This function assumes that the first character of s is a digit.
251template <typename Char>
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700252int parse_nonnegative_int(const Char *&s) {
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700253 assert('0' <= *s && *s <= '9');
254 unsigned value = 0;
255 do {
256 unsigned new_value = value * 10 + (*s++ - '0');
257 // Check if value wrapped around.
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700258 if (new_value < value) {
259 value = UINT_MAX;
260 break;
261 }
262 value = new_value;
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700263 } while ('0' <= *s && *s <= '9');
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700264 if (value > INT_MAX)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700265 FMT_THROW(fmt::FormatError("number is too big"));
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700266 return value;
267}
Victor Zveroviche8251562014-07-08 16:20:33 -0700268
jamboree7487bde2015-06-10 09:32:59 +0800269template <typename Char>
270inline bool is_name_start(Char c) {
271 return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c;
272}
273
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700274inline void require_numeric_argument(const Arg &arg, char spec) {
275 if (arg.type > Arg::LAST_NUMERIC_TYPE) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700276 std::string message =
277 fmt::format("format specifier '{}' requires numeric argument", spec);
278 FMT_THROW(fmt::FormatError(message));
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700279 }
280}
281
Victor Zveroviche8251562014-07-08 16:20:33 -0700282template <typename Char>
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700283void check_sign(const Char *&s, const Arg &arg) {
284 char sign = static_cast<char>(*s);
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700285 require_numeric_argument(arg, sign);
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700286 if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700287 FMT_THROW(fmt::FormatError(fmt::format(
288 "format specifier '{}' requires signed argument", sign)));
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700289 }
290 ++s;
291}
292
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700293// Checks if an argument is a valid printf width specifier and sets
294// left alignment if it is negative.
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700295class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700296 private:
297 fmt::FormatSpec &spec_;
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700298
Victor Zverovich6f3c0952014-12-03 06:16:52 -0800299 FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
300
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700301 public:
302 explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700303
vitautd4ea2d72015-03-26 08:55:20 -0700304 void report_unhandled_arg() {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700305 FMT_THROW(fmt::FormatError("width is not integer"));
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700306 }
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700307
Victor Zverovich9d74f952014-07-16 07:27:54 -0700308 template <typename T>
309 unsigned visit_any_int(T value) {
310 typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType;
311 UnsignedType width = value;
312 if (fmt::internal::is_negative(value)) {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700313 spec_.align_ = fmt::ALIGN_LEFT;
314 width = 0 - width;
315 }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700316 if (width > INT_MAX)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700317 FMT_THROW(fmt::FormatError("number is too big"));
Victor Zverovich9d74f952014-07-16 07:27:54 -0700318 return static_cast<unsigned>(width);
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700319 }
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700320};
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700321
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700322class PrecisionHandler :
323 public fmt::internal::ArgVisitor<PrecisionHandler, int> {
324 public:
vitautd4ea2d72015-03-26 08:55:20 -0700325 void report_unhandled_arg() {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700326 FMT_THROW(fmt::FormatError("precision is not integer"));
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700327 }
328
329 template <typename T>
330 int visit_any_int(T value) {
Victor Zverovichadce0242014-08-17 07:53:55 -0700331 if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
Victor Zverovich8b76e972014-10-06 08:30:55 -0700332 FMT_THROW(fmt::FormatError("number is too big"));
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700333 return static_cast<int>(value);
334 }
335};
336
Victor Zverovich32344d92014-08-28 08:11:21 -0700337// Converts an integer argument to an integral type T for printf.
Victor Zverovicheeca2232014-07-30 07:37:16 -0700338template <typename T>
339class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
340 private:
341 fmt::internal::Arg &arg_;
Victor Zveroviche22d6572014-08-08 06:51:09 -0700342 wchar_t type_;
Victor Zverovicheeca2232014-07-30 07:37:16 -0700343
Victor Zverovich6f3c0952014-12-03 06:16:52 -0800344 FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
345
Victor Zverovicheeca2232014-07-30 07:37:16 -0700346 public:
Victor Zveroviche22d6572014-08-08 06:51:09 -0700347 ArgConverter(fmt::internal::Arg &arg, wchar_t type)
348 : arg_(arg), type_(type) {}
Victor Zverovicheeca2232014-07-30 07:37:16 -0700349
350 template <typename U>
351 void visit_any_int(U value) {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700352 bool is_signed = type_ == 'd' || type_ == 'i';
353 using fmt::internal::Arg;
354 if (sizeof(T) <= sizeof(int)) {
Victor Zverovich32344d92014-08-28 08:11:21 -0700355 // Extra casts are used to silence warnings.
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700356 if (is_signed) {
357 arg_.type = Arg::INT;
Victor Zverovichbb016332014-08-15 09:03:59 -0700358 arg_.int_value = static_cast<int>(static_cast<T>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700359 } else {
360 arg_.type = Arg::UINT;
Victor Zverovich186734c2014-08-18 07:03:12 -0700361 arg_.uint_value = static_cast<unsigned>(
362 static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700363 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700364 } else {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700365 if (is_signed) {
366 arg_.type = Arg::LONG_LONG;
Victor Zverovicha259c942014-08-01 07:15:27 -0700367 arg_.long_long_value =
368 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700369 } else {
370 arg_.type = Arg::ULONG_LONG;
371 arg_.ulong_long_value =
Victor Zverovicha259c942014-08-01 07:15:27 -0700372 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700373 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700374 }
375 }
376};
377
Victor Zverovich32344d92014-08-28 08:11:21 -0700378// Converts an integer argument to char for printf.
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700379class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
380 private:
381 fmt::internal::Arg &arg_;
382
Victor Zverovich6f3c0952014-12-03 06:16:52 -0800383 FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
384
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700385 public:
386 explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
387
388 template <typename T>
389 void visit_any_int(T value) {
390 arg_.type = Arg::CHAR;
391 arg_.int_value = static_cast<char>(value);
392 }
393};
394
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700395// This function template is used to prevent compile errors when handling
396// incompatible string arguments, e.g. handling a wide string in a narrow
397// string formatter.
398template <typename Char>
399Arg::StringValue<Char> ignore_incompatible_str(Arg::StringValue<wchar_t>);
400
401template <>
402inline Arg::StringValue<char> ignore_incompatible_str(
403 Arg::StringValue<wchar_t>) { return Arg::StringValue<char>(); }
404
405template <>
406inline Arg::StringValue<wchar_t> ignore_incompatible_str(
407 Arg::StringValue<wchar_t> s) { return s; }
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700408} // namespace
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700409
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800410FMT_FUNC void fmt::SystemError::init(
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800411 int err_code, StringRef format_str, ArgList args) {
412 error_code_ = err_code;
Victor Zverovichd1ded562014-09-29 08:48:16 -0700413 MemoryWriter w;
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800414 internal::format_system_error(w, err_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700415 std::runtime_error &base = *this;
416 base = std::runtime_error(w.str());
417}
418
Victor Zverovichb605b392013-09-09 22:21:40 -0700419template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700420int fmt::internal::CharTraits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700421 char *buffer, std::size_t size, const char *format,
422 unsigned width, int precision, T value) {
423 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700424 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700425 FMT_SNPRINTF(buffer, size, format, value) :
426 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700427 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700428 return precision < 0 ?
429 FMT_SNPRINTF(buffer, size, format, width, value) :
430 FMT_SNPRINTF(buffer, size, format, width, precision, value);
431}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700432
Victor Zverovichb605b392013-09-09 22:21:40 -0700433template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700434int fmt::internal::CharTraits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700435 wchar_t *buffer, std::size_t size, const wchar_t *format,
436 unsigned width, int precision, T value) {
437 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700438 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000439 FMT_SWPRINTF(buffer, size, format, value) :
440 FMT_SWPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700441 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700442 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000443 FMT_SWPRINTF(buffer, size, format, width, value) :
444 FMT_SWPRINTF(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700445}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800446
Victor Zverovich311251e2014-11-29 06:58:00 -0800447template <typename T>
448const char fmt::internal::BasicData<T>::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800449 "0001020304050607080910111213141516171819"
450 "2021222324252627282930313233343536373839"
451 "4041424344454647484950515253545556575859"
452 "6061626364656667686970717273747576777879"
453 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800454
Victor Zverovichf1d85162014-02-19 13:02:22 -0800455#define FMT_POWERS_OF_10(factor) \
456 factor * 10, \
457 factor * 100, \
458 factor * 1000, \
459 factor * 10000, \
460 factor * 100000, \
461 factor * 1000000, \
462 factor * 10000000, \
463 factor * 100000000, \
464 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800465
Victor Zverovich311251e2014-11-29 06:58:00 -0800466template <typename T>
467const uint32_t fmt::internal::BasicData<T>::POWERS_OF_10_32[] = {
468 0, FMT_POWERS_OF_10(1)
469};
470
471template <typename T>
472const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800473 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800474 FMT_POWERS_OF_10(1),
Victor Zverovichecd2b802014-12-17 06:42:26 -0800475 FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
Victor Zverovich406c6122014-08-19 08:47:38 -0700476 // Multiply several constants instead of using a single long long constant
Victor Zverovichf1d85162014-02-19 13:02:22 -0800477 // to avoid warnings about C++98 not supporting long long.
Victor Zverovichecd2b802014-12-17 06:42:26 -0800478 fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800479};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800480
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800481FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
Carter Li2d4631a2015-03-14 14:54:37 +0800482 (void)type;
Victor Zverovich877abaf2013-01-08 09:56:05 -0800483 if (std::isprint(static_cast<unsigned char>(code))) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700484 FMT_THROW(fmt::FormatError(
485 fmt::format("unknown format code '{}' for {}", code, type)));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800486 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700487 FMT_THROW(fmt::FormatError(
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700488 fmt::format("unknown format code '\\x{:02x}' for {}",
Victor Zverovich8b76e972014-10-06 08:30:55 -0700489 static_cast<unsigned>(code), type)));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800490}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700491
vitaut24c309f2015-06-12 07:15:57 -0700492#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700493
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800494FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700495 int length = MultiByteToWideChar(
496 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, 0, 0);
Victor Zverovichdff21372014-12-16 07:01:01 -0800497 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700498 if (length == 0)
Victor Zverovichdff21372014-12-16 07:01:01 -0800499 FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700500 buffer_.resize(length);
501 length = MultiByteToWideChar(
502 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, &buffer_[0], length);
503 if (length == 0)
Victor Zverovichdff21372014-12-16 07:01:01 -0800504 FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700505}
506
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800507FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700508 if (int error_code = convert(s)) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700509 FMT_THROW(WindowsError(error_code,
510 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700511 }
512}
513
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800514FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700515 int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, 0, 0, 0, 0);
516 if (length == 0)
517 return GetLastError();
518 buffer_.resize(length);
519 length = WideCharToMultiByte(
520 CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, 0, 0);
521 if (length == 0)
522 return GetLastError();
523 return 0;
524}
525
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800526FMT_FUNC void fmt::WindowsError::init(
Carter Li3f574c12015-02-17 10:11:42 +0800527 int err_code, StringRef format_str, ArgList args) {
528 error_code_ = err_code;
Victor Zverovich8c4db502014-09-29 09:17:02 -0700529 MemoryWriter w;
Carter Li3f574c12015-02-17 10:11:42 +0800530 internal::format_windows_error(w, err_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700531 std::runtime_error &base = *this;
532 base = std::runtime_error(w.str());
533}
534
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800535FMT_FUNC void fmt::internal::format_windows_error(
Victor Zverovich22f75d82014-09-03 08:03:05 -0700536 fmt::Writer &out, int error_code,
Carter Lie2583ab2015-02-14 09:58:29 +0800537 fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovich53b4c312014-04-30 15:00:41 -0700538 class String {
539 private:
540 LPWSTR str_;
541
542 public:
543 String() : str_() {}
544 ~String() { LocalFree(str_); }
545 LPWSTR *ptr() { return &str_; }
546 LPCWSTR c_str() const { return str_; }
547 };
Victor Zverovich8b76e972014-10-06 08:30:55 -0700548 FMT_TRY {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700549 String system_message;
550 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
551 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
552 error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
553 reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
554 UTF16ToUTF8 utf8_message;
555 if (utf8_message.convert(system_message.c_str()) == ERROR_SUCCESS) {
556 out << message << ": " << utf8_message;
557 return;
558 }
Victor Zverovich53b4c312014-04-30 15:00:41 -0700559 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700560 } FMT_CATCH(...) {}
Victor Zverovich22f75d82014-09-03 08:03:05 -0700561 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700562}
vitaut24c309f2015-06-12 07:15:57 -0700563
564#endif // FMT_USE_WINDOWS_H
565
566FMT_FUNC void fmt::internal::format_system_error(
567 fmt::Writer &out, int error_code,
568 fmt::StringRef message) FMT_NOEXCEPT {
569 FMT_TRY {
570 MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
571 buffer.resize(INLINE_BUFFER_SIZE);
572 for (;;) {
573 char *system_message = &buffer[0];
574 int result = safe_strerror(error_code, system_message, buffer.size());
575 if (result == 0) {
576 out << message << ": " << system_message;
577 return;
578 }
579 if (result != ERANGE)
580 break; // Can't get error message, report error code instead.
581 buffer.resize(buffer.size() * 2);
582 }
583 } FMT_CATCH(...) {}
584 format_error_code(out, error_code, message);
585}
Victor Zverovich53b4c312014-04-30 15:00:41 -0700586
jamboree7487bde2015-06-10 09:32:59 +0800587template <typename Char>
vitauta98583d2015-06-10 08:49:22 -0700588void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
jamboree7487bde2015-06-10 09:32:59 +0800589 if (!map_.empty())
590 return;
vitauta98583d2015-06-10 08:49:22 -0700591 typedef internal::NamedArg<Char> NamedArg;
vitautfccff7b2015-06-11 07:19:00 -0700592 const NamedArg *named_arg = 0;
vitauta98583d2015-06-10 08:49:22 -0700593 bool use_values =
594 args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
jamboree7487bde2015-06-10 09:32:59 +0800595 if (use_values) {
596 for (unsigned i = 0;/*nothing*/; ++i) {
597 internal::Arg::Type arg_type = args.type(i);
598 switch (arg_type) {
599 case internal::Arg::NONE:
600 return;
601 case internal::Arg::NAMED_ARG:
vitauta98583d2015-06-10 08:49:22 -0700602 named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
jamboree7487bde2015-06-10 09:32:59 +0800603 map_.insert(Pair(named_arg->name, *named_arg));
604 break;
605 default:
606 /*nothing*/;
607 }
608 }
609 return;
610 }
vitauta98583d2015-06-10 08:49:22 -0700611 for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
jamboree7487bde2015-06-10 09:32:59 +0800612 internal::Arg::Type arg_type = args.type(i);
613 if (arg_type == internal::Arg::NAMED_ARG) {
vitauta98583d2015-06-10 08:49:22 -0700614 named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
jamboree7487bde2015-06-10 09:32:59 +0800615 map_.insert(Pair(named_arg->name, *named_arg));
616 }
617 }
vitauta98583d2015-06-10 08:49:22 -0700618 for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
jamboree7487bde2015-06-10 09:32:59 +0800619 switch (args.args_[i].type) {
620 case internal::Arg::NONE:
621 return;
622 case internal::Arg::NAMED_ARG:
vitauta98583d2015-06-10 08:49:22 -0700623 named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
jamboree7487bde2015-06-10 09:32:59 +0800624 map_.insert(Pair(named_arg->name, *named_arg));
625 break;
626 default:
627 /*nothing*/;
628 }
629 }
630}
631
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700632// An argument formatter.
633template <typename Char>
634class fmt::internal::ArgFormatter :
635 public fmt::internal::ArgVisitor<fmt::internal::ArgFormatter<Char>, void> {
636 private:
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700637 fmt::BasicFormatter<Char> &formatter_;
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700638 fmt::BasicWriter<Char> &writer_;
639 fmt::FormatSpec &spec_;
640 const Char *format_;
641
Victor Zverovich6f3c0952014-12-03 06:16:52 -0800642 FMT_DISALLOW_COPY_AND_ASSIGN(ArgFormatter);
643
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700644 public:
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700645 ArgFormatter(
646 fmt::BasicFormatter<Char> &f,fmt::FormatSpec &s, const Char *fmt)
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700647 : formatter_(f), writer_(f.writer()), spec_(s), format_(fmt) {}
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700648
Victor Zverovich9d74f952014-07-16 07:27:54 -0700649 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700650 void visit_any_int(T value) { writer_.write_int(value, spec_); }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700651
652 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700653 void visit_any_double(T value) { writer_.write_double(value, spec_); }
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700654
vitaut9d092142015-06-11 09:00:06 -0700655 void visit_bool(bool value) {
656 if (spec_.type_) {
657 writer_.write_int(value, spec_);
658 return;
659 }
660 const char *str_value = value ? "true" : "false";
661 Arg::StringValue<char> str = { str_value, strlen(str_value) };
662 writer_.write_str(str, spec_);
663 }
664
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700665 void visit_char(int value) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700666 if (spec_.type_ && spec_.type_ != 'c') {
Victor Zverovichd699c2a2014-07-25 08:24:27 -0700667 spec_.flags_ |= CHAR_FLAG;
668 writer_.write_int(value, spec_);
669 return;
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700670 }
671 if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700672 FMT_THROW(FormatError("invalid format specifier for char"));
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700673 typedef typename fmt::BasicWriter<Char>::CharPtr CharPtr;
Victor Zverovich43aebf52015-01-08 07:56:08 -0800674 Char fill = static_cast<Char>(spec_.fill());
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700675 CharPtr out = CharPtr();
676 if (spec_.width_ > 1) {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700677 out = writer_.grow_buffer(spec_.width_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700678 if (spec_.align_ == fmt::ALIGN_RIGHT) {
679 std::fill_n(out, spec_.width_ - 1, fill);
680 out += spec_.width_ - 1;
681 } else if (spec_.align_ == fmt::ALIGN_CENTER) {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700682 out = writer_.fill_padding(out, spec_.width_, 1, fill);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700683 } else {
684 std::fill_n(out + 1, spec_.width_ - 1, fill);
685 }
686 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700687 out = writer_.grow_buffer(1);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700688 }
689 *out = static_cast<Char>(value);
690 }
691
692 void visit_string(Arg::StringValue<char> value) {
693 writer_.write_str(value, spec_);
694 }
695 void visit_wstring(Arg::StringValue<wchar_t> value) {
696 writer_.write_str(ignore_incompatible_str<Char>(value), spec_);
697 }
698
699 void visit_pointer(const void *value) {
700 if (spec_.type_ && spec_.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700701 fmt::internal::report_unknown_type(spec_.type_, "pointer");
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700702 spec_.flags_ = fmt::HASH_FLAG;
703 spec_.type_ = 'x';
Victor Zverovichc1db2932014-07-24 08:53:27 -0700704 writer_.write_int(reinterpret_cast<uintptr_t>(value), spec_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700705 }
706
707 void visit_custom(Arg::CustomValue c) {
Victor Zverovich271fa8c2014-08-29 07:23:54 -0700708 c.format(&formatter_, c.value, &format_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700709 }
710};
711
Victor Zverovichd1ded562014-09-29 08:48:16 -0700712template <typename Char>
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800713void fmt::internal::FixedBuffer<Char>::grow(std::size_t) {
714 FMT_THROW(std::runtime_error("buffer overflow"));
715}
716
717template <typename Char>
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700718template <typename StrChar>
Victor Zverovichd1ded562014-09-29 08:48:16 -0700719void fmt::BasicWriter<Char>::write_str(
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800720 const Arg::StringValue<StrChar> &s, const FormatSpec &spec) {
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700721 // Check if StrChar is convertible to Char.
722 internal::CharTraits<Char>::convert(StrChar());
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700723 if (spec.type_ && spec.type_ != 's')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700724 internal::report_unknown_type(spec.type_, "string");
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800725 const StrChar *str_value = s.value;
726 std::size_t str_size = s.size;
727 if (str_size == 0) {
728 if (!str_value)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700729 FMT_THROW(FormatError("string pointer is null"));
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800730 if (*str_value)
731 str_size = std::char_traits<StrChar>::length(str_value);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700732 }
Victor Zverovich59254412015-02-06 07:27:19 -0800733 std::size_t precision = spec.precision_;
734 if (spec.precision_ >= 0 && precision < str_size)
Victor Zverovich43aebf52015-01-08 07:56:08 -0800735 str_size = spec.precision_;
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800736 write_str(str_value, str_size, spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700737}
738
739template <typename Char>
jamboree7487bde2015-06-10 09:32:59 +0800740inline Arg fmt::BasicFormatter<Char>::get_arg(
vitautfccff7b2015-06-11 07:19:00 -0700741 BasicStringRef<Char> arg_name, const char *&error) {
jamboree7487bde2015-06-10 09:32:59 +0800742 if (check_no_auto_index(error)) {
vitautfccff7b2015-06-11 07:19:00 -0700743 map_.init(args());
744 const Arg *arg = map_.find(arg_name);
jamboree7487bde2015-06-10 09:32:59 +0800745 if (arg)
746 return *arg;
747 error = "argument not found";
748 }
749 return Arg();
750}
751
752template <typename Char>
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700753inline Arg fmt::BasicFormatter<Char>::parse_arg_index(const Char *&s) {
Victor Zverovich9646e382014-08-27 09:13:42 -0700754 const char *error = 0;
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700755 Arg arg = *s < '0' || *s > '9' ?
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700756 next_arg(error) : get_arg(parse_nonnegative_int(s), error);
Victor Zverovich8b76e972014-10-06 08:30:55 -0700757 if (error) {
758 FMT_THROW(FormatError(
759 *s != '}' && *s != ':' ? "invalid format string" : error));
760 }
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700761 return arg;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700762}
763
jamboree7487bde2015-06-10 09:32:59 +0800764template <typename Char>
765inline Arg fmt::BasicFormatter<Char>::parse_arg_name(const Char *&s) {
766 assert(is_name_start(*s));
767 const Char *start = s;
768 Char c;
769 do {
770 c = *++s;
jamboree3c99ed42015-06-11 12:03:22 +0800771 } while (is_name_start(c) || ('0' <= c && c <= '9'));
jamboree7487bde2015-06-10 09:32:59 +0800772 const char *error = 0;
773 Arg arg = get_arg(fmt::BasicStringRef<Char>(start, s - start), error);
774 if (error)
775 FMT_THROW(fmt::FormatError(error));
776 return arg;
777}
778
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800779FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
Victor Zverovich605d2602014-08-29 07:45:55 -0700780 unsigned arg_index, const char *&error) {
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700781 Arg arg = args_[arg_index];
jamboree7487bde2015-06-10 09:32:59 +0800782 switch (arg.type) {
783 case Arg::NONE:
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700784 error = "argument index out of range";
jamboree7487bde2015-06-10 09:32:59 +0800785 break;
786 case Arg::NAMED_ARG:
787 arg = *static_cast<const internal::Arg*>(arg.pointer);
788 default:
789 /*nothing*/;
790 }
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700791 return arg;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700792}
793
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700794inline Arg fmt::internal::FormatterBase::next_arg(const char *&error) {
Victor Zverovich605d2602014-08-29 07:45:55 -0700795 if (next_arg_index_ >= 0)
796 return do_get_arg(next_arg_index_++, error);
797 error = "cannot switch from manual to automatic argument indexing";
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700798 return Arg();
Victor Zverovich605d2602014-08-29 07:45:55 -0700799}
800
vitautfccff7b2015-06-11 07:19:00 -0700801inline bool fmt::internal::FormatterBase::check_no_auto_index(
802 const char *&error) {
jamboree7487bde2015-06-10 09:32:59 +0800803 if (next_arg_index_ > 0) {
804 error = "cannot switch from automatic to manual argument indexing";
805 return false;
806 }
vitautfccff7b2015-06-11 07:19:00 -0700807 next_arg_index_ = -1;
jamboree7487bde2015-06-10 09:32:59 +0800808 return true;
809}
810
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700811inline Arg fmt::internal::FormatterBase::get_arg(
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700812 unsigned arg_index, const char *&error) {
vitautfccff7b2015-06-11 07:19:00 -0700813 return check_no_auto_index(error) ? do_get_arg(arg_index, error) : Arg();
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 Zverovichbeb00ed2014-09-23 07:59:43 -0700844Arg fmt::internal::PrintfFormatter<Char>::get_arg(
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700845 const Char *s, unsigned arg_index) {
Carter Li2d4631a2015-03-14 14:54:37 +0800846 (void)s;
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700847 const char *error = 0;
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700848 Arg arg = arg_index == UINT_MAX ?
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700849 next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
850 if (error)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700851 FMT_THROW(FormatError(!*s ? "invalid format string" : error));
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700852 return arg;
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700853}
854
855template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700856unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700857 const Char *&s, FormatSpec &spec) {
Victor Zverovichcb743c02014-06-19 07:40:35 -0700858 unsigned arg_index = UINT_MAX;
859 Char c = *s;
860 if (c >= '0' && c <= '9') {
861 // Parse an argument index (if followed by '$') or a width possibly
Victor Zverovich879838a2014-06-20 07:34:02 -0700862 // preceded with '0' flag(s).
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700863 unsigned value = parse_nonnegative_int(s);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700864 if (*s == '$') { // value is an argument index
865 ++s;
866 arg_index = value;
867 } else {
868 if (c == '0')
869 spec.fill_ = '0';
870 if (value != 0) {
871 // Nonzero value means that we parsed width and don't need to
872 // parse it or flags again, so return now.
873 spec.width_ = value;
874 return arg_index;
875 }
876 }
877 }
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700878 parse_flags(spec, s);
Victor Zverovich4099a122014-06-23 08:10:50 -0700879 // Parse width.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700880 if (*s >= '0' && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700881 spec.width_ = parse_nonnegative_int(s);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700882 } else if (*s == '*') {
883 ++s;
Victor Zverovich56fc5252014-08-28 07:48:55 -0700884 spec.width_ = WidthHandler(spec).visit(get_arg(s));
Victor Zverovichcb743c02014-06-19 07:40:35 -0700885 }
886 return arg_index;
887}
888
Victor Zverovich1f19b982014-06-16 07:49:30 -0700889template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700890void fmt::internal::PrintfFormatter<Char>::format(
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800891 BasicWriter<Char> &writer, BasicStringRef<Char> format_str,
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700892 const ArgList &args) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800893 const Char *start = format_str.c_str();
Victor Zverovich605d2602014-08-29 07:45:55 -0700894 set_args(args);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700895 const Char *s = start;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700896 while (*s) {
Victor Zverovich0fc73162013-09-07 12:52:52 -0700897 Char c = *s++;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700898 if (c != '%') continue;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700899 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -0700900 write(writer, start, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700901 start = ++s;
902 continue;
903 }
Victor Zverovichc1db2932014-07-24 08:53:27 -0700904 write(writer, start, s - 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700905
Victor Zverovichcb743c02014-06-19 07:40:35 -0700906 FormatSpec spec;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700907 spec.align_ = ALIGN_RIGHT;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700908
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700909 // Parse argument index, flags and width.
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700910 unsigned arg_index = parse_header(s, spec);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700911
912 // Parse precision.
913 if (*s == '.') {
914 ++s;
915 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700916 spec.precision_ = parse_nonnegative_int(s);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700917 } else if (*s == '*') {
918 ++s;
Victor Zverovich56fc5252014-08-28 07:48:55 -0700919 spec.precision_ = PrecisionHandler().visit(get_arg(s));
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700920 }
921 }
922
Victor Zverovich56fc5252014-08-28 07:48:55 -0700923 Arg arg = get_arg(s, arg_index);
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700924 if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
Victor Zverovichcb743c02014-06-19 07:40:35 -0700925 spec.flags_ &= ~HASH_FLAG;
926 if (spec.fill_ == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700927 if (arg.type <= Arg::LAST_NUMERIC_TYPE)
Victor Zverovichcb743c02014-06-19 07:40:35 -0700928 spec.align_ = ALIGN_NUMERIC;
929 else
930 spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700931 }
932
Victor Zverovichf4156b52014-07-30 08:39:07 -0700933 // Parse length and convert the argument to the required type.
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700934 switch (*s++) {
935 case 'h':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700936 if (*s == 'h')
937 ArgConverter<signed char>(arg, *++s).visit(arg);
Victor Zverovich39b09302014-07-30 08:08:08 -0700938 else
Victor Zverovichf4156b52014-07-30 08:39:07 -0700939 ArgConverter<short>(arg, *s).visit(arg);
Victor Zverovicheeca2232014-07-30 07:37:16 -0700940 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700941 case 'l':
Victor Zverovichd3a70392014-08-12 08:36:19 -0700942 if (*s == 'l')
Victor Zveroviche488a282014-08-13 06:53:43 -0700943 ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
Victor Zverovichd3a70392014-08-12 08:36:19 -0700944 else
945 ArgConverter<long>(arg, *s).visit(arg);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700946 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700947 case 'j':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700948 ArgConverter<intmax_t>(arg, *s).visit(arg);
949 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700950 case 'z':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700951 ArgConverter<size_t>(arg, *s).visit(arg);
952 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700953 case 't':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700954 ArgConverter<ptrdiff_t>(arg, *s).visit(arg);
955 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700956 case 'L':
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700957 // printf produces garbage when 'L' is omitted for long double, no
958 // need to do the same.
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700959 break;
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700960 default:
961 --s;
Victor Zverovichbe00d8b2014-08-19 08:49:10 -0700962 ArgConverter<int>(arg, *s).visit(arg);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700963 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700964
965 // Parse type.
966 if (!*s)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700967 FMT_THROW(FormatError("invalid format string"));
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700968 spec.type_ = static_cast<char>(*s++);
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700969 if (arg.type <= Arg::LAST_INTEGER_TYPE) {
970 // Normalize type.
971 switch (spec.type_) {
972 case 'i': case 'u':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700973 spec.type_ = 'd';
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700974 break;
975 case 'c':
976 // TODO: handle wchar_t
977 CharConverter(arg).visit(arg);
978 break;
979 }
Victor Zverovichf4156b52014-07-30 08:39:07 -0700980 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700981
982 start = s;
983
984 // Format argument.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700985 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700986 case Arg::INT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700987 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700988 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700989 case Arg::UINT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700990 writer.write_int(arg.uint_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700991 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700992 case Arg::LONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700993 writer.write_int(arg.long_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700994 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700995 case Arg::ULONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700996 writer.write_int(arg.ulong_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700997 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700998 case Arg::CHAR: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700999 if (spec.type_ && spec.type_ != 'c')
Victor Zverovichc1db2932014-07-24 08:53:27 -07001000 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001001 typedef typename BasicWriter<Char>::CharPtr CharPtr;
1002 CharPtr out = CharPtr();
1003 if (spec.width_ > 1) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001004 Char fill = ' ';
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001005 out = writer.grow_buffer(spec.width_);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001006 if (spec.align_ != ALIGN_LEFT) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001007 std::fill_n(out, spec.width_ - 1, fill);
1008 out += spec.width_ - 1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001009 } else {
1010 std::fill_n(out + 1, spec.width_ - 1, fill);
1011 }
1012 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001013 out = writer.grow_buffer(1);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001014 }
Victor Zverovichcb743c02014-06-19 07:40:35 -07001015 *out = static_cast<Char>(arg.int_value);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001016 break;
1017 }
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001018 case Arg::DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001019 writer.write_double(arg.double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001020 break;
1021 case Arg::LONG_DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001022 writer.write_double(arg.long_double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001023 break;
Victor Zverovich75a2ea02014-09-25 07:10:44 -07001024 case Arg::CSTRING:
1025 arg.string.size = 0;
1026 writer.write_str(arg.string, spec);
1027 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001028 case Arg::STRING:
Victor Zverovich53201032014-06-30 14:26:29 -07001029 writer.write_str(arg.string, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001030 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001031 case Arg::WSTRING:
Victor Zverovich512e2ce2014-07-14 08:47:03 -07001032 writer.write_str(ignore_incompatible_str<Char>(arg.wstring), spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001033 break;
1034 case Arg::POINTER:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001035 if (spec.type_ && spec.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001036 internal::report_unknown_type(spec.type_, "pointer");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001037 spec.flags_= HASH_FLAG;
1038 spec.type_ = 'x';
Victor Zverovichab6e7592014-09-23 08:21:58 -07001039 writer.write_int(reinterpret_cast<uintptr_t>(arg.pointer), spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001040 break;
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001041 case Arg::CUSTOM: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001042 if (spec.type_)
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001043 internal::report_unknown_type(spec.type_, "object");
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -08001044 const void *str_format = "s";
1045 arg.custom.format(&writer, arg.custom.value, &str_format);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001046 break;
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001047 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001048 default:
1049 assert(false);
1050 break;
1051 }
1052 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001053 write(writer, start, s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001054}
1055
1056template <typename Char>
Victor Zverovichb9a06ba2014-07-08 16:38:50 -07001057const Char *fmt::BasicFormatter<Char>::format(
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001058 const Char *&format_str, const Arg &arg) {
Victor Zveroviche8251562014-07-08 16:20:33 -07001059 const Char *s = format_str;
Victor Zveroviche8251562014-07-08 16:20:33 -07001060 FormatSpec spec;
1061 if (*s == ':') {
1062 if (arg.type == Arg::CUSTOM) {
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001063 arg.custom.format(this, arg.custom.value, &s);
1064 return s;
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 Zverovich8b76e972014-10-06 08:30:55 -07001090 FMT_THROW(FormatError("invalid fill character '{'"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001091 s += 2;
1092 spec.fill_ = c;
1093 } else ++s;
Victor Zverovich5debb2a2014-08-29 08:16:10 -07001094 if (spec.align_ == ALIGN_NUMERIC)
1095 require_numeric_argument(arg, '=');
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 == '#') {
Victor Zverovich5debb2a2014-08-29 08:16:10 -07001118 require_numeric_argument(arg, '#');
Victor Zveroviche8251562014-07-08 16:20:33 -07001119 spec.flags_ |= HASH_FLAG;
1120 ++s;
1121 }
1122
jamboree54a6cb32015-06-04 13:59:37 +08001123 // Parse zero flag.
1124 if (*s == '0') {
vitaut8949a2e2015-06-08 06:53:18 -07001125 require_numeric_argument(arg, '0');
1126 spec.align_ = ALIGN_NUMERIC;
1127 spec.fill_ = '0';
1128 ++s;
jamboree54a6cb32015-06-04 13:59:37 +08001129 }
1130
1131 // Parse width.
1132 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -07001133 spec.width_ = parse_nonnegative_int(s);
jamboree54a6cb32015-06-04 13:59:37 +08001134 } else if (*s == '{') {
vitaut8949a2e2015-06-08 06:53:18 -07001135 ++s;
vitautfccff7b2015-06-11 07:19:00 -07001136 Arg width_arg = is_name_start(*s) ?
1137 parse_arg_name(s) : parse_arg_index(s);
vitaut8949a2e2015-06-08 06:53:18 -07001138 if (*s++ != '}')
1139 FMT_THROW(FormatError("invalid format string"));
1140 ULongLong value = 0;
1141 switch (width_arg.type) {
1142 case Arg::INT:
1143 if (width_arg.int_value < 0)
1144 FMT_THROW(FormatError("negative width"));
1145 value = width_arg.int_value;
1146 break;
1147 case Arg::UINT:
1148 value = width_arg.uint_value;
1149 break;
1150 case Arg::LONG_LONG:
1151 if (width_arg.long_long_value < 0)
1152 FMT_THROW(FormatError("negative width"));
1153 value = width_arg.long_long_value;
1154 break;
1155 case Arg::ULONG_LONG:
1156 value = width_arg.ulong_long_value;
1157 break;
1158 default:
1159 FMT_THROW(FormatError("width is not integer"));
1160 }
1161 if (value > INT_MAX)
1162 FMT_THROW(FormatError("number is too big"));
1163 spec.width_ = static_cast<int>(value);
Victor Zveroviche8251562014-07-08 16:20:33 -07001164 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001165
Victor Zveroviche8251562014-07-08 16:20:33 -07001166 // Parse precision.
1167 if (*s == '.') {
1168 ++s;
1169 spec.precision_ = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001170 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -07001171 spec.precision_ = parse_nonnegative_int(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001172 } else if (*s == '{') {
Victor Zverovich7cae7632013-09-06 20:23:42 -07001173 ++s;
vitautfccff7b2015-06-11 07:19:00 -07001174 Arg precision_arg =
1175 is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s);
Victor Zverovich42de4f12014-08-27 08:24:31 -07001176 if (*s++ != '}')
Victor Zverovich8b76e972014-10-06 08:30:55 -07001177 FMT_THROW(FormatError("invalid format string"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001178 ULongLong value = 0;
1179 switch (precision_arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001180 case Arg::INT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001181 if (precision_arg.int_value < 0)
Victor Zverovich8b76e972014-10-06 08:30:55 -07001182 FMT_THROW(FormatError("negative precision"));
Victor Zverovich7cae7632013-09-06 20:23:42 -07001183 value = precision_arg.int_value;
1184 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001185 case Arg::UINT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001186 value = precision_arg.uint_value;
1187 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001188 case Arg::LONG_LONG:
Victor Zverovich56f12b72013-11-22 07:45:43 -08001189 if (precision_arg.long_long_value < 0)
Victor Zverovich8b76e972014-10-06 08:30:55 -07001190 FMT_THROW(FormatError("negative precision"));
Victor Zverovich56f12b72013-11-22 07:45:43 -08001191 value = precision_arg.long_long_value;
1192 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001193 case Arg::ULONG_LONG:
Gregory Czajkowskia65542b2013-11-18 22:58:39 -08001194 value = precision_arg.ulong_long_value;
Victor Zverovicha4e72b42013-11-21 09:11:58 -08001195 break;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001196 default:
Victor Zverovich8b76e972014-10-06 08:30:55 -07001197 FMT_THROW(FormatError("precision is not integer"));
Victor Zverovich7cae7632013-09-06 20:23:42 -07001198 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001199 if (value > INT_MAX)
Victor Zverovich8b76e972014-10-06 08:30:55 -07001200 FMT_THROW(FormatError("number is too big"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001201 spec.precision_ = static_cast<int>(value);
Victor Zveroviche8251562014-07-08 16:20:33 -07001202 } else {
Victor Zverovich8b76e972014-10-06 08:30:55 -07001203 FMT_THROW(FormatError("missing precision specifier"));
Victor Zverovich7cae7632013-09-06 20:23:42 -07001204 }
vitautfd5c2e92015-06-11 08:58:31 -07001205 if (arg.type <= Arg::LAST_INTEGER_TYPE || arg.type == Arg::POINTER) {
Victor Zverovich8b76e972014-10-06 08:30:55 -07001206 FMT_THROW(FormatError(
Victor Zverovich43aebf52015-01-08 07:56:08 -08001207 fmt::format("precision not allowed in {} format specifier",
1208 arg.type == Arg::POINTER ? "pointer" : "integer")));
Victor Zveroviche8251562014-07-08 16:20:33 -07001209 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001210 }
1211
Victor Zveroviche8251562014-07-08 16:20:33 -07001212 // Parse type.
1213 if (*s != '}' && *s)
1214 spec.type_ = static_cast<char>(*s++);
1215 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001216
Victor Zveroviche8251562014-07-08 16:20:33 -07001217 if (*s++ != '}')
Victor Zverovich8b76e972014-10-06 08:30:55 -07001218 FMT_THROW(FormatError("missing '}' in format string"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001219 start_ = s;
1220
1221 // Format argument.
Victor Zverovich4edc88f2014-07-16 08:38:15 -07001222 internal::ArgFormatter<Char>(*this, spec, s - 1).visit(arg);
Victor Zveroviche8251562014-07-08 16:20:33 -07001223 return s;
1224}
1225
1226template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001227void fmt::BasicFormatter<Char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001228 BasicStringRef<Char> format_str, const ArgList &args) {
1229 const Char *s = start_ = format_str.c_str();
Victor Zverovich605d2602014-08-29 07:45:55 -07001230 set_args(args);
Victor Zveroviche8251562014-07-08 16:20:33 -07001231 while (*s) {
1232 Char c = *s++;
1233 if (c != '{' && c != '}') continue;
1234 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -07001235 write(writer_, start_, s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001236 start_ = ++s;
1237 continue;
1238 }
1239 if (c == '}')
Victor Zverovich8b76e972014-10-06 08:30:55 -07001240 FMT_THROW(FormatError("unmatched '}' in format string"));
Victor Zverovichc1db2932014-07-24 08:53:27 -07001241 write(writer_, start_, s - 1);
jamboree7487bde2015-06-10 09:32:59 +08001242 Arg arg = is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001243 s = format(s, arg);
1244 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001245 write(writer_, start_, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001246}
1247
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001248FMT_FUNC void fmt::report_system_error(
Carter Lie2583ab2015-02-14 09:58:29 +08001249 int error_code, fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001250 report_error(internal::format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001251}
1252
vitaut24c309f2015-06-12 07:15:57 -07001253#if FMT_USE_WINDOWS_H
Victor Zverovichb49a1b42014-12-09 06:32:07 -08001254FMT_FUNC void fmt::report_windows_error(
Carter Lie2583ab2015-02-14 09:58:29 +08001255 int error_code, fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001256 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001257}
Victor Zverovich400812a2014-04-30 12:38:17 -07001258#endif
Victor Zverovichf7939862014-04-30 10:18:11 -07001259
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001260FMT_FUNC void fmt::print(std::FILE *f, StringRef format_str, ArgList args) {
Victor Zverovichd1ded562014-09-29 08:48:16 -07001261 MemoryWriter w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001262 w.write(format_str, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001263 std::fwrite(w.data(), 1, w.size(), f);
1264}
1265
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001266FMT_FUNC void fmt::print(StringRef format_str, ArgList args) {
Victor Zverovich163178e2014-09-25 07:08:25 -07001267 print(stdout, format_str, args);
1268}
1269
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001270FMT_FUNC void fmt::print(std::ostream &os, StringRef format_str, ArgList args) {
Victor Zverovichd1ded562014-09-29 08:48:16 -07001271 MemoryWriter w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001272 w.write(format_str, args);
Victor Zveroviche3a44c12014-07-09 06:56:36 -07001273 os.write(w.data(), w.size());
1274}
1275
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001276FMT_FUNC void fmt::print_colored(Color c, StringRef format, ArgList args) {
Victor Zverovich2dc108b2014-07-01 09:10:43 -07001277 char escape[] = "\x1b[30m";
1278 escape[3] = '0' + static_cast<char>(c);
1279 std::fputs(escape, stdout);
1280 print(format, args);
1281 std::fputs(RESET_COLOR, stdout);
1282}
1283
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001284FMT_FUNC int fmt::fprintf(std::FILE *f, StringRef format, ArgList args) {
Victor Zverovichd1ded562014-09-29 08:48:16 -07001285 MemoryWriter w;
Victor Zverovich21111cc2014-06-29 19:52:26 -07001286 printf(w, format, args);
Victor Zverovich615c1ee2014-11-14 09:40:01 -08001287 std::size_t size = w.size();
1288 return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001289}
1290
Victor Zverovichc09c42f2015-03-01 09:43:33 -08001291#ifndef FMT_HEADER_ONLY
1292
vitaut9ca1ce22015-05-23 08:04:06 -07001293template struct fmt::internal::BasicData<void>;
vitaut804a74c2015-05-14 12:58:42 -07001294
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001295// Explicit instantiations for char.
1296
Victor Zverovich7c0d5752015-03-01 18:19:56 -08001297template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
1298
Victor Zverovichf43caef2014-09-25 07:21:48 -07001299template const char *fmt::BasicFormatter<char>::format(
1300 const char *&format_str, const fmt::internal::Arg &arg);
1301
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001302template void fmt::BasicFormatter<char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001303 BasicStringRef<char> format, const ArgList &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001304
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001305template void fmt::internal::PrintfFormatter<char>::format(
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001306 BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001307
Victor Zverovich14f25772014-09-19 08:45:05 -07001308template int fmt::internal::CharTraits<char>::format_float(
1309 char *buffer, std::size_t size, const char *format,
1310 unsigned width, int precision, double value);
1311
1312template int fmt::internal::CharTraits<char>::format_float(
1313 char *buffer, std::size_t size, const char *format,
1314 unsigned width, int precision, long double value);
1315
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001316// Explicit instantiations for wchar_t.
1317
Victor Zverovich7c0d5752015-03-01 18:19:56 -08001318template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
1319
Victor Zverovichf43caef2014-09-25 07:21:48 -07001320template const wchar_t *fmt::BasicFormatter<wchar_t>::format(
1321 const wchar_t *&format_str, const fmt::internal::Arg &arg);
1322
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001323template void fmt::BasicFormatter<wchar_t>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001324 BasicStringRef<wchar_t> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001325
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001326template void fmt::internal::PrintfFormatter<wchar_t>::format(
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001327 BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001328 const ArgList &args);
jdale88a9862fd2014-03-11 18:56:24 +00001329
Victor Zverovich14f25772014-09-19 08:45:05 -07001330template int fmt::internal::CharTraits<wchar_t>::format_float(
1331 wchar_t *buffer, std::size_t size, const wchar_t *format,
1332 unsigned width, int precision, double value);
1333
1334template int fmt::internal::CharTraits<wchar_t>::format_float(
1335 wchar_t *buffer, std::size_t size, const wchar_t *format,
1336 unsigned width, int precision, long double value);
1337
Victor Zverovichc09c42f2015-03-01 09:43:33 -08001338#endif // FMT_HEADER_ONLY
1339
jdale88a9862fd2014-03-11 18:56:24 +00001340#if _MSC_VER
1341# pragma warning(pop)
1342#endif