summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcppdap/src/jsoncpp_json_serializer.cpp
diff options
context:
space:
mode:
authorGlen Chung <kuchung@microsoft.com>2023-05-26 13:33:57 (GMT)
committerBrad King <brad.king@kitware.com>2023-05-26 13:36:03 (GMT)
commit3381e6bd5cbfa1694f07c97a19747adda10b06f2 (patch)
treea99c177695b41b4f6576f74a7a59a7721de96687 /Utilities/cmcppdap/src/jsoncpp_json_serializer.cpp
parentbd58bc7817e9546cb6726a52657f54b1cde59b0c (diff)
parent1daeefc37856c209718b406dcb86d44519393dd1 (diff)
downloadCMake-3381e6bd5cbfa1694f07c97a19747adda10b06f2.zip
CMake-3381e6bd5cbfa1694f07c97a19747adda10b06f2.tar.gz
CMake-3381e6bd5cbfa1694f07c97a19747adda10b06f2.tar.bz2
Merge branch 'upstream-cppdap' into import-cppdap
* upstream-cppdap: cppdap 2023-05-26 (03cc1867)
Diffstat (limited to 'Utilities/cmcppdap/src/jsoncpp_json_serializer.cpp')
-rw-r--r--Utilities/cmcppdap/src/jsoncpp_json_serializer.cpp272
1 files changed, 272 insertions, 0 deletions
diff --git a/Utilities/cmcppdap/src/jsoncpp_json_serializer.cpp b/Utilities/cmcppdap/src/jsoncpp_json_serializer.cpp
new file mode 100644
index 0000000..954b0e5
--- /dev/null
+++ b/Utilities/cmcppdap/src/jsoncpp_json_serializer.cpp
@@ -0,0 +1,272 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "jsoncpp_json_serializer.h"
+
+#include "null_json_serializer.h"
+
+#include <json/json.h>
+#include <cstdlib>
+#include <memory>
+
+namespace dap {
+namespace json {
+
+JsonCppDeserializer::JsonCppDeserializer(const std::string& str)
+ : json(new Json::Value(JsonCppDeserializer::parse(str))), ownsJson(true) {}
+
+JsonCppDeserializer::JsonCppDeserializer(const Json::Value* json)
+ : json(json), ownsJson(false) {}
+
+JsonCppDeserializer::~JsonCppDeserializer() {
+ if (ownsJson) {
+ delete json;
+ }
+}
+
+bool JsonCppDeserializer::deserialize(dap::boolean* v) const {
+ if (!json->isBool()) {
+ return false;
+ }
+ *v = json->asBool();
+ return true;
+}
+
+bool JsonCppDeserializer::deserialize(dap::integer* v) const {
+ if (!json->isInt64()) {
+ return false;
+ }
+ *v = json->asInt64();
+ return true;
+}
+
+bool JsonCppDeserializer::deserialize(dap::number* v) const {
+ if (!json->isNumeric()) {
+ return false;
+ }
+ *v = json->asDouble();
+ return true;
+}
+
+bool JsonCppDeserializer::deserialize(dap::string* v) const {
+ if (!json->isString()) {
+ return false;
+ }
+ *v = json->asString();
+ return true;
+}
+
+bool JsonCppDeserializer::deserialize(dap::object* v) const {
+ v->reserve(json->size());
+ for (auto i = json->begin(); i != json->end(); i++) {
+ JsonCppDeserializer d(&*i);
+ dap::any val;
+ if (!d.deserialize(&val)) {
+ return false;
+ }
+ (*v)[i.name()] = val;
+ }
+ return true;
+}
+
+bool JsonCppDeserializer::deserialize(dap::any* v) const {
+ if (json->isBool()) {
+ *v = dap::boolean(json->asBool());
+ } else if (json->type() == Json::ValueType::realValue) {
+ // json->isDouble() returns true for integers as well, so we need to
+ // explicitly look for the realValue type.
+ *v = dap::number(json->asDouble());
+ } else if (json->isInt64()) {
+ *v = dap::integer(json->asInt64());
+ } else if (json->isString()) {
+ *v = json->asString();
+ } else if (json->isObject()) {
+ dap::object obj;
+ if (!deserialize(&obj)) {
+ return false;
+ }
+ *v = obj;
+ } else if (json->isArray()) {
+ dap::array<any> arr;
+ if (!deserialize(&arr)) {
+ return false;
+ }
+ *v = arr;
+ } else if (json->isNull()) {
+ *v = null();
+ } else {
+ return false;
+ }
+ return true;
+}
+
+size_t JsonCppDeserializer::count() const {
+ return json->size();
+}
+
+bool JsonCppDeserializer::array(
+ const std::function<bool(dap::Deserializer*)>& cb) const {
+ if (!json->isArray()) {
+ return false;
+ }
+ for (const auto& value : *json) {
+ JsonCppDeserializer d(&value);
+ if (!cb(&d)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool JsonCppDeserializer::field(
+ const std::string& name,
+ const std::function<bool(dap::Deserializer*)>& cb) const {
+ if (!json->isObject()) {
+ return false;
+ }
+ auto value = json->find(name.data(), name.data() + name.size());
+ if (value == nullptr) {
+ return cb(&NullDeserializer::instance);
+ }
+ JsonCppDeserializer d(value);
+ return cb(&d);
+}
+
+Json::Value JsonCppDeserializer::parse(const std::string& text) {
+ Json::CharReaderBuilder builder;
+ auto jsonReader = std::unique_ptr<Json::CharReader>(builder.newCharReader());
+ Json::Value json;
+ std::string error;
+ if (!jsonReader->parse(text.data(), text.data() + text.size(), &json,
+ &error)) {
+ // cppdap expects that the JSON layer does not throw exceptions.
+ std::abort();
+ }
+ return json;
+}
+
+JsonCppSerializer::JsonCppSerializer()
+ : json(new Json::Value()), ownsJson(true) {}
+
+JsonCppSerializer::JsonCppSerializer(Json::Value* json)
+ : json(json), ownsJson(false) {}
+
+JsonCppSerializer::~JsonCppSerializer() {
+ if (ownsJson) {
+ delete json;
+ }
+}
+
+std::string JsonCppSerializer::dump() const {
+ Json::StreamWriterBuilder writer;
+ return Json::writeString(writer, *json);
+}
+
+bool JsonCppSerializer::serialize(dap::boolean v) {
+ *json = (bool)v;
+ return true;
+}
+
+bool JsonCppSerializer::serialize(dap::integer v) {
+ *json = (Json::LargestInt)v;
+ return true;
+}
+
+bool JsonCppSerializer::serialize(dap::number v) {
+ *json = (double)v;
+ return true;
+}
+
+bool JsonCppSerializer::serialize(const dap::string& v) {
+ *json = v;
+ return true;
+}
+
+bool JsonCppSerializer::serialize(const dap::object& v) {
+ if (!json->isObject()) {
+ *json = Json::Value(Json::objectValue);
+ }
+ for (auto& it : v) {
+ JsonCppSerializer s(&(*json)[it.first]);
+ if (!s.serialize(it.second)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool JsonCppSerializer::serialize(const dap::any& v) {
+ if (v.is<dap::boolean>()) {
+ *json = (bool)v.get<dap::boolean>();
+ } else if (v.is<dap::integer>()) {
+ *json = (Json::LargestInt)v.get<dap::integer>();
+ } else if (v.is<dap::number>()) {
+ *json = (double)v.get<dap::number>();
+ } else if (v.is<dap::string>()) {
+ *json = v.get<dap::string>();
+ } else if (v.is<dap::object>()) {
+ // reachable if dap::object nested is inside other dap::object
+ return serialize(v.get<dap::object>());
+ } else if (v.is<dap::null>()) {
+ } else {
+ // reachable if array or custom serialized type is nested inside other
+ auto type = get_any_type(v);
+ auto value = get_any_val(v);
+ if (type && value) {
+ return type->serialize(this, value);
+ }
+ return false;
+ }
+ return true;
+}
+
+bool JsonCppSerializer::array(size_t count,
+ const std::function<bool(dap::Serializer*)>& cb) {
+ *json = Json::Value(Json::arrayValue);
+ for (size_t i = 0; i < count; i++) {
+ JsonCppSerializer s(&(*json)[Json::Value::ArrayIndex(i)]);
+ if (!cb(&s)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool JsonCppSerializer::object(
+ const std::function<bool(dap::FieldSerializer*)>& cb) {
+ struct FS : public FieldSerializer {
+ Json::Value* const json;
+
+ FS(Json::Value* json) : json(json) {}
+ bool field(const std::string& name, const SerializeFunc& cb) override {
+ JsonCppSerializer s(&(*json)[name]);
+ auto res = cb(&s);
+ if (s.removed) {
+ json->removeMember(name);
+ }
+ return res;
+ }
+ };
+
+ *json = Json::Value(Json::objectValue);
+ FS fs{json};
+ return cb(&fs);
+}
+
+void JsonCppSerializer::remove() {
+ removed = true;
+}
+
+} // namespace json
+} // namespace dap