Explorar el Código

Added support for custom writer classes (closes #1088)

Benoit Blanchon hace 6 años
padre
commit
498a2e4c1e

+ 5 - 0
CHANGELOG.md

@@ -1,6 +1,11 @@
 ArduinoJson: change log
 =======================
 
+HEAD
+----
+
+* Added support for custom writer classes (issue #1088)
+
 v6.12.0 (2019-09-05)
 -------
 

+ 1 - 0
extras/tests/JsonSerializer/CMakeLists.txt

@@ -3,6 +3,7 @@
 # MIT License
 
 add_executable(JsonSerializerTests
+	CustomWriter.cpp
 	JsonArray.cpp
 	JsonArrayPretty.cpp
 	JsonObject.cpp

+ 41 - 0
extras/tests/JsonSerializer/CustomWriter.cpp

@@ -0,0 +1,41 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2019
+// MIT License
+
+#include <ArduinoJson.h>
+#include <catch.hpp>
+
+struct CustomWriter {
+  std::string str;
+
+  size_t write(uint8_t c) {
+    str.append(1, static_cast<char>(c));
+    return 1;
+  }
+
+  size_t write(const uint8_t *s, size_t n) {
+    str.append(reinterpret_cast<const char *>(s), n);
+    return n;
+  }
+};
+
+TEST_CASE("CustomWriter") {
+  DynamicJsonDocument doc(4096);
+  JsonArray array = doc.to<JsonArray>();
+  array.add(4);
+  array.add(2);
+
+  SECTION("serializeJson()") {
+    CustomWriter writer;
+    serializeJson(array, writer);
+
+    REQUIRE("[4,2]" == writer.str);
+  }
+
+  SECTION("serializeJsonPretty") {
+    CustomWriter writer;
+    serializeJsonPretty(array, writer);
+
+    REQUIRE("[\r\n  4,\r\n  2\r\n]" == writer.str);
+  }
+}

+ 3 - 3
extras/tests/TextFormatter/CMakeLists.txt

@@ -2,10 +2,10 @@
 # Copyright Benoit Blanchon 2014-2019
 # MIT License
 
-add_executable(JsonWriterTests 
+add_executable(TextFormatterTests 
 	writeFloat.cpp
 	writeString.cpp
 )
 
-target_link_libraries(JsonWriterTests catch)
-add_test(TextFormatter JsonWriterTests)
+target_link_libraries(TextFormatterTests catch)
+add_test(TextFormatter TextFormatterTests)

+ 9 - 0
src/ArduinoJson/Serialization/DynamicStringWriter.hpp

@@ -4,7 +4,9 @@
 
 #pragma once
 
+#include <ArduinoJson/Configuration.hpp>
 #include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Serialization/WriterSelector.hpp>
 
 #if ARDUINOJSON_ENABLE_ARDUINO_STRING
 #include <WString.h>
@@ -79,4 +81,11 @@ class DynamicStringWriter<std::basic_string<char, TCharTraits, TAllocator> > {
   string_type *_str;
 };
 #endif
+
+template <typename TDestination>
+struct WriterSelector<
+    TDestination,
+    typename enable_if<IsWriteableString<TDestination>::value>::type> {
+  typedef DynamicStringWriter<TDestination> writer_type;
+};
 }  // namespace ARDUINOJSON_NAMESPACE

+ 37 - 0
src/ArduinoJson/Serialization/PrintWriter.hpp

@@ -0,0 +1,37 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2019
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Serialization/WriterSelector.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class PrintWriter {
+ public:
+  explicit PrintWriter(Print& print) : _print(print) {}
+
+  size_t write(uint8_t c) {
+    return _print.write(c);
+  }
+
+  size_t write(const uint8_t* s, size_t n) {
+    return _print.write(s, n);
+  }
+
+ private:
+  // cannot be assigned
+  PrintWriter& operator=(const PrintWriter&);
+
+  Print& _print;
+};
+
+template <typename TDestination>
+struct WriterSelector<
+    TDestination,
+    typename enable_if<is_base_of<Print, TDestination>::value>::type> {
+  typedef PrintWriter writer_type;
+};
+}  // namespace ARDUINOJSON_NAMESPACE

+ 8 - 4
src/ArduinoJson/Serialization/StreamWriter.hpp

@@ -5,8 +5,7 @@
 #pragma once
 
 #include <ArduinoJson/Configuration.hpp>
-
-#if ARDUINOJSON_ENABLE_STD_STREAM
+#include <ArduinoJson/Serialization/WriterSelector.hpp>
 
 #include <ostream>
 
@@ -33,6 +32,11 @@ class StreamWriter {
 
   std::ostream& _os;
 };
-}  // namespace ARDUINOJSON_NAMESPACE
 
-#endif  // ARDUINOJSON_ENABLE_STD_STREAM
+template <typename TDestination>
+struct WriterSelector<
+    TDestination,
+    typename enable_if<is_base_of<std::ostream, TDestination>::value>::type> {
+  typedef StreamWriter writer_type;
+};
+}  // namespace ARDUINOJSON_NAMESPACE

