Skip to content

Commit b6d2653

Browse files
committed
♻️ replace snprintf with stream
Signed-off-by: Niels Lohmann <[email protected]>
1 parent dfb9eb6 commit b6d2653

File tree

2 files changed

+14
-96
lines changed

2 files changed

+14
-96
lines changed

include/nlohmann/detail/output/serializer.hpp

Lines changed: 7 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <cstdint> // uint8_t
1818
#include <cstdio> // snprintf
1919
#include <limits> // numeric_limits
20+
#include <sstream> // string_stream
2021
#include <string> // string, char_traits
2122
#include <iomanip> // setfill, setw
2223
#include <type_traits> // is_same
@@ -827,55 +828,13 @@ class serializer
827828

828829
void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
829830
{
830-
// get number of digits for a float -> text -> float round-trip
831-
static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
832-
833-
// the actual conversion (Note that is_ieee_single_or_double==false
834-
// rules out that number_float_t is double or long double. Therefore,
835-
// we need to cast the argument x to double to be able to use snprintf.)
836-
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
837-
std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, static_cast<double>(x));
838-
839-
// negative value indicates an error
840-
JSON_ASSERT(len > 0);
841-
// check if buffer was large enough
842-
JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
843-
844-
// erase thousands separator
845-
if (thousands_sep != '\0')
846-
{
847-
// NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
848-
const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
849-
std::fill(end, number_buffer.end(), '\0');
850-
JSON_ASSERT((end - number_buffer.begin()) <= len);
851-
len = (end - number_buffer.begin());
852-
}
853-
854-
// convert decimal point to '.'
855-
if (decimal_point != '\0' && decimal_point != '.')
856-
{
857-
// NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
858-
const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
859-
if (dec_pos != number_buffer.end())
860-
{
861-
*dec_pos = '.';
862-
}
863-
}
864-
865-
o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
866-
867-
// determine if we need to append ".0"
868-
const bool value_is_int_like =
869-
std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
870-
[](char c)
871-
{
872-
return c == '.' || c == 'e';
873-
});
831+
std::ostringstream oss;
832+
oss.precision(std::numeric_limits<number_float_t>::max_digits10);
833+
oss.imbue(std::locale::classic());
834+
oss << std::defaultfloat << x;
874835

875-
if (value_is_int_like)
876-
{
877-
o->write_characters(".0", 2);
878-
}
836+
const auto s = oss.str();
837+
o->write_characters(s.c_str(), s.size());
879838
}
880839

881840
/*!

single_include/nlohmann/json.hpp

Lines changed: 7 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -17625,6 +17625,7 @@ NLOHMANN_JSON_NAMESPACE_END
1762517625
#include <cstdint> // uint8_t
1762617626
#include <cstdio> // snprintf
1762717627
#include <limits> // numeric_limits
17628+
#include <sstream> // string_stream
1762817629
#include <string> // string, char_traits
1762917630
#include <iomanip> // setfill, setw
1763017631
#include <type_traits> // is_same
@@ -19562,55 +19563,13 @@ class serializer
1956219563

1956319564
void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
1956419565
{
19565-
// get number of digits for a float -> text -> float round-trip
19566-
static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
19566+
std::ostringstream oss;
19567+
oss.precision(std::numeric_limits<number_float_t>::max_digits10);
19568+
oss.imbue(std::locale::classic());
19569+
oss << std::defaultfloat << x;
1956719570

19568-
// the actual conversion (Note that is_ieee_single_or_double==false
19569-
// rules out that number_float_t is double or long double. Therefore,
19570-
// we need to cast the argument x to double to be able to use snprintf.)
19571-
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19572-
std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, static_cast<double>(x));
19573-
19574-
// negative value indicates an error
19575-
JSON_ASSERT(len > 0);
19576-
// check if buffer was large enough
19577-
JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
19578-
19579-
// erase thousands separator
19580-
if (thousands_sep != '\0')
19581-
{
19582-
// NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
19583-
const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
19584-
std::fill(end, number_buffer.end(), '\0');
19585-
JSON_ASSERT((end - number_buffer.begin()) <= len);
19586-
len = (end - number_buffer.begin());
19587-
}
19588-
19589-
// convert decimal point to '.'
19590-
if (decimal_point != '\0' && decimal_point != '.')
19591-
{
19592-
// NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
19593-
const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
19594-
if (dec_pos != number_buffer.end())
19595-
{
19596-
*dec_pos = '.';
19597-
}
19598-
}
19599-
19600-
o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
19601-
19602-
// determine if we need to append ".0"
19603-
const bool value_is_int_like =
19604-
std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
19605-
[](char c)
19606-
{
19607-
return c == '.' || c == 'e';
19608-
});
19609-
19610-
if (value_is_int_like)
19611-
{
19612-
o->write_characters(".0", 2);
19613-
}
19571+
const auto s = oss.str();
19572+
o->write_characters(s.c_str(), s.size());
1961419573
}
1961519574

1961619575
/*!

0 commit comments

Comments
 (0)