Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/JsonArray.h>
8#include <AK/JsonObject.h>
9#include <AK/JsonValue.h>
10#include <AK/StringView.h>
11
12#ifndef KERNEL
13# include <AK/JsonParser.h>
14#endif
15
16namespace AK {
17
18JsonValue::JsonValue(Type type)
19 : m_type(type)
20{
21}
22
23JsonValue::JsonValue(JsonValue const& other)
24{
25 copy_from(other);
26}
27
28JsonValue& JsonValue::operator=(JsonValue const& other)
29{
30 if (this != &other) {
31 clear();
32 copy_from(other);
33 }
34 return *this;
35}
36
37void JsonValue::copy_from(JsonValue const& other)
38{
39 m_type = other.m_type;
40 switch (m_type) {
41 case Type::String:
42 VERIFY(!m_value.as_string);
43 m_value.as_string = other.m_value.as_string;
44 m_value.as_string->ref();
45 break;
46 case Type::Object:
47 m_value.as_object = new JsonObject(*other.m_value.as_object);
48 break;
49 case Type::Array:
50 m_value.as_array = new JsonArray(*other.m_value.as_array);
51 break;
52 default:
53 m_value.as_u64 = other.m_value.as_u64;
54 break;
55 }
56}
57
58JsonValue::JsonValue(JsonValue&& other)
59{
60 m_type = exchange(other.m_type, Type::Null);
61 m_value.as_u64 = exchange(other.m_value.as_u64, 0);
62}
63
64JsonValue& JsonValue::operator=(JsonValue&& other)
65{
66 if (this != &other) {
67 clear();
68 m_type = exchange(other.m_type, Type::Null);
69 m_value.as_u64 = exchange(other.m_value.as_u64, 0);
70 }
71 return *this;
72}
73
74bool JsonValue::equals(JsonValue const& other) const
75{
76 if (is_null() && other.is_null())
77 return true;
78
79 if (is_bool() && other.is_bool() && as_bool() == other.as_bool())
80 return true;
81
82 if (is_string() && other.is_string() && as_string() == other.as_string())
83 return true;
84
85#if !defined(KERNEL)
86 if (is_number() && other.is_number() && to_number<double>() == other.to_number<double>()) {
87 return true;
88 }
89#else
90 if (is_number() && other.is_number() && to_number<i64>() == other.to_number<i64>()) {
91 return true;
92 }
93#endif
94
95 if (is_array() && other.is_array() && as_array().size() == other.as_array().size()) {
96 bool result = true;
97 for (size_t i = 0; i < as_array().size(); ++i) {
98 result &= as_array().at(i).equals(other.as_array().at(i));
99 }
100 return result;
101 }
102
103 if (is_object() && other.is_object() && as_object().size() == other.as_object().size()) {
104 bool result = true;
105 as_object().for_each_member([&](auto& key, auto& value) {
106 auto other_value = other.as_object().get(key);
107 if (other_value.has_value())
108 result &= value.equals(*other_value);
109 else
110 result = false;
111 });
112 return result;
113 }
114
115 return false;
116}
117
118JsonValue::JsonValue(int value)
119 : m_type(Type::Int32)
120{
121 m_value.as_i32 = value;
122}
123
124JsonValue::JsonValue(unsigned value)
125 : m_type(Type::UnsignedInt32)
126{
127 m_value.as_u32 = value;
128}
129
130JsonValue::JsonValue(long value)
131 : m_type(sizeof(long) == 8 ? Type::Int64 : Type::Int32)
132{
133 if constexpr (sizeof(long) == 8)
134 m_value.as_i64 = value;
135 else
136 m_value.as_i32 = value;
137}
138
139JsonValue::JsonValue(unsigned long value)
140 : m_type(sizeof(long) == 8 ? Type::UnsignedInt64 : Type::UnsignedInt32)
141{
142 if constexpr (sizeof(long) == 8)
143 m_value.as_u64 = value;
144 else
145 m_value.as_u32 = value;
146}
147
148JsonValue::JsonValue(long long value)
149 : m_type(Type::Int64)
150{
151 static_assert(sizeof(long long unsigned) == 8);
152 m_value.as_i64 = value;
153}
154
155JsonValue::JsonValue(long long unsigned value)
156 : m_type(Type::UnsignedInt64)
157{
158 static_assert(sizeof(long long unsigned) == 8);
159 m_value.as_u64 = value;
160}
161
162JsonValue::JsonValue(char const* cstring)
163 : JsonValue(DeprecatedString(cstring))
164{
165}
166
167#if !defined(KERNEL)
168JsonValue::JsonValue(double value)
169 : m_type(Type::Double)
170{
171 m_value.as_double = value;
172}
173#endif
174
175JsonValue::JsonValue(DeprecatedString const& value)
176{
177 if (value.is_null()) {
178 m_type = Type::Null;
179 } else {
180 m_type = Type::String;
181 m_value.as_string = const_cast<StringImpl*>(value.impl());
182 m_value.as_string->ref();
183 }
184}
185
186JsonValue::JsonValue(StringView value)
187 : JsonValue(value.to_deprecated_string())
188{
189}
190
191JsonValue::JsonValue(JsonObject const& value)
192 : m_type(Type::Object)
193{
194 m_value.as_object = new JsonObject(value);
195}
196
197JsonValue::JsonValue(JsonArray const& value)
198 : m_type(Type::Array)
199{
200 m_value.as_array = new JsonArray(value);
201}
202
203JsonValue::JsonValue(JsonObject&& value)
204 : m_type(Type::Object)
205{
206 m_value.as_object = new JsonObject(move(value));
207}
208
209JsonValue::JsonValue(JsonArray&& value)
210 : m_type(Type::Array)
211{
212 m_value.as_array = new JsonArray(move(value));
213}
214
215void JsonValue::clear()
216{
217 switch (m_type) {
218 case Type::String:
219 m_value.as_string->unref();
220 break;
221 case Type::Object:
222 delete m_value.as_object;
223 break;
224 case Type::Array:
225 delete m_value.as_array;
226 break;
227 default:
228 break;
229 }
230 m_type = Type::Null;
231 m_value.as_string = nullptr;
232}
233
234#ifndef KERNEL
235ErrorOr<JsonValue> JsonValue::from_string(StringView input)
236{
237 return JsonParser(input).parse();
238}
239#endif
240
241}