Add support for rapidjson as the JSON library

nlohmann is still the default, but if `CPPDAP_JSON_DIR` points to rapidjson, then this will be used instead

Most of this was upstreamed from:
https://fuchsia-review.googlesource.com/c/third_party/github.com/google/cppdap/+/456566
This commit is contained in:
Ben Clayton 2020-12-01 16:30:45 +00:00
parent 77209caf04
commit 6d6cbf17d7
12 changed files with 689 additions and 176 deletions

View File

@ -64,14 +64,34 @@ if(CPPDAP_BUILD_TESTS)
endif() endif()
endif(CPPDAP_BUILD_TESTS) endif(CPPDAP_BUILD_TESTS)
###########################################################
# JSON library
###########################################################
if(NOT DEFINED CPPDAP_JSON_LIBRARY)
# Attempt to detect JSON library from CPPDAP_JSON_DIR
if(NOT EXISTS "${CPPDAP_JSON_DIR}")
message(FATAL_ERROR "CPPDAP_JSON_DIR '${CPPDAP_JSON_DIR}' does not exist")
endif()
if(EXISTS "${CPPDAP_JSON_DIR}/include/nlohmann")
set(CPPDAP_JSON_LIBRARY "nlohmann")
elseif(EXISTS "${CPPDAP_JSON_DIR}/include/rapidjson")
set(CPPDAP_JSON_LIBRARY "rapid")
else()
message(FATAL_ERROR "Could not determine JSON library from ${CPPDAP_JSON_LIBRARY}")
endif()
endif()
string(TOUPPER ${CPPDAP_JSON_LIBRARY} CPPDAP_JSON_LIBRARY_UPPER)
########################################################### ###########################################################
# File lists # File lists
########################################################### ###########################################################
set(CPPDAP_LIST set(CPPDAP_LIST
${CPPDAP_SRC_DIR}/content_stream.cpp ${CPPDAP_SRC_DIR}/content_stream.cpp
${CPPDAP_SRC_DIR}/io.cpp ${CPPDAP_SRC_DIR}/io.cpp
${CPPDAP_SRC_DIR}/json_serializer.cpp ${CPPDAP_SRC_DIR}/${CPPDAP_JSON_LIBRARY}_json_serializer.cpp
${CPPDAP_SRC_DIR}/network.cpp ${CPPDAP_SRC_DIR}/network.cpp
${CPPDAP_SRC_DIR}/null_json_serializer.cpp
${CPPDAP_SRC_DIR}/protocol_events.cpp ${CPPDAP_SRC_DIR}/protocol_events.cpp
${CPPDAP_SRC_DIR}/protocol_requests.cpp ${CPPDAP_SRC_DIR}/protocol_requests.cpp
${CPPDAP_SRC_DIR}/protocol_response.cpp ${CPPDAP_SRC_DIR}/protocol_response.cpp
@ -117,6 +137,11 @@ function(cppdap_set_target_options target)
) )
endif() endif()
# Add define for JSON library in use
set_target_properties(${target} PROPERTIES
COMPILE_DEFINITIONS "CPPDAP_JSON_${CPPDAP_JSON_LIBRARY_UPPER}=1"
)
# Treat all warnings as errors # Treat all warnings as errors
if(CPPDAP_WARNINGS_AS_ERRORS) if(CPPDAP_WARNINGS_AS_ERRORS)
if(MSVC) if(MSVC)
@ -151,9 +176,7 @@ endfunction(cppdap_set_target_options)
# dap # dap
add_library(cppdap STATIC ${CPPDAP_LIST}) add_library(cppdap STATIC ${CPPDAP_LIST})
set_target_properties(cppdap PROPERTIES set_target_properties(cppdap PROPERTIES POSITION_INDEPENDENT_CODE 1)
POSITION_INDEPENDENT_CODE 1
)
target_include_directories(cppdap PRIVATE "${CPPDAP_JSON_DIR}/include/") target_include_directories(cppdap PRIVATE "${CPPDAP_JSON_DIR}/include/")

