blob: 04e64bf74a7031ae40a956a82e048576038e1bd7 [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
65
Victor Zverovichbe785a82014-07-29 09:14:07 -070066// Portable version of signbit.
Victor Zverovichd8b9f412014-07-29 06:38:05 -070067// When compiled in C++11 mode signbit is no longer a macro but a function
68// defined in namespace std and the macro is undefined.
Victor Zverovichbe785a82014-07-29 09:14:07 -070069inline int getsign(double x) {
70#ifdef signbit
71 return signbit(x);
72#else
73 return std::signbit(x);
Victor Zverovichf2e06802014-04-10 10:49:55 -070074#endif
Victor Zverovichbe785a82014-07-29 09:14:07 -070075}
Victor Zverovich9ff3b972013-09-07 10:15:08 -070076
Victor Zverovich24d6baa2014-07-29 07:49:34 -070077// Portable version of isinf.
Victor Zverovich24d6baa2014-07-29 07:49:34 -070078#ifdef isinf
Victor Zverovichd4412a02014-08-13 08:01:51 -070079inline int isinfinity(double x) { return isinf(x); }
80inline int isinfinity(long double x) { return isinf(x); }
Victor Zverovich24d6baa2014-07-29 07:49:34 -070081#else
Victor Zverovichd4412a02014-08-13 08:01:51 -070082inline int isinfinity(double x) { return std::isinf(x); }
83inline int isinfinity(long double x) { return std::isinf(x); }
Victor Zverovich9ff3b972013-09-07 10:15:08 -070084#endif
Victor Zverovich1a0c76a2014-08-13 07:51:02 -070085
Victor Zverovich9ff3b972013-09-07 10:15:08 -070086#define FMT_SNPRINTF snprintf
87
Victor Zverovicha684d0c2013-12-27 08:00:10 -080088#else // _MSC_VER
Victor Zverovich9ff3b972013-09-07 10:15:08 -070089
Victor Zverovichbe785a82014-07-29 09:14:07 -070090inline int getsign(double value) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -070091 if (value < 0) return 1;
92 if (value == value) return 0;
93 int dec = 0, sign = 0;
94 char buffer[2]; // The buffer size must be >= 2 or _ecvt_s will fail.
95 _ecvt_s(buffer, sizeof(buffer), value, 0, &dec, &sign);
96 return sign;
97}
98
Victor Zverovichbf5b2462014-07-29 08:22:52 -070099inline int isinfinity(double x) { return !_finite(x); }
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700100
Victor Zverovich406c6122014-08-19 08:47:38 -0700101inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
Victor Zverovicha684d0c2013-12-27 08:00:10 -0800102 va_list args;
103 va_start(args, format);
104 int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
105 va_end(args);
106 return result;
107}
Victor Zverovich406c6122014-08-19 08:47:38 -0700108#define FMT_SNPRINTF fmt_snprintf
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700109
110#endif // _MSC_VER
Victor Zverovich43fe1002014-02-19 14:20:26 -0800111
Victor Zverovichfb321612014-08-15 08:40:03 -0700112template <typename T>
113struct IsLongDouble { enum {VALUE = 0}; };
114
115template <>
116struct IsLongDouble<long double> { enum {VALUE = 1}; };
117
Victor Zverovichadce0242014-08-17 07:53:55 -0700118// Checks if a value fits in int - used to avoid warnings about comparing
119// signed and unsigned integers.
120template <bool IsSigned>
121struct IntChecker {
122 template <typename T>
123 static bool fits_in_int(T value) {
124 unsigned max = INT_MAX;
125 return value <= max;
126 }
127};
128
129template <>
130struct IntChecker<true> {
131 template <typename T>
132 static bool fits_in_int(T value) {
133 return value >= INT_MIN && value <= INT_MAX;
134 }
135};
136
Victor Zverovich43fe1002014-02-19 14:20:26 -0800137const char RESET_COLOR[] = "\x1b[0m";
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700138
139typedef void (*FormatFunc)(fmt::Writer &, int , fmt::StringRef);
140
Victor Zverovichd8b9f412014-07-29 06:38:05 -0700141void report_error(FormatFunc func,
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700142 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
143 try {
144 fmt::Writer full_message;
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700145 func(full_message, error_code, message); // TODO: make sure this doesn't throw
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700146 std::fwrite(full_message.c_str(), full_message.size(), 1, stderr);
147 std::fputc('\n', stderr);
148 } catch (...) {}
Victor Zverovichb605b392013-09-09 22:21:40 -0700149}
Victor Zverovichd29e5052014-06-30 07:12:09 -0700150
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700151// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
152class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> {
153 public:
154 template <typename T>
155 bool visit_any_int(T value) { return value == 0; }
156};
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700157
158// Parses an unsigned integer advancing s to the end of the parsed input.
159// This function assumes that the first character of s is a digit.
160template <typename Char>
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700161int parse_nonnegative_int(const Char *&s) {
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700162 assert('0' <= *s && *s <= '9');
163 unsigned value = 0;
164 do {
165 unsigned new_value = value * 10 + (*s++ - '0');
166 // Check if value wrapped around.
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700167 if (new_value < value) {
168 value = UINT_MAX;
169 break;
170 }
171 value = new_value;
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700172 } while ('0' <= *s && *s <= '9');
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700173 if (value > INT_MAX)
Victor Zverovich279c7a62014-08-28 06:50:52 -0700174 throw fmt::FormatError("number is too big");
Victor Zverovich6e5551e2014-07-02 06:33:25 -0700175 return value;
176}
Victor Zveroviche8251562014-07-08 16:20:33 -0700177
178template <typename Char>
179const Char *find_closing_brace(const Char *s, int num_open_braces = 1) {
180 for (int n = num_open_braces; *s; ++s) {
181 if (*s == '{') {
182 ++n;
183 } else if (*s == '}') {
184 if (--n == 0)
185 return s;
186 }
187 }
188 throw fmt::FormatError("unmatched '{' in format");
189}
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700190
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700191// Checks if an argument is a valid printf width specifier and sets
192// left alignment if it is negative.
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700193class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700194 private:
195 fmt::FormatSpec &spec_;
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700196
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700197 public:
198 explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700199
Victor Zverovich9d74f952014-07-16 07:27:54 -0700200 unsigned visit_unhandled_arg() {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700201 throw fmt::FormatError("width is not integer");
202 }
Victor Zveroviche3a2ac82014-07-14 08:04:17 -0700203
Victor Zverovich9d74f952014-07-16 07:27:54 -0700204 template <typename T>
205 unsigned visit_any_int(T value) {
206 typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType;
207 UnsignedType width = value;
208 if (fmt::internal::is_negative(value)) {
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700209 spec_.align_ = fmt::ALIGN_LEFT;
210 width = 0 - width;
211 }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700212 if (width > INT_MAX)
Victor Zverovich279c7a62014-08-28 06:50:52 -0700213 throw fmt::FormatError("number is too big");
Victor Zverovich9d74f952014-07-16 07:27:54 -0700214 return static_cast<unsigned>(width);
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700215 }
Victor Zverovich591ad0a2014-07-14 06:55:29 -0700216};
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700217
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700218class PrecisionHandler :
219 public fmt::internal::ArgVisitor<PrecisionHandler, int> {
220 public:
221 unsigned visit_unhandled_arg() {
222 throw fmt::FormatError("precision is not integer");
223 }
224
225 template <typename T>
226 int visit_any_int(T value) {
Victor Zverovichadce0242014-08-17 07:53:55 -0700227 if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
Victor Zverovich279c7a62014-08-28 06:50:52 -0700228 throw fmt::FormatError("number is too big");
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700229 return static_cast<int>(value);
230 }
231};
232
Victor Zverovich32344d92014-08-28 08:11:21 -0700233// Converts an integer argument to an integral type T for printf.
Victor Zverovicheeca2232014-07-30 07:37:16 -0700234template <typename T>
235class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
236 private:
237 fmt::internal::Arg &arg_;
Victor Zveroviche22d6572014-08-08 06:51:09 -0700238 wchar_t type_;
Victor Zverovicheeca2232014-07-30 07:37:16 -0700239
240 public:
Victor Zveroviche22d6572014-08-08 06:51:09 -0700241 ArgConverter(fmt::internal::Arg &arg, wchar_t type)
242 : arg_(arg), type_(type) {}
Victor Zverovicheeca2232014-07-30 07:37:16 -0700243
244 template <typename U>
245 void visit_any_int(U value) {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700246 bool is_signed = type_ == 'd' || type_ == 'i';
247 using fmt::internal::Arg;
248 if (sizeof(T) <= sizeof(int)) {
Victor Zverovich32344d92014-08-28 08:11:21 -0700249 // Extra casts are used to silence warnings.
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700250 if (is_signed) {
251 arg_.type = Arg::INT;
Victor Zverovichbb016332014-08-15 09:03:59 -0700252 arg_.int_value = static_cast<int>(static_cast<T>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700253 } else {
254 arg_.type = Arg::UINT;
Victor Zverovich186734c2014-08-18 07:03:12 -0700255 arg_.uint_value = static_cast<unsigned>(
256 static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700257 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700258 } else {
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700259 if (is_signed) {
260 arg_.type = Arg::LONG_LONG;
Victor Zverovicha259c942014-08-01 07:15:27 -0700261 arg_.long_long_value =
262 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700263 } else {
264 arg_.type = Arg::ULONG_LONG;
265 arg_.ulong_long_value =
Victor Zverovicha259c942014-08-01 07:15:27 -0700266 static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700267 }
Victor Zverovicheeca2232014-07-30 07:37:16 -0700268 }
269 }
270};
271
Victor Zverovich32344d92014-08-28 08:11:21 -0700272// Converts an integer argument to char for printf.
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700273class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
274 private:
275 fmt::internal::Arg &arg_;
276
277 public:
278 explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
279
280 template <typename T>
281 void visit_any_int(T value) {
282 arg_.type = Arg::CHAR;
283 arg_.int_value = static_cast<char>(value);
284 }
285};
286
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700287// This function template is used to prevent compile errors when handling
288// incompatible string arguments, e.g. handling a wide string in a narrow
289// string formatter.
290template <typename Char>
291Arg::StringValue<Char> ignore_incompatible_str(Arg::StringValue<wchar_t>);
292
293template <>
294inline Arg::StringValue<char> ignore_incompatible_str(
295 Arg::StringValue<wchar_t>) { return Arg::StringValue<char>(); }
296
297template <>
298inline Arg::StringValue<wchar_t> ignore_incompatible_str(
299 Arg::StringValue<wchar_t> s) { return s; }
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700300} // namespace
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700301
Victor Zverovich53201032014-06-30 14:26:29 -0700302void fmt::SystemError::init(
303 int error_code, StringRef format_str, const ArgList &args) {
304 error_code_ = error_code;
305 Writer w;
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700306 internal::format_system_error(w, error_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700307 std::runtime_error &base = *this;
308 base = std::runtime_error(w.str());
309}
310
Victor Zverovichb605b392013-09-09 22:21:40 -0700311template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700312int fmt::internal::CharTraits<char>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700313 char *buffer, std::size_t size, const char *format,
314 unsigned width, int precision, T value) {
315 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700316 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700317 FMT_SNPRINTF(buffer, size, format, value) :
318 FMT_SNPRINTF(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700319 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700320 return precision < 0 ?
321 FMT_SNPRINTF(buffer, size, format, width, value) :
322 FMT_SNPRINTF(buffer, size, format, width, precision, value);
323}
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700324
Victor Zverovichb605b392013-09-09 22:21:40 -0700325template <typename T>
Victor Zverovichb498ba02014-07-26 08:03:03 -0700326int fmt::internal::CharTraits<wchar_t>::format_float(
Victor Zverovichb605b392013-09-09 22:21:40 -0700327 wchar_t *buffer, std::size_t size, const wchar_t *format,
328 unsigned width, int precision, T value) {
329 if (width == 0) {
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700330 return precision < 0 ?
Victor Zverovichb605b392013-09-09 22:21:40 -0700331 swprintf(buffer, size, format, value) :
332 swprintf(buffer, size, format, precision, value);
Victor Zverovich9ff3b972013-09-07 10:15:08 -0700333 }
Victor Zverovichb605b392013-09-09 22:21:40 -0700334 return precision < 0 ?
335 swprintf(buffer, size, format, width, value) :
336 swprintf(buffer, size, format, width, precision, value);
Victor Zverovich65d47e52013-09-09 06:51:03 -0700337}
Victor Zveroviche8ba9602012-12-12 09:29:50 -0800338
Victor Zverovich65d47e52013-09-09 06:51:03 -0700339const char fmt::internal::DIGITS[] =
Victor Zverovich687301c2013-01-26 16:07:28 -0800340 "0001020304050607080910111213141516171819"
341 "2021222324252627282930313233343536373839"
342 "4041424344454647484950515253545556575859"
343 "6061626364656667686970717273747576777879"
344 "8081828384858687888990919293949596979899";
Victor Zveroviche9b21912014-02-19 12:43:55 -0800345
Victor Zverovichf1d85162014-02-19 13:02:22 -0800346#define FMT_POWERS_OF_10(factor) \
347 factor * 10, \
348 factor * 100, \
349 factor * 1000, \
350 factor * 10000, \
351 factor * 100000, \
352 factor * 1000000, \
353 factor * 10000000, \
354 factor * 100000000, \
355 factor * 1000000000
Victor Zveroviche9b21912014-02-19 12:43:55 -0800356
Victor Zverovichf1d85162014-02-19 13:02:22 -0800357const uint32_t fmt::internal::POWERS_OF_10_32[] = {0, FMT_POWERS_OF_10(1)};
Victor Zveroviche9b21912014-02-19 12:43:55 -0800358const uint64_t fmt::internal::POWERS_OF_10_64[] = {
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800359 0,
Victor Zverovichf1d85162014-02-19 13:02:22 -0800360 FMT_POWERS_OF_10(1),
361 FMT_POWERS_OF_10(ULongLong(1000000000)),
Victor Zverovich406c6122014-08-19 08:47:38 -0700362 // Multiply several constants instead of using a single long long constant
Victor Zverovichf1d85162014-02-19 13:02:22 -0800363 // to avoid warnings about C++98 not supporting long long.
Victor Zverovich6f6fe512014-02-15 11:16:44 -0800364 ULongLong(1000000000) * ULongLong(1000000000) * 10
Victor Zverovich6f0387f2014-02-14 10:36:17 -0800365};
Victor Zverovich877abaf2013-01-08 09:56:05 -0800366
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700367void fmt::internal::report_unknown_type(char code, const char *type) {
Victor Zverovich877abaf2013-01-08 09:56:05 -0800368 if (std::isprint(static_cast<unsigned char>(code))) {
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700369 throw fmt::FormatError(
370 fmt::format("unknown format code '{}' for {}", code, type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800371 }
372 throw fmt::FormatError(
Victor Zveroviche63a0ff2014-06-30 06:43:53 -0700373 fmt::format("unknown format code '\\x{:02x}' for {}",
374 static_cast<unsigned>(code), type));
Victor Zverovich877abaf2013-01-08 09:56:05 -0800375}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700376
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700377#ifdef _WIN32
378
379fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
380 int length = MultiByteToWideChar(
381 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, 0, 0);
382 static const char ERROR[] = "cannot convert string from UTF-8 to UTF-16";
383 if (length == 0)
Victor Zverovichf4208772014-06-30 17:32:08 -0700384 throw WindowsError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700385 buffer_.resize(length);
386 length = MultiByteToWideChar(
387 CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, &buffer_[0], length);
388 if (length == 0)
Victor Zverovichf4208772014-06-30 17:32:08 -0700389 throw WindowsError(GetLastError(), ERROR);
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700390}
391
392fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700393 if (int error_code = convert(s)) {
Victor Zverovich8321d0e2014-07-09 08:39:01 -0700394 throw WindowsError(error_code,
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700395 "cannot convert string from UTF-16 to UTF-8");
396 }
397}
398
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700399int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700400 int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, 0, 0, 0, 0);
401 if (length == 0)
402 return GetLastError();
403 buffer_.resize(length);
404 length = WideCharToMultiByte(
405 CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, 0, 0);
406 if (length == 0)
407 return GetLastError();
408 return 0;
409}
410
Victor Zverovich53201032014-06-30 14:26:29 -0700411void fmt::WindowsError::init(
412 int error_code, StringRef format_str, const ArgList &args) {
413 error_code_ = error_code;
414 Writer w;
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700415 internal::format_windows_error(w, error_code, format(format_str, args));
Victor Zverovich53201032014-06-30 14:26:29 -0700416 std::runtime_error &base = *this;
417 base = std::runtime_error(w.str());
418}
419
Victor Zverovichda9aeab2014-04-30 07:23:43 -0700420#endif
421
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700422int fmt::internal::safe_strerror(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -0700423 int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT(true) {
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700424 assert(buffer != 0 && buffer_size != 0);
Victor Zverovich99e61122014-04-30 11:20:41 -0700425 int result = 0;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700426#ifdef _GNU_SOURCE
427 char *message = strerror_r(error_code, buffer, buffer_size);
Victor Zverovich99e61122014-04-30 11:20:41 -0700428 // If the buffer is full then the message is probably truncated.
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700429 if (message == buffer && strlen(buffer) == buffer_size - 1)
Victor Zverovich99e61122014-04-30 11:20:41 -0700430 result = ERANGE;
431 buffer = message;
Victor Zverovich9c47f3e2014-07-09 09:45:18 -0700432#elif __MINGW32__
433 errno = 0;
434 (void)buffer_size;
435 buffer = strerror(error_code);
436 result = errno;
437#elif _WIN32
Victor Zverovich99e61122014-04-30 11:20:41 -0700438 result = strerror_s(buffer, buffer_size, error_code);
439 // If the buffer is full then the message is probably truncated.
440 if (result == 0 && std::strlen(buffer) == buffer_size - 1)
441 result = ERANGE;
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700442#else
Victor Zverovich99e61122014-04-30 11:20:41 -0700443 result = strerror_r(error_code, buffer, buffer_size);
444 if (result == -1)
445 result = errno; // glibc versions before 2.13 return result in errno.
Victor Zverovich2c6372d2014-04-30 09:42:48 -0700446#endif
Victor Zverovich99e61122014-04-30 11:20:41 -0700447 return result;
Victor Zverovich859a4972014-04-30 06:55:21 -0700448}
Victor Zverovich7cae7632013-09-06 20:23:42 -0700449
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700450void fmt::internal::format_system_error(
Victor Zverovich53b4c312014-04-30 15:00:41 -0700451 fmt::Writer &out, int error_code, fmt::StringRef message) {
452 Array<char, INLINE_BUFFER_SIZE> buffer;
453 buffer.resize(INLINE_BUFFER_SIZE);
454 char *system_message = 0;
455 for (;;) {
456 system_message = &buffer[0];
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700457 int result = safe_strerror(error_code, system_message, buffer.size());
Victor Zverovich53b4c312014-04-30 15:00:41 -0700458 if (result == 0)
459 break;
460 if (result != ERANGE) {
461 // Can't get error message, report error code instead.
462 out << message << ": error code = " << error_code;
463 return;
464 }
465 buffer.resize(buffer.size() * 2);
466 }
467 out << message << ": " << system_message;
468}
469
470#ifdef _WIN32
Victor Zverovich75b5eb42014-07-27 15:09:05 -0700471void fmt::internal::format_windows_error(
Victor Zverovich53b4c312014-04-30 15:00:41 -0700472 fmt::Writer &out, int error_code, fmt::StringRef message) {
473 class String {
474 private:
475 LPWSTR str_;
476
477 public:
478 String() : str_() {}
479 ~String() { LocalFree(str_); }
480 LPWSTR *ptr() { return &str_; }
481 LPCWSTR c_str() const { return str_; }
482 };
483 String system_message;
484 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
485 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
486 error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
487 reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
488 UTF16ToUTF8 utf8_message;
Victor Zverovich5d4803a2014-07-27 12:53:42 -0700489 if (!utf8_message.convert(system_message.c_str())) {
Victor Zverovicheb034a02014-06-30 17:40:53 -0700490 out << message << ": " << utf8_message;
Victor Zverovich53b4c312014-04-30 15:00:41 -0700491 return;
492 }
493 }
494 // Can't get error message, report error code instead.
495 out << message << ": error code = " << error_code;
496}
497#endif
498
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700499// An argument formatter.
500template <typename Char>
501class fmt::internal::ArgFormatter :
502 public fmt::internal::ArgVisitor<fmt::internal::ArgFormatter<Char>, void> {
503 private:
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700504 fmt::BasicFormatter<Char> &formatter_;
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700505 fmt::BasicWriter<Char> &writer_;
506 fmt::FormatSpec &spec_;
507 const Char *format_;
508
509 public:
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700510 ArgFormatter(
511 fmt::BasicFormatter<Char> &f,fmt::FormatSpec &s, const Char *fmt)
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700512 : formatter_(f), writer_(f.writer()), spec_(s), format_(fmt) {}
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700513
Victor Zverovich9d74f952014-07-16 07:27:54 -0700514 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700515 void visit_any_int(T value) { writer_.write_int(value, spec_); }
Victor Zverovich9d74f952014-07-16 07:27:54 -0700516
517 template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700518 void visit_any_double(T value) { writer_.write_double(value, spec_); }
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700519
520 void visit_char(int value) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700521 if (spec_.type_ && spec_.type_ != 'c') {
Victor Zverovichd699c2a2014-07-25 08:24:27 -0700522 spec_.flags_ |= CHAR_FLAG;
523 writer_.write_int(value, spec_);
524 return;
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700525 }
526 if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
527 throw FormatError("invalid format specifier for char");
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700528 typedef typename fmt::BasicWriter<Char>::CharPtr CharPtr;
529 CharPtr out = CharPtr();
530 if (spec_.width_ > 1) {
531 Char fill = static_cast<Char>(spec_.fill());
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700532 out = writer_.grow_buffer(spec_.width_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700533 if (spec_.align_ == fmt::ALIGN_RIGHT) {
534 std::fill_n(out, spec_.width_ - 1, fill);
535 out += spec_.width_ - 1;
536 } else if (spec_.align_ == fmt::ALIGN_CENTER) {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700537 out = writer_.fill_padding(out, spec_.width_, 1, fill);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700538 } else {
539 std::fill_n(out + 1, spec_.width_ - 1, fill);
540 }
541 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700542 out = writer_.grow_buffer(1);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700543 }
544 *out = static_cast<Char>(value);
545 }
546
547 void visit_string(Arg::StringValue<char> value) {
548 writer_.write_str(value, spec_);
549 }
550 void visit_wstring(Arg::StringValue<wchar_t> value) {
551 writer_.write_str(ignore_incompatible_str<Char>(value), spec_);
552 }
553
554 void visit_pointer(const void *value) {
555 if (spec_.type_ && spec_.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700556 fmt::internal::report_unknown_type(spec_.type_, "pointer");
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700557 spec_.flags_ = fmt::HASH_FLAG;
558 spec_.type_ = 'x';
Victor Zverovichc1db2932014-07-24 08:53:27 -0700559 writer_.write_int(reinterpret_cast<uintptr_t>(value), spec_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700560 }
561
562 void visit_custom(Arg::CustomValue c) {
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700563 c.format(&formatter_, c.value, format_);
Victor Zverovich512e2ce2014-07-14 08:47:03 -0700564 }
565};
566
Victor Zverovich7cae7632013-09-06 20:23:42 -0700567// Fills the padding around the content and returns the pointer to the
568// content area.
569template <typename Char>
Victor Zverovich93e41252013-09-08 13:07:04 -0700570typename fmt::BasicWriter<Char>::CharPtr
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700571 fmt::BasicWriter<Char>::fill_padding(CharPtr buffer,
Victor Zverovich93e41252013-09-08 13:07:04 -0700572 unsigned total_size, std::size_t content_size, wchar_t fill) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700573 std::size_t padding = total_size - content_size;
574 std::size_t left_padding = padding / 2;
Victor Zverovich563a5752013-09-08 13:47:06 -0700575 Char fill_char = static_cast<Char>(fill);
576 std::fill_n(buffer, left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700577 buffer += left_padding;
578 CharPtr content = buffer;
Victor Zverovich563a5752013-09-08 13:47:06 -0700579 std::fill_n(buffer + content_size, padding - left_padding, fill_char);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700580 return content;
581}
582
583template <typename Char>
Victor Zverovich7cae7632013-09-06 20:23:42 -0700584template <typename T>
Victor Zverovichc1db2932014-07-24 08:53:27 -0700585void fmt::BasicWriter<Char>::write_double(T value, const FormatSpec &spec) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700586 // Check type.
587 char type = spec.type();
588 bool upper = false;
589 switch (type) {
590 case 0:
591 type = 'g';
592 break;
Victor Zverovich03776dd2014-06-10 07:03:49 -0700593 case 'e': case 'f': case 'g': case 'a':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700594 break;
595 case 'F':
596#ifdef _MSC_VER
597 // MSVC's printf doesn't support 'F'.
598 type = 'f';
599#endif
600 // Fall through.
Victor Zverovich03776dd2014-06-10 07:03:49 -0700601 case 'E': case 'G': case 'A':
Victor Zverovich7cae7632013-09-06 20:23:42 -0700602 upper = true;
603 break;
604 default:
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700605 internal::report_unknown_type(type, "double");
Victor Zverovich7cae7632013-09-06 20:23:42 -0700606 break;
607 }
608
609 char sign = 0;
Victor Zverovichbe785a82014-07-29 09:14:07 -0700610 // Use getsign instead of value < 0 because the latter is always
Victor Zverovich7cae7632013-09-06 20:23:42 -0700611 // false for NaN.
Victor Zverovichbe785a82014-07-29 09:14:07 -0700612 if (getsign(static_cast<double>(value))) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700613 sign = '-';
614 value = -value;
Victor Zverovichd142e3b2014-07-25 08:29:06 -0700615 } else if (spec.flag(SIGN_FLAG)) {
616 sign = spec.flag(PLUS_FLAG) ? '+' : ' ';
Victor Zverovich7cae7632013-09-06 20:23:42 -0700617 }
618
619 if (value != value) {
620 // Format NaN ourselves because sprintf's output is not consistent
621 // across platforms.
622 std::size_t size = 4;
623 const char *nan = upper ? " NAN" : " nan";
624 if (!sign) {
625 --size;
626 ++nan;
627 }
Victor Zverovich53201032014-06-30 14:26:29 -0700628 CharPtr out = write_str(nan, size, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700629 if (sign)
630 *out = sign;
631 return;
632 }
633
Victor Zverovich1a0c76a2014-08-13 07:51:02 -0700634 if (isinfinity(value)) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700635 // Format infinity ourselves because sprintf's output is not consistent
636 // across platforms.
637 std::size_t size = 4;
638 const char *inf = upper ? " INF" : " inf";
639 if (!sign) {
640 --size;
641 ++inf;
642 }
Victor Zverovich53201032014-06-30 14:26:29 -0700643 CharPtr out = write_str(inf, size, spec);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700644 if (sign)
645 *out = sign;
646 return;
647 }
648
649 std::size_t offset = buffer_.size();
650 unsigned width = spec.width();
651 if (sign) {
652 buffer_.reserve(buffer_.size() + (std::max)(width, 1u));
653 if (width > 0)
654 --width;
655 ++offset;
656 }
657
658 // Build format string.
659 enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg
660 Char format[MAX_FORMAT_SIZE];
661 Char *format_ptr = format;
662 *format_ptr++ = '%';
663 unsigned width_for_sprintf = width;
Victor Zverovichd142e3b2014-07-25 08:29:06 -0700664 if (spec.flag(HASH_FLAG))
Victor Zverovich7cae7632013-09-06 20:23:42 -0700665 *format_ptr++ = '#';
666 if (spec.align() == ALIGN_CENTER) {
667 width_for_sprintf = 0;
668 } else {
669 if (spec.align() == ALIGN_LEFT)
670 *format_ptr++ = '-';
671 if (width != 0)
672 *format_ptr++ = '*';
673 }
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700674 if (spec.precision() >= 0) {
Victor Zverovich7cae7632013-09-06 20:23:42 -0700675 *format_ptr++ = '.';
676 *format_ptr++ = '*';
677 }
Victor Zverovichfb321612014-08-15 08:40:03 -0700678 if (IsLongDouble<T>::VALUE)
Victor Zverovich7cae7632013-09-06 20:23:42 -0700679 *format_ptr++ = 'L';
680 *format_ptr++ = type;
681 *format_ptr = '\0';
682
683 // Format using snprintf.
Victor Zverovich88972f42013-09-08 13:30:14 -0700684 Char fill = static_cast<Char>(spec.fill());
Victor Zverovich7cae7632013-09-06 20:23:42 -0700685 for (;;) {
686 std::size_t size = buffer_.capacity() - offset;
Victor Zverovich33baa8f2014-04-23 18:37:08 -0700687#if _MSC_VER
688 // MSVC's vsnprintf_s doesn't work with zero size, so reserve
689 // space for at least one extra character to make the size non-zero.
690 // Note that the buffer's capacity will increase by more than 1.
691 if (size == 0) {
692 buffer_.reserve(offset + 1);
693 size = buffer_.capacity() - offset;
694 }
695#endif
Victor Zverovich7cae7632013-09-06 20:23:42 -0700696 Char *start = &buffer_[offset];
Victor Zverovichb498ba02014-07-26 08:03:03 -0700697 int n = internal::CharTraits<Char>::format_float(
Victor Zverovichb1bbc902014-06-21 08:32:00 -0700698 start, size, format, width_for_sprintf, spec.precision(), value);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700699 if (n >= 0 && offset + n < buffer_.capacity()) {
700 if (sign) {
701 if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) ||
702 *start != ' ') {
703 *(start - 1) = sign;
704 sign = 0;
705 } else {
Victor Zverovich88972f42013-09-08 13:30:14 -0700706 *(start - 1) = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700707 }
708 ++n;
709 }
710 if (spec.align() == ALIGN_CENTER &&
711 spec.width() > static_cast<unsigned>(n)) {
712 unsigned width = spec.width();
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700713 CharPtr p = grow_buffer(width);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700714 std::copy(p, p + n, p + (width - n) / 2);
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700715 fill_padding(p, spec.width(), n, fill);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700716 return;
717 }
718 if (spec.fill() != ' ' || sign) {
719 while (*start == ' ')
Victor Zverovich88972f42013-09-08 13:30:14 -0700720 *start++ = fill;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700721 if (sign)
722 *(start - 1) = sign;
723 }
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700724 grow_buffer(n);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700725 return;
726 }
Victor Zverovichcfeba452014-04-23 18:37:49 -0700727 // If n is negative we ask to increase the capacity by at least 1,
728 // but as std::vector, the buffer grows exponentially.
729 buffer_.reserve(n >= 0 ? offset + n + 1 : buffer_.capacity() + 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700730 }
731}
732
Victor Zverovich7cae7632013-09-06 20:23:42 -0700733template <typename Char>
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700734template <typename StrChar>
Victor Zverovich53201032014-06-30 14:26:29 -0700735void fmt::BasicWriter<Char>::write_str(
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700736 const Arg::StringValue<StrChar> &str, const FormatSpec &spec) {
737 // Check if StrChar is convertible to Char.
738 internal::CharTraits<Char>::convert(StrChar());
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700739 if (spec.type_ && spec.type_ != 's')
Victor Zverovichf634ccb2014-07-26 08:42:19 -0700740 internal::report_unknown_type(spec.type_, "string");
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700741 const StrChar *s = str.value;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700742 std::size_t size = str.size;
743 if (size == 0) {
744 if (!s)
745 throw FormatError("string pointer is null");
746 if (*s)
Victor Zverovich2a1c0c92014-07-26 09:45:03 -0700747 size = std::char_traits<StrChar>::length(s);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700748 }
Victor Zverovich53201032014-06-30 14:26:29 -0700749 write_str(s, size, spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700750}
751
752template <typename Char>
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700753inline const Arg &fmt::BasicFormatter<Char>::parse_arg_index(const Char *&s) {
Victor Zverovich9646e382014-08-27 09:13:42 -0700754 const char *error = 0;
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700755 const Arg *arg = *s < '0' || *s > '9' ?
756 next_arg(error) : get_arg(parse_nonnegative_int(s), error);
Victor Zverovich9646e382014-08-27 09:13:42 -0700757 if (error)
758 throw FormatError(*s != '}' && *s != ':' ? "invalid format string" : error);
Victor Zverovichda0f7c02014-08-27 09:04:51 -0700759 return *arg;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700760}
761
762template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700763void fmt::BasicFormatter<Char>::check_sign(
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700764 const Char *&s, const Arg &arg) {
Victor Zverovichcc6af502013-12-10 08:01:08 -0800765 char sign = static_cast<char>(*s);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700766 if (arg.type > Arg::LAST_NUMERIC_TYPE) {
Victor Zverovich42de4f12014-08-27 08:24:31 -0700767 throw FormatError(fmt::format(
768 "format specifier '{}' requires numeric argument", sign));
Victor Zverovich7cae7632013-09-06 20:23:42 -0700769 }
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700770 if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
Victor Zverovich42de4f12014-08-27 08:24:31 -0700771 throw FormatError(fmt::format(
772 "format specifier '{}' requires signed argument", sign));
Victor Zverovich7cae7632013-09-06 20:23:42 -0700773 }
774 ++s;
775}
776
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700777const Arg *fmt::internal::FormatterBase::next_arg(const char *&error) {
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700778 if (next_arg_index_ < 0) {
Victor Zverovich9646e382014-08-27 09:13:42 -0700779 error = "cannot switch from manual to automatic argument indexing";
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700780 return 0;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700781 }
782 unsigned arg_index = next_arg_index_++;
783 if (arg_index < args_.size())
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700784 return &args_[arg_index];
Victor Zverovich9646e382014-08-27 09:13:42 -0700785 error = "argument index is out of range in format";
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700786 return 0;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700787}
788
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700789const Arg *fmt::internal::FormatterBase::get_arg(
790 unsigned arg_index, const char *&error) {
791 if (next_arg_index_ > 0) {
792 error = "cannot switch from automatic to manual argument indexing";
793 return 0;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700794 }
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700795 next_arg_index_ = -1;
796 if (arg_index < args_.size())
797 return &args_[arg_index];
798 error = "argument index is out of range in format";
799 return 0;
Victor Zverovich4edc88f2014-07-16 08:38:15 -0700800}
801
Victor Zverovich7cae7632013-09-06 20:23:42 -0700802template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700803void fmt::internal::PrintfFormatter<Char>::parse_flags(
Victor Zverovichcb743c02014-06-19 07:40:35 -0700804 FormatSpec &spec, const Char *&s) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700805 for (;;) {
Victor Zverovich1b801482014-06-07 08:57:55 -0700806 switch (*s++) {
Victor Zverovichbf790d22014-06-07 07:31:25 -0700807 case '-':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700808 spec.align_ = ALIGN_LEFT;
809 break;
810 case '+':
Victor Zverovichbf790d22014-06-07 07:31:25 -0700811 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
812 break;
813 case '0':
814 spec.fill_ = '0';
Victor Zverovich1b801482014-06-07 08:57:55 -0700815 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700816 case ' ':
Victor Zverovich1b801482014-06-07 08:57:55 -0700817 spec.flags_ |= SIGN_FLAG;
818 break;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700819 case '#':
Victor Zverovichcb743c02014-06-19 07:40:35 -0700820 spec.flags_ |= HASH_FLAG;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700821 break;
822 default:
Victor Zverovich1b801482014-06-07 08:57:55 -0700823 --s;
Victor Zverovichbf790d22014-06-07 07:31:25 -0700824 return;
825 }
826 }
827}
828
Victor Zverovichcb743c02014-06-19 07:40:35 -0700829template <typename Char>
Victor Zverovichc57d7a52014-08-28 08:05:47 -0700830const Arg &fmt::internal::PrintfFormatter<Char>::get_arg(
831 const Char *s, unsigned arg_index) {
832 const char *error = 0;
833 const Arg *arg = arg_index == UINT_MAX ?
834 next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
835 if (error)
836 throw FormatError(!*s ? "invalid format string" : error);
837 return *arg;
838}
839
840template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700841unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
Victor Zverovichf1dfd592014-07-16 08:49:23 -0700842 const Char *&s, FormatSpec &spec) {
Victor Zverovichcb743c02014-06-19 07:40:35 -0700843 unsigned arg_index = UINT_MAX;
844 Char c = *s;
845 if (c >= '0' && c <= '9') {
846 // Parse an argument index (if followed by '$') or a width possibly
Victor Zverovich879838a2014-06-20 07:34:02 -0700847 // preceded with '0' flag(s).
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700848 unsigned value = parse_nonnegative_int(s);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700849 if (*s == '$') { // value is an argument index
850 ++s;
851 arg_index = value;
852 } else {
853 if (c == '0')
854 spec.fill_ = '0';
855 if (value != 0) {
856 // Nonzero value means that we parsed width and don't need to
857 // parse it or flags again, so return now.
858 spec.width_ = value;
859 return arg_index;
860 }
861 }
862 }
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700863 parse_flags(spec, s);
Victor Zverovich4099a122014-06-23 08:10:50 -0700864 // Parse width.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700865 if (*s >= '0' && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700866 spec.width_ = parse_nonnegative_int(s);
Victor Zverovichcb743c02014-06-19 07:40:35 -0700867 } else if (*s == '*') {
868 ++s;
Victor Zverovich56fc5252014-08-28 07:48:55 -0700869 spec.width_ = WidthHandler(spec).visit(get_arg(s));
Victor Zverovichcb743c02014-06-19 07:40:35 -0700870 }
871 return arg_index;
872}
873
Victor Zverovich1f19b982014-06-16 07:49:30 -0700874template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700875void fmt::internal::PrintfFormatter<Char>::format(
Victor Zveroviche78904b2014-04-23 08:27:50 -0700876 BasicWriter<Char> &writer, BasicStringRef<Char> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700877 const ArgList &args) {
Victor Zveroviche78904b2014-04-23 08:27:50 -0700878 const Char *start = format.c_str();
Victor Zveroviche78904b2014-04-23 08:27:50 -0700879 args_ = args;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700880 next_arg_index_ = 0;
881 const Char *s = start;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700882 while (*s) {
Victor Zverovich0fc73162013-09-07 12:52:52 -0700883 Char c = *s++;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700884 if (c != '%') continue;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700885 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -0700886 write(writer, start, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700887 start = ++s;
888 continue;
889 }
Victor Zverovichc1db2932014-07-24 08:53:27 -0700890 write(writer, start, s - 1);
Victor Zverovich7cae7632013-09-06 20:23:42 -0700891
Victor Zverovichcb743c02014-06-19 07:40:35 -0700892 FormatSpec spec;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700893 spec.align_ = ALIGN_RIGHT;
Victor Zverovich7cae7632013-09-06 20:23:42 -0700894
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700895 // Parse argument index, flags and width.
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700896 unsigned arg_index = parse_header(s, spec);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700897
898 // Parse precision.
899 if (*s == '.') {
900 ++s;
901 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -0700902 spec.precision_ = parse_nonnegative_int(s);
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700903 } else if (*s == '*') {
904 ++s;
Victor Zverovich56fc5252014-08-28 07:48:55 -0700905 spec.precision_ = PrecisionHandler().visit(get_arg(s));
Victor Zverovich1a75ed02014-06-23 07:16:46 -0700906 }
907 }
908
Victor Zverovich56fc5252014-08-28 07:48:55 -0700909 Arg arg = get_arg(s, arg_index);
Victor Zveroviche4c4e4e2014-07-30 06:51:35 -0700910 if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
Victor Zverovichcb743c02014-06-19 07:40:35 -0700911 spec.flags_ &= ~HASH_FLAG;
912 if (spec.fill_ == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700913 if (arg.type <= Arg::LAST_NUMERIC_TYPE)
Victor Zverovichcb743c02014-06-19 07:40:35 -0700914 spec.align_ = ALIGN_NUMERIC;
915 else
916 spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700917 }
918
Victor Zverovichf4156b52014-07-30 08:39:07 -0700919 // Parse length and convert the argument to the required type.
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700920 switch (*s++) {
921 case 'h':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700922 if (*s == 'h')
923 ArgConverter<signed char>(arg, *++s).visit(arg);
Victor Zverovich39b09302014-07-30 08:08:08 -0700924 else
Victor Zverovichf4156b52014-07-30 08:39:07 -0700925 ArgConverter<short>(arg, *s).visit(arg);
Victor Zverovicheeca2232014-07-30 07:37:16 -0700926 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700927 case 'l':
Victor Zverovichd3a70392014-08-12 08:36:19 -0700928 if (*s == 'l')
Victor Zveroviche488a282014-08-13 06:53:43 -0700929 ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
Victor Zverovichd3a70392014-08-12 08:36:19 -0700930 else
931 ArgConverter<long>(arg, *s).visit(arg);
Victor Zverovichd81fafc2014-07-31 07:43:14 -0700932 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700933 case 'j':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700934 ArgConverter<intmax_t>(arg, *s).visit(arg);
935 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700936 case 'z':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700937 ArgConverter<size_t>(arg, *s).visit(arg);
938 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700939 case 't':
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700940 ArgConverter<ptrdiff_t>(arg, *s).visit(arg);
941 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700942 case 'L':
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700943 // printf produces garbage when 'L' is omitted for long double, no
944 // need to do the same.
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700945 break;
Victor Zverovich316ae7e2014-08-09 10:04:35 -0700946 default:
947 --s;
Victor Zverovichbe00d8b2014-08-19 08:49:10 -0700948 ArgConverter<int>(arg, *s).visit(arg);
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700949 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700950
951 // Parse type.
952 if (!*s)
953 throw FormatError("invalid format string");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700954 spec.type_ = static_cast<char>(*s++);
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700955 if (arg.type <= Arg::LAST_INTEGER_TYPE) {
956 // Normalize type.
957 switch (spec.type_) {
958 case 'i': case 'u':
Victor Zverovichf4156b52014-07-30 08:39:07 -0700959 spec.type_ = 'd';
Victor Zverovichc4a4a052014-08-19 08:14:21 -0700960 break;
961 case 'c':
962 // TODO: handle wchar_t
963 CharConverter(arg).visit(arg);
964 break;
965 }
Victor Zverovichf4156b52014-07-30 08:39:07 -0700966 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700967
968 start = s;
969
970 // Format argument.
Victor Zverovichcb743c02014-06-19 07:40:35 -0700971 switch (arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700972 case Arg::INT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700973 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700974 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700975 case Arg::UINT:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700976 writer.write_int(arg.uint_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700977 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700978 case Arg::LONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700979 writer.write_int(arg.long_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700980 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700981 case Arg::ULONG_LONG:
Victor Zverovichc1db2932014-07-24 08:53:27 -0700982 writer.write_int(arg.ulong_long_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700983 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -0700984 case Arg::CHAR: {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700985 if (spec.type_ && spec.type_ != 'c')
Victor Zverovichc1db2932014-07-24 08:53:27 -0700986 writer.write_int(arg.int_value, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700987 typedef typename BasicWriter<Char>::CharPtr CharPtr;
988 CharPtr out = CharPtr();
989 if (spec.width_ > 1) {
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700990 Char fill = ' ';
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700991 out = writer.grow_buffer(spec.width_);
Victor Zverovicha7d94f02014-07-22 12:37:10 -0700992 if (spec.align_ != ALIGN_LEFT) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700993 std::fill_n(out, spec.width_ - 1, fill);
994 out += spec.width_ - 1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -0700995 } else {
996 std::fill_n(out + 1, spec.width_ - 1, fill);
997 }
998 } else {
Victor Zverovich4d049cf2014-07-28 08:41:50 -0700999 out = writer.grow_buffer(1);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001000 }
Victor Zverovichcb743c02014-06-19 07:40:35 -07001001 *out = static_cast<Char>(arg.int_value);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001002 break;
1003 }
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001004 case Arg::DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001005 writer.write_double(arg.double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001006 break;
1007 case Arg::LONG_DOUBLE:
Victor Zverovichc1db2932014-07-24 08:53:27 -07001008 writer.write_double(arg.long_double_value, spec);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001009 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001010 case Arg::STRING:
Victor Zverovich53201032014-06-30 14:26:29 -07001011 writer.write_str(arg.string, spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001012 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001013 case Arg::WSTRING:
Victor Zverovich512e2ce2014-07-14 08:47:03 -07001014 writer.write_str(ignore_incompatible_str<Char>(arg.wstring), spec);
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001015 break;
1016 case Arg::POINTER:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001017 if (spec.type_ && spec.type_ != 'p')
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001018 internal::report_unknown_type(spec.type_, "pointer");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001019 spec.flags_= HASH_FLAG;
1020 spec.type_ = 'x';
Victor Zverovichc1db2932014-07-24 08:53:27 -07001021 writer.write_int(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001022 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001023 case Arg::CUSTOM:
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001024 if (spec.type_)
Victor Zverovichf634ccb2014-07-26 08:42:19 -07001025 internal::report_unknown_type(spec.type_, "object");
Victor Zveroviche8251562014-07-08 16:20:33 -07001026 arg.custom.format(&writer, arg.custom.value, "s");
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001027 break;
1028 default:
1029 assert(false);
1030 break;
1031 }
1032 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001033 write(writer, start, s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001034}
1035
1036template <typename Char>
Victor Zverovichb9a06ba2014-07-08 16:38:50 -07001037const Char *fmt::BasicFormatter<Char>::format(
Victor Zverovich512e2ce2014-07-14 08:47:03 -07001038 const Char *format_str, const Arg &arg) {
Victor Zveroviche8251562014-07-08 16:20:33 -07001039 const Char *s = format_str;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001040 const char *error = 0;
Victor Zveroviche8251562014-07-08 16:20:33 -07001041 FormatSpec spec;
1042 if (*s == ':') {
1043 if (arg.type == Arg::CUSTOM) {
1044 arg.custom.format(this, arg.custom.value, s);
1045 return find_closing_brace(s) + 1;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001046 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001047 ++s;
1048 // Parse fill and alignment.
1049 if (Char c = *s) {
1050 const Char *p = s + 1;
1051 spec.align_ = ALIGN_DEFAULT;
1052 do {
1053 switch (*p) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001054 case '<':
1055 spec.align_ = ALIGN_LEFT;
1056 break;
1057 case '>':
1058 spec.align_ = ALIGN_RIGHT;
1059 break;
1060 case '=':
1061 spec.align_ = ALIGN_NUMERIC;
1062 break;
1063 case '^':
1064 spec.align_ = ALIGN_CENTER;
1065 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001066 }
1067 if (spec.align_ != ALIGN_DEFAULT) {
1068 if (p != s) {
1069 if (c == '}') break;
1070 if (c == '{')
Victor Zverovich42de4f12014-08-27 08:24:31 -07001071 throw FormatError("invalid fill character '{'");
Victor Zveroviche8251562014-07-08 16:20:33 -07001072 s += 2;
1073 spec.fill_ = c;
1074 } else ++s;
1075 if (spec.align_ == ALIGN_NUMERIC && arg.type > Arg::LAST_NUMERIC_TYPE)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001076 throw FormatError("format specifier '=' requires numeric argument");
Victor Zveroviche8251562014-07-08 16:20:33 -07001077 break;
1078 }
1079 } while (--p >= s);
1080 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001081
Victor Zveroviche8251562014-07-08 16:20:33 -07001082 // Parse sign.
1083 switch (*s) {
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001084 case '+':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001085 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001086 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
1087 break;
1088 case '-':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001089 check_sign(s, arg);
Victor Zverovicha7d94f02014-07-22 12:37:10 -07001090 spec.flags_ |= MINUS_FLAG;
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001091 break;
1092 case ' ':
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001093 check_sign(s, arg);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001094 spec.flags_ |= SIGN_FLAG;
1095 break;
Victor Zveroviche8251562014-07-08 16:20:33 -07001096 }
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001097
Victor Zveroviche8251562014-07-08 16:20:33 -07001098 if (*s == '#') {
1099 if (arg.type > Arg::LAST_NUMERIC_TYPE)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001100 // TODO: make FormatError accept arguments
1101 throw FormatError("format specifier '#' requires numeric argument");
Victor Zveroviche8251562014-07-08 16:20:33 -07001102 spec.flags_ |= HASH_FLAG;
1103 ++s;
1104 }
1105
1106 // Parse width and zero flag.
1107 if ('0' <= *s && *s <= '9') {
1108 if (*s == '0') {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001109 if (arg.type > Arg::LAST_NUMERIC_TYPE)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001110 throw FormatError("format specifier '0' requires numeric argument");
Victor Zveroviche8251562014-07-08 16:20:33 -07001111 spec.align_ = ALIGN_NUMERIC;
1112 spec.fill_ = '0';
Victor Zverovich7cae7632013-09-06 20:23:42 -07001113 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001114 // Zero may be parsed again as a part of the width, but it is simpler
1115 // and more efficient than checking if the next char is a digit.
Victor Zverovich526b7fc2014-08-28 06:42:59 -07001116 spec.width_ = parse_nonnegative_int(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001117 if (error)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001118 throw FormatError(error);
Victor Zveroviche8251562014-07-08 16:20:33 -07001119 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001120
Victor Zveroviche8251562014-07-08 16:20:33 -07001121 // Parse precision.
1122 if (*s == '.') {
1123 ++s;
1124 spec.precision_ = 0;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001125 if ('0' <= *s && *s <= '9') {
Victor Zverovich526b7fc2014-08-28 06:42:59 -07001126 spec.precision_ = parse_nonnegative_int(s);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001127 if (error)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001128 throw FormatError(error);
Victor Zveroviche8251562014-07-08 16:20:33 -07001129 } else if (*s == '{') {
Victor Zverovich7cae7632013-09-06 20:23:42 -07001130 ++s;
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001131 const Arg &precision_arg = parse_arg_index(s);
Victor Zverovich42de4f12014-08-27 08:24:31 -07001132 if (*s++ != '}')
1133 throw FormatError("unmatched '{' in format");
Victor Zveroviche8251562014-07-08 16:20:33 -07001134 ULongLong value = 0;
1135 switch (precision_arg.type) {
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001136 case Arg::INT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001137 if (precision_arg.int_value < 0)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001138 throw FormatError("negative precision in format");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001139 value = precision_arg.int_value;
1140 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001141 case Arg::UINT:
Victor Zverovich7cae7632013-09-06 20:23:42 -07001142 value = precision_arg.uint_value;
1143 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001144 case Arg::LONG_LONG:
Victor Zverovich56f12b72013-11-22 07:45:43 -08001145 if (precision_arg.long_long_value < 0)
Victor Zverovich42de4f12014-08-27 08:24:31 -07001146 throw FormatError("negative precision in format");
Victor Zverovich56f12b72013-11-22 07:45:43 -08001147 value = precision_arg.long_long_value;
1148 break;
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001149 case Arg::ULONG_LONG:
Gregory Czajkowskia65542b2013-11-18 22:58:39 -08001150 value = precision_arg.ulong_long_value;
Victor Zverovicha4e72b42013-11-21 09:11:58 -08001151 break;
Victor Zverovich7cae7632013-09-06 20:23:42 -07001152 default:
Victor Zverovich42de4f12014-08-27 08:24:31 -07001153 throw FormatError("precision is not integer");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001154 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001155 if (value > INT_MAX)
Victor Zverovich279c7a62014-08-28 06:50:52 -07001156 throw FormatError("number is too big");
Victor Zveroviche8251562014-07-08 16:20:33 -07001157 spec.precision_ = static_cast<int>(value);
Victor Zveroviche8251562014-07-08 16:20:33 -07001158 } else {
Victor Zverovich42de4f12014-08-27 08:24:31 -07001159 throw FormatError("missing precision in format");
Victor Zverovich7cae7632013-09-06 20:23:42 -07001160 }
Victor Zveroviche8251562014-07-08 16:20:33 -07001161 if (arg.type != Arg::DOUBLE && arg.type != Arg::LONG_DOUBLE) {
Victor Zverovich42de4f12014-08-27 08:24:31 -07001162 throw FormatError(
Victor Zveroviche8251562014-07-08 16:20:33 -07001163 "precision specifier requires floating-point argument");
1164 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001165 }
1166
Victor Zveroviche8251562014-07-08 16:20:33 -07001167 // Parse type.
1168 if (*s != '}' && *s)
1169 spec.type_ = static_cast<char>(*s++);
1170 }
Victor Zverovich7cae7632013-09-06 20:23:42 -07001171
Victor Zveroviche8251562014-07-08 16:20:33 -07001172 if (*s++ != '}')
1173 throw FormatError("unmatched '{' in format");
1174 start_ = s;
1175
1176 // Format argument.
Victor Zverovich4edc88f2014-07-16 08:38:15 -07001177 internal::ArgFormatter<Char>(*this, spec, s - 1).visit(arg);
Victor Zveroviche8251562014-07-08 16:20:33 -07001178 return s;
1179}
1180
1181template <typename Char>
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001182void fmt::BasicFormatter<Char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001183 BasicStringRef<Char> format_str, const ArgList &args) {
1184 const Char *s = start_ = format_str.c_str();
1185 args_ = args;
1186 next_arg_index_ = 0;
1187 while (*s) {
1188 Char c = *s++;
1189 if (c != '{' && c != '}') continue;
1190 if (*s == c) {
Victor Zverovichc1db2932014-07-24 08:53:27 -07001191 write(writer_, start_, s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001192 start_ = ++s;
1193 continue;
1194 }
1195 if (c == '}')
1196 throw FormatError("unmatched '}' in format");
Victor Zverovichc1db2932014-07-24 08:53:27 -07001197 write(writer_, start_, s - 1);
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001198 Arg arg = parse_arg_index(s);
Victor Zveroviche8251562014-07-08 16:20:33 -07001199 s = format(s, arg);
1200 }
Victor Zverovichc1db2932014-07-24 08:53:27 -07001201 write(writer_, start_, s);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001202}
1203
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001204void fmt::report_system_error(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001205 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
Victor Zverovich75b5eb42014-07-27 15:09:05 -07001206 // FIXME: format_system_error may throw
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001207 report_error(internal::format_system_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001208}
1209
Victor Zverovich400812a2014-04-30 12:38:17 -07001210#ifdef _WIN32
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001211void fmt::report_windows_error(
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001212 int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
Victor Zverovich75b5eb42014-07-27 15:09:05 -07001213 // FIXME: format_windows_error may throw
Victor Zverovichd8b9f412014-07-29 06:38:05 -07001214 report_error(internal::format_windows_error, error_code, message);
Victor Zverovich1a2d7be2014-05-03 09:48:54 -07001215}
Victor Zverovich400812a2014-04-30 12:38:17 -07001216#endif
Victor Zverovichf7939862014-04-30 10:18:11 -07001217
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001218void fmt::print(std::FILE *f, StringRef format_str, const ArgList &args) {
Victor Zverovich2e039632014-06-28 19:44:39 -07001219 Writer w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001220 w.write(format_str, args);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001221 std::fwrite(w.data(), 1, w.size(), f);
1222}
1223
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001224void fmt::print(std::ostream &os, StringRef format_str, const ArgList &args) {
Victor Zveroviche3a44c12014-07-09 06:56:36 -07001225 Writer w;
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001226 w.write(format_str, args);
Victor Zveroviche3a44c12014-07-09 06:56:36 -07001227 os.write(w.data(), w.size());
1228}
1229
Victor Zverovich2dc108b2014-07-01 09:10:43 -07001230void fmt::print_colored(Color c, StringRef format, const ArgList &args) {
1231 char escape[] = "\x1b[30m";
1232 escape[3] = '0' + static_cast<char>(c);
1233 std::fputs(escape, stdout);
1234 print(format, args);
1235 std::fputs(RESET_COLOR, stdout);
1236}
1237
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001238int fmt::fprintf(std::FILE *f, StringRef format, const ArgList &args) {
Victor Zverovichd5b81962014-06-28 21:56:40 -07001239 Writer w;
Victor Zverovich21111cc2014-06-29 19:52:26 -07001240 printf(w, format, args);
Victor Zverovichdd4323f2014-08-21 08:49:13 -07001241 return std::fwrite(w.data(), 1, w.size(), f);
Victor Zverovichd5b81962014-06-28 21:56:40 -07001242}
1243
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001244// Explicit instantiations for char.
1245
Victor Zverovich93e41252013-09-08 13:07:04 -07001246template fmt::BasicWriter<char>::CharPtr
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001247 fmt::BasicWriter<char>::fill_padding(CharPtr buffer,
Victor Zverovich93e41252013-09-08 13:07:04 -07001248 unsigned total_size, std::size_t content_size, wchar_t fill);
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001249
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001250template void fmt::BasicFormatter<char>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001251 BasicStringRef<char> format, const ArgList &args);
Victor Zverovich7cae7632013-09-06 20:23:42 -07001252
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001253template void fmt::internal::PrintfFormatter<char>::format(
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001254 BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001255
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001256// Explicit instantiations for wchar_t.
1257
Victor Zverovich7cae7632013-09-06 20:23:42 -07001258template fmt::BasicWriter<wchar_t>::CharPtr
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001259 fmt::BasicWriter<wchar_t>::fill_padding(CharPtr buffer,
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001260 unsigned total_size, std::size_t content_size, wchar_t fill);
Victor Zverovich9ff3b972013-09-07 10:15:08 -07001261
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001262template void fmt::BasicFormatter<wchar_t>::format(
Victor Zveroviche8251562014-07-08 16:20:33 -07001263 BasicStringRef<wchar_t> format, const ArgList &args);
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001264
Victor Zverovich4d049cf2014-07-28 08:41:50 -07001265template void fmt::internal::PrintfFormatter<wchar_t>::format(
Victor Zverovichbf8b29f2014-06-06 06:38:37 -07001266 BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
Victor Zverovichea99bfb2014-06-24 07:54:26 -07001267 const ArgList &args);
jdale88a9862fd2014-03-11 18:56:24 +00001268
1269#if _MSC_VER
1270# pragma warning(pop)
1271#endif