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
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a41d6ae..2ec3ac0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -65,13 +65,33 @@
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
###########################################################
set(CPPDAP_LIST
${CPPDAP_SRC_DIR}/content_stream.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}/null_json_serializer.cpp
${CPPDAP_SRC_DIR}/protocol_events.cpp
${CPPDAP_SRC_DIR}/protocol_requests.cpp
${CPPDAP_SRC_DIR}/protocol_response.cpp
@@ -117,6 +137,11 @@
)
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
if(CPPDAP_WARNINGS_AS_ERRORS)
if(MSVC)
@@ -151,9 +176,7 @@
# dap
add_library(cppdap STATIC ${CPPDAP_LIST})
-set_target_properties(cppdap PROPERTIES
- POSITION_INDEPENDENT_CODE 1
-)
+set_target_properties(cppdap PROPERTIES POSITION_INDEPENDENT_CODE 1)
target_include_directories(cppdap PRIVATE "${CPPDAP_JSON_DIR}/include/")
diff --git a/src/chan.h b/src/chan.h
index c4183c2..f2345e9 100644
--- a/src/chan.h
+++ b/src/chan.h
@@ -87,4 +87,4 @@
} // namespace dap
-#endif // dap_chan_h
\ No newline at end of file
+#endif // dap_chan_h
diff --git a/src/io.cpp b/src/io.cpp
index 04db817..3ee972e 100644
--- a/src/io.cpp
+++ b/src/io.cpp
@@ -145,7 +145,7 @@
const bool closable;
std::mutex readMutex;
std::mutex writeMutex;
- std::atomic<bool> closed = { false };
+ std::atomic<bool> closed = {false};
};
class ReaderSpy : public dap::Reader {
@@ -254,4 +254,4 @@
return w->write(buf, strlen(buf));
}
-} // namespace dap
\ No newline at end of file
+} // namespace dap
diff --git a/src/json_serializer.h b/src/json_serializer.h
index 4ae4e11..9bc26d5 100644
--- a/src/json_serializer.h
+++ b/src/json_serializer.h
@@ -1,4 +1,4 @@
-// Copyright 2019 Google LLC
+// 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.
@@ -15,119 +15,28 @@
#ifndef dap_json_serializer_h
#define dap_json_serializer_h
-#include "dap/protocol.h"
-#include "dap/serialization.h"
-#include "dap/types.h"
-
-#include <nlohmann/json_fwd.hpp>
+#if defined(CPPDAP_JSON_NLOHMANN)
+#include "nlohmann_json_serializer.h"
+#elif defined(CPPDAP_JSON_RAPID)
+#include "rapid_json_serializer.h"
+#else
+#error "Unrecognised cppdap JSON library"
+#endif
namespace dap {
namespace json {
-struct Deserializer : public dap::Deserializer {
- explicit Deserializer(const std::string&);
- ~Deserializer();
-
- // 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:
- 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;
-};
+#if defined(CPPDAP_JSON_NLOHMANN)
+using Deserializer = NlohmannDeserializer;
+using Serializer = NlohmannSerializer;
+#elif defined(CPPDAP_JSON_RAPID)
+using Deserializer = RapidDeserializer;
+using Serializer = RapidSerializer;
+#else
+#error "Unrecognised cppdap JSON library"
+#endif
} // namespace json
} // namespace dap
-#endif // dap_json_serializer_h
\ No newline at end of file
+#endif // dap_json_serializer_h
diff --git a/src/json_serializer.cpp b/src/nlohmann_json_serializer.cpp
similarity index 61%
rename from src/json_serializer.cpp
rename to src/nlohmann_json_serializer.cpp
index 9d44dc1..7aa0399 100644
--- a/src/json_serializer.cpp
+++ b/src/nlohmann_json_serializer.cpp
@@ -12,55 +12,32 @@
// See the License for the specific language governing permissions and
// 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
// fired in this file.
#define JSON_NOEXCEPTION 1
#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 json {
-Deserializer::Deserializer(const std::string& str)
+NlohmannDeserializer::NlohmannDeserializer(const std::string& str)
: json(new nlohmann::json(nlohmann::json::parse(str, nullptr, false))),
ownsJson(true) {}
-Deserializer::Deserializer(const nlohmann::json* json)
+NlohmannDeserializer::NlohmannDeserializer(const nlohmann::json* json)
: json(json), ownsJson(false) {}
-Deserializer::~Deserializer() {
+NlohmannDeserializer::~NlohmannDeserializer() {
if (ownsJson) {
delete json;
}
}
-bool Deserializer::deserialize(dap::boolean* v) const {
+bool NlohmannDeserializer::deserialize(dap::boolean* v) const {
if (!json->is_boolean()) {
return false;
}
@@ -68,7 +45,7 @@
return true;
}
-bool Deserializer::deserialize(dap::integer* v) const {
+bool NlohmannDeserializer::deserialize(dap::integer* v) const {
if (!json->is_number_integer()) {
return false;
}
@@ -76,7 +53,7 @@
return true;
}
-bool Deserializer::deserialize(dap::number* v) const {
+bool NlohmannDeserializer::deserialize(dap::number* v) const {
if (!json->is_number()) {
return false;
}
@@ -84,7 +61,7 @@
return true;
}
-bool Deserializer::deserialize(dap::string* v) const {
+bool NlohmannDeserializer::deserialize(dap::string* v) const {
if (!json->is_string()) {
return false;
}
@@ -92,10 +69,10 @@
return true;
}
-bool Deserializer::deserialize(dap::object* v) const {
+bool NlohmannDeserializer::deserialize(dap::object* v) const {
v->reserve(json->size());
for (auto& el : json->items()) {
- Deserializer d(&el.value());
+ NlohmannDeserializer d(&el.value());
dap::any val;
if (!d.deserialize(&val)) {
return false;
@@ -105,7 +82,7 @@
return true;
}
-bool Deserializer::deserialize(dap::any* v) const {
+bool NlohmannDeserializer::deserialize(dap::any* v) const {
if (json->is_boolean()) {
*v = dap::boolean(json->get<bool>());
} else if (json->is_number_float()) {
@@ -122,17 +99,17 @@
return true;
}
-size_t Deserializer::count() const {
+size_t NlohmannDeserializer::count() const {
return json->size();
}
-bool Deserializer::array(
+bool NlohmannDeserializer::array(
const std::function<bool(dap::Deserializer*)>& cb) const {
if (!json->is_array()) {
return false;
}
for (size_t i = 0; i < json->size(); i++) {
- Deserializer d(&(*json)[i]);
+ NlohmannDeserializer d(&(*json)[i]);
if (!cb(&d)) {
return false;
}
@@ -140,7 +117,7 @@
return true;
}
-bool Deserializer::field(
+bool NlohmannDeserializer::field(
const std::string& name,
const std::function<bool(dap::Deserializer*)>& cb) const {
if (!json->is_structured()) {
@@ -151,47 +128,49 @@
return cb(&NullDeserializer::instance);
}
auto obj = *it;
- Deserializer d(&obj);
+ NlohmannDeserializer d(&obj);
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) {
delete json;
}
}
-std::string Serializer::dump() const {
+std::string NlohmannSerializer::dump() const {
return json->dump();
}
-bool Serializer::serialize(dap::boolean v) {
+bool NlohmannSerializer::serialize(dap::boolean v) {
*json = (bool)v;
return true;
}
-bool Serializer::serialize(dap::integer v) {
+bool NlohmannSerializer::serialize(dap::integer v) {
*json = (int)v;
return true;
}
-bool Serializer::serialize(dap::number v) {
+bool NlohmannSerializer::serialize(dap::number v) {
*json = (double)v;
return true;
}
-bool Serializer::serialize(const dap::string& v) {
+bool NlohmannSerializer::serialize(const dap::string& v) {
*json = v;
return true;
}
-bool Serializer::serialize(const dap::object& v) {
+bool NlohmannSerializer::serialize(const dap::object& v) {
for (auto& it : v) {
- Serializer s(&(*json)[it.first]);
+ NlohmannSerializer s(&(*json)[it.first]);
if (!s.serialize(it.second)) {
return false;
}
@@ -199,7 +178,7 @@
return true;
}
-bool Serializer::serialize(const dap::any& v) {
+bool NlohmannSerializer::serialize(const dap::any& v) {
if (v.is<dap::boolean>()) {
*json = (bool)v.get<dap::boolean>();
} else if (v.is<dap::integer>()) {
@@ -216,11 +195,12 @@
return true;
}
-bool Serializer::array(size_t count,
- const std::function<bool(dap::Serializer*)>& cb) {
+bool NlohmannSerializer::array(
+ size_t count,
+ const std::function<bool(dap::Serializer*)>& cb) {
*json = std::vector<int>();
for (size_t i = 0; i < count; i++) {
- Serializer s(&(*json)[i]);
+ NlohmannSerializer s(&(*json)[i]);
if (!cb(&s)) {
return false;
}
@@ -228,13 +208,14 @@
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 {
nlohmann::json* const json;
FS(nlohmann::json* json) : json(json) {}
bool field(const std::string& name, const SerializeFunc& cb) override {
- Serializer s(&(*json)[name]);
+ NlohmannSerializer s(&(*json)[name]);
auto res = cb(&s);
if (s.removed) {
json->erase(name);
@@ -248,7 +229,7 @@
return cb(&fs);
}
-void Serializer::remove() {
+void NlohmannSerializer::remove() {
removed = true;
}
diff --git a/src/nlohmann_json_serializer.h b/src/nlohmann_json_serializer.h
new file mode 100644
index 0000000..f75fe78
--- /dev/null
+++ b/src/nlohmann_json_serializer.h
@@ -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
\ No newline at end of file
diff --git a/src/null_json_serializer.cpp b/src/null_json_serializer.cpp
new file mode 100644
index 0000000..5aa5a03
--- /dev/null
+++ b/src/null_json_serializer.cpp
@@ -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
diff --git a/src/null_json_serializer.h b/src/null_json_serializer.h
new file mode 100644
index 0000000..c92b99a
--- /dev/null
+++ b/src/null_json_serializer.h
@@ -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
diff --git a/src/rapid_json_serializer.cpp b/src/rapid_json_serializer.cpp
new file mode 100644
index 0000000..35cf7e5
--- /dev/null
+++ b/src/rapid_json_serializer.cpp
@@ -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
diff --git a/src/rapid_json_serializer.h b/src/rapid_json_serializer.h
new file mode 100644
index 0000000..6e83384
--- /dev/null
+++ b/src/rapid_json_serializer.h
@@ -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
diff --git a/src/socket.cpp b/src/socket.cpp
index 2e54580..998fed9 100644
--- a/src/socket.cpp
+++ b/src/socket.cpp
@@ -302,7 +302,7 @@
timeval tv;
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);
if (res > 0 && !errored(socket) && setBlocking(socket, true)) {
out = shared;
diff --git a/src/typeof.cpp b/src/typeof.cpp
index a5685d3..055421c 100644
--- a/src/typeof.cpp
+++ b/src/typeof.cpp
@@ -130,7 +130,7 @@
}
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() {