aboutsummaryrefslogtreecommitdiff
path: root/boot/result.cc
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-08-01 09:30:39 +0200
committerEugen Wissner <belka@caraus.de>2026-08-01 09:34:21 +0200
commit8539c10542a4be1e1127daea60bf1b1e4c37e092 (patch)
treef04e3b0e97e4d201ee5ebdb0b2bd9079af4b1820 /boot/result.cc
parent661c29a7835cf1755deaf21f91832f00e958a318 (diff)
downloadelna-8539c10542a4be1e1127daea60bf1b1e4c37e092.tar.gz
Fix compile-time negation and array access
Diffstat (limited to 'boot/result.cc')
-rw-r--r--boot/result.cc55
1 files changed, 49 insertions, 6 deletions
diff --git a/boot/result.cc b/boot/result.cc
index f9f57db..4d4c20f 100644
--- a/boot/result.cc
+++ b/boot/result.cc
@@ -129,12 +129,14 @@ namespace elna::boot
}
integer_literal::integer_literal(integer_literal&& that) noexcept
+ : m_signed(that.is_signed()), m_size(that.size())
{
mpz_init(this->raw);
mpz_swap(this->raw, that.raw);
}
integer_literal::integer_literal(const integer_literal& that)
+ : m_signed(that.is_signed()), m_size(that.size())
{
mpz_init(this->raw);
mpz_set(this->raw, that.raw);
@@ -293,10 +295,7 @@ namespace elna::boot
integer_literal& integer_literal::operator=(integer_literal&& that) noexcept
{
- if (this != &that)
- {
- mpz_swap(this->raw, that.raw);
- }
+ swap(*this, that);
return *this;
}
@@ -304,11 +303,43 @@ namespace elna::boot
{
if (this != &that)
{
- mpz_set(this->raw, that.raw);
+ integer_literal temp(that);
+
+ swap(*this, temp);
}
return *this;
}
+ std::optional<std::ptrdiff_t> integer_literal::to_signed() const
+ {
+ if (!is_signed())
+ {
+ return std::nullopt;
+ }
+ if (is_negative_minimum(sizeof(std::ptrdiff_t) * CHAR_BIT))
+ {
+ return std::numeric_limits<ptrdiff_t>::min();
+ }
+ auto [written, rop] = export_to_words<std::ptrdiff_t>();
+
+ if (written > 1 || rop < 0)
+ {
+ return std::nullopt;
+ }
+ return mpz_sgn(this->raw) < 0 ? -rop : rop;
+ }
+
+ std::optional<std::size_t> integer_literal::to_unsigned() const
+ {
+ if (is_signed())
+ {
+ return std::nullopt;
+ }
+ auto [written, rop] = export_to_words<std::size_t>();
+
+ return written > 1 ? std::nullopt : std::make_optional(rop);
+ }
+
bool integer_literal::is_signed() const
{
return this->m_signed;
@@ -319,6 +350,13 @@ namespace elna::boot
return this->m_size;
}
+ void swap(integer_literal& lhs, integer_literal& rhs) noexcept
+ {
+ mpz_swap(lhs.raw, rhs.raw);
+ std::swap(lhs.m_signed, rhs.m_signed);
+ std::swap(lhs.m_size, rhs.m_size);
+ }
+
std::optional<integer_literal> integer_literal::check() &&
{
std::size_t required_bits = mpz_sizeinbase(this->raw, 2);
@@ -337,9 +375,14 @@ namespace elna::boot
}
}
+ bool integer_literal::is_negative_minimum(const std::size_t bits) const
+ {
+ return mpz_sgn(this->raw) < 0 && mpz_scan1(this->raw, 0) == bits - 1;
+ }
+
bool integer_literal::is_negative_minimum() const
{
- return mpz_sgn(this->raw) < 0 && mpz_scan1(this->raw, 0) == bits() - 1;
+ return is_negative_minimum(bits());
}
std::size_t integer_literal::bits() const