added toml::format_flags::relaxed_float_precision
This commit is contained in:
parent
f6ce95907e
commit
cdf85a9b60
@ -59,6 +59,7 @@ Highlights are indicated with ❤️.
|
||||
- added `toml::format_flags::allow_unicode_strings`
|
||||
- added `toml::format_flags::indent_array_elements` (#120) (@W4RH4WK)
|
||||
- added `toml::format_flags::indent_sub_tables` (#120) (@W4RH4WK)
|
||||
- added `toml::format_flags::relaxed_float_precision` (#89) (@vaartis)
|
||||
- added `toml::format_flags::quote_infinities_and_nans`
|
||||
- added `toml::is_key<>` and toml::is_key_or_convertible<>` metafunctions
|
||||
- added `toml::node_view::operator==`
|
||||
|
@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
|
||||
project(
|
||||
tomlplusplus
|
||||
VERSION 3.0.0
|
||||
DESCRIPTION "Header-only TOML config file parser and serializer for C++17 (and later!)"
|
||||
DESCRIPTION "Header-only TOML config file parser and serializer for C++17"
|
||||
HOMEPAGE_URL "https://marzer.github.io/tomlplusplus/"
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
@ -30,7 +30,7 @@ TOML_NAMESPACE_START
|
||||
/// \eout
|
||||
///
|
||||
///
|
||||
/// \warning Keys in paths are interpreted literally, so whitespace (or lack thereof) matters:
|
||||
/// \note Keys in paths are interpreted literally, so whitespace (or lack thereof) matters:
|
||||
/// \cpp
|
||||
/// toml::at_path(config, "foo.bar") // same as config["foo"]["bar"]
|
||||
/// toml::at_path(config, "foo. bar") // same as config["foo"][" bar"]
|
||||
|
@ -410,7 +410,12 @@ TOML_IMPL_NAMESPACE_START
|
||||
case fp_class::neg_inf: inf_nan = &constants_->float_neg_inf; break;
|
||||
case fp_class::pos_inf: inf_nan = &constants_->float_pos_inf; break;
|
||||
case fp_class::nan: inf_nan = &constants_->float_nan; break;
|
||||
case fp_class::ok: print_to_stream(*stream_, *val); break;
|
||||
case fp_class::ok:
|
||||
print_to_stream(*stream_,
|
||||
*val,
|
||||
value_flags::none,
|
||||
!!(config_.flags & format_flags::relaxed_float_precision));
|
||||
break;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
|
@ -329,6 +329,13 @@ TOML_NAMESPACE_START // abi namespace
|
||||
|
||||
/// \brief Combination mask of all indentation-enabling flags.
|
||||
indentation = indent_sub_tables | indent_array_elements,
|
||||
|
||||
/// \brief Emit floating-point values with relaxed precision.
|
||||
///
|
||||
/// \warning Setting this flag may cause serialized documents to no longer round-trip correctly
|
||||
/// since floats might have a less precise value upon being written out than they did when being
|
||||
/// read in. Use this flag at your own risk.
|
||||
relaxed_float_precision = (1ull << 11),
|
||||
};
|
||||
TOML_MAKE_FLAGS(format_flags);
|
||||
|
||||
|
@ -516,12 +516,12 @@
|
||||
//# ATTRIBUTES, UTILITY MACROS ETC
|
||||
//#====================================================================================================================
|
||||
|
||||
#if TOML_GCC || TOML_CLANG || (TOML_ICC && !TOML_ICC_CL)
|
||||
#if !defined(TOML_FLOAT_CHARCONV) && (TOML_GCC || TOML_CLANG || (TOML_ICC && !TOML_ICC_CL))
|
||||
// not supported by any version of GCC or Clang as of 26/11/2020
|
||||
// not supported by any version of ICC on Linux as of 11/01/2021
|
||||
#define TOML_FLOAT_CHARCONV 0
|
||||
#endif
|
||||
#if defined(__EMSCRIPTEN__) || defined(__APPLE__)
|
||||
#if !defined(TOML_INT_CHARCONV) && (defined(__EMSCRIPTEN__) || defined(__APPLE__))
|
||||
// causes link errors on emscripten
|
||||
// causes Mac OS SDK version errors on some versions of Apple Clang
|
||||
#define TOML_INT_CHARCONV 0
|
||||
@ -690,9 +690,7 @@
|
||||
#endif
|
||||
|
||||
#define TOML_MAKE_FLAGS_(name, op) \
|
||||
TOML_NODISCARD \
|
||||
TOML_ALWAYS_INLINE \
|
||||
TOML_ATTR(const) \
|
||||
TOML_CONST_INLINE_GETTER \
|
||||
constexpr name operator op(name lhs, name rhs) noexcept \
|
||||
{ \
|
||||
using under = std::underlying_type_t<name>; \
|
||||
@ -708,17 +706,13 @@
|
||||
TOML_MAKE_FLAGS_(name, &); \
|
||||
TOML_MAKE_FLAGS_(name, |); \
|
||||
TOML_MAKE_FLAGS_(name, ^); \
|
||||
TOML_NODISCARD \
|
||||
TOML_ALWAYS_INLINE \
|
||||
TOML_ATTR(const) \
|
||||
TOML_CONST_INLINE_GETTER \
|
||||
constexpr name operator~(name val) noexcept \
|
||||
{ \
|
||||
using under = std::underlying_type_t<name>; \
|
||||
return static_cast<name>(~static_cast<under>(val)); \
|
||||
} \
|
||||
TOML_NODISCARD \
|
||||
TOML_ALWAYS_INLINE \
|
||||
TOML_ATTR(const) \
|
||||
TOML_CONST_INLINE_GETTER \
|
||||
constexpr bool operator!(name val) noexcept \
|
||||
{ \
|
||||
using under = std::underlying_type_t<name>; \
|
||||
|
@ -54,10 +54,10 @@ TOML_IMPL_NAMESPACE_START
|
||||
void print_to_stream(std::ostream&, uint64_t, value_flags = {}, size_t min_digits = 0);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, float, value_flags = {});
|
||||
void print_to_stream(std::ostream&, float, value_flags = {}, bool relaxed_precision = false);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, double, value_flags = {});
|
||||
void print_to_stream(std::ostream&, double, value_flags = {}, bool relaxed_precision = false);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, bool);
|
||||
|
@ -62,10 +62,10 @@ TOML_ANON_NAMESPACE_START
|
||||
inline constexpr size_t charconv_buffer_length<uint64_t> = 20; // strlen("18446744073709551615")
|
||||
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<float> = 40;
|
||||
inline constexpr size_t charconv_buffer_length<float> = 64;
|
||||
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<double> = 60;
|
||||
inline constexpr size_t charconv_buffer_length<double> = 64;
|
||||
|
||||
template <typename T>
|
||||
TOML_INTERNAL_LINKAGE
|
||||
@ -156,7 +156,10 @@ TOML_ANON_NAMESPACE_START
|
||||
|
||||
template <typename T>
|
||||
TOML_INTERNAL_LINKAGE
|
||||
void print_floating_point_to_stream(std::ostream & stream, T val, value_flags format = {})
|
||||
void print_floating_point_to_stream(std::ostream & stream,
|
||||
T val,
|
||||
value_flags format,
|
||||
[[maybe_unused]] bool relaxed_precision)
|
||||
{
|
||||
switch (impl::fpclassify(val))
|
||||
{
|
||||
@ -178,19 +181,30 @@ TOML_ANON_NAMESPACE_START
|
||||
|
||||
#if TOML_FLOAT_CHARCONV
|
||||
|
||||
const auto hex = !!(format & value_flags::format_as_hexadecimal);
|
||||
char buf[charconv_buffer_length<T>];
|
||||
const auto res = !!(format & value_flags::format_as_hexadecimal)
|
||||
? std::to_chars(buf, buf + sizeof(buf), val, std::chars_format::hex)
|
||||
auto res = hex ? std::to_chars(buf, buf + sizeof(buf), val, std::chars_format::hex)
|
||||
: std::to_chars(buf, buf + sizeof(buf), val);
|
||||
const auto str = std::string_view{ buf, static_cast<size_t>(res.ptr - buf) };
|
||||
auto str = std::string_view{ buf, static_cast<size_t>(res.ptr - buf) };
|
||||
|
||||
char buf2[charconv_buffer_length<T>];
|
||||
if (!hex && relaxed_precision)
|
||||
{
|
||||
res = std::to_chars(buf2, buf2 + sizeof(buf2), val, std::chars_format::general, 6);
|
||||
const auto str2 = std::string_view{ buf2, static_cast<size_t>(res.ptr - buf2) };
|
||||
if (str2.length() < str.length())
|
||||
str = str2;
|
||||
}
|
||||
|
||||
impl::print_to_stream(stream, str);
|
||||
if (!(format & value_flags::format_as_hexadecimal) && needs_decimal_point(str))
|
||||
if (!hex && needs_decimal_point(str))
|
||||
toml::impl::print_to_stream(stream, ".0"sv);
|
||||
|
||||
#else
|
||||
|
||||
std::ostringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
if (!relaxed_precision)
|
||||
ss.precision(std::numeric_limits<T>::max_digits10);
|
||||
if (!!(format & value_flags::format_as_hexadecimal))
|
||||
ss << std::hexfloat;
|
||||
@ -286,15 +300,15 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, float val, value_flags format)
|
||||
void print_to_stream(std::ostream & stream, float val, value_flags format, bool relaxed_precision)
|
||||
{
|
||||
TOML_ANON_NAMESPACE::print_floating_point_to_stream(stream, val, format);
|
||||
TOML_ANON_NAMESPACE::print_floating_point_to_stream(stream, val, format, relaxed_precision);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, double val, value_flags format)
|
||||
void print_to_stream(std::ostream & stream, double val, value_flags format, bool relaxed_precision)
|
||||
{
|
||||
TOML_ANON_NAMESPACE::print_floating_point_to_stream(stream, val, format);
|
||||
TOML_ANON_NAMESPACE::print_floating_point_to_stream(stream, val, format, relaxed_precision);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
|
@ -133,6 +133,12 @@ TEST_CASE("parsing - floats")
|
||||
parse_expected_value(FILE_LINE_ARGS, "6.02e23"sv, 6.02e23);
|
||||
parse_expected_value(FILE_LINE_ARGS, "6.02e+23"sv, 6.02e+23);
|
||||
parse_expected_value(FILE_LINE_ARGS, "1.112_650_06e-17"sv, 1.11265006e-17);
|
||||
parse_expected_value(FILE_LINE_ARGS, "0.010284358729827818"sv, 0.010284358729827818);
|
||||
parse_expected_value(FILE_LINE_ARGS, "0.010284358729827818"sv, 0.010284358729827818);
|
||||
parse_expected_value(FILE_LINE_ARGS, "0.0102"sv, 0.0102);
|
||||
parse_expected_value(FILE_LINE_ARGS, "10.0102"sv, 10.0102);
|
||||
parse_expected_value(FILE_LINE_ARGS, "10.010284358729828"sv, 10.010284358729828);
|
||||
parse_expected_value(FILE_LINE_ARGS, "10.0"sv, 10.0);
|
||||
|
||||
// toml/issues/562 (hexfloats)
|
||||
#if TOML_LANG_UNRELEASED
|
||||
|
64
toml.hpp
64
toml.hpp
@ -526,12 +526,12 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if TOML_GCC || TOML_CLANG || (TOML_ICC && !TOML_ICC_CL)
|
||||
#if !defined(TOML_FLOAT_CHARCONV) && (TOML_GCC || TOML_CLANG || (TOML_ICC && !TOML_ICC_CL))
|
||||
// not supported by any version of GCC or Clang as of 26/11/2020
|
||||
// not supported by any version of ICC on Linux as of 11/01/2021
|
||||
#define TOML_FLOAT_CHARCONV 0
|
||||
#endif
|
||||
#if defined(__EMSCRIPTEN__) || defined(__APPLE__)
|
||||
#if !defined(TOML_INT_CHARCONV) && (defined(__EMSCRIPTEN__) || defined(__APPLE__))
|
||||
// causes link errors on emscripten
|
||||
// causes Mac OS SDK version errors on some versions of Apple Clang
|
||||
#define TOML_INT_CHARCONV 0
|
||||
@ -700,9 +700,7 @@
|
||||
#endif
|
||||
|
||||
#define TOML_MAKE_FLAGS_(name, op) \
|
||||
TOML_NODISCARD \
|
||||
TOML_ALWAYS_INLINE \
|
||||
TOML_ATTR(const) \
|
||||
TOML_CONST_INLINE_GETTER \
|
||||
constexpr name operator op(name lhs, name rhs) noexcept \
|
||||
{ \
|
||||
using under = std::underlying_type_t<name>; \
|
||||
@ -718,17 +716,13 @@
|
||||
TOML_MAKE_FLAGS_(name, &); \
|
||||
TOML_MAKE_FLAGS_(name, |); \
|
||||
TOML_MAKE_FLAGS_(name, ^); \
|
||||
TOML_NODISCARD \
|
||||
TOML_ALWAYS_INLINE \
|
||||
TOML_ATTR(const) \
|
||||
TOML_CONST_INLINE_GETTER \
|
||||
constexpr name operator~(name val) noexcept \
|
||||
{ \
|
||||
using under = std::underlying_type_t<name>; \
|
||||
return static_cast<name>(~static_cast<under>(val)); \
|
||||
} \
|
||||
TOML_NODISCARD \
|
||||
TOML_ALWAYS_INLINE \
|
||||
TOML_ATTR(const) \
|
||||
TOML_CONST_INLINE_GETTER \
|
||||
constexpr bool operator!(name val) noexcept \
|
||||
{ \
|
||||
using under = std::underlying_type_t<name>; \
|
||||
@ -1295,6 +1289,7 @@ TOML_NAMESPACE_START // abi namespace
|
||||
indent_sub_tables = (1ull << 9),
|
||||
indent_array_elements = (1ull << 10),
|
||||
indentation = indent_sub_tables | indent_array_elements,
|
||||
relaxed_float_precision = (1ull << 11),
|
||||
};
|
||||
TOML_MAKE_FLAGS(format_flags);
|
||||
|
||||
@ -2045,10 +2040,10 @@ TOML_IMPL_NAMESPACE_START
|
||||
void print_to_stream(std::ostream&, uint64_t, value_flags = {}, size_t min_digits = 0);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, float, value_flags = {});
|
||||
void print_to_stream(std::ostream&, float, value_flags = {}, bool relaxed_precision = false);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, double, value_flags = {});
|
||||
void print_to_stream(std::ostream&, double, value_flags = {}, bool relaxed_precision = false);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, bool);
|
||||
@ -9376,10 +9371,10 @@ TOML_ANON_NAMESPACE_START
|
||||
inline constexpr size_t charconv_buffer_length<uint64_t> = 20; // strlen("18446744073709551615")
|
||||
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<float> = 40;
|
||||
inline constexpr size_t charconv_buffer_length<float> = 64;
|
||||
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<double> = 60;
|
||||
inline constexpr size_t charconv_buffer_length<double> = 64;
|
||||
|
||||
template <typename T>
|
||||
TOML_INTERNAL_LINKAGE
|
||||
@ -9470,7 +9465,10 @@ TOML_ANON_NAMESPACE_START
|
||||
|
||||
template <typename T>
|
||||
TOML_INTERNAL_LINKAGE
|
||||
void print_floating_point_to_stream(std::ostream & stream, T val, value_flags format = {})
|
||||
void print_floating_point_to_stream(std::ostream & stream,
|
||||
T val,
|
||||
value_flags format,
|
||||
[[maybe_unused]] bool relaxed_precision)
|
||||
{
|
||||
switch (impl::fpclassify(val))
|
||||
{
|
||||
@ -9492,19 +9490,30 @@ TOML_ANON_NAMESPACE_START
|
||||
|
||||
#if TOML_FLOAT_CHARCONV
|
||||
|
||||
const auto hex = !!(format & value_flags::format_as_hexadecimal);
|
||||
char buf[charconv_buffer_length<T>];
|
||||
const auto res = !!(format & value_flags::format_as_hexadecimal)
|
||||
? std::to_chars(buf, buf + sizeof(buf), val, std::chars_format::hex)
|
||||
auto res = hex ? std::to_chars(buf, buf + sizeof(buf), val, std::chars_format::hex)
|
||||
: std::to_chars(buf, buf + sizeof(buf), val);
|
||||
const auto str = std::string_view{ buf, static_cast<size_t>(res.ptr - buf) };
|
||||
auto str = std::string_view{ buf, static_cast<size_t>(res.ptr - buf) };
|
||||
|
||||
char buf2[charconv_buffer_length<T>];
|
||||
if (!hex && relaxed_precision)
|
||||
{
|
||||
res = std::to_chars(buf2, buf2 + sizeof(buf2), val, std::chars_format::general, 6);
|
||||
const auto str2 = std::string_view{ buf2, static_cast<size_t>(res.ptr - buf2) };
|
||||
if (str2.length() < str.length())
|
||||
str = str2;
|
||||
}
|
||||
|
||||
impl::print_to_stream(stream, str);
|
||||
if (!(format & value_flags::format_as_hexadecimal) && needs_decimal_point(str))
|
||||
if (!hex && needs_decimal_point(str))
|
||||
toml::impl::print_to_stream(stream, ".0"sv);
|
||||
|
||||
#else
|
||||
|
||||
std::ostringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
if (!relaxed_precision)
|
||||
ss.precision(std::numeric_limits<T>::max_digits10);
|
||||
if (!!(format & value_flags::format_as_hexadecimal))
|
||||
ss << std::hexfloat;
|
||||
@ -9600,15 +9609,15 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, float val, value_flags format)
|
||||
void print_to_stream(std::ostream & stream, float val, value_flags format, bool relaxed_precision)
|
||||
{
|
||||
TOML_ANON_NAMESPACE::print_floating_point_to_stream(stream, val, format);
|
||||
TOML_ANON_NAMESPACE::print_floating_point_to_stream(stream, val, format, relaxed_precision);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, double val, value_flags format)
|
||||
void print_to_stream(std::ostream & stream, double val, value_flags format, bool relaxed_precision)
|
||||
{
|
||||
TOML_ANON_NAMESPACE::print_floating_point_to_stream(stream, val, format);
|
||||
TOML_ANON_NAMESPACE::print_floating_point_to_stream(stream, val, format, relaxed_precision);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
@ -15244,7 +15253,12 @@ TOML_IMPL_NAMESPACE_START
|
||||
case fp_class::neg_inf: inf_nan = &constants_->float_neg_inf; break;
|
||||
case fp_class::pos_inf: inf_nan = &constants_->float_pos_inf; break;
|
||||
case fp_class::nan: inf_nan = &constants_->float_nan; break;
|
||||
case fp_class::ok: print_to_stream(*stream_, *val); break;
|
||||
case fp_class::ok:
|
||||
print_to_stream(*stream_,
|
||||
*val,
|
||||
value_flags::none,
|
||||
!!(config_.flags & format_flags::relaxed_float_precision));
|
||||
break;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user