1
0
mirror of https://github.com/SerenityOS/serenity synced 2024-07-09 06:20:46 +00:00

AK: Add JsonValue::{is,as}_integer() methods

The existing `is_i32()` and friends only check if `i32` is their
internal type, but a value such as `0` could be literally any integer
type internally. `is_integer<T>()` instead determines whether the
contained value is an integer and can fit inside T.
This commit is contained in:
Sam Atkins 2022-12-21 16:07:14 +00:00 committed by Tim Flynn
parent 6d93947212
commit efe4329f9f
2 changed files with 95 additions and 0 deletions

View File

@ -261,6 +261,42 @@ public:
return default_value;
}
template<Integral T>
bool is_integer() const
{
switch (m_type) {
case Type::Int32:
return is_within_range<T>(m_value.as_i32);
case Type::UnsignedInt32:
return is_within_range<T>(m_value.as_u32);
case Type::Int64:
return is_within_range<T>(m_value.as_i64);
case Type::UnsignedInt64:
return is_within_range<T>(m_value.as_u64);
default:
return false;
}
}
template<Integral T>
T as_integer() const
{
VERIFY(is_integer<T>());
switch (m_type) {
case Type::Int32:
return static_cast<T>(m_value.as_i32);
case Type::UnsignedInt32:
return static_cast<T>(m_value.as_u32);
case Type::Int64:
return static_cast<T>(m_value.as_i64);
case Type::UnsignedInt64:
return static_cast<T>(m_value.as_u64);
default:
VERIFY_NOT_REACHED();
}
}
bool equals(JsonValue const& other) const;
private:

View File

@ -371,3 +371,62 @@ TEST_CASE(fallible_json_array_for_each)
EXPECT(result4.is_error());
EXPECT((IsSame<decltype(result4.release_error()), CustomError>));
}
TEST_CASE(json_value_as_integer)
{
// is_integer() should validate based on the value, not the underlying type.
JsonValue value_int { static_cast<int>(42) };
JsonValue value_unsigned { static_cast<unsigned>(42) };
JsonValue value_long { static_cast<long>(42) };
JsonValue value_long_unsigned { static_cast<long unsigned>(42) };
JsonValue value_long_long { static_cast<long long>(42) };
JsonValue value_long_long_unsigned { static_cast<long long unsigned>(42) };
auto check_is_valid_for_all_types = [](JsonValue& value) {
EXPECT(value.is_integer<u8>());
EXPECT_EQ(value.as_integer<u8>(), static_cast<u8>(42));
EXPECT(value.is_integer<u16>());
EXPECT_EQ(value.as_integer<u16>(), static_cast<u16>(42));
EXPECT(value.is_integer<u32>());
EXPECT_EQ(value.as_integer<u32>(), static_cast<u32>(42));
EXPECT(value.is_integer<u64>());
EXPECT_EQ(value.as_integer<u64>(), static_cast<u64>(42));
EXPECT(value.is_integer<i8>());
EXPECT_EQ(value.as_integer<i8>(), static_cast<i8>(42));
EXPECT(value.is_integer<i16>());
EXPECT_EQ(value.as_integer<i16>(), static_cast<i16>(42));
EXPECT(value.is_integer<i32>());
EXPECT_EQ(value.as_integer<i32>(), static_cast<i32>(42));
EXPECT(value.is_integer<i64>());
EXPECT_EQ(value.as_integer<i64>(), static_cast<i64>(42));
};
check_is_valid_for_all_types(value_int);
check_is_valid_for_all_types(value_unsigned);
check_is_valid_for_all_types(value_long);
check_is_valid_for_all_types(value_long_unsigned);
check_is_valid_for_all_types(value_long_long);
check_is_valid_for_all_types(value_long_long_unsigned);
// Negative values should only fit in signed types.
JsonValue negative_value { -42 };
EXPECT(!negative_value.is_integer<u8>());
EXPECT(!negative_value.is_integer<u16>());
EXPECT(!negative_value.is_integer<u32>());
EXPECT(!negative_value.is_integer<u64>());
EXPECT(negative_value.is_integer<i8>());
EXPECT(negative_value.is_integer<i16>());
EXPECT(negative_value.is_integer<i32>());
EXPECT(negative_value.is_integer<i64>());
// 64-bit only
JsonValue very_large_value { INT64_MAX };
EXPECT(!very_large_value.is_integer<u8>());
EXPECT(!very_large_value.is_integer<u16>());
EXPECT(!very_large_value.is_integer<u32>());
EXPECT(very_large_value.is_integer<u64>());
EXPECT(!very_large_value.is_integer<i8>());
EXPECT(!very_large_value.is_integer<i16>());
EXPECT(!very_large_value.is_integer<i32>());
EXPECT(very_large_value.is_integer<i64>());
}