From f6ae7cbe5f3dc94de092f89886c1b8936e65ca2c Mon Sep 17 00:00:00 2001 From: Denis Angell Date: Thu, 23 Mar 2023 18:19:52 +0000 Subject: [PATCH 1/3] replace hand-rolled lexicalCast --- .../app/rdb/backend/detail/impl/Node.cpp | 13 +- src/ripple/beast/core/LexicalCast.h | 136 ++---------------- src/test/beast/LexicalCast_test.cpp | 2 - 3 files changed, 19 insertions(+), 132 deletions(-) diff --git a/src/ripple/app/rdb/backend/detail/impl/Node.cpp b/src/ripple/app/rdb/backend/detail/impl/Node.cpp index b3b354ebe72..8948360a3ad 100644 --- a/src/ripple/app/rdb/backend/detail/impl/Node.cpp +++ b/src/ripple/app/rdb/backend/detail/impl/Node.cpp @@ -518,7 +518,7 @@ getHashByIndex(soci::session& session, LedgerIndex ledgerIndex) std::string sql = "SELECT LedgerHash FROM Ledgers INDEXED BY SeqLedger WHERE LedgerSeq='"; - sql.append(beast::lexicalCastThrow(ledgerIndex)); + sql.append(std::to_string(ledgerIndex)); sql.append("';"); std::string hash; @@ -581,9 +581,9 @@ getHashesByIndex( { std::string sql = "SELECT LedgerSeq,LedgerHash,PrevHash FROM Ledgers WHERE LedgerSeq >= "; - sql.append(beast::lexicalCastThrow(minSeq)); + sql.append(std::to_string(minSeq)); sql.append(" AND LedgerSeq <= "); - sql.append(beast::lexicalCastThrow(maxSeq)); + sql.append(std::to_string(maxSeq)); sql.append(";"); std::uint64_t ls; @@ -761,8 +761,7 @@ transactionsSQL( boost::format("SELECT %s FROM AccountTransactions " "WHERE Account = '%s' %s %s LIMIT %u, %u;") % selection % toBase58(options.account) % maxClause % minClause % - beast::lexicalCastThrow(options.offset) % - beast::lexicalCastThrow(numberOfResults)); + options.offset % numberOfResults); else sql = boost::str( boost::format( @@ -775,9 +774,7 @@ transactionsSQL( "LIMIT %u, %u;") % selection % toBase58(options.account) % maxClause % minClause % (descending ? "DESC" : "ASC") % (descending ? "DESC" : "ASC") % - (descending ? "DESC" : "ASC") % - beast::lexicalCastThrow(options.offset) % - beast::lexicalCastThrow(numberOfResults)); + (descending ? "DESC" : "ASC") % options.offset % numberOfResults); JLOG(j.trace()) << "txSQL query: " << sql; return sql; } diff --git a/src/ripple/beast/core/LexicalCast.h b/src/ripple/beast/core/LexicalCast.h index de1a6a396e9..975dd1ded43 100644 --- a/src/ripple/beast/core/LexicalCast.h +++ b/src/ripple/beast/core/LexicalCast.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -32,111 +33,10 @@ #include #include -#include - namespace beast { namespace detail { -#if BOOST_COMP_MSVC -#pragma warning(push) -#pragma warning(disable : 4800) -#pragma warning(disable : 4804) -#endif - -template -bool -parse_integral(Int& num, FwdIt first, FwdIt last, Accumulator accumulator) -{ - num = 0; - - if (first == last) - return false; - - while (first != last) - { - auto const c = *first++; - if (c < '0' || c > '9') - return false; - if (!accumulator(num, Int(c - '0'))) - return false; - } - - return true; -} - -template -bool -parse_negative_integral(Int& num, FwdIt first, FwdIt last) -{ - Int limit_value = std::numeric_limits::min() / 10; - Int limit_digit = std::numeric_limits::min() % 10; - - if (limit_digit < 0) - limit_digit = -limit_digit; - - return parse_integral( - num, first, last, [limit_value, limit_digit](Int& value, Int digit) { - assert((digit >= 0) && (digit <= 9)); - if (value < limit_value || - (value == limit_value && digit > limit_digit)) - return false; - value = (value * 10) - digit; - return true; - }); -} - -template -bool -parse_positive_integral(Int& num, FwdIt first, FwdIt last) -{ - Int limit_value = std::numeric_limits::max() / 10; - Int limit_digit = std::numeric_limits::max() % 10; - - return parse_integral( - num, first, last, [limit_value, limit_digit](Int& value, Int digit) { - assert((digit >= 0) && (digit <= 9)); - if (value > limit_value || - (value == limit_value && digit > limit_digit)) - return false; - value = (value * 10) + digit; - return true; - }); -} - -template -bool -parseSigned(IntType& result, FwdIt first, FwdIt last) -{ - static_assert( - std::is_signed::value, - "You may only call parseSigned with a signed integral type."); - - if (first != last && *first == '-') - return parse_negative_integral(result, first + 1, last); - - if (first != last && *first == '+') - return parse_positive_integral(result, first + 1, last); - - return parse_positive_integral(result, first, last); -} - -template -bool -parseUnsigned(UIntType& result, FwdIt first, FwdIt last) -{ - static_assert( - std::is_unsigned::value, - "You may only call parseUnsigned with an unsigned integral type."); - - if (first != last && *first == '+') - return parse_positive_integral(result, first + 1, last); - - return parse_positive_integral(result, first, last); -} - -//------------------------------------------------------------------------------ - // These specializatons get called by the non-member functions to do the work template struct LexicalCast; @@ -148,7 +48,7 @@ struct LexicalCast explicit LexicalCast() = default; template - std::enable_if_t::value, bool> + std::enable_if_t, bool> operator()(std::string& out, Arithmetic in) { out = std::to_string(in); @@ -156,7 +56,7 @@ struct LexicalCast } template - std::enable_if_t::value, bool> + std::enable_if_t, bool> operator()(std::string& out, Enumeration in) { out = std::to_string( @@ -172,21 +72,21 @@ struct LexicalCast explicit LexicalCast() = default; static_assert( - std::is_integral::value, + std::is_integral_v, "beast::LexicalCast can only be used with integral types"); template - std::enable_if_t::value, bool> + std::enable_if_t< + std::is_integral_v && !std::is_same_v, + bool> operator()(Integral& out, std::string const& in) const { - return parseUnsigned(out, in.begin(), in.end()); - } + auto first = in.data(); + auto last = in.data() + in.size(); - template - std::enable_if_t::value, bool> - operator()(Integral& out, std::string const& in) const - { - return parseSigned(out, in.begin(), in.end()); + auto ret = std::from_chars(first, last, out); + + return ret.ec == std::errc() && ret.ptr == last; } bool @@ -242,10 +142,6 @@ struct LexicalCast } }; -#if BOOST_COMP_MSVC -#pragma warning(pop) -#endif - } // namespace detail //------------------------------------------------------------------------------ @@ -278,9 +174,7 @@ template Out lexicalCastThrow(In in) { - Out out; - - if (lexicalCastChecked(out, in)) + if (Out out; lexicalCastChecked(out, in)) return out; throw BadLexicalCast(); @@ -295,9 +189,7 @@ template Out lexicalCast(In in, Out defaultValue = Out()) { - Out out; - - if (lexicalCastChecked(out, in)) + if (Out out; lexicalCastChecked(out, in)) return out; return defaultValue; diff --git a/src/test/beast/LexicalCast_test.cpp b/src/test/beast/LexicalCast_test.cpp index 680dc6d69ac..3daf5b0433d 100644 --- a/src/test/beast/LexicalCast_test.cpp +++ b/src/test/beast/LexicalCast_test.cpp @@ -221,7 +221,6 @@ class LexicalCast_test : public unit_test::suite expect(lexicalCastChecked(out, "-0"), "0"); expect(lexicalCastChecked(out, "0"), "0"); - expect(lexicalCastChecked(out, "+0"), "0"); } { @@ -229,7 +228,6 @@ class LexicalCast_test : public unit_test::suite expect(!lexicalCastChecked(out, "-0"), "0"); expect(lexicalCastChecked(out, "0"), "0"); - expect(lexicalCastChecked(out, "+0"), "0"); } } From 2ec019e1bb076325e3ef724d1553ce96e19762b3 Mon Sep 17 00:00:00 2001 From: Denis Angell Date: Fri, 26 May 2023 17:11:38 +0000 Subject: [PATCH 2/3] address the '+' issue --- src/ripple/beast/core/LexicalCast.h | 3 +++ src/test/beast/LexicalCast_test.cpp | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/ripple/beast/core/LexicalCast.h b/src/ripple/beast/core/LexicalCast.h index 975dd1ded43..07b09eb6738 100644 --- a/src/ripple/beast/core/LexicalCast.h +++ b/src/ripple/beast/core/LexicalCast.h @@ -84,6 +84,9 @@ struct LexicalCast auto first = in.data(); auto last = in.data() + in.size(); + if (first != last && *first == '+') + ++first; + auto ret = std::from_chars(first, last, out); return ret.ec == std::errc() && ret.ptr == last; diff --git a/src/test/beast/LexicalCast_test.cpp b/src/test/beast/LexicalCast_test.cpp index 3daf5b0433d..680dc6d69ac 100644 --- a/src/test/beast/LexicalCast_test.cpp +++ b/src/test/beast/LexicalCast_test.cpp @@ -221,6 +221,7 @@ class LexicalCast_test : public unit_test::suite expect(lexicalCastChecked(out, "-0"), "0"); expect(lexicalCastChecked(out, "0"), "0"); + expect(lexicalCastChecked(out, "+0"), "0"); } { @@ -228,6 +229,7 @@ class LexicalCast_test : public unit_test::suite expect(!lexicalCastChecked(out, "-0"), "0"); expect(lexicalCastChecked(out, "0"), "0"); + expect(lexicalCastChecked(out, "+0"), "0"); } } From 6e65149a58f796a20697cc78684a9763d431bc3b Mon Sep 17 00:00:00 2001 From: Denis Angell Date: Thu, 1 Jun 2023 19:50:53 +0000 Subject: [PATCH 3/3] remove unused dependency --- src/ripple/beast/core/LexicalCast.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ripple/beast/core/LexicalCast.h b/src/ripple/beast/core/LexicalCast.h index 07b09eb6738..f4c78341b91 100644 --- a/src/ripple/beast/core/LexicalCast.h +++ b/src/ripple/beast/core/LexicalCast.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include