blob: 88801fc0f2502f27ca9b06bf1885c7fe7ce8dd25 [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>
vitaut7dcf0512015-11-13 06:52:13 -080037#include <cstddef> // for std::ptrdiff_t
Victor Zverovich9ff3b972013-09-07 10:15:08 -070038
vitaut24c309f2015-06-12 07:15:57 -070039#if defined(_WIN32) && defined(__MINGW32__)
40# include <cstring>
41#endif
42
43#if FMT_USE_WINDOWS_H
vitaut67ce3942015-04-30 07:48:36 -070044# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
45# include <windows.h>
46# else
47# define NOMINMAX
48# include <windows.h>
49# undef NOMINMAX
50# endif
Ryuuke5a9dc8f2015-02-08 16:08:29 +000051#endif
52
Victor Zverovich6e5551e2014-07-02 06:33:25 -070053using fmt::internal::Arg;
Victor Zverovich447e02c2014-02-15 10:48:34 -080054
Victor Zverovich8b76e972014-10-06 08:30:55 -070055// Check if exceptions are disabled.
Ingo van Lil41ebedf2015-11-03 11:21:09 +010056#if defined(__GNUC__) && !defined(__EXCEPTIONS)
Victor Zverovich8b76e972014-10-06 08:30:55 -070057# define FMT_EXCEPTIONS 0
58#endif
Ingo van Lilb4b13ee2015-11-02 12:34:46 +010059#if defined(_MSC_VER) && !_HAS_EXCEPTIONS
Victor Zverovich8b76e972014-10-06 08:30:55 -070060# define FMT_EXCEPTIONS 0
61#endif
62#ifndef FMT_EXCEPTIONS
63# define FMT_EXCEPTIONS 1
64#endif
65
66#if FMT_EXCEPTIONS
67# define FMT_TRY try
68# define FMT_CATCH(x) catch (x)
69#else
70# define FMT_TRY if (true)
71# define FMT_CATCH(x) if (false)
72#endif
73
74#ifndef FMT_THROW
75# if FMT_EXCEPTIONS
76# define FMT_THROW(x) throw x
77# else
vitaut66915782015-03-25 07:24:26 -070078# define FMT_THROW(x) assert(false)
Victor Zverovich8b76e972014-10-06 08:30:55 -070079# endif
80#endif
81
Victor Zverovichd9c605c2014-11-28 06:40:57 -080082#ifdef FMT_HEADER_ONLY
83# define FMT_FUNC inline
Victor Zverovichc2a69032014-11-28 15:30:03 -080084#else
85# define FMT_FUNC
Victor Zverovichd9c605c2014-11-28 06:40:57 -080086#endif
87
Ingo van Lilb4b13ee2015-11-02 12:34:46 +010088#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +000089# pragma warning(push)
Victor Zverovich8b76e972014-10-06 08:30:55 -070090# pragma warning(disable: 4127) // conditional expression is constant
Daniel.Perrybd0067e2014-11-25 18:01:09 -050091# pragma warning(disable: 4702) // unreachable code
vitautdf47d812015-03-16 18:53:14 -070092// Disable deprecation warning for strerror. The latter is not called but
93// MSVC fails to detect it.
94# pragma warning(disable: 4996)
jdale88a9862fd2014-03-11 18:56:24 +000095#endif
96
vitaut341b98c2015-03-14 13:39:33 -070097// Dummy implementations of strerror_r and strerror_s called if corresponding
98// system functions are not available.
vitautc669cbe2015-07-07 07:05:17 -070099static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
100 return fmt::internal::Null<>();
vitaut341b98c2015-03-14 13:39:33 -0700101}
vitautc669cbe2015-07-07 07:05:17 -0700102static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
103 return fmt::internal::Null<>();
vitaut341b98c2015-03-14 13:39:33 -0700104}
105
vitaut8725d072015-06-12 07:56:58 -0700106namespace fmt {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700107namespace {
108
109#ifndef _MSC_VER
Victor Zverovichb9a568b2014-09-19 07:51:42 -0700110# define FMT_SNPRINTF snprintf
Victor Zverovicha684d0c2013-12-27 08:00:10 -0800111#else // _MSC_VER
Victor Zverovich406c6122014-08-19 08:47:38 -0700112inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -0800113 va_list args;
114 va_start(args, format);
115 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
116 va_end(args);
117 return result;
118}
Victor Zverovichb9a568b2014-09-19 07:51:42 -0700119# define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700120#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -0800121
cstamford55836ca2015-03-10 07:04:31 +0000122#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
123# define FMT_SWPRINTF snwprintf
124#else
125# define FMT_SWPRINTF swprintf
126#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
127
Victor Zverovichadce0242014-08-17 07:53:55 -0700128// Checks if a value fits in int - used to avoid warnings about comparing
129// signed and unsigned integers.
130template <bool IsSigned>
131struct IntChecker {
132 template <typename T>
133 static bool fits_in_int(T value) {
134 unsigned max = INT_MAX;
135 return value <= max;
136 }
vitaut6484a152015-07-08 07:35:57 -0700137 static bool fits_in_int(bool) { return true; }
Victor Zverovichadce0242014-08-17 07:53:55 -0700138};
139
140template <>
141struct IntChecker<true> {
142 template <typename T>
143 static bool fits_in_int(T value) {
vitautfb277232015-10-22 07:33:01 -0700144 return value >= INT_MIN && value <= INT_MAX;
Victor Zverovichadce0242014-08-17 07:53:55 -0700145 }
vitaut17960dd2015-10-28 06:23:22 -0700146 static bool fits_in_int(int) { return true; }
Victor Zverovichadce0242014-08-17 07:53:55 -0700147};
148
Victor Zverovich7004d1e2015-02-08 19:54:39 -0800149const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700150
Victor Zverovich22f75d82014-09-03 08:03:05 -0700151typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
152
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700153// Portable thread-safe version of strerror.
154// Sets buffer to point to a string describing the error code.
155// This can be either a pointer to a string stored in buffer,
156// or a pointer to some static immutable string.
157// Returns one of the following values:
158// 0 - success
159// ERANGE - buffer is not large enough to store the error message
160// other - failure
161// Buffer should be at least of size 1.
162int safe_strerror(
Carter Lie2583ab2015-02-14 09:58:29 +0800163 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
vitaut8ab665a2015-06-22 08:17:23 -0700164 FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
vitaut341b98c2015-03-14 13:39:33 -0700165
vitaut341b98c2015-03-14 13:39:33 -0700166 class StrError {
167 private:
168 int error_code_;
169 char *&buffer_;
170 std::size_t buffer_size_;
171
vitautda052ae2015-03-21 07:53:39 -0700172 // A noop assignment operator to avoid bogus warnings.
173 void operator=(const StrError &) {}
174
vitaut341b98c2015-03-14 13:39:33 -0700175 // Handle the result of XSI-compliant version of strerror_r.
176 int handle(int result) {
vitaute1776ac2015-03-14 14:05:02 -0700177 // glibc versions before 2.13 return result in errno.
178 return result == -1 ? errno : result;
vitaut341b98c2015-03-14 13:39:33 -0700179 }
180
181 // Handle the result of GNU-specific version of strerror_r.
182 int handle(char *message) {
183 // If the buffer is full then the message is probably truncated.
184 if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
185 return ERANGE;
186 buffer_ = message;
187 return 0;
188 }
189
190 // Handle the case when strerror_r is not available.
vitautc669cbe2015-07-07 07:05:17 -0700191 int handle(fmt::internal::Null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700192 return fallback(strerror_s(buffer_, buffer_size_, error_code_));
193 }
194
195 // Fallback to strerror_s when strerror_r is not available.
196 int fallback(int result) {
197 // If the buffer is full then the message is probably truncated.
198 return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
199 ERANGE : result;
200 }
201
202 // Fallback to strerror if strerror_r and strerror_s are not available.
vitautc669cbe2015-07-07 07:05:17 -0700203 int fallback(fmt::internal::Null<>) {
vitaut341b98c2015-03-14 13:39:33 -0700204 errno = 0;
205 buffer_ = strerror(error_code_);
206 return errno;
207 }
208
209 public:
Radu Popescu0affb232015-08-04 12:52:44 +0200210 StrError(int err_code, char *&buf, std::size_t buf_size)
211 : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
vitaut341b98c2015-03-14 13:39:33 -0700212
vitaut63f6c102015-06-14 09:36:23 -0700213 int run() {
214 strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r.
215 return handle(strerror_r(error_code_, buffer_, buffer_size_));
216 }
vitaut341b98c2015-03-14 13:39:33 -0700217 };
218 return StrError(error_code, buffer, buffer_size).run();
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700219}
220
Victor Zverovich22f75d82014-09-03 08:03:05 -0700221void format_error_code(fmt::Writer &out, int error_code,
Carter Lie2583ab2015-02-14 09:58:29 +0800222 fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700223 // Report error code making sure that the output fits into
224 // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
225 // bad_alloc.
226 out.clear();
227 static const char SEP[] = ": ";
vitaut1addec92015-03-21 20:16:36 -0700228 static const char ERROR_STR[] = "error ";
Victor Zverovich22f75d82014-09-03 08:03:05 -0700229 fmt::internal::IntTraits<int>::MainType ec_value = error_code;
vitaut1addec92015-03-21 20:16:36 -0700230 // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
231 std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
232 error_code_size += fmt::internal::count_digits(ec_value);
Victor Zverovich88e0db82014-09-05 08:04:26 -0700233 if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size)
Victor Zverovich22f75d82014-09-03 08:03:05 -0700234 out << message << SEP;
vitaut1addec92015-03-21 20:16:36 -0700235 out << ERROR_STR << error_code;
Victor Zverovich22f75d82014-09-03 08:03:05 -0700236 assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE);
237}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700238
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700239void report_error(FormatFunc func,
Carter Lie2583ab2015-02-14 09:58:29 +0800240 int error_code, fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovichd1ded562014-09-29 08:48:16 -0700241 fmt::MemoryWriter full_message;
Victor Zverovich88e0db82014-09-05 08:04:26 -0700242 func(full_message, error_code, message);
243 // Use Writer::data instead of Writer::c_str to avoid potential memory
244 // allocation.
245 std::fwrite(full_message.data(), full_message.size(), 1, stderr);
246 std::fputc('\n', stderr);
Victor Zverovichb605b392013-09-09 22:21:40 -0700247}
Victor Zverovichd29e5052014-06-30 07:12:09 -0700248
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700249// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
250class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> {
251 public:
252 template <typename T>
253 bool visit_any_int(T value) { return value == 0; }
254};
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700255
256// Parses an unsigned integer advancing s to the end of the parsed input.
257// This function assumes that the first character of s is a digit.
258template <typename Char>
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700259int parse_nonnegative_int(const Char *&s) {
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700260 assert('0' <= *s && *s <= '9');
261 unsigned value = 0;
262 do {
263 unsigned new_value = value * 10 + (*s++ - '0');
264 // Check if value wrapped around.
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700265 if (new_value < value) {
266 value = UINT_MAX;
267 break;
268 }
269 value = new_value;
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700270 } while ('0' <= *s && *s <= '9');
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700271 if (value > INT_MAX)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700272 FMT_THROW(fmt::FormatError("number is too big"));
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700273 return value;
274}
Victor Zveroviche8251562014-07-08 16:20:33 -0700275
jamboree7487bde2015-06-10 09:32:59 +0800276template <typename Char>
277inline bool is_name_start(Char c) {
278 return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c;
279}
280
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700281inline void require_numeric_argument(const Arg &arg, char spec) {
282 if (arg.type > Arg::LAST_NUMERIC_TYPE) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700283 std::string message =
284 fmt::format("format specifier '{}' requires numeric argument", spec);
285 FMT_THROW(fmt::FormatError(message));
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700286 }
287}
288
Victor Zveroviche8251562014-07-08 16:20:33 -0700289template <typename Char>
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700290void check_sign(const Char *&s, const Arg &arg) {
291 char sign = static_cast<char>(*s);
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700292 require_numeric_argument(arg, sign);
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700293 if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700294 FMT_THROW(fmt::FormatError(fmt::format(
295 "format specifier '{}' requires signed argument", sign)));
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700296 }
297 ++s;
298}
299
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700300// Checks if an argument is a valid printf width specifier and sets
301// left alignment if it is negative.
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700302class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700303 private:
304 fmt::FormatSpec &spec_;
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700305
Victor Zverovich6f3c0952014-12-03 06:16:52 -0800306 FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
307
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700308 public:
309 explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700310
vitautd4ea2d72015-03-26 08:55:20 -0700311 void report_unhandled_arg() {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700312 FMT_THROW(fmt::FormatError("width is not integer"));
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700313 }
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700314
Victor Zverovich9d74f952014-07-16 07:27:54 -0700315 template <typename T>
316 unsigned visit_any_int(T value) {
317 typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType;
318 UnsignedType width = value;
319 if (fmt::internal::is_negative(value)) {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700320 spec_.align_ = fmt::ALIGN_LEFT;
321 width = 0 - width;
322 }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700323 if (width > INT_MAX)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700324 FMT_THROW(fmt::FormatError("number is too big"));
Victor Zverovich9d74f952014-07-16 07:27:54 -0700325 return static_cast<unsigned>(width);
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700326 }
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700327};
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700328
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700329class PrecisionHandler :
330 public fmt::internal::ArgVisitor<PrecisionHandler, int> {
331 public:
vitautd4ea2d72015-03-26 08:55:20 -0700332 void report_unhandled_arg() {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700333 FMT_THROW(fmt::FormatError("precision is not integer"));
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700334 }
335
336 template <typename T>
337 int visit_any_int(T value) {
Victor Zverovichadce0242014-08-17 07:53:55 -0700338 if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
Victor Zverovich8b76e972014-10-06 08:30:55 -0700339 FMT_THROW(fmt::FormatError("number is too big"));
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700340 return static_cast<int>(value);
341 }
342};
343
Victor Zverovich32344d92014-08-28 08:11:21 -0700344// Converts an integer argument to an integral type T for printf.
Victor Zverovicheeca2232014-07-30 07:37:16 -0700345template <typename T>
346class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
347 private:
348 fmt::internal::Arg &arg_;
Victor Zveroviche22d6572014-08-08 06:51:09 -0700349 wchar_t type_;
Victor Zverovicheeca2232014-07-30 07:37:16 -0700350
Victor Zverovich6f3c0952014-12-03 06:16:52 -0800351 FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
352
Victor Zverovicheeca2232014-07-30 07:37:16 -0700353 public:
Victor Zveroviche22d6572014-08-08 06:51:09 -0700354 ArgConverter(fmt::internal::Arg &arg, wchar_t type)
355 : arg_(arg), type_(type) {}
Victor Zverovicheeca2232014-07-30 07:37:16 -0700356
357 template <typename U>
358 void visit_any_int(U value) {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700359 bool is_signed = type_ == 'd' || type_ == 'i';
360 using fmt::internal::Arg;
361 if (sizeof(T) <= sizeof(int)) {
Victor Zverovich32344d92014-08-28 08:11:21 -0700362 // Extra casts are used to silence warnings.
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700363 if (is_signed) {
364 arg_.type = Arg::INT;
Victor Zverovichbb016332014-08-15 09:03:59 -0700365 arg_.int_value = static_cast<int>(static_cast<T>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700366 } else {
367 arg_.type = Arg::UINT;
Victor Zverovich186734c2014-08-18 07:03:12 -0700368 arg_.uint_value = static_cast<unsigned>(
369 static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700370 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700371 } else {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700372 if (is_signed) {
373 arg_.type = Arg::LONG_LONG;
Victor Zverovicha259c942014-08-01 07:15:27 -0700374 arg_.long_long_value =
375 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700376 } else {
377 arg_.type = Arg::ULONG_LONG;
378 arg_.ulong_long_value =
Victor Zverovicha259c942014-08-01 07:15:27 -0700379 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700380 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700381 }
382 }
383};
384
Victor Zverovich32344d92014-08-28 08:11:21 -0700385// Converts an integer argument to char for printf.
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700386class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
387 private:
388 fmt::internal::Arg &arg_;
389
Victor Zverovich6f3c0952014-12-03 06:16:52 -0800390 FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
391
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700392 public:
393 explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
394
395 template <typename T>
396 void visit_any_int(T value) {
397 arg_.type = Arg::CHAR;
398 arg_.int_value = static_cast<char>(value);
399 }
400};
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700401} // namespace
vitaut270069b2015-06-16 07:36:32 -0700402
403namespace internal {
404
405template <typename Impl, typename Char>
406class BasicArgFormatter : public ArgVisitor<Impl, void> {
407 private:
408 BasicWriter<Char> &writer_;
409 FormatSpec &spec_;
410
411 FMT_DISALLOW_COPY_AND_ASSIGN(BasicArgFormatter);
412
vitaut8b86a742015-11-09 07:17:36 -0800413 void write_pointer(const void *p) {
414 spec_.flags_ = HASH_FLAG;
415 spec_.type_ = 'x';
416 writer_.write_int(reinterpret_cast<uintptr_t>(p), spec_);
417 }
418
vitaut270069b2015-06-16 07:36:32 -0700419 protected:
420 BasicWriter<Char> &writer() { return writer_; }
421 const FormatSpec &spec() const { return spec_; }
422
423 public:
424 BasicArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
425 : writer_(w), spec_(s) {}
426
427 template <typename T>
428 void visit_any_int(T value) { writer_.write_int(value, spec_); }
429
430 template <typename T>
431 void visit_any_double(T value) { writer_.write_double(value, spec_); }
432
433 void visit_bool(bool value) {
434 if (spec_.type_) {
435 writer_.write_int(value, spec_);
436 return;
437 }
438 const char *str_value = value ? "true" : "false";
439 Arg::StringValue<char> str = { str_value, strlen(str_value) };
440 writer_.write_str(str, spec_);
441 }
442
443 void visit_char(int value) {
444 if (spec_.type_ && spec_.type_ != 'c') {
445 spec_.flags_ |= CHAR_FLAG;
446 writer_.write_int(value, spec_);
447 return;
448 }
449 if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
450 FMT_THROW(FormatError("invalid format specifier for char"));
451 typedef typename BasicWriter<Char>::CharPtr CharPtr;
vitaut147e5eb2015-06-17 07:21:16 -0700452 Char fill = internal::CharTraits<Char>::cast(spec_.fill());
vitaut270069b2015-06-16 07:36:32 -0700453 CharPtr out = CharPtr();
vitaut82acd482015-10-30 07:54:55 -0700454 const unsigned CHAR_WIDTH = 1;
vitaut316b05c2015-10-28 06:31:37 -0700455 if (spec_.width_ > CHAR_WIDTH) {
vitaut270069b2015-06-16 07:36:32 -0700456 out = writer_.grow_buffer(spec_.width_);
457 if (spec_.align_ == ALIGN_RIGHT) {
vitaut316b05c2015-10-28 06:31:37 -0700458 std::fill_n(out, spec_.width_ - CHAR_WIDTH, fill);
459 out += spec_.width_ - CHAR_WIDTH;
vitaut270069b2015-06-16 07:36:32 -0700460 } else if (spec_.align_ == ALIGN_CENTER) {
vitaut2d727e72015-10-28 07:01:28 -0700461 out = writer_.fill_padding(out, spec_.width_,
462 internal::check(CHAR_WIDTH), fill);
vitaut270069b2015-06-16 07:36:32 -0700463 } else {
vitaut316b05c2015-10-28 06:31:37 -0700464 std::fill_n(out + CHAR_WIDTH, spec_.width_ - CHAR_WIDTH, fill);
vitaut270069b2015-06-16 07:36:32 -0700465 }
466 } else {
vitaut2d727e72015-10-28 07:01:28 -0700467 out = writer_.grow_buffer(CHAR_WIDTH);
vitaut270069b2015-06-16 07:36:32 -0700468 }
vitaut147e5eb2015-06-17 07:21:16 -0700469 *out = internal::CharTraits<Char>::cast(value);
vitaut270069b2015-06-16 07:36:32 -0700470 }
471
vitaut8b86a742015-11-09 07:17:36 -0800472 void visit_cstring(const char *value) {
473 if (spec_.type_ == 'p') {
474 write_pointer(value);
475 return;
476 }
477 Arg::StringValue<char> str = {value, 0};
478 writer_.write_str(str, spec_);
479 }
480
vitaut270069b2015-06-16 07:36:32 -0700481 void visit_string(Arg::StringValue<char> value) {
482 writer_.write_str(value, spec_);
483 }
484
485 using ArgVisitor<Impl, void>::visit_wstring;
486
487 void visit_wstring(Arg::StringValue<Char> value) {
488 writer_.write_str(value, spec_);
489 }
490
491 void visit_pointer(const void *value) {
492 if (spec_.type_ && spec_.type_ != 'p')
493 report_unknown_type(spec_.type_, "pointer");
vitaut8b86a742015-11-09 07:17:36 -0800494 write_pointer(value);
vitaut270069b2015-06-16 07:36:32 -0700495 }
496};
497
498// An argument formatter.
499template <typename Char>
500class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> {
501 private:
502 BasicFormatter<Char> &formatter_;
503 const Char *format_;
504
505 public:
506 ArgFormatter(BasicFormatter<Char> &f, FormatSpec &s, const Char *fmt)
507 : BasicArgFormatter<ArgFormatter<Char>, Char>(f.writer(), s),
508 formatter_(f), format_(fmt) {}
509
510 void visit_custom(Arg::CustomValue c) {
511 c.format(&formatter_, c.value, &format_);
512 }
513};
514
515template <typename Char>
516class PrintfArgFormatter :
517 public BasicArgFormatter<PrintfArgFormatter<Char>, Char> {
vitaut57ba9432015-11-12 06:09:08 -0800518
519 void write_null_pointer() {
520 this->writer() << "(nil)";
521 }
522
vitaut270069b2015-06-16 07:36:32 -0700523 public:
524 PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
525 : BasicArgFormatter<PrintfArgFormatter<Char>, Char>(w, s) {}
526
527 void visit_char(int value) {
vitaut7fa17fe2015-08-04 07:55:33 -0700528 const FormatSpec &fmt_spec = this->spec();
vitautecdc7ec2015-08-04 08:01:28 -0700529 BasicWriter<Char> &w = this->writer();
vitaut7fa17fe2015-08-04 07:55:33 -0700530 if (fmt_spec.type_ && fmt_spec.type_ != 'c')
vitautecdc7ec2015-08-04 08:01:28 -0700531 w.write_int(value, fmt_spec);
vitaut270069b2015-06-16 07:36:32 -0700532 typedef typename BasicWriter<Char>::CharPtr CharPtr;
533 CharPtr out = CharPtr();
vitaut7fa17fe2015-08-04 07:55:33 -0700534 if (fmt_spec.width_ > 1) {
vitaut270069b2015-06-16 07:36:32 -0700535 Char fill = ' ';
vitautecdc7ec2015-08-04 08:01:28 -0700536 out = w.grow_buffer(fmt_spec.width_);
vitaut7fa17fe2015-08-04 07:55:33 -0700537 if (fmt_spec.align_ != ALIGN_LEFT) {
538 std::fill_n(out, fmt_spec.width_ - 1, fill);
539 out += fmt_spec.width_ - 1;
vitaut270069b2015-06-16 07:36:32 -0700540 } else {
vitaut7fa17fe2015-08-04 07:55:33 -0700541 std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
vitaut270069b2015-06-16 07:36:32 -0700542 }
543 } else {
vitautecdc7ec2015-08-04 08:01:28 -0700544 out = w.grow_buffer(1);
vitaut270069b2015-06-16 07:36:32 -0700545 }
546 *out = static_cast<Char>(value);
547 }
vitaut79d8f592015-09-08 08:36:20 -0700548
vitautb5fda1c2015-11-11 07:57:19 -0800549 void visit_cstring(const char *value) {
550 if (value)
551 BasicArgFormatter<PrintfArgFormatter<Char>, Char>::visit_cstring(value);
vitaut57ba9432015-11-12 06:09:08 -0800552 else if (this->spec().type_ == 'p')
553 write_null_pointer();
vitautb5fda1c2015-11-11 07:57:19 -0800554 else
555 this->writer() << "(null)";
556 }
557
558 void visit_pointer(const void *value) {
559 if (value)
560 BasicArgFormatter<PrintfArgFormatter<Char>, Char>::visit_pointer(value);
561 else
vitaut57ba9432015-11-12 06:09:08 -0800562 write_null_pointer();
vitautb5fda1c2015-11-11 07:57:19 -0800563 }
564
vitaut79d8f592015-09-08 08:36:20 -0700565 void visit_custom(Arg::CustomValue c) {
566 BasicFormatter<Char> formatter(ArgList(), this->writer());
vitautef710de2015-09-18 16:26:41 -0700567 const Char format_str[] = {'}', 0};
568 const Char *format = format_str;
vitaut79d8f592015-09-08 08:36:20 -0700569 c.format(&formatter, c.value, &format);
570 }
vitaut270069b2015-06-16 07:36:32 -0700571};
572} // namespace internal
vitaut8725d072015-06-12 07:56:58 -0700573} // namespace fmt
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700574
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800575FMT_FUNC void fmt::SystemError::init(
vitaut438bd9b2015-06-26 07:43:54 -0700576 int err_code, CStringRef format_str, ArgList args) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800577 error_code_ = err_code;
Victor Zverovichd1ded562014-09-29 08:48:16 -0700578 MemoryWriter w;
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800579 internal::format_system_error(w, err_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700580 std::runtime_error &base = *this;
581 base = std::runtime_error(w.str());
582}
583
Victor Zverovichb605b392013-09-09 22:21:40 -0700584template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700585int fmt::internal::CharTraits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700586 char *buffer, std::size_t size, const char *format,
587 unsigned width, int precision, T value) {
588 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700589 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700590 FMT_SNPRINTF(buffer, size, format, value) :
591 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700592 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700593 return precision < 0 ?
594 FMT_SNPRINTF(buffer, size, format, width, value) :
595 FMT_SNPRINTF(buffer, size, format, width, precision, value);
596}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700597
Victor Zverovichb605b392013-09-09 22:21:40 -0700598template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700599int fmt::internal::CharTraits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700600 wchar_t *buffer, std::size_t size, const wchar_t *format,
601 unsigned width, int precision, T value) {
602 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700603 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000604 FMT_SWPRINTF(buffer, size, format, value) :
605 FMT_SWPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700606 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700607 return precision < 0 ?
cstamford55836ca2015-03-10 07:04:31 +0000608 FMT_SWPRINTF(buffer, size, format, width, value) :
609 FMT_SWPRINTF(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700610}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800611
Victor Zverovich311251e2014-11-29 06:58:00 -0800612template <typename T>
613const char fmt::internal::BasicData<T>::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800614 "0001020304050607080910111213141516171819"
615 "2021222324252627282930313233343536373839"
616 "4041424344454647484950515253545556575859"
617 "6061626364656667686970717273747576777879"
618 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800619
Victor Zverovichf1d85162014-02-19 13:02:22 -0800620#define FMT_POWERS_OF_10(factor) \
621 factor * 10, \
622 factor * 100, \
623 factor * 1000, \
624 factor * 10000, \
625 factor * 100000, \
626 factor * 1000000, \
627 factor * 10000000, \
628 factor * 100000000, \
629 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800630
Victor Zverovich311251e2014-11-29 06:58:00 -0800631template <typename T>
632const uint32_t fmt::internal::BasicData<T>::POWERS_OF_10_32[] = {
633 0, FMT_POWERS_OF_10(1)
634};
635
636template <typename T>
637const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800638 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800639 FMT_POWERS_OF_10(1),
Victor Zverovichecd2b802014-12-17 06:42:26 -0800640 FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
Victor Zverovich406c6122014-08-19 08:47:38 -0700641 // Multiply several constants instead of using a single long long constant
Victor Zverovichf1d85162014-02-19 13:02:22 -0800642 // to avoid warnings about C++98 not supporting long long.
Victor Zverovichecd2b802014-12-17 06:42:26 -0800643 fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800644};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800645
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800646FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
Carter Li2d4631a2015-03-14 14:54:37 +0800647 (void)type;
Victor Zverovich877abaf2013-01-08 09:56:05 -0800648 if (std::isprint(static_cast<unsigned char>(code))) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700649 FMT_THROW(fmt::FormatError(
650 fmt::format("unknown format code '{}' for {}", code, type)));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800651 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700652 FMT_THROW(fmt::FormatError(
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700653 fmt::format("unknown format code '\\x{:02x}' for {}",
Victor Zverovich8b76e972014-10-06 08:30:55 -0700654 static_cast<unsigned>(code), type)));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800655}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700656
vitaut24c309f2015-06-12 07:15:57 -0700657#if FMT_USE_WINDOWS_H
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700658
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800659FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
Victor Zverovichdff21372014-12-16 07:01:01 -0800660 static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
vitautc3ba6152015-08-07 07:34:58 -0700661 if (s.size() > INT_MAX)
662 FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
663 int s_size = static_cast<int>(s.size());
664 int length = MultiByteToWideChar(
665 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700666 if (length == 0)
Victor Zverovichdff21372014-12-16 07:01:01 -0800667 FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700668 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700669 length = MultiByteToWideChar(
vitautc3ba6152015-08-07 07:34:58 -0700670 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700671 if (length == 0)
Victor Zverovichdff21372014-12-16 07:01:01 -0800672 FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
vitaut71542382015-06-27 09:11:15 -0700673 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700674}
675
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800676FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700677 if (int error_code = convert(s)) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700678 FMT_THROW(WindowsError(error_code,
679 "cannot convert string from UTF-16 to UTF-8"));
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700680 }
681}
682
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800683FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
vitautca747812015-08-07 07:08:46 -0700684 if (s.size() > INT_MAX)
685 return ERROR_INVALID_PARAMETER;
686 int s_size = static_cast<int>(s.size());
687 int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700688 if (length == 0)
689 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700690 buffer_.resize(length + 1);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700691 length = WideCharToMultiByte(
vitautca747812015-08-07 07:08:46 -0700692 CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700693 if (length == 0)
694 return GetLastError();
vitaut71542382015-06-27 09:11:15 -0700695 buffer_[length] = 0;
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700696 return 0;
697}
698
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800699FMT_FUNC void fmt::WindowsError::init(
vitautba09c1b2015-06-26 09:23:11 -0700700 int err_code, CStringRef format_str, ArgList args) {
Carter Li3f574c12015-02-17 10:11:42 +0800701 error_code_ = err_code;
Victor Zverovich8c4db502014-09-29 09:17:02 -0700702 MemoryWriter w;
Carter Li3f574c12015-02-17 10:11:42 +0800703 internal::format_windows_error(w, err_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700704 std::runtime_error &base = *this;
705 base = std::runtime_error(w.str());
706}
707
Victor Zverovichb49a1b42014-12-09 06:32:07 -0800708FMT_FUNC void fmt::internal::format_windows_error(
Victor Zverovich22f75d82014-09-03 08:03:05 -0700709 fmt::Writer &out, int error_code,
Carter Lie2583ab2015-02-14 09:58:29 +0800710 fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovich53b4c312014-04-30 15:00:41 -0700711 class String {
712 private:
713 LPWSTR str_;
714
715 public:
716 String() : str_() {}
717 ~String() { LocalFree(str_); }
718 LPWSTR *ptr() { return &str_; }
719 LPCWSTR c_str() const { return str_; }
720 };
Victor Zverovich8b76e972014-10-06 08:30:55 -0700721 FMT_TRY {
Victor Zverovich22f75d82014-09-03 08:03:05 -0700722 String system_message;
723 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
724 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
725 error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
726 reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
727 UTF16ToUTF8 utf8_message;
728 if (utf8_message.convert(system_message.c_str()) == ERROR_SUCCESS) {
729 out << message << ": " << utf8_message;
730 return;
731 }
Victor Zverovich53b4c312014-04-30 15:00:41 -0700732 }
Victor Zverovich8b76e972014-10-06 08:30:55 -0700733 } FMT_CATCH(...) {}
Victor Zverovich22f75d82014-09-03 08:03:05 -0700734 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700735}
vitaut24c309f2015-06-12 07:15:57 -0700736
737#endif // FMT_USE_WINDOWS_H
738
739FMT_FUNC void fmt::internal::format_system_error(
740 fmt::Writer &out, int error_code,
741 fmt::StringRef message) FMT_NOEXCEPT {
742 FMT_TRY {
743 MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
744 buffer.resize(INLINE_BUFFER_SIZE);
745 for (;;) {
746 char *system_message = &buffer[0];
747 int result = safe_strerror(error_code, system_message, buffer.size());
748 if (result == 0) {
749 out << message << ": " << system_message;
750 return;
751 }
752 if (result != ERANGE)
753 break; // Can't get error message, report error code instead.
754 buffer.resize(buffer.size() * 2);
755 }
756 } FMT_CATCH(...) {}
757 format_error_code(out, error_code, message);
758}
Victor Zverovich53b4c312014-04-30 15:00:41 -0700759
jamboree7487bde2015-06-10 09:32:59 +0800760template <typename Char>
vitauta98583d2015-06-10 08:49:22 -0700761void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
jamboree7487bde2015-06-10 09:32:59 +0800762 if (!map_.empty())
763 return;
vitauta98583d2015-06-10 08:49:22 -0700764 typedef internal::NamedArg<Char> NamedArg;
vitautfccff7b2015-06-11 07:19:00 -0700765 const NamedArg *named_arg = 0;
vitauta98583d2015-06-10 08:49:22 -0700766 bool use_values =
767 args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
jamboree7487bde2015-06-10 09:32:59 +0800768 if (use_values) {
769 for (unsigned i = 0;/*nothing*/; ++i) {
770 internal::Arg::Type arg_type = args.type(i);
771 switch (arg_type) {
772 case internal::Arg::NONE:
773 return;
774 case internal::Arg::NAMED_ARG:
vitauta98583d2015-06-10 08:49:22 -0700775 named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
jamboree7487bde2015-06-10 09:32:59 +0800776 map_.insert(Pair(named_arg->name, *named_arg));
777 break;
778 default:
779 /*nothing*/;
780 }
781 }
782 return;
783 }
vitauta98583d2015-06-10 08:49:22 -0700784 for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
jamboree7487bde2015-06-10 09:32:59 +0800785 internal::Arg::Type arg_type = args.type(i);
786 if (arg_type == internal::Arg::NAMED_ARG) {
vitauta98583d2015-06-10 08:49:22 -0700787 named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
jamboree7487bde2015-06-10 09:32:59 +0800788 map_.insert(Pair(named_arg->name, *named_arg));
789 }
790 }
vitauta98583d2015-06-10 08:49:22 -0700791 for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
jamboree7487bde2015-06-10 09:32:59 +0800792 switch (args.args_[i].type) {
793 case internal::Arg::NONE:
794 return;
795 case internal::Arg::NAMED_ARG:
vitauta98583d2015-06-10 08:49:22 -0700796 named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
jamboree7487bde2015-06-10 09:32:59 +0800797 map_.insert(Pair(named_arg->name, *named_arg));
798 break;
799 default:
800 /*nothing*/;
801 }
802 }
803}
804
Victor Zverovichd1ded562014-09-29 08:48:16 -0700805template <typename Char>
Victor Zverovich7c0d5752015-03-01 18:19:56 -0800806void fmt::internal::FixedBuffer<Char>::grow(std::size_t) {
807 FMT_THROW(std::runtime_error("buffer overflow"));
808}
809
810template <typename Char>
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700811template <typename StrChar>
Victor Zverovichd1ded562014-09-29 08:48:16 -0700812void fmt::BasicWriter<Char>::write_str(
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800813 const Arg::StringValue<StrChar> &s, const FormatSpec &spec) {
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700814 // Check if StrChar is convertible to Char.
815 internal::CharTraits<Char>::convert(StrChar());
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700816 if (spec.type_ && spec.type_ != 's')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700817 internal::report_unknown_type(spec.type_, "string");
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800818 const StrChar *str_value = s.value;
819 std::size_t str_size = s.size;
820 if (str_size == 0) {
vitautcd097d32015-10-21 06:16:55 -0700821 if (!str_value) {
Victor Zverovich8b76e972014-10-06 08:30:55 -0700822 FMT_THROW(FormatError("string pointer is null"));
vitautcd097d32015-10-21 06:16:55 -0700823 return;
824 }
825 if (*str_value)
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800826 str_size = std::char_traits<StrChar>::length(str_value);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700827 }
Victor Zverovich59254412015-02-06 07:27:19 -0800828 std::size_t precision = spec.precision_;
829 if (spec.precision_ >= 0 && precision < str_size)
Victor Zverovich43aebf52015-01-08 07:56:08 -0800830 str_size = spec.precision_;
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800831 write_str(str_value, str_size, spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700832}
833
834template <typename Char>
jamboree7487bde2015-06-10 09:32:59 +0800835inline Arg fmt::BasicFormatter<Char>::get_arg(
vitautfccff7b2015-06-11 07:19:00 -0700836 BasicStringRef<Char> arg_name, const char *&error) {
jamboree7487bde2015-06-10 09:32:59 +0800837 if (check_no_auto_index(error)) {
vitautfccff7b2015-06-11 07:19:00 -0700838 map_.init(args());
839 const Arg *arg = map_.find(arg_name);
jamboree7487bde2015-06-10 09:32:59 +0800840 if (arg)
841 return *arg;
842 error = "argument not found";
843 }
844 return Arg();
845}
846
847template <typename Char>
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700848inline Arg fmt::BasicFormatter<Char>::parse_arg_index(const Char *&s) {
Victor Zverovich9646e382014-08-27 09:13:42 -0700849 const char *error = 0;
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700850 Arg arg = *s < '0' || *s > '9' ?
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700851 next_arg(error) : get_arg(parse_nonnegative_int(s), error);
Victor Zverovich8b76e972014-10-06 08:30:55 -0700852 if (error) {
853 FMT_THROW(FormatError(
854 *s != '}' && *s != ':' ? "invalid format string" : error));
855 }
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700856 return arg;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700857}
858
jamboree7487bde2015-06-10 09:32:59 +0800859template <typename Char>
860inline Arg fmt::BasicFormatter<Char>::parse_arg_name(const Char *&s) {
861 assert(is_name_start(*s));
862 const Char *start = s;
863 Char c;
864 do {
865 c = *++s;
jamboree3c99ed42015-06-11 12:03:22 +0800866 } while (is_name_start(c) || ('0' <= c && c <= '9'));
jamboree7487bde2015-06-10 09:32:59 +0800867 const char *error = 0;
868 Arg arg = get_arg(fmt::BasicStringRef<Char>(start, s - start), error);
869 if (error)
870 FMT_THROW(fmt::FormatError(error));
871 return arg;
872}
873
Victor Zverovichd9c605c2014-11-28 06:40:57 -0800874FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
Victor Zverovich605d2602014-08-29 07:45:55 -0700875 unsigned arg_index, const char *&error) {
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700876 Arg arg = args_[arg_index];
jamboree7487bde2015-06-10 09:32:59 +0800877 switch (arg.type) {
878 case Arg::NONE:
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700879 error = "argument index out of range";
jamboree7487bde2015-06-10 09:32:59 +0800880 break;
881 case Arg::NAMED_ARG:
882 arg = *static_cast<const internal::Arg*>(arg.pointer);
883 default:
884 /*nothing*/;
885 }
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700886 return arg;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700887}
888
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700889inline Arg fmt::internal::FormatterBase::next_arg(const char *&error) {
Victor Zverovich605d2602014-08-29 07:45:55 -0700890 if (next_arg_index_ >= 0)
891 return do_get_arg(next_arg_index_++, error);
892 error = "cannot switch from manual to automatic argument indexing";
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700893 return Arg();
Victor Zverovich605d2602014-08-29 07:45:55 -0700894}
895
vitautfccff7b2015-06-11 07:19:00 -0700896inline bool fmt::internal::FormatterBase::check_no_auto_index(
897 const char *&error) {
jamboree7487bde2015-06-10 09:32:59 +0800898 if (next_arg_index_ > 0) {
899 error = "cannot switch from automatic to manual argument indexing";
900 return false;
901 }
vitautfccff7b2015-06-11 07:19:00 -0700902 next_arg_index_ = -1;
jamboree7487bde2015-06-10 09:32:59 +0800903 return true;
904}
905
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700906inline Arg fmt::internal::FormatterBase::get_arg(
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700907 unsigned arg_index, const char *&error) {
vitautfccff7b2015-06-11 07:19:00 -0700908 return check_no_auto_index(error) ? do_get_arg(arg_index, error) : Arg();
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700909}
910
Victor Zverovich7cae7632013-09-06 20:23:42 -0700911template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700912void fmt::internal::PrintfFormatter<Char>::parse_flags(
Victor Zverovichcb743c02014-06-19 07:40:35 -0700913 FormatSpec &spec, const Char *&s) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700914 for (;;) {
Victor Zverovich1b801482014-06-07 08:57:55 -0700915 switch (*s++) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700916 case '-':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700917 spec.align_ = ALIGN_LEFT;
918 break;
919 case '+':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700920 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
921 break;
922 case '0':
923 spec.fill_ = '0';
Victor Zverovich1b801482014-06-07 08:57:55 -0700924 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700925 case ' ':
Victor Zverovich1b801482014-06-07 08:57:55 -0700926 spec.flags_ |= SIGN_FLAG;
927 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700928 case '#':
Victor Zverovichcb743c02014-06-19 07:40:35 -0700929 spec.flags_ |= HASH_FLAG;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700930 break;
931 default:
Victor Zverovich1b801482014-06-07 08:57:55 -0700932 --s;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700933 return;
934 }
935 }
936}
937
Victor Zverovichcb743c02014-06-19 07:40:35 -0700938template <typename Char>
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700939Arg fmt::internal::PrintfFormatter<Char>::get_arg(
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700940 const Char *s, unsigned arg_index) {
Carter Li2d4631a2015-03-14 14:54:37 +0800941 (void)s;
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700942 const char *error = 0;
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700943 Arg arg = arg_index == UINT_MAX ?
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700944 next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
945 if (error)
Victor Zverovich8b76e972014-10-06 08:30:55 -0700946 FMT_THROW(FormatError(!*s ? "invalid format string" : error));
Victor Zverovichbeb00ed2014-09-23 07:59:43 -0700947 return arg;
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700948}
949
950template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700951unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700952 const Char *&s, FormatSpec &spec) {
Victor Zverovichcb743c02014-06-19 07:40:35 -0700953 unsigned arg_index = UINT_MAX;
954 Char c = *s;
955 if (c >= '0' && c <= '9') {
956 // Parse an argument index (if followed by '$') or a width possibly
Victor Zverovich879838a2014-06-20 07:34:02 -0700957 // preceded with '0' flag(s).
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700958 unsigned value = parse_nonnegative_int(s);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700959 if (*s == '$') { // value is an argument index
960 ++s;
961 arg_index = value;
962 } else {
963 if (c == '0')
964 spec.fill_ = '0';
965 if (value != 0) {
966 // Nonzero value means that we parsed width and don't need to
967 // parse it or flags again, so return now.
968 spec.width_ = value;
969 return arg_index;
970 }
971 }
972 }
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700973 parse_flags(spec, s);
Victor Zverovich4099a122014-06-23 08:10:50 -0700974 // Parse width.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700975 if (*s >= '0' && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700976 spec.width_ = parse_nonnegative_int(s);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700977 } else if (*s == '*') {
978 ++s;
Victor Zverovich56fc5252014-08-28 07:48:55 -0700979 spec.width_ = WidthHandler(spec).visit(get_arg(s));
Victor Zverovichcb743c02014-06-19 07:40:35 -0700980 }
981 return arg_index;
982}
983
Victor Zverovich1f19b982014-06-16 07:49:30 -0700984template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700985void fmt::internal::PrintfFormatter<Char>::format(
vitaut20003762015-07-28 08:09:29 -0700986 BasicWriter<Char> &writer, BasicCStringRef<Char> format_str) {
Victor Zverovichf9fc8fd2014-12-09 07:45:54 -0800987 const Char *start = format_str.c_str();
Victor Zverovich7cae7632013-09-06 20:23:42 -0700988 const Char *s = start;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700989 while (*s) {
Victor Zverovich0fc73162013-09-07 12:52:52 -0700990 Char c = *s++;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700991 if (c != '%') continue;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700992 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -0700993 write(writer, start, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700994 start = ++s;
995 continue;
996 }
Victor Zverovichc1db2932014-07-24 08:53:27 -0700997 write(writer, start, s - 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700998
Victor Zverovichcb743c02014-06-19 07:40:35 -0700999 FormatSpec spec;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001000 spec.align_ = ALIGN_RIGHT;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001001
Victor Zverovich1a75ed02014-06-23 07:16:46 -07001002 // Parse argument index, flags and width.
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001003 unsigned arg_index = parse_header(s, spec);
Victor Zverovich1a75ed02014-06-23 07:16:46 -07001004
1005 // Parse precision.
1006 if (*s == '.') {
1007 ++s;
1008 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -07001009 spec.precision_ = parse_nonnegative_int(s);
Victor Zverovich1a75ed02014-06-23 07:16:46 -07001010 } else if (*s == '*') {
1011 ++s;
Victor Zverovich56fc5252014-08-28 07:48:55 -07001012 spec.precision_ = PrecisionHandler().visit(get_arg(s));
Victor Zverovich1a75ed02014-06-23 07:16:46 -07001013 }
1014 }
1015
Victor Zverovich56fc5252014-08-28 07:48:55 -07001016 Arg arg = get_arg(s, arg_index);
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -07001017 if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
Victor Zverovichcb743c02014-06-19 07:40:35 -07001018 spec.flags_ &= ~HASH_FLAG;
1019 if (spec.fill_ == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001020 if (arg.type <= Arg::LAST_NUMERIC_TYPE)
Victor Zverovichcb743c02014-06-19 07:40:35 -07001021 spec.align_ = ALIGN_NUMERIC;
1022 else
1023 spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001024 }
1025
Victor Zverovichf4156b52014-07-30 08:39:07 -07001026 // Parse length and convert the argument to the required type.
Victor Zverovich316ae7e2014-08-09 10:04:35 -07001027 switch (*s++) {
1028 case 'h':
Victor Zverovichf4156b52014-07-30 08:39:07 -07001029 if (*s == 'h')
1030 ArgConverter<signed char>(arg, *++s).visit(arg);
Victor Zverovich39b09302014-07-30 08:08:08 -07001031 else
Victor Zverovichf4156b52014-07-30 08:39:07 -07001032 ArgConverter<short>(arg, *s).visit(arg);
Victor Zverovicheeca2232014-07-30 07:37:16 -07001033 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001034 case 'l':
Victor Zverovichd3a70392014-08-12 08:36:19 -07001035 if (*s == 'l')
Victor Zveroviche488a282014-08-13 06:53:43 -07001036 ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
Victor Zverovichd3a70392014-08-12 08:36:19 -07001037 else
1038 ArgConverter<long>(arg, *s).visit(arg);
Victor Zverovichd81fafc2014-07-31 07:43:14 -07001039 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001040 case 'j':
Victor Zverovich316ae7e2014-08-09 10:04:35 -07001041 ArgConverter<intmax_t>(arg, *s).visit(arg);
1042 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001043 case 'z':
vitaut7dcf0512015-11-13 06:52:13 -08001044 ArgConverter<std::size_t>(arg, *s).visit(arg);
Victor Zverovich316ae7e2014-08-09 10:04:35 -07001045 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001046 case 't':
vitaut7dcf0512015-11-13 06:52:13 -08001047 ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
Victor Zverovich316ae7e2014-08-09 10:04:35 -07001048 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001049 case 'L':
Victor Zverovichc4a4a052014-08-19 08:14:21 -07001050 // printf produces garbage when 'L' is omitted for long double, no
1051 // need to do the same.
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001052 break;
Victor Zverovich316ae7e2014-08-09 10:04:35 -07001053 default:
1054 --s;
Victor Zverovichbe00d8b2014-08-19 08:49:10 -07001055 ArgConverter<int>(arg, *s).visit(arg);
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001056 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001057
1058 // Parse type.
1059 if (!*s)
Victor Zverovich8b76e972014-10-06 08:30:55 -07001060 FMT_THROW(FormatError("invalid format string"));
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001061 spec.type_ = static_cast<char>(*s++);
Victor Zverovichc4a4a052014-08-19 08:14:21 -07001062 if (arg.type <= Arg::LAST_INTEGER_TYPE) {
1063 // Normalize type.
1064 switch (spec.type_) {
1065 case 'i': case 'u':
Victor Zverovichf4156b52014-07-30 08:39:07 -07001066 spec.type_ = 'd';
Victor Zverovichc4a4a052014-08-19 08:14:21 -07001067 break;
1068 case 'c':
1069 // TODO: handle wchar_t
1070 CharConverter(arg).visit(arg);
1071 break;
1072 }
Victor Zverovichf4156b52014-07-30 08:39:07 -07001073 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001074
1075 start = s;
1076
1077 // Format argument.
vitaut270069b2015-06-16 07:36:32 -07001078 internal::PrintfArgFormatter<Char>(writer, spec).visit(arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001079 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001080 write(writer, start, s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001081}
1082
1083template <typename Char>
Victor Zverovichb9a06ba2014-07-08 16:38:50 -07001084const Char *fmt::BasicFormatter<Char>::format(
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001085 const Char *&format_str, const Arg &arg) {
Victor Zveroviche8251562014-07-08 16:20:33 -07001086 const Char *s = format_str;
Victor Zveroviche8251562014-07-08 16:20:33 -07001087 FormatSpec spec;
1088 if (*s == ':') {
1089 if (arg.type == Arg::CUSTOM) {
Victor Zverovich271fa8c2014-08-29 07:23:54 -07001090 arg.custom.format(this, arg.custom.value, &s);
1091 return s;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001092 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001093 ++s;
1094 // Parse fill and alignment.
1095 if (Char c = *s) {
1096 const Char *p = s + 1;
1097 spec.align_ = ALIGN_DEFAULT;
1098 do {
1099 switch (*p) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001100 case '<':
1101 spec.align_ = ALIGN_LEFT;
1102 break;
1103 case '>':
1104 spec.align_ = ALIGN_RIGHT;
1105 break;
1106 case '=':
1107 spec.align_ = ALIGN_NUMERIC;
1108 break;
1109 case '^':
1110 spec.align_ = ALIGN_CENTER;
1111 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001112 }
1113 if (spec.align_ != ALIGN_DEFAULT) {
1114 if (p != s) {
1115 if (c == '}') break;
1116 if (c == '{')
Victor Zverovich8b76e972014-10-06 08:30:55 -07001117 FMT_THROW(FormatError("invalid fill character '{'"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001118 s += 2;
1119 spec.fill_ = c;
1120 } else ++s;
Victor Zverovich5debb2a2014-08-29 08:16:10 -07001121 if (spec.align_ == ALIGN_NUMERIC)
1122 require_numeric_argument(arg, '=');
Victor Zveroviche8251562014-07-08 16:20:33 -07001123 break;
1124 }
1125 } while (--p >= s);
1126 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001127
Victor Zveroviche8251562014-07-08 16:20:33 -07001128 // Parse sign.
1129 switch (*s) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001130 case '+':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001131 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001132 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
1133 break;
1134 case '-':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001135 check_sign(s, arg);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001136 spec.flags_ |= MINUS_FLAG;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001137 break;
1138 case ' ':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001139 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001140 spec.flags_ |= SIGN_FLAG;
1141 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001142 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001143
Victor Zveroviche8251562014-07-08 16:20:33 -07001144 if (*s == '#') {
Victor Zverovich5debb2a2014-08-29 08:16:10 -07001145 require_numeric_argument(arg, '#');
Victor Zveroviche8251562014-07-08 16:20:33 -07001146 spec.flags_ |= HASH_FLAG;
1147 ++s;
1148 }
1149
jamboree54a6cb32015-06-04 13:59:37 +08001150 // Parse zero flag.
1151 if (*s == '0') {
vitaut8949a2e2015-06-08 06:53:18 -07001152 require_numeric_argument(arg, '0');
1153 spec.align_ = ALIGN_NUMERIC;
1154 spec.fill_ = '0';
1155 ++s;
jamboree54a6cb32015-06-04 13:59:37 +08001156 }
1157
1158 // Parse width.
1159 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -07001160 spec.width_ = parse_nonnegative_int(s);
jamboree54a6cb32015-06-04 13:59:37 +08001161 } else if (*s == '{') {
vitaut8949a2e2015-06-08 06:53:18 -07001162 ++s;
vitautfccff7b2015-06-11 07:19:00 -07001163 Arg width_arg = is_name_start(*s) ?
1164 parse_arg_name(s) : parse_arg_index(s);
vitaut8949a2e2015-06-08 06:53:18 -07001165 if (*s++ != '}')
1166 FMT_THROW(FormatError("invalid format string"));
1167 ULongLong value = 0;
1168 switch (width_arg.type) {
1169 case Arg::INT:
1170 if (width_arg.int_value < 0)
1171 FMT_THROW(FormatError("negative width"));
1172 value = width_arg.int_value;
1173 break;
1174 case Arg::UINT:
1175 value = width_arg.uint_value;
1176 break;
1177 case Arg::LONG_LONG:
1178 if (width_arg.long_long_value < 0)
1179 FMT_THROW(FormatError("negative width"));
1180 value = width_arg.long_long_value;
1181 break;
1182 case Arg::ULONG_LONG:
1183 value = width_arg.ulong_long_value;
1184 break;
1185 default:
1186 FMT_THROW(FormatError("width is not integer"));
1187 }
1188 if (value > INT_MAX)
1189 FMT_THROW(FormatError("number is too big"));
1190 spec.width_ = static_cast<int>(value);
Victor Zveroviche8251562014-07-08 16:20:33 -07001191 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001192
Victor Zveroviche8251562014-07-08 16:20:33 -07001193 // Parse precision.
1194 if (*s == '.') {
1195 ++s;
1196 spec.precision_ = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001197 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -07001198 spec.precision_ = parse_nonnegative_int(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001199 } else if (*s == '{') {
Victor Zverovich7cae7632013-09-06 20:23:42 -07001200 ++s;
vitautfccff7b2015-06-11 07:19:00 -07001201 Arg precision_arg =
1202 is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s);
Victor Zverovich42de4f12014-08-27 08:24:31 -07001203 if (*s++ != '}')
Victor Zverovich8b76e972014-10-06 08:30:55 -07001204 FMT_THROW(FormatError("invalid format string"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001205 ULongLong value = 0;
1206 switch (precision_arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001207 case Arg::INT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001208 if (precision_arg.int_value < 0)
Victor Zverovich8b76e972014-10-06 08:30:55 -07001209 FMT_THROW(FormatError("negative precision"));
Victor Zverovich7cae7632013-09-06 20:23:42 -07001210 value = precision_arg.int_value;
1211 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001212 case Arg::UINT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001213 value = precision_arg.uint_value;
1214 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001215 case Arg::LONG_LONG:
Victor Zverovich56f12b72013-11-22 07:45:43 -08001216 if (precision_arg.long_long_value < 0)
Victor Zverovich8b76e972014-10-06 08:30:55 -07001217 FMT_THROW(FormatError("negative precision"));
Victor Zverovich56f12b72013-11-22 07:45:43 -08001218 value = precision_arg.long_long_value;
1219 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001220 case Arg::ULONG_LONG:
Gregory Czajkowskia65542b2013-11-18 22:58:39 -08001221 value = precision_arg.ulong_long_value;
Victor Zverovicha4e72b42013-11-21 09:11:58 -08001222 break;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001223 default:
Victor Zverovich8b76e972014-10-06 08:30:55 -07001224 FMT_THROW(FormatError("precision is not integer"));
Victor Zverovich7cae7632013-09-06 20:23:42 -07001225 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001226 if (value > INT_MAX)
Victor Zverovich8b76e972014-10-06 08:30:55 -07001227 FMT_THROW(FormatError("number is too big"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001228 spec.precision_ = static_cast<int>(value);
Victor Zveroviche8251562014-07-08 16:20:33 -07001229 } else {
Victor Zverovich8b76e972014-10-06 08:30:55 -07001230 FMT_THROW(FormatError("missing precision specifier"));
Victor Zverovich7cae7632013-09-06 20:23:42 -07001231 }
vitautfd5c2e92015-06-11 08:58:31 -07001232 if (arg.type <= Arg::LAST_INTEGER_TYPE || arg.type == Arg::POINTER) {
Victor Zverovich8b76e972014-10-06 08:30:55 -07001233 FMT_THROW(FormatError(
Victor Zverovich43aebf52015-01-08 07:56:08 -08001234 fmt::format("precision not allowed in {} format specifier",
1235 arg.type == Arg::POINTER ? "pointer" : "integer")));
Victor Zveroviche8251562014-07-08 16:20:33 -07001236 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001237 }
1238
Victor Zveroviche8251562014-07-08 16:20:33 -07001239 // Parse type.
1240 if (*s != '}' && *s)
1241 spec.type_ = static_cast<char>(*s++);
1242 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001243
Victor Zveroviche8251562014-07-08 16:20:33 -07001244 if (*s++ != '}')
Victor Zverovich8b76e972014-10-06 08:30:55 -07001245 FMT_THROW(FormatError("missing '}' in format string"));
Victor Zveroviche8251562014-07-08 16:20:33 -07001246
1247 // Format argument.
Victor Zverovich4edc88f2014-07-16 08:38:15 -07001248 internal::ArgFormatter<Char>(*this, spec, s - 1).visit(arg);
Victor Zveroviche8251562014-07-08 16:20:33 -07001249 return s;
1250}
1251
1252template <typename Char>
vitaut20003762015-07-28 08:09:29 -07001253void fmt::BasicFormatter<Char>::format(BasicCStringRef<Char> format_str) {
vitaut0eac0372015-07-28 06:46:41 -07001254 const Char *s = format_str.c_str();
1255 const Char *start = s;
Victor Zveroviche8251562014-07-08 16:20:33 -07001256 while (*s) {
1257 Char c = *s++;
1258 if (c != '{' && c != '}') continue;
1259 if (*s == c) {
vitaut0eac0372015-07-28 06:46:41 -07001260 write(writer_, start, s);
1261 start = ++s;
Victor Zveroviche8251562014-07-08 16:20:33 -07001262 continue;
1263 }
1264 if (c == '}')
Victor Zverovich8b76e972014-10-06 08:30:55 -07001265 FMT_THROW(FormatError("unmatched '}' in format string"));
vitaut0eac0372015-07-28 06:46:41 -07001266 write(writer_, start, s - 1);
jamboree7487bde2015-06-10 09:32:59 +08001267 Arg arg = is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s);
vitaut0eac0372015-07-28 06:46:41 -07001268 start = s = format(s, arg);
Victor Zveroviche8251562014-07-08 16:20:33 -07001269 }
vitaut0eac0372015-07-28 06:46:41 -07001270 write(writer_, start, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001271}
1272
Victor Zverovichd9c605c2014-11-28 06:40:57 -08001273FMT_FUNC void fmt::report_system_error(
Carter Lie2583ab2015-02-14 09:58:29 +08001274 int error_code, fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001275 report_error(internal::format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001276}
1277
vitaut24c309f2015-06-12 07:15:57 -07001278#if FMT_USE_WINDOWS_H
Victor Zverovichb49a1b42014-12-09 06:32:07 -08001279FMT_FUNC void fmt::report_windows_error(
Carter Lie2583ab2015-02-14 09:58:29 +08001280 int error_code, fmt::StringRef message) FMT_NOEXCEPT {
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001281 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001282}
Victor Zverovich400812a2014-04-30 12:38:17 -07001283#endif
Victor Zverovichf7939862014-04-30 10:18:11 -07001284
vitaut438bd9b2015-06-26 07:43:54 -07001285FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args) {
Victor Zverovichd1ded562014-09-29 08:48:16 -07001286 MemoryWriter w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001287 w.write(format_str, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001288 std::fwrite(w.data(), 1, w.size(), f);
1289}
1290
vitaut438bd9b2015-06-26 07:43:54 -07001291FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) {
Victor Zverovich163178e2014-09-25 07:08:25 -07001292 print(stdout, format_str, args);
1293}
1294
vitaut438bd9b2015-06-26 07:43:54 -07001295FMT_FUNC void fmt::print(std::ostream &os, CStringRef format_str, ArgList args) {
Victor Zverovichd1ded562014-09-29 08:48:16 -07001296 MemoryWriter w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001297 w.write(format_str, args);
Victor Zveroviche3a44c12014-07-09 06:56:36 -07001298 os.write(w.data(), w.size());
1299}
1300
vitaut438bd9b2015-06-26 07:43:54 -07001301FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
Victor Zverovich2dc108b2014-07-01 09:10:43 -07001302 char escape[] = "\x1b[30m";
Ingo van Lilf4d88842015-11-02 19:14:47 +01001303 escape[3] = static_cast<char>('0' + c);
Victor Zverovich2dc108b2014-07-01 09:10:43 -07001304 std::fputs(escape, stdout);
1305 print(format, args);
1306 std::fputs(RESET_COLOR, stdout);
1307}
1308
vitaut438bd9b2015-06-26 07:43:54 -07001309FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) {
Victor Zverovichd1ded562014-09-29 08:48:16 -07001310 MemoryWriter w;
Victor Zverovich21111cc2014-06-29 19:52:26 -07001311 printf(w, format, args);
Victor Zverovich615c1ee2014-11-14 09:40:01 -08001312 std::size_t size = w.size();
1313 return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001314}
1315
Victor Zverovichc09c42f2015-03-01 09:43:33 -08001316#ifndef FMT_HEADER_ONLY
1317
vitaut9ca1ce22015-05-23 08:04:06 -07001318template struct fmt::internal::BasicData<void>;
vitaut804a74c2015-05-14 12:58:42 -07001319
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001320// Explicit instantiations for char.
1321
Victor Zverovich7c0d5752015-03-01 18:19:56 -08001322template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
1323
Victor Zverovichf43caef2014-09-25 07:21:48 -07001324template const char *fmt::BasicFormatter<char>::format(
1325 const char *&format_str, const fmt::internal::Arg &arg);
1326
vitaut20003762015-07-28 08:09:29 -07001327template void fmt::BasicFormatter<char>::format(CStringRef format);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001328
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001329template void fmt::internal::PrintfFormatter<char>::format(
vitaut20003762015-07-28 08:09:29 -07001330 BasicWriter<char> &writer, CStringRef format);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001331
Victor Zverovich14f25772014-09-19 08:45:05 -07001332template int fmt::internal::CharTraits<char>::format_float(
1333 char *buffer, std::size_t size, const char *format,
1334 unsigned width, int precision, double value);
1335
1336template int fmt::internal::CharTraits<char>::format_float(
1337 char *buffer, std::size_t size, const char *format,
1338 unsigned width, int precision, long double value);
1339
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001340// Explicit instantiations for wchar_t.
1341
Victor Zverovich7c0d5752015-03-01 18:19:56 -08001342template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
1343
Victor Zverovichf43caef2014-09-25 07:21:48 -07001344template const wchar_t *fmt::BasicFormatter<wchar_t>::format(
1345 const wchar_t *&format_str, const fmt::internal::Arg &arg);
1346
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001347template void fmt::BasicFormatter<wchar_t>::format(
vitaut20003762015-07-28 08:09:29 -07001348 BasicCStringRef<wchar_t> format);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001349
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001350template void fmt::internal::PrintfFormatter<wchar_t>::format(
vitaut20003762015-07-28 08:09:29 -07001351 BasicWriter<wchar_t> &writer, WCStringRef format);
jdale88a9862fd2014-03-11 18:56:24 +00001352
Victor Zverovich14f25772014-09-19 08:45:05 -07001353template int fmt::internal::CharTraits<wchar_t>::format_float(
1354 wchar_t *buffer, std::size_t size, const wchar_t *format,
1355 unsigned width, int precision, double value);
1356
1357template int fmt::internal::CharTraits<wchar_t>::format_float(
1358 wchar_t *buffer, std::size_t size, const wchar_t *format,
1359 unsigned width, int precision, long double value);
1360
Victor Zverovichc09c42f2015-03-01 09:43:33 -08001361#endif // FMT_HEADER_ONLY
1362
Ingo van Lilb4b13ee2015-11-02 12:34:46 +01001363#ifdef _MSC_VER
jdale88a9862fd2014-03-11 18:56:24 +00001364# pragma warning(pop)
1365#endif