22namespace hi {
inline namespace v1 {
30[[nodiscard]]
constexpr bool bound_check(std::unsigned_integral
auto index, std::unsigned_integral
auto upper)
noexcept
32 using value_type = common_integer_t<
decltype(index),
decltype(upper)>;
34 hilet index_ =
static_cast<value_type
>(index);
35 hilet upper_ =
static_cast<value_type
>(upper);
36 return index_ < upper_;
39[[nodiscard]]
constexpr bool bound_check(std::unsigned_integral
auto index, std::signed_integral
auto upper)
noexcept
44 return bound_check(index,
static_cast<std::make_unsigned_t<decltype(upper)
>>(upper));
55[[nodiscard]]
constexpr bool bound_check(std::integral
auto index, std::integral
auto lower, std::integral
auto upper)
noexcept
57 using value_type = common_integer_t<
decltype(index),
decltype(lower),
decltype(upper)>;
59 auto index_ =
static_cast<value_type
>(index);
60 auto lower_ =
static_cast<value_type
>(lower);
61 auto upper_ =
static_cast<value_type
>(upper);
64 if (not (lower_ < upper_)) {
68 hi_assume(lower_ < upper_);
71 return index_ >= lower_ and index_ < upper_;
74template<
typename Context>
77 std::ranges::size(range)
78 } -> std::unsigned_integral;
87[[nodiscard]]
constexpr bool bound_check(std::integral
auto index, bound_check_range_helper
auto&& range)
noexcept
89 static_assert(
sizeof(index) <=
sizeof(size_t));
91 if constexpr (std::is_signed_v<std::decay_t<
decltype(index)>>) {
97 return static_cast<size_t>(index) < std::ranges::size(range);
110#define hi_check(expression, message, ...) \
112 if (not(expression)) { \
113 if constexpr (__VA_OPT__(not ) false) { \
114 throw parse_error(std::format(message __VA_OPT__(, ) __VA_ARGS__)); \
116 throw parse_error(message); \
132#define hi_check_bounds(x, ...) \
134 if (not ::hi::bound_check(x, __VA_ARGS__)) { \
135 throw parse_error("assert bounds: " hi_stringify(x) " between " hi_for_each(hi_stringify, (__VA_ARGS__))); \
151#define hi_check_subspan(span, offset, ...) \
152 [&](auto _hi_check_subspan_span, size_t _hi_check_subspan_offset, auto... _hi_check_subspan_count) { \
153 if constexpr (sizeof...(_hi_check_subspan_count) == 0) { \
154 if (_hi_check_subspan_offset < _hi_check_subspan_span.size()) { \
155 return _hi_check_subspan_span.subspan(_hi_check_subspan_offset); \
157 } else if constexpr (sizeof...(_hi_check_subspan_count) == 1) { \
158 if (_hi_check_subspan_offset + wide_cast<size_t>(_hi_check_subspan_count...) <= _hi_check_subspan_span.size()) { \
159 return _hi_check_subspan_span.subspan(_hi_check_subspan_offset, _hi_check_subspan_count...); \
163 "assert bounds on: " hi_stringify(span) ".subspan(" hi_stringify(offset __VA_OPT__(", ") __VA_ARGS__) ")"); \
164 }(span, offset __VA_OPT__(, ) __VA_ARGS__)
176#define hi_check_at(span, index) \
177 [&](auto _hi_check_subspan_span, size_t _hi_check_subspan_index) { \
178 if (_hi_check_subspan_index < _hi_check_subspan_span.size()) { \
179 return _hi_check_subspan_span[_hi_check_subspan_index]; \
181 throw parse_error("assert bounds on: " hi_stringify(span) "[" hi_stringify(index) "]"); \
185#define hi_hresult_check(expression) \
186 ([](HRESULT result) { \
187 if (FAILED(result)) { \
188 throw ::hi::io_error(std::format("Call to '{}' failed with {:08x}", #expression, result)); \
199#define hi_assert(expression, ...) \
201 if (not(expression)) { \
202 hi_debug_abort("assert: " __VA_ARGS__ " (" hi_stringify(expression) ")"); \
212#define hi_assert_or_return(x, y) \
214 [[unlikely]] return y; \
225#define hi_assert_bounds(x, ...) \
227 if (not ::hi::bound_check(x, __VA_ARGS__)) { \
228 hi_debug_abort("assert bounds: " hi_stringify(x) " between " hi_for_each(hi_stringify, (__VA_ARGS__))); \
238#define hi_assert_not_null(x, ...) \
240 if (x == nullptr) { \
241 hi_debug_abort("assert not-null: " __VA_ARGS__ " (" hi_stringify(x) ")"); \
253#define hi_axiom(expression, ...) hi_assert(expression __VA_OPT__(, ) __VA_ARGS__)
264#define hi_axiom_bounds(x, ...) hi_assert_bounds(x, __VA_ARGS__)
272#define hi_axiom_not_null(expression, ...) hi_assert_not_null(expression __VA_OPT__(, ) __VA_ARGS__)
279#define hi_no_default(...) [[unlikely]] hi_debug_abort("Reached no-default:" __VA_ARGS__)
289#define hi_axiom(expression, ...) hi_assume(expression)
300#define hi_axiom_bounds(x, ...) hi_assume(not ::hi::bound_check(x, __VA_ARGS__))
308#define hi_axiom_not_null(expression, ...) hi_assume(expression != nullptr)
315#define hi_no_default(...) hi_unreachable()
323#define hi_static_no_default(...) \
324 []<bool Flag = false>() \
326 static_assert(Flag, "No default: " __VA_ARGS__); \
335#define hi_not_implemented(...) [[unlikely]] hi_debug_abort("Not implemented: " __VA_ARGS__);
342#define hi_static_not_implemented(...) hi_static_no_default("Not implemented: " __VA_ARGS__)
hi_warning_ignore_msvc(26472)
Definition int_carry.hpp:27
Utilities for throwing exceptions and terminating the application.
Functions and macros for handling architectural difference between compilers, CPUs and operating syst...
Utilities used by the HikoGUI library itself.
Utilities to interact with the debugger this application runs under.
#define hi_debug_abort(...)
Debug-break and abort the application.
Definition debugger.hpp:50
geometry/margins.hpp
Definition cache.hpp:11
The HikoGUI API version 1.
Definition cache.hpp:11
constexpr bool bound_check(std::unsigned_integral auto index, std::unsigned_integral auto upper) noexcept
Check if an unsigned index is less than the bound.
Definition assert.hpp:30