blob: 64c24fb81699c81d78495a4a96f4e8aa492f5d63 [file] [log] [blame]
Victor Zverovichb076df42012-12-07 08:31:09 -08001/*
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07002 Formatting library for C++
Victor Zverovichfaccb4c2012-12-12 07:44:41 -08003
Victor Zveroviche3a44c12014-07-09 06:56:36 -07004 Copyright (c) 2012 - 2014, Victor Zverovich
Victor Zverovichfaccb4c2012-12-12 07:44:41 -08005 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 1. Redistributions of source code must retain the above copyright notice, this
11 list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Victor Zverovichb076df42012-12-07 08:31:09 -080026 */
27
Victor Zverovichd53f2092012-12-16 15:06:31 -080028// Disable useless MSVC warnings.
Victor Zverovichf8c91062012-12-17 15:41:00 -080029#undef _CRT_SECURE_NO_WARNINGS
Victor Zverovichd53f2092012-12-16 15:06:31 -080030#define _CRT_SECURE_NO_WARNINGS
Victor Zverovichc240a122012-12-21 15:02:25 -080031#undef _SCL_SECURE_NO_WARNINGS
32#define _SCL_SECURE_NO_WARNINGS
Victor Zverovichd53f2092012-12-16 15:06:31 -080033
Victor Zverovichfbfedcf2013-01-14 15:16:20 -080034#include "format.h"
35
Victor Zverovich859a4972014-04-30 06:55:21 -070036#include <string.h>
37
Victor Zverovich72f896d2012-12-12 09:17:28 -080038#include <cctype>
Victor Zverovich5d15bdd2014-07-01 16:23:50 -070039#include <cerrno>
Victor Zverovichf28645f2014-04-24 12:37:06 -070040#include <climits>
Victor Zverovich9ff3b972013-09-07 10:15:08 -070041#include <cmath>
Victor Zverovicha684d0c2013-12-27 08:00:10 -080042#include <cstdarg>
Victor Zverovich9ff3b972013-09-07 10:15:08 -070043
Victor Zverovich859a4972014-04-30 06:55:21 -070044#ifdef _WIN32
Victor Zverovichdcd039d2014-05-01 07:09:42 -070045# define WIN32_LEAN_AND_MEAN
Constantine Tarasenkov6aace692014-06-11 02:38:57 +040046# ifdef __MINGW32__
47# include <cstring>
48# endif
Victor Zverovich859a4972014-04-30 06:55:21 -070049# include <windows.h>
Victor Zveroviched2bdba2014-04-30 07:41:54 -070050# undef ERROR
Victor Zverovich859a4972014-04-30 06:55:21 -070051#endif
52
Victor Zverovich591ad0a2014-07-14 06:55:29 -070053using fmt::LongLong;
Victor Zverovich447e02c2014-02-15 10:48:34 -080054using fmt::ULongLong;
Victor Zverovich6e5551e2014-07-02 06:33:25 -070055using fmt::internal::Arg;
Victor Zverovich447e02c2014-02-15 10:48:34 -080056
jdale88a9862fd2014-03-11 18:56:24 +000057#if _MSC_VER
58# pragma warning(push)
59# pragma warning(disable: 4127) // conditional expression is constant
60#endif
61
Victor Zverovich9ff3b972013-09-07 10:15:08 -070062namespace {
63
64#ifndef _MSC_VER
Victor Zverovichb9a568b2014-09-19 07:51:42 -070065# define FMT_SNPRINTF snprintf
Victor Zverovicha684d0c2013-12-27 08:00:10 -080066#else // _MSC_VER
Victor Zverovich406c6122014-08-19 08:47:38 -070067inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -080068 va_list args;
69 va_start(args, format);
70 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
71 va_end(args);
72 return result;
73}
Victor Zverovichb9a568b2014-09-19 07:51:42 -070074# define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -070075#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -080076
Victor Zverovichadce0242014-08-17 07:53:55 -070077// Checks if a value fits in int - used to avoid warnings about comparing
78// signed and unsigned integers.
79template <bool IsSigned>
80struct IntChecker {
81 template <typename T>
82 static bool fits_in_int(T value) {
83 unsigned max = INT_MAX;
84 return value <= max;
85 }
86};
87
88template <>
89struct IntChecker<true> {
90 template <typename T>
91 static bool fits_in_int(T value) {
92 return value >= INT_MIN && value <= INT_MAX;
93 }
94};
95
Victor Zverovich43fe1002014-02-19 14:20:26 -080096const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -070097
Victor Zverovich22f75d82014-09-03 08:03:05 -070098typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
99
Victor Zverovichf2c9df82014-09-05 08:44:41 -0700100// Portable thread-safe version of strerror.
101// Sets buffer to point to a string describing the error code.
102// This can be either a pointer to a string stored in buffer,
103// or a pointer to some static immutable string.
104// Returns one of the following values:
105// 0 - success
106// ERANGE - buffer is not large enough to store the error message
107// other - failure
108// Buffer should be at least of size 1.
109int safe_strerror(
110 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT(true) {
111 assert(buffer != 0 && buffer_size != 0);
112 int result = 0;
113#ifdef _GNU_SOURCE
114 char *message = strerror_r(error_code, buffer, buffer_size);
115 // If the buffer is full then the message is probably truncated.
116 if (message == buffer && strlen(buffer) == buffer_size - 1)
117 result = ERANGE;
118 buffer = message;
119#elif __MINGW32__
120 errno = 0;
121 (void)buffer_size;
122 buffer = strerror(error_code);
123 result = errno;
124#elif _WIN32
125 result = strerror_s(buffer, buffer_size, error_code);
126 // If the buffer is full then the message is probably truncated.
127 if (result == 0 && std::strlen(buffer) == buffer_size - 1)
128 result = ERANGE;
129#else
130 result = strerror_r(error_code, buffer, buffer_size);
131 if (result == -1)
132 result = errno; // glibc versions before 2.13 return result in errno.
133#endif
134 return result;
135}
136
Victor Zverovich22f75d82014-09-03 08:03:05 -0700137void format_error_code(fmt::Writer &out, int error_code,
138 fmt::StringRef message) FMT_NOEXCEPT(true) {
139 // Report error code making sure that the output fits into
140 // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
141 // bad_alloc.
142 out.clear();
143 static const char SEP[] = ": ";
144 static const char ERROR[] = "error ";
Victor Zverovich22f75d82014-09-03 08:03:05 -0700145 fmt::internal::IntTraits<int>::MainType ec_value = error_code;
Victor Zverovich88e0db82014-09-05 08:04:26 -0700146 // Subtract 2 to account for terminating null characters in SEP and ERROR.
Victor Zverovich22f75d82014-09-03 08:03:05 -0700147 std::size_t error_code_size =
Victor Zverovich88e0db82014-09-05 08:04:26 -0700148 sizeof(SEP) + sizeof(ERROR) + fmt::internal::count_digits(ec_value) - 2;
149 if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size)
Victor Zverovich22f75d82014-09-03 08:03:05 -0700150 out << message << SEP;
151 out << ERROR << error_code;
152 assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE);
153}
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700154
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700155void report_error(FormatFunc func,
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700156 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
Victor Zverovich88e0db82014-09-05 08:04:26 -0700157 fmt::Writer full_message;
158 func(full_message, error_code, message);
159 // Use Writer::data instead of Writer::c_str to avoid potential memory
160 // allocation.
161 std::fwrite(full_message.data(), full_message.size(), 1, stderr);
162 std::fputc('\n', stderr);
Victor Zverovichb605b392013-09-09 22:21:40 -0700163}
Victor Zverovichd29e5052014-06-30 07:12:09 -0700164
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700165// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
166class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> {
167 public:
168 template <typename T>
169 bool visit_any_int(T value) { return value == 0; }
170};
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700171
172// Parses an unsigned integer advancing s to the end of the parsed input.
173// This function assumes that the first character of s is a digit.
174template <typename Char>
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700175int parse_nonnegative_int(const Char *&s) {
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700176 assert('0' <= *s && *s <= '9');
177 unsigned value = 0;
178 do {
179 unsigned new_value = value * 10 + (*s++ - '0');
180 // Check if value wrapped around.
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700181 if (new_value < value) {
182 value = UINT_MAX;
183 break;
184 }
185 value = new_value;
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700186 } while ('0' <= *s && *s <= '9');
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700187 if (value > INT_MAX)
Victor Zverovich279c7a62014-08-28 06:50:52 -0700188 throw fmt::FormatError("number is too big");
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700189 return value;
190}
Victor Zveroviche8251562014-07-08 16:20:33 -0700191
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700192inline void require_numeric_argument(const Arg &arg, char spec) {
193 if (arg.type > Arg::LAST_NUMERIC_TYPE) {
194 throw fmt::FormatError(
195 fmt::format("format specifier '{}' requires numeric argument", spec));
196 }
197}
198
Victor Zveroviche8251562014-07-08 16:20:33 -0700199template <typename Char>
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700200void check_sign(const Char *&s, const Arg &arg) {
201 char sign = static_cast<char>(*s);
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700202 require_numeric_argument(arg, sign);
Victor Zverovich3947a7a2014-08-29 06:57:53 -0700203 if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
204 throw fmt::FormatError(fmt::format(
205 "format specifier '{}' requires signed argument", sign));
206 }
207 ++s;
208}
209
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700210// Checks if an argument is a valid printf width specifier and sets
211// left alignment if it is negative.
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700212class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700213 private:
214 fmt::FormatSpec &spec_;
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700215
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700216 public:
217 explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700218
Victor Zverovich9d74f952014-07-16 07:27:54 -0700219 unsigned visit_unhandled_arg() {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700220 throw fmt::FormatError("width is not integer");
221 }
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700222
Victor Zverovich9d74f952014-07-16 07:27:54 -0700223 template <typename T>
224 unsigned visit_any_int(T value) {
225 typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType;
226 UnsignedType width = value;
227 if (fmt::internal::is_negative(value)) {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700228 spec_.align_ = fmt::ALIGN_LEFT;
229 width = 0 - width;
230 }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700231 if (width > INT_MAX)
Victor Zverovich279c7a62014-08-28 06:50:52 -0700232 throw fmt::FormatError("number is too big");
Victor Zverovich9d74f952014-07-16 07:27:54 -0700233 return static_cast<unsigned>(width);
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700234 }
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700235};
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700236
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700237class PrecisionHandler :
238 public fmt::internal::ArgVisitor<PrecisionHandler, int> {
239 public:
240 unsigned visit_unhandled_arg() {
241 throw fmt::FormatError("precision is not integer");
242 }
243
244 template <typename T>
245 int visit_any_int(T value) {
Victor Zverovichadce0242014-08-17 07:53:55 -0700246 if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
Victor Zverovich279c7a62014-08-28 06:50:52 -0700247 throw fmt::FormatError("number is too big");
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700248 return static_cast<int>(value);
249 }
250};
251
Victor Zverovich32344d92014-08-28 08:11:21 -0700252// Converts an integer argument to an integral type T for printf.
Victor Zverovicheeca2232014-07-30 07:37:16 -0700253template <typename T>
254class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
255 private:
256 fmt::internal::Arg &arg_;
Victor Zveroviche22d6572014-08-08 06:51:09 -0700257 wchar_t type_;
Victor Zverovicheeca2232014-07-30 07:37:16 -0700258
259 public:
Victor Zveroviche22d6572014-08-08 06:51:09 -0700260 ArgConverter(fmt::internal::Arg &arg, wchar_t type)
261 : arg_(arg), type_(type) {}
Victor Zverovicheeca2232014-07-30 07:37:16 -0700262
263 template <typename U>
264 void visit_any_int(U value) {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700265 bool is_signed = type_ == 'd' || type_ == 'i';
266 using fmt::internal::Arg;
267 if (sizeof(T) <= sizeof(int)) {
Victor Zverovich32344d92014-08-28 08:11:21 -0700268 // Extra casts are used to silence warnings.
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700269 if (is_signed) {
270 arg_.type = Arg::INT;
Victor Zverovichbb016332014-08-15 09:03:59 -0700271 arg_.int_value = static_cast<int>(static_cast<T>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700272 } else {
273 arg_.type = Arg::UINT;
Victor Zverovich186734c2014-08-18 07:03:12 -0700274 arg_.uint_value = static_cast<unsigned>(
275 static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700276 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700277 } else {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700278 if (is_signed) {
279 arg_.type = Arg::LONG_LONG;
Victor Zverovicha259c942014-08-01 07:15:27 -0700280 arg_.long_long_value =
281 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700282 } else {
283 arg_.type = Arg::ULONG_LONG;
284 arg_.ulong_long_value =
Victor Zverovicha259c942014-08-01 07:15:27 -0700285 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700286 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700287 }
288 }
289};
290
Victor Zverovich32344d92014-08-28 08:11:21 -0700291// Converts an integer argument to char for printf.
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700292class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
293 private:
294 fmt::internal::Arg &arg_;
295
296 public:
297 explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
298
299 template <typename T>
300 void visit_any_int(T value) {
301 arg_.type = Arg::CHAR;
302 arg_.int_value = static_cast<char>(value);
303 }
304};
305
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700306// This function template is used to prevent compile errors when handling
307// incompatible string arguments, e.g. handling a wide string in a narrow
308// string formatter.
309template <typename Char>
310Arg::StringValue<Char> ignore_incompatible_str(Arg::StringValue<wchar_t>);
311
312template <>
313inline Arg::StringValue<char> ignore_incompatible_str(
314 Arg::StringValue<wchar_t>) { return Arg::StringValue<char>(); }
315
316template <>
317inline Arg::StringValue<wchar_t> ignore_incompatible_str(
318 Arg::StringValue<wchar_t> s) { return s; }
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700319} // namespace
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700320
Victor Zverovich53201032014-06-30 14:26:29 -0700321void fmt::SystemError::init(
322 int error_code, StringRef format_str, const ArgList &args) {
323 error_code_ = error_code;
324 Writer w;
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700325 internal::format_system_error(w, error_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700326 std::runtime_error &base = *this;
327 base = std::runtime_error(w.str());
328}
329
Victor Zverovichb605b392013-09-09 22:21:40 -0700330template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700331int fmt::internal::CharTraits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700332 char *buffer, std::size_t size, const char *format,
333 unsigned width, int precision, T value) {
334 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700335 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700336 FMT_SNPRINTF(buffer, size, format, value) :
337 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700338 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700339 return precision < 0 ?
340 FMT_SNPRINTF(buffer, size, format, width, value) :
341 FMT_SNPRINTF(buffer, size, format, width, precision, value);
342}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700343
Victor Zverovichb605b392013-09-09 22:21:40 -0700344template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700345int fmt::internal::CharTraits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700346 wchar_t *buffer, std::size_t size, const wchar_t *format,
347 unsigned width, int precision, T value) {
348 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700349 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700350 swprintf(buffer, size, format, value) :
351 swprintf(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700352 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700353 return precision < 0 ?
354 swprintf(buffer, size, format, width, value) :
355 swprintf(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700356}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800357
Victor Zverovich65d47e52013-09-09 06:51:03 -0700358const char fmt::internal::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800359 "0001020304050607080910111213141516171819"
360 "2021222324252627282930313233343536373839"
361 "4041424344454647484950515253545556575859"
362 "6061626364656667686970717273747576777879"
363 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800364
Victor Zverovichf1d85162014-02-19 13:02:22 -0800365#define FMT_POWERS_OF_10(factor) \
366 factor * 10, \
367 factor * 100, \
368 factor * 1000, \
369 factor * 10000, \
370 factor * 100000, \
371 factor * 1000000, \
372 factor * 10000000, \
373 factor * 100000000, \
374 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800375
Victor Zverovichf1d85162014-02-19 13:02:22 -0800376const uint32_t fmt::internal::POWERS_OF_10_32[] = {0, FMT_POWERS_OF_10(1)};
Victor Zveroviche9b21912014-02-19 12:43:55 -0800377const uint64_t fmt::internal::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800378 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800379 FMT_POWERS_OF_10(1),
380 FMT_POWERS_OF_10(ULongLong(1000000000)),
Victor Zverovich406c6122014-08-19 08:47:38 -0700381 // Multiply several constants instead of using a single long long constant
Victor Zverovichf1d85162014-02-19 13:02:22 -0800382 // to avoid warnings about C++98 not supporting long long.
Victor Zverovich6f6fe512014-02-15 11:16:44 -0800383 ULongLong(1000000000) * ULongLong(1000000000) * 10
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800384};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800385
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700386void fmt::internal::report_unknown_type(char code, const char *type) {
Victor Zverovich877abaf2013-01-08 09:56:05 -0800387 if (std::isprint(static_cast<unsigned char>(code))) {
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700388 throw fmt::FormatError(
389 fmt::format("unknown format code '{}' for {}", code, type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800390 }
391 throw fmt::FormatError(
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700392 fmt::format("unknown format code '\\x{:02x}' for {}",
393 static_cast<unsigned>(code), type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800394}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700395
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700396#ifdef _WIN32
397
398fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
399 int length = MultiByteToWideChar(
400 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, 0, 0);
401 static const char ERROR[] = "cannot convert string from UTF-8 to UTF-16";
402 if (length == 0)
Victor Zverovichf4208772014-06-30 17:32:08 -0700403 throw WindowsError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700404 buffer_.resize(length);
405 length = MultiByteToWideChar(
406 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, &buffer_[0], length);
407 if (length == 0)
Victor Zverovichf4208772014-06-30 17:32:08 -0700408 throw WindowsError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700409}
410
411fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700412 if (int error_code = convert(s)) {
Victor Zverovich8321d0e2014-07-09 08:39:01 -0700413 throw WindowsError(error_code,
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700414 "cannot convert string from UTF-16 to UTF-8");
415 }
416}
417
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700418int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700419 int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, 0, 0, 0, 0);
420 if (length == 0)
421 return GetLastError();
422 buffer_.resize(length);
423 length = WideCharToMultiByte(
424 CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, 0, 0);
425 if (length == 0)
426 return GetLastError();
427 return 0;
428}
429
Victor Zverovich53201032014-06-30 14:26:29 -0700430void fmt::WindowsError::init(
431 int error_code, StringRef format_str, const ArgList &args) {
432 error_code_ = error_code;
433 Writer w;
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700434 internal::format_windows_error(w, error_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700435 std::runtime_error &base = *this;
436 base = std::runtime_error(w.str());
437}
438
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700439#endif
440
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700441void fmt::internal::format_system_error(
Victor Zverovich22f75d82014-09-03 08:03:05 -0700442 fmt::Writer &out, int error_code,
443 fmt::StringRef message) FMT_NOEXCEPT(true) {
444 try {
445 Array<char, INLINE_BUFFER_SIZE> buffer;
446 buffer.resize(INLINE_BUFFER_SIZE);
447 char *system_message = 0;
448 for (;;) {
449 system_message = &buffer[0];
450 int result = safe_strerror(error_code, system_message, buffer.size());
451 if (result == 0) {
452 out << message << ": " << system_message;
453 return;
454 }
455 if (result != ERANGE)
456 break; // Can't get error message, report error code instead.
457 buffer.resize(buffer.size() * 2);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700458 }
Victor Zverovich22f75d82014-09-03 08:03:05 -0700459 } catch (...) {}
460 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700461}
462
463#ifdef _WIN32
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700464void fmt::internal::format_windows_error(
Victor Zverovich22f75d82014-09-03 08:03:05 -0700465 fmt::Writer &out, int error_code,
466 fmt::StringRef message) FMT_NOEXCEPT(true) {
Victor Zverovich53b4c312014-04-30 15:00:41 -0700467 class String {
468 private:
469 LPWSTR str_;
470
471 public:
472 String() : str_() {}
473 ~String() { LocalFree(str_); }
474 LPWSTR *ptr() { return &str_; }
475 LPCWSTR c_str() const { return str_; }
476 };
Victor Zverovich22f75d82014-09-03 08:03:05 -0700477 try {
478 String system_message;
479 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
480 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
481 error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
482 reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
483 UTF16ToUTF8 utf8_message;
484 if (utf8_message.convert(system_message.c_str()) == ERROR_SUCCESS) {
485 out << message << ": " << utf8_message;
486 return;
487 }
Victor Zverovich53b4c312014-04-30 15:00:41 -0700488 }
Victor Zverovich22f75d82014-09-03 08:03:05 -0700489 } catch (...) {}
490 format_error_code(out, error_code, message);
Victor Zverovich53b4c312014-04-30 15:00:41 -0700491}
492#endif
493
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700494// An argument formatter.
495template <typename Char>
496class fmt::internal::ArgFormatter :
497 public fmt::internal::ArgVisitor<fmt::internal::ArgFormatter<Char>, void> {
498 private:
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700499 fmt::BasicFormatter<Char> &formatter_;
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700500 fmt::BasicWriter<Char> &writer_;
501 fmt::FormatSpec &spec_;
502 const Char *format_;
503
504 public:
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700505 ArgFormatter(
506 fmt::BasicFormatter<Char> &f,fmt::FormatSpec &s, const Char *fmt)
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700507 : formatter_(f), writer_(f.writer()), spec_(s), format_(fmt) {}
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700508
Victor Zverovich9d74f952014-07-16 07:27:54 -0700509 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700510 void visit_any_int(T value) { writer_.write_int(value, spec_); }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700511
512 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700513 void visit_any_double(T value) { writer_.write_double(value, spec_); }
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700514
515 void visit_char(int value) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700516 if (spec_.type_ && spec_.type_ != 'c') {
Victor Zverovichd699c2a2014-07-25 08:24:27 -0700517 spec_.flags_ |= CHAR_FLAG;
518 writer_.write_int(value, spec_);
519 return;
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700520 }
521 if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
522 throw FormatError("invalid format specifier for char");
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700523 typedef typename fmt::BasicWriter<Char>::CharPtr CharPtr;
524 CharPtr out = CharPtr();
525 if (spec_.width_ > 1) {
526 Char fill = static_cast<Char>(spec_.fill());
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700527 out = writer_.grow_buffer(spec_.width_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700528 if (spec_.align_ == fmt::ALIGN_RIGHT) {
529 std::fill_n(out, spec_.width_ - 1, fill);
530 out += spec_.width_ - 1;
531 } else if (spec_.align_ == fmt::ALIGN_CENTER) {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700532 out = writer_.fill_padding(out, spec_.width_, 1, fill);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700533 } else {
534 std::fill_n(out + 1, spec_.width_ - 1, fill);
535 }
536 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700537 out = writer_.grow_buffer(1);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700538 }
539 *out = static_cast<Char>(value);
540 }
541
542 void visit_string(Arg::StringValue<char> value) {
543 writer_.write_str(value, spec_);
544 }
545 void visit_wstring(Arg::StringValue<wchar_t> value) {
546 writer_.write_str(ignore_incompatible_str<Char>(value), spec_);
547 }
548
549 void visit_pointer(const void *value) {
550 if (spec_.type_ && spec_.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700551 fmt::internal::report_unknown_type(spec_.type_, "pointer");
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700552 spec_.flags_ = fmt::HASH_FLAG;
553 spec_.type_ = 'x';
Victor Zverovichc1db2932014-07-24 08:53:27 -0700554 writer_.write_int(reinterpret_cast<uintptr_t>(value), spec_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700555 }
556
557 void visit_custom(Arg::CustomValue c) {
Victor Zverovich271fa8c2014-08-29 07:23:54 -0700558 c.format(&formatter_, c.value, &format_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700559 }
560};
561
Victor Zverovichb9a568b2014-09-19 07:51:42 -0700562template <typename Char, typename Allocator>
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700563template <typename StrChar>
Victor Zverovichb9a568b2014-09-19 07:51:42 -0700564void fmt::BasicWriter<Char, Allocator>::write_str(
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700565 const Arg::StringValue<StrChar> &str, const FormatSpec &spec) {
566 // Check if StrChar is convertible to Char.
567 internal::CharTraits<Char>::convert(StrChar());
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700568 if (spec.type_ && spec.type_ != 's')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700569 internal::report_unknown_type(spec.type_, "string");
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700570 const StrChar *s = str.value;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700571 std::size_t size = str.size;
572 if (size == 0) {
573 if (!s)
574 throw FormatError("string pointer is null");
575 if (*s)
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700576 size = std::char_traits<StrChar>::length(s);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700577 }
Victor Zverovich53201032014-06-30 14:26:29 -0700578 write_str(s, size, spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700579}
580
581template <typename Char>
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700582inline const Arg &fmt::BasicFormatter<Char>::parse_arg_index(const Char *&s) {
Victor Zverovich9646e382014-08-27 09:13:42 -0700583 const char *error = 0;
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700584 const Arg *arg = *s < '0' || *s > '9' ?
585 next_arg(error) : get_arg(parse_nonnegative_int(s), error);
Victor Zverovich9646e382014-08-27 09:13:42 -0700586 if (error)
587 throw FormatError(*s != '}' && *s != ':' ? "invalid format string" : error);
Victor Zverovichda0f7c02014-08-27 09:04:51 -0700588 return *arg;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700589}
590
Victor Zverovich605d2602014-08-29 07:45:55 -0700591const Arg *fmt::internal::FormatterBase::do_get_arg(
592 unsigned arg_index, const char *&error) {
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700593 if (arg_index < args_.size())
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700594 return &args_[arg_index];
Victor Zverovich605d2602014-08-29 07:45:55 -0700595 error = "argument index out of range";
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700596 return 0;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700597}
598
Victor Zverovich605d2602014-08-29 07:45:55 -0700599inline const Arg *fmt::internal::FormatterBase::next_arg(const char *&error) {
600 if (next_arg_index_ >= 0)
601 return do_get_arg(next_arg_index_++, error);
602 error = "cannot switch from manual to automatic argument indexing";
603 return 0;
604}
605
606inline const Arg *fmt::internal::FormatterBase::get_arg(
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700607 unsigned arg_index, const char *&error) {
Victor Zverovich605d2602014-08-29 07:45:55 -0700608 if (next_arg_index_ <= 0) {
609 next_arg_index_ = -1;
610 return do_get_arg(arg_index, error);
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700611 }
Victor Zverovich605d2602014-08-29 07:45:55 -0700612 error = "cannot switch from automatic to manual argument indexing";
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700613 return 0;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700614}
615
Victor Zverovich7cae7632013-09-06 20:23:42 -0700616template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700617void fmt::internal::PrintfFormatter<Char>::parse_flags(
Victor Zverovichcb743c02014-06-19 07:40:35 -0700618 FormatSpec &spec, const Char *&s) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700619 for (;;) {
Victor Zverovich1b801482014-06-07 08:57:55 -0700620 switch (*s++) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700621 case '-':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700622 spec.align_ = ALIGN_LEFT;
623 break;
624 case '+':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700625 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
626 break;
627 case '0':
628 spec.fill_ = '0';
Victor Zverovich1b801482014-06-07 08:57:55 -0700629 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700630 case ' ':
Victor Zverovich1b801482014-06-07 08:57:55 -0700631 spec.flags_ |= SIGN_FLAG;
632 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700633 case '#':
Victor Zverovichcb743c02014-06-19 07:40:35 -0700634 spec.flags_ |= HASH_FLAG;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700635 break;
636 default:
Victor Zverovich1b801482014-06-07 08:57:55 -0700637 --s;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700638 return;
639 }
640 }
641}
642
Victor Zverovichcb743c02014-06-19 07:40:35 -0700643template <typename Char>
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700644const Arg &fmt::internal::PrintfFormatter<Char>::get_arg(
645 const Char *s, unsigned arg_index) {
646 const char *error = 0;
647 const Arg *arg = arg_index == UINT_MAX ?
648 next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
649 if (error)
650 throw FormatError(!*s ? "invalid format string" : error);
651 return *arg;
652}
653
654template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700655unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700656 const Char *&s, FormatSpec &spec) {
Victor Zverovichcb743c02014-06-19 07:40:35 -0700657 unsigned arg_index = UINT_MAX;
658 Char c = *s;
659 if (c >= '0' && c <= '9') {
660 // Parse an argument index (if followed by '$') or a width possibly
Victor Zverovich879838a2014-06-20 07:34:02 -0700661 // preceded with '0' flag(s).
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700662 unsigned value = parse_nonnegative_int(s);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700663 if (*s == '$') { // value is an argument index
664 ++s;
665 arg_index = value;
666 } else {
667 if (c == '0')
668 spec.fill_ = '0';
669 if (value != 0) {
670 // Nonzero value means that we parsed width and don't need to
671 // parse it or flags again, so return now.
672 spec.width_ = value;
673 return arg_index;
674 }
675 }
676 }
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700677 parse_flags(spec, s);
Victor Zverovich4099a122014-06-23 08:10:50 -0700678 // Parse width.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700679 if (*s >= '0' && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700680 spec.width_ = parse_nonnegative_int(s);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700681 } else if (*s == '*') {
682 ++s;
Victor Zverovich56fc5252014-08-28 07:48:55 -0700683 spec.width_ = WidthHandler(spec).visit(get_arg(s));
Victor Zverovichcb743c02014-06-19 07:40:35 -0700684 }
685 return arg_index;
686}
687
Victor Zverovich1f19b982014-06-16 07:49:30 -0700688template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700689void fmt::internal::PrintfFormatter<Char>::format(
Victor Zveroviche78904b2014-04-23 08:27:50 -0700690 BasicWriter<Char> &writer, BasicStringRef<Char> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700691 const ArgList &args) {
Victor Zveroviche78904b2014-04-23 08:27:50 -0700692 const Char *start = format.c_str();
Victor Zverovich605d2602014-08-29 07:45:55 -0700693 set_args(args);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700694 const Char *s = start;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700695 while (*s) {
Victor Zverovich0fc73162013-09-07 12:52:52 -0700696 Char c = *s++;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700697 if (c != '%') continue;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700698 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -0700699 write(writer, start, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700700 start = ++s;
701 continue;
702 }
Victor Zverovichc1db2932014-07-24 08:53:27 -0700703 write(writer, start, s - 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700704
Victor Zverovichcb743c02014-06-19 07:40:35 -0700705 FormatSpec spec;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700706 spec.align_ = ALIGN_RIGHT;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700707
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700708 // Parse argument index, flags and width.
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700709 unsigned arg_index = parse_header(s, spec);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700710
711 // Parse precision.
712 if (*s == '.') {
713 ++s;
714 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700715 spec.precision_ = parse_nonnegative_int(s);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700716 } else if (*s == '*') {
717 ++s;
Victor Zverovich56fc5252014-08-28 07:48:55 -0700718 spec.precision_ = PrecisionHandler().visit(get_arg(s));
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700719 }
720 }
721
Victor Zverovich56fc5252014-08-28 07:48:55 -0700722 Arg arg = get_arg(s, arg_index);
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700723 if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
Victor Zverovichcb743c02014-06-19 07:40:35 -0700724 spec.flags_ &= ~HASH_FLAG;
725 if (spec.fill_ == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700726 if (arg.type <= Arg::LAST_NUMERIC_TYPE)
Victor Zverovichcb743c02014-06-19 07:40:35 -0700727 spec.align_ = ALIGN_NUMERIC;
728 else
729 spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700730 }
731
Victor Zverovichf4156b52014-07-30 08:39:07 -0700732 // Parse length and convert the argument to the required type.
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700733 switch (*s++) {
734 case 'h':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700735 if (*s == 'h')
736 ArgConverter<signed char>(arg, *++s).visit(arg);
Victor Zverovich39b09302014-07-30 08:08:08 -0700737 else
Victor Zverovichf4156b52014-07-30 08:39:07 -0700738 ArgConverter<short>(arg, *s).visit(arg);
Victor Zverovicheeca2232014-07-30 07:37:16 -0700739 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700740 case 'l':
Victor Zverovichd3a70392014-08-12 08:36:19 -0700741 if (*s == 'l')
Victor Zveroviche488a282014-08-13 06:53:43 -0700742 ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
Victor Zverovichd3a70392014-08-12 08:36:19 -0700743 else
744 ArgConverter<long>(arg, *s).visit(arg);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700745 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700746 case 'j':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700747 ArgConverter<intmax_t>(arg, *s).visit(arg);
748 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700749 case 'z':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700750 ArgConverter<size_t>(arg, *s).visit(arg);
751 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700752 case 't':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700753 ArgConverter<ptrdiff_t>(arg, *s).visit(arg);
754 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700755 case 'L':
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700756 // printf produces garbage when 'L' is omitted for long double, no
757 // need to do the same.
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700758 break;
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700759 default:
760 --s;
Victor Zverovichbe00d8b2014-08-19 08:49:10 -0700761 ArgConverter<int>(arg, *s).visit(arg);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700762 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700763
764 // Parse type.
765 if (!*s)
766 throw FormatError("invalid format string");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700767 spec.type_ = static_cast<char>(*s++);
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700768 if (arg.type <= Arg::LAST_INTEGER_TYPE) {
769 // Normalize type.
770 switch (spec.type_) {
771 case 'i': case 'u':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700772 spec.type_ = 'd';
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700773 break;
774 case 'c':
775 // TODO: handle wchar_t
776 CharConverter(arg).visit(arg);
777 break;
778 }
Victor Zverovichf4156b52014-07-30 08:39:07 -0700779 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700780
781 start = s;
782
783 // Format argument.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700784 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700785 case Arg::INT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700786 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700787 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700788 case Arg::UINT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700789 writer.write_int(arg.uint_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700790 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700791 case Arg::LONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700792 writer.write_int(arg.long_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700793 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700794 case Arg::ULONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700795 writer.write_int(arg.ulong_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700796 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700797 case Arg::CHAR: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700798 if (spec.type_ && spec.type_ != 'c')
Victor Zverovichc1db2932014-07-24 08:53:27 -0700799 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700800 typedef typename BasicWriter<Char>::CharPtr CharPtr;
801 CharPtr out = CharPtr();
802 if (spec.width_ > 1) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700803 Char fill = ' ';
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700804 out = writer.grow_buffer(spec.width_);
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700805 if (spec.align_ != ALIGN_LEFT) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700806 std::fill_n(out, spec.width_ - 1, fill);
807 out += spec.width_ - 1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700808 } else {
809 std::fill_n(out + 1, spec.width_ - 1, fill);
810 }
811 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700812 out = writer.grow_buffer(1);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700813 }
Victor Zverovichcb743c02014-06-19 07:40:35 -0700814 *out = static_cast<Char>(arg.int_value);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700815 break;
816 }
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700817 case Arg::DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700818 writer.write_double(arg.double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700819 break;
820 case Arg::LONG_DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700821 writer.write_double(arg.long_double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700822 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700823 case Arg::STRING:
Victor Zverovich53201032014-06-30 14:26:29 -0700824 writer.write_str(arg.string, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700825 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700826 case Arg::WSTRING:
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700827 writer.write_str(ignore_incompatible_str<Char>(arg.wstring), spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700828 break;
829 case Arg::POINTER:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700830 if (spec.type_ && spec.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700831 internal::report_unknown_type(spec.type_, "pointer");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700832 spec.flags_= HASH_FLAG;
833 spec.type_ = 'x';
Victor Zverovichc1db2932014-07-24 08:53:27 -0700834 writer.write_int(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700835 break;
Victor Zverovich271fa8c2014-08-29 07:23:54 -0700836 case Arg::CUSTOM: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700837 if (spec.type_)
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700838 internal::report_unknown_type(spec.type_, "object");
Victor Zverovich271fa8c2014-08-29 07:23:54 -0700839 const void *s = "s";
840 arg.custom.format(&writer, arg.custom.value, &s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700841 break;
Victor Zverovich271fa8c2014-08-29 07:23:54 -0700842 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700843 default:
844 assert(false);
845 break;
846 }
847 }
Victor Zverovichc1db2932014-07-24 08:53:27 -0700848 write(writer, start, s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700849}
850
851template <typename Char>
Victor Zverovichb9a06ba2014-07-08 16:38:50 -0700852const Char *fmt::BasicFormatter<Char>::format(
Victor Zverovich271fa8c2014-08-29 07:23:54 -0700853 const Char *&format_str, const Arg &arg) {
Victor Zveroviche8251562014-07-08 16:20:33 -0700854 const Char *s = format_str;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700855 const char *error = 0;
Victor Zveroviche8251562014-07-08 16:20:33 -0700856 FormatSpec spec;
857 if (*s == ':') {
858 if (arg.type == Arg::CUSTOM) {
Victor Zverovich271fa8c2014-08-29 07:23:54 -0700859 arg.custom.format(this, arg.custom.value, &s);
860 return s;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700861 }
Victor Zveroviche8251562014-07-08 16:20:33 -0700862 ++s;
863 // Parse fill and alignment.
864 if (Char c = *s) {
865 const Char *p = s + 1;
866 spec.align_ = ALIGN_DEFAULT;
867 do {
868 switch (*p) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700869 case '<':
870 spec.align_ = ALIGN_LEFT;
871 break;
872 case '>':
873 spec.align_ = ALIGN_RIGHT;
874 break;
875 case '=':
876 spec.align_ = ALIGN_NUMERIC;
877 break;
878 case '^':
879 spec.align_ = ALIGN_CENTER;
880 break;
Victor Zveroviche8251562014-07-08 16:20:33 -0700881 }
882 if (spec.align_ != ALIGN_DEFAULT) {
883 if (p != s) {
884 if (c == '}') break;
885 if (c == '{')
Victor Zverovich42de4f12014-08-27 08:24:31 -0700886 throw FormatError("invalid fill character '{'");
Victor Zveroviche8251562014-07-08 16:20:33 -0700887 s += 2;
888 spec.fill_ = c;
889 } else ++s;
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700890 if (spec.align_ == ALIGN_NUMERIC)
891 require_numeric_argument(arg, '=');
Victor Zveroviche8251562014-07-08 16:20:33 -0700892 break;
893 }
894 } while (--p >= s);
895 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700896
Victor Zveroviche8251562014-07-08 16:20:33 -0700897 // Parse sign.
898 switch (*s) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700899 case '+':
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700900 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700901 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
902 break;
903 case '-':
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700904 check_sign(s, arg);
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700905 spec.flags_ |= MINUS_FLAG;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700906 break;
907 case ' ':
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700908 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700909 spec.flags_ |= SIGN_FLAG;
910 break;
Victor Zveroviche8251562014-07-08 16:20:33 -0700911 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700912
Victor Zveroviche8251562014-07-08 16:20:33 -0700913 if (*s == '#') {
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700914 require_numeric_argument(arg, '#');
Victor Zveroviche8251562014-07-08 16:20:33 -0700915 spec.flags_ |= HASH_FLAG;
916 ++s;
917 }
918
919 // Parse width and zero flag.
920 if ('0' <= *s && *s <= '9') {
921 if (*s == '0') {
Victor Zverovich5debb2a2014-08-29 08:16:10 -0700922 require_numeric_argument(arg, '0');
Victor Zveroviche8251562014-07-08 16:20:33 -0700923 spec.align_ = ALIGN_NUMERIC;
924 spec.fill_ = '0';
Victor Zverovich7cae7632013-09-06 20:23:42 -0700925 }
Victor Zveroviche8251562014-07-08 16:20:33 -0700926 // Zero may be parsed again as a part of the width, but it is simpler
927 // and more efficient than checking if the next char is a digit.
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700928 spec.width_ = parse_nonnegative_int(s);
Victor Zveroviche8251562014-07-08 16:20:33 -0700929 if (error)
Victor Zverovich42de4f12014-08-27 08:24:31 -0700930 throw FormatError(error);
Victor Zveroviche8251562014-07-08 16:20:33 -0700931 }
Victor Zverovich7cae7632013-09-06 20:23:42 -0700932
Victor Zveroviche8251562014-07-08 16:20:33 -0700933 // Parse precision.
934 if (*s == '.') {
935 ++s;
936 spec.precision_ = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700937 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700938 spec.precision_ = parse_nonnegative_int(s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700939 if (error)
Victor Zverovich42de4f12014-08-27 08:24:31 -0700940 throw FormatError(error);
Victor Zveroviche8251562014-07-08 16:20:33 -0700941 } else if (*s == '{') {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700942 ++s;
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700943 const Arg &precision_arg = parse_arg_index(s);
Victor Zverovich42de4f12014-08-27 08:24:31 -0700944 if (*s++ != '}')
Victor Zverovich605d2602014-08-29 07:45:55 -0700945 throw FormatError("invalid format string");
Victor Zveroviche8251562014-07-08 16:20:33 -0700946 ULongLong value = 0;
947 switch (precision_arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700948 case Arg::INT:
Victor Zverovich7cae7632013-09-06 20:23:42 -0700949 if (precision_arg.int_value < 0)
Victor Zverovich605d2602014-08-29 07:45:55 -0700950 throw FormatError("negative precision");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700951 value = precision_arg.int_value;
952 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700953 case Arg::UINT:
Victor Zverovich7cae7632013-09-06 20:23:42 -0700954 value = precision_arg.uint_value;
955 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700956 case Arg::LONG_LONG:
Victor Zverovich56f12b72013-11-22 07:45:43 -0800957 if (precision_arg.long_long_value < 0)
Victor Zverovich605d2602014-08-29 07:45:55 -0700958 throw FormatError("negative precision");
Victor Zverovich56f12b72013-11-22 07:45:43 -0800959 value = precision_arg.long_long_value;
960 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700961 case Arg::ULONG_LONG:
Gregory Czajkowskia65542b2013-11-18 22:58:39 -0800962 value = precision_arg.ulong_long_value;
Victor Zverovicha4e72b42013-11-21 09:11:58 -0800963 break;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700964 default:
Victor Zverovich42de4f12014-08-27 08:24:31 -0700965 throw FormatError("precision is not integer");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700966 }
Victor Zveroviche8251562014-07-08 16:20:33 -0700967 if (value > INT_MAX)
Victor Zverovich279c7a62014-08-28 06:50:52 -0700968 throw FormatError("number is too big");
Victor Zveroviche8251562014-07-08 16:20:33 -0700969 spec.precision_ = static_cast<int>(value);
Victor Zveroviche8251562014-07-08 16:20:33 -0700970 } else {
Victor Zverovich605d2602014-08-29 07:45:55 -0700971 throw FormatError("missing precision specifier");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700972 }
Victor Zveroviche8251562014-07-08 16:20:33 -0700973 if (arg.type != Arg::DOUBLE && arg.type != Arg::LONG_DOUBLE) {
Victor Zverovich42de4f12014-08-27 08:24:31 -0700974 throw FormatError(
Victor Zveroviche8251562014-07-08 16:20:33 -0700975 "precision specifier requires floating-point argument");
976 }
Victor Zverovich7cae7632013-09-06 20:23:42 -0700977 }
978
Victor Zveroviche8251562014-07-08 16:20:33 -0700979 // Parse type.
980 if (*s != '}' && *s)
981 spec.type_ = static_cast<char>(*s++);
982 }
Victor Zverovich7cae7632013-09-06 20:23:42 -0700983
Victor Zveroviche8251562014-07-08 16:20:33 -0700984 if (*s++ != '}')
Victor Zverovich605d2602014-08-29 07:45:55 -0700985 throw FormatError("missing '}' in format string");
Victor Zveroviche8251562014-07-08 16:20:33 -0700986 start_ = s;
987
988 // Format argument.
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700989 internal::ArgFormatter<Char>(*this, spec, s - 1).visit(arg);
Victor Zveroviche8251562014-07-08 16:20:33 -0700990 return s;
991}
992
993template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700994void fmt::BasicFormatter<Char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -0700995 BasicStringRef<Char> format_str, const ArgList &args) {
996 const Char *s = start_ = format_str.c_str();
Victor Zverovich605d2602014-08-29 07:45:55 -0700997 set_args(args);
Victor Zveroviche8251562014-07-08 16:20:33 -0700998 while (*s) {
999 Char c = *s++;
1000 if (c != '{' && c != '}') continue;
1001 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -07001002 write(writer_, start_, s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001003 start_ = ++s;
1004 continue;
1005 }
1006 if (c == '}')
Victor Zverovich605d2602014-08-29 07:45:55 -07001007 throw FormatError("unmatched '}' in format string");
Victor Zverovichc1db2932014-07-24 08:53:27 -07001008 write(writer_, start_, s - 1);
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001009 Arg arg = parse_arg_index(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001010 s = format(s, arg);
1011 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001012 write(writer_, start_, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001013}
1014
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001015void fmt::report_system_error(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001016 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001017 report_error(internal::format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001018}
1019
Victor Zverovich400812a2014-04-30 12:38:17 -07001020#ifdef _WIN32
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001021void fmt::report_windows_error(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001022 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001023 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001024}
Victor Zverovich400812a2014-04-30 12:38:17 -07001025#endif
Victor Zverovichf7939862014-04-30 10:18:11 -07001026
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001027void fmt::print(std::FILE *f, StringRef format_str, const ArgList &args) {
Victor Zverovich2e039632014-06-28 19:44:39 -07001028 Writer w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001029 w.write(format_str, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001030 std::fwrite(w.data(), 1, w.size(), f);
1031}
1032
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001033void fmt::print(std::ostream &os, StringRef format_str, const ArgList &args) {
Victor Zveroviche3a44c12014-07-09 06:56:36 -07001034 Writer w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001035 w.write(format_str, args);
Victor Zveroviche3a44c12014-07-09 06:56:36 -07001036 os.write(w.data(), w.size());
1037}
1038
Victor Zverovich2dc108b2014-07-01 09:10:43 -07001039void fmt::print_colored(Color c, StringRef format, const ArgList &args) {
1040 char escape[] = "\x1b[30m";
1041 escape[3] = '0' + static_cast<char>(c);
1042 std::fputs(escape, stdout);
1043 print(format, args);
1044 std::fputs(RESET_COLOR, stdout);
1045}
1046
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001047int fmt::fprintf(std::FILE *f, StringRef format, const ArgList &args) {
Victor Zverovichd5b81962014-06-28 21:56:40 -07001048 Writer w;
Victor Zverovich21111cc2014-06-29 19:52:26 -07001049 printf(w, format, args);
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001050 return std::fwrite(w.data(), 1, w.size(), f);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001051}
1052
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001053// Explicit instantiations for char.
1054
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001055template void fmt::BasicFormatter<char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001056 BasicStringRef<char> format, const ArgList &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001057
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001058template void fmt::internal::PrintfFormatter<char>::format(
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001059 BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001060
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001061// Explicit instantiations for wchar_t.
1062
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001063template void fmt::BasicFormatter<wchar_t>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001064 BasicStringRef<wchar_t> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001065
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001066template void fmt::internal::PrintfFormatter<wchar_t>::format(
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001067 BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001068 const ArgList &args);
jdale88a9862fd2014-03-11 18:56:24 +00001069
1070#if _MSC_VER
1071# pragma warning(pop)
1072#endif