Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmcppdap/src/jsoncpp_json_serializer.cpp
3153 views
1
// Copyright 2023 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include "jsoncpp_json_serializer.h"
16
17
#include "null_json_serializer.h"
18
19
#include <cm3p/json/json.h>
20
#include <cstdlib>
21
#include <memory>
22
23
namespace dap {
24
namespace json {
25
26
JsonCppDeserializer::JsonCppDeserializer(const std::string& str)
27
: json(new Json::Value(JsonCppDeserializer::parse(str))), ownsJson(true) {}
28
29
JsonCppDeserializer::JsonCppDeserializer(const Json::Value* json)
30
: json(json), ownsJson(false) {}
31
32
JsonCppDeserializer::~JsonCppDeserializer() {
33
if (ownsJson) {
34
delete json;
35
}
36
}
37
38
bool JsonCppDeserializer::deserialize(dap::boolean* v) const {
39
if (!json->isBool()) {
40
return false;
41
}
42
*v = json->asBool();
43
return true;
44
}
45
46
bool JsonCppDeserializer::deserialize(dap::integer* v) const {
47
if (!json->isInt64()) {
48
return false;
49
}
50
*v = json->asInt64();
51
return true;
52
}
53
54
bool JsonCppDeserializer::deserialize(dap::number* v) const {
55
if (!json->isNumeric()) {
56
return false;
57
}
58
*v = json->asDouble();
59
return true;
60
}
61
62
bool JsonCppDeserializer::deserialize(dap::string* v) const {
63
if (!json->isString()) {
64
return false;
65
}
66
*v = json->asString();
67
return true;
68
}
69
70
bool JsonCppDeserializer::deserialize(dap::object* v) const {
71
v->reserve(json->size());
72
for (auto i = json->begin(); i != json->end(); i++) {
73
JsonCppDeserializer d(&*i);
74
dap::any val;
75
if (!d.deserialize(&val)) {
76
return false;
77
}
78
(*v)[i.name()] = val;
79
}
80
return true;
81
}
82
83
bool JsonCppDeserializer::deserialize(dap::any* v) const {
84
if (json->isBool()) {
85
*v = dap::boolean(json->asBool());
86
} else if (json->type() == Json::ValueType::realValue) {
87
// json->isDouble() returns true for integers as well, so we need to
88
// explicitly look for the realValue type.
89
*v = dap::number(json->asDouble());
90
} else if (json->isInt64()) {
91
*v = dap::integer(json->asInt64());
92
} else if (json->isString()) {
93
*v = json->asString();
94
} else if (json->isObject()) {
95
dap::object obj;
96
if (!deserialize(&obj)) {
97
return false;
98
}
99
*v = obj;
100
} else if (json->isArray()) {
101
dap::array<any> arr;
102
if (!deserialize(&arr)) {
103
return false;
104
}
105
*v = arr;
106
} else if (json->isNull()) {
107
*v = null();
108
} else {
109
return false;
110
}
111
return true;
112
}
113
114
size_t JsonCppDeserializer::count() const {
115
return json->size();
116
}
117
118
bool JsonCppDeserializer::array(
119
const std::function<bool(dap::Deserializer*)>& cb) const {
120
if (!json->isArray()) {
121
return false;
122
}
123
for (const auto& value : *json) {
124
JsonCppDeserializer d(&value);
125
if (!cb(&d)) {
126
return false;
127
}
128
}
129
return true;
130
}
131
132
bool JsonCppDeserializer::field(
133
const std::string& name,
134
const std::function<bool(dap::Deserializer*)>& cb) const {
135
if (!json->isObject()) {
136
return false;
137
}
138
auto value = json->find(name.data(), name.data() + name.size());
139
if (value == nullptr) {
140
return cb(&NullDeserializer::instance);
141
}
142
JsonCppDeserializer d(value);
143
return cb(&d);
144
}
145
146
Json::Value JsonCppDeserializer::parse(const std::string& text) {
147
Json::CharReaderBuilder builder;
148
auto jsonReader = std::unique_ptr<Json::CharReader>(builder.newCharReader());
149
Json::Value json;
150
std::string error;
151
if (!jsonReader->parse(text.data(), text.data() + text.size(), &json,
152
&error)) {
153
// cppdap expects that the JSON layer does not throw exceptions.
154
std::abort();
155
}
156
return json;
157
}
158
159
JsonCppSerializer::JsonCppSerializer()
160
: json(new Json::Value()), ownsJson(true) {}
161
162
JsonCppSerializer::JsonCppSerializer(Json::Value* json)
163
: json(json), ownsJson(false) {}
164
165
JsonCppSerializer::~JsonCppSerializer() {
166
if (ownsJson) {
167
delete json;
168
}
169
}
170
171
std::string JsonCppSerializer::dump() const {
172
Json::StreamWriterBuilder writer;
173
return Json::writeString(writer, *json);
174
}
175
176
bool JsonCppSerializer::serialize(dap::boolean v) {
177
*json = (bool)v;
178
return true;
179
}
180
181
bool JsonCppSerializer::serialize(dap::integer v) {
182
*json = (Json::LargestInt)v;
183
return true;
184
}
185
186
bool JsonCppSerializer::serialize(dap::number v) {
187
*json = (double)v;
188
return true;
189
}
190
191
bool JsonCppSerializer::serialize(const dap::string& v) {
192
*json = v;
193
return true;
194
}
195
196
bool JsonCppSerializer::serialize(const dap::object& v) {
197
if (!json->isObject()) {
198
*json = Json::Value(Json::objectValue);
199
}
200
for (auto& it : v) {
201
JsonCppSerializer s(&(*json)[it.first]);
202
if (!s.serialize(it.second)) {
203
return false;
204
}
205
}
206
return true;
207
}
208
209
bool JsonCppSerializer::serialize(const dap::any& v) {
210
if (v.is<dap::boolean>()) {
211
*json = (bool)v.get<dap::boolean>();
212
} else if (v.is<dap::integer>()) {
213
*json = (Json::LargestInt)v.get<dap::integer>();
214
} else if (v.is<dap::number>()) {
215
*json = (double)v.get<dap::number>();
216
} else if (v.is<dap::string>()) {
217
*json = v.get<dap::string>();
218
} else if (v.is<dap::object>()) {
219
// reachable if dap::object nested is inside other dap::object
220
return serialize(v.get<dap::object>());
221
} else if (v.is<dap::null>()) {
222
} else {
223
// reachable if array or custom serialized type is nested inside other
224
auto type = get_any_type(v);
225
auto value = get_any_val(v);
226
if (type && value) {
227
return type->serialize(this, value);
228
}
229
return false;
230
}
231
return true;
232
}
233
234
bool JsonCppSerializer::array(size_t count,
235
const std::function<bool(dap::Serializer*)>& cb) {
236
*json = Json::Value(Json::arrayValue);
237
for (size_t i = 0; i < count; i++) {
238
JsonCppSerializer s(&(*json)[Json::Value::ArrayIndex(i)]);
239
if (!cb(&s)) {
240
return false;
241
}
242
}
243
return true;
244
}
245
246
bool JsonCppSerializer::object(
247
const std::function<bool(dap::FieldSerializer*)>& cb) {
248
struct FS : public FieldSerializer {
249
Json::Value* const json;
250
251
FS(Json::Value* json) : json(json) {}
252
bool field(const std::string& name, const SerializeFunc& cb) override {
253
JsonCppSerializer s(&(*json)[name]);
254
auto res = cb(&s);
255
if (s.removed) {
256
json->removeMember(name);
257
}
258
return res;
259
}
260
};
261
262
*json = Json::Value(Json::objectValue);
263
FS fs{json};
264
return cb(&fs);
265
}
266
267
void JsonCppSerializer::remove() {
268
removed = true;
269
}
270
271
} // namespace json
272
} // namespace dap
273
274