blob: a6a8565137d7810e6481f3ca2d222b3a00186fbb [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
Ryuuke5a9dc8f2015-02-08 16:08:29 +000038#ifdef _WIN32
Ryuuke5a9dc8f2015-02-08 16:08:29 +000039# ifdef __MINGW32__
40# include <cstring>
41# endif
vitaut67ce3942015-04-30 07:48:36 -070042# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
43# include <windows.h>
44# else
45# define NOMINMAX
46# include <windows.h>
47# undef NOMINMAX
48# endif
Ryuuke5a9dc8f2015-02-08 16:08:29 +000049#endif
50
Victor Zverovich6e5551e2014-07-02 06:33:25 -070051using fmt::internal::Arg;
Victor Zverovich447e02c2014-02-15 10:48:34 -080052
Victor Zverovich8b76e972014-10-06 08:30:55 -070053// Check if exceptions are disabled.
54#if __GNUC__ && !__EXCEPTIONS
55# define FMT_EXCEPTIONS 0
56#endif
57#if _MSC_VER && !_HAS_EXCEPTIONS
58# define FMT_EXCEPTIONS 0
59#endif
60#ifndef FMT_EXCEPTIONS
61# define FMT_EXCEPTIONS 1
62#endif
63
64#if FMT_EXCEPTIONS
65# define FMT_TRY try
66# define FMT_CATCH(x) catch (x)
67#else
68# define FMT_TRY if (true)
69# define FMT_CATCH(x) if (false)
70#endif
71
72#ifndef FMT_THROW
73# if FMT_EXCEPTIONS
74# define FMT_THROW(x) throw x
75# else
vitaut66915782015-03-25 07:24:26 -070076# define FMT_THROW(x) assert(false)
Victor Zverovich8b76e972014-10-06 08:30:55 -070077# endif
78#endif
79
Victor Zverovichd9c605c2014-11-28 06:40:57 -080080#ifdef FMT_HEADER_ONLY
81# define FMT_FUNC inline
Victor Zverovichc2a69032014-11-28 15:30:03 -080082#else
83# define FMT_FUNC
Victor Zverovichd9c605c2014-11-28 06:40:57 -080084#endif
85
jdale88a9862fd2014-03-11 18:56:24 +000086#if _MSC_VER
87# pragma warning(push)
Victor Zverovich8b76e972014-10-06 08:30:55 -070088# pragma warning(disable: 4127) // conditional expression is constant
Daniel.Perrybd0067e2014-11-25 18:01:09 -050089# pragma warning(disable: 4702) // unreachable code
vitautdf47d812015-03-16 18:53:14 -070090// Disable deprecation warning for strerror. The latter is not called but
91// MSVC fails to detect it.
92# pragma warning(disable: 4996)
jdale88a9862fd2014-03-11 18:56:24 +000093#endif
94
vitaut341b98c2015-03-14 13:39:33 -070095// Dummy implementations of strerror_r and strerror_s called if corresponding
96// system functions are not available.
vitaut4825fb42015-03-16 08:43:33 -070097static inline fmt::internal::None<> strerror_r(int, char *, ...) {
98 return fmt::internal::None<>();
vitaut341b98c2015-03-14 13:39:33 -070099}
vitaut4825fb42015-03-16 08:43:33 -0700100static inline fmt::internal::None<> strerror_s(char *, std::size_t, ...) {
101 return fmt::internal::None<>();
vitaut341b98c2015-03-14 13:39:33 -0700102}
103
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700104namespace {
105
106#ifndef _MSC_VER
Victor Zverovichb9a568b2014-09-19 07:51:42 -0700107# define FMT_SNPRINTF snprintf
Victor Zverovicha684d0c2013-12-27 08:00:10 -0800108#else // _MSC_VER
Victor Zverovich406c6122014-08-19 08:47:38 -0700109inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -0800110 va_list args;
111 va_start(args, format);
112 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
113 va_end(args);
114 return result;
115}
Victor Zverovichb9a568b2014-09-19 07:51:42 -0700116# define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700117#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -0800118
cstamford55836ca2015-03-10 07:04:31 +0000119#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
120# define FMT_SWPRINTF snwprintf
121#else
122# define FMT_SWPRINTF swprintf
123#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
124
Victor Zverovichadce0242014-08-17 07:53:55 -0700125// Checks if a value fits in int - used to avoid warnings about comparing
126// signed and unsigned integers.
127template <bool IsSigned>
128struct IntChecker {
129 template <typename T>
130 static bool fits_in_int(T value) {
131 unsigned max = INT_MAX;
132 return value <= max;
133 }
134};
135
136template <>
137struct IntChecker<true> {
138 template <typename T>
139 static bool fits_in_int(T value) {
140 return value >= INT_MIN && value <= INT_MAX;
141 }
142};
143
Victor Zverovich7004d1e2015-02-08 19:54:39 -0800144const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700145
Victor Zverovich22f75d82014-09-03 08:03:05 -0700146typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
147
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700148// Portable thread-safe version of strerror.
149// Sets buffer to point to a string describing the error code.
150// This can be either a pointer to a string stored in buffer,
151// or a pointer to some static immutable string.
152// Returns one of the following values:
153// 0 - success
154// ERANGE - buffer is not large enough to store the error message
155// other - failure
156// Buffer should be at least of size 1.
157int safe_strerror(
Carter Lie2583ab2015-02-14 09:58:29 +0800158 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700159 assert(buffer != 0 && buffer_size != 0);
vitaut341b98c2015-03-14 13:39:33 -0700160
vitaut341b98c2015-03-14 13:39:33 -0700161 class StrError {
162 private:
163 int error_code_;
164 char *&buffer_;
165 std::size_t buffer_size_;
166
vitautda052ae2015-03-21 07:53:39 -0700167 // A noop assignment operator to avoid bogus warnings.
168 void operator=(const StrError &) {}
169
vitaut341b98c2015-03-14 13:39:33 -0700170 // Handle the result of XSI-compliant version of strerror_r.
171 int handle(int result) {
vitaute1776ac2015-03-14 14:05:02 -0700172 // glibc versions before 2.13 return result in errno.
173 return result == -1 ? errno : result;
vitaut341b98c2015-03-14 13:39:33 -0700174 }
175
176 // Handle the result of GNU-specific version of strerror_r.
177 int handle(char *message) {
178 // If the buffer is full then the message is probably truncated.
179 if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
180 return ERANGE;
181 buffer_ = message;
182 return 0;
183 }
184
185 // Handle the case when strerror_r is not available.
vitaut4825fb42015-03-16 08:43:33 -0700186 int handle(fmt::internal::None<>) {
vitaut341b98c2015-03-14 13:39:33 -0700187 return fallback(strerror_s(buffer_, buffer_size_, error_code_));
188 }
189
190 // Fallback to strerror_s when strerror_r is not available.
191 int fallback(int result) {
192 // If the buffer is full then the message is probably truncated.
193 return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
194 ERANGE : result;
195 }
196
197 // Fallback to strerror if strerror_r and strerror_s are not available.
vitaut4825fb42015-03-16 08:43:33 -0700198 int fallback(fmt::internal::None<>) {
vitaut341b98c2015-03-14 13:39:33 -0700199 errno = 0;
200 buffer_ = strerror(error_code_);
201 return errno;
202 }
203
204 public:
205 StrError(int error_code, char *&buffer, std::size_t buffer_size)
206 : error_code_(error_code), buffer_(buffer), buffer_size_(buffer_size) {}
207
208 int run() { return handle(strerror_r(error_code_, buffer_, buffer_size_)); }
209 };
210 return StrError(error_code, buffer, buffer_size).run();
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700211}
212
Victor Zverovich22f75d82014-09-03 08:03:05 -0700213void format_error_code(fmt::Writer &out, int error_code,
Carter Lie2583ab2015-02-14 09:58:29 +0800214 fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700215 // Report error code making sure that the output fits into
216 // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
217 // bad_alloc.
218 out.clear();
219 static const char SEP[] = ": ";
vitaut1addec92015-03-21 20:16:36 -0700220 static const char ERROR_STR[] = "error ";
Victor Zverovich22f75d82014-09-03 08:03:05 -0700221 fmt::internal::IntTraits<int>::MainType ec_value = error_code;
vitaut1addec92015-03-21 20:16:36 -0700222 // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
223 std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
224 error_code_size += fmt::internal::count_digits(ec_value);
Victor Zverovich88e0db82014-09-05 08:04:26 -0700225 if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size)
Victor Zverovich22f75d82014-09-03 08:03:05 -0700226 out << message << SEP;
vitaut1addec92015-03-21 20:16:36 -0700227 out << ERROR_STR << error_code;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700228 assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE);
229}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700230
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700231void report_error(FormatFunc func,
Carter Lie2583ab2015-02-14 09:58:29 +0800232 int error_code, fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovichd1ded562014-09-29 08:48:16 -0700233 fmt::MemoryWriter full_message;
Victor Zverovich88e0db82014-09-05 08:04:26 -0700234 func(full_message, error_code, message);
235 // Use Writer::data instead of Writer::c_str to avoid potential memory
236 // allocation.
237 std::fwrite(full_message.data(), full_message.size(), 1, stderr);
238 std::fputc('\n', stderr);
Victor Zverovichb605b392013-09-09 22:21:40 -0700239}
Victor Zverovichd29e5052014-06-30 07:12:09 -0700240
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700241// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
242class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> {
243 public:
244 template <typename T>
245 bool visit_any_int(T value) { return value == 0; }
246};
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700247
248// Parses an unsigned integer advancing s to the end of the parsed input.
249// This function assumes that the first character of s is a digit.
250template <typename Char>
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700251int parse_nonnegative_int(const Char *&s) {
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700252 assert('0' <= *s && *s <= '9');
253 unsigned value = 0;
254 do {
255 unsigned new_value = value * 10 + (*s++ - '0');
256 // Check if value wrapped around.
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700257 if (new_value < value) {
258 value = UINT_MAX;
259 break;
260 }
261 value = new_value;
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700262 } while ('0' <= *s && *s <= '9');
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700263 if (value > INT_MAX)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700264 FMT_THROW(fmt::FormatError("number is too big"));
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700265 return value;
266}
Victor Zveroviche8251562014-07-08 16:20:33 -0700267
jamboree7487bde2015-06-10 09:32:59 +0800268template <typename Char>
269inline bool is_name_start(Char c) {
270 return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c;
271}
272
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700273inline void require_numeric_argument(const Arg &arg, char spec) {
274 if (arg.type > Arg::LAST_NUMERIC_TYPE) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700275 std::string message =
276 fmt::format("format specifier '{}' requires numeric argument", spec);
277 FMT_THROW(fmt::FormatError(message));
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700278 }
279}
280
Victor Zveroviche8251562014-07-08 16:20:33 -0700281template <typename Char>
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700282void check_sign(const Char *&s, const Arg &arg) {
283 char sign = static_cast<char>(*s);
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700284 require_numeric_argument(arg, sign);
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700285 if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700286 FMT_THROW(fmt::FormatError(fmt::format(
287 "format specifier '{}' requires signed argument", sign)));
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700288 }
289 ++s;
290}
291
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700292// Checks if an argument is a valid printf width specifier and sets
293// left alignment if it is negative.
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700294class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700295 private:
296 fmt::FormatSpec &spec_;
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700297
Victor Zverovich6f3c0952014-12-03 06:16:52 -0800298 FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
299
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700300 public:
301 explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700302
vitautd4ea2d72015-03-26 08:55:20 -0700303 void report_unhandled_arg() {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700304 FMT_THROW(fmt::FormatError("width is not integer"));
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700305 }
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700306
Victor Zverovich9d74f952014-07-16 07:27:54 -0700307 template <typename T>
308 unsigned visit_any_int(T value) {
309 typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType;
310 UnsignedType width = value;
311 if (fmt::internal::is_negative(value)) {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700312 spec_.align_ = fmt::ALIGN_LEFT;
313 width = 0 - width;
314 }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700315 if (width > INT_MAX)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700316 FMT_THROW(fmt::FormatError("number is too big"));
Victor Zverovich9d74f952014-07-16 07:27:54 -0700317 return static_cast<unsigned>(width);
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700318 }
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700319};
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700320
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700321class PrecisionHandler :
322 public fmt::internal::ArgVisitor<PrecisionHandler, int> {
323 public:
vitautd4ea2d72015-03-26 08:55:20 -0700324 void report_unhandled_arg() {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700325 FMT_THROW(fmt::FormatError("precision is not integer"));
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700326 }
327
328 template <typename T>
329 int visit_any_int(T value) {
Victor Zverovichadce0242014-08-17 07:53:55 -0700330 if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
Victor Zverovich8b76e972014-10-06 08:30:55 -0700331 FMT_THROW(fmt::FormatError("number is too big"));
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700332 return static_cast<int>(value);
333 }
334};
335
Victor Zverovich32344d92014-08-28 08:11:21 -0700336// Converts an integer argument to an integral type T for printf.
Victor Zverovicheeca2232014-07-30 07:37:16 -0700337template <typename T>
338class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
339 private:
340 fmt::internal::Arg &arg_;
Victor Zveroviche22d6572014-08-08 06:51:09 -0700341 wchar_t type_;
Victor Zverovicheeca2232014-07-30 07:37:16 -0700342
Victor Zverovich6f3c0952014-12-03 06:16:52 -0800343 FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
344
Victor Zverovicheeca2232014-07-30 07:37:16 -0700345 public:
Victor Zveroviche22d6572014-08-08 06:51:09 -0700346 ArgConverter(fmt::internal::Arg &arg, wchar_t type)
347 : arg_(arg), type_(type) {}
Victor Zverovicheeca2232014-07-30 07:37:16 -0700348
349 template <typename U>
350 void visit_any_int(U value) {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700351 bool is_signed = type_ == 'd' || type_ == 'i';
352 using fmt::internal::Arg;
353 if (sizeof(T) <= sizeof(int)) {
Victor Zverovich32344d92014-08-28 08:11:21 -0700354 // Extra casts are used to silence warnings.
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700355 if (is_signed) {
356 arg_.type = Arg::INT;
Victor Zverovichbb016332014-08-15 09:03:59 -0700357 arg_.int_value = static_cast<int>(static_cast<T>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700358 } else {
359 arg_.type = Arg::UINT;
Victor Zverovich186734c2014-08-18 07:03:12 -0700360 arg_.uint_value = static_cast<unsigned>(
361 static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700362 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700363 } else {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700364 if (is_signed) {
365 arg_.type = Arg::LONG_LONG;
Victor Zverovicha259c942014-08-01 07:15:27 -0700366 arg_.long_long_value =
367 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700368 } else {
369 arg_.type = Arg::ULONG_LONG;
370 arg_.ulong_long_value =
Victor Zverovicha259c942014-08-01 07:15:27 -0700371 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700372 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700373 }
374 }
375};
376
Victor Zverovich32344d92014-08-28 08:11:21 -0700377// Converts an integer argument to char for printf.
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700378class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
379 private:
380 fmt::internal::Arg &arg_;
381
Victor Zverovich6f3c0952014-12-03 06:16:52 -0800382 FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
383
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700384 public:
385 explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
386
387 template <typename T>
388 void visit_any_int(T value) {
389 arg_.type = Arg::CHAR;
390 arg_.int_value = static_cast<char>(value);
391 }
392};
393
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700394// This function template is used to prevent compile errors when handling
395// incompatible string arguments, e.g. handling a wide string in a narrow
396// string formatter.
397template <typename Char>
398Arg::StringValue<Char> ignore_incompatible_str(Arg::StringValue<wchar_t>);
399
400template <>
401inline Arg::StringValue<char> ignore_incompatible_str(
402 Arg::StringValue<wchar_t>) { return Arg::StringValue<char>(); }
403
404template <>
405inline Arg::StringValue<wchar_t> ignore_incompatible_str(
406 Arg::StringValue<wchar_t> s) { return s; }
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700407} // namespace
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700408
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800409FMT_FUNC void fmt::SystemError::init(
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800410 int err_code, StringRef format_str, ArgList args) {
411 error_code_ = err_code;
Victor Zverovichd1ded562014-09-29 08:48:16 -0700412 MemoryWriter w;
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800413 internal::format_system_error(w, err_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700414 std::runtime_error &base = *this;
415 base = std::runtime_error(w.str());
416}
417
Victor Zverovichb605b392013-09-09 22:21:40 -0700418template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700419int fmt::internal::CharTraits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700420 char *buffer, std::size_t size, const char *format,
421 unsigned width, int precision, T value) {
422 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700423 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700424 FMT_SNPRINTF(buffer, size, format, value) :
425 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700426 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700427 return precision < 0 ?
428 FMT_SNPRINTF(buffer, size, format, width, value) :
429 FMT_SNPRINTF(buffer, size, format, width, precision, value);
430}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700431
Victor Zverovichb605b392013-09-09 22:21:40 -0700432template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700433int fmt::internal::CharTraits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700434 wchar_t *buffer, std::size_t size, const wchar_t *format,
435 unsigned width, int precision, T value) {
436 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700437 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000438 FMT_SWPRINTF(buffer, size, format, value) :
439 FMT_SWPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700440 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700441 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000442 FMT_SWPRINTF(buffer, size, format, width, value) :
443 FMT_SWPRINTF(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700444}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800445
Victor Zverovich311251e2014-11-29 06:58:00 -0800446template <typename T>
447const char fmt::internal::BasicData<T>::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800448 "0001020304050607080910111213141516171819"
449 "2021222324252627282930313233343536373839"
450 "4041424344454647484950515253545556575859"
451 "6061626364656667686970717273747576777879"
452 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800453
Victor Zverovichf1d85162014-02-19 13:02:22 -0800454#define FMT_POWERS_OF_10(factor) \
455 factor * 10, \
456 factor * 100, \
457 factor * 1000, \
458 factor * 10000, \
459 factor * 100000, \
460 factor * 1000000, \
461 factor * 10000000, \
462 factor * 100000000, \
463 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800464
Victor Zverovich311251e2014-11-29 06:58:00 -0800465template <typename T>
466const uint32_t fmt::internal::BasicData<T>::POWERS_OF_10_32[] = {
467 0, FMT_POWERS_OF_10(1)
468};
469
470template <typename T>
471const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800472 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800473 FMT_POWERS_OF_10(1),
Victor Zverovichecd2b802014-12-17 06:42:26 -0800474 FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
Victor Zverovich406c6122014-08-19 08:47:38 -0700475 // Multiply several constants instead of using a single long long constant
Victor Zverovichf1d85162014-02-19 13:02:22 -0800476 // to avoid warnings about C++98 not supporting long long.
Victor Zverovichecd2b802014-12-17 06:42:26 -0800477 fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800478};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800479
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800480FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
Carter Li2d4631a2015-03-14 14:54:37 +0800481 (void)type;
Victor Zverovich877abaf2013-01-08 09:56:05 -0800482 if (std::isprint(static_cast<unsigned char>(code))) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700483 FMT_THROW(fmt::FormatError(
484 fmt::format("unknown format code '{}' for {}", code, type)));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800485 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700486 FMT_THROW(fmt::FormatError(
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700487 fmt::format("unknown format code '\\x{:02x}' for {}",
Victor Zverovich8b76e972014-10-06 08:30:55 -0700488 static_cast<unsigned>(code), type)));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800489}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700490
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700491#ifdef _WIN32
492
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800493FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700494 int length = MultiByteToWideChar(
495 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, 0, 0);
Victor Zverovichdff21372014-12-16 07:01:01 -0800496 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700497 if (length == 0)
Victor Zverovichdff21372014-12-16 07:01:01 -0800498 FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700499 buffer_.resize(length);
500 length = MultiByteToWideChar(
501 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, &buffer_[0], length);
502 if (length == 0)
Victor Zverovichdff21372014-12-16 07:01:01 -0800503 FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700504}
505
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800506FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700507 if (int error_code = convert(s)) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700508 FMT_THROW(WindowsError(error_code,
509 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700510 }
511}
512
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800513FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700514 int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, 0, 0, 0, 0);
515 if (length == 0)
516 return GetLastError();
517 buffer_.resize(length);
518 length = WideCharToMultiByte(
519 CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, 0, 0);
520 if (length == 0)
521 return GetLastError();
522 return 0;
523}
524
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800525FMT_FUNC void fmt::WindowsError::init(
Carter Li3f574c12015-02-17 10:11:42 +0800526 int err_code, StringRef format_str, ArgList args) {
527 error_code_ = err_code;
Victor Zverovich8c4db502014-09-29 09:17:02 -0700528 MemoryWriter w;
Carter Li3f574c12015-02-17 10:11:42 +0800529 internal::format_windows_error(w, err_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700530 std::runtime_error &base = *this;
531 base = std::runtime_error(w.str());
532}
533
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700534#endif
535
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800536FMT_FUNC void fmt::internal::format_system_error(
Victor Zverovich22f75d82014-09-03 08:03:05 -0700537 fmt::Writer &out, int error_code,
Carter Lie2583ab2015-02-14 09:58:29 +0800538 fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700539 FMT_TRY {
Victor Zverovichd1ded562014-09-29 08:48:16 -0700540 MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700541 buffer.resize(INLINE_BUFFER_SIZE);
Victor Zverovich22f75d82014-09-03 08:03:05 -0700542 for (;;) {
Victor Zverovichaca49372014-11-24 07:38:26 -0800543 char *system_message = &buffer[0];
Victor Zverovich22f75d82014-09-03 08:03:05 -0700544 int result = safe_strerror(error_code, system_message, buffer.size());
545 if (result == 0) {
546 out << message << ": " << system_message;
547 return;
548 }
549 if (result != ERANGE)
550 break; // Can't get error message, report error code instead.
551 buffer.resize(buffer.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700552 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700553 } FMT_CATCH(...) {}
Victor Zverovich22f75d82014-09-03 08:03:05 -0700554 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700555}
556
557#ifdef _WIN32
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800558FMT_FUNC void fmt::internal::format_windows_error(
Victor Zverovich22f75d82014-09-03 08:03:05 -0700559 fmt::Writer &out, int error_code,
Carter Lie2583ab2015-02-14 09:58:29 +0800560 fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovich53b4c312014-04-30 15:00:41 -0700561 class String {
562 private:
563 LPWSTR str_;
564
565 public:
566 String() : str_() {}
567 ~String() { LocalFree(str_); }
568 LPWSTR *ptr() { return &str_; }
569 LPCWSTR c_str() const { return str_; }
570 };
Victor Zverovich8b76e972014-10-06 08:30:55 -0700571 FMT_TRY {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700572 String system_message;
573 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
574 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
575 error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
576 reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
577 UTF16ToUTF8 utf8_message;
578 if (utf8_message.convert(system_message.c_str()) == ERROR_SUCCESS) {
579 out << message << ": " << utf8_message;
580 return;
581 }
Victor Zverovich53b4c312014-04-30 15:00:41 -0700582 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700583 } FMT_CATCH(...) {}
Victor Zverovich22f75d82014-09-03 08:03:05 -0700584 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700585}
586#endif
587
jamboree7487bde2015-06-10 09:32:59 +0800588template <typename Char>
vitauta98583d2015-06-10 08:49:22 -0700589void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
jamboree7487bde2015-06-10 09:32:59 +0800590 if (!map_.empty())
591 return;
vitauta98583d2015-06-10 08:49:22 -0700592 typedef internal::NamedArg<Char> NamedArg;
vitautfccff7b2015-06-11 07:19:00 -0700593 const NamedArg *named_arg = 0;
vitauta98583d2015-06-10 08:49:22 -0700594 bool use_values =
595 args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
jamboree7487bde2015-06-10 09:32:59 +0800596 if (use_values) {
597 for (unsigned i = 0;/*nothing*/; ++i) {
598 internal::Arg::Type arg_type = args.type(i);
599 switch (arg_type) {
600 case internal::Arg::NONE:
601 return;
602 case internal::Arg::NAMED_ARG:
vitauta98583d2015-06-10 08:49:22 -0700603 named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
jamboree7487bde2015-06-10 09:32:59 +0800604 map_.insert(Pair(named_arg->name, *named_arg));
605 break;
606 default:
607 /*nothing*/;
608 }
609 }
610 return;
611 }
vitauta98583d2015-06-10 08:49:22 -0700612 for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
jamboree7487bde2015-06-10 09:32:59 +0800613 internal::Arg::Type arg_type = args.type(i);
614 if (arg_type == internal::Arg::NAMED_ARG) {
vitauta98583d2015-06-10 08:49:22 -0700615 named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
jamboree7487bde2015-06-10 09:32:59 +0800616 map_.insert(Pair(named_arg->name, *named_arg));
617 }
618 }
vitauta98583d2015-06-10 08:49:22 -0700619 for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
jamboree7487bde2015-06-10 09:32:59 +0800620 switch (args.args_[i].type) {
621 case internal::Arg::NONE:
622 return;
623 case internal::Arg::NAMED_ARG:
vitauta98583d2015-06-10 08:49:22 -0700624 named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
jamboree7487bde2015-06-10 09:32:59 +0800625 map_.insert(Pair(named_arg->name, *named_arg));
626 break;
627 default:
628 /*nothing*/;
629 }
630 }
631}
632
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700633// An argument formatter.
634template <typename Char>
635class fmt::internal::ArgFormatter :
636 public fmt::internal::ArgVisitor<fmt::internal::ArgFormatter<Char>, void> {
637 private:
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700638 fmt::BasicFormatter<Char> &formatter_;
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700639 fmt::BasicWriter<Char> &writer_;
640 fmt::FormatSpec &spec_;
641 const Char *format_;
642
Victor Zverovich6f3c0952014-12-03 06:16:52 -0800643 FMT_DISALLOW_COPY_AND_ASSIGN(ArgFormatter);
644
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700645 public:
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700646 ArgFormatter(
647 fmt::BasicFormatter<Char> &f,fmt::FormatSpec &s, const Char *fmt)
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700648 : formatter_(f), writer_(f.writer()), spec_(s), format_(fmt) {}
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700649
Victor Zverovich9d74f952014-07-16 07:27:54 -0700650 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700651 void visit_any_int(T value) { writer_.write_int(value, spec_); }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700652
653 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700654 void visit_any_double(T value) { writer_.write_double(value, spec_); }
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700655
656 void visit_char(int value) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700657 if (spec_.type_ && spec_.type_ != 'c') {
Victor Zverovichd699c2a2014-07-25 08:24:27 -0700658 spec_.flags_ |= CHAR_FLAG;
659 writer_.write_int(value, spec_);
660 return;
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700661 }
662 if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700663 FMT_THROW(FormatError("invalid format specifier for char"));
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700664 typedef typename fmt::BasicWriter<Char>::CharPtr CharPtr;
Victor Zverovich43aebf52015-01-08 07:56:08 -0800665 Char fill = static_cast<Char>(spec_.fill());
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700666 CharPtr out = CharPtr();
667 if (spec_.width_ > 1) {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700668 out = writer_.grow_buffer(spec_.width_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700669 if (spec_.align_ == fmt::ALIGN_RIGHT) {
670 std::fill_n(out, spec_.width_ - 1, fill);
671 out += spec_.width_ - 1;
672 } else if (spec_.align_ == fmt::ALIGN_CENTER) {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700673 out = writer_.fill_padding(out, spec_.width_, 1, fill);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700674 } else {
675 std::fill_n(out + 1, spec_.width_ - 1, fill);
676 }
677 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700678 out = writer_.grow_buffer(1);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700679 }
680 *out = static_cast<Char>(value);
681 }
682
683 void visit_string(Arg::StringValue<char> value) {
684 writer_.write_str(value, spec_);
685 }
686 void visit_wstring(Arg::StringValue<wchar_t> value) {
687 writer_.write_str(ignore_incompatible_str<Char>(value), spec_);
688 }
689
690 void visit_pointer(const void *value) {
691 if (spec_.type_ && spec_.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700692 fmt::internal::report_unknown_type(spec_.type_, "pointer");
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700693 spec_.flags_ = fmt::HASH_FLAG;
694 spec_.type_ = 'x';
Victor Zverovichc1db2932014-07-24 08:53:27 -0700695 writer_.write_int(reinterpret_cast<uintptr_t>(value), spec_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700696 }
697
698 void visit_custom(Arg::CustomValue c) {
Victor Zverovich271fa8c2014-08-29 07:23:54 -0700699 c.format(&formatter_, c.value, &format_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700700 }
701};
702
Victor Zverovichd1ded562014-09-29 08:48:16 -0700703template <typename Char>
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800704void fmt::internal::FixedBuffer<Char>::grow(std::size_t) {
705 FMT_THROW(std::runtime_error("buffer overflow"));
706}
707
708template <typename Char>
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700709template <typename StrChar>
Victor Zverovichd1ded562014-09-29 08:48:16 -0700710void fmt::BasicWriter<Char>::write_str(
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800711 const Arg::StringValue<StrChar> &s, const FormatSpec &spec) {
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700712 // Check if StrChar is convertible to Char.
713 internal::CharTraits<Char>::convert(StrChar());
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700714 if (spec.type_ && spec.type_ != 's')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700715 internal::report_unknown_type(spec.type_, "string");
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800716 const StrChar *str_value = s.value;
717 std::size_t str_size = s.size;
718 if (str_size == 0) {
719 if (!str_value)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700720 FMT_THROW(FormatError("string pointer is null"));
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800721 if (*str_value)
722 str_size = std::char_traits<StrChar>::length(str_value);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700723 }
Victor Zverovich59254412015-02-06 07:27:19 -0800724 std::size_t precision = spec.precision_;
725 if (spec.precision_ >= 0 && precision < str_size)
Victor Zverovich43aebf52015-01-08 07:56:08 -0800726 str_size = spec.precision_;
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800727 write_str(str_value, str_size, spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700728}
729
730template <typename Char>
jamboree7487bde2015-06-10 09:32:59 +0800731inline Arg fmt::BasicFormatter<Char>::get_arg(
vitautfccff7b2015-06-11 07:19:00 -0700732 BasicStringRef<Char> arg_name, const char *&error) {
jamboree7487bde2015-06-10 09:32:59 +0800733 if (check_no_auto_index(error)) {
vitautfccff7b2015-06-11 07:19:00 -0700734 map_.init(args());
735 const Arg *arg = map_.find(arg_name);
jamboree7487bde2015-06-10 09:32:59 +0800736 if (arg)
737 return *arg;
738 error = "argument not found";
739 }
740 return Arg();
741}
742
743template <typename Char>
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700744inline Arg fmt::BasicFormatter<Char>::parse_arg_index(const Char *&s) {
Victor Zverovich9646e382014-08-27 09:13:42 -0700745 const char *error = 0;
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700746 Arg arg = *s < '0' || *s > '9' ?
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700747 next_arg(error) : get_arg(parse_nonnegative_int(s), error);
Victor Zverovich8b76e972014-10-06 08:30:55 -0700748 if (error) {
749 FMT_THROW(FormatError(
750 *s != '}' && *s != ':' ? "invalid format string" : error));
751 }
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700752 return arg;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700753}
754
jamboree7487bde2015-06-10 09:32:59 +0800755template <typename Char>
756inline Arg fmt::BasicFormatter<Char>::parse_arg_name(const Char *&s) {
757 assert(is_name_start(*s));
758 const Char *start = s;
759 Char c;
760 do {
761 c = *++s;
jamboree3c99ed42015-06-11 12:03:22 +0800762 } while (is_name_start(c) || ('0' <= c && c <= '9'));
jamboree7487bde2015-06-10 09:32:59 +0800763 const char *error = 0;
764 Arg arg = get_arg(fmt::BasicStringRef<Char>(start, s - start), error);
765 if (error)
766 FMT_THROW(fmt::FormatError(error));
767 return arg;
768}
769
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800770FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
Victor Zverovich605d2602014-08-29 07:45:55 -0700771 unsigned arg_index, const char *&error) {
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700772 Arg arg = args_[arg_index];
jamboree7487bde2015-06-10 09:32:59 +0800773 switch (arg.type) {
774 case Arg::NONE:
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700775 error = "argument index out of range";
jamboree7487bde2015-06-10 09:32:59 +0800776 break;
777 case Arg::NAMED_ARG:
778 arg = *static_cast<const internal::Arg*>(arg.pointer);
779 default:
780 /*nothing*/;
781 }
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700782 return arg;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700783}
784
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700785inline Arg fmt::internal::FormatterBase::next_arg(const char *&error) {
Victor Zverovich605d2602014-08-29 07:45:55 -0700786 if (next_arg_index_ >= 0)
787 return do_get_arg(next_arg_index_++, error);
788 error = "cannot switch from manual to automatic argument indexing";
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700789 return Arg();
Victor Zverovich605d2602014-08-29 07:45:55 -0700790}
791
vitautfccff7b2015-06-11 07:19:00 -0700792inline bool fmt::internal::FormatterBase::check_no_auto_index(
793 const char *&error) {
jamboree7487bde2015-06-10 09:32:59 +0800794 if (next_arg_index_ > 0) {
795 error = "cannot switch from automatic to manual argument indexing";
796 return false;
797 }
vitautfccff7b2015-06-11 07:19:00 -0700798 next_arg_index_ = -1;
jamboree7487bde2015-06-10 09:32:59 +0800799 return true;
800}
801
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700802inline Arg fmt::internal::FormatterBase::get_arg(
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700803 unsigned arg_index, const char *&error) {
vitautfccff7b2015-06-11 07:19:00 -0700804 return check_no_auto_index(error) ? do_get_arg(arg_index, error) : Arg();
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700805}
806
Victor Zverovich7cae7632013-09-06 20:23:42 -0700807template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700808void fmt::internal::PrintfFormatter<Char>::parse_flags(
Victor Zverovichcb743c02014-06-19 07:40:35 -0700809 FormatSpec &spec, const Char *&s) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700810 for (;;) {
Victor Zverovich1b801482014-06-07 08:57:55 -0700811 switch (*s++) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700812 case '-':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700813 spec.align_ = ALIGN_LEFT;
814 break;
815 case '+':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700816 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
817 break;
818 case '0':
819 spec.fill_ = '0';
Victor Zverovich1b801482014-06-07 08:57:55 -0700820 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700821 case ' ':
Victor Zverovich1b801482014-06-07 08:57:55 -0700822 spec.flags_ |= SIGN_FLAG;
823 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700824 case '#':
Victor Zverovichcb743c02014-06-19 07:40:35 -0700825 spec.flags_ |= HASH_FLAG;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700826 break;
827 default:
Victor Zverovich1b801482014-06-07 08:57:55 -0700828 --s;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700829 return;
830 }
831 }
832}
833
Victor Zverovichcb743c02014-06-19 07:40:35 -0700834template <typename Char>
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700835Arg fmt::internal::PrintfFormatter<Char>::get_arg(
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700836 const Char *s, unsigned arg_index) {
Carter Li2d4631a2015-03-14 14:54:37 +0800837 (void)s;
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700838 const char *error = 0;
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700839 Arg arg = arg_index == UINT_MAX ?
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700840 next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
841 if (error)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700842 FMT_THROW(FormatError(!*s ? "invalid format string" : error));
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700843 return arg;
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700844}
845
846template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700847unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700848 const Char *&s, FormatSpec &spec) {
Victor Zverovichcb743c02014-06-19 07:40:35 -0700849 unsigned arg_index = UINT_MAX;
850 Char c = *s;
851 if (c >= '0' && c <= '9') {
852 // Parse an argument index (if followed by '$') or a width possibly
Victor Zverovich879838a2014-06-20 07:34:02 -0700853 // preceded with '0' flag(s).
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700854 unsigned value = parse_nonnegative_int(s);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700855 if (*s == '$') { // value is an argument index
856 ++s;
857 arg_index = value;
858 } else {
859 if (c == '0')
860 spec.fill_ = '0';
861 if (value != 0) {
862 // Nonzero value means that we parsed width and don't need to
863 // parse it or flags again, so return now.
864 spec.width_ = value;
865 return arg_index;
866 }
867 }
868 }
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700869 parse_flags(spec, s);
Victor Zverovich4099a122014-06-23 08:10:50 -0700870 // Parse width.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700871 if (*s >= '0' && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700872 spec.width_ = parse_nonnegative_int(s);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700873 } else if (*s == '*') {
874 ++s;
Victor Zverovich56fc5252014-08-28 07:48:55 -0700875 spec.width_ = WidthHandler(spec).visit(get_arg(s));
Victor Zverovichcb743c02014-06-19 07:40:35 -0700876 }
877 return arg_index;
878}
879
Victor Zverovich1f19b982014-06-16 07:49:30 -0700880template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700881void fmt::internal::PrintfFormatter<Char>::format(
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800882 BasicWriter<Char> &writer, BasicStringRef<Char> format_str,
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700883 const ArgList &args) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800884 const Char *start = format_str.c_str();
Victor Zverovich605d2602014-08-29 07:45:55 -0700885 set_args(args);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700886 const Char *s = start;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700887 while (*s) {
Victor Zverovich0fc73162013-09-07 12:52:52 -0700888 Char c = *s++;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700889 if (c != '%') continue;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700890 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -0700891 write(writer, start, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700892 start = ++s;
893 continue;
894 }
Victor Zverovichc1db2932014-07-24 08:53:27 -0700895 write(writer, start, s - 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700896
Victor Zverovichcb743c02014-06-19 07:40:35 -0700897 FormatSpec spec;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700898 spec.align_ = ALIGN_RIGHT;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700899
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700900 // Parse argument index, flags and width.
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700901 unsigned arg_index = parse_header(s, spec);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700902
903 // Parse precision.
904 if (*s == '.') {
905 ++s;
906 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700907 spec.precision_ = parse_nonnegative_int(s);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700908 } else if (*s == '*') {
909 ++s;
Victor Zverovich56fc5252014-08-28 07:48:55 -0700910 spec.precision_ = PrecisionHandler().visit(get_arg(s));
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700911 }
912 }
913
Victor Zverovich56fc5252014-08-28 07:48:55 -0700914 Arg arg = get_arg(s, arg_index);
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700915 if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
Victor Zverovichcb743c02014-06-19 07:40:35 -0700916 spec.flags_ &= ~HASH_FLAG;
917 if (spec.fill_ == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700918 if (arg.type <= Arg::LAST_NUMERIC_TYPE)
Victor Zverovichcb743c02014-06-19 07:40:35 -0700919 spec.align_ = ALIGN_NUMERIC;
920 else
921 spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700922 }
923
Victor Zverovichf4156b52014-07-30 08:39:07 -0700924 // Parse length and convert the argument to the required type.
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700925 switch (*s++) {
926 case 'h':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700927 if (*s == 'h')
928 ArgConverter<signed char>(arg, *++s).visit(arg);
Victor Zverovich39b09302014-07-30 08:08:08 -0700929 else
Victor Zverovichf4156b52014-07-30 08:39:07 -0700930 ArgConverter<short>(arg, *s).visit(arg);
Victor Zverovicheeca2232014-07-30 07:37:16 -0700931 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700932 case 'l':
Victor Zverovichd3a70392014-08-12 08:36:19 -0700933 if (*s == 'l')
Victor Zveroviche488a282014-08-13 06:53:43 -0700934 ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
Victor Zverovichd3a70392014-08-12 08:36:19 -0700935 else
936 ArgConverter<long>(arg, *s).visit(arg);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700937 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700938 case 'j':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700939 ArgConverter<intmax_t>(arg, *s).visit(arg);
940 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700941 case 'z':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700942 ArgConverter<size_t>(arg, *s).visit(arg);
943 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700944 case 't':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700945 ArgConverter<ptrdiff_t>(arg, *s).visit(arg);
946 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700947 case 'L':
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700948 // printf produces garbage when 'L' is omitted for long double, no
949 // need to do the same.
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700950 break;
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700951 default:
952 --s;
Victor Zverovichbe00d8b2014-08-19 08:49:10 -0700953 ArgConverter<int>(arg, *s).visit(arg);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700954 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700955
956 // Parse type.
957 if (!*s)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700958 FMT_THROW(FormatError("invalid format string"));
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700959 spec.type_ = static_cast<char>(*s++);
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700960 if (arg.type <= Arg::LAST_INTEGER_TYPE) {
961 // Normalize type.
962 switch (spec.type_) {
963 case 'i': case 'u':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700964 spec.type_ = 'd';
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700965 break;
966 case 'c':
967 // TODO: handle wchar_t
968 CharConverter(arg).visit(arg);
969 break;
970 }
Victor Zverovichf4156b52014-07-30 08:39:07 -0700971 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700972
973 start = s;
974
975 // Format argument.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700976 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700977 case Arg::INT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700978 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700979 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700980 case Arg::UINT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700981 writer.write_int(arg.uint_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700982 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700983 case Arg::LONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700984 writer.write_int(arg.long_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700985 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700986 case Arg::ULONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700987 writer.write_int(arg.ulong_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700988 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700989 case Arg::CHAR: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700990 if (spec.type_ && spec.type_ != 'c')
Victor Zverovichc1db2932014-07-24 08:53:27 -0700991 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700992 typedef typename BasicWriter<Char>::CharPtr CharPtr;
993 CharPtr out = CharPtr();
994 if (spec.width_ > 1) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700995 Char fill = ' ';
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700996 out = writer.grow_buffer(spec.width_);
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700997 if (spec.align_ != ALIGN_LEFT) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700998 std::fill_n(out, spec.width_ - 1, fill);
999 out += spec.width_ - 1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001000 } else {
1001 std::fill_n(out + 1, spec.width_ - 1, fill);
1002 }
1003 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001004 out = writer.grow_buffer(1);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001005 }
Victor Zverovichcb743c02014-06-19 07:40:35 -07001006 *out = static_cast<Char>(arg.int_value);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001007 break;
1008 }
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001009 case Arg::DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001010 writer.write_double(arg.double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001011 break;
1012 case Arg::LONG_DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001013 writer.write_double(arg.long_double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001014 break;
Victor Zverovich75a2ea02014-09-25 07:10:44 -07001015 case Arg::CSTRING:
1016 arg.string.size = 0;
1017 writer.write_str(arg.string, spec);
1018 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001019 case Arg::STRING:
Victor Zverovich53201032014-06-30 14:26:29 -07001020 writer.write_str(arg.string, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001021 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001022 case Arg::WSTRING:
Victor Zverovich512e2ce2014-07-14 08:47:03 -07001023 writer.write_str(ignore_incompatible_str<Char>(arg.wstring), spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001024 break;
1025 case Arg::POINTER:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001026 if (spec.type_ && spec.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001027 internal::report_unknown_type(spec.type_, "pointer");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001028 spec.flags_= HASH_FLAG;
1029 spec.type_ = 'x';
Victor Zverovichab6e7592014-09-23 08:21:58 -07001030 writer.write_int(reinterpret_cast<uintptr_t>(arg.pointer), spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001031 break;
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001032 case Arg::CUSTOM: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001033 if (spec.type_)
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001034 internal::report_unknown_type(spec.type_, "object");
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -08001035 const void *str_format = "s";
1036 arg.custom.format(&writer, arg.custom.value, &str_format);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001037 break;
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001038 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001039 default:
1040 assert(false);
1041 break;
1042 }
1043 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001044 write(writer, start, s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001045}
1046
1047template <typename Char>
Victor Zverovichb9a06ba2014-07-08 16:38:50 -07001048const Char *fmt::BasicFormatter<Char>::format(
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001049 const Char *&format_str, const Arg &arg) {
Victor Zveroviche8251562014-07-08 16:20:33 -07001050 const Char *s = format_str;
Victor Zveroviche8251562014-07-08 16:20:33 -07001051 FormatSpec spec;
1052 if (*s == ':') {
1053 if (arg.type == Arg::CUSTOM) {
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001054 arg.custom.format(this, arg.custom.value, &s);
1055 return s;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001056 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001057 ++s;
1058 // Parse fill and alignment.
1059 if (Char c = *s) {
1060 const Char *p = s + 1;
1061 spec.align_ = ALIGN_DEFAULT;
1062 do {
1063 switch (*p) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001064 case '<':
1065 spec.align_ = ALIGN_LEFT;
1066 break;
1067 case '>':
1068 spec.align_ = ALIGN_RIGHT;
1069 break;
1070 case '=':
1071 spec.align_ = ALIGN_NUMERIC;
1072 break;
1073 case '^':
1074 spec.align_ = ALIGN_CENTER;
1075 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001076 }
1077 if (spec.align_ != ALIGN_DEFAULT) {
1078 if (p != s) {
1079 if (c == '}') break;
1080 if (c == '{')
Victor Zverovich8b76e972014-10-06 08:30:55 -07001081 FMT_THROW(FormatError("invalid fill character '{'"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001082 s += 2;
1083 spec.fill_ = c;
1084 } else ++s;
Victor Zverovich5debb2a2014-08-29 08:16:10 -07001085 if (spec.align_ == ALIGN_NUMERIC)
1086 require_numeric_argument(arg, '=');
Victor Zveroviche8251562014-07-08 16:20:33 -07001087 break;
1088 }
1089 } while (--p >= s);
1090 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001091
Victor Zveroviche8251562014-07-08 16:20:33 -07001092 // Parse sign.
1093 switch (*s) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001094 case '+':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001095 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001096 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
1097 break;
1098 case '-':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001099 check_sign(s, arg);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001100 spec.flags_ |= MINUS_FLAG;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001101 break;
1102 case ' ':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001103 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001104 spec.flags_ |= SIGN_FLAG;
1105 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001106 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001107
Victor Zveroviche8251562014-07-08 16:20:33 -07001108 if (*s == '#') {
Victor Zverovich5debb2a2014-08-29 08:16:10 -07001109 require_numeric_argument(arg, '#');
Victor Zveroviche8251562014-07-08 16:20:33 -07001110 spec.flags_ |= HASH_FLAG;
1111 ++s;
1112 }
1113
jamboree54a6cb32015-06-04 13:59:37 +08001114 // Parse zero flag.
1115 if (*s == '0') {
vitaut8949a2e2015-06-08 06:53:18 -07001116 require_numeric_argument(arg, '0');
1117 spec.align_ = ALIGN_NUMERIC;
1118 spec.fill_ = '0';
1119 ++s;
jamboree54a6cb32015-06-04 13:59:37 +08001120 }
1121
1122 // Parse width.
1123 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -07001124 spec.width_ = parse_nonnegative_int(s);
jamboree54a6cb32015-06-04 13:59:37 +08001125 } else if (*s == '{') {
vitaut8949a2e2015-06-08 06:53:18 -07001126 ++s;
vitautfccff7b2015-06-11 07:19:00 -07001127 Arg width_arg = is_name_start(*s) ?
1128 parse_arg_name(s) : parse_arg_index(s);
vitaut8949a2e2015-06-08 06:53:18 -07001129 if (*s++ != '}')
1130 FMT_THROW(FormatError("invalid format string"));
1131 ULongLong value = 0;
1132 switch (width_arg.type) {
1133 case Arg::INT:
1134 if (width_arg.int_value < 0)
1135 FMT_THROW(FormatError("negative width"));
1136 value = width_arg.int_value;
1137 break;
1138 case Arg::UINT:
1139 value = width_arg.uint_value;
1140 break;
1141 case Arg::LONG_LONG:
1142 if (width_arg.long_long_value < 0)
1143 FMT_THROW(FormatError("negative width"));
1144 value = width_arg.long_long_value;
1145 break;
1146 case Arg::ULONG_LONG:
1147 value = width_arg.ulong_long_value;
1148 break;
1149 default:
1150 FMT_THROW(FormatError("width is not integer"));
1151 }
1152 if (value > INT_MAX)
1153 FMT_THROW(FormatError("number is too big"));
1154 spec.width_ = static_cast<int>(value);
Victor Zveroviche8251562014-07-08 16:20:33 -07001155 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001156
Victor Zveroviche8251562014-07-08 16:20:33 -07001157 // Parse precision.
1158 if (*s == '.') {
1159 ++s;
1160 spec.precision_ = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001161 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -07001162 spec.precision_ = parse_nonnegative_int(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001163 } else if (*s == '{') {
Victor Zverovich7cae7632013-09-06 20:23:42 -07001164 ++s;
vitautfccff7b2015-06-11 07:19:00 -07001165 Arg precision_arg =
1166 is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s);
Victor Zverovich42de4f12014-08-27 08:24:31 -07001167 if (*s++ != '}')
Victor Zverovich8b76e972014-10-06 08:30:55 -07001168 FMT_THROW(FormatError("invalid format string"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001169 ULongLong value = 0;
1170 switch (precision_arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001171 case Arg::INT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001172 if (precision_arg.int_value < 0)
Victor Zverovich8b76e972014-10-06 08:30:55 -07001173 FMT_THROW(FormatError("negative precision"));
Victor Zverovich7cae7632013-09-06 20:23:42 -07001174 value = precision_arg.int_value;
1175 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001176 case Arg::UINT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001177 value = precision_arg.uint_value;
1178 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001179 case Arg::LONG_LONG:
Victor Zverovich56f12b72013-11-22 07:45:43 -08001180 if (precision_arg.long_long_value < 0)
Victor Zverovich8b76e972014-10-06 08:30:55 -07001181 FMT_THROW(FormatError("negative precision"));
Victor Zverovich56f12b72013-11-22 07:45:43 -08001182 value = precision_arg.long_long_value;
1183 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001184 case Arg::ULONG_LONG:
Gregory Czajkowskia65542b2013-11-18 22:58:39 -08001185 value = precision_arg.ulong_long_value;
Victor Zverovicha4e72b42013-11-21 09:11:58 -08001186 break;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001187 default:
Victor Zverovich8b76e972014-10-06 08:30:55 -07001188 FMT_THROW(FormatError("precision is not integer"));
Victor Zverovich7cae7632013-09-06 20:23:42 -07001189 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001190 if (value > INT_MAX)
Victor Zverovich8b76e972014-10-06 08:30:55 -07001191 FMT_THROW(FormatError("number is too big"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001192 spec.precision_ = static_cast<int>(value);
Victor Zveroviche8251562014-07-08 16:20:33 -07001193 } else {
Victor Zverovich8b76e972014-10-06 08:30:55 -07001194 FMT_THROW(FormatError("missing precision specifier"));
Victor Zverovich7cae7632013-09-06 20:23:42 -07001195 }
vitautfd5c2e92015-06-11 08:58:31 -07001196 if (arg.type <= Arg::LAST_INTEGER_TYPE || arg.type == Arg::POINTER) {
Victor Zverovich8b76e972014-10-06 08:30:55 -07001197 FMT_THROW(FormatError(
Victor Zverovich43aebf52015-01-08 07:56:08 -08001198 fmt::format("precision not allowed in {} format specifier",
1199 arg.type == Arg::POINTER ? "pointer" : "integer")));
Victor Zveroviche8251562014-07-08 16:20:33 -07001200 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001201 }
1202
Victor Zveroviche8251562014-07-08 16:20:33 -07001203 // Parse type.
1204 if (*s != '}' && *s)
1205 spec.type_ = static_cast<char>(*s++);
1206 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001207
Victor Zveroviche8251562014-07-08 16:20:33 -07001208 if (*s++ != '}')
Victor Zverovich8b76e972014-10-06 08:30:55 -07001209 FMT_THROW(FormatError("missing '}' in format string"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001210 start_ = s;
1211
1212 // Format argument.
Victor Zverovich4edc88f2014-07-16 08:38:15 -07001213 internal::ArgFormatter<Char>(*this, spec, s - 1).visit(arg);
Victor Zveroviche8251562014-07-08 16:20:33 -07001214 return s;
1215}
1216
1217template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001218void fmt::BasicFormatter<Char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001219 BasicStringRef<Char> format_str, const ArgList &args) {
1220 const Char *s = start_ = format_str.c_str();
Victor Zverovich605d2602014-08-29 07:45:55 -07001221 set_args(args);
Victor Zveroviche8251562014-07-08 16:20:33 -07001222 while (*s) {
1223 Char c = *s++;
1224 if (c != '{' && c != '}') continue;
1225 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -07001226 write(writer_, start_, s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001227 start_ = ++s;
1228 continue;
1229 }
1230 if (c == '}')
Victor Zverovich8b76e972014-10-06 08:30:55 -07001231 FMT_THROW(FormatError("unmatched '}' in format string"));
Victor Zverovichc1db2932014-07-24 08:53:27 -07001232 write(writer_, start_, s - 1);
jamboree7487bde2015-06-10 09:32:59 +08001233 Arg arg = is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001234 s = format(s, arg);
1235 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001236 write(writer_, start_, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001237}
1238
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001239FMT_FUNC void fmt::report_system_error(
Carter Lie2583ab2015-02-14 09:58:29 +08001240 int error_code, fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001241 report_error(internal::format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001242}
1243
Victor Zverovich400812a2014-04-30 12:38:17 -07001244#ifdef _WIN32
Victor Zverovichb49a1b42014-12-09 06:32:07 -08001245FMT_FUNC void fmt::report_windows_error(
Carter Lie2583ab2015-02-14 09:58:29 +08001246 int error_code, fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001247 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001248}
Victor Zverovich400812a2014-04-30 12:38:17 -07001249#endif
Victor Zverovichf7939862014-04-30 10:18:11 -07001250
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001251FMT_FUNC void fmt::print(std::FILE *f, StringRef format_str, ArgList args) {
Victor Zverovichd1ded562014-09-29 08:48:16 -07001252 MemoryWriter w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001253 w.write(format_str, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001254 std::fwrite(w.data(), 1, w.size(), f);
1255}
1256
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001257FMT_FUNC void fmt::print(StringRef format_str, ArgList args) {
Victor Zverovich163178e2014-09-25 07:08:25 -07001258 print(stdout, format_str, args);
1259}
1260
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001261FMT_FUNC void fmt::print(std::ostream &os, StringRef format_str, ArgList args) {
Victor Zverovichd1ded562014-09-29 08:48:16 -07001262 MemoryWriter w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001263 w.write(format_str, args);
Victor Zveroviche3a44c12014-07-09 06:56:36 -07001264 os.write(w.data(), w.size());
1265}
1266
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001267FMT_FUNC void fmt::print_colored(Color c, StringRef format, ArgList args) {
Victor Zverovich2dc108b2014-07-01 09:10:43 -07001268 char escape[] = "\x1b[30m";
1269 escape[3] = '0' + static_cast<char>(c);
1270 std::fputs(escape, stdout);
1271 print(format, args);
1272 std::fputs(RESET_COLOR, stdout);
1273}
1274
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001275FMT_FUNC int fmt::fprintf(std::FILE *f, StringRef format, ArgList args) {
Victor Zverovichd1ded562014-09-29 08:48:16 -07001276 MemoryWriter w;
Victor Zverovich21111cc2014-06-29 19:52:26 -07001277 printf(w, format, args);
Victor Zverovich615c1ee2014-11-14 09:40:01 -08001278 std::size_t size = w.size();
1279 return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001280}
1281
Victor Zverovichc09c42f2015-03-01 09:43:33 -08001282#ifndef FMT_HEADER_ONLY
1283
vitaut9ca1ce22015-05-23 08:04:06 -07001284template struct fmt::internal::BasicData<void>;
vitaut804a74c2015-05-14 12:58:42 -07001285
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001286// Explicit instantiations for char.
1287
Victor Zverovich7c0d5752015-03-01 18:19:56 -08001288template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
1289
Victor Zverovichf43caef2014-09-25 07:21:48 -07001290template const char *fmt::BasicFormatter<char>::format(
1291 const char *&format_str, const fmt::internal::Arg &arg);
1292
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001293template void fmt::BasicFormatter<char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001294 BasicStringRef<char> format, const ArgList &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001295
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001296template void fmt::internal::PrintfFormatter<char>::format(
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001297 BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001298
Victor Zverovich14f25772014-09-19 08:45:05 -07001299template int fmt::internal::CharTraits<char>::format_float(
1300 char *buffer, std::size_t size, const char *format,
1301 unsigned width, int precision, double value);
1302
1303template int fmt::internal::CharTraits<char>::format_float(
1304 char *buffer, std::size_t size, const char *format,
1305 unsigned width, int precision, long double value);
1306
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001307// Explicit instantiations for wchar_t.
1308
Victor Zverovich7c0d5752015-03-01 18:19:56 -08001309template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
1310
Victor Zverovichf43caef2014-09-25 07:21:48 -07001311template const wchar_t *fmt::BasicFormatter<wchar_t>::format(
1312 const wchar_t *&format_str, const fmt::internal::Arg &arg);
1313
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001314template void fmt::BasicFormatter<wchar_t>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001315 BasicStringRef<wchar_t> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001316
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001317template void fmt::internal::PrintfFormatter<wchar_t>::format(
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001318 BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001319 const ArgList &args);
jdale88a9862fd2014-03-11 18:56:24 +00001320
Victor Zverovich14f25772014-09-19 08:45:05 -07001321template int fmt::internal::CharTraits<wchar_t>::format_float(
1322 wchar_t *buffer, std::size_t size, const wchar_t *format,
1323 unsigned width, int precision, double value);
1324
1325template int fmt::internal::CharTraits<wchar_t>::format_float(
1326 wchar_t *buffer, std::size_t size, const wchar_t *format,
1327 unsigned width, int precision, long double value);
1328
Victor Zverovichc09c42f2015-03-01 09:43:33 -08001329#endif // FMT_HEADER_ONLY
1330
jdale88a9862fd2014-03-11 18:56:24 +00001331#if _MSC_VER
1332# pragma warning(pop)
1333#endif