Fix CI: useless cast in the Zmij digit writer and snprintf truncation

- ci_test_gcc (Linux x86-64): static_cast<std::size_t>(d.significand % 100)
  was a useless cast (a std::uint64_t prvalue, the same type as
  std::size_t there); cast a named variable instead.
- ci_test_gcc: -Werror=format-truncation for snprintf("%.*e") in
  unit-to_chars.cpp, whose precision GCC cannot bound; write the
  neighboring decimal with a stream (classic locale, std::scientific),
  which gives the same text.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-09-30 00:15:35 +02:00
parent 14a5064204
commit 3336423f04
3 changed files with 12 additions and 5 deletions

View File

@@ -983,7 +983,8 @@ inline void shortest_digits(char* buf, int& len, int& decimal_exponent, double v
std::size_t n = digits.size();
while (d.significand >= 100)
{
const auto i = static_cast<std::size_t>(d.significand % 100) * 2;
const std::uint64_t two_digits = d.significand % 100; // a variable: GCC calls a cast of the remainder useless where std::uint64_t is std::size_t
const auto i = static_cast<std::size_t>(two_digits) * 2;
d.significand /= 100;
n -= 2;
digits[n] = pairs[i];

View File

@@ -25427,7 +25427,8 @@ inline void shortest_digits(char* buf, int& len, int& decimal_exponent, double v
std::size_t n = digits.size();
while (d.significand >= 100)
{
const auto i = static_cast<std::size_t>(d.significand % 100) * 2;
const std::uint64_t two_digits = d.significand % 100; // a variable: GCC calls a cast of the remainder useless where std::uint64_t is std::size_t
const auto i = static_cast<std::size_t>(two_digits) * 2;
d.significand /= 100;
n -= 2;
digits[n] = pairs[i];

View File

@@ -20,8 +20,11 @@ using nlohmann::detail::dtoa_impl::reinterpret_bits;
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <limits>
#include <locale>
#include <random>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
@@ -664,9 +667,11 @@ void check_shortest(double v)
if (digits.size() > 1)
{
// the decimals of one digit fewer next to the value
std::array<char, 64> shorter{};
const int n = std::snprintf(shorter.data(), shorter.size(), "%.*e", static_cast<int>(digits.size()) - 2, v); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
const auto near = digits_and_exponent(std::string(shorter.data(), static_cast<std::size_t>(n)));
// (a stream rather than snprintf("%.*e"), whose output GCC cannot bound)
std::ostringstream shorter;
shorter.imbue(std::locale::classic());
shorter << std::scientific << std::setprecision(static_cast<int>(digits.size()) - 2) << v;
const auto near = digits_and_exponent(shorter.str());
// as an integer with digits.size() - 1 digits
std::string m = near.first;
int e = near.second;