ソースを参照

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.
Sam Atkins 2 年 前
コミット
efe4329f9f
2 ファイル変更95 行追加0 行削除
  1. 36 0
      AK/JsonValue.h
  2. 59 0
      Tests/AK/TestJSON.cpp

+ 36 - 0
AK/JsonValue.h

@@ -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:

+ 59 - 0
Tests/AK/TestJSON.cpp

@@ -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>());
+}