diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-08-01 16:05:51 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-08-01 16:05:51 +0200 |
| commit | 71b3bbb7698b13b42c99a4ca66c27db4a6189ff8 (patch) | |
| tree | 1fc6ed246ecc0cf561f38ad774a4815ba357ea7b /boot/result.cc | |
| parent | 8539c10542a4be1e1127daea60bf1b1e4c37e092 (diff) | |
| download | elna-71b3bbb7698b13b42c99a4ca66c27db4a6189ff8.tar.gz | |
Enforce integral values in slice ranges
Diffstat (limited to 'boot/result.cc')
| -rw-r--r-- | boot/result.cc | 57 |
1 files changed, 46 insertions, 11 deletions
diff --git a/boot/result.cc b/boot/result.cc index 4d4c20f..f769625 100644 --- a/boot/result.cc +++ b/boot/result.cc @@ -17,6 +17,7 @@ along with GCC; see the file COPYING3. If not see #include "elna/boot/result.h" +#include <cstring> #include <numeric> namespace elna::boot @@ -340,6 +341,16 @@ namespace elna::boot return written > 1 ? std::nullopt : std::make_optional(rop); } + bool integer_literal::fit_into(const std::size_t target_size) + { + if (fits_in(target_size * CHAR_BIT)) + { + this->m_size = target_size; + return true; + } + return false; + } + bool integer_literal::is_signed() const { return this->m_signed; @@ -350,6 +361,18 @@ namespace elna::boot return this->m_size; } + std::string integer_literal::to_string(const std::uint8_t base) const + { + // +1 sign, +1 null terminator + const size_t buffer_size = mpz_sizeinbase(this->raw, static_cast<int>(base)) + 2; + std::string result(buffer_size, '\0'); + + mpz_get_str(result.data(), base, this->raw); + result.resize(std::strlen(result.c_str())); + + return result; + } + void swap(integer_literal& lhs, integer_literal& rhs) noexcept { mpz_swap(lhs.raw, rhs.raw); @@ -357,22 +380,20 @@ namespace elna::boot std::swap(lhs.m_size, rhs.m_size); } - std::optional<integer_literal> integer_literal::check() && + bool integer_literal::fits_in(const std::size_t bits) const { std::size_t required_bits = mpz_sizeinbase(this->raw, 2); - if (!is_negative_minimum()) + if (!is_negative_minimum(bits)) { ++required_bits; // Add one bit for the sign. } - if (required_bits > bits() || (mpz_sgn(this->raw) < 0 && !is_signed())) - { - return std::nullopt; - } - else - { - return std::move(*this); - } + return required_bits <= bits && (mpz_sgn(this->raw) >= 0 || is_signed()); + } + + std::optional<integer_literal> integer_literal::check() && + { + return fits_in(bits()) ? std::make_optional(std::move(*this)) : std::nullopt; } bool integer_literal::is_negative_minimum(const std::size_t bits) const @@ -454,5 +475,19 @@ std::size_t std::hash<elna::boot::constant_aggregate<elna::boot::ordered_map>>:: std::size_t std::hash<elna::boot::integer_literal>::operator()(const elna::boot::integer_literal& key) const noexcept { - return std::hash<std::uint32_t>{}(key.to<std::uint32_t>()); + if (key.is_signed()) + { + if (auto converted = key.to_signed()) + { + return std::hash<std::ptrdiff_t>{}(*converted); + } + } + else + { + if (auto converted = key.to_unsigned()) + { + return std::hash<std::size_t>{}(*converted); + } + } + return 0; } |
