diff options
Diffstat (limited to 'Utilities/cmcppdap/src/jsoncpp_json_serializer.cpp')
-rw-r--r-- | Utilities/cmcppdap/src/jsoncpp_json_serializer.cpp | 272 |
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 |