mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Renamed function RawJson() to serialized()
				
					
				
			This commit is contained in:
		
							
								
								
									
										18
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -6,11 +6,29 @@ HEAD | |||||||
|  |  | ||||||
| * Disabled lazy number deserialization (issue #772) | * Disabled lazy number deserialization (issue #772) | ||||||
| * Improved float serialization when `-fsingle-precision-constant` is used | * Improved float serialization when `-fsingle-precision-constant` is used | ||||||
|  | * Renamed function `RawJson()` to `serialized()` | ||||||
|  | * `serializeMsgPack()` now supports values marked with `serialized()` | ||||||
|  |  | ||||||
| > ### BREAKING CHANGES | > ### BREAKING CHANGES | ||||||
| > | > | ||||||
|  | > #### Non quoted strings | ||||||
|  | > | ||||||
| > Non quoted strings are now forbidden in values, but they are still allowed in keys. | > Non quoted strings are now forbidden in values, but they are still allowed in keys. | ||||||
| > For example, `{key:"value"}` is accepted, but `{key:value}` is not. | > For example, `{key:"value"}` is accepted, but `{key:value}` is not. | ||||||
|  | > | ||||||
|  | > #### Preformatted values | ||||||
|  | > | ||||||
|  | > Old code: | ||||||
|  | > | ||||||
|  | > ```c++ | ||||||
|  | > object["values"] = RawJson("[1,2,3,4]"); | ||||||
|  | > ``` | ||||||
|  | >  | ||||||
|  | > New code: | ||||||
|  | >  | ||||||
|  | > ```c++ | ||||||
|  | > object["values"] = serialized("[1,2,3,4]"); | ||||||
|  | > ``` | ||||||
|  |  | ||||||
| v6.1.0-beta | v6.1.0-beta | ||||||
| ----------- | ----------- | ||||||
|   | |||||||
| @@ -37,8 +37,9 @@ void setup() { | |||||||
|   // JsonBuffer. |   // JsonBuffer. | ||||||
|   obj["sensor"] = F("gps"); |   obj["sensor"] = F("gps"); | ||||||
|  |  | ||||||
|   // It works with RawJson too: |   // It works with serialized() too: | ||||||
|   obj["sensor"] = RawJson(F("\"gps\"")); |   obj["sensor"] = serialized(F("\"gps\"")); | ||||||
|  |   obj["sensor"] = serialized(F("\xA3gps"), 3); | ||||||
|  |  | ||||||
|   // You can compare the content of a JsonVariant to a Flash String |   // You can compare the content of a JsonVariant to a Flash String | ||||||
|   if (obj["sensor"] == F("gps")) { |   if (obj["sensor"] == F("gps")) { | ||||||
|   | |||||||
| @@ -41,8 +41,8 @@ void setup() { | |||||||
|   // WARNING: the content of the String will be duplicated in the JsonBuffer. |   // WARNING: the content of the String will be duplicated in the JsonBuffer. | ||||||
|   obj["sensor"] = sensor; |   obj["sensor"] = sensor; | ||||||
|  |  | ||||||
|   // It works with RawJson too: |   // It works with serialized() too: | ||||||
|   obj["sensor"] = RawJson(sensor); |   obj["sensor"] = serialized(sensor); | ||||||
|  |  | ||||||
|   // You can also concatenate strings |   // You can also concatenate strings | ||||||
|   // WARNING: the content of the String will be duplicated in the JsonBuffer. |   // WARNING: the content of the String will be duplicated in the JsonBuffer. | ||||||
|   | |||||||
| @@ -18,9 +18,13 @@ struct JsonObjectData; | |||||||
| union JsonVariantContent { | union JsonVariantContent { | ||||||
|   JsonFloat asFloat;         // used for double and float |   JsonFloat asFloat;         // used for double and float | ||||||
|   JsonUInt asInteger;        // used for bool, char, short, int and longs |   JsonUInt asInteger;        // used for bool, char, short, int and longs | ||||||
|   const char* asString;      // asString can be null |  | ||||||
|   JsonArrayData* asArray;    // asArray cannot be null |   JsonArrayData* asArray;    // asArray cannot be null | ||||||
|   JsonObjectData* asObject;  // asObject cannot be null |   JsonObjectData* asObject;  // asObject cannot be null | ||||||
|  |   const char* asString;      // asString can be null | ||||||
|  |   struct { | ||||||
|  |     const char* data; | ||||||
|  |     size_t size; | ||||||
|  |   } asRaw; | ||||||
| }; | }; | ||||||
| }  // namespace Internals | }  // namespace Internals | ||||||
| }  // namespace ArduinoJson | }  // namespace ArduinoJson | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
| #include "../JsonVariant.hpp" | #include "../JsonVariant.hpp" | ||||||
| #include "../Memory/JsonBuffer.hpp" | #include "../Memory/JsonBuffer.hpp" | ||||||
| #include "../Polyfills/type_traits.hpp" | #include "../Polyfills/type_traits.hpp" | ||||||
| #include "../Strings/StringTraits.hpp" | #include "../Strings/StringTypes.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace Internals { | namespace Internals { | ||||||
| @@ -21,30 +21,31 @@ struct ValueSaver { | |||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| template <typename Source> | // We duplicate all strings except const char* | ||||||
|  | template <typename TString> | ||||||
| struct ValueSaver< | struct ValueSaver< | ||||||
|     Source, typename enable_if<StringTraits<Source>::should_duplicate>::type> { |     TString, typename enable_if<IsString<TString>::value && | ||||||
|  |                                 !is_same<const char*, TString>::value>::type> { | ||||||
|   template <typename Destination> |   template <typename Destination> | ||||||
|   static bool save(JsonBuffer* buffer, Destination& dest, Source source) { |   static bool save(JsonBuffer* buffer, Destination& dest, TString source) { | ||||||
|     if (!StringTraits<Source>::is_null(source)) { |     const char* dup = makeString(source).save(buffer); | ||||||
|       typename StringTraits<Source>::duplicate_t dup = |     if (!dup) return false; | ||||||
|           StringTraits<Source>::duplicate(source, buffer); |     dest = dup; | ||||||
|       if (!dup) return false; |  | ||||||
|       dest = dup; |  | ||||||
|     } else { |  | ||||||
|       dest = reinterpret_cast<const char*>(0); |  | ||||||
|     } |  | ||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // const char*, const signed char*, const unsigned char* | // We duplicate all SerializedValue<T> except SerializedValue<const char*> | ||||||
| template <typename Char> | template <typename TString> | ||||||
| struct ValueSaver< | struct ValueSaver< | ||||||
|     Char*, typename enable_if<!StringTraits<Char*>::should_duplicate>::type> { |     const SerializedValue<TString>&, | ||||||
|  |     typename enable_if<!is_same<const char*, TString>::value>::type> { | ||||||
|   template <typename Destination> |   template <typename Destination> | ||||||
|   static bool save(JsonBuffer*, Destination& dest, Char* source) { |   static bool save(JsonBuffer* buffer, Destination& dest, | ||||||
|     dest = reinterpret_cast<const char*>(source); |                    const SerializedValue<TString>& source) { | ||||||
|  |     const char* dup = makeString(source.data(), source.size()).save(buffer); | ||||||
|  |     if (!dup) return false; | ||||||
|  |     dest = SerializedValue<const char*>(dup, source.size()); | ||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -19,19 +19,22 @@ class IndentedPrint { | |||||||
|     isNewLine = true; |     isNewLine = true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t print(char c) { |   size_t write(uint8_t c) { | ||||||
|     size_t n = 0; |     size_t n = 0; | ||||||
|     if (isNewLine) n += writeTabs(); |     if (isNewLine) n += writeTabs(); | ||||||
|     n += sink->print(c); |     n += sink->write(c); | ||||||
|     isNewLine = c == '\n'; |     isNewLine = c == '\n'; | ||||||
|     return n; |     return n; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t print(const char *s) { |   size_t write(const uint8_t *s, size_t n) { | ||||||
|     // TODO: optimize |     // TODO: optimize | ||||||
|     size_t n = 0; |     size_t bytesWritten = 0; | ||||||
|     while (*s) n += print(*s++); |     while (n > 0) { | ||||||
|     return n; |       bytesWritten += write(*s++); | ||||||
|  |       n--; | ||||||
|  |     } | ||||||
|  |     return bytesWritten; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Adds one level of indentation |   // Adds one level of indentation | ||||||
| @@ -57,7 +60,7 @@ class IndentedPrint { | |||||||
|  |  | ||||||
|   size_t writeTabs() { |   size_t writeTabs() { | ||||||
|     size_t n = 0; |     size_t n = 0; | ||||||
|     for (int i = 0; i < level * tabSize; i++) n += sink->print(' '); |     for (int i = 0; i < level * tabSize; i++) n += sink->write(' '); | ||||||
|     return n; |     return n; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,10 +11,10 @@ | |||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace Internals { | namespace Internals { | ||||||
|  |  | ||||||
| template <typename TPrint> | template <typename TWriter> | ||||||
| class JsonSerializer { | class JsonSerializer { | ||||||
|  public: |  public: | ||||||
|   JsonSerializer(TPrint &destination) : _writer(destination) {} |   JsonSerializer(TWriter &writer) : _writer(writer) {} | ||||||
|  |  | ||||||
|   void acceptFloat(JsonFloat value) { |   void acceptFloat(JsonFloat value) { | ||||||
|     _writer.writeFloat(value); |     _writer.writeFloat(value); | ||||||
| @@ -58,8 +58,9 @@ class JsonSerializer { | |||||||
|     _writer.writeString(value); |     _writer.writeString(value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void acceptRawJson(const char *value) { |   void acceptRawJson(const char *data, size_t n) { | ||||||
|     _writer.writeRaw(value); |     // TODO | ||||||
|  |     for (size_t i = 0; i < n; i++) _writer.writeRaw(data[i]); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void acceptNegativeInteger(JsonUInt value) { |   void acceptNegativeInteger(JsonUInt value) { | ||||||
| @@ -84,7 +85,7 @@ class JsonSerializer { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   JsonWriter<TPrint> _writer; |   JsonWriter<TWriter> _writer; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace Internals | }  // namespace Internals | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
|  | #include <string.h>  // for strlen | ||||||
| #include "../Data/JsonInteger.hpp" | #include "../Data/JsonInteger.hpp" | ||||||
| #include "../Numbers/FloatParts.hpp" | #include "../Numbers/FloatParts.hpp" | ||||||
| #include "../Polyfills/attributes.hpp" | #include "../Polyfills/attributes.hpp" | ||||||
| @@ -13,12 +14,12 @@ | |||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace Internals { | namespace Internals { | ||||||
|  |  | ||||||
| template <typename Print> | template <typename TWriter> | ||||||
| class JsonWriter { | class JsonWriter { | ||||||
|  public: |  public: | ||||||
|   explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {} |   explicit JsonWriter(TWriter &writer) : _writer(writer), _length(0) {} | ||||||
|  |  | ||||||
|   // Returns the number of bytes sent to the Print implementation. |   // Returns the number of bytes sent to the TWriter implementation. | ||||||
|   size_t bytesWritten() const { |   size_t bytesWritten() const { | ||||||
|     return _length; |     return _length; | ||||||
|   } |   } | ||||||
| @@ -45,7 +46,10 @@ class JsonWriter { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void writeBoolean(bool value) { |   void writeBoolean(bool value) { | ||||||
|     writeRaw(value ? "true" : "false"); |     if (value) | ||||||
|  |       writeRaw("true"); | ||||||
|  |     else | ||||||
|  |       writeRaw("false"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void writeString(const char *value) { |   void writeString(const char *value) { | ||||||
| @@ -98,45 +102,53 @@ class JsonWriter { | |||||||
|   template <typename UInt> |   template <typename UInt> | ||||||
|   void writeInteger(UInt value) { |   void writeInteger(UInt value) { | ||||||
|     char buffer[22]; |     char buffer[22]; | ||||||
|     char *end = buffer + sizeof(buffer) - 1; |     char *end = buffer + sizeof(buffer); | ||||||
|     char *ptr = end; |     char *begin = end; | ||||||
|  |  | ||||||
|     *ptr = 0; |     // write the string in reverse order | ||||||
|     do { |     do { | ||||||
|       *--ptr = char(value % 10 + '0'); |       *--begin = char(value % 10 + '0'); | ||||||
|       value = UInt(value / 10); |       value = UInt(value / 10); | ||||||
|     } while (value); |     } while (value); | ||||||
|  |  | ||||||
|     writeRaw(ptr); |     // and dump it in the right order | ||||||
|  |     writeRaw(begin, end); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void writeDecimals(uint32_t value, int8_t width) { |   void writeDecimals(uint32_t value, int8_t width) { | ||||||
|     // buffer should be big enough for all digits, the dot and the null |     // buffer should be big enough for all digits and the dot | ||||||
|     // terminator |  | ||||||
|     char buffer[16]; |     char buffer[16]; | ||||||
|     char *ptr = buffer + sizeof(buffer) - 1; |     char *end = buffer + sizeof(buffer); | ||||||
|  |     char *begin = end; | ||||||
|  |  | ||||||
|     // write the string in reverse order |     // write the string in reverse order | ||||||
|     *ptr = 0; |  | ||||||
|     while (width--) { |     while (width--) { | ||||||
|       *--ptr = char(value % 10 + '0'); |       *--begin = char(value % 10 + '0'); | ||||||
|       value /= 10; |       value /= 10; | ||||||
|     } |     } | ||||||
|     *--ptr = '.'; |     *--begin = '.'; | ||||||
|  |  | ||||||
|     // and dump it in the right order |     // and dump it in the right order | ||||||
|     writeRaw(ptr); |     writeRaw(begin, end); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void writeRaw(const char *s) { |   void writeRaw(const char *s) { | ||||||
|     _length += _sink.print(s); |     _length += _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s)); | ||||||
|  |   } | ||||||
|  |   void writeRaw(const char *begin, const char *end) { | ||||||
|  |     _length += _writer.write(reinterpret_cast<const uint8_t *>(begin), | ||||||
|  |                              static_cast<size_t>(end - begin)); | ||||||
|  |   } | ||||||
|  |   template <size_t N> | ||||||
|  |   void writeRaw(const char (&s)[N]) { | ||||||
|  |     _length += _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1); | ||||||
|   } |   } | ||||||
|   void writeRaw(char c) { |   void writeRaw(char c) { | ||||||
|     _length += _sink.print(c); |     _length += _writer.write(static_cast<uint8_t>(c)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   Print &_sink; |   TWriter &_writer; | ||||||
|   size_t _length; |   size_t _length; | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   | |||||||
| @@ -10,25 +10,28 @@ namespace ArduinoJson { | |||||||
| namespace Internals { | namespace Internals { | ||||||
|  |  | ||||||
| // Converts a compact JSON string into an indented one. | // Converts a compact JSON string into an indented one. | ||||||
| template <typename Print> | template <typename TWriter> | ||||||
| class Prettyfier { | class Prettyfier { | ||||||
|  public: |  public: | ||||||
|   explicit Prettyfier(IndentedPrint<Print>& p) : _sink(p) { |   explicit Prettyfier(IndentedPrint<TWriter>& p) : _sink(p) { | ||||||
|     _previousChar = 0; |     _previousChar = 0; | ||||||
|     _inString = false; |     _inString = false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t print(char c) { |   size_t write(uint8_t c) { | ||||||
|     size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c); |     size_t n = _inString ? handleStringChar(c) : handleMarkupChar(char(c)); | ||||||
|     _previousChar = c; |     _previousChar = char(c); | ||||||
|     return n; |     return n; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t print(const char* s) { |   size_t write(const uint8_t* s, size_t n) { | ||||||
|     // TODO: optimize |     // TODO: optimize | ||||||
|     size_t n = 0; |     size_t bytesWritten = 0; | ||||||
|     while (*s) n += print(*s++); |     while (n > 0) { | ||||||
|     return n; |       bytesWritten += write(*s++); | ||||||
|  |       n--; | ||||||
|  |     } | ||||||
|  |     return bytesWritten; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
| @@ -38,12 +41,12 @@ class Prettyfier { | |||||||
|     return _previousChar == '{' || _previousChar == '['; |     return _previousChar == '{' || _previousChar == '['; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t handleStringChar(char c) { |   size_t handleStringChar(uint8_t c) { | ||||||
|     bool isQuote = c == '"' && _previousChar != '\\'; |     bool isQuote = c == '"' && _previousChar != '\\'; | ||||||
|  |  | ||||||
|     if (isQuote) _inString = false; |     if (isQuote) _inString = false; | ||||||
|  |  | ||||||
|     return _sink.print(c); |     return _sink.write(c); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t handleMarkupChar(char c) { |   size_t handleMarkupChar(char c) { | ||||||
| @@ -73,26 +76,26 @@ class Prettyfier { | |||||||
|   size_t writeBlockClose(char c) { |   size_t writeBlockClose(char c) { | ||||||
|     size_t n = 0; |     size_t n = 0; | ||||||
|     n += unindentIfNeeded(); |     n += unindentIfNeeded(); | ||||||
|     n += _sink.print(c); |     n += write(c); | ||||||
|     return n; |     return n; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t writeBlockOpen(char c) { |   size_t writeBlockOpen(char c) { | ||||||
|     size_t n = 0; |     size_t n = 0; | ||||||
|     n += indentIfNeeded(); |     n += indentIfNeeded(); | ||||||
|     n += _sink.print(c); |     n += write(c); | ||||||
|     return n; |     return n; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t writeColon() { |   size_t writeColon() { | ||||||
|     size_t n = 0; |     size_t n = 0; | ||||||
|     n += _sink.print(": "); |     n += write(": "); | ||||||
|     return n; |     return n; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t writeComma() { |   size_t writeComma() { | ||||||
|     size_t n = 0; |     size_t n = 0; | ||||||
|     n += _sink.print(",\r\n"); |     n += write(",\r\n"); | ||||||
|     return n; |     return n; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -100,14 +103,14 @@ class Prettyfier { | |||||||
|     _inString = true; |     _inString = true; | ||||||
|     size_t n = 0; |     size_t n = 0; | ||||||
|     n += indentIfNeeded(); |     n += indentIfNeeded(); | ||||||
|     n += _sink.print('"'); |     n += write('"'); | ||||||
|     return n; |     return n; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t writeNormalChar(char c) { |   size_t writeNormalChar(char c) { | ||||||
|     size_t n = 0; |     size_t n = 0; | ||||||
|     n += indentIfNeeded(); |     n += indentIfNeeded(); | ||||||
|     n += _sink.print(c); |     n += write(c); | ||||||
|     return n; |     return n; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -115,19 +118,28 @@ class Prettyfier { | |||||||
|     if (!inEmptyBlock()) return 0; |     if (!inEmptyBlock()) return 0; | ||||||
|  |  | ||||||
|     _sink.indent(); |     _sink.indent(); | ||||||
|     return _sink.print("\r\n"); |     return write("\r\n"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t unindentIfNeeded() { |   size_t unindentIfNeeded() { | ||||||
|     if (inEmptyBlock()) return 0; |     if (inEmptyBlock()) return 0; | ||||||
|  |  | ||||||
|     _sink.unindent(); |     _sink.unindent(); | ||||||
|     return _sink.print("\r\n"); |     return write("\r\n"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t write(char c) { | ||||||
|  |     return _sink.write(static_cast<uint8_t>(c)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <size_t N> | ||||||
|  |   size_t write(const char (&s)[N]) { | ||||||
|  |     return _sink.write(reinterpret_cast<const uint8_t*>(s), N - 1); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   char _previousChar; |   char _previousChar; | ||||||
|   IndentedPrint<Print>& _sink; |   IndentedPrint<TWriter>& _sink; | ||||||
|   bool _inString; |   bool _inString; | ||||||
| }; | }; | ||||||
| } | }  // namespace Internals | ||||||
| } | }  // namespace ArduinoJson | ||||||
|   | |||||||
| @@ -29,7 +29,7 @@ class JsonArray { | |||||||
|   // Adds the specified value at the end of the array. |   // Adds the specified value at the end of the array. | ||||||
|   // |   // | ||||||
|   // bool add(TValue); |   // bool add(TValue); | ||||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, |   // TValue = bool, long, int, short, float, double, serialized, JsonVariant, | ||||||
|   //          std::string, String, JsonArrayData, JsonObject |   //          std::string, String, JsonArrayData, JsonObject | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   bool add(const T& value) { |   bool add(const T& value) { | ||||||
| @@ -154,7 +154,7 @@ class JsonArray { | |||||||
|   // Sets the value at specified index. |   // Sets the value at specified index. | ||||||
|   // |   // | ||||||
|   // bool add(size_t index, const TValue&); |   // bool add(size_t index, const TValue&); | ||||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, |   // TValue = bool, long, int, short, float, double, serialized, JsonVariant, | ||||||
|   //          std::string, String, JsonArrayData, JsonObject |   //          std::string, String, JsonArrayData, JsonObject | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   bool set(size_t index, const T& value) { |   bool set(size_t index, const T& value) { | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ | |||||||
| #include "JsonVariant.hpp" | #include "JsonVariant.hpp" | ||||||
| #include "Memory/JsonBufferAllocated.hpp" | #include "Memory/JsonBufferAllocated.hpp" | ||||||
| #include "Polyfills/type_traits.hpp" | #include "Polyfills/type_traits.hpp" | ||||||
| #include "Strings/StringTraits.hpp" |  | ||||||
|  |  | ||||||
| // Returns the size (in bytes) of an array with n elements. | // Returns the size (in bytes) of an array with n elements. | ||||||
| // Can be very handy to determine the size of a StaticJsonBuffer. | // Can be very handy to determine the size of a StaticJsonBuffer. | ||||||
|   | |||||||
| @@ -27,7 +27,7 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | |||||||
|   // Replaces the value |   // Replaces the value | ||||||
|   // |   // | ||||||
|   // operator=(const TValue&) |   // operator=(const TValue&) | ||||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, |   // TValue = bool, long, int, short, float, double, serialized, JsonVariant, | ||||||
|   //          std::string, String, JsonArray, JsonObject |   //          std::string, String, JsonArray, JsonObject | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE JsonArraySubscript& operator=(const T& src) { |   FORCE_INLINE JsonArraySubscript& operator=(const T& src) { | ||||||
| @@ -60,7 +60,7 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | |||||||
|   // Replaces the value |   // Replaces the value | ||||||
|   // |   // | ||||||
|   // bool set(const TValue&) |   // bool set(const TValue&) | ||||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, |   // TValue = bool, long, int, short, float, double, serialized, JsonVariant, | ||||||
|   //          std::string, String, JsonArray, JsonObject |   //          std::string, String, JsonArray, JsonObject | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool set(const TValue& value) { |   FORCE_INLINE bool set(const TValue& value) { | ||||||
|   | |||||||
| @@ -188,7 +188,7 @@ class JsonObject { | |||||||
|   // |   // | ||||||
|   // bool set(TKey, TValue); |   // bool set(TKey, TValue); | ||||||
|   // TKey = const std::string&, const String& |   // TKey = const std::string&, const String& | ||||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, |   // TValue = bool, long, int, short, float, double, serialized, JsonVariant, | ||||||
|   //          std::string, String, JsonArray, JsonObject |   //          std::string, String, JsonArray, JsonObject | ||||||
|   template <typename TValue, typename TString> |   template <typename TValue, typename TString> | ||||||
|   bool set(const TString& key, const TValue& value) { |   bool set(const TString& key, const TValue& value) { | ||||||
| @@ -205,7 +205,7 @@ class JsonObject { | |||||||
|   // |   // | ||||||
|   // bool set(TKey, const TValue&); |   // bool set(TKey, const TValue&); | ||||||
|   // TKey = char*, const char*, const FlashStringHelper* |   // TKey = char*, const char*, const FlashStringHelper* | ||||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, |   // TValue = bool, long, int, short, float, double, serialized, JsonVariant, | ||||||
|   //          std::string, String, JsonArray, JsonObject |   //          std::string, String, JsonArray, JsonObject | ||||||
|   template <typename TValue, typename TString> |   template <typename TValue, typename TString> | ||||||
|   bool set(TString* key, const TValue& value) { |   bool set(TString* key, const TValue& value) { | ||||||
| @@ -254,7 +254,7 @@ class JsonObject { | |||||||
|   iterator findKey(TStringRef key) { |   iterator findKey(TStringRef key) { | ||||||
|     iterator it; |     iterator it; | ||||||
|     for (it = begin(); it != end(); ++it) { |     for (it = begin(); it != end(); ++it) { | ||||||
|       if (Internals::StringTraits<TStringRef>::equals(key, it->key)) break; |       if (Internals::makeString(key).equals(it->key)) break; | ||||||
|     } |     } | ||||||
|     return it; |     return it; | ||||||
|   } |   } | ||||||
| @@ -288,7 +288,7 @@ class JsonObject { | |||||||
|     if (!_data) return false; |     if (!_data) return false; | ||||||
|  |  | ||||||
|     // ignore null key |     // ignore null key | ||||||
|     if (Internals::StringTraits<TStringRef>::is_null(key)) return false; |     if (Internals::makeString(key).is_null()) return false; | ||||||
|  |  | ||||||
|     // search a matching key |     // search a matching key | ||||||
|     iterator it = findKey<TStringRef>(key); |     iterator it = findKey<TStringRef>(key); | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ | |||||||
| #include "JsonPair.hpp" | #include "JsonPair.hpp" | ||||||
| #include "Memory/JsonBufferAllocated.hpp" | #include "Memory/JsonBufferAllocated.hpp" | ||||||
| #include "Polyfills/type_traits.hpp" | #include "Polyfills/type_traits.hpp" | ||||||
| #include "Strings/StringTraits.hpp" |  | ||||||
|  |  | ||||||
| // Returns the size (in bytes) of an object with n elements. | // Returns the size (in bytes) of an object with n elements. | ||||||
| // Can be very handy to determine the size of a StaticJsonBuffer. | // Can be very handy to determine the size of a StaticJsonBuffer. | ||||||
|   | |||||||
| @@ -67,7 +67,8 @@ class JsonObjectSubscript | |||||||
|   // Sets the specified value. |   // Sets the specified value. | ||||||
|   // |   // | ||||||
|   // bool set(const TValue&); |   // bool set(const TValue&); | ||||||
|   // TValue = bool, char, long, int, short, float, double, RawJson, JsonVariant, |   // TValue = bool, char, long, int, short, float, double, serialized, | ||||||
|  |   // JsonVariant, | ||||||
|   //          std::string, String, JsonArray, JsonObject |   //          std::string, String, JsonArray, JsonObject | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set( |   FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set( | ||||||
| @@ -94,7 +95,7 @@ class JsonObjectSubscript | |||||||
|  |  | ||||||
| template <typename TImpl> | template <typename TImpl> | ||||||
| template <typename TString> | template <typename TString> | ||||||
| inline typename enable_if<StringTraits<TString>::has_equals, | inline typename enable_if<IsString<TString>::value, | ||||||
|                           const JsonObjectSubscript<const TString &> >::type |                           const JsonObjectSubscript<const TString &> >::type | ||||||
|     JsonVariantSubscripts<TImpl>::operator[](const TString &key) const { |     JsonVariantSubscripts<TImpl>::operator[](const TString &key) const { | ||||||
|   return impl()->template as<JsonObject>()[key]; |   return impl()->template as<JsonObject>()[key]; | ||||||
| @@ -102,7 +103,7 @@ inline typename enable_if<StringTraits<TString>::has_equals, | |||||||
|  |  | ||||||
| template <typename TImpl> | template <typename TImpl> | ||||||
| template <typename TString> | template <typename TString> | ||||||
| inline typename enable_if<StringTraits<TString>::has_equals, | inline typename enable_if<IsString<TString>::value, | ||||||
|                           JsonObjectSubscript<const TString &> >::type |                           JsonObjectSubscript<const TString &> >::type | ||||||
|     JsonVariantSubscripts<TImpl>::operator[](const TString &key) { |     JsonVariantSubscripts<TImpl>::operator[](const TString &key) { | ||||||
|   return impl()->template as<JsonObject>()[key]; |   return impl()->template as<JsonObject>()[key]; | ||||||
| @@ -110,7 +111,7 @@ inline typename enable_if<StringTraits<TString>::has_equals, | |||||||
|  |  | ||||||
| template <typename TImpl> | template <typename TImpl> | ||||||
| template <typename TString> | template <typename TString> | ||||||
| inline typename enable_if<StringTraits<const TString *>::has_equals, | inline typename enable_if<IsString<const TString *>::value, | ||||||
|                           JsonObjectSubscript<const TString *> >::type |                           JsonObjectSubscript<const TString *> >::type | ||||||
|     JsonVariantSubscripts<TImpl>::operator[](const TString *key) { |     JsonVariantSubscripts<TImpl>::operator[](const TString *key) { | ||||||
|   return impl()->template as<JsonObject>()[key]; |   return impl()->template as<JsonObject>()[key]; | ||||||
| @@ -118,7 +119,7 @@ inline typename enable_if<StringTraits<const TString *>::has_equals, | |||||||
|  |  | ||||||
| template <typename TImpl> | template <typename TImpl> | ||||||
| template <typename TString> | template <typename TString> | ||||||
| inline typename enable_if<StringTraits<TString *>::has_equals, | inline typename enable_if<IsString<TString *>::value, | ||||||
|                           const JsonObjectSubscript<const TString *> >::type |                           const JsonObjectSubscript<const TString *> >::type | ||||||
|     JsonVariantSubscripts<TImpl>::operator[](const TString *key) const { |     JsonVariantSubscripts<TImpl>::operator[](const TString *key) const { | ||||||
|   return impl()->template as<JsonObject>()[key]; |   return impl()->template as<JsonObject>()[key]; | ||||||
|   | |||||||
| @@ -12,7 +12,8 @@ | |||||||
| #include "Data/JsonVariantType.hpp" | #include "Data/JsonVariantType.hpp" | ||||||
| #include "JsonVariantBase.hpp" | #include "JsonVariantBase.hpp" | ||||||
| #include "Polyfills/type_traits.hpp" | #include "Polyfills/type_traits.hpp" | ||||||
| #include "RawJson.hpp" | #include "Serialization/DynamicStringWriter.hpp" | ||||||
|  | #include "SerializedValue.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|  |  | ||||||
| @@ -99,9 +100,10 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Create a JsonVariant containing an unparsed string |   // Create a JsonVariant containing an unparsed string | ||||||
|   JsonVariant(Internals::RawJsonString<const char *> value) { |   JsonVariant(Internals::SerializedValue<const char *> value) { | ||||||
|     _type = Internals::JSON_UNPARSED; |     _type = Internals::JSON_UNPARSED; | ||||||
|     _content.asString = value; |     _content.asRaw.data = value.data(); | ||||||
|  |     _content.asRaw.size = value.size(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   JsonVariant(JsonArray array); |   JsonVariant(JsonArray array); | ||||||
| @@ -153,7 +155,7 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | |||||||
|   // std::string as<std::string>() const; |   // std::string as<std::string>() const; | ||||||
|   // String as<String>() const; |   // String as<String>() const; | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   typename Internals::enable_if<Internals::StringTraits<T>::has_append, T>::type |   typename Internals::enable_if<Internals::IsWriteableString<T>::value, T>::type | ||||||
|   as() const { |   as() const { | ||||||
|     const char *cstr = variantAsString(); |     const char *cstr = variantAsString(); | ||||||
|     if (cstr) return T(cstr); |     if (cstr) return T(cstr); | ||||||
| @@ -276,7 +278,7 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | |||||||
|         return visitor.acceptString(_content.asString); |         return visitor.acceptString(_content.asString); | ||||||
|  |  | ||||||
|       case JSON_UNPARSED: |       case JSON_UNPARSED: | ||||||
|         return visitor.acceptRawJson(_content.asString); |         return visitor.acceptRawJson(_content.asRaw.data, _content.asRaw.size); | ||||||
|  |  | ||||||
|       case JSON_NEGATIVE_INTEGER: |       case JSON_NEGATIVE_INTEGER: | ||||||
|         return visitor.acceptNegativeInteger(_content.asInteger); |         return visitor.acceptNegativeInteger(_content.asInteger); | ||||||
| @@ -310,9 +312,7 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | |||||||
|     return _type == Internals::JSON_OBJECT; |     return _type == Internals::JSON_OBJECT; | ||||||
|   } |   } | ||||||
|   bool variantIsString() const { |   bool variantIsString() const { | ||||||
|     return _type == Internals::JSON_STRING || |     return _type == Internals::JSON_STRING; | ||||||
|            (_type == Internals::JSON_UNPARSED && _content.asString && |  | ||||||
|             !strcmp("null", _content.asString)); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // The current type of the variant |   // The current type of the variant | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ | |||||||
|  |  | ||||||
| #include "Data/IsVariant.hpp" | #include "Data/IsVariant.hpp" | ||||||
| #include "Polyfills/type_traits.hpp" | #include "Polyfills/type_traits.hpp" | ||||||
| #include "Strings/StringTraits.hpp" | #include "Strings/StringTypes.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| class JsonArray; | class JsonArray; | ||||||
| @@ -104,16 +104,14 @@ class JsonVariantComparisons { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   typename enable_if<StringTraits<TString>::has_equals, bool>::type equals( |   typename enable_if<IsString<TString>::value, bool>::type equals( | ||||||
|       const TString &comparand) const { |       const TString &comparand) const { | ||||||
|     const char *value = as<const char *>(); |     return makeString(comparand).equals(as<const char *>()); | ||||||
|     return StringTraits<TString>::equals(comparand, value); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TComparand> |   template <typename TComparand> | ||||||
|   typename enable_if<!IsVariant<TComparand>::value && |   typename enable_if< | ||||||
|                          !StringTraits<TComparand>::has_equals, |       !IsVariant<TComparand>::value && !IsString<TComparand>::value, bool>::type | ||||||
|                      bool>::type |  | ||||||
|   equals(const TComparand &comparand) const { |   equals(const TComparand &comparand) const { | ||||||
|     return as<TComparand>() == comparand; |     return as<TComparand>() == comparand; | ||||||
|   } |   } | ||||||
| @@ -132,8 +130,7 @@ class JsonVariantComparisons { | |||||||
|     if (is<JsonObject>() && right.template is<JsonObject>()) |     if (is<JsonObject>() && right.template is<JsonObject>()) | ||||||
|       return as<JsonObject>() == right.template as<JsonObject>(); |       return as<JsonObject>() == right.template as<JsonObject>(); | ||||||
|     if (is<char *>() && right.template is<char *>()) |     if (is<char *>() && right.template is<char *>()) | ||||||
|       return StringTraits<const char *>::equals(as<char *>(), |       return makeString(as<char *>()).equals(right.template as<char *>()); | ||||||
|                                                 right.template as<char *>()); |  | ||||||
|  |  | ||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -68,6 +68,7 @@ inline T JsonVariant::variantAsInteger() const { | |||||||
|   using namespace Internals; |   using namespace Internals; | ||||||
|   switch (_type) { |   switch (_type) { | ||||||
|     case JSON_UNDEFINED: |     case JSON_UNDEFINED: | ||||||
|  |     case JSON_UNPARSED: | ||||||
|       return 0; |       return 0; | ||||||
|     case JSON_POSITIVE_INTEGER: |     case JSON_POSITIVE_INTEGER: | ||||||
|     case JSON_BOOLEAN: |     case JSON_BOOLEAN: | ||||||
| @@ -75,7 +76,6 @@ inline T JsonVariant::variantAsInteger() const { | |||||||
|     case JSON_NEGATIVE_INTEGER: |     case JSON_NEGATIVE_INTEGER: | ||||||
|       return T(~_content.asInteger + 1); |       return T(~_content.asInteger + 1); | ||||||
|     case JSON_STRING: |     case JSON_STRING: | ||||||
|     case JSON_UNPARSED: |  | ||||||
|       return parseInteger<T>(_content.asString); |       return parseInteger<T>(_content.asString); | ||||||
|     default: |     default: | ||||||
|       return T(_content.asFloat); |       return T(_content.asFloat); | ||||||
| @@ -84,11 +84,7 @@ inline T JsonVariant::variantAsInteger() const { | |||||||
|  |  | ||||||
| inline const char *JsonVariant::variantAsString() const { | inline const char *JsonVariant::variantAsString() const { | ||||||
|   using namespace Internals; |   using namespace Internals; | ||||||
|   if (_type == JSON_UNPARSED && _content.asString && |   return _type == JSON_STRING ? _content.asString : NULL; | ||||||
|       !strcmp("null", _content.asString)) |  | ||||||
|     return NULL; |  | ||||||
|   if (_type == JSON_STRING || _type == JSON_UNPARSED) return _content.asString; |  | ||||||
|   return NULL; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| @@ -96,6 +92,7 @@ inline T JsonVariant::variantAsFloat() const { | |||||||
|   using namespace Internals; |   using namespace Internals; | ||||||
|   switch (_type) { |   switch (_type) { | ||||||
|     case JSON_UNDEFINED: |     case JSON_UNDEFINED: | ||||||
|  |     case JSON_UNPARSED: | ||||||
|       return 0; |       return 0; | ||||||
|     case JSON_POSITIVE_INTEGER: |     case JSON_POSITIVE_INTEGER: | ||||||
|     case JSON_BOOLEAN: |     case JSON_BOOLEAN: | ||||||
| @@ -103,7 +100,6 @@ inline T JsonVariant::variantAsFloat() const { | |||||||
|     case JSON_NEGATIVE_INTEGER: |     case JSON_NEGATIVE_INTEGER: | ||||||
|       return -static_cast<T>(_content.asInteger); |       return -static_cast<T>(_content.asInteger); | ||||||
|     case JSON_STRING: |     case JSON_STRING: | ||||||
|     case JSON_UNPARSED: |  | ||||||
|       return parseFloat<T>(_content.asString); |       return parseFloat<T>(_content.asString); | ||||||
|     default: |     default: | ||||||
|       return static_cast<T>(_content.asFloat); |       return static_cast<T>(_content.asFloat); | ||||||
| @@ -112,27 +108,20 @@ inline T JsonVariant::variantAsFloat() const { | |||||||
|  |  | ||||||
| inline bool JsonVariant::variantIsBoolean() const { | inline bool JsonVariant::variantIsBoolean() const { | ||||||
|   using namespace Internals; |   using namespace Internals; | ||||||
|   if (_type == JSON_BOOLEAN) return true; |   return _type == JSON_BOOLEAN; | ||||||
|  |  | ||||||
|   if (_type != JSON_UNPARSED || _content.asString == NULL) return false; |  | ||||||
|  |  | ||||||
|   return !strcmp(_content.asString, "true") || |  | ||||||
|          !strcmp(_content.asString, "false"); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool JsonVariant::variantIsInteger() const { | inline bool JsonVariant::variantIsInteger() const { | ||||||
|   using namespace Internals; |   using namespace Internals; | ||||||
|  |  | ||||||
|   return _type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER || |   return _type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER; | ||||||
|          (_type == JSON_UNPARSED && isInteger(_content.asString)); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool JsonVariant::variantIsFloat() const { | inline bool JsonVariant::variantIsFloat() const { | ||||||
|   using namespace Internals; |   using namespace Internals; | ||||||
|  |  | ||||||
|   return _type == JSON_FLOAT || _type == JSON_POSITIVE_INTEGER || |   return _type == JSON_FLOAT || _type == JSON_POSITIVE_INTEGER || | ||||||
|          _type == JSON_NEGATIVE_INTEGER || |          _type == JSON_NEGATIVE_INTEGER; | ||||||
|          (_type == JSON_UNPARSED && isFloat(_content.asString)); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| }  // namespace ArduinoJson | }  // namespace ArduinoJson | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
| #include "Data/JsonVariantAs.hpp" | #include "Data/JsonVariantAs.hpp" | ||||||
| #include "Polyfills/attributes.hpp" | #include "Polyfills/attributes.hpp" | ||||||
| #include "Polyfills/type_traits.hpp" | #include "Polyfills/type_traits.hpp" | ||||||
| #include "Strings/StringTraits.hpp" | #include "Strings/StringTypes.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| class JsonArray; | class JsonArray; | ||||||
| @@ -43,21 +43,21 @@ class JsonVariantSubscripts { | |||||||
|   // TKey = const std::string&, const String& |   // TKey = const std::string&, const String& | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   FORCE_INLINE |   FORCE_INLINE | ||||||
|       typename enable_if<StringTraits<TString>::has_equals, |       typename enable_if<IsString<TString>::value, | ||||||
|                          const JsonObjectSubscript<const TString &> >::type |                          const JsonObjectSubscript<const TString &> >::type | ||||||
|       operator[](const TString &key) const; |       operator[](const TString &key) const; | ||||||
|   // |   // | ||||||
|   // const JsonObjectSubscript operator[](TKey) const; |   // const JsonObjectSubscript operator[](TKey) const; | ||||||
|   // TKey = const std::string&, const String& |   // TKey = const std::string&, const String& | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   FORCE_INLINE typename enable_if<StringTraits<TString>::has_equals, |   FORCE_INLINE typename enable_if<IsString<TString>::value, | ||||||
|                                   JsonObjectSubscript<const TString &> >::type |                                   JsonObjectSubscript<const TString &> >::type | ||||||
|   operator[](const TString &key); |   operator[](const TString &key); | ||||||
|   // |   // | ||||||
|   // JsonObjectSubscript operator[](TKey); |   // JsonObjectSubscript operator[](TKey); | ||||||
|   // TKey = const char*, const char[N], const FlashStringHelper* |   // TKey = const char*, const char[N], const FlashStringHelper* | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   FORCE_INLINE typename enable_if<StringTraits<const TString *>::has_equals, |   FORCE_INLINE typename enable_if<IsString<const TString *>::value, | ||||||
|                                   JsonObjectSubscript<const TString *> >::type |                                   JsonObjectSubscript<const TString *> >::type | ||||||
|   operator[](const TString *key); |   operator[](const TString *key); | ||||||
|   // |   // | ||||||
| @@ -65,7 +65,7 @@ class JsonVariantSubscripts { | |||||||
|   // TKey = const char*, const char[N], const FlashStringHelper* |   // TKey = const char*, const char[N], const FlashStringHelper* | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   FORCE_INLINE |   FORCE_INLINE | ||||||
|       typename enable_if<StringTraits<TString *>::has_equals, |       typename enable_if<IsString<TString *>::value, | ||||||
|                          const JsonObjectSubscript<const TString *> >::type |                          const JsonObjectSubscript<const TString *> >::type | ||||||
|       operator[](const TString *key) const; |       operator[](const TString *key) const; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,10 +13,10 @@ | |||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace Internals { | namespace Internals { | ||||||
|  |  | ||||||
| template <typename TPrint> | template <typename TWriter> | ||||||
| class MsgPackSerializer { | class MsgPackSerializer { | ||||||
|  public: |  public: | ||||||
|   MsgPackSerializer(TPrint& output) : _output(&output), _bytesWritten(0) {} |   MsgPackSerializer(TWriter& writer) : _writer(&writer), _bytesWritten(0) {} | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   typename enable_if<sizeof(T) == 4>::type acceptFloat(T value32) { |   typename enable_if<sizeof(T) == 4>::type acceptFloat(T value32) { | ||||||
| @@ -91,7 +91,9 @@ class MsgPackSerializer { | |||||||
|     writeBytes(reinterpret_cast<const uint8_t*>(value), n); |     writeBytes(reinterpret_cast<const uint8_t*>(value), n); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void acceptRawJson(const char* /*value*/) {} |   void acceptRawJson(const char* data, size_t size) { | ||||||
|  |     writeBytes(reinterpret_cast<const uint8_t*>(data), size); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   void acceptNegativeInteger(JsonUInt value) { |   void acceptNegativeInteger(JsonUInt value) { | ||||||
|     JsonUInt negated = JsonUInt(~value + 1); |     JsonUInt negated = JsonUInt(~value + 1); | ||||||
| @@ -150,12 +152,11 @@ class MsgPackSerializer { | |||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   void writeByte(uint8_t c) { |   void writeByte(uint8_t c) { | ||||||
|     _output->print(char(c)); |     _bytesWritten += _writer->write(c); | ||||||
|     _bytesWritten++; |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void writeBytes(const uint8_t* c, size_t n) { |   void writeBytes(const uint8_t* p, size_t n) { | ||||||
|     for (; n > 0; --n, ++c) writeByte(*c); |     _bytesWritten += _writer->write(p, n); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
| @@ -164,7 +165,7 @@ class MsgPackSerializer { | |||||||
|     writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value)); |     writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   TPrint* _output; |   TWriter* _writer; | ||||||
|   size_t _bytesWritten; |   size_t _bytesWritten; | ||||||
| }; | }; | ||||||
| }  // namespace Internals | }  // namespace Internals | ||||||
|   | |||||||
| @@ -1,46 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2018 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| namespace ArduinoJson { |  | ||||||
|  |  | ||||||
| namespace Internals { |  | ||||||
| // A special type of data that can be used to insert pregenerated JSON portions. |  | ||||||
| template <typename T> |  | ||||||
| class RawJsonString { |  | ||||||
|  public: |  | ||||||
|   explicit RawJsonString(T str) : _str(str) {} |  | ||||||
|   operator T() const { |  | ||||||
|     return _str; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|  private: |  | ||||||
|   T _str; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| template <typename String> |  | ||||||
| struct StringTraits<RawJsonString<String>, void> { |  | ||||||
|   static bool is_null(RawJsonString<String> source) { |  | ||||||
|     return StringTraits<String>::is_null(static_cast<String>(source)); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   typedef RawJsonString<const char*> duplicate_t; |  | ||||||
|  |  | ||||||
|   template <typename Buffer> |  | ||||||
|   static duplicate_t duplicate(RawJsonString<String> source, Buffer* buffer) { |  | ||||||
|     return duplicate_t(StringTraits<String>::duplicate(source, buffer)); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static const bool has_append = false; |  | ||||||
|   static const bool has_equals = false; |  | ||||||
|   static const bool should_duplicate = StringTraits<String>::should_duplicate; |  | ||||||
| }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline Internals::RawJsonString<T> RawJson(T str) { |  | ||||||
|   return Internals::RawJsonString<T>(str); |  | ||||||
| } |  | ||||||
| } |  | ||||||
| @@ -7,14 +7,14 @@ | |||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace Internals { | namespace Internals { | ||||||
| 
 | 
 | ||||||
| class DummyPrint { | class DummyWriter { | ||||||
|  public: |  public: | ||||||
|   size_t print(char) { |   size_t write(uint8_t) { | ||||||
|     return 1; |     return 1; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   size_t print(const char* s) { |   size_t write(const uint8_t*, size_t n) { | ||||||
|     return strlen(s); |     return n; | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| }  // namespace Internals
 | }  // namespace Internals
 | ||||||
| @@ -1,35 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2018 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #include "../Strings/StringTraits.hpp" |  | ||||||
|  |  | ||||||
| namespace ArduinoJson { |  | ||||||
| namespace Internals { |  | ||||||
|  |  | ||||||
| // A Print implementation that allows to write in a String |  | ||||||
| template <typename TString> |  | ||||||
| class DynamicStringBuilder { |  | ||||||
|  public: |  | ||||||
|   DynamicStringBuilder(TString &str) : _str(str) {} |  | ||||||
|  |  | ||||||
|   size_t print(char c) { |  | ||||||
|     StringTraits<TString>::append(_str, c); |  | ||||||
|     return 1; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t print(const char *s) { |  | ||||||
|     size_t initialLen = _str.length(); |  | ||||||
|     StringTraits<TString>::append(_str, s); |  | ||||||
|     return _str.length() - initialLen; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|  private: |  | ||||||
|   DynamicStringBuilder &operator=(const DynamicStringBuilder &); |  | ||||||
|  |  | ||||||
|   TString &_str; |  | ||||||
| }; |  | ||||||
| }  // namespace Internals |  | ||||||
| }  // namespace ArduinoJson |  | ||||||
							
								
								
									
										81
									
								
								src/ArduinoJson/Serialization/DynamicStringWriter.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								src/ArduinoJson/Serialization/DynamicStringWriter.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "../Polyfills/type_traits.hpp" | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_ENABLE_ARDUINO_STRING | ||||||
|  | #include <WString.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_ENABLE_STD_STRING | ||||||
|  | #include <string> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace Internals { | ||||||
|  |  | ||||||
|  | template <typename> | ||||||
|  | struct IsWriteableString : false_type {}; | ||||||
|  |  | ||||||
|  | // A Print implementation that allows to write in a String | ||||||
|  | template <typename TString> | ||||||
|  | class DynamicStringWriter {}; | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_ENABLE_ARDUINO_STRING | ||||||
|  | template <> | ||||||
|  | struct IsWriteableString<String> : true_type {}; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | class DynamicStringWriter<String> { | ||||||
|  |  public: | ||||||
|  |   DynamicStringWriter(String &str) : _str(&str) {} | ||||||
|  |  | ||||||
|  |   size_t write(uint8_t c) { | ||||||
|  |     _str->operator+=(static_cast<char>(c)); | ||||||
|  |     return 1; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t write(const uint8_t *s, size_t n) { | ||||||
|  |     // CAUTION: Arduino String doesn't have append() | ||||||
|  |     // and old version doesn't have size() either | ||||||
|  |     _str->reserve(_str->length() + n); | ||||||
|  |     while (n > 0) { | ||||||
|  |       _str->operator+=(static_cast<char>(*s++)); | ||||||
|  |       n--; | ||||||
|  |     } | ||||||
|  |     return n; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   String *_str; | ||||||
|  | }; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_ENABLE_STD_STRING | ||||||
|  | template <> | ||||||
|  | struct IsWriteableString<std::string> : true_type {}; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | class DynamicStringWriter<std::string> { | ||||||
|  |  public: | ||||||
|  |   DynamicStringWriter(std::string &str) : _str(&str) {} | ||||||
|  |  | ||||||
|  |   size_t write(uint8_t c) { | ||||||
|  |     _str->operator+=(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; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   std::string *_str; | ||||||
|  | }; | ||||||
|  | #endif | ||||||
|  | }  // namespace Internals | ||||||
|  | }  // namespace ArduinoJson | ||||||
| @@ -8,22 +8,25 @@ namespace ArduinoJson { | |||||||
| namespace Internals { | namespace Internals { | ||||||
| 
 | 
 | ||||||
| // A Print implementation that allows to write in a char[]
 | // A Print implementation that allows to write in a char[]
 | ||||||
| class StaticStringBuilder { | class StaticStringWriter { | ||||||
|  public: |  public: | ||||||
|   StaticStringBuilder(char *buf, size_t size) : end(buf + size - 1), p(buf) { |   StaticStringWriter(char *buf, size_t size) : end(buf + size - 1), p(buf) { | ||||||
|     *p = '\0'; |     *p = '\0'; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   size_t print(char c) { |   size_t write(uint8_t c) { | ||||||
|     if (p >= end) return 0; |     if (p >= end) return 0; | ||||||
|     *p++ = c; |     *p++ = static_cast<char>(c); | ||||||
|     *p = '\0'; |     *p = '\0'; | ||||||
|     return 1; |     return 1; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   size_t print(const char *s) { |   size_t write(const uint8_t *s, size_t n) { | ||||||
|     char *begin = p; |     char *begin = p; | ||||||
|     while (p < end && *s) *p++ = *s++; |     while (p < end && n > 0) { | ||||||
|  |       *p++ = static_cast<char>(*s++); | ||||||
|  |       n--; | ||||||
|  |     } | ||||||
|     *p = '\0'; |     *p = '\0'; | ||||||
|     return size_t(p - begin); |     return size_t(p - begin); | ||||||
|   } |   } | ||||||
| @@ -13,27 +13,28 @@ | |||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace Internals { | namespace Internals { | ||||||
| 
 | 
 | ||||||
| class StreamPrintAdapter { | class StreamWriter { | ||||||
|  public: |  public: | ||||||
|   explicit StreamPrintAdapter(std::ostream& os) : _os(os) {} |   explicit StreamWriter(std::ostream& os) : _os(os) {} | ||||||
| 
 | 
 | ||||||
|   size_t print(char c) { |   size_t write(uint8_t c) { | ||||||
|     _os << c; |     _os << c; | ||||||
|     return 1; |     return 1; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   size_t print(const char* s) { |   size_t write(const uint8_t* s, size_t n) { | ||||||
|     _os << s; |     _os.write(reinterpret_cast<const char*>(s), | ||||||
|     return strlen(s); |               static_cast<std::streamsize>(n)); | ||||||
|  |     return n; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  private: |  private: | ||||||
|   // cannot be assigned
 |   // cannot be assigned
 | ||||||
|   StreamPrintAdapter& operator=(const StreamPrintAdapter&); |   StreamWriter& operator=(const StreamWriter&); | ||||||
| 
 | 
 | ||||||
|   std::ostream& _os; |   std::ostream& _os; | ||||||
| }; | }; | ||||||
| } | }  // namespace Internals
 | ||||||
| } | }  // namespace ArduinoJson
 | ||||||
| 
 | 
 | ||||||
| #endif  // ARDUINOJSON_ENABLE_STD_STREAM
 | #endif  // ARDUINOJSON_ENABLE_STD_STREAM
 | ||||||
| @@ -4,15 +4,15 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "./DummyPrint.hpp" | #include "./DummyWriter.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace Internals { | namespace Internals { | ||||||
|  |  | ||||||
| template <template <typename> class TSerializer, typename TSource> | template <template <typename> class TSerializer, typename TSource> | ||||||
| size_t measure(const TSource &source) { | size_t measure(const TSource &source) { | ||||||
|   DummyPrint dp; |   DummyWriter dp; | ||||||
|   TSerializer<DummyPrint> serializer(dp); |   TSerializer<DummyWriter> serializer(dp); | ||||||
|   source.visit(serializer); |   source.visit(serializer); | ||||||
|   return serializer.bytesWritten(); |   return serializer.bytesWritten(); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,11 +4,11 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "./DynamicStringBuilder.hpp" | #include "./DynamicStringWriter.hpp" | ||||||
| #include "./StaticStringBuilder.hpp" | #include "./StaticStringWriter.hpp" | ||||||
|  |  | ||||||
| #if ARDUINOJSON_ENABLE_STD_STREAM | #if ARDUINOJSON_ENABLE_STD_STREAM | ||||||
| #include "./StreamPrintAdapter.hpp" | #include "./StreamWriter.hpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| @@ -16,7 +16,7 @@ namespace Internals { | |||||||
|  |  | ||||||
| template <template <typename> class TSerializer, typename TSource, | template <template <typename> class TSerializer, typename TSource, | ||||||
|           typename TPrint> |           typename TPrint> | ||||||
| typename enable_if<!StringTraits<TPrint>::has_append, size_t>::type serialize( | typename enable_if<!IsWriteableString<TPrint>::value, size_t>::type serialize( | ||||||
|     const TSource &source, TPrint &destination) { |     const TSource &source, TPrint &destination) { | ||||||
|   TSerializer<TPrint> serializer(destination); |   TSerializer<TPrint> serializer(destination); | ||||||
|   source.visit(serializer); |   source.visit(serializer); | ||||||
| @@ -26,29 +26,29 @@ typename enable_if<!StringTraits<TPrint>::has_append, size_t>::type serialize( | |||||||
| #if ARDUINOJSON_ENABLE_STD_STREAM | #if ARDUINOJSON_ENABLE_STD_STREAM | ||||||
| template <template <typename> class TSerializer, typename TSource> | template <template <typename> class TSerializer, typename TSource> | ||||||
| size_t serialize(const TSource &source, std::ostream &os) { | size_t serialize(const TSource &source, std::ostream &os) { | ||||||
|   StreamPrintAdapter adapter(os); |   StreamWriter writer(os); | ||||||
|   return serialize<TSerializer>(source, adapter); |   return serialize<TSerializer>(source, writer); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| template <template <typename> class TSerializer, typename TSource> | template <template <typename> class TSerializer, typename TSource> | ||||||
| size_t serialize(const TSource &source, char *buffer, size_t bufferSize) { | size_t serialize(const TSource &source, char *buffer, size_t bufferSize) { | ||||||
|   StaticStringBuilder sb(buffer, bufferSize); |   StaticStringWriter writer(buffer, bufferSize); | ||||||
|   return serialize<TSerializer>(source, sb); |   return serialize<TSerializer>(source, writer); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <template <typename> class TSerializer, typename TSource, size_t N> | template <template <typename> class TSerializer, typename TSource, size_t N> | ||||||
| size_t serialize(const TSource &source, char (&buffer)[N]) { | size_t serialize(const TSource &source, char (&buffer)[N]) { | ||||||
|   StaticStringBuilder sb(buffer, N); |   StaticStringWriter writer(buffer, N); | ||||||
|   return serialize<TSerializer>(source, sb); |   return serialize<TSerializer>(source, writer); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <template <typename> class TSerializer, typename TSource, | template <template <typename> class TSerializer, typename TSource, | ||||||
|           typename TString> |           typename TString> | ||||||
| typename enable_if<StringTraits<TString>::has_append, size_t>::type serialize( | typename enable_if<IsWriteableString<TString>::value, size_t>::type serialize( | ||||||
|     const TSource &source, TString &str) { |     const TSource &source, TString &str) { | ||||||
|   DynamicStringBuilder<TString> sb(str); |   DynamicStringWriter<TString> writer(str); | ||||||
|   return serialize<TSerializer>(source, sb); |   return serialize<TSerializer>(source, writer); | ||||||
| } | } | ||||||
|  |  | ||||||
| }  // namespace Internals | }  // namespace Internals | ||||||
|   | |||||||
							
								
								
									
										70
									
								
								src/ArduinoJson/SerializedValue.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/ArduinoJson/SerializedValue.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "Strings/StringTypes.hpp" | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  |  | ||||||
|  | namespace Internals { | ||||||
|  | // A special type of data that can be used to insert pregenerated JSON portions. | ||||||
|  | template <typename T> | ||||||
|  | class SerializedValue { | ||||||
|  |  public: | ||||||
|  |   explicit SerializedValue(T str) : _str(str) {} | ||||||
|  |   operator T() const { | ||||||
|  |     return _str; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   const char* data() const { | ||||||
|  |     return _str.c_str(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t size() const { | ||||||
|  |     // CAUTION: the old Arduino String doesn't have size() | ||||||
|  |     return _str.length(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   T _str; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename TChar> | ||||||
|  | class SerializedValue<TChar*> { | ||||||
|  |  public: | ||||||
|  |   explicit SerializedValue(TChar* p, size_t n) : _data(p), _size(n) {} | ||||||
|  |   operator TChar*() const { | ||||||
|  |     return _data; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   TChar* data() const { | ||||||
|  |     return _data; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t size() const { | ||||||
|  |     return _size; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   TChar* _data; | ||||||
|  |   size_t _size; | ||||||
|  | }; | ||||||
|  | }  // namespace Internals | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | inline Internals::SerializedValue<T> serialized(T str) { | ||||||
|  |   return Internals::SerializedValue<T>(str); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename TChar> | ||||||
|  | inline Internals::SerializedValue<TChar*> serialized(TChar* p) { | ||||||
|  |   return Internals::SerializedValue<TChar*>(p, Internals::makeString(p).size()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename TChar> | ||||||
|  | inline Internals::SerializedValue<TChar*> serialized(TChar* p, size_t n) { | ||||||
|  |   return Internals::SerializedValue<TChar*>(p, n); | ||||||
|  | } | ||||||
|  | }  // namespace ArduinoJson | ||||||
							
								
								
									
										60
									
								
								src/ArduinoJson/Strings/ArduinoString.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/ArduinoJson/Strings/ArduinoString.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <WString.h> | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace Internals { | ||||||
|  |  | ||||||
|  | class ArduinoString { | ||||||
|  |  public: | ||||||
|  |   ArduinoString(const ::String& str) : _str(&str) {} | ||||||
|  |  | ||||||
|  |   template <typename Buffer> | ||||||
|  |   const char* save(Buffer* buffer) const { | ||||||
|  |     if (!_str->c_str()) return NULL;  // <- Arduino string can return NULL | ||||||
|  |     size_t n = _str->length() + 1; | ||||||
|  |     void* dup = buffer->alloc(n); | ||||||
|  |     if (dup != NULL) memcpy(dup, _str->c_str(), n); | ||||||
|  |     return static_cast<const char*>(dup); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool is_null() const { | ||||||
|  |     // Arduino's String::c_str() can return NULL | ||||||
|  |     return _str->c_str(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool equals(const char* expected) const { | ||||||
|  |     // Arduino's String::c_str() can return NULL | ||||||
|  |     const char* actual = _str->c_str(); | ||||||
|  |     if (!actual || !expected) return actual == expected; | ||||||
|  |     return 0 == strcmp(actual, expected); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   const char* data() const { | ||||||
|  |     return _str->c_str(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t size() const { | ||||||
|  |     return _str->length(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   const ::String* _str; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct IsString< ::String> : true_type {}; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct IsString< ::StringSumHelper> : true_type {}; | ||||||
|  |  | ||||||
|  | inline ArduinoString makeString(const ::String& str) { | ||||||
|  |   return ArduinoString(str); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace Internals | ||||||
|  | }  // namespace ArduinoJson | ||||||
| @@ -1,44 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2018 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| namespace ArduinoJson { |  | ||||||
| namespace Internals { |  | ||||||
|  |  | ||||||
| template <typename TChar> |  | ||||||
| struct CharPointerTraits { |  | ||||||
|   static bool equals(const TChar* str, const char* expected) { |  | ||||||
|     const char* actual = reinterpret_cast<const char*>(str); |  | ||||||
|     if (!actual || !expected) return actual == expected; |  | ||||||
|     return strcmp(actual, expected) == 0; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static bool is_null(const TChar* str) { |  | ||||||
|     return !str; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   typedef const char* duplicate_t; |  | ||||||
|  |  | ||||||
|   template <typename Buffer> |  | ||||||
|   static duplicate_t duplicate(const TChar* str, Buffer* buffer) { |  | ||||||
|     if (!str) return NULL; |  | ||||||
|     size_t size = strlen(reinterpret_cast<const char*>(str)) + 1; |  | ||||||
|     void* dup = buffer->alloc(size); |  | ||||||
|     if (dup != NULL) memcpy(dup, str, size); |  | ||||||
|     return static_cast<duplicate_t>(dup); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static const bool has_append = false; |  | ||||||
|   static const bool has_equals = true; |  | ||||||
|   static const bool should_duplicate = !is_const<TChar>::value; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| // char*, unsigned char*, signed char* |  | ||||||
| // const char*, const unsigned char*, const signed char* |  | ||||||
| template <typename TChar> |  | ||||||
| struct StringTraits<TChar*, typename enable_if<sizeof(TChar) == 1>::type> |  | ||||||
|     : CharPointerTraits<TChar> {}; |  | ||||||
| }  // namespace Internals |  | ||||||
| }  // namespace ArduinoJson |  | ||||||
							
								
								
									
										47
									
								
								src/ArduinoJson/Strings/FixedSizeFlashString.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/ArduinoJson/Strings/FixedSizeFlashString.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace Internals { | ||||||
|  |  | ||||||
|  | class FixedSizeFlashString { | ||||||
|  |  public: | ||||||
|  |   FixedSizeFlashString(const __FlashStringHelper* str, size_t sz) | ||||||
|  |       : _str(str), _size(sz) {} | ||||||
|  |  | ||||||
|  |   bool equals(const char* expected) const { | ||||||
|  |     const char* actual = reinterpret_cast<const char*>(_str); | ||||||
|  |     if (!actual || !expected) return actual == expected; | ||||||
|  |     return strcmp_P(actual, expected) == 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool is_null() const { | ||||||
|  |     return !_str; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename Buffer> | ||||||
|  |   const char* save(Buffer* buffer) const { | ||||||
|  |     if (!_str) return NULL; | ||||||
|  |     void* dup = buffer->alloc(_size); | ||||||
|  |     if (dup != NULL) memcpy_P(dup, (const char*)_str, _size); | ||||||
|  |     return static_cast<const char*>(dup); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t size() const { | ||||||
|  |     return strlen_P(reinterpret_cast<const char*>(_str)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   const __FlashStringHelper* _str; | ||||||
|  |   size_t _size; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | inline FixedSizeFlashString makeString(const __FlashStringHelper* str, | ||||||
|  |                                        size_t sz) { | ||||||
|  |   return FixedSizeFlashString(str, sz); | ||||||
|  | } | ||||||
|  | }  // namespace Internals | ||||||
|  | }  // namespace ArduinoJson | ||||||
							
								
								
									
										48
									
								
								src/ArduinoJson/Strings/FixedSizeRamString.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/ArduinoJson/Strings/FixedSizeRamString.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace Internals { | ||||||
|  |  | ||||||
|  | class FixedSizeRamString { | ||||||
|  |  public: | ||||||
|  |   FixedSizeRamString(const char* str, size_t n) : _str(str), _size(n) {} | ||||||
|  |  | ||||||
|  |   bool equals(const char* expected) const { | ||||||
|  |     const char* actual = reinterpret_cast<const char*>(_str); | ||||||
|  |     if (!actual || !expected) return actual == expected; | ||||||
|  |     return strcmp(actual, expected) == 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool is_null() const { | ||||||
|  |     return !_str; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename Buffer> | ||||||
|  |   const char* save(Buffer* buffer) const { | ||||||
|  |     if (!_str) return NULL; | ||||||
|  |     void* dup = buffer->alloc(_size); | ||||||
|  |     if (!dup) return NULL; | ||||||
|  |     memcpy(dup, _str, _size); | ||||||
|  |     return static_cast<const char*>(dup); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t size() const { | ||||||
|  |     return strlen(reinterpret_cast<const char*>(_str)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   const char* _str; | ||||||
|  |   size_t _size; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename TChar> | ||||||
|  | inline FixedSizeRamString makeString(const TChar* str, size_t size) { | ||||||
|  |   return FixedSizeRamString(reinterpret_cast<const char*>(str), size); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace Internals | ||||||
|  | }  // namespace ArduinoJson | ||||||
| @@ -1,41 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2018 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #if ARDUINOJSON_ENABLE_PROGMEM |  | ||||||
|  |  | ||||||
| namespace ArduinoJson { |  | ||||||
| namespace Internals { |  | ||||||
| template <> |  | ||||||
| struct StringTraits<const __FlashStringHelper*, void> { |  | ||||||
|   static bool equals(const __FlashStringHelper* str, const char* expected) { |  | ||||||
|     const char* actual = reinterpret_cast<const char*>(str); |  | ||||||
|     if (!actual || !expected) return actual == expected; |  | ||||||
|     return strcmp_P(expected, actual) == 0; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static bool is_null(const __FlashStringHelper* str) { |  | ||||||
|     return !str; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   typedef const char* duplicate_t; |  | ||||||
|  |  | ||||||
|   template <typename Buffer> |  | ||||||
|   static duplicate_t duplicate(const __FlashStringHelper* str, Buffer* buffer) { |  | ||||||
|     if (!str) return NULL; |  | ||||||
|     size_t size = strlen_P((const char*)str) + 1; |  | ||||||
|     void* dup = buffer->alloc(size); |  | ||||||
|     if (dup != NULL) memcpy_P(dup, (const char*)str, size); |  | ||||||
|     return static_cast<duplicate_t>(dup); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static const bool has_append = false; |  | ||||||
|   static const bool has_equals = true; |  | ||||||
|   static const bool should_duplicate = true; |  | ||||||
| }; |  | ||||||
| }  // namespace Internals |  | ||||||
| }  // namespace ArduinoJson |  | ||||||
|  |  | ||||||
| #endif |  | ||||||
| @@ -1,73 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2018 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #if ARDUINOJSON_ENABLE_STD_STRING || ARDUINOJSON_ENABLE_ARDUINO_STRING |  | ||||||
|  |  | ||||||
| #if ARDUINOJSON_ENABLE_ARDUINO_STRING |  | ||||||
| #include <WString.h> |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if ARDUINOJSON_ENABLE_STD_STRING |  | ||||||
| #include <string> |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| namespace ArduinoJson { |  | ||||||
| namespace Internals { |  | ||||||
|  |  | ||||||
| template <typename TString> |  | ||||||
| struct StdStringTraits { |  | ||||||
|   typedef const char* duplicate_t; |  | ||||||
|  |  | ||||||
|   template <typename Buffer> |  | ||||||
|   static duplicate_t duplicate(const TString& str, Buffer* buffer) { |  | ||||||
|     if (!str.c_str()) return NULL;  // <- Arduino string can return NULL |  | ||||||
|     size_t size = str.length() + 1; |  | ||||||
|     void* dup = buffer->alloc(size); |  | ||||||
|     if (dup != NULL) memcpy(dup, str.c_str(), size); |  | ||||||
|     return static_cast<duplicate_t>(dup); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static bool is_null(const TString& str) { |  | ||||||
|     // Arduino's String::c_str() can return NULL |  | ||||||
|     return !str.c_str(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static bool equals(const TString& str, const char* expected) { |  | ||||||
|     // Arduino's String::c_str() can return NULL |  | ||||||
|     const char* actual = str.c_str(); |  | ||||||
|     if (!actual || !expected) return actual == expected; |  | ||||||
|     return 0 == strcmp(actual, expected); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static void append(TString& str, char c) { |  | ||||||
|     str += c; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static void append(TString& str, const char* s) { |  | ||||||
|     str += s; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static const bool has_append = true; |  | ||||||
|   static const bool has_equals = true; |  | ||||||
|   static const bool should_duplicate = true; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| #if ARDUINOJSON_ENABLE_ARDUINO_STRING |  | ||||||
| template <> |  | ||||||
| struct StringTraits<String, void> : StdStringTraits<String> {}; |  | ||||||
| template <> |  | ||||||
| struct StringTraits<StringSumHelper, void> : StdStringTraits<StringSumHelper> { |  | ||||||
| }; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if ARDUINOJSON_ENABLE_STD_STRING |  | ||||||
| template <> |  | ||||||
| struct StringTraits<std::string, void> : StdStringTraits<std::string> {}; |  | ||||||
| #endif |  | ||||||
| }  // namespace Internals |  | ||||||
| }  // namespace ArduinoJson |  | ||||||
|  |  | ||||||
| #endif |  | ||||||
							
								
								
									
										52
									
								
								src/ArduinoJson/Strings/StlString.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/ArduinoJson/Strings/StlString.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <string> | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace Internals { | ||||||
|  |  | ||||||
|  | class StlString { | ||||||
|  |  public: | ||||||
|  |   StlString(const std::string& str) : _str(&str) {} | ||||||
|  |  | ||||||
|  |   template <typename Buffer> | ||||||
|  |   const char* save(Buffer* buffer) const { | ||||||
|  |     size_t n = _str->length() + 1; | ||||||
|  |     void* dup = buffer->alloc(n); | ||||||
|  |     if (dup != NULL) memcpy(dup, _str->c_str(), n); | ||||||
|  |     return static_cast<const char*>(dup); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool is_null() const { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool equals(const char* expected) const { | ||||||
|  |     return *_str == expected; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   const char* data() const { | ||||||
|  |     return _str->data(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t size() const { | ||||||
|  |     return _str->size(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   const std::string* _str; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct IsString<std::string> : true_type {}; | ||||||
|  |  | ||||||
|  | inline StlString makeString(const std::string& str) { | ||||||
|  |   return StlString(str); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace Internals | ||||||
|  | }  // namespace ArduinoJson | ||||||
| @@ -1,30 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2018 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #include <string.h> |  | ||||||
| #include "../Configuration.hpp" |  | ||||||
| #include "../Polyfills/type_traits.hpp" |  | ||||||
|  |  | ||||||
| namespace ArduinoJson { |  | ||||||
| namespace Internals { |  | ||||||
|  |  | ||||||
| template <typename TString, typename Enable = void> |  | ||||||
| struct StringTraits { |  | ||||||
|   static const bool has_append = false; |  | ||||||
|   static const bool has_equals = false; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| template <typename TString> |  | ||||||
| struct StringTraits<const TString, void> : StringTraits<TString> {}; |  | ||||||
|  |  | ||||||
| template <typename TString> |  | ||||||
| struct StringTraits<TString&, void> : StringTraits<TString> {}; |  | ||||||
| }  // namespace Internals |  | ||||||
| }  // namespace ArduinoJson |  | ||||||
|  |  | ||||||
| #include "CharPointer.hpp" |  | ||||||
| #include "FlashString.hpp" |  | ||||||
| #include "StdString.hpp" |  | ||||||
							
								
								
									
										36
									
								
								src/ArduinoJson/Strings/StringTypes.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/ArduinoJson/Strings/StringTypes.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "../Polyfills/type_traits.hpp" | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace Internals { | ||||||
|  | template <typename> | ||||||
|  | struct IsString : false_type {}; | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | struct IsString<const T> : IsString<T> {}; | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | struct IsString<T&> : IsString<T> {}; | ||||||
|  | }  // namespace Internals | ||||||
|  | }  // namespace ArduinoJson | ||||||
|  |  | ||||||
|  | #include "FixedSizeRamString.hpp" | ||||||
|  | #include "ZeroTerminatedRamString.hpp" | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_ENABLE_STD_STRING | ||||||
|  | #include "StlString.hpp" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_ENABLE_ARDUINO_STRING | ||||||
|  | #include "ArduinoString.hpp" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_ENABLE_PROGMEM | ||||||
|  | #include "FixedSizeFlashString.hpp" | ||||||
|  | #include "ZeroTerminatedFlashString.hpp" | ||||||
|  | #endif | ||||||
							
								
								
									
										48
									
								
								src/ArduinoJson/Strings/ZeroTerminatedFlashString.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/ArduinoJson/Strings/ZeroTerminatedFlashString.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace Internals { | ||||||
|  |  | ||||||
|  | class ZeroTerminatedFlashString { | ||||||
|  |  public: | ||||||
|  |   ZeroTerminatedFlashString(const __FlashStringHelper* str) : _str(str) {} | ||||||
|  |  | ||||||
|  |   bool equals(const char* expected) const { | ||||||
|  |     const char* actual = reinterpret_cast<const char*>(_str); | ||||||
|  |     if (!actual || !expected) return actual == expected; | ||||||
|  |     return strcmp_P(actual, expected) == 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool is_null() const { | ||||||
|  |     return !_str; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename Buffer> | ||||||
|  |   const char* save(Buffer* buffer) const { | ||||||
|  |     if (!_str) return NULL; | ||||||
|  |     size_t n = size() + 1;  // copy the terminator | ||||||
|  |     void* dup = buffer->alloc(n); | ||||||
|  |     if (dup != NULL) memcpy_P(dup, (const char*)_str, n); | ||||||
|  |     return static_cast<const char*>(dup); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t size() const { | ||||||
|  |     return strlen_P(reinterpret_cast<const char*>(_str)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   const __FlashStringHelper* _str; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | inline ZeroTerminatedFlashString makeString(const __FlashStringHelper* str) { | ||||||
|  |   return ZeroTerminatedFlashString(str); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct IsString<const __FlashStringHelper*> : true_type {}; | ||||||
|  | }  // namespace Internals | ||||||
|  | }  // namespace ArduinoJson | ||||||
							
								
								
									
										53
									
								
								src/ArduinoJson/Strings/ZeroTerminatedRamString.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/ArduinoJson/Strings/ZeroTerminatedRamString.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace Internals { | ||||||
|  |  | ||||||
|  | class ZeroTerminatedRamString { | ||||||
|  |  public: | ||||||
|  |   ZeroTerminatedRamString(const char* str) : _str(str) {} | ||||||
|  |  | ||||||
|  |   bool equals(const char* expected) const { | ||||||
|  |     const char* actual = reinterpret_cast<const char*>(_str); | ||||||
|  |     if (!actual || !expected) return actual == expected; | ||||||
|  |     return strcmp(actual, expected) == 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool is_null() const { | ||||||
|  |     return !_str; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename Buffer> | ||||||
|  |   const char* save(Buffer* buffer) const { | ||||||
|  |     if (!_str) return NULL; | ||||||
|  |     size_t n = size() + 1; | ||||||
|  |     void* dup = buffer->alloc(n); | ||||||
|  |     if (!dup) return NULL; | ||||||
|  |     memcpy(dup, _str, n); | ||||||
|  |     return static_cast<const char*>(dup); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t size() const { | ||||||
|  |     return strlen(reinterpret_cast<const char*>(_str)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   const char* _str; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename TChar> | ||||||
|  | inline ZeroTerminatedRamString makeString(const TChar* str) { | ||||||
|  |   return ZeroTerminatedRamString(reinterpret_cast<const char*>(str)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename TChar> | ||||||
|  | struct IsString<TChar*> { | ||||||
|  |   static const bool value = sizeof(TChar) == 1; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace Internals | ||||||
|  | }  // namespace ArduinoJson | ||||||
| @@ -4,16 +4,17 @@ | |||||||
|  |  | ||||||
| add_executable(JsonArrayTests  | add_executable(JsonArrayTests  | ||||||
| 	add.cpp | 	add.cpp | ||||||
| 	basics.cpp |  | ||||||
| 	copyFrom.cpp | 	copyFrom.cpp | ||||||
| 	copyTo.cpp | 	copyTo.cpp | ||||||
| 	invalid.cpp | 	createNested.cpp | ||||||
|  | 	isNull.cpp | ||||||
| 	iterator.cpp | 	iterator.cpp | ||||||
| 	remove.cpp | 	remove.cpp | ||||||
| 	set.cpp | 	set.cpp | ||||||
| 	size.cpp | 	size.cpp | ||||||
| 	std_string.cpp | 	std_string.cpp | ||||||
| 	subscript.cpp | 	subscript.cpp | ||||||
|  | 	undefined.cpp | ||||||
| ) | ) | ||||||
|  |  | ||||||
| target_link_libraries(JsonArrayTests catch) | target_link_libraries(JsonArrayTests catch) | ||||||
|   | |||||||
| @@ -100,14 +100,26 @@ TEST_CASE("JsonArray::add()") { | |||||||
|     REQUIRE(expectedSize == doc.memoryUsage()); |     REQUIRE(expectedSize == doc.memoryUsage()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("should not duplicate RawJson(const char*)") { |   SECTION("should not duplicate serialized(const char*)") { | ||||||
|     _array.add(RawJson("{}")); |     _array.add(serialized("{}")); | ||||||
|     const size_t expectedSize = JSON_ARRAY_SIZE(1); |     const size_t expectedSize = JSON_ARRAY_SIZE(1); | ||||||
|     REQUIRE(expectedSize == doc.memoryUsage()); |     REQUIRE(expectedSize == doc.memoryUsage()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("should duplicate RawJson(char*)") { |   SECTION("should duplicate serialized(char*)") { | ||||||
|     _array.add(RawJson(const_cast<char*>("{}"))); |     _array.add(serialized(const_cast<char*>("{}"))); | ||||||
|  |     const size_t expectedSize = JSON_ARRAY_SIZE(1) + 2; | ||||||
|  |     REQUIRE(expectedSize == doc.memoryUsage()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate serialized(std::string)") { | ||||||
|  |     _array.add(serialized(std::string("{}"))); | ||||||
|  |     const size_t expectedSize = JSON_ARRAY_SIZE(1) + 2; | ||||||
|  |     REQUIRE(expectedSize == doc.memoryUsage()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate serialized(std::string)") { | ||||||
|  |     _array.add(serialized(std::string("\0XX", 3))); | ||||||
|     const size_t expectedSize = JSON_ARRAY_SIZE(1) + 3; |     const size_t expectedSize = JSON_ARRAY_SIZE(1) + 3; | ||||||
|     REQUIRE(expectedSize == doc.memoryUsage()); |     REQUIRE(expectedSize == doc.memoryUsage()); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -9,14 +9,6 @@ TEST_CASE("JsonArray basics") { | |||||||
|   DynamicJsonDocument doc; |   DynamicJsonDocument doc; | ||||||
|   JsonArray array = doc.to<JsonArray>(); |   JsonArray array = doc.to<JsonArray>(); | ||||||
| 
 | 
 | ||||||
|   SECTION("isNull()") { |  | ||||||
|     REQUIRE(array.isNull() == false); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   SECTION("InitialSizeIsZero") { |  | ||||||
|     REQUIRE(0U == array.size()); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   SECTION("CreateNestedArray") { |   SECTION("CreateNestedArray") { | ||||||
|     JsonArray arr = array.createNestedArray(); |     JsonArray arr = array.createNestedArray(); | ||||||
|     REQUIRE(arr == array[0].as<JsonArray>()); |     REQUIRE(arr == array[0].as<JsonArray>()); | ||||||
							
								
								
									
										25
									
								
								test/JsonArray/isNull.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								test/JsonArray/isNull.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonArray::isNull()") { | ||||||
|  |   SECTION("returns true for undefined JsonArray") { | ||||||
|  |     JsonArray array; | ||||||
|  |     REQUIRE(array.isNull() == true); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("returns false when allocation succeeds") { | ||||||
|  |     StaticJsonDocument<JSON_ARRAY_SIZE(0)> doc; | ||||||
|  |     JsonArray array = doc.to<JsonArray>(); | ||||||
|  |     REQUIRE(array.isNull() == false); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("returns true when allocation fails") { | ||||||
|  |     StaticJsonDocument<1> doc; | ||||||
|  |     JsonArray array = doc.to<JsonArray>(); | ||||||
|  |     REQUIRE(array.isNull() == true); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -7,29 +7,33 @@ | |||||||
|  |  | ||||||
| TEST_CASE("JsonArray::size()") { | TEST_CASE("JsonArray::size()") { | ||||||
|   DynamicJsonDocument doc; |   DynamicJsonDocument doc; | ||||||
|   JsonArray _array = doc.to<JsonArray>(); |   JsonArray array = doc.to<JsonArray>(); | ||||||
|  |  | ||||||
|  |   SECTION("InitialSizeIsZero") { | ||||||
|  |     REQUIRE(0U == array.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   SECTION("increases after add()") { |   SECTION("increases after add()") { | ||||||
|     _array.add("hello"); |     array.add("hello"); | ||||||
|     REQUIRE(1U == _array.size()); |     REQUIRE(1U == array.size()); | ||||||
|  |  | ||||||
|     _array.add("world"); |     array.add("world"); | ||||||
|     REQUIRE(2U == _array.size()); |     REQUIRE(2U == array.size()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("remains the same after set()") { |   SECTION("remains the same after set()") { | ||||||
|     _array.add("hello"); |     array.add("hello"); | ||||||
|     REQUIRE(1U == _array.size()); |     REQUIRE(1U == array.size()); | ||||||
|  |  | ||||||
|     _array.set(0, "hello"); |     array.set(0, "hello"); | ||||||
|     REQUIRE(1U == _array.size()); |     REQUIRE(1U == array.size()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("remains the same after assigment") { |   SECTION("remains the same after assigment") { | ||||||
|     _array.add("hello"); |     array.add("hello"); | ||||||
|     REQUIRE(1U == _array.size()); |     REQUIRE(1U == array.size()); | ||||||
|  |  | ||||||
|     _array[0] = "hello"; |     array[0] = "hello"; | ||||||
|     REQUIRE(1U == _array.size()); |     REQUIRE(1U == array.size()); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -3,10 +3,10 @@ | |||||||
| # MIT License | # MIT License | ||||||
|  |  | ||||||
| add_executable(JsonObjectTests  | add_executable(JsonObjectTests  | ||||||
| 	basics.cpp |  | ||||||
| 	containsKey.cpp | 	containsKey.cpp | ||||||
| 	get.cpp | 	get.cpp | ||||||
| 	invalid.cpp | 	invalid.cpp | ||||||
|  | 	isNull.cpp | ||||||
| 	iterator.cpp | 	iterator.cpp | ||||||
| 	remove.cpp | 	remove.cpp | ||||||
| 	set.cpp | 	set.cpp | ||||||
|   | |||||||
| @@ -1,15 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2018 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #include <ArduinoJson.h> |  | ||||||
| #include <catch.hpp> |  | ||||||
|  |  | ||||||
| TEST_CASE("JsonObject basics") { |  | ||||||
|   DynamicJsonDocument doc; |  | ||||||
|   JsonObject obj = doc.to<JsonObject>(); |  | ||||||
|  |  | ||||||
|   SECTION("isNull()") { |  | ||||||
|     REQUIRE(obj.isNull() == false); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
							
								
								
									
										25
									
								
								test/JsonObject/isNull.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								test/JsonObject/isNull.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonObject::isNull()") { | ||||||
|  |   SECTION("returns true for undefined JsonObject") { | ||||||
|  |     JsonObject array; | ||||||
|  |     REQUIRE(array.isNull() == true); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("returns false when allocation succeeds") { | ||||||
|  |     StaticJsonDocument<JSON_OBJECT_SIZE(0)> doc; | ||||||
|  |     JsonObject array = doc.to<JsonObject>(); | ||||||
|  |     REQUIRE(array.isNull() == false); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("returns true when allocation fails") { | ||||||
|  |     StaticJsonDocument<1> doc; | ||||||
|  |     JsonObject array = doc.to<JsonObject>(); | ||||||
|  |     REQUIRE(array.isNull() == true); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -67,15 +67,15 @@ TEST_CASE("serializeJson(JsonArray)") { | |||||||
|     check(array, "[1,2]"); |     check(array, "[1,2]"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("RawJson(const char*)") { |   SECTION("serialized(const char*)") { | ||||||
|     array.add(RawJson("{\"key\":\"value\"}")); |     array.add(serialized("{\"key\":\"value\"}")); | ||||||
|  |  | ||||||
|     check(array, "[{\"key\":\"value\"}]"); |     check(array, "[{\"key\":\"value\"}]"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("RawJson(char*)") { |   SECTION("serialized(char*)") { | ||||||
|     char tmp[] = "{\"key\":\"value\"}"; |     char tmp[] = "{\"key\":\"value\"}"; | ||||||
|     array.add(RawJson(tmp)); |     array.add(serialized(tmp)); | ||||||
|  |  | ||||||
|     check(array, "[{\"key\":\"value\"}]"); |     check(array, "[{\"key\":\"value\"}]"); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -68,9 +68,9 @@ TEST_CASE("serializeJson(JsonObject)") { | |||||||
|     check(obj, "{\"a\":1,\"b\":2}"); |     check(obj, "{\"a\":1,\"b\":2}"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("RawJson") { |   SECTION("serialized(const char*)") { | ||||||
|     obj["a"] = RawJson("[1,2]"); |     obj["a"] = serialized("[1,2]"); | ||||||
|     obj.set("b", RawJson("[4,5]")); |     obj.set("b", serialized("[4,5]")); | ||||||
|     check(obj, "{\"a\":[1,2],\"b\":[4,5]}"); |     check(obj, "{\"a\":[1,2],\"b\":[4,5]}"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -95,21 +95,4 @@ TEST_CASE("JsonVariant::is()") { | |||||||
|   SECTION("string") { |   SECTION("string") { | ||||||
|     checkIsString("42"); |     checkIsString("42"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("unparsed bool") { |  | ||||||
|     checkIsBool(RawJson("true")); |  | ||||||
|     checkIsBool(RawJson("false")); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("unparsed int") { |  | ||||||
|     checkIsInteger(RawJson("42")); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("unparsed float") { |  | ||||||
|     checkIsFloat(RawJson("4.2e-10")); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("unparsed null") { |  | ||||||
|     checkIsString(RawJson("null")); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,15 +7,15 @@ | |||||||
| #include <string> | #include <string> | ||||||
|  |  | ||||||
| #include <ArduinoJson/Json/JsonWriter.hpp> | #include <ArduinoJson/Json/JsonWriter.hpp> | ||||||
| #include <ArduinoJson/Serialization/DynamicStringBuilder.hpp> | #include <ArduinoJson/Serialization/DynamicStringWriter.hpp> | ||||||
|  |  | ||||||
| using namespace ArduinoJson::Internals; | using namespace ArduinoJson::Internals; | ||||||
|  |  | ||||||
| template <typename TFloat> | template <typename TFloat> | ||||||
| void check(TFloat input, const std::string& expected) { | void check(TFloat input, const std::string& expected) { | ||||||
|   std::string output; |   std::string output; | ||||||
|   DynamicStringBuilder<std::string> sb(output); |   DynamicStringWriter<std::string> sb(output); | ||||||
|   JsonWriter<DynamicStringBuilder<std::string> > writer(sb); |   JsonWriter<DynamicStringWriter<std::string> > writer(sb); | ||||||
|   writer.writeFloat(input); |   writer.writeFloat(input); | ||||||
|   REQUIRE(writer.bytesWritten() == output.size()); |   REQUIRE(writer.bytesWritten() == output.size()); | ||||||
|   CHECK(expected == output); |   CHECK(expected == output); | ||||||
|   | |||||||
| @@ -5,14 +5,14 @@ | |||||||
| #include <catch.hpp> | #include <catch.hpp> | ||||||
|  |  | ||||||
| #include <ArduinoJson/Json/JsonWriter.hpp> | #include <ArduinoJson/Json/JsonWriter.hpp> | ||||||
| #include <ArduinoJson/Serialization/StaticStringBuilder.hpp> | #include <ArduinoJson/Serialization/StaticStringWriter.hpp> | ||||||
|  |  | ||||||
| using namespace ArduinoJson::Internals; | using namespace ArduinoJson::Internals; | ||||||
|  |  | ||||||
| void check(const char* input, std::string expected) { | void check(const char* input, std::string expected) { | ||||||
|   char output[1024]; |   char output[1024]; | ||||||
|   StaticStringBuilder sb(output, sizeof(output)); |   StaticStringWriter sb(output, sizeof(output)); | ||||||
|   JsonWriter<StaticStringBuilder> writer(sb); |   JsonWriter<StaticStringWriter> writer(sb); | ||||||
|   writer.writeString(input); |   writer.writeString(input); | ||||||
|   REQUIRE(expected == output); |   REQUIRE(expected == output); | ||||||
|   REQUIRE(writer.bytesWritten() == expected.size()); |   REQUIRE(writer.bytesWritten() == expected.size()); | ||||||
|   | |||||||
| @@ -4,8 +4,7 @@ | |||||||
|  |  | ||||||
| add_executable(MiscTests | add_executable(MiscTests | ||||||
| 	FloatParts.cpp | 	FloatParts.cpp | ||||||
| 	StringBuilder.cpp | 	StringWriter.cpp | ||||||
| 	StringTraits.cpp |  | ||||||
| 	TypeTraits.cpp | 	TypeTraits.cpp | ||||||
| 	unsigned_char.cpp | 	unsigned_char.cpp | ||||||
| 	version.cpp | 	version.cpp | ||||||
|   | |||||||
| @@ -1,22 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2018 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #include <ArduinoJson.h> |  | ||||||
| #include <catch.hpp> |  | ||||||
|  |  | ||||||
| using namespace ArduinoJson::Internals; |  | ||||||
|  |  | ||||||
| template <typename String> |  | ||||||
| bool should_duplicate() { |  | ||||||
|   return StringTraits<String>::should_duplicate; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| TEST_CASE("StringTraits") { |  | ||||||
|   SECTION("should_duplicate") { |  | ||||||
|     REQUIRE(false == should_duplicate<const char*>()); |  | ||||||
|     REQUIRE(true == should_duplicate<char*>()); |  | ||||||
|     REQUIRE(true == should_duplicate<RawJsonString<char*> >()); |  | ||||||
|     REQUIRE(false == should_duplicate<RawJsonString<const char*> >()); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -7,44 +7,49 @@ | |||||||
| 
 | 
 | ||||||
| using namespace ArduinoJson::Internals; | using namespace ArduinoJson::Internals; | ||||||
| 
 | 
 | ||||||
| template <typename StringBuilder, typename String> | template <typename StringWriter> | ||||||
| void common_tests(StringBuilder& sb, const String& output) { | static size_t print(StringWriter& sb, const char* s) { | ||||||
|  |   return sb.write(reinterpret_cast<const uint8_t*>(s), strlen(s)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <typename StringWriter, typename String> | ||||||
|  | void common_tests(StringWriter& sb, const String& output) { | ||||||
|   SECTION("InitialState") { |   SECTION("InitialState") { | ||||||
|     REQUIRE(std::string("") == output); |     REQUIRE(std::string("") == output); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   SECTION("EmptyString") { |   SECTION("EmptyString") { | ||||||
|     REQUIRE(0 == sb.print("")); |     REQUIRE(0 == print(sb, "")); | ||||||
|     REQUIRE(std::string("") == output); |     REQUIRE(std::string("") == output); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   SECTION("OneString") { |   SECTION("OneString") { | ||||||
|     REQUIRE(4 == sb.print("ABCD")); |     REQUIRE(4 == print(sb, "ABCD")); | ||||||
|     REQUIRE(std::string("ABCD") == output); |     REQUIRE(std::string("ABCD") == output); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   SECTION("TwoStrings") { |   SECTION("TwoStrings") { | ||||||
|     REQUIRE(4 == sb.print("ABCD")); |     REQUIRE(4 == print(sb, "ABCD")); | ||||||
|     REQUIRE(4 == sb.print("EFGH")); |     REQUIRE(4 == print(sb, "EFGH")); | ||||||
|     REQUIRE(std::string("ABCDEFGH") == output); |     REQUIRE(std::string("ABCDEFGH") == output); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("StaticStringBuilder") { | TEST_CASE("StaticStringWriter") { | ||||||
|   char output[20]; |   char output[20]; | ||||||
|   StaticStringBuilder 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 == sb.print("ABCDEFGHIJKLMNOPQRSTUVWXYZ")); |     REQUIRE(19 == print(sb, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); | ||||||
|     REQUIRE(0 == sb.print("ABC")); |     REQUIRE(0 == print(sb, "ABC")); | ||||||
|     REQUIRE(std::string("ABCDEFGHIJKLMNOPQRS") == output); |     REQUIRE(std::string("ABCDEFGHIJKLMNOPQRS") == output); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("DynamicStringBuilder") { | TEST_CASE("DynamicStringWriter") { | ||||||
|   std::string output; |   std::string output; | ||||||
|   DynamicStringBuilder<std::string> sb(output); |   DynamicStringWriter<std::string> sb(output); | ||||||
|   common_tests(sb, output); |   common_tests(sb, output); | ||||||
| } | } | ||||||
| @@ -70,4 +70,14 @@ TEST_CASE("serialize MsgPack object") { | |||||||
|   // |   // | ||||||
|   //   check(object, expected); |   //   check(object, expected); | ||||||
|   // } |   // } | ||||||
|  |  | ||||||
|  |   SECTION("serialized(const char*)") { | ||||||
|  |     object["hello"] = serialized("\xDB\x00\x01\x00\x00", 5); | ||||||
|  |     check(object, "\x81\xA5hello\xDB\x00\x01\x00\x00"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("serialized(std::string)") { | ||||||
|  |     object["hello"] = serialized(std::string("\xDB\x00\x01\x00\x00", 5)); | ||||||
|  |     check(object, "\x81\xA5hello\xDB\x00\x01\x00\x00"); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -126,4 +126,9 @@ TEST_CASE("serialize MsgPack value") { | |||||||
|     std::string shortest(65536, '?'); |     std::string shortest(65536, '?'); | ||||||
|     check(shortest.c_str(), std::string("\xDB\x00\x01\x00\x00", 5) + shortest); |     check(shortest.c_str(), std::string("\xDB\x00\x01\x00\x00", 5) + shortest); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("serialized(const char*)") { | ||||||
|  |     check(serialized("\xDA\xFF\xFF"), "\xDA\xFF\xFF"); | ||||||
|  |     check(serialized("\xDB\x00\x01\x00\x00", 5), "\xDB\x00\x01\x00\x00"); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user