| 2380 | |
| 2381 | template <typename OutputIt, typename DecimalFP, typename Char, typename Grouping = digit_grouping<Char>> |
| 2382 | FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& f, const format_specs<Char>& specs, |
| 2383 | float_specs fspecs, locale_ref loc) -> OutputIt { |
| 2384 | auto significand = f.significand; |
| 2385 | int significand_size = get_significand_size(f); |
| 2386 | const Char zero = static_cast<Char>('0'); |
| 2387 | auto sign = fspecs.sign; |
| 2388 | size_t size = to_unsigned(significand_size) + (sign ? 1 : 0); |
| 2389 | using iterator = reserve_iterator<OutputIt>; |
| 2390 | |
| 2391 | Char decimal_point = fspecs.locale ? detail::decimal_point<Char>(loc) : static_cast<Char>('.'); |
| 2392 | |
| 2393 | int output_exp = f.exponent + significand_size - 1; |
| 2394 | auto use_exp_format = [=]() { |
| 2395 | if (fspecs.format == float_format::exp) return true; |
| 2396 | if (fspecs.format != float_format::general) return false; |
| 2397 | // Use the fixed notation if the exponent is in [exp_lower, exp_upper), |
| 2398 | // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation. |
| 2399 | const int exp_lower = -4, exp_upper = 16; |
| 2400 | return output_exp < exp_lower || output_exp >= (fspecs.precision > 0 ? fspecs.precision : exp_upper); |
| 2401 | }; |
| 2402 | if (use_exp_format()) { |
| 2403 | int num_zeros = 0; |
| 2404 | if (fspecs.showpoint) { |
| 2405 | num_zeros = fspecs.precision - significand_size; |
| 2406 | if (num_zeros < 0) num_zeros = 0; |
| 2407 | size += to_unsigned(num_zeros); |
| 2408 | } else if (significand_size == 1) { |
| 2409 | decimal_point = Char(); |
| 2410 | } |
| 2411 | auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp; |
| 2412 | int exp_digits = 2; |
| 2413 | if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3; |
| 2414 | |
| 2415 | size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits); |
| 2416 | char exp_char = fspecs.upper ? 'E' : 'e'; |
| 2417 | auto write = [=](iterator it) { |
| 2418 | if (sign) *it++ = detail::sign<Char>(sign); |
| 2419 | // Insert a decimal point after the first digit and add an exponent. |
| 2420 | it = write_significand(it, significand, significand_size, 1, decimal_point); |
| 2421 | if (num_zeros > 0) it = detail::fill_n(it, num_zeros, zero); |
| 2422 | *it++ = static_cast<Char>(exp_char); |
| 2423 | return write_exponent<Char>(output_exp, it); |
| 2424 | }; |
| 2425 | return specs.width > 0 ? write_padded<align::right>(out, specs, size, write) |
| 2426 | : base_iterator(out, write(reserve(out, size))); |
| 2427 | } |
| 2428 | |
| 2429 | int exp = f.exponent + significand_size; |
| 2430 | if (f.exponent >= 0) { |
| 2431 | // 1234e5 -> 123400000[.0+] |
| 2432 | size += to_unsigned(f.exponent); |
| 2433 | int num_zeros = fspecs.precision - exp; |
| 2434 | abort_fuzzing_if(num_zeros > 5000); |
| 2435 | if (fspecs.showpoint) { |
| 2436 | ++size; |
| 2437 | if (num_zeros <= 0 && fspecs.format != float_format::fixed) num_zeros = 0; |
| 2438 | if (num_zeros > 0) size += to_unsigned(num_zeros); |
| 2439 | } |
nothing calls this directly
no test coverage detected