View File

@ -145,7 +145,7 @@ class File : public dap::ReaderWriter {
const bool closable; const bool closable;
std::mutex readMutex; std::mutex readMutex;
std::mutex writeMutex; std::mutex writeMutex;
std::atomic<bool> closed = { false }; std::atomic<bool> closed = {false};
}; };
class ReaderSpy : public dap::Reader { class ReaderSpy : public dap::Reader {

View File

@ -1,4 +1,4 @@
// Copyright 2019 Google LLC // Copyright 2020 Google LLC
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -15,117 +15,26 @@
#ifndef dap_json_serializer_h #ifndef dap_json_serializer_h
#define dap_json_serializer_h #define dap_json_serializer_h
#include "dap/protocol.h" #if defined(CPPDAP_JSON_NLOHMANN)
#include "dap/serialization.h" #include "nlohmann_json_serializer.h"
#include "dap/types.h" #elif defined(CPPDAP_JSON_RAPID)
#include "rapid_json_serializer.h"
#include <nlohmann/json_fwd.hpp> #else
#error "Unrecognised cppdap JSON library"
#endif
namespace dap { namespace dap {
namespace json { namespace json {
struct Deserializer : public dap::Deserializer { #if defined(CPPDAP_JSON_NLOHMANN)
explicit Deserializer(const std::string&); using Deserializer = NlohmannDeserializer;
~Deserializer(); using Serializer = NlohmannSerializer;
#elif defined(CPPDAP_JSON_RAPID)
// dap::Deserializer compliance using Deserializer = RapidDeserializer;
bool deserialize(boolean* v) const override; using Serializer = RapidSerializer;
bool deserialize(integer* v) const override; #else
bool deserialize(number* v) const override; #error "Unrecognised cppdap JSON library"
bool deserialize(string* v) const override; #endif
bool deserialize(object* v) const override;
bool deserialize(any* v) const override;
size_t count() const override;
bool array(const std::function<bool(dap::Deserializer*)>&) const override;
bool field(const std::string& name,
const std::function<bool(dap::Deserializer*)>&) const override;
// Unhide base overloads
template <typename T>
inline bool field(const std::string& name, T* v) {
return dap::Deserializer::field(name, v);
}
template <typename T,
typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
inline bool deserialize(T* v) const {
return dap::Deserializer::deserialize(v);
}
template <typename T>
inline bool deserialize(dap::array<T>* v) const {
return dap::Deserializer::deserialize(v);
}
template <typename T>
inline bool deserialize(dap::optional<T>* v) const {
return dap::Deserializer::deserialize(v);
}
template <typename T0, typename... Types>
inline bool deserialize(dap::variant<T0, Types...>* v) const {
return dap::Deserializer::deserialize(v);
}
template <typename T>
inline bool field(const std::string& name, T* v) const {
return dap::Deserializer::deserialize(name, v);
}
private:
Deserializer(const nlohmann::json*);
const nlohmann::json* const json;
const bool ownsJson;
};
struct Serializer : public dap::Serializer {
Serializer();
~Serializer();
std::string dump() const;
// dap::Serializer compliance
bool serialize(boolean v) override;
bool serialize(integer v) override;
bool serialize(number v) override;
bool serialize(const string& v) override;
bool serialize(const dap::object& v) override;
bool serialize(const any& v) override;
bool array(size_t count,
const std::function<bool(dap::Serializer*)>&) override;
bool object(const std::function<bool(dap::FieldSerializer*)>&) override;
void remove() override;
// Unhide base overloads
template <typename T,
typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
inline bool serialize(const T& v) {
return dap::Serializer::serialize(v);
}
template <typename T>
inline bool serialize(const dap::array<T>& v) {
return dap::Serializer::serialize(v);
}
template <typename T>
inline bool serialize(const dap::optional<T>& v) {
return dap::Serializer::serialize(v);
}
template <typename T0, typename... Types>
inline bool serialize(const dap::variant<T0, Types...>& v) {
return dap::Serializer::serialize(v);
}
inline bool serialize(const char* v) { return dap::Serializer::serialize(v); }
private:
Serializer(nlohmann::json*);
nlohmann::json* const json;
const bool ownsJson;
bool removed = false;
};
} // namespace json } // namespace json
} // namespace dap } // namespace dap

View File

@ -12,55 +12,32 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "json_serializer.h" #include "nlohmann_json_serializer.h"
#include "null_json_serializer.h"
// Disable JSON exceptions. We should be guarding against any exceptions being // Disable JSON exceptions. We should be guarding against any exceptions being
// fired in this file. // fired in this file.
#define JSON_NOEXCEPTION 1 #define JSON_NOEXCEPTION 1
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
namespace {
struct NullDeserializer : public dap::Deserializer {
static NullDeserializer instance;
bool deserialize(dap::boolean*) const override { return false; }
bool deserialize(dap::integer*) const override { return false; }
bool deserialize(dap::number*) const override { return false; }
bool deserialize(dap::string*) const override { return false; }
bool deserialize(dap::object*) const override { return false; }
bool deserialize(dap::any*) const override { return false; }
size_t count() const override { return 0; }
bool array(const std::function<bool(dap::Deserializer*)>&) const override {
return false;
}
bool field(const std::string&,
const std::function<bool(dap::Deserializer*)>&) const override {
return false;
}
};
NullDeserializer NullDeserializer::instance;
} // anonymous namespace
namespace dap { namespace dap {
namespace json { namespace json {
Deserializer::Deserializer(const std::string& str) NlohmannDeserializer::NlohmannDeserializer(const std::string& str)
: json(new nlohmann::json(nlohmann::json::parse(str, nullptr, false))), : json(new nlohmann::json(nlohmann::json::parse(str, nullptr, false))),
ownsJson(true) {} ownsJson(true) {}
Deserializer::Deserializer(const nlohmann::json* json) NlohmannDeserializer::NlohmannDeserializer(const nlohmann::json* json)
: json(json), ownsJson(false) {} : json(json), ownsJson(false) {}
Deserializer::~Deserializer() { NlohmannDeserializer::~NlohmannDeserializer() {
if (ownsJson) { if (ownsJson) {
delete json; delete json;
} }
} }
bool Deserializer::deserialize(dap::boolean* v) const { bool NlohmannDeserializer::deserialize(dap::boolean* v) const {
if (!json->is_boolean()) { if (!json->is_boolean()) {
return false; return false;
} }
@ -68,7 +45,7 @@ bool Deserializer::deserialize(dap::boolean* v) const {
return true; return true;
} }
bool Deserializer::deserialize(dap::integer* v) const { bool NlohmannDeserializer::deserialize(dap::integer* v) const {
if (!json->is_number_integer()) { if (!json->is_number_integer()) {
return false; return false;
} }
@ -76,7 +53,7 @@ bool Deserializer::deserialize(dap::integer* v) const {
return true; return true;
} }
bool Deserializer::deserialize(dap::number* v) const { bool NlohmannDeserializer::deserialize(dap::number* v) const {
if (!json->is_number()) { if (!json->is_number()) {
return false; return false;
} }
@ -84,7 +61,7 @@ bool Deserializer::deserialize(dap::number* v) const {
return true; return true;
} }
bool Deserializer::deserialize(dap::string* v) const { bool NlohmannDeserializer::deserialize(dap::string* v) const {
if (!json->is_string()) { if (!json->is_string()) {
return false; return false;
} }
@ -92,10 +69,10 @@ bool Deserializer::deserialize(dap::string* v) const {
return true; return true;
} }
bool Deserializer::deserialize(dap::object* v) const { bool NlohmannDeserializer::deserialize(dap::object* v) const {
v->reserve(json->size()); v->reserve(json->size());
for (auto& el : json->items()) { for (auto& el : json->items()) {
Deserializer d(&el.value()); NlohmannDeserializer d(&el.value());
dap::any val; dap::any val;
if (!d.deserialize(&val)) { if (!d.deserialize(&val)) {
return false; return false;
@ -105,7 +82,7 @@ bool Deserializer::deserialize(dap::object* v) const {
return true; return true;
} }
bool Deserializer::deserialize(dap::any* v) const { bool NlohmannDeserializer::deserialize(dap::any* v) const {
if (json->is_boolean()) { if (json->is_boolean()) {
*v = dap::boolean(json->get<bool>()); *v = dap::boolean(json->get<bool>());
} else if (json->is_number_float()) { } else if (json->is_number_float()) {
@ -122,17 +99,17 @@ bool Deserializer::deserialize(dap::any* v) const {
return true; return true;
} }
size_t Deserializer::count() const { size_t NlohmannDeserializer::count() const {
return json->size(); return json->size();
} }
bool Deserializer::array( bool NlohmannDeserializer::array(
const std::function<bool(dap::Deserializer*)>& cb) const { const std::function<bool(dap::Deserializer*)>& cb) const {
if (!json->is_array()) { if (!json->is_array()) {
return false; return false;
} }
for (size_t i = 0; i < json->size(); i++) { for (size_t i = 0; i < json->size(); i++) {
Deserializer d(&(*json)[i]); NlohmannDeserializer d(&(*json)[i]);
if (!cb(&d)) { if (!cb(&d)) {
return false; return false;
} }
@ -140,7 +117,7 @@ bool Deserializer::array(
return true; return true;
} }
bool Deserializer::field( bool NlohmannDeserializer::field(
const std::string& name, const std::string& name,
const std::function<bool(dap::Deserializer*)>& cb) const { const std::function<bool(dap::Deserializer*)>& cb) const {
if (!json->is_structured()) { if (!json->is_structured()) {
@ -151,47 +128,49 @@ bool Deserializer::field(
return cb(&NullDeserializer::instance); return cb(&NullDeserializer::instance);
} }
auto obj = *it; auto obj = *it;
Deserializer d(&obj); NlohmannDeserializer d(&obj);
return cb(&d); return cb(&d);
} }
Serializer::Serializer() : json(new nlohmann::json()), ownsJson(true) {} NlohmannSerializer::NlohmannSerializer()
: json(new nlohmann::json()), ownsJson(true) {}
Serializer::Serializer(nlohmann::json* json) : json(json), ownsJson(false) {} NlohmannSerializer::NlohmannSerializer(nlohmann::json* json)
: json(json), ownsJson(false) {}
Serializer::~Serializer() { NlohmannSerializer::~NlohmannSerializer() {
if (ownsJson) { if (ownsJson) {
delete json; delete json;
} }
} }
std::string Serializer::dump() const { std::string NlohmannSerializer::dump() const {
return json->dump(); return json->dump();
} }
bool Serializer::serialize(dap::boolean v) { bool NlohmannSerializer::serialize(dap::boolean v) {
*json = (bool)v; *json = (bool)v;
return true; return true;
} }
bool Serializer::serialize(dap::integer v) { bool NlohmannSerializer::serialize(dap::integer v) {
*json = (int)v; *json = (int)v;
return true; return true;
} }
bool Serializer::serialize(dap::number v) { bool NlohmannSerializer::serialize(dap::number v) {
*json = (double)v; *json = (double)v;
return true; return true;
} }
bool Serializer::serialize(const dap::string& v) { bool NlohmannSerializer::serialize(const dap::string& v) {
*json = v; *json = v;
return true; return true;
} }
bool Serializer::serialize(const dap::object& v) { bool NlohmannSerializer::serialize(const dap::object& v) {
for (auto& it : v) { for (auto& it : v) {
Serializer s(&(*json)[it.first]); NlohmannSerializer s(&(*json)[it.first]);
if (!s.serialize(it.second)) { if (!s.serialize(it.second)) {
return false; return false;
} }
@ -199,7 +178,7 @@ bool Serializer::serialize(const dap::object& v) {
return true; return true;
} }
bool Serializer::serialize(const dap::any& v) { bool NlohmannSerializer::serialize(const dap::any& v) {
if (v.is<dap::boolean>()) { if (v.is<dap::boolean>()) {
*json = (bool)v.get<dap::boolean>(); *json = (bool)v.get<dap::boolean>();
} else if (v.is<dap::integer>()) { } else if (v.is<dap::integer>()) {
@ -216,11 +195,12 @@ bool Serializer::serialize(const dap::any& v) {
return true; return true;
} }
bool Serializer::array(size_t count, bool NlohmannSerializer::array(
size_t count,
const std::function<bool(dap::Serializer*)>& cb) { const std::function<bool(dap::Serializer*)>& cb) {
*json = std::vector<int>(); *json = std::vector<int>();
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
Serializer s(&(*json)[i]); NlohmannSerializer s(&(*json)[i]);
if (!cb(&s)) { if (!cb(&s)) {
return false; return false;
} }
@ -228,13 +208,14 @@ bool Serializer::array(size_t count,
return true; return true;
} }
bool Serializer::object(const std::function<bool(dap::FieldSerializer*)>& cb) { bool NlohmannSerializer::object(
const std::function<bool(dap::FieldSerializer*)>& cb) {
struct FS : public FieldSerializer { struct FS : public FieldSerializer {
nlohmann::json* const json; nlohmann::json* const json;
FS(nlohmann::json* json) : json(json) {} FS(nlohmann::json* json) : json(json) {}
bool field(const std::string& name, const SerializeFunc& cb) override { bool field(const std::string& name, const SerializeFunc& cb) override {
Serializer s(&(*json)[name]); NlohmannSerializer s(&(*json)[name]);
auto res = cb(&s); auto res = cb(&s);
if (s.removed) { if (s.removed) {
json->erase(name); json->erase(name);
@ -248,7 +229,7 @@ bool Serializer::object(const std::function<bool(dap::FieldSerializer*)>& cb) {
return cb(&fs); return cb(&fs);
} }
void Serializer::remove() { void NlohmannSerializer::remove() {
removed = true; removed = true;
} }

View File

@ -0,0 +1,133 @@
// 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.
#ifndef dap_nlohmann_json_serializer_h
#define dap_nlohmann_json_serializer_h
#include "dap/protocol.h"
#include "dap/serialization.h"
#include "dap/types.h"
#include <nlohmann/json_fwd.hpp>
namespace dap {
namespace json {
struct NlohmannDeserializer : public dap::Deserializer {
explicit NlohmannDeserializer(const std::string&);
~NlohmannDeserializer();
// dap::Deserializer compliance
bool deserialize(boolean* v) const override;
bool deserialize(integer* v) const override;
bool deserialize(number* v) const override;
bool deserialize(string* v) const override;
bool deserialize(object* v) const override;
bool deserialize(any* v) const override;
size_t count() const override;
bool array(const std::function<bool(dap::Deserializer*)>&) const override;
bool field(const std::string& name,
const std::function<bool(dap::Deserializer*)>&) const override;
// Unhide base overloads
template <typename T>
inline bool field(const std::string& name, T* v) {
return dap::Deserializer::field(name, v);
}
template <typename T,
typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
inline bool deserialize(T* v) const {
return dap::Deserializer::deserialize(v);
}
template <typename T>
inline bool deserialize(dap::array<T>* v) const {
return dap::Deserializer::deserialize(v);
}
template <typename T>
inline bool deserialize(dap::optional<T>* v) const {
return dap::Deserializer::deserialize(v);
}
template <typename T0, typename... Types>
inline bool deserialize(dap::variant<T0, Types...>* v) const {
return dap::Deserializer::deserialize(v);
}
template <typename T>
inline bool field(const std::string& name, T* v) const {
return dap::Deserializer::deserialize(name, v);
}
private:
NlohmannDeserializer(const nlohmann::json*);
const nlohmann::json* const json;
const bool ownsJson;
};
struct NlohmannSerializer : public dap::Serializer {
NlohmannSerializer();
~NlohmannSerializer();
std::string dump() const;
// dap::Serializer compliance
bool serialize(boolean v) override;
bool serialize(integer v) override;
bool serialize(number v) override;
bool serialize(const string& v) override;
bool serialize(const dap::object& v) override;
bool serialize(const any& v) override;
bool array(size_t count,
const std::function<bool(dap::Serializer*)>&) override;
bool object(const std::function<bool(dap::FieldSerializer*)>&) override;
void remove() override;
// Unhide base overloads
template <typename T,
typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
inline bool serialize(const T& v) {
return dap::Serializer::serialize(v);
}
template <typename T>
inline bool serialize(const dap::array<T>& v) {
return dap::Serializer::serialize(v);
}
template <typename T>
inline bool serialize(const dap::optional<T>& v) {
return dap::Serializer::serialize(v);
}
template <typename T0, typename... Types>
inline bool serialize(const dap::variant<T0, Types...>& v) {
return dap::Serializer::serialize(v);
}
inline bool serialize(const char* v) { return dap::Serializer::serialize(v); }
private:
NlohmannSerializer(nlohmann::json*);
nlohmann::json* const json;
const bool ownsJson;
bool removed = false;
};
} // namespace json
} // namespace dap
#endif // dap_nlohmann_json_serializer_h

View File

@ -0,0 +1,23 @@
// Copyright 2020 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 "null_json_serializer.h"
namespace dap {
namespace json {
NullDeserializer NullDeserializer::instance;
} // namespace json
} // namespace dap

View File

@ -0,0 +1,47 @@
// Copyright 2020 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.
#ifndef dap_null_json_serializer_h
#define dap_null_json_serializer_h
#include "dap/protocol.h"
#include "dap/serialization.h"
#include "dap/types.h"
namespace dap {
namespace json {
struct NullDeserializer : public dap::Deserializer {
static NullDeserializer instance;
bool deserialize(dap::boolean*) const override { return false; }
bool deserialize(dap::integer*) const override { return false; }
bool deserialize(dap::number*) const override { return false; }
bool deserialize(dap::string*) const override { return false; }
bool deserialize(dap::object*) const override { return false; }
bool deserialize(dap::any*) const override { return false; }
size_t count() const override { return 0; }
bool array(const std::function<bool(dap::Deserializer*)>&) const override {
return false;
}
bool field(const std::string&,
const std::function<bool(dap::Deserializer*)>&) const override {
return false;
}
};
} // namespace json
} // namespace dap
#endif // dap_null_json_serializer_h

View File

@ -0,0 +1,259 @@
// 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()) {
return false;
}
*v = json()->GetInt();
return true;
}
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 val;
RapidDeserializer d(&(el->value));
if (!d.deserialize(&val)) {
return false;
}
(*v)[el->name.GetString()] = 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 {
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()->SetInt((int)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::null>()) {
} else {
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

138
src/rapid_json_serializer.h Normal file
View File

@ -0,0 +1,138 @@
// 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.
#ifndef dap_rapid_json_serializer_h
#define dap_rapid_json_serializer_h
#include "dap/protocol.h"
#include "dap/serialization.h"
#include "dap/types.h"
#include <rapidjson/document.h>
namespace dap {
namespace json {
struct RapidDeserializer : public dap::Deserializer {
explicit RapidDeserializer(const std::string&);
~RapidDeserializer();
// dap::Deserializer compliance
bool deserialize(boolean* v) const override;
bool deserialize(integer* v) const override;
bool deserialize(number* v) const override;
bool deserialize(string* v) const override;
bool deserialize(object* v) const override;
bool deserialize(any* v) const override;
size_t count() const override;
bool array(const std::function<bool(dap::Deserializer*)>&) const override;
bool field(const std::string& name,
const std::function<bool(dap::Deserializer*)>&) const override;
// Unhide base overloads
template <typename T>
inline bool field(const std::string& name, T* v) {
return dap::Deserializer::field(name, v);
}
template <typename T,
typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
inline bool deserialize(T* v) const {
return dap::Deserializer::deserialize(v);
}
template <typename T>
inline bool deserialize(dap::array<T>* v) const {
return dap::Deserializer::deserialize(v);
}
template <typename T>
inline bool deserialize(dap::optional<T>* v) const {
return dap::Deserializer::deserialize(v);
}
template <typename T0, typename... Types>
inline bool deserialize(dap::variant<T0, Types...>* v) const {
return dap::Deserializer::deserialize(v);
}
template <typename T>
inline bool field(const std::string& name, T* v) const {
return dap::Deserializer::deserialize(name, v);
}
inline rapidjson::Value* json() const { return (val == nullptr) ? doc : val; }
private:
RapidDeserializer(rapidjson::Value*);
rapidjson::Document* const doc = nullptr;
rapidjson::Value* const val = nullptr;
};
struct RapidSerializer : public dap::Serializer {
RapidSerializer();
~RapidSerializer();
std::string dump() const;
// dap::Serializer compliance
bool serialize(boolean v) override;
bool serialize(integer v) override;
bool serialize(number v) override;
bool serialize(const string& v) override;
bool serialize(const dap::object& v) override;
bool serialize(const any& v) override;
bool array(size_t count,
const std::function<bool(dap::Serializer*)>&) override;
bool object(const std::function<bool(dap::FieldSerializer*)>&) override;
void remove() override;
// Unhide base overloads
template <typename T,
typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
inline bool serialize(const T& v) {
return dap::Serializer::serialize(v);
}
template <typename T>
inline bool serialize(const dap::array<T>& v) {
return dap::Serializer::serialize(v);
}
template <typename T>
inline bool serialize(const dap::optional<T>& v) {
return dap::Serializer::serialize(v);
}
template <typename T0, typename... Types>
inline bool serialize(const dap::variant<T0, Types...>& v) {
return dap::Serializer::serialize(v);
}
inline bool serialize(const char* v) { return dap::Serializer::serialize(v); }
inline rapidjson::Value* json() const { return (val == nullptr) ? doc : val; }
private:
RapidSerializer(rapidjson::Value*, rapidjson::Document::AllocatorType&);
rapidjson::Document* const doc = nullptr;
rapidjson::Value* const val = nullptr;
rapidjson::Document::AllocatorType& allocator;
bool removed = false;
};
} // namespace json
} // namespace dap
#endif // dap_rapid_json_serializer_h

View File

@ -302,7 +302,7 @@ std::shared_ptr<ReaderWriter> Socket::connect(const char* address,
timeval tv; timeval tv;
tv.tv_sec = microseconds / 1000000; tv.tv_sec = microseconds / 1000000;
tv.tv_usec = microseconds - (tv.tv_sec * 1000000); tv.tv_usec = microseconds - static_cast<uint32_t>(tv.tv_sec * 1000000);
res = select(static_cast<int>(socket + 1), nullptr, &fdset, nullptr, &tv); res = select(static_cast<int>(socket + 1), nullptr, &fdset, nullptr, &tv);
if (res > 0 && !errored(socket) && setBlocking(socket, true)) { if (res > 0 && !errored(socket) && setBlocking(socket, true)) {
out = shared; out = shared;

View File

@ -130,7 +130,7 @@ const TypeInfo* TypeOf<null>::type() {
} }
void TypeInfo::deleteOnExit(TypeInfo* ti) { void TypeInfo::deleteOnExit(TypeInfo* ti) {
return TypeInfos::get()->types.emplace_back(std::unique_ptr<TypeInfo>(ti)); TypeInfos::get()->types.emplace_back(std::unique_ptr<TypeInfo>(ti));
} }
void initialize() { void initialize() {