blob: d12424d0098004a23471a63477c6fb0aac843ad4 [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
vitaut8725d072015-06-12 07:56:58 -0700105namespace fmt {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700106namespace {
107
108#ifndef _MSC_VER
Victor Zverovichb9a568b2014-09-19 07:51:42 -0700109# define FMT_SNPRINTF snprintf
Victor Zverovicha684d0c2013-12-27 08:00:10 -0800110#else // _MSC_VER
Victor Zverovich406c6122014-08-19 08:47:38 -0700111inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -0800112 va_list args;
113 va_start(args, format);
114 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
115 va_end(args);
116 return result;
117}
Victor Zverovichb9a568b2014-09-19 07:51:42 -0700118# define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700119#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -0800120
cstamford55836ca2015-03-10 07:04:31 +0000121#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
122# define FMT_SWPRINTF snwprintf
123#else
124# define FMT_SWPRINTF swprintf
125#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
126
Victor Zverovichadce0242014-08-17 07:53:55 -0700127// Checks if a value fits in int - used to avoid warnings about comparing
128// signed and unsigned integers.
129template <bool IsSigned>
130struct IntChecker {
131 template <typename T>
132 static bool fits_in_int(T value) {
133 unsigned max = INT_MAX;
134 return value <= max;
135 }
136};
137
138template <>
139struct IntChecker<true> {
140 template <typename T>
141 static bool fits_in_int(T value) {
142 return value >= INT_MIN && value <= INT_MAX;
143 }
144};
145
Victor Zverovich7004d1e2015-02-08 19:54:39 -0800146const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700147
Victor Zverovich22f75d82014-09-03 08:03:05 -0700148typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
149
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700150// Portable thread-safe version of strerror.
151// Sets buffer to point to a string describing the error code.
152// This can be either a pointer to a string stored in buffer,
153// or a pointer to some static immutable string.
154// Returns one of the following values:
155// 0 - success
156// ERANGE - buffer is not large enough to store the error message
157// other - failure
158// Buffer should be at least of size 1.
159int safe_strerror(
Carter Lie2583ab2015-02-14 09:58:29 +0800160 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700161 assert(buffer != 0 && buffer_size != 0);
vitaut341b98c2015-03-14 13:39:33 -0700162
vitaut341b98c2015-03-14 13:39:33 -0700163 class StrError {
164 private:
165 int error_code_;
166 char *&buffer_;
167 std::size_t buffer_size_;
168
vitautda052ae2015-03-21 07:53:39 -0700169 // A noop assignment operator to avoid bogus warnings.
170 void operator=(const StrError &) {}
171
vitaut341b98c2015-03-14 13:39:33 -0700172 // Handle the result of XSI-compliant version of strerror_r.
173 int handle(int result) {
vitaute1776ac2015-03-14 14:05:02 -0700174 // glibc versions before 2.13 return result in errno.
175 return result == -1 ? errno : result;
vitaut341b98c2015-03-14 13:39:33 -0700176 }
177
178 // Handle the result of GNU-specific version of strerror_r.
179 int handle(char *message) {
180 // If the buffer is full then the message is probably truncated.
181 if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
182 return ERANGE;
183 buffer_ = message;
184 return 0;
185 }
186
187 // Handle the case when strerror_r is not available.
vitaut4825fb42015-03-16 08:43:33 -0700188 int handle(fmt::internal::None<>) {
vitaut341b98c2015-03-14 13:39:33 -0700189 return fallback(strerror_s(buffer_, buffer_size_, error_code_));
190 }
191
192 // Fallback to strerror_s when strerror_r is not available.
193 int fallback(int result) {
194 // If the buffer is full then the message is probably truncated.
195 return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
196 ERANGE : result;
197 }
198
199 // Fallback to strerror if strerror_r and strerror_s are not available.
vitaut4825fb42015-03-16 08:43:33 -0700200 int fallback(fmt::internal::None<>) {
vitaut341b98c2015-03-14 13:39:33 -0700201 errno = 0;
202 buffer_ = strerror(error_code_);
203 return errno;
204 }
205
206 public:
207 StrError(int error_code, char *&buffer, std::size_t buffer_size)
208 : error_code_(error_code), buffer_(buffer), buffer_size_(buffer_size) {}
209
210 int run() { return handle(strerror_r(error_code_, buffer_, buffer_size_)); }
211 };
212 return StrError(error_code, buffer, buffer_size).run();
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700213}
214
Victor Zverovich22f75d82014-09-03 08:03:05 -0700215void format_error_code(fmt::Writer &out, int error_code,
Carter Lie2583ab2015-02-14 09:58:29 +0800216 fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700217 // Report error code making sure that the output fits into
218 // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
219 // bad_alloc.
220 out.clear();
221 static const char SEP[] = ": ";
vitaut1addec92015-03-21 20:16:36 -0700222 static const char ERROR_STR[] = "error ";
Victor Zverovich22f75d82014-09-03 08:03:05 -0700223 fmt::internal::IntTraits<int>::MainType ec_value = error_code;
vitaut1addec92015-03-21 20:16:36 -0700224 // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
225 std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
226 error_code_size += fmt::internal::count_digits(ec_value);
Victor Zverovich88e0db82014-09-05 08:04:26 -0700227 if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size)
Victor Zverovich22f75d82014-09-03 08:03:05 -0700228 out << message << SEP;
vitaut1addec92015-03-21 20:16:36 -0700229 out << ERROR_STR << error_code;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700230 assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE);
231}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700232
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700233void report_error(FormatFunc func,
Carter Lie2583ab2015-02-14 09:58:29 +0800234 int error_code, fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovichd1ded562014-09-29 08:48:16 -0700235 fmt::MemoryWriter full_message;
Victor Zverovich88e0db82014-09-05 08:04:26 -0700236 func(full_message, error_code, message);
237 // Use Writer::data instead of Writer::c_str to avoid potential memory
238 // allocation.
239 std::fwrite(full_message.data(), full_message.size(), 1, stderr);
240 std::fputc('\n', stderr);
Victor Zverovichb605b392013-09-09 22:21:40 -0700241}
Victor Zverovichd29e5052014-06-30 07:12:09 -0700242
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700243// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
244class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> {
245 public:
246 template <typename T>
247 bool visit_any_int(T value) { return value == 0; }
248};
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700249
250// Parses an unsigned integer advancing s to the end of the parsed input.
251// This function assumes that the first character of s is a digit.
252template <typename Char>
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700253int parse_nonnegative_int(const Char *&s) {
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700254 assert('0' <= *s && *s <= '9');
255 unsigned value = 0;
256 do {
257 unsigned new_value = value * 10 + (*s++ - '0');
258 // Check if value wrapped around.
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700259 if (new_value < value) {
260 value = UINT_MAX;
261 break;
262 }
263 value = new_value;
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700264 } while ('0' <= *s && *s <= '9');
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700265 if (value > INT_MAX)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700266 FMT_THROW(fmt::FormatError("number is too big"));
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700267 return value;
268}
Victor Zveroviche8251562014-07-08 16:20:33 -0700269
jamboree7487bde2015-06-10 09:32:59 +0800270template <typename Char>
271inline bool is_name_start(Char c) {
272 return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c;
273}
274
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700275inline void require_numeric_argument(const Arg &arg, char spec) {
276 if (arg.type > Arg::LAST_NUMERIC_TYPE) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700277 std::string message =
278 fmt::format("format specifier '{}' requires numeric argument", spec);
279 FMT_THROW(fmt::FormatError(message));
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700280 }
281}
282
Victor Zveroviche8251562014-07-08 16:20:33 -0700283template <typename Char>
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700284void check_sign(const Char *&s, const Arg &arg) {
285 char sign = static_cast<char>(*s);
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700286 require_numeric_argument(arg, sign);
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700287 if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700288 FMT_THROW(fmt::FormatError(fmt::format(
289 "format specifier '{}' requires signed argument", sign)));
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700290 }
291 ++s;
292}
293
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700294// Checks if an argument is a valid printf width specifier and sets
295// left alignment if it is negative.
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700296class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700297 private:
298 fmt::FormatSpec &spec_;
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700299
Victor Zverovich6f3c0952014-12-03 06:16:52 -0800300 FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
301
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700302 public:
303 explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700304
vitautd4ea2d72015-03-26 08:55:20 -0700305 void report_unhandled_arg() {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700306 FMT_THROW(fmt::FormatError("width is not integer"));
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700307 }
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700308
Victor Zverovich9d74f952014-07-16 07:27:54 -0700309 template <typename T>
310 unsigned visit_any_int(T value) {
311 typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType;
312 UnsignedType width = value;
313 if (fmt::internal::is_negative(value)) {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700314 spec_.align_ = fmt::ALIGN_LEFT;
315 width = 0 - width;
316 }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700317 if (width > INT_MAX)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700318 FMT_THROW(fmt::FormatError("number is too big"));
Victor Zverovich9d74f952014-07-16 07:27:54 -0700319 return static_cast<unsigned>(width);
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700320 }
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700321};
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700322
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700323class PrecisionHandler :
324 public fmt::internal::ArgVisitor<PrecisionHandler, int> {
325 public:
vitautd4ea2d72015-03-26 08:55:20 -0700326 void report_unhandled_arg() {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700327 FMT_THROW(fmt::FormatError("precision is not integer"));
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700328 }
329
330 template <typename T>
331 int visit_any_int(T value) {
Victor Zverovichadce0242014-08-17 07:53:55 -0700332 if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
Victor Zverovich8b76e972014-10-06 08:30:55 -0700333 FMT_THROW(fmt::FormatError("number is too big"));
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700334 return static_cast<int>(value);
335 }
336};
337
Victor Zverovich32344d92014-08-28 08:11:21 -0700338// Converts an integer argument to an integral type T for printf.
Victor Zverovicheeca2232014-07-30 07:37:16 -0700339template <typename T>
340class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
341 private:
342 fmt::internal::Arg &arg_;
Victor Zveroviche22d6572014-08-08 06:51:09 -0700343 wchar_t type_;
Victor Zverovicheeca2232014-07-30 07:37:16 -0700344
Victor Zverovich6f3c0952014-12-03 06:16:52 -0800345 FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
346
Victor Zverovicheeca2232014-07-30 07:37:16 -0700347 public:
Victor Zveroviche22d6572014-08-08 06:51:09 -0700348 ArgConverter(fmt::internal::Arg &arg, wchar_t type)
349 : arg_(arg), type_(type) {}
Victor Zverovicheeca2232014-07-30 07:37:16 -0700350
351 template <typename U>
352 void visit_any_int(U value) {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700353 bool is_signed = type_ == 'd' || type_ == 'i';
354 using fmt::internal::Arg;
355 if (sizeof(T) <= sizeof(int)) {
Victor Zverovich32344d92014-08-28 08:11:21 -0700356 // Extra casts are used to silence warnings.
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700357 if (is_signed) {
358 arg_.type = Arg::INT;
Victor Zverovichbb016332014-08-15 09:03:59 -0700359 arg_.int_value = static_cast<int>(static_cast<T>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700360 } else {
361 arg_.type = Arg::UINT;
Victor Zverovich186734c2014-08-18 07:03:12 -0700362 arg_.uint_value = static_cast<unsigned>(
363 static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700364 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700365 } else {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700366 if (is_signed) {
367 arg_.type = Arg::LONG_LONG;
Victor Zverovicha259c942014-08-01 07:15:27 -0700368 arg_.long_long_value =
369 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700370 } else {
371 arg_.type = Arg::ULONG_LONG;
372 arg_.ulong_long_value =
Victor Zverovicha259c942014-08-01 07:15:27 -0700373 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700374 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700375 }
376 }
377};
378
Victor Zverovich32344d92014-08-28 08:11:21 -0700379// Converts an integer argument to char for printf.
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700380class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
381 private:
382 fmt::internal::Arg &arg_;
383
Victor Zverovich6f3c0952014-12-03 06:16:52 -0800384 FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
385
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700386 public:
387 explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
388
389 template <typename T>
390 void visit_any_int(T value) {
391 arg_.type = Arg::CHAR;
392 arg_.int_value = static_cast<char>(value);
393 }
394};
395
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700396// This function template is used to prevent compile errors when handling
397// incompatible string arguments, e.g. handling a wide string in a narrow
398// string formatter.
399template <typename Char>
400Arg::StringValue<Char> ignore_incompatible_str(Arg::StringValue<wchar_t>);
401
402template <>
403inline Arg::StringValue<char> ignore_incompatible_str(
404 Arg::StringValue<wchar_t>) { return Arg::StringValue<char>(); }
405
406template <>
407inline Arg::StringValue<wchar_t> ignore_incompatible_str(
408 Arg::StringValue<wchar_t> s) { return s; }
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700409} // namespace
vitaut8725d072015-06-12 07:56:58 -0700410} // namespace fmt
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700411
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800412FMT_FUNC void fmt::SystemError::init(
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800413 int err_code, StringRef format_str, ArgList args) {
414 error_code_ = err_code;
Victor Zverovichd1ded562014-09-29 08:48:16 -0700415 MemoryWriter w;
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800416 internal::format_system_error(w, err_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700417 std::runtime_error &base = *this;
418 base = std::runtime_error(w.str());
419}
420
Victor Zverovichb605b392013-09-09 22:21:40 -0700421template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700422int fmt::internal::CharTraits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700423 char *buffer, std::size_t size, const char *format,
424 unsigned width, int precision, T value) {
425 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700426 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700427 FMT_SNPRINTF(buffer, size, format, value) :
428 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700429 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700430 return precision < 0 ?
431 FMT_SNPRINTF(buffer, size, format, width, value) :
432 FMT_SNPRINTF(buffer, size, format, width, precision, value);
433}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700434
Victor Zverovichb605b392013-09-09 22:21:40 -0700435template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700436int fmt::internal::CharTraits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700437 wchar_t *buffer, std::size_t size, const wchar_t *format,
438 unsigned width, int precision, T value) {
439 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700440 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000441 FMT_SWPRINTF(buffer, size, format, value) :
442 FMT_SWPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700443 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700444 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000445 FMT_SWPRINTF(buffer, size, format, width, value) :
446 FMT_SWPRINTF(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700447}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800448
Victor Zverovich311251e2014-11-29 06:58:00 -0800449template <typename T>
450const char fmt::internal::BasicData<T>::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800451 "0001020304050607080910111213141516171819"
452 "2021222324252627282930313233343536373839"
453 "4041424344454647484950515253545556575859"
454 "6061626364656667686970717273747576777879"
455 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800456
Victor Zverovichf1d85162014-02-19 13:02:22 -0800457#define FMT_POWERS_OF_10(factor) \
458 factor * 10, \
459 factor * 100, \
460 factor * 1000, \
461 factor * 10000, \
462 factor * 100000, \
463 factor * 1000000, \
464 factor * 10000000, \
465 factor * 100000000, \
466 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800467
Victor Zverovich311251e2014-11-29 06:58:00 -0800468template <typename T>
469const uint32_t fmt::internal::BasicData<T>::POWERS_OF_10_32[] = {
470 0, FMT_POWERS_OF_10(1)
471};
472
473template <typename T>
474const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800475 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800476 FMT_POWERS_OF_10(1),
Victor Zverovichecd2b802014-12-17 06:42:26 -0800477 FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
Victor Zverovich406c6122014-08-19 08:47:38 -0700478 // Multiply several constants instead of using a single long long constant
Victor Zverovichf1d85162014-02-19 13:02:22 -0800479 // to avoid warnings about C++98 not supporting long long.
Victor Zverovichecd2b802014-12-17 06:42:26 -0800480 fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800481};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800482
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800483FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
Carter Li2d4631a2015-03-14 14:54:37 +0800484 (void)type;
Victor Zverovich877abaf2013-01-08 09:56:05 -0800485 if (std::isprint(static_cast<unsigned char>(code))) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700486 FMT_THROW(fmt::FormatError(
487 fmt::format("unknown format code '{}' for {}", code, type)));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800488 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700489 FMT_THROW(fmt::FormatError(
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700490 fmt::format("unknown format code '\\x{:02x}' for {}",
Victor Zverovich8b76e972014-10-06 08:30:55 -0700491 static_cast<unsigned>(code), type)));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800492}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700493
vitaut24c309f2015-06-12 07:15:57 -0700494#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700495
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800496FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700497 int length = MultiByteToWideChar(
498 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, 0, 0);
Victor Zverovichdff21372014-12-16 07:01:01 -0800499 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700500 if (length == 0)
Victor Zverovichdff21372014-12-16 07:01:01 -0800501 FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700502 buffer_.resize(length);
503 length = MultiByteToWideChar(
504 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, &buffer_[0], length);
505 if (length == 0)
Victor Zverovichdff21372014-12-16 07:01:01 -0800506 FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700507}
508
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800509FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700510 if (int error_code = convert(s)) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700511 FMT_THROW(WindowsError(error_code,
512 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700513 }
514}
515
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800516FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700517 int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, 0, 0, 0, 0);
518 if (length == 0)
519 return GetLastError();
520 buffer_.resize(length);
521 length = WideCharToMultiByte(
522 CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, 0, 0);
523 if (length == 0)
524 return GetLastError();
525 return 0;
526}
527
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800528FMT_FUNC void fmt::WindowsError::init(
Carter Li3f574c12015-02-17 10:11:42 +0800529 int err_code, StringRef format_str, ArgList args) {
530 error_code_ = err_code;
Victor Zverovich8c4db502014-09-29 09:17:02 -0700531 MemoryWriter w;
Carter Li3f574c12015-02-17 10:11:42 +0800532 internal::format_windows_error(w, err_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700533 std::runtime_error &base = *this;
534 base = std::runtime_error(w.str());
535}
536
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800537FMT_FUNC void fmt::internal::format_windows_error(
Victor Zverovich22f75d82014-09-03 08:03:05 -0700538 fmt::Writer &out, int error_code,
Carter Lie2583ab2015-02-14 09:58:29 +0800539 fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovich53b4c312014-04-30 15:00:41 -0700540 class String {
541 private:
542 LPWSTR str_;
543
544 public:
545 String() : str_() {}
546 ~String() { LocalFree(str_); }
547 LPWSTR *ptr() { return &str_; }
548 LPCWSTR c_str() const { return str_; }
549 };
Victor Zverovich8b76e972014-10-06 08:30:55 -0700550 FMT_TRY {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700551 String system_message;
552 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
553 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
554 error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
555 reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
556 UTF16ToUTF8 utf8_message;
557 if (utf8_message.convert(system_message.c_str()) == ERROR_SUCCESS) {
558 out << message << ": " << utf8_message;
559 return;
560 }
Victor Zverovich53b4c312014-04-30 15:00:41 -0700561 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700562 } FMT_CATCH(...) {}
Victor Zverovich22f75d82014-09-03 08:03:05 -0700563 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700564}
vitaut24c309f2015-06-12 07:15:57 -0700565
566#endif // FMT_USE_WINDOWS_H
567
568FMT_FUNC void fmt::internal::format_system_error(
569 fmt::Writer &out, int error_code,
570 fmt::StringRef message) FMT_NOEXCEPT {
571 FMT_TRY {
572 MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
573 buffer.resize(INLINE_BUFFER_SIZE);
574 for (;;) {
575 char *system_message = &buffer[0];
576 int result = safe_strerror(error_code, system_message, buffer.size());
577 if (result == 0) {
578 out << message << ": " << system_message;
579 return;
580 }
581 if (result != ERANGE)
582 break; // Can't get error message, report error code instead.
583 buffer.resize(buffer.size() * 2);
584 }
585 } FMT_CATCH(...) {}
586 format_error_code(out, error_code, message);
587}
Victor Zverovich53b4c312014-04-30 15:00:41 -0700588
jamboree7487bde2015-06-10 09:32:59 +0800589template <typename Char>
vitauta98583d2015-06-10 08:49:22 -0700590void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
jamboree7487bde2015-06-10 09:32:59 +0800591 if (!map_.empty())
592 return;
vitauta98583d2015-06-10 08:49:22 -0700593 typedef internal::NamedArg<Char> NamedArg;
vitautfccff7b2015-06-11 07:19:00 -0700594 const NamedArg *named_arg = 0;
vitauta98583d2015-06-10 08:49:22 -0700595 bool use_values =
596 args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
jamboree7487bde2015-06-10 09:32:59 +0800597 if (use_values) {
598 for (unsigned i = 0;/*nothing*/; ++i) {
599 internal::Arg::Type arg_type = args.type(i);
600 switch (arg_type) {
601 case internal::Arg::NONE:
602 return;
603 case internal::Arg::NAMED_ARG:
vitauta98583d2015-06-10 08:49:22 -0700604 named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
jamboree7487bde2015-06-10 09:32:59 +0800605 map_.insert(Pair(named_arg->name, *named_arg));
606 break;
607 default:
608 /*nothing*/;
609 }
610 }
611 return;
612 }
vitauta98583d2015-06-10 08:49:22 -0700613 for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
jamboree7487bde2015-06-10 09:32:59 +0800614 internal::Arg::Type arg_type = args.type(i);
615 if (arg_type == internal::Arg::NAMED_ARG) {
vitauta98583d2015-06-10 08:49:22 -0700616 named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
jamboree7487bde2015-06-10 09:32:59 +0800617 map_.insert(Pair(named_arg->name, *named_arg));
618 }
619 }
vitauta98583d2015-06-10 08:49:22 -0700620 for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
jamboree7487bde2015-06-10 09:32:59 +0800621 switch (args.args_[i].type) {
622 case internal::Arg::NONE:
623 return;
624 case internal::Arg::NAMED_ARG:
vitauta98583d2015-06-10 08:49:22 -0700625 named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
jamboree7487bde2015-06-10 09:32:59 +0800626 map_.insert(Pair(named_arg->name, *named_arg));
627 break;
628 default:
629 /*nothing*/;
630 }
631 }
632}
633
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700634// An argument formatter.
635template <typename Char>
636class fmt::internal::ArgFormatter :
637 public fmt::internal::ArgVisitor<fmt::internal::ArgFormatter<Char>, void> {
638 private:
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700639 fmt::BasicFormatter<Char> &formatter_;
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700640 fmt::BasicWriter<Char> &writer_;
641 fmt::FormatSpec &spec_;
642 const Char *format_;
643
Victor Zverovich6f3c0952014-12-03 06:16:52 -0800644 FMT_DISALLOW_COPY_AND_ASSIGN(ArgFormatter);
645
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700646 public:
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700647 ArgFormatter(
648 fmt::BasicFormatter<Char> &f,fmt::FormatSpec &s, const Char *fmt)
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700649 : formatter_(f), writer_(f.writer()), spec_(s), format_(fmt) {}
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700650
Victor Zverovich9d74f952014-07-16 07:27:54 -0700651 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700652 void visit_any_int(T value) { writer_.write_int(value, spec_); }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700653
654 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700655 void visit_any_double(T value) { writer_.write_double(value, spec_); }
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700656
vitaut9d092142015-06-11 09:00:06 -0700657 void visit_bool(bool value) {
658 if (spec_.type_) {
659 writer_.write_int(value, spec_);
660 return;
661 }
662 const char *str_value = value ? "true" : "false";
663 Arg::StringValue<char> str = { str_value, strlen(str_value) };
664 writer_.write_str(str, spec_);
665 }
666
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700667 void visit_char(int value) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700668 if (spec_.type_ && spec_.type_ != 'c') {
Victor Zverovichd699c2a2014-07-25 08:24:27 -0700669 spec_.flags_ |= CHAR_FLAG;
670 writer_.write_int(value, spec_);
671 return;
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700672 }
673 if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700674 FMT_THROW(FormatError("invalid format specifier for char"));
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700675 typedef typename fmt::BasicWriter<Char>::CharPtr CharPtr;
Victor Zverovich43aebf52015-01-08 07:56:08 -0800676 Char fill = static_cast<Char>(spec_.fill());
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700677 CharPtr out = CharPtr();
678 if (spec_.width_ > 1) {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700679 out = writer_.grow_buffer(spec_.width_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700680 if (spec_.align_ == fmt::ALIGN_RIGHT) {
681 std::fill_n(out, spec_.width_ - 1, fill);
682 out += spec_.width_ - 1;
683 } else if (spec_.align_ == fmt::ALIGN_CENTER) {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700684 out = writer_.fill_padding(out, spec_.width_, 1, fill);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700685 } else {
686 std::fill_n(out + 1, spec_.width_ - 1, fill);
687 }
688 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700689 out = writer_.grow_buffer(1);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700690 }
691 *out = static_cast<Char>(value);
692 }
693
694 void visit_string(Arg::StringValue<char> value) {
695 writer_.write_str(value, spec_);
696 }
697 void visit_wstring(Arg::StringValue<wchar_t> value) {
698 writer_.write_str(ignore_incompatible_str<Char>(value), spec_);
699 }
700
701 void visit_pointer(const void *value) {
702 if (spec_.type_ && spec_.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700703 fmt::internal::report_unknown_type(spec_.type_, "pointer");
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700704 spec_.flags_ = fmt::HASH_FLAG;
705 spec_.type_ = 'x';
Victor Zverovichc1db2932014-07-24 08:53:27 -0700706 writer_.write_int(reinterpret_cast<uintptr_t>(value), spec_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700707 }
708
709 void visit_custom(Arg::CustomValue c) {
Victor Zverovich271fa8c2014-08-29 07:23:54 -0700710 c.format(&formatter_, c.value, &format_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700711 }
712};
713
Victor Zverovichd1ded562014-09-29 08:48:16 -0700714template <typename Char>
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800715void fmt::internal::FixedBuffer<Char>::grow(std::size_t) {
716 FMT_THROW(std::runtime_error("buffer overflow"));
717}
718
719template <typename Char>
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700720template <typename StrChar>
Victor Zverovichd1ded562014-09-29 08:48:16 -0700721void fmt::BasicWriter<Char>::write_str(
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800722 const Arg::StringValue<StrChar> &s, const FormatSpec &spec) {
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700723 // Check if StrChar is convertible to Char.
724 internal::CharTraits<Char>::convert(StrChar());
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700725 if (spec.type_ && spec.type_ != 's')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700726 internal::report_unknown_type(spec.type_, "string");
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800727 const StrChar *str_value = s.value;
728 std::size_t str_size = s.size;
729 if (str_size == 0) {
730 if (!str_value)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700731 FMT_THROW(FormatError("string pointer is null"));
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800732 if (*str_value)
733 str_size = std::char_traits<StrChar>::length(str_value);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700734 }
Victor Zverovich59254412015-02-06 07:27:19 -0800735 std::size_t precision = spec.precision_;
736 if (spec.precision_ >= 0 && precision < str_size)
Victor Zverovich43aebf52015-01-08 07:56:08 -0800737 str_size = spec.precision_;
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800738 write_str(str_value, str_size, spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700739}
740
741template <typename Char>
jamboree7487bde2015-06-10 09:32:59 +0800742inline Arg fmt::BasicFormatter<Char>::get_arg(
vitautfccff7b2015-06-11 07:19:00 -0700743 BasicStringRef<Char> arg_name, const char *&error) {
jamboree7487bde2015-06-10 09:32:59 +0800744 if (check_no_auto_index(error)) {
vitautfccff7b2015-06-11 07:19:00 -0700745 map_.init(args());
746 const Arg *arg = map_.find(arg_name);
jamboree7487bde2015-06-10 09:32:59 +0800747 if (arg)
748 return *arg;
749 error = "argument not found";
750 }
751 return Arg();
752}
753
754template <typename Char>
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700755inline Arg fmt::BasicFormatter<Char>::parse_arg_index(const Char *&s) {
Victor Zverovich9646e382014-08-27 09:13:42 -0700756 const char *error = 0;
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700757 Arg arg = *s < '0' || *s > '9' ?
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700758 next_arg(error) : get_arg(parse_nonnegative_int(s), error);
Victor Zverovich8b76e972014-10-06 08:30:55 -0700759 if (error) {
760 FMT_THROW(FormatError(
761 *s != '}' && *s != ':' ? "invalid format string" : error));
762 }
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700763 return arg;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700764}
765
jamboree7487bde2015-06-10 09:32:59 +0800766template <typename Char>
767inline Arg fmt::BasicFormatter<Char>::parse_arg_name(const Char *&s) {
768 assert(is_name_start(*s));
769 const Char *start = s;
770 Char c;
771 do {
772 c = *++s;
jamboree3c99ed42015-06-11 12:03:22 +0800773 } while (is_name_start(c) || ('0' <= c && c <= '9'));
jamboree7487bde2015-06-10 09:32:59 +0800774 const char *error = 0;
775 Arg arg = get_arg(fmt::BasicStringRef<Char>(start, s - start), error);
776 if (error)
777 FMT_THROW(fmt::FormatError(error));
778 return arg;
779}
780
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800781FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
Victor Zverovich605d2602014-08-29 07:45:55 -0700782 unsigned arg_index, const char *&error) {
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700783 Arg arg = args_[arg_index];
jamboree7487bde2015-06-10 09:32:59 +0800784 switch (arg.type) {
785 case Arg::NONE:
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700786 error = "argument index out of range";
jamboree7487bde2015-06-10 09:32:59 +0800787 break;
788 case Arg::NAMED_ARG:
789 arg = *static_cast<const internal::Arg*>(arg.pointer);
790 default:
791 /*nothing*/;
792 }
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700793 return arg;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700794}
795
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700796inline Arg fmt::internal::FormatterBase::next_arg(const char *&error) {
Victor Zverovich605d2602014-08-29 07:45:55 -0700797 if (next_arg_index_ >= 0)
798 return do_get_arg(next_arg_index_++, error);
799 error = "cannot switch from manual to automatic argument indexing";
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700800 return Arg();
Victor Zverovich605d2602014-08-29 07:45:55 -0700801}
802
vitautfccff7b2015-06-11 07:19:00 -0700803inline bool fmt::internal::FormatterBase::check_no_auto_index(
804 const char *&error) {
jamboree7487bde2015-06-10 09:32:59 +0800805 if (next_arg_index_ > 0) {
806 error = "cannot switch from automatic to manual argument indexing";
807 return false;
808 }
vitautfccff7b2015-06-11 07:19:00 -0700809 next_arg_index_ = -1;
jamboree7487bde2015-06-10 09:32:59 +0800810 return true;
811}
812
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700813inline Arg fmt::internal::FormatterBase::get_arg(
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700814 unsigned arg_index, const char *&error) {
vitautfccff7b2015-06-11 07:19:00 -0700815 return check_no_auto_index(error) ? do_get_arg(arg_index, error) : Arg();
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700816}
817
Victor Zverovich7cae7632013-09-06 20:23:42 -0700818template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700819void fmt::internal::PrintfFormatter<Char>::parse_flags(
Victor Zverovichcb743c02014-06-19 07:40:35 -0700820 FormatSpec &spec, const Char *&s) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700821 for (;;) {
Victor Zverovich1b801482014-06-07 08:57:55 -0700822 switch (*s++) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700823 case '-':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700824 spec.align_ = ALIGN_LEFT;
825 break;
826 case '+':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700827 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
828 break;
829 case '0':
830 spec.fill_ = '0';
Victor Zverovich1b801482014-06-07 08:57:55 -0700831 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700832 case ' ':
Victor Zverovich1b801482014-06-07 08:57:55 -0700833 spec.flags_ |= SIGN_FLAG;
834 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700835 case '#':
Victor Zverovichcb743c02014-06-19 07:40:35 -0700836 spec.flags_ |= HASH_FLAG;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700837 break;
838 default:
Victor Zverovich1b801482014-06-07 08:57:55 -0700839 --s;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700840 return;
841 }
842 }
843}
844
Victor Zverovichcb743c02014-06-19 07:40:35 -0700845template <typename Char>
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700846Arg fmt::internal::PrintfFormatter<Char>::get_arg(
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700847 const Char *s, unsigned arg_index) {
Carter Li2d4631a2015-03-14 14:54:37 +0800848 (void)s;
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700849 const char *error = 0;
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700850 Arg arg = arg_index == UINT_MAX ?
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700851 next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
852 if (error)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700853 FMT_THROW(FormatError(!*s ? "invalid format string" : error));
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700854 return arg;
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700855}
856
857template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700858unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700859 const Char *&s, FormatSpec &spec) {
Victor Zverovichcb743c02014-06-19 07:40:35 -0700860 unsigned arg_index = UINT_MAX;
861 Char c = *s;
862 if (c >= '0' && c <= '9') {
863 // Parse an argument index (if followed by '$') or a width possibly
Victor Zverovich879838a2014-06-20 07:34:02 -0700864 // preceded with '0' flag(s).
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700865 unsigned value = parse_nonnegative_int(s);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700866 if (*s == '$') { // value is an argument index
867 ++s;
868 arg_index = value;
869 } else {
870 if (c == '0')
871 spec.fill_ = '0';
872 if (value != 0) {
873 // Nonzero value means that we parsed width and don't need to
874 // parse it or flags again, so return now.
875 spec.width_ = value;
876 return arg_index;
877 }
878 }
879 }
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700880 parse_flags(spec, s);
Victor Zverovich4099a122014-06-23 08:10:50 -0700881 // Parse width.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700882 if (*s >= '0' && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700883 spec.width_ = parse_nonnegative_int(s);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700884 } else if (*s == '*') {
885 ++s;
Victor Zverovich56fc5252014-08-28 07:48:55 -0700886 spec.width_ = WidthHandler(spec).visit(get_arg(s));
Victor Zverovichcb743c02014-06-19 07:40:35 -0700887 }
888 return arg_index;
889}
890
Victor Zverovich1f19b982014-06-16 07:49:30 -0700891template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700892void fmt::internal::PrintfFormatter<Char>::format(
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800893 BasicWriter<Char> &writer, BasicStringRef<Char> format_str,
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700894 const ArgList &args) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800895 const Char *start = format_str.c_str();
Victor Zverovich605d2602014-08-29 07:45:55 -0700896 set_args(args);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700897 const Char *s = start;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700898 while (*s) {
Victor Zverovich0fc73162013-09-07 12:52:52 -0700899 Char c = *s++;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700900 if (c != '%') continue;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700901 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -0700902 write(writer, start, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700903 start = ++s;
904 continue;
905 }
Victor Zverovichc1db2932014-07-24 08:53:27 -0700906 write(writer, start, s - 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700907
Victor Zverovichcb743c02014-06-19 07:40:35 -0700908 FormatSpec spec;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700909 spec.align_ = ALIGN_RIGHT;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700910
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700911 // Parse argument index, flags and width.
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700912 unsigned arg_index = parse_header(s, spec);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700913
914 // Parse precision.
915 if (*s == '.') {
916 ++s;
917 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700918 spec.precision_ = parse_nonnegative_int(s);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700919 } else if (*s == '*') {
920 ++s;
Victor Zverovich56fc5252014-08-28 07:48:55 -0700921 spec.precision_ = PrecisionHandler().visit(get_arg(s));
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700922 }
923 }
924
Victor Zverovich56fc5252014-08-28 07:48:55 -0700925 Arg arg = get_arg(s, arg_index);
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700926 if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
Victor Zverovichcb743c02014-06-19 07:40:35 -0700927 spec.flags_ &= ~HASH_FLAG;
928 if (spec.fill_ == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700929 if (arg.type <= Arg::LAST_NUMERIC_TYPE)
Victor Zverovichcb743c02014-06-19 07:40:35 -0700930 spec.align_ = ALIGN_NUMERIC;
931 else
932 spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700933 }
934
Victor Zverovichf4156b52014-07-30 08:39:07 -0700935 // Parse length and convert the argument to the required type.
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700936 switch (*s++) {
937 case 'h':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700938 if (*s == 'h')
939 ArgConverter<signed char>(arg, *++s).visit(arg);
Victor Zverovich39b09302014-07-30 08:08:08 -0700940 else
Victor Zverovichf4156b52014-07-30 08:39:07 -0700941 ArgConverter<short>(arg, *s).visit(arg);
Victor Zverovicheeca2232014-07-30 07:37:16 -0700942 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700943 case 'l':
Victor Zverovichd3a70392014-08-12 08:36:19 -0700944 if (*s == 'l')
Victor Zveroviche488a282014-08-13 06:53:43 -0700945 ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
Victor Zverovichd3a70392014-08-12 08:36:19 -0700946 else
947 ArgConverter<long>(arg, *s).visit(arg);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700948 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700949 case 'j':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700950 ArgConverter<intmax_t>(arg, *s).visit(arg);
951 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700952 case 'z':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700953 ArgConverter<size_t>(arg, *s).visit(arg);
954 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700955 case 't':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700956 ArgConverter<ptrdiff_t>(arg, *s).visit(arg);
957 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700958 case 'L':
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700959 // printf produces garbage when 'L' is omitted for long double, no
960 // need to do the same.
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700961 break;
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700962 default:
963 --s;
Victor Zverovichbe00d8b2014-08-19 08:49:10 -0700964 ArgConverter<int>(arg, *s).visit(arg);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700965 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700966
967 // Parse type.
968 if (!*s)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700969 FMT_THROW(FormatError("invalid format string"));
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700970 spec.type_ = static_cast<char>(*s++);
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700971 if (arg.type <= Arg::LAST_INTEGER_TYPE) {
972 // Normalize type.
973 switch (spec.type_) {
974 case 'i': case 'u':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700975 spec.type_ = 'd';
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700976 break;
977 case 'c':
978 // TODO: handle wchar_t
979 CharConverter(arg).visit(arg);
980 break;
981 }
Victor Zverovichf4156b52014-07-30 08:39:07 -0700982 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700983
984 start = s;
985
986 // Format argument.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700987 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700988 case Arg::INT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700989 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700990 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700991 case Arg::UINT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700992 writer.write_int(arg.uint_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700993 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700994 case Arg::LONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700995 writer.write_int(arg.long_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700996 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700997 case Arg::ULONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700998 writer.write_int(arg.ulong_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700999 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001000 case Arg::CHAR: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001001 if (spec.type_ && spec.type_ != 'c')
Victor Zverovichc1db2932014-07-24 08:53:27 -07001002 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001003 typedef typename BasicWriter<Char>::CharPtr CharPtr;
1004 CharPtr out = CharPtr();
1005 if (spec.width_ > 1) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001006 Char fill = ' ';
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001007 out = writer.grow_buffer(spec.width_);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001008 if (spec.align_ != ALIGN_LEFT) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001009 std::fill_n(out, spec.width_ - 1, fill);
1010 out += spec.width_ - 1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001011 } else {
1012 std::fill_n(out + 1, spec.width_ - 1, fill);
1013 }
1014 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001015 out = writer.grow_buffer(1);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001016 }
Victor Zverovichcb743c02014-06-19 07:40:35 -07001017 *out = static_cast<Char>(arg.int_value);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001018 break;
1019 }
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001020 case Arg::DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001021 writer.write_double(arg.double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001022 break;
1023 case Arg::LONG_DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001024 writer.write_double(arg.long_double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001025 break;
Victor Zverovich75a2ea02014-09-25 07:10:44 -07001026 case Arg::CSTRING:
1027 arg.string.size = 0;
1028 writer.write_str(arg.string, spec);
1029 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001030 case Arg::STRING:
Victor Zverovich53201032014-06-30 14:26:29 -07001031 writer.write_str(arg.string, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001032 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001033 case Arg::WSTRING:
Victor Zverovich512e2ce2014-07-14 08:47:03 -07001034 writer.write_str(ignore_incompatible_str<Char>(arg.wstring), spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001035 break;
1036 case Arg::POINTER:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001037 if (spec.type_ && spec.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001038 internal::report_unknown_type(spec.type_, "pointer");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001039 spec.flags_= HASH_FLAG;
1040 spec.type_ = 'x';
Victor Zverovichab6e7592014-09-23 08:21:58 -07001041 writer.write_int(reinterpret_cast<uintptr_t>(arg.pointer), spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001042 break;
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001043 case Arg::CUSTOM: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001044 if (spec.type_)
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001045 internal::report_unknown_type(spec.type_, "object");
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -08001046 const void *str_format = "s";
1047 arg.custom.format(&writer, arg.custom.value, &str_format);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001048 break;
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001049 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001050 default:
1051 assert(false);
1052 break;
1053 }
1054 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001055 write(writer, start, s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001056}
1057
1058template <typename Char>
Victor Zverovichb9a06ba2014-07-08 16:38:50 -07001059const Char *fmt::BasicFormatter<Char>::format(
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001060 const Char *&format_str, const Arg &arg) {
Victor Zveroviche8251562014-07-08 16:20:33 -07001061 const Char *s = format_str;
Victor Zveroviche8251562014-07-08 16:20:33 -07001062 FormatSpec spec;
1063 if (*s == ':') {
1064 if (arg.type == Arg::CUSTOM) {
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001065 arg.custom.format(this, arg.custom.value, &s);
1066 return s;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001067 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001068 ++s;
1069 // Parse fill and alignment.
1070 if (Char c = *s) {
1071 const Char *p = s + 1;
1072 spec.align_ = ALIGN_DEFAULT;
1073 do {
1074 switch (*p) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001075 case '<':
1076 spec.align_ = ALIGN_LEFT;
1077 break;
1078 case '>':
1079 spec.align_ = ALIGN_RIGHT;
1080 break;
1081 case '=':
1082 spec.align_ = ALIGN_NUMERIC;
1083 break;
1084 case '^':
1085 spec.align_ = ALIGN_CENTER;
1086 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001087 }
1088 if (spec.align_ != ALIGN_DEFAULT) {
1089 if (p != s) {
1090 if (c == '}') break;
1091 if (c == '{')
Victor Zverovich8b76e972014-10-06 08:30:55 -07001092 FMT_THROW(FormatError("invalid fill character '{'"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001093 s += 2;
1094 spec.fill_ = c;
1095 } else ++s;
Victor Zverovich5debb2a2014-08-29 08:16:10 -07001096 if (spec.align_ == ALIGN_NUMERIC)
1097 require_numeric_argument(arg, '=');
Victor Zveroviche8251562014-07-08 16:20:33 -07001098 break;
1099 }
1100 } while (--p >= s);
1101 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001102
Victor Zveroviche8251562014-07-08 16:20:33 -07001103 // Parse sign.
1104 switch (*s) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001105 case '+':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001106 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001107 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
1108 break;
1109 case '-':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001110 check_sign(s, arg);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001111 spec.flags_ |= MINUS_FLAG;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001112 break;
1113 case ' ':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001114 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001115 spec.flags_ |= SIGN_FLAG;
1116 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001117 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001118
Victor Zveroviche8251562014-07-08 16:20:33 -07001119 if (*s == '#') {
Victor Zverovich5debb2a2014-08-29 08:16:10 -07001120 require_numeric_argument(arg, '#');
Victor Zveroviche8251562014-07-08 16:20:33 -07001121 spec.flags_ |= HASH_FLAG;
1122 ++s;
1123 }
1124
jamboree54a6cb32015-06-04 13:59:37 +08001125 // Parse zero flag.
1126 if (*s == '0') {
vitaut8949a2e2015-06-08 06:53:18 -07001127 require_numeric_argument(arg, '0');
1128 spec.align_ = ALIGN_NUMERIC;
1129 spec.fill_ = '0';
1130 ++s;
jamboree54a6cb32015-06-04 13:59:37 +08001131 }
1132
1133 // Parse width.
1134 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -07001135 spec.width_ = parse_nonnegative_int(s);
jamboree54a6cb32015-06-04 13:59:37 +08001136 } else if (*s == '{') {
vitaut8949a2e2015-06-08 06:53:18 -07001137 ++s;
vitautfccff7b2015-06-11 07:19:00 -07001138 Arg width_arg = is_name_start(*s) ?
1139 parse_arg_name(s) : parse_arg_index(s);
vitaut8949a2e2015-06-08 06:53:18 -07001140 if (*s++ != '}')
1141 FMT_THROW(FormatError("invalid format string"));
1142 ULongLong value = 0;
1143 switch (width_arg.type) {
1144 case Arg::INT:
1145 if (width_arg.int_value < 0)
1146 FMT_THROW(FormatError("negative width"));
1147 value = width_arg.int_value;
1148 break;
1149 case Arg::UINT:
1150 value = width_arg.uint_value;
1151 break;
1152 case Arg::LONG_LONG:
1153 if (width_arg.long_long_value < 0)
1154 FMT_THROW(FormatError("negative width"));
1155 value = width_arg.long_long_value;
1156 break;
1157 case Arg::ULONG_LONG:
1158 value = width_arg.ulong_long_value;
1159 break;
1160 default:
1161 FMT_THROW(FormatError("width is not integer"));
1162 }
1163 if (value > INT_MAX)
1164 FMT_THROW(FormatError("number is too big"));
1165 spec.width_ = static_cast<int>(value);
Victor Zveroviche8251562014-07-08 16:20:33 -07001166 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001167
Victor Zveroviche8251562014-07-08 16:20:33 -07001168 // Parse precision.
1169 if (*s == '.') {
1170 ++s;
1171 spec.precision_ = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001172 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -07001173 spec.precision_ = parse_nonnegative_int(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001174 } else if (*s == '{') {
Victor Zverovich7cae7632013-09-06 20:23:42 -07001175 ++s;
vitautfccff7b2015-06-11 07:19:00 -07001176 Arg precision_arg =
1177 is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s);
Victor Zverovich42de4f12014-08-27 08:24:31 -07001178 if (*s++ != '}')
Victor Zverovich8b76e972014-10-06 08:30:55 -07001179 FMT_THROW(FormatError("invalid format string"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001180 ULongLong value = 0;
1181 switch (precision_arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001182 case Arg::INT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001183 if (precision_arg.int_value < 0)
Victor Zverovich8b76e972014-10-06 08:30:55 -07001184 FMT_THROW(FormatError("negative precision"));
Victor Zverovich7cae7632013-09-06 20:23:42 -07001185 value = precision_arg.int_value;
1186 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001187 case Arg::UINT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001188 value = precision_arg.uint_value;
1189 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001190 case Arg::LONG_LONG:
Victor Zverovich56f12b72013-11-22 07:45:43 -08001191 if (precision_arg.long_long_value < 0)
Victor Zverovich8b76e972014-10-06 08:30:55 -07001192 FMT_THROW(FormatError("negative precision"));
Victor Zverovich56f12b72013-11-22 07:45:43 -08001193 value = precision_arg.long_long_value;
1194 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001195 case Arg::ULONG_LONG:
Gregory Czajkowskia65542b2013-11-18 22:58:39 -08001196 value = precision_arg.ulong_long_value;
Victor Zverovicha4e72b42013-11-21 09:11:58 -08001197 break;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001198 default:
Victor Zverovich8b76e972014-10-06 08:30:55 -07001199 FMT_THROW(FormatError("precision is not integer"));
Victor Zverovich7cae7632013-09-06 20:23:42 -07001200 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001201 if (value > INT_MAX)
Victor Zverovich8b76e972014-10-06 08:30:55 -07001202 FMT_THROW(FormatError("number is too big"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001203 spec.precision_ = static_cast<int>(value);
Victor Zveroviche8251562014-07-08 16:20:33 -07001204 } else {
Victor Zverovich8b76e972014-10-06 08:30:55 -07001205 FMT_THROW(FormatError("missing precision specifier"));
Victor Zverovich7cae7632013-09-06 20:23:42 -07001206 }
vitautfd5c2e92015-06-11 08:58:31 -07001207 if (arg.type <= Arg::LAST_INTEGER_TYPE || arg.type == Arg::POINTER) {
Victor Zverovich8b76e972014-10-06 08:30:55 -07001208 FMT_THROW(FormatError(
Victor Zverovich43aebf52015-01-08 07:56:08 -08001209 fmt::format("precision not allowed in {} format specifier",
1210 arg.type == Arg::POINTER ? "pointer" : "integer")));
Victor Zveroviche8251562014-07-08 16:20:33 -07001211 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001212 }
1213
Victor Zveroviche8251562014-07-08 16:20:33 -07001214 // Parse type.
1215 if (*s != '}' && *s)
1216 spec.type_ = static_cast<char>(*s++);
1217 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001218
Victor Zveroviche8251562014-07-08 16:20:33 -07001219 if (*s++ != '}')
Victor Zverovich8b76e972014-10-06 08:30:55 -07001220 FMT_THROW(FormatError("missing '}' in format string"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001221 start_ = s;
1222
1223 // Format argument.
Victor Zverovich4edc88f2014-07-16 08:38:15 -07001224 internal::ArgFormatter<Char>(*this, spec, s - 1).visit(arg);
Victor Zveroviche8251562014-07-08 16:20:33 -07001225 return s;
1226}
1227
1228template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001229void fmt::BasicFormatter<Char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001230 BasicStringRef<Char> format_str, const ArgList &args) {
1231 const Char *s = start_ = format_str.c_str();
Victor Zverovich605d2602014-08-29 07:45:55 -07001232 set_args(args);
Victor Zveroviche8251562014-07-08 16:20:33 -07001233 while (*s) {
1234 Char c = *s++;
1235 if (c != '{' && c != '}') continue;
1236 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -07001237 write(writer_, start_, s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001238 start_ = ++s;
1239 continue;
1240 }
1241 if (c == '}')
Victor Zverovich8b76e972014-10-06 08:30:55 -07001242 FMT_THROW(FormatError("unmatched '}' in format string"));
Victor Zverovichc1db2932014-07-24 08:53:27 -07001243 write(writer_, start_, s - 1);
jamboree7487bde2015-06-10 09:32:59 +08001244 Arg arg = is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001245 s = format(s, arg);
1246 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001247 write(writer_, start_, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001248}
1249
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001250FMT_FUNC void fmt::report_system_error(
Carter Lie2583ab2015-02-14 09:58:29 +08001251 int error_code, fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001252 report_error(internal::format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001253}
1254
vitaut24c309f2015-06-12 07:15:57 -07001255#if FMT_USE_WINDOWS_H
Victor Zverovichb49a1b42014-12-09 06:32:07 -08001256FMT_FUNC void fmt::report_windows_error(
Carter Lie2583ab2015-02-14 09:58:29 +08001257 int error_code, fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001258 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001259}
Victor Zverovich400812a2014-04-30 12:38:17 -07001260#endif
Victor Zverovichf7939862014-04-30 10:18:11 -07001261
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001262FMT_FUNC void fmt::print(std::FILE *f, StringRef format_str, ArgList args) {
Victor Zverovichd1ded562014-09-29 08:48:16 -07001263 MemoryWriter w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001264 w.write(format_str, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001265 std::fwrite(w.data(), 1, w.size(), f);
1266}
1267
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001268FMT_FUNC void fmt::print(StringRef format_str, ArgList args) {
Victor Zverovich163178e2014-09-25 07:08:25 -07001269 print(stdout, format_str, args);
1270}
1271
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001272FMT_FUNC void fmt::print(std::ostream &os, StringRef format_str, ArgList args) {
Victor Zverovichd1ded562014-09-29 08:48:16 -07001273 MemoryWriter w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001274 w.write(format_str, args);
Victor Zveroviche3a44c12014-07-09 06:56:36 -07001275 os.write(w.data(), w.size());
1276}
1277
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001278FMT_FUNC void fmt::print_colored(Color c, StringRef format, ArgList args) {
Victor Zverovich2dc108b2014-07-01 09:10:43 -07001279 char escape[] = "\x1b[30m";
1280 escape[3] = '0' + static_cast<char>(c);
1281 std::fputs(escape, stdout);
1282 print(format, args);
1283 std::fputs(RESET_COLOR, stdout);
1284}
1285
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001286FMT_FUNC int fmt::fprintf(std::FILE *f, StringRef format, ArgList args) {
Victor Zverovichd1ded562014-09-29 08:48:16 -07001287 MemoryWriter w;
Victor Zverovich21111cc2014-06-29 19:52:26 -07001288 printf(w, format, args);
Victor Zverovich615c1ee2014-11-14 09:40:01 -08001289 std::size_t size = w.size();
1290 return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001291}
1292
Victor Zverovichc09c42f2015-03-01 09:43:33 -08001293#ifndef FMT_HEADER_ONLY
1294
vitaut9ca1ce22015-05-23 08:04:06 -07001295template struct fmt::internal::BasicData<void>;
vitaut804a74c2015-05-14 12:58:42 -07001296
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001297// Explicit instantiations for char.
1298
Victor Zverovich7c0d5752015-03-01 18:19:56 -08001299template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
1300
Victor Zverovichf43caef2014-09-25 07:21:48 -07001301template const char *fmt::BasicFormatter<char>::format(
1302 const char *&format_str, const fmt::internal::Arg &arg);
1303
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001304template void fmt::BasicFormatter<char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001305 BasicStringRef<char> format, const ArgList &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001306
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001307template void fmt::internal::PrintfFormatter<char>::format(
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001308 BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001309
Victor Zverovich14f25772014-09-19 08:45:05 -07001310template int fmt::internal::CharTraits<char>::format_float(
1311 char *buffer, std::size_t size, const char *format,
1312 unsigned width, int precision, double value);
1313
1314template int fmt::internal::CharTraits<char>::format_float(
1315 char *buffer, std::size_t size, const char *format,
1316 unsigned width, int precision, long double value);
1317
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001318// Explicit instantiations for wchar_t.
1319
Victor Zverovich7c0d5752015-03-01 18:19:56 -08001320template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
1321
Victor Zverovichf43caef2014-09-25 07:21:48 -07001322template const wchar_t *fmt::BasicFormatter<wchar_t>::format(
1323 const wchar_t *&format_str, const fmt::internal::Arg &arg);
1324
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001325template void fmt::BasicFormatter<wchar_t>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001326 BasicStringRef<wchar_t> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001327
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001328template void fmt::internal::PrintfFormatter<wchar_t>::format(
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001329 BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001330 const ArgList &args);
jdale88a9862fd2014-03-11 18:56:24 +00001331
Victor Zverovich14f25772014-09-19 08:45:05 -07001332template int fmt::internal::CharTraits<wchar_t>::format_float(
1333 wchar_t *buffer, std::size_t size, const wchar_t *format,
1334 unsigned width, int precision, double value);
1335
1336template int fmt::internal::CharTraits<wchar_t>::format_float(
1337 wchar_t *buffer, std::size_t size, const wchar_t *format,
1338 unsigned width, int precision, long double value);
1339
Victor Zverovichc09c42f2015-03-01 09:43:33 -08001340#endif // FMT_HEADER_ONLY
1341
jdale88a9862fd2014-03-11 18:56:24 +00001342#if _MSC_VER
1343# pragma warning(pop)
1344#endif