From 56fef50c0a7c0e3a604b8a9b68017ed265b9fa88 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 5 Aug 2023 15:23:10 +0100 Subject: Use faster std::from_chars over boost::lexical_cast for XML numeric parse --- slicer/xml/serializer.cpp | 31 +++++++++++++++++++++++++------ slicer/xml/testSpecifics.cpp | 6 +++--- slicer/xml/xmlExceptions.ice | 4 ++++ 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index 27bf10b..56cdbaa 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -1,5 +1,6 @@ #include "serializer.h" #include +#include #include #include #pragma GCC diagnostic push @@ -73,37 +74,37 @@ namespace Slicer { void set(Ice::Byte & v) const override { - v = boost::numeric_cast(boost::lexical_cast(value)); + from_chars(v); } void set(Ice::Short & v) const override { - v = boost::lexical_cast(value); + from_chars(v); } void set(Ice::Int & v) const override { - v = boost::lexical_cast(value); + from_chars(v); } void set(Ice::Long & v) const override { - v = boost::lexical_cast(value); + from_chars(v); } void set(Ice::Float & v) const override { - v = boost::lexical_cast(value); + from_chars(v); } void set(Ice::Double & v) const override { - v = boost::lexical_cast(value); + from_chars(v); } void @@ -113,6 +114,16 @@ namespace Slicer { } private: + template + void + from_chars(T & v) const + { + std::string_view raw {value.raw()}; + if (std::from_chars(raw.begin(), raw.end(), v).ec != std::errc {}) { + throw BadNumericValue(value); + } + } + const Glib::ustring value; }; @@ -489,4 +500,12 @@ namespace Slicer { { BadBooleanValueMsg::write(s, text); } + + AdHocFormatter(BadNumericValueMsg, "Bad numeric value [%?]"); + + void + BadNumericValue::ice_print(std::ostream & s) const + { + BadNumericValueMsg::write(s, text); + } } diff --git a/slicer/xml/testSpecifics.cpp b/slicer/xml/testSpecifics.cpp index ec9fe11..24edf78 100644 --- a/slicer/xml/testSpecifics.cpp +++ b/slicer/xml/testSpecifics.cpp @@ -54,11 +54,11 @@ BOOST_AUTO_TEST_CASE(int_values) doc.parse_memory("-4"); BOOST_REQUIRE_EQUAL(-4, BoostThrowWrapperHelper(doc.get_document())); doc.parse_memory(" "); - BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), std::bad_cast); + BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), Slicer::BadNumericValue); doc.parse_memory("notanint"); - BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), std::bad_cast); + BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), Slicer::BadNumericValue); doc.parse_memory(""); - BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), std::bad_cast); + BOOST_REQUIRE_THROW(BoostThrowWrapperHelper(doc.get_document()), Slicer::BadNumericValue); } BOOST_AUTO_TEST_CASE(factories) diff --git a/slicer/xml/xmlExceptions.ice b/slicer/xml/xmlExceptions.ice index 390f458..26d8aa2 100644 --- a/slicer/xml/xmlExceptions.ice +++ b/slicer/xml/xmlExceptions.ice @@ -8,6 +8,10 @@ module Slicer { exception BadBooleanValue extends DeserializerError { string text; }; + ["cpp:ice_print"] + exception BadNumericValue extends DeserializerError { + string text; + }; }; #endif -- cgit v1.2.3