Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <AK/Function.h>
28#include <AK/JsonArray.h>
29#include <AK/JsonObject.h>
30#include <AK/JsonParser.h>
31#include <AK/JsonValue.h>
32#include <AK/StringBuilder.h>
33
34namespace AK {
35
36JsonValue::JsonValue(Type type)
37 : m_type(type)
38{
39}
40
41JsonValue::JsonValue(const JsonValue& other)
42{
43 copy_from(other);
44}
45
46JsonValue& JsonValue::operator=(const JsonValue& other)
47{
48 if (this != &other) {
49 clear();
50 copy_from(other);
51 }
52 return *this;
53}
54
55void JsonValue::copy_from(const JsonValue& other)
56{
57 m_type = other.m_type;
58 switch (m_type) {
59 case Type::String:
60 ASSERT(!m_value.as_string);
61 m_value.as_string = other.m_value.as_string;
62 m_value.as_string->ref();
63 break;
64 case Type::Object:
65 m_value.as_object = new JsonObject(*other.m_value.as_object);
66 break;
67 case Type::Array:
68 m_value.as_array = new JsonArray(*other.m_value.as_array);
69 break;
70 default:
71 m_value.as_string = other.m_value.as_string;
72 break;
73 }
74}
75
76JsonValue::JsonValue(JsonValue&& other)
77{
78 m_type = exchange(other.m_type, Type::Undefined);
79 m_value.as_string = exchange(other.m_value.as_string, nullptr);
80}
81
82JsonValue& JsonValue::operator=(JsonValue&& other)
83{
84 if (this != &other) {
85 clear();
86 m_type = exchange(other.m_type, Type::Undefined);
87 m_value.as_string = exchange(other.m_value.as_string, nullptr);
88 }
89 return *this;
90}
91
92bool JsonValue::equals(const JsonValue& other) const
93{
94 if (is_null() && other.is_null())
95 return true;
96
97 if (is_bool() && other.is_bool() && as_bool() == other.as_bool())
98 return true;
99
100 if (is_string() && other.is_string() && as_string() == other.as_string())
101 return true;
102
103#if !defined(KERNEL) && !defined(BOOTSTRAPPER)
104 if (is_number() && other.is_number() && to_number<double>() == other.to_number<double>()) {
105 return true;
106 }
107#else
108 if (is_number() && other.is_number() && to_number<i64>() == other.to_number<i64>()) {
109 return true;
110 }
111#endif
112
113 if (is_array() && other.is_array() && as_array().size() == other.as_array().size()) {
114 bool result = true;
115 for (int i = 0; i < as_array().size(); ++i) {
116 result &= as_array().at(i).equals(other.as_array().at(i));
117 }
118 return result;
119 }
120
121 if (is_object() && other.is_object() && as_object().size() == other.as_object().size()) {
122 bool result = true;
123 as_object().for_each_member([&](auto& key, auto& value) {
124 result &= value.equals(other.as_object().get(key));
125 });
126 return result;
127 }
128
129 return false;
130}
131
132JsonValue::JsonValue(i32 value)
133 : m_type(Type::Int32)
134{
135 m_value.as_i32 = value;
136}
137
138JsonValue::JsonValue(u32 value)
139 : m_type(Type::UnsignedInt32)
140{
141 m_value.as_u32 = value;
142}
143
144JsonValue::JsonValue(i64 value)
145 : m_type(Type::Int64)
146{
147 m_value.as_i64 = value;
148}
149
150JsonValue::JsonValue(u64 value)
151 : m_type(Type::UnsignedInt64)
152{
153 m_value.as_u64 = value;
154}
155
156JsonValue::JsonValue(const char* cstring)
157 : JsonValue(String(cstring))
158{
159}
160
161#if !defined(BOOTSTRAPPER) && !defined(KERNEL)
162JsonValue::JsonValue(double value)
163 : m_type(Type::Double)
164{
165 m_value.as_double = value;
166}
167#endif
168
169JsonValue::JsonValue(bool value)
170 : m_type(Type::Bool)
171{
172 m_value.as_bool = value;
173}
174
175JsonValue::JsonValue(const String& 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(const IPv4Address& value)
187 : JsonValue(value.to_string())
188{
189}
190
191JsonValue::JsonValue(const JsonObject& value)
192 : m_type(Type::Object)
193{
194 m_value.as_object = new JsonObject(value);
195}
196
197JsonValue::JsonValue(const JsonArray& 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::Undefined;
231 m_value.as_string = nullptr;
232}
233
234JsonValue JsonValue::from_string(const StringView& input)
235{
236 return JsonParser(input).parse();
237}
238
239}