aboutsummaryrefslogtreecommitdiff
path: root/boot/result.cc
diff options
context:
space:
mode:
Diffstat (limited to 'boot/result.cc')
-rw-r--r--boot/result.cc57
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;
}