1 // Formatting library for C++
3 // Copyright (c) 2012 - 2016, Victor Zverovich
4 // All rights reserved.
6 // For the license information refer to format.h.
8 #ifndef FMT_FORMAT_INL_H_
9 #define FMT_FORMAT_INL_H_
20 #include <cstddef> // for std::ptrdiff_t
21 #include <cstring> // for std::memmove
22 #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
27 # if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)
28 # define WIN32_LEAN_AND_MEAN
30 # if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
41 # define FMT_CATCH(x) catch (x)
43 # define FMT_TRY if (true)
44 # define FMT_CATCH(x) if (false)
48 # pragma warning(push)
49 # pragma warning(disable: 4127) // conditional expression is constant
50 # pragma warning(disable: 4702) // unreachable code
51 // Disable deprecation warning for strerror. The latter is not called but
52 // MSVC fails to detect it.
53 # pragma warning(disable: 4996)
56 // Dummy implementations of strerror_r and strerror_s called if corresponding
57 // system functions are not available.
58 inline fmt::internal::null
<> strerror_r(int, char *, ...) {
59 return fmt::internal::null
<>();
61 inline fmt::internal::null
<> strerror_s(char *, std::size_t, ...) {
62 return fmt::internal::null
<>();
70 # define FMT_SNPRINTF snprintf
72 inline int fmt_snprintf(char *buffer
, size_t size
, const char *format
, ...) {
74 va_start(args
, format
);
75 int result
= vsnprintf_s(buffer
, size
, _TRUNCATE
, format
, args
);
79 # define FMT_SNPRINTF fmt_snprintf
82 #if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
83 # define FMT_SWPRINTF snwprintf
85 # define FMT_SWPRINTF swprintf
86 #endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
88 typedef void (*FormatFunc
)(internal::buffer
&, int, string_view
);
90 // Portable thread-safe version of strerror.
91 // Sets buffer to point to a string describing the error code.
92 // This can be either a pointer to a string stored in buffer,
93 // or a pointer to some static immutable string.
94 // Returns one of the following values:
96 // ERANGE - buffer is not large enough to store the error message
98 // Buffer should be at least of size 1.
100 int error_code
, char *&buffer
, std::size_t buffer_size
) FMT_NOEXCEPT
{
101 FMT_ASSERT(buffer
!= FMT_NULL
&& buffer_size
!= 0, "invalid buffer");
107 std::size_t buffer_size_
;
109 // A noop assignment operator to avoid bogus warnings.
110 void operator=(const dispatcher
&) {}
112 // Handle the result of XSI-compliant version of strerror_r.
113 int handle(int result
) {
114 // glibc versions before 2.13 return result in errno.
115 return result
== -1 ? errno
: result
;
118 // Handle the result of GNU-specific version of strerror_r.
119 int handle(char *message
) {
120 // If the buffer is full then the message is probably truncated.
121 if (message
== buffer_
&& strlen(buffer_
) == buffer_size_
- 1)
127 // Handle the case when strerror_r is not available.
128 int handle(internal::null
<>) {
129 return fallback(strerror_s(buffer_
, buffer_size_
, error_code_
));
132 // Fallback to strerror_s when strerror_r is not available.
133 int fallback(int result
) {
134 // If the buffer is full then the message is probably truncated.
135 return result
== 0 && strlen(buffer_
) == buffer_size_
- 1 ?
139 // Fallback to strerror if strerror_r and strerror_s are not available.
140 int fallback(internal::null
<>) {
142 buffer_
= strerror(error_code_
);
147 dispatcher(int err_code
, char *&buf
, std::size_t buf_size
)
148 : error_code_(err_code
), buffer_(buf
), buffer_size_(buf_size
) {}
151 return handle(strerror_r(error_code_
, buffer_
, buffer_size_
));
154 return dispatcher(error_code
, buffer
, buffer_size
).run();
157 void format_error_code(internal::buffer
&out
, int error_code
,
158 string_view message
) FMT_NOEXCEPT
{
159 // Report error code making sure that the output fits into
160 // inline_buffer_size to avoid dynamic memory allocation and potential
163 static const char SEP
[] = ": ";
164 static const char ERROR_STR
[] = "error ";
165 // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
166 std::size_t error_code_size
= sizeof(SEP
) + sizeof(ERROR_STR
) - 2;
167 typedef internal::int_traits
<int>::main_type main_type
;
168 main_type abs_value
= static_cast<main_type
>(error_code
);
169 if (internal::is_negative(error_code
)) {
170 abs_value
= 0 - abs_value
;
173 error_code_size
+= internal::count_digits(abs_value
);
175 if (message
.size() <= inline_buffer_size
- error_code_size
) {
181 assert(out
.size() <= inline_buffer_size
);
184 void report_error(FormatFunc func
, int error_code
,
185 string_view message
) FMT_NOEXCEPT
{
186 memory_buffer full_message
;
187 func(full_message
, error_code
, message
);
188 // Use Writer::data instead of Writer::c_str to avoid potential memory
190 std::fwrite(full_message
.data(), full_message
.size(), 1, stderr
);
191 std::fputc('\n', stderr
);
195 #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
201 explicit locale(std::locale loc
= std::locale()) : locale_(loc
) {}
202 std::locale
get() { return locale_
; }
205 FMT_FUNC
size_t internal::count_code_points(u8string_view s
) {
206 const char8_t
*data
= s
.data();
207 int num_code_points
= 0;
208 for (size_t i
= 0, size
= s
.size(); i
!= size
; ++i
) {
209 if ((data
[i
].value
& 0xc0) != 0x80)
212 return num_code_points
;
215 template <typename Char
>
216 FMT_FUNC Char
internal::thousands_sep(locale_provider
*lp
) {
217 std::locale loc
= lp
? lp
->locale().get() : std::locale();
218 return std::use_facet
<std::numpunct
<Char
>>(loc
).thousands_sep();
221 template <typename Char
>
222 FMT_FUNC Char
internal::thousands_sep(locale_provider
*lp
) {
223 return FMT_STATIC_THOUSANDS_SEPARATOR
;
227 FMT_FUNC
void system_error::init(
228 int err_code
, string_view format_str
, format_args args
) {
229 error_code_
= err_code
;
230 memory_buffer buffer
;
231 format_system_error(buffer
, err_code
, vformat(format_str
, args
));
232 std::runtime_error
&base
= *this;
233 base
= std::runtime_error(to_string(buffer
));
237 template <typename T
>
238 int char_traits
<char>::format_float(
239 char *buffer
, std::size_t size
, const char *format
, int precision
, T value
) {
240 return precision
< 0 ?
241 FMT_SNPRINTF(buffer
, size
, format
, value
) :
242 FMT_SNPRINTF(buffer
, size
, format
, precision
, value
);
245 template <typename T
>
246 int char_traits
<wchar_t>::format_float(
247 wchar_t *buffer
, std::size_t size
, const wchar_t *format
, int precision
,
249 return precision
< 0 ?
250 FMT_SWPRINTF(buffer
, size
, format
, value
) :
251 FMT_SWPRINTF(buffer
, size
, format
, precision
, value
);
254 template <typename T
>
255 const char basic_data
<T
>::DIGITS
[] =
256 "0001020304050607080910111213141516171819"
257 "2021222324252627282930313233343536373839"
258 "4041424344454647484950515253545556575859"
259 "6061626364656667686970717273747576777879"
260 "8081828384858687888990919293949596979899";
262 #define FMT_POWERS_OF_10(factor) \
270 factor * 100000000, \
273 template <typename T
>
274 const uint32_t basic_data
<T
>::POWERS_OF_10_32
[] = {
275 1, FMT_POWERS_OF_10(1)
278 template <typename T
>
279 const uint32_t basic_data
<T
>::ZERO_OR_POWERS_OF_10_32
[] = {
280 0, FMT_POWERS_OF_10(1)
283 template <typename T
>
284 const uint64_t basic_data
<T
>::ZERO_OR_POWERS_OF_10_64
[] = {
287 FMT_POWERS_OF_10(1000000000ull),
288 10000000000000000000ull
291 // Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.
292 // These are generated by support/compute-powers.py.
293 template <typename T
>
294 const uint64_t basic_data
<T
>::POW10_SIGNIFICANDS
[] = {
295 0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76,
296 0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df,
297 0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c,
298 0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5,
299 0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57,
300 0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7,
301 0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e,
302 0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996,
303 0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126,
304 0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053,
305 0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f,
306 0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b,
307 0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06,
308 0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb,
309 0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000,
310 0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984,
311 0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068,
312 0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8,
313 0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758,
314 0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85,
315 0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d,
316 0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25,
317 0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2,
318 0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a,
319 0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410,
320 0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129,
321 0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85,
322 0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841,
323 0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b,
326 // Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding
327 // to significands above.
328 template <typename T
>
329 const int16_t basic_data
<T
>::POW10_EXPONENTS
[] = {
330 -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954,
331 -927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661,
332 -635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369,
333 -343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77,
334 -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216,
335 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508,
336 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800,
337 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066
340 template <typename T
> const char basic_data
<T
>::RESET_COLOR
[] = "\x1b[0m";
341 template <typename T
> const wchar_t basic_data
<T
>::WRESET_COLOR
[] = L
"\x1b[0m";
343 // A handmade floating-point number f * pow(2, e).
346 typedef uint64_t significand_type
;
348 // All sizes are in bits.
349 static FMT_CONSTEXPR_DECL
const int char_size
=
350 std::numeric_limits
<unsigned char>::digits
;
351 // Subtract 1 to account for an implicit most significant bit in the
353 static FMT_CONSTEXPR_DECL
const int double_significand_size
=
354 std::numeric_limits
<double>::digits
- 1;
355 static FMT_CONSTEXPR_DECL
const uint64_t implicit_bit
=
356 1ull << double_significand_size
;
362 static FMT_CONSTEXPR_DECL
const int significand_size
=
363 sizeof(significand_type
) * char_size
;
366 fp(uint64_t f
, int e
): f(f
), e(e
) {}
368 // Constructs fp from an IEEE754 double. It is a template to prevent compile
369 // errors on platforms where double is not IEEE754.
370 template <typename Double
>
371 explicit fp(Double d
) {
372 // Assume double is in the format [sign][exponent][significand].
373 typedef std::numeric_limits
<Double
> limits
;
374 const int double_size
= static_cast<int>(sizeof(Double
) * char_size
);
375 const int exponent_size
=
376 double_size
- double_significand_size
- 1; // -1 for sign
377 const uint64_t significand_mask
= implicit_bit
- 1;
378 const uint64_t exponent_mask
= (~0ull >> 1) & ~significand_mask
;
379 const int exponent_bias
= (1 << exponent_size
) - limits::max_exponent
- 1;
380 auto u
= bit_cast
<uint64_t>(d
);
381 auto biased_e
= (u
& exponent_mask
) >> double_significand_size
;
382 f
= u
& significand_mask
;
386 biased_e
= 1; // Subnormals use biased exponent 1 (min exponent).
387 e
= static_cast<int>(biased_e
- exponent_bias
- double_significand_size
);
390 // Normalizes the value converted from double and multiplied by (1 << SHIFT).
391 template <int SHIFT
= 0>
393 // Handle subnormals.
394 auto shifted_implicit_bit
= implicit_bit
<< SHIFT
;
395 while ((f
& shifted_implicit_bit
) == 0) {
399 // Subtract 1 to account for hidden bit.
400 auto offset
= significand_size
- double_significand_size
- SHIFT
- 1;
405 // Compute lower and upper boundaries (m^- and m^+ in the Grisu paper), where
406 // a boundary is a value half way between the number and its predecessor
407 // (lower) or successor (upper). The upper boundary is normalized and lower
408 // has the same exponent but may be not normalized.
409 void compute_boundaries(fp
&lower
, fp
&upper
) const {
410 lower
= f
== implicit_bit
?
411 fp((f
<< 2) - 1, e
- 2) : fp((f
<< 1) - 1, e
- 1);
412 upper
= fp((f
<< 1) + 1, e
- 1);
413 upper
.normalize
<1>(); // 1 is to account for the exponent shift above.
414 lower
.f
<<= lower
.e
- upper
.e
;
419 // Returns an fp number representing x - y. Result may not be normalized.
420 inline fp
operator-(fp x
, fp y
) {
421 FMT_ASSERT(x
.f
>= y
.f
&& x
.e
== y
.e
, "invalid operands");
422 return fp(x
.f
- y
.f
, x
.e
);
425 // Computes an fp number r with r.f = x.f * y.f / pow(2, 64) rounded to nearest
426 // with half-up tie breaking, r.e = x.e + y.e + 64. Result may not be normalized.
427 FMT_API fp
operator*(fp x
, fp y
);
429 // Returns cached power (of 10) c_k = c_k.f * pow(2, c_k.e) such that its
430 // (binary) exponent satisfies min_exponent <= c_k.e <= min_exponent + 3.
431 FMT_API fp
get_cached_power(int min_exponent
, int &pow10_exponent
);
433 FMT_FUNC fp
operator*(fp x
, fp y
) {
434 // Multiply 32-bit parts of significands.
435 uint64_t mask
= (1ULL << 32) - 1;
436 uint64_t a
= x
.f
>> 32, b
= x
.f
& mask
;
437 uint64_t c
= y
.f
>> 32, d
= y
.f
& mask
;
438 uint64_t ac
= a
* c
, bc
= b
* c
, ad
= a
* d
, bd
= b
* d
;
439 // Compute mid 64-bit of result and round.
440 uint64_t mid
= (bd
>> 32) + (ad
& mask
) + (bc
& mask
) + (1U << 31);
441 return fp(ac
+ (ad
>> 32) + (bc
>> 32) + (mid
>> 32), x
.e
+ y
.e
+ 64);
444 FMT_FUNC fp
get_cached_power(int min_exponent
, int &pow10_exponent
) {
445 const double one_over_log2_10
= 0.30102999566398114; // 1 / log2(10)
446 int index
= static_cast<int>(std::ceil(
447 (min_exponent
+ fp::significand_size
- 1) * one_over_log2_10
));
448 // Decimal exponent of the first (smallest) cached power of 10.
449 const int first_dec_exp
= -348;
450 // Difference between 2 consecutive decimal exponents in cached powers of 10.
451 const int dec_exp_step
= 8;
452 index
= (index
- first_dec_exp
- 1) / dec_exp_step
+ 1;
453 pow10_exponent
= first_dec_exp
+ index
* dec_exp_step
;
454 return fp(data::POW10_SIGNIFICANDS
[index
], data::POW10_EXPONENTS
[index
]);
457 // Generates output using Grisu2 digit-gen algorithm.
458 FMT_FUNC
void grisu2_gen_digits(
459 const fp
&scaled_value
, const fp
&scaled_upper
, uint64_t delta
,
460 char *buffer
, size_t &size
, int &dec_exp
) {
461 internal::fp
one(1ull << -scaled_upper
.e
, scaled_upper
.e
);
462 // hi (p1 in Grisu) contains the most significant digits of scaled_upper.
463 // hi = floor(scaled_upper / one).
464 uint32_t hi
= static_cast<uint32_t>(scaled_upper
.f
>> -one
.e
);
465 // lo (p2 in Grisu) contains the least significants digits of scaled_upper.
466 // lo = scaled_upper mod 1.
467 uint64_t lo
= scaled_upper
.f
& (one
.f
- 1);
469 auto exp
= count_digits(hi
); // kappa in Grisu.
472 // This optimization by miloyip reduces the number of integer divisions by
473 // one per iteration.
475 case 10: digit
= hi
/ 1000000000; hi
%= 1000000000; break;
476 case 9: digit
= hi
/ 100000000; hi
%= 100000000; break;
477 case 8: digit
= hi
/ 10000000; hi
%= 10000000; break;
478 case 7: digit
= hi
/ 1000000; hi
%= 1000000; break;
479 case 6: digit
= hi
/ 100000; hi
%= 100000; break;
480 case 5: digit
= hi
/ 10000; hi
%= 10000; break;
481 case 4: digit
= hi
/ 1000; hi
%= 1000; break;
482 case 3: digit
= hi
/ 100; hi
%= 100; break;
483 case 2: digit
= hi
/ 10; hi
%= 10; break;
484 case 1: digit
= hi
; hi
= 0; break;
486 FMT_ASSERT(false, "invalid number of digits");
488 if (digit
!= 0 || size
!= 0)
489 buffer
[size
++] = static_cast<char>('0' + digit
);
491 uint64_t remainder
= (static_cast<uint64_t>(hi
) << -one
.e
) + lo
;
492 if (remainder
<= delta
) {
494 // TODO: use scaled_value
502 char digit
= static_cast<char>(lo
>> -one
.e
);
503 if (digit
!= 0 || size
!= 0)
504 buffer
[size
++] = static_cast<char>('0' + digit
);
514 FMT_FUNC
void grisu2_format_positive(double value
, char *buffer
, size_t &size
,
516 FMT_ASSERT(value
> 0, "value is nonpositive");
518 fp lower
, upper
; // w^- and w^+ in the Grisu paper.
519 fp_value
.compute_boundaries(lower
, upper
);
520 // Find a cached power of 10 close to 1 / upper.
521 const int min_exp
= -60; // alpha in Grisu.
522 auto dec_pow
= get_cached_power( // \tilde{c}_{-k} in Grisu.
523 min_exp
- (upper
.e
+ fp::significand_size
), dec_exp
);
525 fp_value
.normalize();
526 fp scaled_value
= fp_value
* dec_pow
;
527 fp scaled_lower
= lower
* dec_pow
; // \tilde{M}^- in Grisu.
528 fp scaled_upper
= upper
* dec_pow
; // \tilde{M}^+ in Grisu.
529 ++scaled_lower
.f
; // \tilde{M}^- + 1 ulp -> M^-_{\uparrow}.
530 --scaled_upper
.f
; // \tilde{M}^+ - 1 ulp -> M^+_{\downarrow}.
531 uint64_t delta
= scaled_upper
.f
- scaled_lower
.f
;
532 grisu2_gen_digits(scaled_value
, scaled_upper
, delta
, buffer
, size
, dec_exp
);
535 FMT_FUNC
void round(char *buffer
, size_t &size
, int &exp
,
536 int digits_to_remove
) {
537 size
-= to_unsigned(digits_to_remove
);
538 exp
+= digits_to_remove
;
539 int digit
= buffer
[size
] - '0';
540 // TODO: proper rounding and carry
541 if (digit
> 5 || (digit
== 5 && (digits_to_remove
> 1 ||
542 (buffer
[size
- 1] - '0') % 2) != 0)) {
547 // Writes the exponent exp in the form "[+-]d{1,3}" to buffer.
548 FMT_FUNC
char *write_exponent(char *buffer
, int exp
) {
549 FMT_ASSERT(-1000 < exp
&& exp
< 1000, "exponent out of range");
557 *buffer
++ = static_cast<char>('0' + exp
/ 100);
559 const char *d
= data::DIGITS
+ exp
* 2;
563 const char *d
= data::DIGITS
+ exp
* 2;
570 FMT_FUNC
void format_exp_notation(
571 char *buffer
, size_t &size
, int exp
, int precision
, bool upper
) {
572 // Insert a decimal point after the first digit and add an exponent.
573 std::memmove(buffer
+ 2, buffer
+ 1, size
- 1);
575 exp
+= static_cast<int>(size
) - 1;
576 int num_digits
= precision
- static_cast<int>(size
) + 1;
577 if (num_digits
> 0) {
578 std::uninitialized_fill_n(buffer
+ size
+ 1, num_digits
, '0');
579 size
+= to_unsigned(num_digits
);
580 } else if (num_digits
< 0) {
581 round(buffer
, size
, exp
, -num_digits
);
583 char *p
= buffer
+ size
+ 1;
584 *p
++ = upper
? 'E' : 'e';
585 size
= to_unsigned(write_exponent(p
, exp
) - buffer
);
588 // Prettifies the output of the Grisu2 algorithm.
589 // The number is given as v = buffer * 10^exp.
590 FMT_FUNC
void grisu2_prettify(char *buffer
, size_t &size
, int exp
,
591 int precision
, bool upper
) {
592 // pow(10, full_exp - 1) <= v <= pow(10, full_exp).
593 int int_size
= static_cast<int>(size
);
594 int full_exp
= int_size
+ exp
;
595 const int exp_threshold
= 21;
596 if (int_size
<= full_exp
&& full_exp
<= exp_threshold
) {
597 // 1234e7 -> 12340000000[.0+]
598 std::uninitialized_fill_n(buffer
+ int_size
, full_exp
- int_size
, '0');
599 char *p
= buffer
+ full_exp
;
602 std::uninitialized_fill_n(p
, precision
, '0');
605 size
= to_unsigned(p
- buffer
);
606 } else if (0 < full_exp
&& full_exp
<= exp_threshold
) {
607 // 1234e-2 -> 12.34[0+]
608 int fractional_size
= -exp
;
609 std::memmove(buffer
+ full_exp
+ 1, buffer
+ full_exp
,
610 to_unsigned(fractional_size
));
611 buffer
[full_exp
] = '.';
612 int num_zeros
= precision
- fractional_size
;
614 std::uninitialized_fill_n(buffer
+ size
+ 1, num_zeros
, '0');
615 size
+= to_unsigned(num_zeros
);
618 } else if (-6 < full_exp
&& full_exp
<= 0) {
619 // 1234e-6 -> 0.001234
620 int offset
= 2 - full_exp
;
621 std::memmove(buffer
+ offset
, buffer
, size
);
624 std::uninitialized_fill_n(buffer
+ 2, -full_exp
, '0');
625 size
= to_unsigned(int_size
+ offset
);
627 format_exp_notation(buffer
, size
, exp
, precision
, upper
);
631 #if FMT_CLANG_VERSION
632 # define FMT_FALLTHROUGH [[clang::fallthrough]];
633 #elif FMT_GCC_VERSION >= 700
634 # define FMT_FALLTHROUGH [[gnu::fallthrough]];
636 # define FMT_FALLTHROUGH
639 // Formats a nonnegative value using Grisu2 algorithm. Grisu2 doesn't give any
640 // guarantees on the shortness of the result.
641 FMT_FUNC
void grisu2_format(double value
, char *buffer
, size_t &size
, char type
,
642 int precision
, bool write_decimal_point
) {
643 FMT_ASSERT(value
>= 0, "value is negative");
644 int dec_exp
= 0; // K in Grisu.
646 grisu2_format_positive(value
, buffer
, size
, dec_exp
);
651 const int default_precision
= 6;
653 precision
= default_precision
;
659 case '\0': case 'g': {
660 int digits_to_remove
= static_cast<int>(size
) - precision
;
661 if (digits_to_remove
> 0) {
662 round(buffer
, size
, dec_exp
, digits_to_remove
);
663 // Remove trailing zeros.
664 while (size
> 0 && buffer
[size
- 1] == '0') {
676 int digits_to_remove
= -dec_exp
- precision
;
677 if (digits_to_remove
> 0) {
678 if (digits_to_remove
>= static_cast<int>(size
))
679 digits_to_remove
= static_cast<int>(size
) - 1;
680 round(buffer
, size
, dec_exp
, digits_to_remove
);
685 format_exp_notation(buffer
, size
, dec_exp
, precision
, type
== 'E');
688 if (write_decimal_point
&& precision
< 1)
690 grisu2_prettify(buffer
, size
, dec_exp
, precision
, upper
);
692 } // namespace internal
694 #if FMT_USE_WINDOWS_H
696 FMT_FUNC
internal::utf8_to_utf16::utf8_to_utf16(string_view s
) {
697 static const char ERROR_MSG
[] = "cannot convert string from UTF-8 to UTF-16";
698 if (s
.size() > INT_MAX
)
699 FMT_THROW(windows_error(ERROR_INVALID_PARAMETER
, ERROR_MSG
));
700 int s_size
= static_cast<int>(s
.size());
702 // MultiByteToWideChar does not support zero length, handle separately.
708 int length
= MultiByteToWideChar(
709 CP_UTF8
, MB_ERR_INVALID_CHARS
, s
.data(), s_size
, FMT_NULL
, 0);
711 FMT_THROW(windows_error(GetLastError(), ERROR_MSG
));
712 buffer_
.resize(length
+ 1);
713 length
= MultiByteToWideChar(
714 CP_UTF8
, MB_ERR_INVALID_CHARS
, s
.data(), s_size
, &buffer_
[0], length
);
716 FMT_THROW(windows_error(GetLastError(), ERROR_MSG
));
720 FMT_FUNC
internal::utf16_to_utf8::utf16_to_utf8(wstring_view s
) {
721 if (int error_code
= convert(s
)) {
722 FMT_THROW(windows_error(error_code
,
723 "cannot convert string from UTF-16 to UTF-8"));
727 FMT_FUNC
int internal::utf16_to_utf8::convert(wstring_view s
) {
728 if (s
.size() > INT_MAX
)
729 return ERROR_INVALID_PARAMETER
;
730 int s_size
= static_cast<int>(s
.size());
732 // WideCharToMultiByte does not support zero length, handle separately.
738 int length
= WideCharToMultiByte(
739 CP_UTF8
, 0, s
.data(), s_size
, FMT_NULL
, 0, FMT_NULL
, FMT_NULL
);
741 return GetLastError();
742 buffer_
.resize(length
+ 1);
743 length
= WideCharToMultiByte(
744 CP_UTF8
, 0, s
.data(), s_size
, &buffer_
[0], length
, FMT_NULL
, FMT_NULL
);
746 return GetLastError();
751 FMT_FUNC
void windows_error::init(
752 int err_code
, string_view format_str
, format_args args
) {
753 error_code_
= err_code
;
754 memory_buffer buffer
;
755 internal::format_windows_error(buffer
, err_code
, vformat(format_str
, args
));
756 std::runtime_error
&base
= *this;
757 base
= std::runtime_error(to_string(buffer
));
760 FMT_FUNC
void internal::format_windows_error(
761 internal::buffer
&out
, int error_code
, string_view message
) FMT_NOEXCEPT
{
764 buf
.resize(inline_buffer_size
);
766 wchar_t *system_message
= &buf
[0];
767 int result
= FormatMessageW(
768 FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
,
769 FMT_NULL
, error_code
, MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
770 system_message
, static_cast<uint32_t>(buf
.size()), FMT_NULL
);
772 utf16_to_utf8 utf8_message
;
773 if (utf8_message
.convert(system_message
) == ERROR_SUCCESS
) {
777 w
.write(utf8_message
);
782 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
783 break; // Can't get error message, report error code instead.
784 buf
.resize(buf
.size() * 2);
787 format_error_code(out
, error_code
, message
);
790 #endif // FMT_USE_WINDOWS_H
792 FMT_FUNC
void format_system_error(
793 internal::buffer
&out
, int error_code
, string_view message
) FMT_NOEXCEPT
{
796 buf
.resize(inline_buffer_size
);
798 char *system_message
= &buf
[0];
799 int result
= safe_strerror(error_code
, system_message
, buf
.size());
804 w
.write(system_message
);
807 if (result
!= ERANGE
)
808 break; // Can't get error message, report error code instead.
809 buf
.resize(buf
.size() * 2);
812 format_error_code(out
, error_code
, message
);
815 template <typename Char
>
816 void basic_fixed_buffer
<Char
>::grow(std::size_t) {
817 FMT_THROW(std::runtime_error("buffer overflow"));
820 FMT_FUNC
void internal::error_handler::on_error(const char *message
) {
821 FMT_THROW(format_error(message
));
824 FMT_FUNC
void report_system_error(
825 int error_code
, fmt::string_view message
) FMT_NOEXCEPT
{
826 report_error(format_system_error
, error_code
, message
);
829 #if FMT_USE_WINDOWS_H
830 FMT_FUNC
void report_windows_error(
831 int error_code
, fmt::string_view message
) FMT_NOEXCEPT
{
832 report_error(internal::format_windows_error
, error_code
, message
);
836 FMT_FUNC
void vprint(std::FILE *f
, string_view format_str
, format_args args
) {
837 memory_buffer buffer
;
838 vformat_to(buffer
, format_str
, args
);
839 std::fwrite(buffer
.data(), 1, buffer
.size(), f
);
842 FMT_FUNC
void vprint(std::FILE *f
, wstring_view format_str
, wformat_args args
) {
843 wmemory_buffer buffer
;
844 vformat_to(buffer
, format_str
, args
);
845 std::fwrite(buffer
.data(), sizeof(wchar_t), buffer
.size(), f
);
848 FMT_FUNC
void vprint(string_view format_str
, format_args args
) {
849 vprint(stdout
, format_str
, args
);
852 FMT_FUNC
void vprint(wstring_view format_str
, wformat_args args
) {
853 vprint(stdout
, format_str
, args
);
856 #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
857 FMT_FUNC locale
locale_provider::locale() { return fmt::locale(); }
863 # pragma warning(pop)
866 #endif // FMT_FORMAT_INL_H_