forked from bblanchon/ArduinoJson
Added support for Stream
(issue #300)
This commit is contained in:
@ -5,6 +5,7 @@ HEAD
|
|||||||
----
|
----
|
||||||
|
|
||||||
* Added operator `==` to compare `JsonVariant` and strings (issue #402)
|
* Added operator `==` to compare `JsonVariant` and strings (issue #402)
|
||||||
|
* Added support for `Stream` (issue #300)
|
||||||
* Reduced memory consumption by not duplicating spaces and comments
|
* Reduced memory consumption by not duplicating spaces and comments
|
||||||
|
|
||||||
v5.7.3
|
v5.7.3
|
||||||
|
@ -5,9 +5,10 @@ Arduino JSON library
|
|||||||
|
|
||||||
*An elegant and efficient JSON library for embedded systems.*
|
*An elegant and efficient JSON library for embedded systems.*
|
||||||
|
|
||||||
It's designed to have the most intuitive API, the smallest footprint and works without any allocation on the heap (no malloc).
|
It's designed to have the most intuitive API, the smallest footprint and is able to work without any allocation on the heap (no malloc).
|
||||||
|
|
||||||
It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project.
|
It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project.
|
||||||
|
For instance, it supports Aduino's `String` and `Stream`, but also `std::string`, `std::istream` and `std::ostream`.
|
||||||
|
|
||||||
Features
|
Features
|
||||||
--------
|
--------
|
||||||
@ -55,6 +56,8 @@ double latitude = root["data"][0];
|
|||||||
double longitude = root["data"][1];
|
double longitude = root["data"][1];
|
||||||
```
|
```
|
||||||
|
|
||||||
|
[See JsonParserExample.ino](examples/JsonParserExample/JsonParserExample.ino)
|
||||||
|
|
||||||
#### Encoding / Generating
|
#### Encoding / Generating
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
@ -73,6 +76,8 @@ root.printTo(Serial);
|
|||||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
[See JsonGeneratorExample.ino](examples/JsonGeneratorExample/JsonGeneratorExample.ino)
|
||||||
|
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
-------------
|
-------------
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
// If you like this project, please add a star!
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <SPI.h>
|
|
||||||
#include <Ethernet.h>
|
#include <Ethernet.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
EthernetClient client;
|
EthernetClient client;
|
||||||
|
|
||||||
@ -36,11 +36,8 @@ void setup() {
|
|||||||
void loop() {
|
void loop() {
|
||||||
if (connect(server)) {
|
if (connect(server)) {
|
||||||
if (sendRequest(server, resource) && skipResponseHeaders()) {
|
if (sendRequest(server, resource) && skipResponseHeaders()) {
|
||||||
char response[MAX_CONTENT_SIZE];
|
|
||||||
readReponseContent(response, sizeof(response));
|
|
||||||
|
|
||||||
UserData userData;
|
UserData userData;
|
||||||
if (parseUserData(response, &userData)) {
|
if (readReponseContent(&userData)) {
|
||||||
printUserData(&userData);
|
printUserData(&userData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,7 +86,7 @@ bool sendRequest(const char* host, const char* resource) {
|
|||||||
client.print(resource);
|
client.print(resource);
|
||||||
client.println(" HTTP/1.0");
|
client.println(" HTTP/1.0");
|
||||||
client.print("Host: ");
|
client.print("Host: ");
|
||||||
client.println(server);
|
client.println(host);
|
||||||
client.println("Connection: close");
|
client.println("Connection: close");
|
||||||
client.println();
|
client.println();
|
||||||
|
|
||||||
@ -111,13 +108,6 @@ bool skipResponseHeaders() {
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the body of the response from the HTTP server
|
|
||||||
void readReponseContent(char* content, size_t maxSize) {
|
|
||||||
size_t length = client.readBytes(content, maxSize);
|
|
||||||
content[length] = 0;
|
|
||||||
Serial.println(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the JSON from the input string and extract the interesting values
|
// Parse the JSON from the input string and extract the interesting values
|
||||||
// Here is the JSON we need to parse
|
// Here is the JSON we need to parse
|
||||||
// {
|
// {
|
||||||
@ -143,21 +133,20 @@ void readReponseContent(char* content, size_t maxSize) {
|
|||||||
// "bs": "harness real-time e-markets"
|
// "bs": "harness real-time e-markets"
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
bool parseUserData(char* content, struct UserData* userData) {
|
bool readReponseContent(struct UserData* userData) {
|
||||||
// Compute optimal size of the JSON buffer according to what we need to parse.
|
// Compute optimal size of the JSON buffer according to what we need to parse.
|
||||||
// This is only required if you use StaticJsonBuffer.
|
// This is only required if you use StaticJsonBuffer.
|
||||||
const size_t BUFFER_SIZE =
|
const size_t BUFFER_SIZE =
|
||||||
JSON_OBJECT_SIZE(8) // the root object has 8 elements
|
JSON_OBJECT_SIZE(8) // the root object has 8 elements
|
||||||
+ JSON_OBJECT_SIZE(5) // the "address" object has 5 elements
|
+ JSON_OBJECT_SIZE(5) // the "address" object has 5 elements
|
||||||
+ JSON_OBJECT_SIZE(2) // the "geo" object has 2 elements
|
+ JSON_OBJECT_SIZE(2) // the "geo" object has 2 elements
|
||||||
+ JSON_OBJECT_SIZE(3); // the "company" object has 3 elements
|
+ JSON_OBJECT_SIZE(3) // the "company" object has 3 elements
|
||||||
|
+ MAX_CONTENT_SIZE; // additional space for strings
|
||||||
|
|
||||||
// Allocate a temporary memory pool on the stack
|
// Allocate a temporary memory pool
|
||||||
StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
|
DynamicJsonBuffer jsonBuffer(BUFFER_SIZE);
|
||||||
// If the memory pool is too big for the stack, use this instead:
|
|
||||||
// DynamicJsonBuffer jsonBuffer;
|
|
||||||
|
|
||||||
JsonObject& root = jsonBuffer.parseObject(content);
|
JsonObject& root = jsonBuffer.parseObject(client);
|
||||||
|
|
||||||
if (!root.success()) {
|
if (!root.success()) {
|
||||||
Serial.println("JSON parsing failed!");
|
Serial.println("JSON parsing failed!");
|
||||||
|
@ -27,6 +27,10 @@
|
|||||||
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
|
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||||
|
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
|
||||||
|
#endif
|
||||||
|
|
||||||
// On AVR archiecture, we can use PROGMEM
|
// On AVR archiecture, we can use PROGMEM
|
||||||
#ifndef ARDUINOJSON_ENABLE_PROGMEM
|
#ifndef ARDUINOJSON_ENABLE_PROGMEM
|
||||||
#ifdef PROGMEM
|
#ifdef PROGMEM
|
||||||
@ -106,6 +110,11 @@
|
|||||||
#define ARDUINOJSON_ENABLE_STD_STREAM 1
|
#define ARDUINOJSON_ENABLE_STD_STREAM 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// on a computer, there is no reason to beleive Arduino Stream is available
|
||||||
|
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||||
|
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
|
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
|
||||||
// even if not required, most cpu's are faster with aligned pointers
|
// even if not required, most cpu's are faster with aligned pointers
|
||||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
|
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
|
||||||
|
@ -1,148 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2016
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
// If you like this project, please add a star!
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../Configuration.hpp"
|
|
||||||
|
|
||||||
#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 StringFuncs {};
|
|
||||||
|
|
||||||
template <typename TString>
|
|
||||||
struct StringFuncs<const TString> : StringFuncs<TString> {};
|
|
||||||
|
|
||||||
template <typename TString>
|
|
||||||
struct StringFuncs<TString&> : StringFuncs<TString> {};
|
|
||||||
|
|
||||||
struct CharPtrFuncs {
|
|
||||||
class Iterator {
|
|
||||||
const char* _ptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Iterator(const char* ptr) : _ptr(ptr ? ptr : "") {}
|
|
||||||
|
|
||||||
char next() {
|
|
||||||
return *_ptr++;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool equals(const char* str, const char* expected) {
|
|
||||||
return strcmp(str, expected) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Buffer>
|
|
||||||
static char* duplicate(const char* str, Buffer* buffer) {
|
|
||||||
if (!str) return NULL;
|
|
||||||
size_t size = strlen(str) + 1;
|
|
||||||
void* dup = buffer->alloc(size);
|
|
||||||
if (dup != NULL) memcpy(dup, str, size);
|
|
||||||
return static_cast<char*>(dup);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const bool has_append = false;
|
|
||||||
static const bool has_equals = true;
|
|
||||||
static const bool should_duplicate = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct StringFuncs<const char*> : CharPtrFuncs {};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct StringFuncs<char*> : CharPtrFuncs {};
|
|
||||||
|
|
||||||
template <size_t N>
|
|
||||||
struct StringFuncs<char[N]> : CharPtrFuncs {};
|
|
||||||
|
|
||||||
template <size_t N>
|
|
||||||
struct StringFuncs<const char[N]> : CharPtrFuncs {};
|
|
||||||
|
|
||||||
template <typename TString>
|
|
||||||
struct StdStringFuncs {
|
|
||||||
template <typename Buffer>
|
|
||||||
static char* 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<char*>(dup);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Iterator : CharPtrFuncs::Iterator {
|
|
||||||
Iterator(const TString& str) : CharPtrFuncs::Iterator(str.c_str()) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool equals(const TString& str, const char* expected) {
|
|
||||||
return str == expected;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void append(TString& str, char c) {
|
|
||||||
str += c;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 StringFuncs<String> : StdStringFuncs<String> {};
|
|
||||||
template <>
|
|
||||||
struct StringFuncs<StringSumHelper> : StdStringFuncs<StringSumHelper> {};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_STD_STRING
|
|
||||||
template <>
|
|
||||||
struct StringFuncs<std::string> : StdStringFuncs<std::string> {};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_PROGMEM
|
|
||||||
template <>
|
|
||||||
struct StringFuncs<const __FlashStringHelper*> {
|
|
||||||
class Iterator {
|
|
||||||
const char* _ptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Iterator(const __FlashStringHelper* ptr)
|
|
||||||
: _ptr(reinterpret_cast<const char*>(ptr)) {}
|
|
||||||
|
|
||||||
char next() {
|
|
||||||
return pgm_read_byte_near(_ptr++);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool equals(const __FlashStringHelper* str, const char* expected) {
|
|
||||||
return strcmp_P(expected, (PGM_P)str) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Buffer>
|
|
||||||
static char* duplicate(const __FlashStringHelper* str, Buffer* buffer) {
|
|
||||||
if (!str) return NULL;
|
|
||||||
size_t size = strlen_P((PGM_P)str) + 1;
|
|
||||||
void* dup = buffer->alloc(size);
|
|
||||||
if (dup != NULL) memcpy_P(dup, (PGM_P)str, size);
|
|
||||||
return static_cast<char*>(dup);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const bool has_append = false;
|
|
||||||
static const bool has_equals = true;
|
|
||||||
static const bool should_duplicate = true;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
#include "../JsonBuffer.hpp"
|
#include "../JsonBuffer.hpp"
|
||||||
#include "../JsonVariant.hpp"
|
#include "../JsonVariant.hpp"
|
||||||
|
#include "../StringTraits/StringTraits.hpp"
|
||||||
#include "../TypeTraits/EnableIf.hpp"
|
#include "../TypeTraits/EnableIf.hpp"
|
||||||
#include "StringFuncs.hpp"
|
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
namespace Internals {
|
namespace Internals {
|
||||||
|
@ -77,7 +77,7 @@ struct JsonParserBuilder {
|
|||||||
typedef typename Internals::StringFuncs<TString>::Iterator InputIterator;
|
typedef typename Internals::StringFuncs<TString>::Iterator InputIterator;
|
||||||
typedef JsonParser<StringReader<InputIterator>, TJsonBuffer &> TParser;
|
typedef JsonParser<StringReader<InputIterator>, TJsonBuffer &> TParser;
|
||||||
|
|
||||||
static TParser makeParser(TJsonBuffer *buffer, const TString &json,
|
static TParser makeParser(TJsonBuffer *buffer, TString &json,
|
||||||
uint8_t nestingLimit) {
|
uint8_t nestingLimit) {
|
||||||
return TParser(buffer, InputIterator(json), *buffer, nestingLimit);
|
return TParser(buffer, InputIterator(json), *buffer, nestingLimit);
|
||||||
}
|
}
|
||||||
@ -94,9 +94,9 @@ struct JsonParserBuilder<TJsonBuffer, char *> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TJsonBuffer, typename TChar, size_t N>
|
template <typename TJsonBuffer, size_t N>
|
||||||
struct JsonParserBuilder<TJsonBuffer, TChar[N]>
|
struct JsonParserBuilder<TJsonBuffer, char[N]>
|
||||||
: JsonParserBuilder<TJsonBuffer, TChar *> {};
|
: JsonParserBuilder<TJsonBuffer, char *> {};
|
||||||
|
|
||||||
template <typename TJsonBuffer, typename TString>
|
template <typename TJsonBuffer, typename TString>
|
||||||
inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser(
|
inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser(
|
||||||
|
@ -10,10 +10,10 @@
|
|||||||
#include "Data/JsonBufferAllocated.hpp"
|
#include "Data/JsonBufferAllocated.hpp"
|
||||||
#include "Data/List.hpp"
|
#include "Data/List.hpp"
|
||||||
#include "Data/ReferenceType.hpp"
|
#include "Data/ReferenceType.hpp"
|
||||||
#include "Data/StringFuncs.hpp"
|
|
||||||
#include "Data/ValueSetter.hpp"
|
#include "Data/ValueSetter.hpp"
|
||||||
#include "JsonVariant.hpp"
|
#include "JsonVariant.hpp"
|
||||||
#include "Serialization/JsonPrintable.hpp"
|
#include "Serialization/JsonPrintable.hpp"
|
||||||
|
#include "StringTraits/StringTraits.hpp"
|
||||||
#include "TypeTraits/ConstRefOrConstPtr.hpp"
|
#include "TypeTraits/ConstRefOrConstPtr.hpp"
|
||||||
#include "TypeTraits/EnableIf.hpp"
|
#include "TypeTraits/EnableIf.hpp"
|
||||||
#include "TypeTraits/IsFloatingPoint.hpp"
|
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||||
|
@ -10,10 +10,10 @@
|
|||||||
#include "Data/JsonBufferAllocated.hpp"
|
#include "Data/JsonBufferAllocated.hpp"
|
||||||
#include "Data/List.hpp"
|
#include "Data/List.hpp"
|
||||||
#include "Data/ReferenceType.hpp"
|
#include "Data/ReferenceType.hpp"
|
||||||
#include "Data/StringFuncs.hpp"
|
|
||||||
#include "Data/ValueSetter.hpp"
|
#include "Data/ValueSetter.hpp"
|
||||||
#include "JsonPair.hpp"
|
#include "JsonPair.hpp"
|
||||||
#include "Serialization/JsonPrintable.hpp"
|
#include "Serialization/JsonPrintable.hpp"
|
||||||
|
#include "StringTraits/StringTraits.hpp"
|
||||||
#include "TypeTraits/ConstRefOrConstPtr.hpp"
|
#include "TypeTraits/ConstRefOrConstPtr.hpp"
|
||||||
#include "TypeTraits/EnableIf.hpp"
|
#include "TypeTraits/EnableIf.hpp"
|
||||||
#include "TypeTraits/IsFloatingPoint.hpp"
|
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Data/StringFuncs.hpp"
|
|
||||||
#include "JsonVariantBase.hpp"
|
#include "JsonVariantBase.hpp"
|
||||||
|
#include "StringTraits/StringTraits.hpp"
|
||||||
#include "TypeTraits/EnableIf.hpp"
|
#include "TypeTraits/EnableIf.hpp"
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Data/StringFuncs.hpp"
|
|
||||||
#include "../Print.hpp"
|
#include "../Print.hpp"
|
||||||
|
#include "../StringTraits/StringTraits.hpp"
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
namespace Internals {
|
namespace Internals {
|
||||||
|
39
include/ArduinoJson/StringTraits/ArduinoStream.hpp
Normal file
39
include/ArduinoJson/StringTraits/ArduinoStream.hpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../TypeTraits/EnableIf.hpp"
|
||||||
|
#include "../TypeTraits/IsBaseOf.hpp"
|
||||||
|
#include "../TypeTraits/RemoveReference.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Internals {
|
||||||
|
|
||||||
|
struct StdStreamFuncs {
|
||||||
|
class Iterator {
|
||||||
|
Stream& _stream;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Iterator(Stream& stream) : _stream(stream) {}
|
||||||
|
|
||||||
|
char next() {
|
||||||
|
int n = _stream.read();
|
||||||
|
return n >= 0 ? static_cast<char>(n) : '\0';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TStream>
|
||||||
|
struct StringFuncs<TStream,
|
||||||
|
// match any type that is derived from std::istream:
|
||||||
|
typename TypeTraits::EnableIf<TypeTraits::IsBaseOf<
|
||||||
|
Stream, typename TypeTraits::RemoveReference<
|
||||||
|
TStream>::type>::value>::type>
|
||||||
|
: StdStreamFuncs {};
|
||||||
|
}
|
||||||
|
}
|
57
include/ArduinoJson/StringTraits/CharPointer.hpp
Normal file
57
include/ArduinoJson/StringTraits/CharPointer.hpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Internals {
|
||||||
|
|
||||||
|
struct CharPtrFuncs {
|
||||||
|
class Iterator {
|
||||||
|
const char* _ptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Iterator(const char* ptr) : _ptr(ptr ? ptr : "") {}
|
||||||
|
|
||||||
|
char next() {
|
||||||
|
char c = *_ptr;
|
||||||
|
if (c) ++_ptr;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool equals(const char* str, const char* expected) {
|
||||||
|
return strcmp(str, expected) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Buffer>
|
||||||
|
static char* duplicate(const char* str, Buffer* buffer) {
|
||||||
|
if (!str) return NULL;
|
||||||
|
size_t size = strlen(str) + 1;
|
||||||
|
void* dup = buffer->alloc(size);
|
||||||
|
if (dup != NULL) memcpy(dup, str, size);
|
||||||
|
return static_cast<char*>(dup);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const bool has_append = false;
|
||||||
|
static const bool has_equals = true;
|
||||||
|
static const bool should_duplicate = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct StringFuncs<const char*, void> : CharPtrFuncs {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct StringFuncs<char*, void> : CharPtrFuncs {};
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
struct StringFuncs<char[N], void> : CharPtrFuncs {};
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
struct StringFuncs<const char[N], void> : CharPtrFuncs {};
|
||||||
|
}
|
||||||
|
}
|
44
include/ArduinoJson/StringTraits/FlashString.hpp
Normal file
44
include/ArduinoJson/StringTraits/FlashString.hpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Internals {
|
||||||
|
template <>
|
||||||
|
struct StringFuncs<const __FlashStringHelper*, void> {
|
||||||
|
class Iterator {
|
||||||
|
const char* _ptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Iterator(const __FlashStringHelper* ptr)
|
||||||
|
: _ptr(reinterpret_cast<const char*>(ptr)) {}
|
||||||
|
|
||||||
|
char next() {
|
||||||
|
return pgm_read_byte_near(_ptr++);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool equals(const __FlashStringHelper* str, const char* expected) {
|
||||||
|
return strcmp_P(expected, (PGM_P)str) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Buffer>
|
||||||
|
static char* duplicate(const __FlashStringHelper* str, Buffer* buffer) {
|
||||||
|
if (!str) return NULL;
|
||||||
|
size_t size = strlen_P((PGM_P)str) + 1;
|
||||||
|
void* dup = buffer->alloc(size);
|
||||||
|
if (dup != NULL) memcpy_P(dup, (PGM_P)str, size);
|
||||||
|
return static_cast<char*>(dup);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const bool has_append = false;
|
||||||
|
static const bool has_equals = true;
|
||||||
|
static const bool should_duplicate = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
42
include/ArduinoJson/StringTraits/StdStream.hpp
Normal file
42
include/ArduinoJson/StringTraits/StdStream.hpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <istream>
|
||||||
|
#include "../TypeTraits/EnableIf.hpp"
|
||||||
|
#include "../TypeTraits/IsBaseOf.hpp"
|
||||||
|
#include "../TypeTraits/RemoveReference.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Internals {
|
||||||
|
|
||||||
|
struct StdStreamFuncs {
|
||||||
|
class Iterator {
|
||||||
|
std::istream& _stream;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Iterator(std::istream& stream) : _stream(stream) {}
|
||||||
|
|
||||||
|
char next() {
|
||||||
|
return _stream.eof() ? '\0' : static_cast<char>(_stream.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Iterator& operator=(const Iterator&); // Visual Studio C4512
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TStream>
|
||||||
|
struct StringFuncs<TStream,
|
||||||
|
// match any type that is derived from std::istream:
|
||||||
|
typename TypeTraits::EnableIf<TypeTraits::IsBaseOf<
|
||||||
|
std::istream, typename TypeTraits::RemoveReference<
|
||||||
|
TStream>::type>::value>::type>
|
||||||
|
: StdStreamFuncs {};
|
||||||
|
}
|
||||||
|
}
|
61
include/ArduinoJson/StringTraits/StdString.hpp
Normal file
61
include/ArduinoJson/StringTraits/StdString.hpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#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 StdStringFuncs {
|
||||||
|
template <typename Buffer>
|
||||||
|
static char* 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<char*>(dup);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Iterator : CharPtrFuncs::Iterator {
|
||||||
|
Iterator(const TString& str) : CharPtrFuncs::Iterator(str.c_str()) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool equals(const TString& str, const char* expected) {
|
||||||
|
return str == expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void append(TString& str, char c) {
|
||||||
|
str += c;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 StringFuncs<String, void> : StdStringFuncs<String> {};
|
||||||
|
template <>
|
||||||
|
struct StringFuncs<StringSumHelper, void> : StdStringFuncs<StringSumHelper> {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_STD_STRING
|
||||||
|
template <>
|
||||||
|
struct StringFuncs<std::string, void> : StdStringFuncs<std::string> {};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
42
include/ArduinoJson/StringTraits/StringTraits.hpp
Normal file
42
include/ArduinoJson/StringTraits/StringTraits.hpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Configuration.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Internals {
|
||||||
|
|
||||||
|
template <typename TString, typename Enable = void>
|
||||||
|
struct StringFuncs {};
|
||||||
|
|
||||||
|
template <typename TString>
|
||||||
|
struct StringFuncs<const TString, void> : StringFuncs<TString> {};
|
||||||
|
|
||||||
|
template <typename TString>
|
||||||
|
struct StringFuncs<TString&, void> : StringFuncs<TString> {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "CharPointer.hpp"
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_STD_STRING || ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||||
|
#include "StdString.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||||
|
#include "StdStream.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||||
|
#include "ArduinoStream.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_PROGMEM
|
||||||
|
#include "FlashString.hpp"
|
||||||
|
#endif
|
30
include/ArduinoJson/TypeTraits/IsBaseOf.hpp
Normal file
30
include/ArduinoJson/TypeTraits/IsBaseOf.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace TypeTraits {
|
||||||
|
|
||||||
|
// A meta-function that returns true if Derived inherits from TBase is an
|
||||||
|
// integral type.
|
||||||
|
template <typename TBase, typename TDerived>
|
||||||
|
class IsBaseOf {
|
||||||
|
protected: // <- to avoid GCC's "all member functions in class are private"
|
||||||
|
typedef char Yes[1];
|
||||||
|
typedef char No[2];
|
||||||
|
|
||||||
|
static Yes &probe(const TBase *);
|
||||||
|
static No &probe(const void *);
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
value = sizeof(probe(reinterpret_cast<TDerived *>(0))) == sizeof(Yes)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -3,5 +3,5 @@
|
|||||||
curl https://cmake.org/files/v3.4/cmake-3.4.0-Linux-x86_64.tar.gz | tar xz -C /tmp --strip 1
|
curl https://cmake.org/files/v3.4/cmake-3.4.0-Linux-x86_64.tar.gz | tar xz -C /tmp --strip 1
|
||||||
|
|
||||||
/tmp/bin/cmake -DSANITIZE=true .
|
/tmp/bin/cmake -DSANITIZE=true .
|
||||||
make
|
cmake --build .
|
||||||
make test
|
ctest -VV .
|
||||||
|
@ -351,6 +351,16 @@ TEST_F(JsonParser_Array_Tests, UnfinishedCComment) {
|
|||||||
parseMustFail();
|
parseMustFail();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(JsonParser_Array_Tests, EndsInCppComment) {
|
||||||
|
whenInputIs("[//COMMENT");
|
||||||
|
parseMustFail();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(JsonParser_Array_Tests, AfterClosingStar) {
|
||||||
|
whenInputIs("[/*COMMENT*");
|
||||||
|
parseMustFail();
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(JsonParser_Array_Tests, DeeplyNested) {
|
TEST_F(JsonParser_Array_Tests, DeeplyNested) {
|
||||||
whenInputIs("[[[[[[[[[[[[[[[[[[[\"Not too deep\"]]]]]]]]]]]]]]]]]]]");
|
whenInputIs("[[[[[[[[[[[[[[[[[[[\"Not too deep\"]]]]]]]]]]]]]]]]]]]");
|
||||||
parseMustSucceed();
|
parseMustSucceed();
|
||||||
|
@ -5,25 +5,25 @@
|
|||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
// If you like this project, please add a star!
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
TEST(StdStream, JsonVariantFalse) {
|
TEST(StdStream_Tests, JsonVariantFalse) {
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
JsonVariant variant = false;
|
JsonVariant variant = false;
|
||||||
os << variant;
|
os << variant;
|
||||||
ASSERT_EQ("false", os.str());
|
ASSERT_EQ("false", os.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StdStream, JsonVariantString) {
|
TEST(StdStream_Tests, JsonVariantString) {
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
JsonVariant variant = "coucou";
|
JsonVariant variant = "coucou";
|
||||||
os << variant;
|
os << variant;
|
||||||
ASSERT_EQ("\"coucou\"", os.str());
|
ASSERT_EQ("\"coucou\"", os.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StdStream, JsonObject) {
|
TEST(StdStream_Tests, JsonObject) {
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
DynamicJsonBuffer jsonBuffer;
|
DynamicJsonBuffer jsonBuffer;
|
||||||
JsonObject& object = jsonBuffer.createObject();
|
JsonObject& object = jsonBuffer.createObject();
|
||||||
@ -32,7 +32,7 @@ TEST(StdStream, JsonObject) {
|
|||||||
ASSERT_EQ("{\"key\":\"value\"}", os.str());
|
ASSERT_EQ("{\"key\":\"value\"}", os.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StdStream, JsonObjectSubscript) {
|
TEST(StdStream_Tests, JsonObjectSubscript) {
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
DynamicJsonBuffer jsonBuffer;
|
DynamicJsonBuffer jsonBuffer;
|
||||||
JsonObject& object = jsonBuffer.createObject();
|
JsonObject& object = jsonBuffer.createObject();
|
||||||
@ -41,7 +41,7 @@ TEST(StdStream, JsonObjectSubscript) {
|
|||||||
ASSERT_EQ("\"value\"", os.str());
|
ASSERT_EQ("\"value\"", os.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StdStream, JsonArray) {
|
TEST(StdStream_Tests, JsonArray) {
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
DynamicJsonBuffer jsonBuffer;
|
DynamicJsonBuffer jsonBuffer;
|
||||||
JsonArray& array = jsonBuffer.createArray();
|
JsonArray& array = jsonBuffer.createArray();
|
||||||
@ -50,7 +50,7 @@ TEST(StdStream, JsonArray) {
|
|||||||
ASSERT_EQ("[\"value\"]", os.str());
|
ASSERT_EQ("[\"value\"]", os.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StdStream, JsonArraySubscript) {
|
TEST(StdStream_Tests, JsonArraySubscript) {
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
DynamicJsonBuffer jsonBuffer;
|
DynamicJsonBuffer jsonBuffer;
|
||||||
JsonArray& array = jsonBuffer.createArray();
|
JsonArray& array = jsonBuffer.createArray();
|
||||||
@ -58,3 +58,21 @@ TEST(StdStream, JsonArraySubscript) {
|
|||||||
os << array[0];
|
os << array[0];
|
||||||
ASSERT_EQ("\"value\"", os.str());
|
ASSERT_EQ("\"value\"", os.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(StdStream_Tests, ParseArray) {
|
||||||
|
std::istringstream json("[42]");
|
||||||
|
DynamicJsonBuffer jsonBuffer;
|
||||||
|
JsonArray& arr = jsonBuffer.parseArray(json);
|
||||||
|
ASSERT_TRUE(arr.success());
|
||||||
|
ASSERT_EQ(1, arr.size());
|
||||||
|
ASSERT_EQ(42, arr[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(StdStream_Tests, ParseObject) {
|
||||||
|
std::istringstream json("{hello:world}");
|
||||||
|
DynamicJsonBuffer jsonBuffer;
|
||||||
|
JsonObject& obj = jsonBuffer.parseObject(json);
|
||||||
|
ASSERT_TRUE(obj.success());
|
||||||
|
ASSERT_EQ(1, obj.size());
|
||||||
|
ASSERT_STREQ("world", obj["hello"]);
|
||||||
|
}
|
17
test/TypeTraits_Tests.cpp
Normal file
17
test/TypeTraits_Tests.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
using namespace ArduinoJson::TypeTraits;
|
||||||
|
|
||||||
|
TEST(StdStream, IsBaseOf) {
|
||||||
|
ASSERT_FALSE((IsBaseOf<std::istream, std::ostringstream>::value));
|
||||||
|
ASSERT_TRUE((IsBaseOf<std::istream, std::istringstream>::value));
|
||||||
|
}
|
Reference in New Issue
Block a user