290 lines
7.4 KiB
C++
290 lines
7.4 KiB
C++
// Copyright 2019 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 "rapid_json_serializer.h"
|
|
|
|
#include "null_json_serializer.h"
|
|
|
|
#include <rapidjson/document.h>
|
|
#include <rapidjson/prettywriter.h>
|
|
|
|
namespace dap {
|
|
namespace json {
|
|
|
|
RapidDeserializer::RapidDeserializer(const std::string& str)
|
|
: doc(new rapidjson::Document()) {
|
|
doc->Parse(str.c_str());
|
|
}
|
|
|
|
RapidDeserializer::RapidDeserializer(rapidjson::Value* json) : val(json) {}
|
|
|
|
RapidDeserializer::~RapidDeserializer() {
|
|
delete doc;
|
|
}
|
|
|
|
bool RapidDeserializer::deserialize(dap::boolean* v) const {
|
|
if (!json()->IsBool()) {
|
|
return false;
|
|
}
|
|
*v = json()->GetBool();
|
|
return true;
|
|
}
|
|
|
|
bool RapidDeserializer::deserialize(dap::integer* v) const {
|
|
if (json()->IsInt()) {
|
|
*v = json()->GetInt();
|
|
return true;
|
|
} else if (json()->IsUint()) {
|
|
*v = static_cast<int64_t>(json()->GetUint());
|
|
return true;
|
|
} else if (json()->IsInt64()) {
|
|
*v = json()->GetInt64();
|
|
return true;
|
|
} else if (json()->IsUint64()) {
|
|
*v = static_cast<int64_t>(json()->GetUint64());
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool RapidDeserializer::deserialize(dap::number* v) const {
|
|
if (!json()->IsNumber()) {
|
|
return false;
|
|
}
|
|
*v = json()->GetDouble();
|
|
return true;
|
|
}
|
|
|
|
bool RapidDeserializer::deserialize(dap::string* v) const {
|
|
if (!json()->IsString()) {
|
|
return false;
|
|
}
|
|
*v = json()->GetString();
|
|
return true;
|
|
}
|
|
|
|
bool RapidDeserializer::deserialize(dap::object* v) const {
|
|
v->reserve(json()->MemberCount());
|
|
for (auto el = json()->MemberBegin(); el != json()->MemberEnd(); el++) {
|
|
dap::any el_val;
|
|
RapidDeserializer d(&(el->value));
|
|
if (!d.deserialize(&el_val)) {
|
|
return false;
|
|
}
|
|
(*v)[el->name.GetString()] = el_val;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool RapidDeserializer::deserialize(dap::any* v) const {
|
|
if (json()->IsBool()) {
|
|
*v = dap::boolean(json()->GetBool());
|
|
} else if (json()->IsDouble()) {
|
|
*v = dap::number(json()->GetDouble());
|
|
} else if (json()->IsInt()) {
|
|
*v = dap::integer(json()->GetInt());
|
|
} else if (json()->IsString()) {
|
|
*v = dap::string(json()->GetString());
|
|
} else if (json()->IsNull()) {
|
|
*v = null();
|
|
} 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 {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
size_t RapidDeserializer::count() const {
|
|
return json()->Size();
|
|
}
|
|
|
|
bool RapidDeserializer::array(
|
|
const std::function<bool(dap::Deserializer*)>& cb) const {
|
|
if (!json()->IsArray()) {
|
|
return false;
|
|
}
|
|
for (uint32_t i = 0; i < json()->Size(); i++) {
|
|
RapidDeserializer d(&(*json())[i]);
|
|
if (!cb(&d)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool RapidDeserializer::field(
|
|
const std::string& name,
|
|
const std::function<bool(dap::Deserializer*)>& cb) const {
|
|
if (!json()->IsObject()) {
|
|
return false;
|
|
}
|
|
auto it = json()->FindMember(name.c_str());
|
|
if (it == json()->MemberEnd()) {
|
|
return cb(&NullDeserializer::instance);
|
|
}
|
|
RapidDeserializer d(&(it->value));
|
|
return cb(&d);
|
|
}
|
|
|
|
RapidSerializer::RapidSerializer()
|
|
: doc(new rapidjson::Document(rapidjson::kObjectType)),
|
|
allocator(doc->GetAllocator()) {}
|
|
|
|
RapidSerializer::RapidSerializer(rapidjson::Value* json,
|
|
rapidjson::Document::AllocatorType& allocator)
|
|
: val(json), allocator(allocator) {}
|
|
|
|
RapidSerializer::~RapidSerializer() {
|
|
delete doc;
|
|
}
|
|
|
|
std::string RapidSerializer::dump() const {
|
|
rapidjson::StringBuffer sb;
|
|
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
|
|
json()->Accept(writer);
|
|
return sb.GetString();
|
|
}
|
|
|
|
bool RapidSerializer::serialize(dap::boolean v) {
|
|
json()->SetBool(v);
|
|
return true;
|
|
}
|
|
|
|
bool RapidSerializer::serialize(dap::integer v) {
|
|
json()->SetInt64(v);
|
|
return true;
|
|
}
|
|
|
|
bool RapidSerializer::serialize(dap::number v) {
|
|
json()->SetDouble(v);
|
|
return true;
|
|
}
|
|
|
|
bool RapidSerializer::serialize(const dap::string& v) {
|
|
json()->SetString(v.data(), static_cast<uint32_t>(v.length()), allocator);
|
|
return true;
|
|
}
|
|
|
|
bool RapidSerializer::serialize(const dap::object& v) {
|
|
if (!json()->IsObject()) {
|
|
json()->SetObject();
|
|
}
|
|
for (auto& it : v) {
|
|
if (!json()->HasMember(it.first.c_str())) {
|
|
rapidjson::Value name_value{it.first.c_str(), allocator};
|
|
json()->AddMember(name_value, rapidjson::Value(), allocator);
|
|
}
|
|
rapidjson::Value& member = (*json())[it.first.c_str()];
|
|
RapidSerializer s(&member, allocator);
|
|
if (!s.serialize(it.second)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool RapidSerializer::serialize(const dap::any& v) {
|
|
if (v.is<dap::boolean>()) {
|
|
json()->SetBool((bool)v.get<dap::boolean>());
|
|
} else if (v.is<dap::integer>()) {
|
|
json()->SetInt64(v.get<dap::integer>());
|
|
} else if (v.is<dap::number>()) {
|
|
json()->SetDouble((double)v.get<dap::number>());
|
|
} else if (v.is<dap::string>()) {
|
|
auto s = v.get<dap::string>();
|
|
json()->SetString(s.data(), static_cast<uint32_t>(s.length()), allocator);
|
|
} 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 dap::object
|
|
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 RapidSerializer::array(size_t count,
|
|
const std::function<bool(dap::Serializer*)>& cb) {
|
|
if (!json()->IsArray()) {
|
|
json()->SetArray();
|
|
}
|
|
|
|
while (count > json()->Size()) {
|
|
json()->PushBack(rapidjson::Value(), allocator);
|
|
}
|
|
|
|
for (uint32_t i = 0; i < count; i++) {
|
|
RapidSerializer s(&(*json())[i], allocator);
|
|
if (!cb(&s)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool RapidSerializer::object(
|
|
const std::function<bool(dap::FieldSerializer*)>& cb) {
|
|
struct FS : public FieldSerializer {
|
|
rapidjson::Value* const json;
|
|
rapidjson::Document::AllocatorType& allocator;
|
|
|
|
FS(rapidjson::Value* json, rapidjson::Document::AllocatorType& allocator)
|
|
: json(json), allocator(allocator) {}
|
|
bool field(const std::string& name, const SerializeFunc& cb) override {
|
|
if (!json->HasMember(name.c_str())) {
|
|
rapidjson::Value name_value{name.c_str(), allocator};
|
|
json->AddMember(name_value, rapidjson::Value(), allocator);
|
|
}
|
|
rapidjson::Value& member = (*json)[name.c_str()];
|
|
RapidSerializer s(&member, allocator);
|
|
auto res = cb(&s);
|
|
if (s.removed) {
|
|
json->RemoveMember(name.c_str());
|
|
}
|
|
return res;
|
|
}
|
|
};
|
|
|
|
if (!json()->IsObject()) {
|
|
json()->SetObject();
|
|
}
|
|
FS fs{json(), allocator};
|
|
return cb(&fs);
|
|
}
|
|
|
|
void RapidSerializer::remove() {
|
|
removed = true;
|
|
}
|
|
|
|
} // namespace json
|
|
} // namespace dap
|