blob: a0ba02df0b0a97d6cd90f8db636619c7b1314154 [file] [log] [blame]
Victor Zverovichb076df42012-12-07 08:31:09 -08001/*
Victor Zverovichfaccb4c2012-12-12 07:44:41 -08002 String formatting library for C++
3
4 Copyright (c) 2012, Victor Zverovich
5 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 Zverovichce604832012-12-28 08:27:54 -080034#include <math.h>
Victor Zverovichb98b2e92012-12-10 11:08:16 -080035
Victor Zverovichfbfedcf2013-01-14 15:16:20 -080036// Wrap signbit because when compiled in C++11 mode signbit is no longer a
37// macro but a function defined in namespace std and the macro is undefined.
38#ifndef _MSC_VER
39inline int SignBit(double value) { return signbit(value); }
40#endif
41
42#include "format.h"
43
Victor Zverovichb076df42012-12-07 08:31:09 -080044#include <cassert>
Victor Zverovich72f896d2012-12-12 09:17:28 -080045#include <cctype>
Victor Zverovich63539c02012-12-08 08:17:12 -080046#include <climits>
Victor Zverovichb076df42012-12-07 08:31:09 -080047#include <cstring>
48#include <algorithm>
49
50using std::size_t;
Victor Zverovich3f739872012-12-25 17:55:41 -080051using fmt::BasicFormatter;
Victor Zverovich877abaf2013-01-08 09:56:05 -080052using fmt::IntFormatter;
Victor Zverovich36335272012-12-12 15:21:11 -080053using fmt::Formatter;
Victor Zverovich3c90a872013-01-12 10:08:16 -080054using fmt::AlignSpec;
Victor Zverovichf28ecaf2012-12-21 09:14:18 -080055using fmt::FormatSpec;
Victor Zverovich877abaf2013-01-08 09:56:05 -080056using fmt::WidthSpec;
Victor Zverovich0f46a3d2012-12-25 13:30:42 -080057using fmt::StringRef;
Victor Zverovichb076df42012-12-07 08:31:09 -080058
Victor Zveroviche8ba9602012-12-12 09:29:50 -080059#if _MSC_VER
Victor Zverovichf8c91062012-12-17 15:41:00 -080060# undef snprintf
Victor Zveroviche8ba9602012-12-12 09:29:50 -080061# define snprintf _snprintf
Victor Zverovich251e8772012-12-29 09:54:57 -080062# define isinf(x) (!_finite(x))
Victor Zveroviche8ba9602012-12-12 09:29:50 -080063#endif
64
Victor Zverovich8b1c7092012-12-08 18:45:35 -080065namespace {
66
Victor Zverovichde17baa2013-01-04 09:14:34 -080067#ifdef _MSC_VER
Victor Zverovichfbfedcf2013-01-14 15:16:20 -080068int SignBit(double value) {
Victor Zverovichde17baa2013-01-04 09:14:34 -080069 if (value < 0) return 1;
70 if (value == value) return 0;
71 int dec = 0, sign = 0;
72 _ecvt(value, 0, &dec, &sign);
73 return sign;
74}
75#endif
76}
77
Victor Zverovich687301c2013-01-26 16:07:28 -080078const char fmt::internal::DIGITS[] =
79 "0001020304050607080910111213141516171819"
80 "2021222324252627282930313233343536373839"
81 "4041424344454647484950515253545556575859"
82 "6061626364656667686970717273747576777879"
83 "8081828384858687888990919293949596979899";
Victor Zverovich877abaf2013-01-08 09:56:05 -080084
Victor Zverovich687301c2013-01-26 16:07:28 -080085void fmt::internal::ReportUnknownType(char code, const char *type) {
Victor Zverovich877abaf2013-01-08 09:56:05 -080086 if (std::isprint(static_cast<unsigned char>(code))) {
87 throw fmt::FormatError(fmt::str(
Victor Zverovich687301c2013-01-26 16:07:28 -080088 fmt::Format("unknown format code '{}' for {}") << code << type));
Victor Zverovich877abaf2013-01-08 09:56:05 -080089 }
90 throw fmt::FormatError(
Victor Zverovich687301c2013-01-26 16:07:28 -080091 fmt::str(fmt::Format("unknown format code '\\x{:02x}' for {}")
Victor Zverovich877abaf2013-01-08 09:56:05 -080092 << static_cast<unsigned>(code) << type));
93}
94
Victor Zverovichde17baa2013-01-04 09:14:34 -080095// Throws Exception(message) if format contains '}', otherwise throws
96// FormatError reporting unmatched '{'. The idea is that unmatched '{'
97// should override other errors.
98void Formatter::ReportError(const char *s, StringRef message) const {
99 for (int num_open_braces = num_open_braces_; *s; ++s) {
100 if (*s == '{') {
101 ++num_open_braces;
102 } else if (*s == '}') {
103 if (--num_open_braces == 0)
104 throw fmt::FormatError(message);
105 }
106 }
107 throw fmt::FormatError("unmatched '{' in format");
108}
109
Victor Zverovich36335272012-12-12 15:21:11 -0800110// Parses an unsigned integer advancing s to the end of the parsed input.
111// This function assumes that the first character of s is a digit.
112unsigned Formatter::ParseUInt(const char *&s) const {
113 assert('0' <= *s && *s <= '9');
114 unsigned value = 0;
115 do {
116 unsigned new_value = value * 10 + (*s++ - '0');
117 if (new_value < value) // Check if value wrapped around.
118 ReportError(s, "number is too big in format");
119 value = new_value;
120 } while ('0' <= *s && *s <= '9');
121 return value;
122}
123
Victor Zverovichde17baa2013-01-04 09:14:34 -0800124inline const Formatter::Arg &Formatter::ParseArgIndex(const char *&s) {
Victor Zverovich8412ad62012-12-27 06:56:55 -0800125 unsigned arg_index = 0;
126 if (*s < '0' || *s > '9') {
127 if (*s != '}' && *s != ':')
128 ReportError(s, "invalid argument index in format string");
129 if (next_arg_index_ < 0) {
130 ReportError(s,
131 "cannot switch from manual to automatic argument indexing");
132 }
133 arg_index = next_arg_index_++;
134 } else {
135 if (next_arg_index_ > 0) {
136 ReportError(s,
137 "cannot switch from automatic to manual argument indexing");
138 }
139 next_arg_index_ = -1;
140 arg_index = ParseUInt(s);
141 if (arg_index >= args_.size())
142 ReportError(s, "argument index is out of range in format");
143 }
Victor Zverovich36335272012-12-12 15:21:11 -0800144 return *args_[arg_index];
145}
146
Victor Zverovich17ca8092012-12-25 13:45:12 -0800147void Formatter::CheckSign(const char *&s, const Arg &arg) {
148 if (arg.type > LAST_NUMERIC_TYPE) {
149 ReportError(s,
150 Format("format specifier '{0}' requires numeric argument") << *s);
151 }
152 if (arg.type == UINT || arg.type == ULONG) {
153 ReportError(s,
154 Format("format specifier '{0}' requires signed argument") << *s);
155 }
156 ++s;
157}
158
Victor Zverovich36335272012-12-12 15:21:11 -0800159void Formatter::DoFormat() {
Victor Zverovichb076df42012-12-07 08:31:09 -0800160 const char *start = format_;
Victor Zverovich57dbd2c2012-12-11 12:23:52 -0800161 format_ = 0;
Victor Zverovich8412ad62012-12-27 06:56:55 -0800162 next_arg_index_ = 0;
Victor Zverovichb076df42012-12-07 08:31:09 -0800163 const char *s = start;
Victor Zverovich5f3ed202012-12-07 17:48:10 -0800164 while (*s) {
Victor Zverovich31a50702012-12-10 15:04:55 -0800165 char c = *s++;
166 if (c != '{' && c != '}') continue;
167 if (*s == c) {
Victor Zverovich198ebe92012-12-10 17:16:08 -0800168 buffer_.append(start, s);
Victor Zverovich31a50702012-12-10 15:04:55 -0800169 start = ++s;
170 continue;
171 }
172 if (c == '}')
173 throw FormatError("unmatched '}' in format");
Victor Zverovich36335272012-12-12 15:21:11 -0800174 num_open_braces_= 1;
Victor Zverovich198ebe92012-12-10 17:16:08 -0800175 buffer_.append(start, s - 1);
Victor Zverovichb076df42012-12-07 08:31:09 -0800176
Victor Zverovich36335272012-12-12 15:21:11 -0800177 const Arg &arg = ParseArgIndex(s);
Victor Zverovichb076df42012-12-07 08:31:09 -0800178
Victor Zverovich64236892012-12-21 09:12:04 -0800179 FormatSpec spec;
Victor Zverovichb076df42012-12-07 08:31:09 -0800180 int precision = -1;
181 if (*s == ':') {
182 ++s;
Victor Zverovich64236892012-12-21 09:12:04 -0800183
184 // Parse fill and alignment.
Victor Zverovicha0d685c2012-12-20 20:10:55 -0800185 if (char c = *s) {
Victor Zverovich64236892012-12-21 09:12:04 -0800186 const char *p = s + 1;
Victor Zverovich877abaf2013-01-08 09:56:05 -0800187 spec.align_ = ALIGN_DEFAULT;
Victor Zverovich64236892012-12-21 09:12:04 -0800188 do {
189 switch (*p) {
190 case '<':
Victor Zverovich877abaf2013-01-08 09:56:05 -0800191 spec.align_ = ALIGN_LEFT;
Victor Zverovich64236892012-12-21 09:12:04 -0800192 break;
193 case '>':
Victor Zverovich877abaf2013-01-08 09:56:05 -0800194 spec.align_ = ALIGN_RIGHT;
Victor Zverovich64236892012-12-21 09:12:04 -0800195 break;
196 case '=':
Victor Zverovich877abaf2013-01-08 09:56:05 -0800197 spec.align_ = ALIGN_NUMERIC;
Victor Zverovich64236892012-12-21 09:12:04 -0800198 break;
199 case '^':
Victor Zverovich877abaf2013-01-08 09:56:05 -0800200 spec.align_ = ALIGN_CENTER;
Victor Zverovich64236892012-12-21 09:12:04 -0800201 break;
Victor Zverovicha0d685c2012-12-20 20:10:55 -0800202 }
Victor Zverovich877abaf2013-01-08 09:56:05 -0800203 if (spec.align_ != ALIGN_DEFAULT) {
Victor Zverovichccbe9412012-12-24 08:34:44 -0800204 if (p != s) {
205 if (c == '}') break;
206 if (c == '{')
207 ReportError(s, "invalid fill character '{'");
Victor Zverovich64236892012-12-21 09:12:04 -0800208 s += 2;
Victor Zverovich877abaf2013-01-08 09:56:05 -0800209 spec.fill_ = c;
Victor Zverovich64236892012-12-21 09:12:04 -0800210 } else ++s;
Victor Zverovich877abaf2013-01-08 09:56:05 -0800211 if (spec.align_ == ALIGN_NUMERIC && arg.type > LAST_NUMERIC_TYPE)
Victor Zverovichccbe9412012-12-24 08:34:44 -0800212 ReportError(s, "format specifier '=' requires numeric argument");
Victor Zverovich64236892012-12-21 09:12:04 -0800213 break;
214 }
215 } while (--p >= s);
Victor Zverovicha0d685c2012-12-20 20:10:55 -0800216 }
Victor Zverovich64236892012-12-21 09:12:04 -0800217
218 // Parse sign.
Victor Zverovich0a138ad2012-12-25 13:25:14 -0800219 switch (*s) {
220 case '+':
Victor Zverovich17ca8092012-12-25 13:45:12 -0800221 CheckSign(s, arg);
Victor Zverovich877abaf2013-01-08 09:56:05 -0800222 spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
Victor Zverovich17ca8092012-12-25 13:45:12 -0800223 break;
Victor Zverovich0a138ad2012-12-25 13:25:14 -0800224 case '-':
Victor Zverovich17ca8092012-12-25 13:45:12 -0800225 CheckSign(s, arg);
226 break;
227 case ' ':
228 CheckSign(s, arg);
Victor Zverovich877abaf2013-01-08 09:56:05 -0800229 spec.flags_ |= SIGN_FLAG;
Victor Zverovich0a138ad2012-12-25 13:25:14 -0800230 break;
Victor Zverovich8b1c7092012-12-08 18:45:35 -0800231 }
Victor Zverovichb076df42012-12-07 08:31:09 -0800232
Victor Zverovich73f13ee2012-12-25 18:19:51 -0800233 if (*s == '#') {
234 if (arg.type > LAST_NUMERIC_TYPE)
235 ReportError(s, "format specifier '#' requires numeric argument");
Victor Zverovich877abaf2013-01-08 09:56:05 -0800236 spec.flags_ |= HASH_FLAG;
Victor Zverovich73f13ee2012-12-25 18:19:51 -0800237 ++s;
238 }
239
Victor Zverovich64236892012-12-21 09:12:04 -0800240 // Parse width and zero flag.
Victor Zverovichb076df42012-12-07 08:31:09 -0800241 if ('0' <= *s && *s <= '9') {
Victor Zverovich64236892012-12-21 09:12:04 -0800242 if (*s == '0') {
243 if (arg.type > LAST_NUMERIC_TYPE)
244 ReportError(s, "format specifier '0' requires numeric argument");
Victor Zverovich877abaf2013-01-08 09:56:05 -0800245 spec.align_ = ALIGN_NUMERIC;
246 spec.fill_ = '0';
Victor Zverovich64236892012-12-21 09:12:04 -0800247 }
248 // Zero may be parsed again as a part of the width, but it is simpler
249 // and more efficient than checking if the next char is a digit.
Victor Zverovich095b43a2012-12-09 11:32:39 -0800250 unsigned value = ParseUInt(s);
251 if (value > INT_MAX)
Victor Zverovichb98b2e92012-12-10 11:08:16 -0800252 ReportError(s, "number is too big in format");
Victor Zverovich877abaf2013-01-08 09:56:05 -0800253 spec.width_ = value;
Victor Zverovichb076df42012-12-07 08:31:09 -0800254 }
255
256 // Parse precision.
257 if (*s == '.') {
Victor Zverovichb076df42012-12-07 08:31:09 -0800258 ++s;
259 precision = 0;
260 if ('0' <= *s && *s <= '9') {
Victor Zverovich095b43a2012-12-09 11:32:39 -0800261 unsigned value = ParseUInt(s);
262 if (value > INT_MAX)
Victor Zverovichb98b2e92012-12-10 11:08:16 -0800263 ReportError(s, "number is too big in format");
Victor Zverovich095b43a2012-12-09 11:32:39 -0800264 precision = value;
Victor Zverovich36335272012-12-12 15:21:11 -0800265 } else if (*s == '{') {
266 ++s;
267 ++num_open_braces_;
268 const Arg &precision_arg = ParseArgIndex(s);
269 unsigned long value = 0;
270 switch (precision_arg.type) {
271 case INT:
272 if (precision_arg.int_value < 0)
273 ReportError(s, "negative precision in format");
274 value = precision_arg.int_value;
275 break;
276 case UINT:
277 value = precision_arg.uint_value;
278 break;
279 case LONG:
280 if (precision_arg.long_value < 0)
281 ReportError(s, "negative precision in format");
282 value = precision_arg.long_value;
283 break;
284 case ULONG:
285 value = precision_arg.ulong_value;
286 break;
287 default:
288 ReportError(s, "precision is not integer");
289 }
290 if (value > INT_MAX)
291 ReportError(s, "number is too big in format");
292 precision = value;
293 if (*s++ != '}')
294 throw FormatError("unmatched '{' in format");
295 --num_open_braces_;
Victor Zverovichb076df42012-12-07 08:31:09 -0800296 } else {
Victor Zverovichb98b2e92012-12-10 11:08:16 -0800297 ReportError(s, "missing precision in format");
Victor Zverovichbbd13a42012-12-09 14:13:23 -0800298 }
Victor Zverovichb98b2e92012-12-10 11:08:16 -0800299 if (arg.type != DOUBLE && arg.type != LONG_DOUBLE) {
300 ReportError(s,
301 "precision specifier requires floating-point argument");
Victor Zverovichb076df42012-12-07 08:31:09 -0800302 }
303 }
304
305 // Parse type.
Victor Zverovichb98b2e92012-12-10 11:08:16 -0800306 if (*s != '}' && *s)
Victor Zverovich877abaf2013-01-08 09:56:05 -0800307 spec.type_ = *s++;
Victor Zverovichb076df42012-12-07 08:31:09 -0800308 }
309
310 if (*s++ != '}')
Victor Zverovich8b1c7092012-12-08 18:45:35 -0800311 throw FormatError("unmatched '{' in format");
Victor Zverovichb076df42012-12-07 08:31:09 -0800312 start = s;
313
314 // Format argument.
Victor Zverovichb076df42012-12-07 08:31:09 -0800315 switch (arg.type) {
Victor Zverovichb076df42012-12-07 08:31:09 -0800316 case INT:
Victor Zverovicha0d685c2012-12-20 20:10:55 -0800317 FormatInt(arg.int_value, spec);
Victor Zverovichb076df42012-12-07 08:31:09 -0800318 break;
319 case UINT:
Victor Zverovicha0d685c2012-12-20 20:10:55 -0800320 FormatInt(arg.uint_value, spec);
Victor Zverovichb076df42012-12-07 08:31:09 -0800321 break;
322 case LONG:
Victor Zverovicha0d685c2012-12-20 20:10:55 -0800323 FormatInt(arg.long_value, spec);
Victor Zverovichb076df42012-12-07 08:31:09 -0800324 break;
325 case ULONG:
Victor Zverovicha0d685c2012-12-20 20:10:55 -0800326 FormatInt(arg.ulong_value, spec);
Victor Zverovichb076df42012-12-07 08:31:09 -0800327 break;
328 case DOUBLE:
Victor Zverovicha0d685c2012-12-20 20:10:55 -0800329 FormatDouble(arg.double_value, spec, precision);
Victor Zverovichb076df42012-12-07 08:31:09 -0800330 break;
331 case LONG_DOUBLE:
Victor Zverovicha0d685c2012-12-20 20:10:55 -0800332 FormatDouble(arg.long_double_value, spec, precision);
Victor Zverovichbbd13a42012-12-09 14:13:23 -0800333 break;
Victor Zverovich198ebe92012-12-10 17:16:08 -0800334 case CHAR: {
Victor Zverovich877abaf2013-01-08 09:56:05 -0800335 if (spec.type_ && spec.type_ != 'c')
Victor Zverovich687301c2013-01-26 16:07:28 -0800336 internal::ReportUnknownType(spec.type_, "char");
Victor Zverovich1b9c22c2012-12-22 17:53:13 -0800337 char *out = 0;
Victor Zverovich877abaf2013-01-08 09:56:05 -0800338 if (spec.width_ > 1) {
339 out = GrowBuffer(spec.width_);
340 if (spec.align_ == ALIGN_RIGHT) {
341 std::fill_n(out, spec.width_ - 1, spec.fill_);
342 out += spec.width_ - 1;
343 } else if (spec.align_ == ALIGN_CENTER) {
344 out = FillPadding(out, spec.width_, 1, spec.fill_);
Victor Zverovich26d2ae62012-12-24 11:58:49 -0800345 } else {
Victor Zverovich877abaf2013-01-08 09:56:05 -0800346 std::fill_n(out + 1, spec.width_ - 1, spec.fill_);
Victor Zverovich26d2ae62012-12-24 11:58:49 -0800347 }
Victor Zverovich1b9c22c2012-12-22 17:53:13 -0800348 } else {
349 out = GrowBuffer(1);
350 }
351 *out = arg.int_value;
Victor Zverovichbbd13a42012-12-09 14:13:23 -0800352 break;
Victor Zverovich198ebe92012-12-10 17:16:08 -0800353 }
Victor Zverovichb98b2e92012-12-10 11:08:16 -0800354 case STRING: {
Victor Zverovich877abaf2013-01-08 09:56:05 -0800355 if (spec.type_ && spec.type_ != 's')
Victor Zverovich687301c2013-01-26 16:07:28 -0800356 internal::ReportUnknownType(spec.type_, "string");
Victor Zverovich33bb6ee2012-12-11 21:47:05 -0800357 const char *str = arg.string.value;
358 size_t size = arg.string.size;
Victor Zverovich1b3c1972012-12-17 16:39:49 -0800359 if (size == 0) {
360 if (!str)
361 throw FormatError("string pointer is null");
362 if (*str)
363 size = std::strlen(str);
364 }
Victor Zverovich1b9c22c2012-12-22 17:53:13 -0800365 FormatString(str, size, spec);
Victor Zverovichb076df42012-12-07 08:31:09 -0800366 break;
Victor Zverovichb98b2e92012-12-10 11:08:16 -0800367 }
368 case POINTER:
Victor Zverovich877abaf2013-01-08 09:56:05 -0800369 if (spec.type_ && spec.type_ != 'p')
Victor Zverovich687301c2013-01-26 16:07:28 -0800370 internal::ReportUnknownType(spec.type_, "pointer");
Victor Zverovich877abaf2013-01-08 09:56:05 -0800371 spec.flags_= HASH_FLAG;
372 spec.type_ = 'x';
Victor Zverovicha0d685c2012-12-20 20:10:55 -0800373 FormatInt(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
Victor Zverovichb076df42012-12-07 08:31:09 -0800374 break;
Victor Zverovich280ea8b2012-12-09 09:03:47 -0800375 case CUSTOM:
Victor Zverovich877abaf2013-01-08 09:56:05 -0800376 if (spec.type_)
Victor Zverovich687301c2013-01-26 16:07:28 -0800377 internal::ReportUnknownType(spec.type_, "object");
Victor Zverovicha0d685c2012-12-20 20:10:55 -0800378 (this->*arg.custom.format)(arg.custom.value, spec);
Victor Zverovich63539c02012-12-08 08:17:12 -0800379 break;
Victor Zverovichb076df42012-12-07 08:31:09 -0800380 default:
381 assert(false);
382 break;
383 }
384 }
Victor Zverovichde17baa2013-01-04 09:14:34 -0800385 buffer_.append(start, s);
Victor Zverovichb076df42012-12-07 08:31:09 -0800386}