diff options
author | Lenny Maiorani <lenny@colorado.edu> | 2021-04-21 13:47:03 -0600 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-04-21 23:26:16 +0200 |
commit | e117756d9f344c4b98b3dda8d5214b5cec8d73a7 (patch) | |
tree | bbb942bd059501d48b782cac0b9e4465e05c2b5d /AK | |
parent | 6cbf88ad4ccb0d7287e32a2f1311bb839e433c25 (diff) | |
download | serenity-e117756d9f344c4b98b3dda8d5214b5cec8d73a7.zip |
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.
Diffstat (limited to 'AK')
-rw-r--r-- | AK/Format.cpp | 36 | ||||
-rw-r--r-- | 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<size_t>::max(); +static constexpr size_t use_next_index = NumericLimits<size_t>::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<u8, 128>& buffer, u8 base, bool upper_case) +static constexpr size_t convert_unsigned_to_string(u64 value, Array<u8, 128>& 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<const u8*>(value); - else if (type == TypeErasedParameter::Type::UInt16) - svalue = *reinterpret_cast<const u16*>(value); - else if (type == TypeErasedParameter::Type::UInt32) - svalue = *reinterpret_cast<const u32*>(value); - else if (type == TypeErasedParameter::Type::UInt64) - svalue = *reinterpret_cast<const u64*>(value); - else if (type == TypeErasedParameter::Type::Int8) - svalue = *reinterpret_cast<const i8*>(value); - else if (type == TypeErasedParameter::Type::Int16) - svalue = *reinterpret_cast<const i16*>(value); - else if (type == TypeErasedParameter::Type::Int32) - svalue = *reinterpret_cast<const i32*>(value); - else if (type == TypeErasedParameter::Type::Int64) - svalue = *reinterpret_cast<const i64*>(value); - else - VERIFY_NOT_REACHED(); - - VERIFY(svalue >= 0); - - return static_cast<size_t>(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<size_t size, bool is_unsigned> + 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<typename T> - static Type get_type() + static consteval Type get_type() { if constexpr (IsIntegral<T>) - return get_type_from_size(sizeof(T), IsUnsigned<T>); + return get_type_from_size<sizeof(T), IsUnsigned<T>>(); 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<const u8*>(value); + else if (type == TypeErasedParameter::Type::UInt16) + svalue = *static_cast<const u16*>(value); + else if (type == TypeErasedParameter::Type::UInt32) + svalue = *static_cast<const u32*>(value); + else if (type == TypeErasedParameter::Type::UInt64) + svalue = *static_cast<const u64*>(value); + else if (type == TypeErasedParameter::Type::Int8) + svalue = *static_cast<const i8*>(value); + else if (type == TypeErasedParameter::Type::Int16) + svalue = *static_cast<const i16*>(value); + else if (type == TypeErasedParameter::Type::Int32) + svalue = *static_cast<const i32*>(value); + else if (type == TypeErasedParameter::Type::Int64) + svalue = *static_cast<const i64*>(value); + else + VERIFY_NOT_REACHED(); + + VERIFY(svalue >= 0); + + return static_cast<size_t>(svalue); + } // FIXME: Getters and setters. |