/* * Copyright (c) 2018-2020, Andreas Kling * Copyright (c) 2024, Dan Klishch * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include namespace AK { namespace { using JsonValueStorage = Variant< Empty, bool, i64, u64, double, ByteString, NonnullOwnPtr, NonnullOwnPtr>; static ErrorOr clone(JsonValueStorage const& other) { return other.visit( [](NonnullOwnPtr const& value) -> ErrorOr { return TRY(try_make(*value)); }, [](NonnullOwnPtr const& value) -> ErrorOr { return TRY(try_make(*value)); }, [](auto const& value) -> ErrorOr { 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))) { } JsonValue& JsonValue::operator=(JsonValue const& other) { if (this != &other) m_value = MUST(clone(other.m_value)); return *this; } JsonValue& JsonValue::operator=(JsonArray const& other) { return *this = JsonValue(other); } JsonValue& JsonValue::operator=(JsonArray&& other) { return *this = JsonValue(other); } JsonValue& JsonValue::operator=(JsonObject const& other) { return *this = JsonValue(other); } JsonValue& JsonValue::operator=(JsonObject&& other) { return *this = JsonValue(other); } bool JsonValue::equals(JsonValue const& other) const { if (is_null() && other.is_null()) return true; if (is_bool() && other.is_bool() && as_bool() == other.as_bool()) return true; if (is_string() && other.is_string() && as_string() == other.as_string()) return true; if (is_number() && other.is_number()) { auto normalize = [](Variant representation, bool& is_negative) { return representation.visit( [&](u64& value) -> Variant { is_negative = false; return value; }, [&](i64& value) -> Variant { is_negative = value < 0; return static_cast(abs(value)); }, [&](double& value) -> Variant { is_negative = value < 0; value = abs(value); if (static_cast(static_cast(value)) == value) return static_cast(value); return value; }); }; bool is_this_negative; auto normalized_this = normalize(as_number(), is_this_negative); bool is_that_negative; auto normalized_that = normalize(other.as_number(), is_that_negative); return is_this_negative == is_that_negative && normalized_this == normalized_that; } if (is_array() && other.is_array() && as_array().size() == other.as_array().size()) { bool result = true; for (size_t i = 0; i < as_array().size(); ++i) { result &= as_array().at(i).equals(other.as_array().at(i)); } return result; } if (is_object() && other.is_object() && as_object().size() == other.as_object().size()) { bool result = true; as_object().for_each_member([&](auto& key, auto& value) { auto other_value = other.as_object().get(key); if (other_value.has_value()) result &= value.equals(*other_value); else result = false; }); return result; } return false; } JsonValue::JsonValue(int value) : m_value(i64 { value }) { } JsonValue::JsonValue(unsigned value) : m_value(i64 { value }) { } JsonValue::JsonValue(long value) : m_value(i64 { value }) { } JsonValue::JsonValue(unsigned long value) : m_value(u64 { value }) { } JsonValue::JsonValue(long long value) : m_value(i64 { value }) { } JsonValue::JsonValue(long long unsigned value) : m_value(u64 { value }) { } JsonValue::JsonValue(char const* cstring) : m_value(ByteString { cstring }) { } JsonValue::JsonValue(double value) : m_value(double { value }) { } JsonValue::JsonValue(ByteString const& value) : m_value(value) { } JsonValue::JsonValue(StringView value) : m_value(ByteString { value }) { } JsonValue::JsonValue(JsonObject const& value) : m_value(make(value)) { } JsonValue::JsonValue(JsonArray const& value) : m_value(make(value)) { } JsonValue::JsonValue(JsonObject&& value) : m_value(make(value)) { } JsonValue::JsonValue(JsonArray&& value) : m_value(make(value)) { } ErrorOr JsonValue::from_string(StringView input) { return JsonParser(input).parse(); } }