mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 08:24:58 +00:00
AK: Store JsonValue's value in AK::Variant
This commit is contained in:
parent
05e53b5fd3
commit
88af15d513
3 changed files with 137 additions and 249 deletions
|
@ -138,44 +138,18 @@ inline typename Builder::OutputType JsonObject::serialized() const
|
||||||
template<typename Builder>
|
template<typename Builder>
|
||||||
inline void JsonValue::serialize(Builder& builder) const
|
inline void JsonValue::serialize(Builder& builder) const
|
||||||
{
|
{
|
||||||
switch (m_type) {
|
m_value.visit(
|
||||||
case Type::String: {
|
[&](Empty const&) { builder.append("null"sv); },
|
||||||
builder.append('\"');
|
[&](bool const& value) { builder.append(value ? "true"sv : "false"sv); },
|
||||||
builder.append_escaped_for_json({ m_value.as_string->characters(), m_value.as_string->length() });
|
[&](Arithmetic auto const& value) { builder.appendff("{}", value); },
|
||||||
builder.append('\"');
|
[&](ByteString const& value) {
|
||||||
} break;
|
builder.append('\"');
|
||||||
case Type::Array:
|
builder.append_escaped_for_json(value.bytes());
|
||||||
m_value.as_array->serialize(builder);
|
builder.append('\"');
|
||||||
break;
|
},
|
||||||
case Type::Object:
|
[&](auto const& array_or_object) {
|
||||||
m_value.as_object->serialize(builder);
|
array_or_object->serialize(builder);
|
||||||
break;
|
});
|
||||||
case Type::Bool:
|
|
||||||
builder.append(m_value.as_bool ? "true"sv : "false"sv);
|
|
||||||
break;
|
|
||||||
#if !defined(KERNEL)
|
|
||||||
case Type::Double:
|
|
||||||
builder.appendff("{}", m_value.as_double);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case Type::Int32:
|
|
||||||
builder.appendff("{}", m_value.as_i32);
|
|
||||||
break;
|
|
||||||
case Type::Int64:
|
|
||||||
builder.appendff("{}", m_value.as_i64);
|
|
||||||
break;
|
|
||||||
case Type::UnsignedInt32:
|
|
||||||
builder.appendff("{}", m_value.as_u32);
|
|
||||||
break;
|
|
||||||
case Type::UnsignedInt64:
|
|
||||||
builder.appendff("{}", m_value.as_u64);
|
|
||||||
break;
|
|
||||||
case Type::Null:
|
|
||||||
builder.append("null"sv);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
VERIFY_NOT_REACHED();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Builder>
|
template<typename Builder>
|
||||||
|
|
156
AK/JsonValue.cpp
156
AK/JsonValue.cpp
|
@ -1,69 +1,77 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||||
|
* Copyright (c) 2024, Dan Klishch <danilklishch@gmail.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/JsonArray.h>
|
#include <AK/JsonArray.h>
|
||||||
#include <AK/JsonObject.h>
|
#include <AK/JsonObject.h>
|
||||||
|
#include <AK/JsonParser.h>
|
||||||
#include <AK/JsonValue.h>
|
#include <AK/JsonValue.h>
|
||||||
#include <AK/StringView.h>
|
#include <AK/StringView.h>
|
||||||
|
|
||||||
#ifndef KERNEL
|
|
||||||
# include <AK/JsonParser.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace AK {
|
namespace AK {
|
||||||
|
|
||||||
JsonValue::JsonValue(JsonValue const& other)
|
namespace {
|
||||||
|
using JsonValueStorage = Variant<
|
||||||
|
Empty,
|
||||||
|
bool,
|
||||||
|
i64,
|
||||||
|
u64,
|
||||||
|
double,
|
||||||
|
ByteString,
|
||||||
|
NonnullOwnPtr<JsonArray>,
|
||||||
|
NonnullOwnPtr<JsonObject>>;
|
||||||
|
|
||||||
|
static ErrorOr<JsonValueStorage> clone(JsonValueStorage const& other)
|
||||||
|
{
|
||||||
|
return other.visit(
|
||||||
|
[](NonnullOwnPtr<JsonArray> const& value) -> ErrorOr<JsonValueStorage> {
|
||||||
|
return TRY(try_make<JsonArray>(*value));
|
||||||
|
},
|
||||||
|
[](NonnullOwnPtr<JsonObject> const& value) -> ErrorOr<JsonValueStorage> {
|
||||||
|
return TRY(try_make<JsonObject>(*value));
|
||||||
|
},
|
||||||
|
[](auto const& value) -> ErrorOr<JsonValueStorage> { return JsonValueStorage(value); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValue::JsonValue() = default;
|
||||||
|
JsonValue::~JsonValue() = default;
|
||||||
|
JsonValue::JsonValue(JsonValue&&) = default;
|
||||||
|
JsonValue& JsonValue::operator=(JsonValue&&) = default;
|
||||||
|
|
||||||
|
JsonValue::JsonValue(JsonValue const& other)
|
||||||
|
: m_value(MUST(clone(other.m_value)))
|
||||||
{
|
{
|
||||||
copy_from(other);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue& JsonValue::operator=(JsonValue const& other)
|
JsonValue& JsonValue::operator=(JsonValue const& other)
|
||||||
{
|
{
|
||||||
if (this != &other) {
|
if (this != &other)
|
||||||
clear();
|
m_value = MUST(clone(other.m_value));
|
||||||
copy_from(other);
|
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonValue::copy_from(JsonValue const& other)
|
JsonValue& JsonValue::operator=(JsonArray const& other)
|
||||||
{
|
{
|
||||||
m_type = other.m_type;
|
return *this = JsonValue(other);
|
||||||
switch (m_type) {
|
|
||||||
case Type::String:
|
|
||||||
VERIFY(!m_value.as_string);
|
|
||||||
m_value.as_string = other.m_value.as_string;
|
|
||||||
m_value.as_string->ref();
|
|
||||||
break;
|
|
||||||
case Type::Object:
|
|
||||||
m_value.as_object = new JsonObject(*other.m_value.as_object);
|
|
||||||
break;
|
|
||||||
case Type::Array:
|
|
||||||
m_value.as_array = new JsonArray(*other.m_value.as_array);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
m_value.as_u64 = other.m_value.as_u64;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue::JsonValue(JsonValue&& other)
|
JsonValue& JsonValue::operator=(JsonArray&& other)
|
||||||
{
|
{
|
||||||
m_type = exchange(other.m_type, Type::Null);
|
return *this = JsonValue(other);
|
||||||
m_value.as_u64 = exchange(other.m_value.as_u64, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue& JsonValue::operator=(JsonValue&& other)
|
JsonValue& JsonValue::operator=(JsonObject const& other)
|
||||||
{
|
{
|
||||||
if (this != &other) {
|
return *this = JsonValue(other);
|
||||||
clear();
|
}
|
||||||
m_type = exchange(other.m_type, Type::Null);
|
|
||||||
m_value.as_u64 = exchange(other.m_value.as_u64, 0);
|
JsonValue& JsonValue::operator=(JsonObject&& other)
|
||||||
}
|
{
|
||||||
return *this;
|
return *this = JsonValue(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonValue::equals(JsonValue const& other) const
|
bool JsonValue::equals(JsonValue const& other) const
|
||||||
|
@ -127,122 +135,78 @@ bool JsonValue::equals(JsonValue const& other) const
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue::JsonValue(int value)
|
JsonValue::JsonValue(int value)
|
||||||
: m_type(Type::Int32)
|
: m_value(i64 { value })
|
||||||
{
|
{
|
||||||
m_value.as_i32 = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue::JsonValue(unsigned value)
|
JsonValue::JsonValue(unsigned value)
|
||||||
: m_type(Type::UnsignedInt32)
|
: m_value(i64 { value })
|
||||||
{
|
{
|
||||||
m_value.as_u32 = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue::JsonValue(long value)
|
JsonValue::JsonValue(long value)
|
||||||
: m_type(sizeof(long) == 8 ? Type::Int64 : Type::Int32)
|
: m_value(i64 { value })
|
||||||
{
|
{
|
||||||
if constexpr (sizeof(long) == 8)
|
|
||||||
m_value.as_i64 = value;
|
|
||||||
else
|
|
||||||
m_value.as_i32 = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue::JsonValue(unsigned long value)
|
JsonValue::JsonValue(unsigned long value)
|
||||||
: m_type(sizeof(long) == 8 ? Type::UnsignedInt64 : Type::UnsignedInt32)
|
: m_value(u64 { value })
|
||||||
{
|
{
|
||||||
if constexpr (sizeof(long) == 8)
|
|
||||||
m_value.as_u64 = value;
|
|
||||||
else
|
|
||||||
m_value.as_u32 = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue::JsonValue(long long value)
|
JsonValue::JsonValue(long long value)
|
||||||
: m_type(Type::Int64)
|
: m_value(i64 { value })
|
||||||
{
|
{
|
||||||
static_assert(sizeof(long long unsigned) == 8);
|
|
||||||
m_value.as_i64 = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue::JsonValue(long long unsigned value)
|
JsonValue::JsonValue(long long unsigned value)
|
||||||
: m_type(Type::UnsignedInt64)
|
: m_value(u64 { value })
|
||||||
{
|
{
|
||||||
static_assert(sizeof(long long unsigned) == 8);
|
|
||||||
m_value.as_u64 = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue::JsonValue(char const* cstring)
|
JsonValue::JsonValue(char const* cstring)
|
||||||
: JsonValue(ByteString(cstring))
|
: m_value(ByteString { cstring })
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(KERNEL)
|
|
||||||
JsonValue::JsonValue(double value)
|
JsonValue::JsonValue(double value)
|
||||||
: m_type(Type::Double)
|
: m_value(double { value })
|
||||||
{
|
{
|
||||||
m_value.as_double = value;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
JsonValue::JsonValue(ByteString const& value)
|
JsonValue::JsonValue(ByteString const& value)
|
||||||
|
: m_value(value)
|
||||||
{
|
{
|
||||||
m_type = Type::String;
|
|
||||||
m_value.as_string = const_cast<StringImpl*>(value.impl());
|
|
||||||
m_value.as_string->ref();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue::JsonValue(StringView value)
|
JsonValue::JsonValue(StringView value)
|
||||||
: JsonValue(value.to_byte_string())
|
: m_value(ByteString { value })
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue::JsonValue(JsonObject const& value)
|
JsonValue::JsonValue(JsonObject const& value)
|
||||||
: m_type(Type::Object)
|
: m_value(make<JsonObject>(value))
|
||||||
{
|
{
|
||||||
m_value.as_object = new JsonObject(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue::JsonValue(JsonArray const& value)
|
JsonValue::JsonValue(JsonArray const& value)
|
||||||
: m_type(Type::Array)
|
: m_value(make<JsonArray>(value))
|
||||||
{
|
{
|
||||||
m_value.as_array = new JsonArray(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue::JsonValue(JsonObject&& value)
|
JsonValue::JsonValue(JsonObject&& value)
|
||||||
: m_type(Type::Object)
|
: m_value(make<JsonObject>(value))
|
||||||
{
|
{
|
||||||
m_value.as_object = new JsonObject(move(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue::JsonValue(JsonArray&& value)
|
JsonValue::JsonValue(JsonArray&& value)
|
||||||
: m_type(Type::Array)
|
: m_value(make<JsonArray>(value))
|
||||||
{
|
{
|
||||||
m_value.as_array = new JsonArray(move(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonValue::clear()
|
|
||||||
{
|
|
||||||
switch (m_type) {
|
|
||||||
case Type::String:
|
|
||||||
m_value.as_string->unref();
|
|
||||||
break;
|
|
||||||
case Type::Object:
|
|
||||||
delete m_value.as_object;
|
|
||||||
break;
|
|
||||||
case Type::Array:
|
|
||||||
delete m_value.as_array;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
m_type = Type::Null;
|
|
||||||
m_value.as_string = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef KERNEL
|
|
||||||
ErrorOr<JsonValue> JsonValue::from_string(StringView input)
|
ErrorOr<JsonValue> JsonValue::from_string(StringView input)
|
||||||
{
|
{
|
||||||
return JsonParser(input).parse();
|
return JsonParser(input).parse();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
180
AK/JsonValue.h
180
AK/JsonValue.h
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||||
|
* Copyright (c) 2024, Dan Klishch <danilklishch@gmail.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -13,6 +14,7 @@
|
||||||
#include <AK/ByteString.h>
|
#include <AK/ByteString.h>
|
||||||
#include <AK/Forward.h>
|
#include <AK/Forward.h>
|
||||||
#include <AK/Optional.h>
|
#include <AK/Optional.h>
|
||||||
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
|
|
||||||
namespace AK {
|
namespace AK {
|
||||||
|
@ -21,12 +23,8 @@ class JsonValue {
|
||||||
public:
|
public:
|
||||||
enum class Type {
|
enum class Type {
|
||||||
Null,
|
Null,
|
||||||
Int32,
|
|
||||||
UnsignedInt32,
|
|
||||||
Int64,
|
|
||||||
UnsignedInt64,
|
|
||||||
Double,
|
|
||||||
Bool,
|
Bool,
|
||||||
|
Number,
|
||||||
String,
|
String,
|
||||||
Array,
|
Array,
|
||||||
Object,
|
Object,
|
||||||
|
@ -34,8 +32,8 @@ public:
|
||||||
|
|
||||||
static ErrorOr<JsonValue> from_string(StringView);
|
static ErrorOr<JsonValue> from_string(StringView);
|
||||||
|
|
||||||
JsonValue() = default;
|
JsonValue();
|
||||||
~JsonValue() { clear(); }
|
~JsonValue();
|
||||||
|
|
||||||
JsonValue(JsonValue const&);
|
JsonValue(JsonValue const&);
|
||||||
JsonValue(JsonValue&&);
|
JsonValue(JsonValue&&);
|
||||||
|
@ -58,8 +56,7 @@ public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
requires(SameAs<RemoveCVReference<T>, bool>)
|
requires(SameAs<RemoveCVReference<T>, bool>)
|
||||||
JsonValue(T value)
|
JsonValue(T value)
|
||||||
: m_type(Type::Bool)
|
: m_value { static_cast<bool>(value) }
|
||||||
, m_value { .as_bool = value }
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,9 +66,11 @@ public:
|
||||||
JsonValue(JsonArray&&);
|
JsonValue(JsonArray&&);
|
||||||
JsonValue(JsonObject&&);
|
JsonValue(JsonObject&&);
|
||||||
|
|
||||||
// FIXME: Implement these
|
JsonValue& operator=(JsonArray const&);
|
||||||
JsonValue& operator=(JsonArray&&) = delete;
|
JsonValue& operator=(JsonObject const&);
|
||||||
JsonValue& operator=(JsonObject&&) = delete;
|
|
||||||
|
JsonValue& operator=(JsonArray&&);
|
||||||
|
JsonValue& operator=(JsonObject&&);
|
||||||
|
|
||||||
template<typename Builder>
|
template<typename Builder>
|
||||||
typename Builder::OutputType serialized() const;
|
typename Builder::OutputType serialized() const;
|
||||||
|
@ -126,166 +125,117 @@ public:
|
||||||
|
|
||||||
bool as_bool() const
|
bool as_bool() const
|
||||||
{
|
{
|
||||||
VERIFY(is_bool());
|
return m_value.get<bool>();
|
||||||
return m_value.as_bool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteString as_string() const
|
ByteString as_string() const
|
||||||
{
|
{
|
||||||
VERIFY(is_string());
|
return m_value.get<ByteString>();
|
||||||
return *m_value.as_string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject& as_object()
|
JsonObject& as_object()
|
||||||
{
|
{
|
||||||
VERIFY(is_object());
|
return *m_value.get<NonnullOwnPtr<JsonObject>>();
|
||||||
return *m_value.as_object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject const& as_object() const
|
JsonObject const& as_object() const
|
||||||
{
|
{
|
||||||
VERIFY(is_object());
|
return *m_value.get<NonnullOwnPtr<JsonObject>>();
|
||||||
return *m_value.as_object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArray& as_array()
|
JsonArray& as_array()
|
||||||
{
|
{
|
||||||
VERIFY(is_array());
|
return *m_value.get<NonnullOwnPtr<JsonArray>>();
|
||||||
return *m_value.as_array;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArray const& as_array() const
|
JsonArray const& as_array() const
|
||||||
{
|
{
|
||||||
VERIFY(is_array());
|
return *m_value.get<NonnullOwnPtr<JsonArray>>();
|
||||||
return *m_value.as_array;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant<u64, i64, double> as_number() const
|
Variant<u64, i64, double> as_number() const
|
||||||
{
|
{
|
||||||
VERIFY(is_number());
|
return m_value.downcast<u64, i64, double>();
|
||||||
|
|
||||||
switch (m_type) {
|
|
||||||
case Type::Int32:
|
|
||||||
return static_cast<i64>(m_value.as_i32);
|
|
||||||
case Type::UnsignedInt32:
|
|
||||||
return static_cast<i64>(m_value.as_u32);
|
|
||||||
case Type::Int64:
|
|
||||||
return m_value.as_i64;
|
|
||||||
case Type::UnsignedInt64:
|
|
||||||
return m_value.as_u64;
|
|
||||||
case Type::Double:
|
|
||||||
return m_value.as_double;
|
|
||||||
default:
|
|
||||||
VERIFY_NOT_REACHED();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Type type() const
|
Type type() const
|
||||||
{
|
{
|
||||||
return m_type;
|
return m_value.visit(
|
||||||
|
[](Empty const&) { return Type::Null; },
|
||||||
|
[](bool const&) { return Type::Bool; },
|
||||||
|
[](Arithmetic auto const&) { return Type::Number; },
|
||||||
|
[](ByteString const&) { return Type::String; },
|
||||||
|
[](NonnullOwnPtr<JsonArray> const&) { return Type::Array; },
|
||||||
|
[](NonnullOwnPtr<JsonObject> const&) { return Type::Object; });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_null() const { return m_type == Type::Null; }
|
bool is_null() const { return m_value.has<Empty>(); }
|
||||||
bool is_bool() const { return m_type == Type::Bool; }
|
bool is_bool() const { return m_value.has<bool>(); }
|
||||||
bool is_string() const { return m_type == Type::String; }
|
bool is_string() const { return m_value.has<ByteString>(); }
|
||||||
bool is_array() const { return m_type == Type::Array; }
|
bool is_array() const { return m_value.has<NonnullOwnPtr<JsonArray>>(); }
|
||||||
bool is_object() const { return m_type == Type::Object; }
|
bool is_object() const { return m_value.has<NonnullOwnPtr<JsonObject>>(); }
|
||||||
bool is_number() const
|
bool is_number() const
|
||||||
{
|
{
|
||||||
switch (m_type) {
|
return m_value.visit(
|
||||||
case Type::Int32:
|
[](bool const&) { return false; },
|
||||||
case Type::UnsignedInt32:
|
[]<Arithmetic U>(U const&) { return true; },
|
||||||
case Type::Int64:
|
[](auto const&) { return false; });
|
||||||
case Type::UnsignedInt64:
|
|
||||||
case Type::Double:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Optional<T> get_number_with_precision_loss() const
|
Optional<T> get_number_with_precision_loss() const
|
||||||
{
|
{
|
||||||
switch (m_type) {
|
return m_value.visit(
|
||||||
case Type::Double:
|
[](bool const&) { return Optional<T> {}; },
|
||||||
return static_cast<T>(m_value.as_double);
|
[]<Arithmetic U>(U const& value) { return Optional<T> { static_cast<T>(value) }; },
|
||||||
case Type::Int32:
|
[](auto const&) { return Optional<T> {}; });
|
||||||
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:
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Integral T>
|
template<Integral T>
|
||||||
bool is_integer() const
|
bool is_integer() const
|
||||||
{
|
{
|
||||||
switch (m_type) {
|
return get_integer<T>().has_value();
|
||||||
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>
|
template<Integral T>
|
||||||
T as_integer() const
|
T as_integer() const
|
||||||
{
|
{
|
||||||
VERIFY(is_integer<T>());
|
return get_integer<T>().value();
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Integral T>
|
template<Integral T>
|
||||||
Optional<T> get_integer() const
|
Optional<T> get_integer() const
|
||||||
{
|
{
|
||||||
if (!is_integer<T>())
|
return m_value.visit(
|
||||||
return {};
|
[](bool const&) { return Optional<T> {}; },
|
||||||
return as_integer<T>();
|
[]<Arithmetic U>(U const& value) -> Optional<T> {
|
||||||
|
if constexpr (Integral<U>) {
|
||||||
|
if (!is_within_range<T>(value))
|
||||||
|
return {};
|
||||||
|
return static_cast<T>(value);
|
||||||
|
} else {
|
||||||
|
// FIXME: Make is_within_range work with floating point numbers.
|
||||||
|
if (static_cast<U>(static_cast<T>(value)) != value)
|
||||||
|
return {};
|
||||||
|
return static_cast<T>(value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](auto const&) { return Optional<T> {}; });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool equals(JsonValue const& other) const;
|
bool equals(JsonValue const& other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void clear();
|
Variant<
|
||||||
void copy_from(JsonValue const&);
|
Empty,
|
||||||
|
bool,
|
||||||
Type m_type { Type::Null };
|
i64,
|
||||||
|
u64,
|
||||||
union {
|
double,
|
||||||
StringImpl* as_string { nullptr };
|
ByteString,
|
||||||
JsonArray* as_array;
|
NonnullOwnPtr<JsonArray>,
|
||||||
JsonObject* as_object;
|
NonnullOwnPtr<JsonObject>>
|
||||||
double as_double;
|
m_value;
|
||||||
i32 as_i32;
|
|
||||||
u32 as_u32;
|
|
||||||
i64 as_i64;
|
|
||||||
u64 as_u64;
|
|
||||||
bool as_bool;
|
|
||||||
} m_value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue