#ifndef BEAST_MODULE_CORE_TEXT_LEXICALCAST_H_INCLUDED #define BEAST_MODULE_CORE_TEXT_LEXICALCAST_H_INCLUDED #include #include #include #include #include #include #include #include #include #include namespace beast { namespace detail { // These specializatons get called by the non-member functions to do the work template struct LexicalCast; // conversion to std::string template struct LexicalCast { explicit LexicalCast() = default; template std::enable_if_t, bool> operator()(std::string& out, Arithmetic in) { out = std::to_string(in); return true; } template std::enable_if_t, bool> operator()(std::string& out, Enumeration in) { out = std::to_string( static_cast>(in)); return true; } }; // Parse a std::string_view into a number template struct LexicalCast { explicit LexicalCast() = default; static_assert( std::is_integral_v, "beast::LexicalCast can only be used with integral types"); template std::enable_if_t< std::is_integral_v && !std::is_same_v, bool> operator()(Integral& out, std::string_view in) const { 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; } bool operator()(bool& out, std::string_view in) const { std::string result; // Convert the input to lowercase std::transform( in.begin(), in.end(), std::back_inserter(result), [](auto c) { return std::tolower(static_cast(c)); }); if (result == "1" || result == "true") { out = true; return true; } if (result == "0" || result == "false") { out = false; return true; } return false; } }; //------------------------------------------------------------------------------ // Parse boost library's string_view to number or boolean value // Note: As of Jan 2024, Boost contains three different types of string_view // (boost::core::basic_string_view, boost::string_ref and // boost::string_view). The below template specialization is included because // it is used in the handshake.cpp file template struct LexicalCast> { explicit LexicalCast() = default; bool operator()(Out& out, boost::core::basic_string_view in) const { return LexicalCast()(out, in); } }; // Parse std::string to number or boolean value template struct LexicalCast { explicit LexicalCast() = default; bool operator()(Out& out, std::string in) const { return LexicalCast()(out, in); } }; // Conversion from null terminated char const* template struct LexicalCast { explicit LexicalCast() = default; bool operator()(Out& out, char const* in) const { XRPL_ASSERT( in, "beast::detail::LexicalCast(char const*) : non-null input"); return LexicalCast()(out, in); } }; // Conversion from null terminated char* // The string is not modified. template struct LexicalCast { explicit LexicalCast() = default; bool operator()(Out& out, char* in) const { XRPL_ASSERT(in, "beast::detail::LexicalCast(char*) : non-null input"); return LexicalCast()(out, in); } }; } // namespace detail //------------------------------------------------------------------------------ /** Thrown when a conversion is not possible with LexicalCast. Only used in the throw variants of lexicalCast. */ struct BadLexicalCast : public std::bad_cast { explicit BadLexicalCast() = default; }; /** Intelligently convert from one type to another. @return `false` if there was a parsing or range error */ template bool lexicalCastChecked(Out& out, In in) { return detail::LexicalCast()(out, in); } /** Convert from one type to another, throw on error An exception of type BadLexicalCast is thrown if the conversion fails. @return The new type. */ template Out lexicalCastThrow(In in) { if (Out out; lexicalCastChecked(out, in)) return out; throw BadLexicalCast(); } /** Convert from one type to another. @param defaultValue The value returned if parsing fails @return The new type. */ template Out lexicalCast(In in, Out defaultValue = Out()) { if (Out out; lexicalCastChecked(out, in)) return out; return defaultValue; } } // namespace beast #endif