diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-08-01 09:30:39 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-08-01 09:34:21 +0200 |
| commit | 8539c10542a4be1e1127daea60bf1b1e4c37e092 (patch) | |
| tree | f04e3b0e97e4d201ee5ebdb0b2bd9079af4b1820 /boot/result.cc | |
| parent | 661c29a7835cf1755deaf21f91832f00e958a318 (diff) | |
| download | elna-8539c10542a4be1e1127daea60bf1b1e4c37e092.tar.gz | |
Fix compile-time negation and array access
Diffstat (limited to 'boot/result.cc')
| -rw-r--r-- | boot/result.cc | 55 |
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 |
