From ad804f8675409caf70f7dbca79f717184bd6bb37 Mon Sep 17 00:00:00 2001 From: Joao Paulo Magalhaes Date: Fri, 21 Jun 2024 16:58:52 +0100 Subject: [PATCH] re #442: ensure leading + is accepted --- src/c4/yml/node.hpp | 30 ++++++++++++++++++++++++------ src/c4/yml/tree.hpp | 4 ++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/c4/yml/node.hpp b/src/c4/yml/node.hpp index ccda50c3..b3f707f2 100644 --- a/src/c4/yml/node.hpp +++ b/src/c4/yml/node.hpp @@ -1604,31 +1604,49 @@ inline void write(NodeRef *n, T const& v) n->set_val_serialized(v); } +namespace detail { +// SFINAE overloads for skipping leading + which cannot be read by the charconv functions +template +C4_ALWAYS_INLINE auto read_skip_plus(csubstr val, T *v) + -> typename std::enable_if::value, bool>::type +{ + if(val.begins_with('+')) + val = val.sub(1); + return from_chars(val, v); +} +template +C4_ALWAYS_INLINE auto read_skip_plus(csubstr val, T *v) + -> typename std::enable_if< ! std::is_arithmetic::value, bool>::type +{ + return from_chars(val, v); +} +} // namespace detail + /** convert the val of a scalar node to a particular type, by * forwarding its val to @ref from_chars(). The full string is * used. * @return false if the conversion failed */ template -typename std::enable_if< ! std::is_floating_point::value, bool>::type -inline read(NodeRef const& n, T *v) +inline auto read(NodeRef const& n, T *v) + -> typename std::enable_if< ! std::is_floating_point::value, bool>::type { csubstr val = n.val(); if(val.empty()) return false; - return from_chars(val, v); + return detail::read_skip_plus(val, v); } /** convert the val of a scalar node to a particular type, by * forwarding its val to @ref from_chars(). The full string is * used. * @return false if the conversion failed */ template -typename std::enable_if< ! std::is_floating_point::value, bool>::type -inline read(ConstNodeRef const& n, T *v) +inline auto read(ConstNodeRef const& n, T *v) + -> typename std::enable_if< ! std::is_floating_point::value, bool>::type { csubstr val = n.val(); if(val.empty()) return false; - return from_chars(val, v); + return detail::read_skip_plus(val, v); } /** convert the val of a scalar node to a floating point type, by diff --git a/src/c4/yml/tree.hpp b/src/c4/yml/tree.hpp index 0dbcb3de..49b1ec7c 100644 --- a/src/c4/yml/tree.hpp +++ b/src/c4/yml/tree.hpp @@ -64,6 +64,10 @@ bool from_chars_float(csubstr buf, T *C4_RESTRICT val) { return true; } + else if(C4_UNLIKELY(buf.begins_with('+'))) + { + return from_chars(buf.sub(1), val); + } else if(C4_UNLIKELY(buf == ".nan" || buf == ".NaN" || buf == ".NAN")) { *val = std::numeric_limits::quiet_NaN();