rx/die: add die handler & fix make_format_args for fmt library

This commit is contained in:
DH 2025-12-28 19:20:05 +03:00
parent 498b580345
commit 0d049f7566
4 changed files with 53 additions and 17 deletions

View file

@ -1,26 +1,31 @@
#pragma once
#include "format-base.hpp"
#include <functional>
#include <utility>
namespace rx {
using DieHandler =
std::function<void(std::string_view text, std::source_location location)>;
void setDieHandler(DieHandler handler);
namespace detail {
[[noreturn]] void dieImpl(std::string_view fmt, format_args args,
std::source_location location);
}
template <typename... Args>
[[noreturn]] void die(rx::format_string_with_location<Args...> fmt,
[[noreturn]] void die(format_string_with_location<Args...> fmt,
const Args &...args) {
detail::dieImpl(fmt.get(), make_format_args(const_cast<Args &>(args)...),
fmt.location);
detail::dieImpl(fmt.get(), rx::make_format_args(args...), fmt.location);
}
template <typename... Args>
void dieIf(bool condition, rx::format_string_with_location<Args...> fmt,
void dieIf(bool condition, format_string_with_location<Args...> fmt,
const Args &...args) {
if (condition) {
detail::dieImpl(fmt.get(), make_format_args(const_cast<Args &>(args)...),
fmt.location);
detail::dieImpl(fmt.get(), rx::make_format_args(args...), fmt.location);
}
}
} // namespace rx

View file

@ -41,15 +41,27 @@ struct format_string_impl : fmt::format_string<Args...> {
return std::string_view(this->str);
}
};
template <typename T> struct make_format_arg_type {
using type = T &;
};
template <typename T>
requires requires(const T &arg) { fmt::make_format_args(arg); }
struct make_format_arg_type<T> {
using type = const T &;
};
} // namespace detail
template <typename... Args>
using format_string = std::type_identity_t<detail::format_string_impl<Args...>>;
template <typename... Args>
auto make_format_args(const Args &...args)
-> decltype(fmt::make_format_args(const_cast<Args &>(args)...)) {
return fmt::make_format_args(const_cast<Args &>(args)...);
auto make_format_args(const Args &...args) -> decltype(fmt::make_format_args(
const_cast<detail::make_format_arg_type<Args>::type>(args)...)) {
return fmt::make_format_args(
const_cast<detail::make_format_arg_type<Args>::type>(args)...);
}
using fmt::format_to;

View file

@ -173,6 +173,8 @@ constexpr auto calcFieldCount() {
return static_cast<std::size_t>(EnumT::_count);
} else if constexpr (requires { EnumT::count; }) {
return static_cast<std::size_t>(EnumT::count);
} else if constexpr (requires { EnumT::_last; }) {
return static_cast<std::size_t>(EnumT::_last) + 1;
} else if constexpr (!requires { getNameOf<EnumT(N)>()[0]; }) {
if constexpr (requires { getNameOf<EnumT(N + 1)>()[0]; }) {
if constexpr (constexpr auto c = getNameOf<EnumT(N + 1)>()[0];

View file

@ -1,18 +1,35 @@
#include "die.hpp"
#include "print.hpp"
#include "format-base.hpp"
#include <cstdio>
#include <cstdlib>
#include <rx/print.hpp>
static rx::DieHandler g_dieHandler;
void rx::setDieHandler(DieHandler handler) {
g_dieHandler = std::move(handler);
}
void rx::detail::dieImpl(std::string_view fmt, format_args args,
std::source_location location) {
rx::print(stderr, "\n");
rx::print(stderr, "{}:{}:{}: ", location.file_name(), location.line(),
location.column());
rx::vprint_nonunicode(stderr, fmt, args);
rx::print(stderr, "\n");
if (g_dieHandler != nullptr) {
rx::print(stderr, "\n");
std::fflush(stdout);
std::fflush(stderr);
g_dieHandler(rx::vformat(fmt, args), location);
} else {
rx::print(stderr, "\n");
rx::print(stderr, "{}:{}:{}: ", location.file_name(), location.line(),
location.column());
rx::vprint_nonunicode(stderr, fmt, args);
rx::print(stderr, "\n");
std::fflush(stdout);
std::fflush(stderr);
}
std::fflush(stdout);
std::fflush(stderr);
std::abort();
}