+ 17 - 0
src/ArduinoJson/Serialization/WriterSelector.hpp

@@ -0,0 +1,17 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2019
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TDestination, typename Enable = void>
+struct WriterSelector {
+  // by default, assume destination implements the Writer concept
+  typedef TDestination& writer_type;
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE

+ 12 - 23
src/ArduinoJson/Serialization/serialize.hpp

@@ -4,6 +4,7 @@
 
 #pragma once
 
+#include <ArduinoJson/Configuration.hpp>
 #include <ArduinoJson/Serialization/DynamicStringWriter.hpp>
 #include <ArduinoJson/Serialization/StaticStringWriter.hpp>
 
@@ -11,30 +12,26 @@
 #include <ArduinoJson/Serialization/StreamWriter.hpp>
 #endif
 
+#if ARDUINOJSON_ENABLE_ARDUINO_PRINT
+#include <ArduinoJson/Serialization/PrintWriter.hpp>
+#endif
+
 namespace ARDUINOJSON_NAMESPACE {
 
 template <template <typename> class TSerializer, typename TSource,
-          typename TDestination>
-size_t doSerialize(const TSource &source, TDestination &destination) {
-  TSerializer<TDestination> serializer(destination);
+          typename TWriter>
+size_t doSerialize(const TSource &source, TWriter &writer) {
+  TSerializer<TWriter> serializer(writer);
   source.accept(serializer);
   return serializer.bytesWritten();
 }
 
-#if ARDUINOJSON_ENABLE_STD_STREAM
-template <template <typename> class TSerializer, typename TSource>
-size_t serialize(const TSource &source, std::ostream &destination) {
-  StreamWriter writer(destination);
+template <template <typename> class TSerializer, typename TSource,
+          typename TDestination>
+size_t serialize(const TSource &source, TDestination &destination) {
+  typename WriterSelector<TDestination>::writer_type writer(destination);
   return doSerialize<TSerializer>(source, writer);
 }
-#endif
-
-#if ARDUINOJSON_ENABLE_ARDUINO_PRINT
-template <template <typename> class TSerializer, typename TSource>
-size_t serialize(const TSource &source, Print &destination) {
-  return doSerialize<TSerializer>(source, destination);
-}
-#endif
 
 template <template <typename> class TSerializer, typename TSource>
 size_t serialize(const TSource &source, char *buffer, size_t bufferSize) {
@@ -48,12 +45,4 @@ size_t serialize(const TSource &source, char (&buffer)[N]) {
   return doSerialize<TSerializer>(source, writer);
 }
 
-template <template <typename> class TSerializer, typename TSource,
-          typename TString>
-typename enable_if<IsWriteableString<TString>::value, size_t>::type serialize(
-    const TSource &source, TString &str) {
-  DynamicStringWriter<TString> writer(str);
-  return doSerialize<TSerializer>(source, writer);
-}
-
 }  // namespace ARDUINOJSON_NAMESPACE