mirror of https://github.com/bitcoin/bitcoin.git
refactor: Throw `std::string_view` instead of `const char*` in constexpr/consteval functions
Works around MinGW/libc++ bug where `BOOST_CHECK_EXCEPTION` catching `const char*` exceptions by reference is broken, see https://github.com/mstorsjo/llvm-mingw/issues/522 While throwing string literals is generally acceptable (clang-tidy explicitly allows it as idiomatic), using proper exception objects provides better type safety and avoids this platform-specific issue. Also deleted `HasReason::operator()(const char*)` to prevent future reliance on const char* exception handling. Co-authored-by: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Co-authored-by: Hodlinator <172445034+hodlinator@users.noreply.github.com> Co-authored-by: maflcko <6399679+maflcko@users.noreply.github.com>
This commit is contained in:
parent
b510893d00
commit
ec2476c811
|
@ -305,7 +305,8 @@ class HasReason
|
||||||
public:
|
public:
|
||||||
explicit HasReason(std::string_view reason) : m_reason(reason) {}
|
explicit HasReason(std::string_view reason) : m_reason(reason) {}
|
||||||
bool operator()(std::string_view s) const { return s.find(m_reason) != std::string_view::npos; }
|
bool operator()(std::string_view s) const { return s.find(m_reason) != std::string_view::npos; }
|
||||||
bool operator()(const std::exception& e) const { return (*this)(e.what()); }
|
bool operator()(const std::exception& e) const { return (*this)(std::string_view{e.what()}); }
|
||||||
|
bool operator()(const char* s) const = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string m_reason;
|
const std::string m_reason;
|
||||||
|
|
|
@ -37,7 +37,7 @@ void PassFmt(ConstevalFormatString<NumArgs> fmt)
|
||||||
template <unsigned WrongNumArgs>
|
template <unsigned WrongNumArgs>
|
||||||
void FailFmtWithError(const char* wrong_fmt, std::string_view error)
|
void FailFmtWithError(const char* wrong_fmt, std::string_view error)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EXCEPTION(CheckNumFormatSpecifiers<WrongNumArgs>(wrong_fmt), const char*, HasReason{error});
|
BOOST_CHECK_EXCEPTION(CheckNumFormatSpecifiers<WrongNumArgs>(wrong_fmt), std::string_view, HasReason{error});
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(ConstevalFormatString_NumSpec)
|
BOOST_AUTO_TEST_CASE(ConstevalFormatString_NumSpec)
|
||||||
|
|
|
@ -124,7 +124,7 @@ public:
|
||||||
template <unsigned int BITS>
|
template <unsigned int BITS>
|
||||||
consteval base_blob<BITS>::base_blob(std::string_view hex_str)
|
consteval base_blob<BITS>::base_blob(std::string_view hex_str)
|
||||||
{
|
{
|
||||||
if (hex_str.length() != m_data.size() * 2) throw "Hex string must fit exactly";
|
if (hex_str.length() != m_data.size() * 2) throw std::string_view("Hex string must fit exactly");
|
||||||
auto str_it = hex_str.rbegin();
|
auto str_it = hex_str.rbegin();
|
||||||
for (auto& elem : m_data) {
|
for (auto& elem : m_data) {
|
||||||
auto lo = util::ConstevalHexDigit(*(str_it++));
|
auto lo = util::ConstevalHexDigit(*(str_it++));
|
||||||
|
|
|
@ -331,7 +331,7 @@ consteval uint8_t ConstevalHexDigit(const char c)
|
||||||
if (c >= '0' && c <= '9') return c - '0';
|
if (c >= '0' && c <= '9') return c - '0';
|
||||||
if (c >= 'a' && c <= 'f') return c - 'a' + 0xa;
|
if (c >= 'a' && c <= 'f') return c - 'a' + 0xa;
|
||||||
|
|
||||||
throw "Only lowercase hex digits are allowed, for consistency";
|
throw std::string_view("Only lowercase hex digits are allowed, for consistency");
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
@ -342,7 +342,7 @@ struct Hex {
|
||||||
// 2 hex digits required per byte + implicit null terminator
|
// 2 hex digits required per byte + implicit null terminator
|
||||||
requires(N % 2 == 1)
|
requires(N % 2 == 1)
|
||||||
{
|
{
|
||||||
if (hex_str[N - 1]) throw "null terminator required";
|
if (hex_str[N - 1]) throw std::string_view("null terminator required");
|
||||||
for (std::size_t i = 0; i < bytes.size(); ++i) {
|
for (std::size_t i = 0; i < bytes.size(); ++i) {
|
||||||
bytes[i] = static_cast<std::byte>(
|
bytes[i] = static_cast<std::byte>(
|
||||||
(ConstevalHexDigit(hex_str[2 * i]) << 4) |
|
(ConstevalHexDigit(hex_str[2 * i]) << 4) |
|
||||||
|
|
|
@ -37,7 +37,7 @@ constexpr static void CheckNumFormatSpecifiers(const char* str)
|
||||||
if (*it == '$') {
|
if (*it == '$') {
|
||||||
++it;
|
++it;
|
||||||
// Positional specifier, like %8$s
|
// Positional specifier, like %8$s
|
||||||
if (maybe_num == 0) throw "Positional format specifier must have position of at least 1";
|
if (maybe_num == 0) throw std::string_view{"Positional format specifier must have position of at least 1"};
|
||||||
count_pos = std::max(count_pos, maybe_num);
|
count_pos = std::max(count_pos, maybe_num);
|
||||||
} else {
|
} else {
|
||||||
// Non-positional specifier, like %s
|
// Non-positional specifier, like %s
|
||||||
|
@ -69,14 +69,14 @@ constexpr static void CheckNumFormatSpecifiers(const char* str)
|
||||||
parse_size();
|
parse_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*it == '\0') throw "Format specifier incorrectly terminated by end of string";
|
if (*it == '\0') throw std::string_view{"Format specifier incorrectly terminated by end of string"};
|
||||||
|
|
||||||
// Length and type in "[flags][width][.precision][length]type"
|
// Length and type in "[flags][width][.precision][length]type"
|
||||||
// is not checked. Parsing continues with the next '%'.
|
// is not checked. Parsing continues with the next '%'.
|
||||||
}
|
}
|
||||||
if (count_normal && count_pos) throw "Format specifiers must be all positional or all non-positional!";
|
if (count_normal && count_pos) throw std::string_view{"Format specifiers must be all positional or all non-positional!"};
|
||||||
unsigned count{count_normal | count_pos};
|
unsigned count{count_normal | count_pos};
|
||||||
if (num_params != count) throw "Format specifier count must match the argument count!";
|
if (num_params != count) throw std::string_view{"Format specifier count must match the argument count!"};
|
||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue