From e117756d9f344c4b98b3dda8d5214b5cec8d73a7 Mon Sep 17 00:00:00 2001 From: Lenny Maiorani Date: Wed, 21 Apr 2021 13:47:03 -0600 Subject: [PATCH] AK/Format: Compute TypeErasedParameter type and size at compile-time Problem: - Type and size information is known at compile-time, but computations are being performed using run-time parameters. Solution: - Move function arguments to be template arguments. - Convert to `consteval` where possible. - Decorate functions with `constexpr` which are used in both run-time and compile-time contexts. --- AK/Format.cpp | 36 ++++------------------------------ AK/Format.h | 53 ++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 44 insertions(+), 45 deletions(-) diff --git a/AK/Format.cpp b/AK/Format.cpp index e9c56489a7..5ee1160067 100644 --- a/AK/Format.cpp +++ b/AK/Format.cpp @@ -46,16 +46,16 @@ namespace AK { namespace { -constexpr size_t use_next_index = NumericLimits::max(); +static constexpr size_t use_next_index = NumericLimits::max(); // The worst case is that we have the largest 64-bit value formatted as binary number, this would take // 65 bytes. Choosing a larger power of two won't hurt and is a bit of mitigation against out-of-bounds accesses. -inline size_t convert_unsigned_to_string(u64 value, Array& buffer, u8 base, bool upper_case) +static constexpr size_t convert_unsigned_to_string(u64 value, Array& buffer, u8 base, bool upper_case) { VERIFY(base >= 2 && base <= 16); - static constexpr const char* lowercase_lookup = "0123456789abcdef"; - static constexpr const char* uppercase_lookup = "0123456789ABCDEF"; + constexpr const char* lowercase_lookup = "0123456789abcdef"; + constexpr const char* uppercase_lookup = "0123456789ABCDEF"; if (value == 0) { buffer[0] = '0'; @@ -102,34 +102,6 @@ void vformat_impl(TypeErasedFormatParams& params, FormatBuilder& builder, Format } // namespace AK::{anonymous} -size_t TypeErasedParameter::to_size() const -{ - i64 svalue; - - if (type == TypeErasedParameter::Type::UInt8) - svalue = *reinterpret_cast(value); - else if (type == TypeErasedParameter::Type::UInt16) - svalue = *reinterpret_cast(value); - else if (type == TypeErasedParameter::Type::UInt32) - svalue = *reinterpret_cast(value); - else if (type == TypeErasedParameter::Type::UInt64) - svalue = *reinterpret_cast(value); - else if (type == TypeErasedParameter::Type::Int8) - svalue = *reinterpret_cast(value); - else if (type == TypeErasedParameter::Type::Int16) - svalue = *reinterpret_cast(value); - else if (type == TypeErasedParameter::Type::Int32) - svalue = *reinterpret_cast(value); - else if (type == TypeErasedParameter::Type::Int64) - svalue = *reinterpret_cast(value); - else - VERIFY_NOT_REACHED(); - - VERIFY(svalue >= 0); - - return static_cast(svalue); -} - FormatParser::FormatParser(StringView input) : GenericLexer(input) { diff --git a/AK/Format.h b/AK/Format.h index 3193c79220..ceaec1dcce 100644 --- a/AK/Format.h +++ b/AK/Format.h @@ -65,25 +65,26 @@ struct TypeErasedParameter { Custom }; - static Type get_type_from_size(size_t size, bool is_unsigned) + template + static consteval Type get_type_from_size() { - if (is_unsigned) { - if (size == 1) + if constexpr (is_unsigned) { + if constexpr (size == 1) return Type::UInt8; - if (size == 2) + if constexpr (size == 2) return Type::UInt16; - if (size == 4) + if constexpr (size == 4) return Type::UInt32; - if (size == 8) + if constexpr (size == 8) return Type::UInt64; } else { - if (size == 1) + if constexpr (size == 1) return Type::Int8; - if (size == 2) + if constexpr (size == 2) return Type::Int16; - if (size == 4) + if constexpr (size == 4) return Type::Int32; - if (size == 8) + if constexpr (size == 8) return Type::Int64; } @@ -91,15 +92,41 @@ struct TypeErasedParameter { } template - static Type get_type() + static consteval Type get_type() { if constexpr (IsIntegral) - return get_type_from_size(sizeof(T), IsUnsigned); + return get_type_from_size>(); else return Type::Custom; } - size_t to_size() const; + constexpr size_t to_size() const + { + i64 svalue; + + if (type == TypeErasedParameter::Type::UInt8) + svalue = *static_cast(value); + else if (type == TypeErasedParameter::Type::UInt16) + svalue = *static_cast(value); + else if (type == TypeErasedParameter::Type::UInt32) + svalue = *static_cast(value); + else if (type == TypeErasedParameter::Type::UInt64) + svalue = *static_cast(value); + else if (type == TypeErasedParameter::Type::Int8) + svalue = *static_cast(value); + else if (type == TypeErasedParameter::Type::Int16) + svalue = *static_cast(value); + else if (type == TypeErasedParameter::Type::Int32) + svalue = *static_cast(value); + else if (type == TypeErasedParameter::Type::Int64) + svalue = *static_cast(value); + else + VERIFY_NOT_REACHED(); + + VERIFY(svalue >= 0); + + return static_cast(svalue); + } // FIXME: Getters and setters.