summaryrefslogtreecommitdiff
path: root/AK
diff options
context:
space:
mode:
authorLenny Maiorani <lenny@colorado.edu>2021-04-21 13:47:03 -0600
committerAndreas Kling <kling@serenityos.org>2021-04-21 23:26:16 +0200
commite117756d9f344c4b98b3dda8d5214b5cec8d73a7 (patch)
treebbb942bd059501d48b782cac0b9e4465e05c2b5d /AK
parent6cbf88ad4ccb0d7287e32a2f1311bb839e433c25 (diff)
downloadserenity-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.cpp36
-rw-r--r--AK/Format.h53
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.