Forráskód Böngészése

Added support for `basic_string<char, traits, allocator>` (closes #1045)

Benoit Blanchon 6 éve
szülő
commit
1e9cc285bb

+ 1 - 0
CHANGELOG.md

@@ -5,6 +5,7 @@ HEAD
 ----
 
 * Added `measureJson()` to the `ArduinoJson` namespace (PR #1069 by @nomis)
+* Added support for `basic_string<char, traits, allocator>` (issue #1045)
 * Fixed example `JsonConfigFile.ino` for ESP8266
 * Include `Arduino.h` if `ARDUINO` is defined (PR #1071 by @nomis)
 

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

@@ -54,13 +54,16 @@ class DynamicStringWriter<String> {
 #endif
 
 #if ARDUINOJSON_ENABLE_STD_STRING
-template <>
-struct IsWriteableString<std::string> : true_type {};
+template <typename TCharTraits, typename TAllocator>
+struct IsWriteableString<std::basic_string<char, TCharTraits, TAllocator> >
+    : true_type {};
+
+template <typename TCharTraits, typename TAllocator>
+class DynamicStringWriter<std::basic_string<char, TCharTraits, TAllocator> > {
+  typedef std::basic_string<char, TCharTraits, TAllocator> string_type;
 
-template <>
-class DynamicStringWriter<std::string> {
  public:
-  DynamicStringWriter(std::string &str) : _str(&str) {}
+  DynamicStringWriter(string_type &str) : _str(&str) {}
 
   size_t write(uint8_t c) {
     _str->operator+=(static_cast<char>(c));
@@ -73,7 +76,7 @@ class DynamicStringWriter<std::string> {
   }
 
  private:
-  std::string *_str;
+  string_type *_str;
 };
 #endif
 }  // namespace ARDUINOJSON_NAMESPACE

+ 11 - 6
src/ArduinoJson/Strings/StlStringAdapter.hpp

@@ -8,9 +8,10 @@
 
 namespace ARDUINOJSON_NAMESPACE {
 
+template <typename TString>
 class StlStringAdapter {
  public:
-  StlStringAdapter(const std::string& str) : _str(&str) {}
+  StlStringAdapter(const TString& str) : _str(&str) {}
 
   char* save(MemoryPool* pool) const {
     size_t n = _str->length() + 1;
@@ -46,14 +47,18 @@ class StlStringAdapter {
   }
 
  private:
-  const std::string* _str;
+  const TString* _str;
 };
 
-template <>
-struct IsString<std::string> : true_type {};
+template <typename TCharTraits, typename TAllocator>
+struct IsString<std::basic_string<char, TCharTraits, TAllocator> > : true_type {
+};
 
-inline StlStringAdapter adaptString(const std::string& str) {
-  return StlStringAdapter(str);
+template <typename TCharTraits, typename TAllocator>
+inline StlStringAdapter<std::basic_string<char, TCharTraits, TAllocator> >
+adaptString(const std::basic_string<char, TCharTraits, TAllocator>& str) {
+  return StlStringAdapter<std::basic_string<char, TCharTraits, TAllocator> >(
+      str);
 }
 
 }  // namespace ARDUINOJSON_NAMESPACE

+ 30 - 2
test/Misc/StringAdapters.cpp

@@ -4,6 +4,7 @@
 
 #include <ArduinoJson.h>
 #include <catch.hpp>
+#include "custom_string.hpp"
 
 using namespace ARDUINOJSON_NAMESPACE;
 
@@ -31,9 +32,9 @@ TEST_CASE("ConstRamStringAdapter") {
   }
 }
 
-TEST_CASE("StlString") {
+TEST_CASE("std::string") {
   std::string str("bravo");
-  StlStringAdapter adapter(str);
+  StlStringAdapter<std::string> adapter = adaptString(str);
 
   REQUIRE(adapter.compare(NULL) > 0);
   REQUIRE(adapter.compare("alpha") > 0);
@@ -43,3 +44,30 @@ TEST_CASE("StlString") {
   REQUIRE(adapter.equals("bravo"));
   REQUIRE_FALSE(adapter.equals("charlie"));
 }
+
+TEST_CASE("custom_string") {
+  custom_string str("bravo");
+  StlStringAdapter<custom_string> adapter = adaptString(str);
+
+  REQUIRE(adapter.compare(NULL) > 0);
+  REQUIRE(adapter.compare("alpha") > 0);
+  REQUIRE(adapter.compare("bravo") == 0);
+  REQUIRE(adapter.compare("charlie") < 0);
+
+  REQUIRE(adapter.equals("bravo"));
+  REQUIRE_FALSE(adapter.equals("charlie"));
+}
+
+TEST_CASE("IsString<T>") {
+  SECTION("std::string") {
+    REQUIRE(IsString<std::string>::value == true);
+  }
+
+  SECTION("basic_string<wchar_t>") {
+    REQUIRE(IsString<std::basic_string<wchar_t> >::value == false);
+  }
+
+  SECTION("custom_string") {
+    REQUIRE(IsString<custom_string>::value == true);
+  }
+}

+ 24 - 1
test/Misc/StringWriter.cpp

@@ -4,6 +4,7 @@
 
 #include <ArduinoJson.h>
 #include <catch.hpp>
+#include "custom_string.hpp"
 
 using namespace ARDUINOJSON_NAMESPACE;
 
@@ -48,8 +49,30 @@ TEST_CASE("StaticStringWriter") {
   }
 }
 
-TEST_CASE("DynamicStringWriter") {
+TEST_CASE("DynamicStringWriter<std::string>") {
   std::string output;
   DynamicStringWriter<std::string> sb(output);
   common_tests(sb, output);
 }
+
+TEST_CASE("DynamicStringWriter<custom_string>") {
+  custom_string output;
+  DynamicStringWriter<custom_string> sb(output);
+
+  REQUIRE(4 == print(sb, "ABCD"));
+  REQUIRE("ABCD" == output);
+}
+
+TEST_CASE("IsWriteableString") {
+  SECTION("std::string") {
+    REQUIRE(IsWriteableString<std::string>::value == true);
+  }
+
+  SECTION("custom_string") {
+    REQUIRE(IsWriteableString<custom_string>::value == true);
+  }
+
+  SECTION("basic_string<wchar_t>") {
+    REQUIRE(IsWriteableString<std::basic_string<wchar_t> >::value == false);
+  }
+}

+ 14 - 0
test/Misc/custom_string.hpp

@@ -0,0 +1,14 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2019
+// MIT License
+
+#pragma once
+
+#include <string>
+
+using namespace ARDUINOJSON_NAMESPACE;
+
+struct custom_char_traits : std::char_traits<char> {};
+struct custom_allocator : std::allocator<char> {};
+typedef std::basic_string<char, custom_char_traits, custom_allocator>
+    custom_string;