2020-01-18 08:38:21 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
|
|
*
|
2021-04-22 08:24:48 +00:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-01-18 08:38:21 +00:00
|
|
|
*/
|
|
|
|
|
2019-06-17 17:47:35 +00:00
|
|
|
#pragma once
|
|
|
|
|
2020-02-14 20:41:10 +00:00
|
|
|
#include <AK/Forward.h>
|
2019-07-08 11:03:23 +00:00
|
|
|
#include <AK/Optional.h>
|
2019-08-07 19:28:07 +00:00
|
|
|
#include <AK/StringBuilder.h>
|
2019-06-17 17:47:35 +00:00
|
|
|
|
2022-02-15 22:22:56 +00:00
|
|
|
#ifndef KERNEL
|
2022-12-04 18:02:33 +00:00
|
|
|
# include <AK/DeprecatedString.h>
|
2022-02-15 22:22:56 +00:00
|
|
|
#endif
|
|
|
|
|
2019-06-17 19:34:12 +00:00
|
|
|
namespace AK {
|
|
|
|
|
2019-06-17 17:47:35 +00:00
|
|
|
class JsonValue {
|
|
|
|
public:
|
|
|
|
enum class Type {
|
|
|
|
Null,
|
2019-10-29 15:36:50 +00:00
|
|
|
Int32,
|
|
|
|
UnsignedInt32,
|
|
|
|
Int64,
|
|
|
|
UnsignedInt64,
|
2020-05-16 10:00:04 +00:00
|
|
|
#if !defined(KERNEL)
|
2019-06-17 17:47:35 +00:00
|
|
|
Double,
|
2019-06-29 07:04:45 +00:00
|
|
|
#endif
|
2019-06-17 17:47:35 +00:00
|
|
|
Bool,
|
|
|
|
String,
|
|
|
|
Array,
|
|
|
|
Object,
|
|
|
|
};
|
|
|
|
|
2021-11-15 00:46:51 +00:00
|
|
|
static ErrorOr<JsonValue> from_string(StringView);
|
2019-06-24 09:25:10 +00:00
|
|
|
|
2022-11-07 21:30:55 +00:00
|
|
|
JsonValue() = default;
|
|
|
|
explicit JsonValue(Type);
|
2019-06-17 17:47:35 +00:00
|
|
|
~JsonValue() { clear(); }
|
|
|
|
|
2022-04-01 17:58:27 +00:00
|
|
|
JsonValue(JsonValue const&);
|
2019-06-17 17:47:35 +00:00
|
|
|
JsonValue(JsonValue&&);
|
|
|
|
|
2022-04-01 17:58:27 +00:00
|
|
|
JsonValue& operator=(JsonValue const&);
|
2019-06-17 17:47:35 +00:00
|
|
|
JsonValue& operator=(JsonValue&&);
|
|
|
|
|
2020-05-22 11:57:23 +00:00
|
|
|
JsonValue(int);
|
|
|
|
JsonValue(unsigned);
|
|
|
|
JsonValue(long);
|
|
|
|
JsonValue(long unsigned);
|
|
|
|
JsonValue(long long);
|
|
|
|
JsonValue(long long unsigned);
|
2019-10-29 15:36:50 +00:00
|
|
|
|
2020-05-16 10:00:04 +00:00
|
|
|
#if !defined(KERNEL)
|
2019-06-17 17:47:35 +00:00
|
|
|
JsonValue(double);
|
2019-06-29 07:04:45 +00:00
|
|
|
#endif
|
2022-04-01 17:58:27 +00:00
|
|
|
JsonValue(char const*);
|
2022-02-15 22:22:56 +00:00
|
|
|
#ifndef KERNEL
|
2022-12-04 18:02:33 +00:00
|
|
|
JsonValue(DeprecatedString const&);
|
2022-02-15 22:22:56 +00:00
|
|
|
#endif
|
2022-01-27 12:01:10 +00:00
|
|
|
JsonValue(StringView);
|
2022-12-08 16:03:39 +00:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
requires(SameAs<RemoveCVReference<T>, bool>)
|
|
|
|
JsonValue(T value)
|
|
|
|
: m_type(Type::Bool)
|
|
|
|
, m_value { .as_bool = value }
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2022-04-01 17:58:27 +00:00
|
|
|
JsonValue(JsonArray const&);
|
|
|
|
JsonValue(JsonObject const&);
|
2019-06-17 17:47:35 +00:00
|
|
|
|
2019-08-04 09:46:31 +00:00
|
|
|
JsonValue(JsonArray&&);
|
|
|
|
JsonValue(JsonObject&&);
|
|
|
|
|
|
|
|
// FIXME: Implement these
|
|
|
|
JsonValue& operator=(JsonArray&&) = delete;
|
|
|
|
JsonValue& operator=(JsonObject&&) = delete;
|
|
|
|
|
2019-08-07 19:28:07 +00:00
|
|
|
template<typename Builder>
|
|
|
|
typename Builder::OutputType serialized() const;
|
|
|
|
template<typename Builder>
|
|
|
|
void serialize(Builder&) const;
|
2019-06-17 17:47:35 +00:00
|
|
|
|
2022-02-15 22:22:56 +00:00
|
|
|
#ifndef KERNEL
|
2022-12-04 18:02:33 +00:00
|
|
|
DeprecatedString as_string_or(DeprecatedString const& alternative) const
|
2019-08-07 20:03:25 +00:00
|
|
|
{
|
|
|
|
if (is_string())
|
|
|
|
return as_string();
|
|
|
|
return alternative;
|
|
|
|
}
|
|
|
|
|
2022-12-06 01:12:49 +00:00
|
|
|
DeprecatedString to_deprecated_string() const
|
2019-06-24 12:25:45 +00:00
|
|
|
{
|
|
|
|
if (is_string())
|
|
|
|
return as_string();
|
2019-08-07 19:28:07 +00:00
|
|
|
return serialized<StringBuilder>();
|
2019-06-24 12:25:45 +00:00
|
|
|
}
|
2022-02-15 22:22:56 +00:00
|
|
|
#endif
|
2019-06-24 12:25:45 +00:00
|
|
|
|
2022-02-15 22:22:56 +00:00
|
|
|
int to_int(int default_value = 0) const
|
|
|
|
{
|
|
|
|
return to_i32(default_value);
|
|
|
|
}
|
2019-10-29 15:36:50 +00:00
|
|
|
i32 to_i32(i32 default_value = 0) const { return to_number<i32>(default_value); }
|
2021-03-17 17:19:30 +00:00
|
|
|
i64 to_i64(i64 default_value = 0) const { return to_number<i64>(default_value); }
|
2019-10-29 15:36:50 +00:00
|
|
|
|
|
|
|
unsigned to_uint(unsigned default_value = 0) const { return to_u32(default_value); }
|
|
|
|
u32 to_u32(u32 default_value = 0) const { return to_number<u32>(default_value); }
|
2021-03-17 17:19:30 +00:00
|
|
|
u64 to_u64(u64 default_value = 0) const { return to_number<u64>(default_value); }
|
2022-02-27 00:31:36 +00:00
|
|
|
#if !defined(KERNEL)
|
2022-03-06 12:18:26 +00:00
|
|
|
float to_float(float default_value = 0) const
|
2022-02-27 00:31:36 +00:00
|
|
|
{
|
2022-03-06 12:18:26 +00:00
|
|
|
return to_number<float>(default_value);
|
2022-02-27 00:31:36 +00:00
|
|
|
}
|
2022-03-06 12:18:26 +00:00
|
|
|
double to_double(double default_value = 0) const { return to_number<double>(default_value); }
|
2022-02-27 00:31:36 +00:00
|
|
|
#endif
|
|
|
|
|
2021-07-21 17:57:05 +00:00
|
|
|
FlatPtr to_addr(FlatPtr default_value = 0) const
|
|
|
|
{
|
|
|
|
#ifdef __LP64__
|
|
|
|
return to_u64(default_value);
|
|
|
|
#else
|
|
|
|
return to_u32(default_value);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-10-29 15:36:50 +00:00
|
|
|
bool to_bool(bool default_value = false) const
|
2019-07-18 06:18:39 +00:00
|
|
|
{
|
2019-10-29 15:36:50 +00:00
|
|
|
if (!is_bool())
|
2019-07-18 06:18:39 +00:00
|
|
|
return default_value;
|
2019-10-29 15:36:50 +00:00
|
|
|
return as_bool();
|
2019-07-18 06:18:39 +00:00
|
|
|
}
|
|
|
|
|
2019-12-12 20:17:26 +00:00
|
|
|
i32 as_i32() const
|
2019-07-18 06:18:39 +00:00
|
|
|
{
|
2021-02-23 19:42:32 +00:00
|
|
|
VERIFY(is_i32());
|
2019-10-29 15:36:50 +00:00
|
|
|
return m_value.as_i32;
|
2019-07-18 06:18:39 +00:00
|
|
|
}
|
|
|
|
|
2019-12-12 20:17:26 +00:00
|
|
|
u32 as_u32() const
|
2019-07-08 12:06:03 +00:00
|
|
|
{
|
2021-02-23 19:42:32 +00:00
|
|
|
VERIFY(is_u32());
|
2019-10-29 15:36:50 +00:00
|
|
|
return m_value.as_u32;
|
2019-07-08 12:06:03 +00:00
|
|
|
}
|
|
|
|
|
2019-12-12 20:17:26 +00:00
|
|
|
i64 as_i64() const
|
2019-06-29 10:04:36 +00:00
|
|
|
{
|
2021-02-23 19:42:32 +00:00
|
|
|
VERIFY(is_i64());
|
2019-10-29 15:36:50 +00:00
|
|
|
return m_value.as_i64;
|
2019-06-29 10:04:36 +00:00
|
|
|
}
|
|
|
|
|
2019-12-12 20:17:26 +00:00
|
|
|
u64 as_u64() const
|
2019-06-29 10:04:36 +00:00
|
|
|
{
|
2021-02-23 19:42:32 +00:00
|
|
|
VERIFY(is_u64());
|
2019-10-29 15:36:50 +00:00
|
|
|
return m_value.as_u64;
|
2019-06-29 10:04:36 +00:00
|
|
|
}
|
|
|
|
|
2021-12-15 13:47:26 +00:00
|
|
|
bool as_bool() const
|
2019-06-29 10:04:36 +00:00
|
|
|
{
|
2021-02-23 19:42:32 +00:00
|
|
|
VERIFY(is_bool());
|
2019-06-29 10:04:36 +00:00
|
|
|
return m_value.as_bool;
|
|
|
|
}
|
|
|
|
|
2022-02-15 22:22:56 +00:00
|
|
|
#ifndef KERNEL
|
2022-12-04 18:02:33 +00:00
|
|
|
DeprecatedString as_string() const
|
2019-06-18 06:55:58 +00:00
|
|
|
{
|
2021-02-23 19:42:32 +00:00
|
|
|
VERIFY(is_string());
|
2019-06-24 10:03:31 +00:00
|
|
|
return *m_value.as_string;
|
|
|
|
}
|
2022-02-15 22:22:56 +00:00
|
|
|
#endif
|
2019-06-24 10:03:31 +00:00
|
|
|
|
2022-11-17 21:17:13 +00:00
|
|
|
JsonObject& as_object()
|
|
|
|
{
|
|
|
|
VERIFY(is_object());
|
|
|
|
return *m_value.as_object;
|
|
|
|
}
|
|
|
|
|
2022-04-01 17:58:27 +00:00
|
|
|
JsonObject const& as_object() const
|
2019-06-24 10:03:31 +00:00
|
|
|
{
|
2021-02-23 19:42:32 +00:00
|
|
|
VERIFY(is_object());
|
2019-06-24 10:03:31 +00:00
|
|
|
return *m_value.as_object;
|
|
|
|
}
|
|
|
|
|
2022-11-17 21:17:13 +00:00
|
|
|
JsonArray& as_array()
|
|
|
|
{
|
|
|
|
VERIFY(is_array());
|
|
|
|
return *m_value.as_array;
|
|
|
|
}
|
|
|
|
|
2022-04-01 17:58:27 +00:00
|
|
|
JsonArray const& as_array() const
|
2019-06-24 10:03:31 +00:00
|
|
|
{
|
2021-02-23 19:42:32 +00:00
|
|
|
VERIFY(is_array());
|
2019-06-24 10:03:31 +00:00
|
|
|
return *m_value.as_array;
|
2019-06-18 06:55:58 +00:00
|
|
|
}
|
|
|
|
|
2020-05-16 10:00:04 +00:00
|
|
|
#if !defined(KERNEL)
|
2019-07-18 06:18:39 +00:00
|
|
|
double as_double() const
|
|
|
|
{
|
2021-02-23 19:42:32 +00:00
|
|
|
VERIFY(is_double());
|
2019-07-18 06:18:39 +00:00
|
|
|
return m_value.as_double;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-08-07 19:28:07 +00:00
|
|
|
Type type() const
|
|
|
|
{
|
|
|
|
return m_type;
|
|
|
|
}
|
2019-06-19 11:08:07 +00:00
|
|
|
|
|
|
|
bool is_null() const { return m_type == Type::Null; }
|
2019-06-29 10:04:36 +00:00
|
|
|
bool is_bool() const { return m_type == Type::Bool; }
|
2019-06-19 11:08:07 +00:00
|
|
|
bool is_string() const { return m_type == Type::String; }
|
2019-10-29 15:36:50 +00:00
|
|
|
bool is_i32() const { return m_type == Type::Int32; }
|
|
|
|
bool is_u32() const { return m_type == Type::UnsignedInt32; }
|
|
|
|
bool is_i64() const { return m_type == Type::Int64; }
|
|
|
|
bool is_u64() const { return m_type == Type::UnsignedInt64; }
|
2020-05-16 10:00:04 +00:00
|
|
|
#if !defined(KERNEL)
|
2019-08-07 19:28:07 +00:00
|
|
|
bool is_double() const
|
|
|
|
{
|
|
|
|
return m_type == Type::Double;
|
|
|
|
}
|
2019-06-29 07:04:45 +00:00
|
|
|
#endif
|
2019-08-07 19:28:07 +00:00
|
|
|
bool is_array() const
|
|
|
|
{
|
|
|
|
return m_type == Type::Array;
|
|
|
|
}
|
2019-06-19 11:08:07 +00:00
|
|
|
bool is_object() const { return m_type == Type::Object; }
|
2019-06-29 07:04:45 +00:00
|
|
|
bool is_number() const
|
|
|
|
{
|
2019-10-29 15:36:50 +00:00
|
|
|
switch (m_type) {
|
|
|
|
case Type::Int32:
|
|
|
|
case Type::UnsignedInt32:
|
|
|
|
case Type::Int64:
|
|
|
|
case Type::UnsignedInt64:
|
2020-05-16 10:00:04 +00:00
|
|
|
#if !defined(KERNEL)
|
2019-10-29 15:36:50 +00:00
|
|
|
case Type::Double:
|
2019-06-29 07:04:45 +00:00
|
|
|
#endif
|
2019-10-29 15:36:50 +00:00
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2019-06-29 07:04:45 +00:00
|
|
|
}
|
2019-06-19 11:08:07 +00:00
|
|
|
|
2019-10-29 15:36:50 +00:00
|
|
|
template<typename T>
|
|
|
|
T to_number(T default_value = 0) const
|
2019-06-19 11:08:07 +00:00
|
|
|
{
|
2020-05-16 10:00:04 +00:00
|
|
|
#if !defined(KERNEL)
|
2019-10-29 15:36:50 +00:00
|
|
|
if (is_double())
|
|
|
|
return (T)as_double();
|
2019-06-29 07:04:45 +00:00
|
|
|
#endif
|
2019-10-29 15:36:50 +00:00
|
|
|
if (type() == Type::Int32)
|
|
|
|
return (T)as_i32();
|
|
|
|
if (type() == Type::UnsignedInt32)
|
|
|
|
return (T)as_u32();
|
|
|
|
if (type() == Type::Int64)
|
|
|
|
return (T)as_i64();
|
|
|
|
if (type() == Type::UnsignedInt64)
|
|
|
|
return (T)as_u64();
|
|
|
|
return default_value;
|
2019-06-19 11:08:07 +00:00
|
|
|
}
|
|
|
|
|
2022-12-21 16:07:14 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-01 17:58:27 +00:00
|
|
|
bool equals(JsonValue const& other) const;
|
2020-03-31 18:44:34 +00:00
|
|
|
|
2019-06-17 17:47:35 +00:00
|
|
|
private:
|
|
|
|
void clear();
|
2022-04-01 17:58:27 +00:00
|
|
|
void copy_from(JsonValue const&);
|
2019-06-17 17:47:35 +00:00
|
|
|
|
2020-06-11 04:40:27 +00:00
|
|
|
Type m_type { Type::Null };
|
2019-06-17 17:47:35 +00:00
|
|
|
|
|
|
|
union {
|
2022-02-15 22:22:56 +00:00
|
|
|
#ifndef KERNEL
|
2019-06-17 17:47:35 +00:00
|
|
|
StringImpl* as_string { nullptr };
|
2022-02-15 22:22:56 +00:00
|
|
|
#endif
|
2019-06-17 17:47:35 +00:00
|
|
|
JsonArray* as_array;
|
|
|
|
JsonObject* as_object;
|
2020-05-16 10:00:04 +00:00
|
|
|
#if !defined(KERNEL)
|
2019-06-17 17:47:35 +00:00
|
|
|
double as_double;
|
2019-06-29 07:04:45 +00:00
|
|
|
#endif
|
2019-10-29 15:36:50 +00:00
|
|
|
i32 as_i32;
|
|
|
|
u32 as_u32;
|
|
|
|
i64 as_i64;
|
|
|
|
u64 as_u64;
|
2019-06-17 17:47:35 +00:00
|
|
|
bool as_bool;
|
|
|
|
} m_value;
|
|
|
|
};
|
2019-06-17 19:34:12 +00:00
|
|
|
|
2022-02-15 22:22:56 +00:00
|
|
|
#ifndef KERNEL
|
2020-10-13 16:34:27 +00:00
|
|
|
template<>
|
|
|
|
struct Formatter<JsonValue> : Formatter<StringView> {
|
2021-11-16 00:15:21 +00:00
|
|
|
ErrorOr<void> format(FormatBuilder& builder, JsonValue const& value)
|
2020-10-13 16:34:27 +00:00
|
|
|
{
|
2022-12-06 01:12:49 +00:00
|
|
|
return Formatter<StringView>::format(builder, value.to_deprecated_string());
|
2020-10-13 16:34:27 +00:00
|
|
|
}
|
|
|
|
};
|
2022-02-15 22:22:56 +00:00
|
|
|
#endif
|
2020-10-13 16:34:27 +00:00
|
|
|
|
2019-06-17 19:34:12 +00:00
|
|
|
}
|
|
|
|
|
2022-11-26 11:18:30 +00:00
|
|
|
#if USING_AK_GLOBALLY
|
2019-06-17 19:34:12 +00:00
|
|
|
using AK::JsonValue;
|
2022-11-26 11:18:30 +00:00
|
|
|
#endif
|