mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	serializeMsgPack(doc, p, n) doesn't add terminator anymore (fixes #1545)
This commit is contained in:
		| @@ -16,6 +16,8 @@ HEAD | |||||||
| * Simplified `JsonVariant::as<T>()` to always return `T` (see below) | * Simplified `JsonVariant::as<T>()` to always return `T` (see below) | ||||||
| * Updated folders list in `.mbedignore` (PR #1515 by @AGlass0fMilk) | * Updated folders list in `.mbedignore` (PR #1515 by @AGlass0fMilk) | ||||||
| * Fixed member-call-on-null-pointer in `getMember()` when array is empty | * Fixed member-call-on-null-pointer in `getMember()` when array is empty | ||||||
|  | * `serializeMsgPack(doc, buffer, size)` doesn't add null-terminator anymore (issue #1545) | ||||||
|  | * `serializeJson(doc, buffer, size)` adds null-terminator only if there is enough room | ||||||
|  |  | ||||||
| > ### BREAKING CHANGES | > ### BREAKING CHANGES | ||||||
| > | > | ||||||
|   | |||||||
| @@ -8,12 +8,15 @@ | |||||||
|  |  | ||||||
| static void checkObject(const JsonObject obj, const std::string &expected) { | static void checkObject(const JsonObject obj, const std::string &expected) { | ||||||
|   char actual[256]; |   char actual[256]; | ||||||
|  |   memset(actual, '!', sizeof(actual)); | ||||||
|  |  | ||||||
|   size_t actualLen = serializeJson(obj, actual); |   size_t actualLen = serializeJson(obj, actual); | ||||||
|   size_t measuredLen = measureJson(obj); |   size_t measuredLen = measureJson(obj); | ||||||
|  |  | ||||||
|   REQUIRE(expected == actual); |  | ||||||
|   REQUIRE(expected.size() == actualLen); |  | ||||||
|   REQUIRE(expected.size() == measuredLen); |   REQUIRE(expected.size() == measuredLen); | ||||||
|  |   REQUIRE(expected.size() == actualLen); | ||||||
|  |   REQUIRE(actual[actualLen] == 0);  // serializeJson() adds a null terminator | ||||||
|  |   REQUIRE(expected == actual); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("serializeJson(JsonObject)") { | TEST_CASE("serializeJson(JsonObject)") { | ||||||
|   | |||||||
| @@ -39,15 +39,15 @@ void common_tests(StringWriter& sb, const String& output) { | |||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("StaticStringWriter") { | TEST_CASE("StaticStringWriter") { | ||||||
|   char output[20]; |   char output[20] = {0}; | ||||||
|   StaticStringWriter sb(output, sizeof(output)); |   StaticStringWriter sb(output, sizeof(output)); | ||||||
|  |  | ||||||
|   common_tests(sb, static_cast<const char*>(output)); |   common_tests(sb, static_cast<const char*>(output)); | ||||||
|  |  | ||||||
|   SECTION("OverCapacity") { |   SECTION("OverCapacity") { | ||||||
|     REQUIRE(19 == print(sb, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); |     REQUIRE(20 == print(sb, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); | ||||||
|     REQUIRE(0 == print(sb, "ABC")); |     REQUIRE(0 == print(sb, "ABC")); | ||||||
|     REQUIRE(std::string("ABCDEFGHIJKLMNOPQRS") == output); |     REQUIRE("ABCDEFGHIJKLMNOPQRST" == std::string(output, 20)); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -29,19 +29,31 @@ TEST_CASE("serialize MsgPack to various destination types") { | |||||||
|     REQUIRE(expected_length == len); |     REQUIRE(expected_length == len); | ||||||
|     } */ |     } */ | ||||||
|  |  | ||||||
|   SECTION("char[]") { |   SECTION("char[] larger than needed") { | ||||||
|     char result[64]; |     char result[64]; | ||||||
|  |     memset(result, 42, sizeof(result)); | ||||||
|     size_t len = serializeMsgPack(object, result); |     size_t len = serializeMsgPack(object, result); | ||||||
|  |  | ||||||
|     REQUIRE(std::string(expected_result) == result); |  | ||||||
|     REQUIRE(expected_length == len); |     REQUIRE(expected_length == len); | ||||||
|  |     REQUIRE(std::string(expected_result, len) == std::string(result, len)); | ||||||
|  |     REQUIRE(result[len] == 42); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("char[] of the right size") {  // #1545 | ||||||
|  |     char result[13]; | ||||||
|  |     size_t len = serializeMsgPack(object, result); | ||||||
|  |  | ||||||
|  |     REQUIRE(expected_length == len); | ||||||
|  |     REQUIRE(std::string(expected_result, len) == std::string(result, len)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("char*") { |   SECTION("char*") { | ||||||
|     char result[64]; |     char result[64]; | ||||||
|  |     memset(result, 42, sizeof(result)); | ||||||
|     size_t len = serializeMsgPack(object, result, 64); |     size_t len = serializeMsgPack(object, result, 64); | ||||||
|  |  | ||||||
|     REQUIRE(std::string(expected_result) == result); |  | ||||||
|     REQUIRE(expected_length == len); |     REQUIRE(expected_length == len); | ||||||
|  |     REQUIRE(std::string(expected_result, len) == std::string(result, len)); | ||||||
|  |     REQUIRE(result[len] == 42); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ using namespace ARDUINOJSON_NAMESPACE; | |||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| void checkWriteInteger(T value, std::string expected) { | void checkWriteInteger(T value, std::string expected) { | ||||||
|   char output[1024]; |   char output[64] = {0}; | ||||||
|   StaticStringWriter sb(output, sizeof(output)); |   StaticStringWriter sb(output, sizeof(output)); | ||||||
|   TextFormatter<StaticStringWriter> writer(sb); |   TextFormatter<StaticStringWriter> writer(sb); | ||||||
|   writer.writeInteger<T>(value); |   writer.writeInteger<T>(value); | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
| using namespace ARDUINOJSON_NAMESPACE; | using namespace ARDUINOJSON_NAMESPACE; | ||||||
|  |  | ||||||
| void check(const char* input, std::string expected) { | void check(const char* input, std::string expected) { | ||||||
|   char output[1024]; |   char output[64] = {0}; | ||||||
|   StaticStringWriter sb(output, sizeof(output)); |   StaticStringWriter sb(output, sizeof(output)); | ||||||
|   TextFormatter<StaticStringWriter> writer(sb); |   TextFormatter<StaticStringWriter> writer(sb); | ||||||
|   writer.writeString(input); |   writer.writeString(input); | ||||||
|   | |||||||
| @@ -14,6 +14,8 @@ namespace ARDUINOJSON_NAMESPACE { | |||||||
| template <typename TWriter> | template <typename TWriter> | ||||||
| class JsonSerializer : public Visitor<size_t> { | class JsonSerializer : public Visitor<size_t> { | ||||||
|  public: |  public: | ||||||
|  |   static const bool producesText = true; | ||||||
|  |  | ||||||
|   JsonSerializer(TWriter writer) : _formatter(writer) {} |   JsonSerializer(TWriter writer) : _formatter(writer) {} | ||||||
|  |  | ||||||
|   FORCE_INLINE size_t visitArray(const CollectionData &array) { |   FORCE_INLINE size_t visitArray(const CollectionData &array) { | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> { | |||||||
|   typedef JsonSerializer<TWriter> base; |   typedef JsonSerializer<TWriter> base; | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
|   PrettyJsonSerializer(TWriter &writer) : base(writer), _nesting(0) {} |   PrettyJsonSerializer(TWriter writer) : base(writer), _nesting(0) {} | ||||||
|  |  | ||||||
|   size_t visitArray(const CollectionData &array) { |   size_t visitArray(const CollectionData &array) { | ||||||
|     VariantSlot *slot = array.head(); |     VariantSlot *slot = array.head(); | ||||||
|   | |||||||
| @@ -17,6 +17,8 @@ namespace ARDUINOJSON_NAMESPACE { | |||||||
| template <typename TWriter> | template <typename TWriter> | ||||||
| class MsgPackSerializer : public Visitor<size_t> { | class MsgPackSerializer : public Visitor<size_t> { | ||||||
|  public: |  public: | ||||||
|  |   static const bool producesText = false; | ||||||
|  |  | ||||||
|   MsgPackSerializer(TWriter writer) : _writer(writer) {} |   MsgPackSerializer(TWriter writer) : _writer(writer) {} | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   | |||||||
| @@ -8,18 +8,14 @@ | |||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| // A Print implementation that allows to write in a char[] |  | ||||||
| class StaticStringWriter { | class StaticStringWriter { | ||||||
|  public: |  public: | ||||||
|   StaticStringWriter(char *buf, size_t size) : end(buf + size - 1), p(buf) { |   StaticStringWriter(char *buf, size_t size) : end(buf + size), p(buf) {} | ||||||
|     *p = '\0'; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t write(uint8_t c) { |   size_t write(uint8_t c) { | ||||||
|     if (p >= end) |     if (p >= end) | ||||||
|       return 0; |       return 0; | ||||||
|     *p++ = static_cast<char>(c); |     *p++ = static_cast<char>(c); | ||||||
|     *p = '\0'; |  | ||||||
|     return 1; |     return 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -29,7 +25,6 @@ class StaticStringWriter { | |||||||
|       *p++ = static_cast<char>(*s++); |       *p++ = static_cast<char>(*s++); | ||||||
|       n--; |       n--; | ||||||
|     } |     } | ||||||
|     *p = '\0'; |  | ||||||
|     return size_t(p - begin); |     return size_t(p - begin); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -23,11 +23,23 @@ size_t serialize(const TSource &source, TDestination &destination) { | |||||||
| } | } | ||||||
|  |  | ||||||
| template <template <typename> class TSerializer, typename TSource> | template <template <typename> class TSerializer, typename TSource> | ||||||
| size_t serialize(const TSource &source, void *buffer, size_t bufferSize) { | typename enable_if<!TSerializer<StaticStringWriter>::producesText, size_t>::type | ||||||
|  | serialize(const TSource &source, void *buffer, size_t bufferSize) { | ||||||
|   StaticStringWriter writer(reinterpret_cast<char *>(buffer), bufferSize); |   StaticStringWriter writer(reinterpret_cast<char *>(buffer), bufferSize); | ||||||
|   return doSerialize<TSerializer>(source, writer); |   return doSerialize<TSerializer>(source, writer); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | template <template <typename> class TSerializer, typename TSource> | ||||||
|  | typename enable_if<TSerializer<StaticStringWriter>::producesText, size_t>::type | ||||||
|  | serialize(const TSource &source, void *buffer, size_t bufferSize) { | ||||||
|  |   StaticStringWriter writer(reinterpret_cast<char *>(buffer), bufferSize); | ||||||
|  |   size_t n = doSerialize<TSerializer>(source, writer); | ||||||
|  |   // add null-terminator for text output (not counted in the size) | ||||||
|  |   if (n < bufferSize) | ||||||
|  |     reinterpret_cast<char *>(buffer)[n] = 0; | ||||||
|  |   return n; | ||||||
|  | } | ||||||
|  |  | ||||||
| template <template <typename> class TSerializer, typename TSource, | template <template <typename> class TSerializer, typename TSource, | ||||||
|           typename TChar, size_t N> |           typename TChar, size_t N> | ||||||
| #if defined _MSC_VER && _MSC_VER < 1900 | #if defined _MSC_VER && _MSC_VER < 1900 | ||||||
| @@ -36,8 +48,7 @@ typename enable_if<sizeof(remove_reference<TChar>::type) == 1, size_t>::type | |||||||
| typename enable_if<sizeof(TChar) == 1, size_t>::type | typename enable_if<sizeof(TChar) == 1, size_t>::type | ||||||
| #endif | #endif | ||||||
| serialize(const TSource &source, TChar (&buffer)[N]) { | serialize(const TSource &source, TChar (&buffer)[N]) { | ||||||
|   StaticStringWriter writer(reinterpret_cast<char *>(buffer), N); |   return serialize<TSerializer>(source, buffer, N); | ||||||
|   return doSerialize<TSerializer>(source, writer); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user