sandbox
Loading...
Searching...
No Matches
assert.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_UTILITY_ASSERT_HPP_
3#define LIBSBX_UTILITY_ASSERT_HPP_
4
5#include <concepts>
6#include <string_view>
7#include <source_location>
8#include <iostream>
9#include <ranges>
10#include <functional>
11
12#include <fmt/format.h>
13
14#include <libsbx/utility/target.hpp>
15
16namespace sbx::utility {
17
18template<std::convertible_to<bool> Expression>
19inline auto assert_that(Expression&& expression, std::string_view message, const std::source_location& source_location = std::source_location::current()) -> void {
20 if constexpr (is_build_configuration_debug_v) {
21 if (!static_cast<bool>(std::forward<Expression>(expression))) {
22 const auto error = fmt::format("Assertion '{}' at {}:{} in '{}' failed. Terminating.\n", message, source_location.file_name(), source_location.line(), source_location.function_name());
23
24 std::cerr.write(error.data(), static_cast<std::streamsize>(error.size()));
25 std::cerr.flush();
26
27 std::terminate();
28 }
29 }
30}
31
32template<std::ranges::range Range, typename Project>
33requires (std::is_invocable_r_v<bool, Project, std::ranges::range_const_reference_t<Range>>)
34inline auto assert_that(Range&& range, Project&& project, std::string_view message, const std::source_location& source_location = std::source_location::current()) -> void {
35 if constexpr (is_build_configuration_debug_v) {
36 for (const auto& [index, value] : std::views::enumerate(range)) {
37 if (!static_cast<bool>(std::invoke(project, value))) {
38 const auto error = fmt::format("Assertion '{}' at {}:{} in '{}' failed at index {}. Terminating.\n", message, source_location.file_name(), source_location.line(), source_location.function_name(), index);
39
40 std::cerr.write(error.data(), static_cast<std::streamsize>(error.size()));
41 std::cerr.flush();
42
43 std::terminate();
44 }
45 }
46
47 }
48}
49
50template<std::convertible_to<bool> Expression>
51inline auto expect_that(Expression&& expression, std::string_view message, const std::source_location& source_location = std::source_location::current()) -> void {
52 if constexpr (is_build_configuration_debug_v) {
53 if (!static_cast<bool>(expression)) {
54 const auto warning = fmt::format("Expectation '{}' at {}:{} in '{}' failed.\n", message, source_location.file_name(), source_location.line(), source_location.function_name());
55
56 std::cerr.write(warning.data(), static_cast<std::streamsize>(warning.size()));
57 std::cerr.flush();
58 }
59 }
60}
61
62template<std::ranges::range Range, typename Project>
63requires (std::is_invocable_r_v<bool, Project, std::ranges::range_const_reference_t<Range>>)
64inline auto expect_that(Range&& range, Project&& project, std::string_view message, const std::source_location& source_location = std::source_location::current()) -> void {
65 if constexpr (is_build_configuration_debug_v) {
66 for (const auto& [index, value] : std::views::enumerate(range)) {
67 if (!static_cast<bool>(std::invoke(project, value))) {
68 const auto error = fmt::format("Expectation '{}' at {}:{} in '{}' failed at index {}.\n", message, source_location.file_name(), source_location.line(), source_location.function_name(), index);
69
70 std::cerr.write(error.data(), static_cast<std::streamsize>(error.size()));
71 std::cerr.flush();
72 }
73 }
74
75 }
76}
77
78} // namespace sbx::utility
79
80#endif // LIBSBX_UTILITY_ASSERT_HPP_