Compare commits

..

26 Commits

Author SHA1 Message Date
7e7074502f Set version to 5.8.0 2017-01-03 22:39:44 +01:00
aa306d5573 Travis: Removed XCode 6.1, 6.2 and 6.3 2017-01-03 22:35:58 +01:00
55669e306e Added support for Stream (issue #300) 2017-01-03 22:03:50 +01:00
3f96e070ce Reduced memory consumption by not duplicating spaces and comments 2017-01-01 21:30:20 +01:00
8032a4b564 Extracted StringReader and StringWriter from JsonParser
Split `Internals/` folder into `Data/`, `Deserialization/`, `Serialization/`
2017-01-01 21:30:20 +01:00
b923e8f4df Travis: Added Clang AddressSanitizer and UndefinedBehaviorSanitizer 2017-01-01 21:29:38 +01:00
c5388cf8e7 Travis: Compile all examples with PlatformIO 2016-12-28 20:23:27 +01:00
cb908a2373 Travis: Fixed SSL error problem with coveralls 2016-12-28 20:22:07 +01:00
cecbcd1929 Added operator == to compare JsonVariant and strings (issue #402) 2016-12-23 14:45:32 +01:00
90e0cc6091 JsonHttpClient: use HTTP 1.0 instead of 1.1 (issue #397, PR #399 by @Chris685)
Downgrading to HTTP 1.0 to prevent HTTP Chunked Transfer Encoding.
2016-12-14 19:41:10 +01:00
45bbf6db86 Set version to 5.7.3 2016-12-10 16:00:52 +01:00
432476c98a Added an printTo(char[N]) and prettyPrintTo(char[N]) (issue #292) 2016-12-10 15:59:48 +01:00
1f3e227a8b Added ability to set a nested value like this: root["A"]["B"] = "C" (issue #352) 2016-12-10 15:22:57 +01:00
66c28020c5 Renamed *.ipp to *Impl.hpp because they were ignored by Arduino IDE (issue #396) 2016-12-03 22:19:11 +01:00
6cfe2a58eb Added Doanh Luong to the list of donators 2016-11-25 18:41:33 +01:00
fc6ad51e68 Added the workaround for issue #118 in StringExample.ino 2016-11-24 18:11:02 +01:00
d3bc52951a Set version to 5.7.2 2016-11-23 21:54:56 +01:00
2f7232859e Fixed PROGMEM causing an exception on ESP8266 (issue #383) 2016-11-23 21:53:29 +01:00
4a7232ac99 Added DynamicJsonBuffer to the keywords 2016-11-23 21:25:49 +01:00
72d78432c9 Made PROGMEM available on more platforms (issue #381) 2016-11-16 22:24:58 +01:00
f6cd42d916 Travis: Added Arduino 1.6.12, removed 1.5.8 2016-11-16 22:24:41 +01:00
542dff2a08 Added Andrew Melvin to the list of donators 2016-11-15 21:48:40 +01:00
e75e843c88 Moved JsonBuffer size calculator to https://bblanchon.github.io/ArduinoJson/ 2016-11-13 20:48:03 +01:00
146a76247c Set version to 5.7.1 2016-11-13 20:21:16 +01:00
f28157cab7 Fixed compilation error when index is not an int (issue #381) 2016-11-13 20:19:36 +01:00
1ce16ce449 Added support for PROGMEM (issue #76) 2016-11-13 20:16:12 +01:00
95 changed files with 1650 additions and 897 deletions

View File

@ -70,20 +70,14 @@ matrix:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.8']
packages: ['clang-3.8']
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++-3.8
- compiler: clang
addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.8']
packages: ['clang-3.8']
env: SCRIPT=sanitize CMAKE_CXX_COMPILER=clang++-3.8
- compiler: gcc
env: SCRIPT=coverage
- os: osx
osx_image: beta-xcode6.1
compiler: clang
env: SCRIPT=cmake-osx
- os: osx
osx_image: beta-xcode6.2
compiler: clang
env: SCRIPT=cmake-osx
- os: osx
osx_image: beta-xcode6.3
compiler: clang
env: SCRIPT=cmake-osx
- os: osx
osx_image: xcode6.4
compiler: clang
@ -104,10 +98,8 @@ matrix:
osx_image: xcode7.3
compiler: clang
env: SCRIPT=cmake-osx
- env: SCRIPT=arduino VERSION=1.5.8 BOARD=arduino:avr:uno
- env: SCRIPT=arduino VERSION=1.6.7 BOARD=arduino:avr:uno
- env: SCRIPT=arduino VERSION=1.6.8 BOARD=arduino:avr:uno
- env: SCRIPT=arduino VERSION=1.6.9 BOARD=arduino:avr:uno
- env: SCRIPT=arduino VERSION=1.6.12 BOARD=arduino:avr:uno
- env: SCRIPT=platformio BOARD=uno
- env: SCRIPT=platformio BOARD=due
- env: SCRIPT=platformio BOARD=esp01

View File

@ -1,6 +1,32 @@
ArduinoJson: change log
=======================
v5.8.0
------
* Added operator `==` to compare `JsonVariant` and strings (issue #402)
* Added support for `Stream` (issue #300)
* Reduced memory consumption by not duplicating spaces and comments
v5.7.3
------
* Added an `printTo(char[N])` and `prettyPrintTo(char[N])` (issue #292)
* Added ability to set a nested value like this: `root["A"]["B"] = "C"` (issue #352)
* Renamed `*.ipp` to `*Impl.hpp` because they were ignored by Arduino IDE (issue #396)
v5.7.2
------
* Made PROGMEM available on more platforms (issue #381)
* Fixed PROGMEM causing an exception on ESP8266 (issue #383)
v5.7.1
------
* Added support for PROGMEM (issue #76)
* Fixed compilation error when index is not an `int` (issue #381)
v5.7.0
------

View File

@ -18,4 +18,8 @@ if(${COVERAGE})
set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
endif()
if(${SANITIZE})
set(CMAKE_CXX_FLAGS "-fsanitize=address,undefined")
endif()
add_subdirectory(test)

View File

@ -5,9 +5,10 @@ Arduino JSON library
*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.
For instance, it supports Aduino's `String` and `Stream`, but also `std::string`, `std::istream` and `std::ostream`.
Features
--------
@ -55,6 +56,8 @@ double latitude = root["data"][0];
double longitude = root["data"][1];
```
[See JsonParserExample.ino](examples/JsonParserExample/JsonParserExample.ino)
#### Encoding / Generating
```c++
@ -73,6 +76,8 @@ root.printTo(Serial);
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
```
[See JsonGeneratorExample.ino](examples/JsonGeneratorExample/JsonGeneratorExample.ino)
Documentation
-------------
@ -103,6 +108,9 @@ From GitHub user `zacsketches`:
[From Twitter user `@hemalchevli`](https://twitter.com/hemalchevli/status/715788439397011456):
> ArduinoJson library should be used as a benchmark/reference for making libraries. Truly elegant.
[From GitHub user `sticilface`](https://github.com/bblanchon/ArduinoJson/issues/381#issuecomment-260203594):
> its a great lib:) and i use it in everything!
Donators
--------
@ -123,6 +131,8 @@ Special thanks to the following persons and companies who made generous donation
* Kestutis Liaugminas <img alt='Lithuania' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f1-1f1f9.svg' width='18' height='18'>
* Darlington Adibe <img alt='Nigeria' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1ec.svg' width='18' height='18'>
* Yoeri Kroon <img alt='Netherlands' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1f1.svg' width='18' height='18'>
* Andrew Melvin <img alt='United Kingdom' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1ec-1f1e7.svg' width='18' height='18'>
* Doanh Luong <img alt ='Vietnam' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fb-1f1f3.svg' width='18' height='18'>
---

View File

@ -1,4 +1,4 @@
version: 5.7.0.{build}
version: 5.8.0.{build}
environment:
matrix:
- CMAKE_GENERATOR: Visual Studio 14 2015

View File

@ -9,8 +9,8 @@
// If you like this project, please add a star!
#include <ArduinoJson.h>
#include <SPI.h>
#include <Ethernet.h>
#include <SPI.h>
EthernetClient client;
@ -36,11 +36,8 @@ void setup() {
void loop() {
if (connect(server)) {
if (sendRequest(server, resource) && skipResponseHeaders()) {
char response[MAX_CONTENT_SIZE];
readReponseContent(response, sizeof(response));
UserData userData;
if (parseUserData(response, &userData)) {
if (readReponseContent(&userData)) {
printUserData(&userData);
}
}
@ -87,9 +84,9 @@ bool sendRequest(const char* host, const char* resource) {
client.print("GET ");
client.print(resource);
client.println(" HTTP/1.1");
client.println(" HTTP/1.0");
client.print("Host: ");
client.println(server);
client.println(host);
client.println("Connection: close");
client.println();
@ -111,13 +108,6 @@ bool skipResponseHeaders() {
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
// 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"
// }
// }
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.
// This is only required if you use StaticJsonBuffer.
const size_t BUFFER_SIZE =
JSON_OBJECT_SIZE(8) // the root object has 8 elements
+ JSON_OBJECT_SIZE(5) // the "address" object has 5 elements
+ JSON_OBJECT_SIZE(2) // the "geo" object has 2 elements
+ JSON_OBJECT_SIZE(3); // the "company" object has 3 elements
JSON_OBJECT_SIZE(8) // the root object has 8 elements
+ JSON_OBJECT_SIZE(5) // the "address" object has 5 elements
+ JSON_OBJECT_SIZE(2) // the "geo" object has 2 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
StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
// If the memory pool is too big for the stack, use this instead:
// DynamicJsonBuffer jsonBuffer;
// Allocate a temporary memory pool
DynamicJsonBuffer jsonBuffer(BUFFER_SIZE);
JsonObject& root = jsonBuffer.parseObject(content);
JsonObject& root = jsonBuffer.parseObject(client);
if (!root.success()) {
Serial.println("JSON parsing failed!");

View File

@ -0,0 +1,56 @@
// 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>
// About
// -----
// This example shows the different ways you can use PROGMEM with ArduinoJson.
// Please don't see this as an invitation to use PROGMEM.
// On the contrary, you should always use char[] when possible, it's much more
// efficient in term of code size, speed and memory usage.
void setup() {
#ifdef PROGMEM
DynamicJsonBuffer jsonBuffer;
// You can use a Flash String as your JSON input.
// WARNING: the content of the Flash String will be duplicated in the
// JsonBuffer.
JsonObject& root =
jsonBuffer.parseObject(F("{\"sensor\":\"gps\",\"time\":1351824120,"
"\"data\":[48.756080,2.302038]}"));
// You can use a Flash String to get an element of a JsonObject
// No duplication is done.
long time = root[F("time")];
// You can use a Flash String to set an element of a JsonObject
// WARNING: the content of the Flash String will be duplicated in the
// JsonBuffer.
root[F("time")] = time;
// You can set a Flash String to a JsonObject or JsonArray:
// WARNING: the content of the Flash String will be duplicated in the
// JsonBuffer.
root["sensor"] = F("gps");
// You can compare the content of a JsonVariant to a Flash String
if (root["sensor"] == F("gps")) {
// ...
}
#else
#warning PROGMEM is not supported on this platform
#endif
}
void loop() {
// not used in this example
}

View File

@ -33,7 +33,12 @@ void setup() {
// You can get a String from a JsonObject or JsonArray:
// No duplication is done, at least not in the JsonBuffer.
String sensor = root[String("sensor")];
String sensor = root["sensor"];
// Unfortunately, the following doesn't work (issue #118):
// sensor = root["sensor"]; // <- error "ambiguous overload for 'operator='"
// As a workaround, you need to replace by:
sensor = root["sensor"].as<String>();
// You can set a String to a JsonObject or JsonArray:
// WARNING: the content of the String will be duplicated in the JsonBuffer.
@ -43,6 +48,11 @@ void setup() {
// WARNING: the content of the String will be duplicated in the JsonBuffer.
root[String("sen") + "sor"] = String("gp") + "s";
// You can compare the content of a JsonObject with a String
if (root["sensor"] == sensor) {
// ...
}
// Lastly, you can print the resulting JSON to a String
String output;
root.printTo(output);

View File

@ -10,13 +10,14 @@
#include "ArduinoJson/DynamicJsonBuffer.hpp"
#include "ArduinoJson/JsonArray.hpp"
#include "ArduinoJson/JsonObject.hpp"
#include "ArduinoJson/JsonVariantComparisons.hpp"
#include "ArduinoJson/StaticJsonBuffer.hpp"
#include "ArduinoJson/Internals/JsonParser.ipp"
#include "ArduinoJson/Internals/JsonSerializer.ipp"
#include "ArduinoJson/JsonArray.ipp"
#include "ArduinoJson/JsonBuffer.ipp"
#include "ArduinoJson/JsonObject.ipp"
#include "ArduinoJson/JsonVariant.ipp"
#include "ArduinoJson/Deserialization/JsonParserImpl.hpp"
#include "ArduinoJson/JsonArrayImpl.hpp"
#include "ArduinoJson/JsonBufferImpl.hpp"
#include "ArduinoJson/JsonObjectImpl.hpp"
#include "ArduinoJson/JsonVariantImpl.hpp"
#include "ArduinoJson/Serialization/JsonSerializerImpl.hpp"
using namespace ArduinoJson;

View File

@ -27,6 +27,19 @@
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
#endif
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
#endif
// On AVR archiecture, we can use PROGMEM
#ifndef ARDUINOJSON_ENABLE_PROGMEM
#ifdef PROGMEM
#define ARDUINOJSON_ENABLE_PROGMEM 1
#else
#define ARDUINOJSON_ENABLE_PROGMEM 0
#endif
#endif
// Arduino doesn't have std::string
#ifndef ARDUINOJSON_ENABLE_STD_STRING
#define ARDUINOJSON_ENABLE_STD_STRING 0
@ -87,11 +100,21 @@
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
#endif
// PROGMEM is only available on AVR architecture
#ifndef ARDUINOJSON_ENABLE_PROGMEM
#define ARDUINOJSON_ENABLE_PROGMEM 0
#endif
// on a computer, we can assume that the STL is there
#ifndef ARDUINOJSON_ENABLE_STD_STREAM
#define ARDUINOJSON_ENABLE_STD_STREAM 1
#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
// even if not required, most cpu's are faster with aligned pointers
#define ARDUINOJSON_ENABLE_ALIGNMENT 1

View File

@ -9,8 +9,8 @@
#include "../JsonBuffer.hpp"
#include "../JsonVariant.hpp"
#include "../StringTraits/StringTraits.hpp"
#include "../TypeTraits/EnableIf.hpp"
#include "StringFuncs.hpp"
namespace ArduinoJson {
namespace Internals {

View File

@ -0,0 +1,76 @@
// 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 <typename TInput>
void skipSpacesAndComments(TInput& input) {
for (;;) {
switch (input.current()) {
// spaces
case ' ':
case '\t':
case '\r':
case '\n':
input.move();
continue;
// comments
case '/':
switch (input.next()) {
// C-style block comment
case '*':
input.move(); // skip '/'
input.move(); // skip '*'
for (;;) {
switch (input.current()) {
case '\0':
return;
case '*':
input.move(); // skip '*'
if (input.current() == '/') {
input.move(); // skip '/'
return;
}
break;
default:
input.move();
}
}
break;
// C++-style line comment
case '/':
input.move(); // skip '/'
for (;;) {
switch (input.current()) {
case '\0':
return;
case '\n':
input.move();
return;
default:
input.move();
}
}
return;
// not a comment, just a '/'
default:
return;
}
break;
default:
return;
}
}
}
}
}

View File

@ -0,0 +1,108 @@
// 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 "../JsonBuffer.hpp"
#include "../JsonVariant.hpp"
#include "StringReader.hpp"
#include "StringWriter.hpp"
namespace ArduinoJson {
namespace Internals {
// Parse JSON string to create JsonArrays and JsonObjects
// This internal class is not indended to be used directly.
// Instead, use JsonBuffer.parseArray() or .parseObject()
template <typename TReader, typename TWriter>
class JsonParser {
public:
JsonParser(JsonBuffer *buffer, TReader reader, TWriter writer,
uint8_t nestingLimit)
: _buffer(buffer),
_reader(reader),
_writer(writer),
_nestingLimit(nestingLimit) {}
JsonArray &parseArray();
JsonObject &parseObject();
JsonVariant parseVariant() {
JsonVariant result;
parseAnythingTo(&result);
return result;
}
private:
JsonParser &operator=(const JsonParser &); // non-copiable
static bool eat(TReader &, char charToSkip);
FORCE_INLINE bool eat(char charToSkip) {
return eat(_reader, charToSkip);
}
const char *parseString();
bool parseAnythingTo(JsonVariant *destination);
FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination);
inline bool parseArrayTo(JsonVariant *destination);
inline bool parseObjectTo(JsonVariant *destination);
inline bool parseStringTo(JsonVariant *destination);
static inline bool isInRange(char c, char min, char max) {
return min <= c && c <= max;
}
static inline bool isLetterOrNumber(char c) {
return isInRange(c, '0', '9') || isInRange(c, 'a', 'z') ||
isInRange(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
}
static inline bool isQuote(char c) {
return c == '\'' || c == '\"';
}
JsonBuffer *_buffer;
TReader _reader;
TWriter _writer;
uint8_t _nestingLimit;
};
template <typename TJsonBuffer, typename TString>
struct JsonParserBuilder {
typedef typename Internals::StringFuncs<TString>::Iterator InputIterator;
typedef JsonParser<StringReader<InputIterator>, TJsonBuffer &> TParser;
static TParser makeParser(TJsonBuffer *buffer, TString &json,
uint8_t nestingLimit) {
return TParser(buffer, InputIterator(json), *buffer, nestingLimit);
}
};
template <typename TJsonBuffer>
struct JsonParserBuilder<TJsonBuffer, char *> {
typedef typename Internals::StringFuncs<char *>::Iterator InputIterator;
typedef JsonParser<StringReader<InputIterator>, StringWriter> TParser;
static TParser makeParser(TJsonBuffer *buffer, char *json,
uint8_t nestingLimit) {
return TParser(buffer, InputIterator(json), json, nestingLimit);
}
};
template <typename TJsonBuffer, size_t N>
struct JsonParserBuilder<TJsonBuffer, char[N]>
: JsonParserBuilder<TJsonBuffer, char *> {};
template <typename TJsonBuffer, typename TString>
inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser(
TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) {
return JsonParserBuilder<TJsonBuffer, TString>::makeParser(buffer, json,
nestingLimit);
}
}
}

View File

@ -10,15 +10,19 @@
#include "Comments.hpp"
#include "JsonParser.hpp"
inline bool ArduinoJson::Internals::JsonParser::skip(char charToSkip) {
const char *ptr = skipSpacesAndComments(_readPtr);
if (*ptr != charToSkip) return false;
ptr++;
_readPtr = skipSpacesAndComments(ptr);
template <typename TReader, typename TWriter>
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::eat(
TReader &reader, char charToSkip) {
skipSpacesAndComments(reader);
if (reader.current() != charToSkip) return false;
reader.move();
skipSpacesAndComments(reader);
return true;
}
inline bool ArduinoJson::Internals::JsonParser::parseAnythingTo(
template <typename TReader, typename TWriter>
inline bool
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseAnythingTo(
JsonVariant *destination) {
if (_nestingLimit == 0) return false;
_nestingLimit--;
@ -27,11 +31,13 @@ inline bool ArduinoJson::Internals::JsonParser::parseAnythingTo(
return success;
}
inline bool ArduinoJson::Internals::JsonParser::parseAnythingToUnsafe(
template <typename TReader, typename TWriter>
inline bool
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseAnythingToUnsafe(
JsonVariant *destination) {
_readPtr = skipSpacesAndComments(_readPtr);
skipSpacesAndComments(_reader);
switch (*_readPtr) {
switch (_reader.current()) {
case '[':
return parseArrayTo(destination);
@ -43,14 +49,15 @@ inline bool ArduinoJson::Internals::JsonParser::parseAnythingToUnsafe(
}
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonArray &
ArduinoJson::Internals::JsonParser::parseArray() {
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArray() {
// Create an empty array
JsonArray &array = _buffer->createArray();
// Check opening braket
if (!skip('[')) goto ERROR_MISSING_BRACKET;
if (skip(']')) goto SUCCESS_EMPTY_ARRAY;
if (!eat('[')) goto ERROR_MISSING_BRACKET;
if (eat(']')) goto SUCCESS_EMPTY_ARRAY;
// Read each value
for (;;) {
@ -60,8 +67,8 @@ ArduinoJson::Internals::JsonParser::parseArray() {
if (!array.add(value)) goto ERROR_NO_MEMORY;
// 2 - More values?
if (skip(']')) goto SUCCES_NON_EMPTY_ARRAY;
if (!skip(',')) goto ERROR_MISSING_COMMA;
if (eat(']')) goto SUCCES_NON_EMPTY_ARRAY;
if (!eat(',')) goto ERROR_MISSING_COMMA;
}
SUCCESS_EMPTY_ARRAY:
@ -75,7 +82,8 @@ ERROR_NO_MEMORY:
return JsonArray::invalid();
}
inline bool ArduinoJson::Internals::JsonParser::parseArrayTo(
template <typename TReader, typename TWriter>
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArrayTo(
JsonVariant *destination) {
JsonArray &array = parseArray();
if (!array.success()) return false;
@ -84,21 +92,22 @@ inline bool ArduinoJson::Internals::JsonParser::parseArrayTo(
return true;
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonObject &
ArduinoJson::Internals::JsonParser::parseObject() {
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObject() {
// Create an empty object
JsonObject &object = _buffer->createObject();
// Check opening brace
if (!skip('{')) goto ERROR_MISSING_BRACE;
if (skip('}')) goto SUCCESS_EMPTY_OBJECT;
if (!eat('{')) goto ERROR_MISSING_BRACE;
if (eat('}')) goto SUCCESS_EMPTY_OBJECT;
// Read each key value pair
for (;;) {
// 1 - Parse key
const char *key = parseString();
if (!key) goto ERROR_INVALID_KEY;
if (!skip(':')) goto ERROR_MISSING_COLON;
if (!eat(':')) goto ERROR_MISSING_COLON;
// 2 - Parse value
JsonVariant value;
@ -106,8 +115,8 @@ ArduinoJson::Internals::JsonParser::parseObject() {
if (!object.set(key, value)) goto ERROR_NO_MEMORY;
// 3 - More keys/values?
if (skip('}')) goto SUCCESS_NON_EMPTY_OBJECT;
if (!skip(',')) goto ERROR_MISSING_COMMA;
if (eat('}')) goto SUCCESS_NON_EMPTY_OBJECT;
if (!eat(',')) goto ERROR_MISSING_COMMA;
}
SUCCESS_EMPTY_OBJECT:
@ -123,7 +132,8 @@ ERROR_NO_MEMORY:
return JsonObject::invalid();
}
inline bool ArduinoJson::Internals::JsonParser::parseObjectTo(
template <typename TReader, typename TWriter>
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObjectTo(
JsonVariant *destination) {
JsonObject &object = parseObject();
if (!object.success()) return false;
@ -132,54 +142,49 @@ inline bool ArduinoJson::Internals::JsonParser::parseObjectTo(
return true;
}
inline const char *ArduinoJson::Internals::JsonParser::parseString() {
const char *readPtr = _readPtr;
char *writePtr = _writePtr;
template <typename TReader, typename TWriter>
inline const char *
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseString() {
typename TypeTraits::RemoveReference<TWriter>::type::String str =
_writer.startString();
char c = *readPtr;
char c = _reader.current();
if (isQuote(c)) { // quotes
_reader.move();
char stopChar = c;
for (;;) {
c = *++readPtr;
c = _reader.current();
if (c == '\0') break;
_reader.move();
if (c == stopChar) {
readPtr++;
break;
}
if (c == stopChar) break;
if (c == '\\') {
// replace char
c = Encoding::unescapeChar(*++readPtr);
c = Encoding::unescapeChar(_reader.current());
if (c == '\0') break;
_reader.move();
}
*writePtr++ = c;
str.append(c);
}
} else { // no quotes
for (;;) {
if (!isLetterOrNumber(c)) break;
*writePtr++ = c;
c = *++readPtr;
_reader.move();
str.append(c);
c = _reader.current();
}
}
// end the string here
*writePtr++ = '\0';
const char *startPtr = _writePtr;
// update end ptr
_readPtr = readPtr;
_writePtr = writePtr;
// return pointer to unquoted string
return startPtr;
return str.c_str();
}
inline bool ArduinoJson::Internals::JsonParser::parseStringTo(
template <typename TReader, typename TWriter>
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseStringTo(
JsonVariant *destination) {
bool hasQuotes = isQuote(_readPtr[0]);
bool hasQuotes = isQuote(_reader.current());
const char *value = parseString();
if (value == NULL) return false;
if (hasQuotes) {

View File

@ -0,0 +1,41 @@
// 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 {
// Parse JSON string to create JsonArrays and JsonObjects
// This internal class is not indended to be used directly.
// Instead, use JsonBuffer.parseArray() or .parseObject()
template <typename TIterator>
class StringReader {
TIterator _input;
char _current, _next;
public:
StringReader(const TIterator& input) : _input(input) {
_current = _input.next();
_next = _input.next();
}
void move() {
_current = _next;
_next = _input.next();
}
char current() const {
return _current;
}
char next() const {
return _next;
}
};
}
}

View File

@ -0,0 +1,43 @@
// 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 {
class StringWriter {
public:
class String {
public:
String(char** ptr) : _writePtr(ptr), _startPtr(*ptr) {}
void append(char c) {
*(*_writePtr)++ = c;
}
const char* c_str() const {
*(*_writePtr)++ = 0;
return _startPtr;
}
private:
char** _writePtr;
char* _startPtr;
};
StringWriter(char* buffer) : _ptr(buffer) {}
String startString() {
return String(&_ptr);
}
private:
char* _ptr;
};
}
}

View File

@ -7,12 +7,153 @@
#pragma once
#include "Internals/BlockJsonBuffer.hpp"
#include "JsonBufferBase.hpp"
#include <stdlib.h>
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
namespace ArduinoJson {
class DefaultAllocator {
public:
void* allocate(size_t size) {
return malloc(size);
}
void deallocate(void* pointer) {
free(pointer);
}
};
template <typename TAllocator>
class DynamicJsonBufferBase
: public JsonBufferBase<DynamicJsonBufferBase<TAllocator> > {
struct Block;
struct EmptyBlock {
Block* next;
size_t capacity;
size_t size;
};
struct Block : EmptyBlock {
uint8_t data[1];
};
public:
DynamicJsonBufferBase(size_t initialSize = 256)
: _head(NULL), _nextBlockCapacity(initialSize) {}
~DynamicJsonBufferBase() {
Block* currentBlock = _head;
while (currentBlock != NULL) {
Block* nextBlock = currentBlock->next;
_allocator.deallocate(currentBlock);
currentBlock = nextBlock;
}
}
size_t size() const {
size_t total = 0;
for (const Block* b = _head; b; b = b->next) total += b->size;
return total;
}
virtual void* alloc(size_t bytes) {
alignNextAlloc();
return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
}
class String {
public:
String(DynamicJsonBufferBase* parent)
: _parent(parent), _start(NULL), _length(0) {}
void append(char c) {
if (_parent->canAllocInHead(1)) {
char* end = static_cast<char*>(_parent->allocInHead(1));
*end = c;
if (_length == 0) _start = end;
} else {
char* newStart =
static_cast<char*>(_parent->allocInNewBlock(_length + 1));
if (_start && newStart) memcpy(newStart, _start, _length);
newStart[_length] = c;
_start = newStart;
}
_length++;
}
const char* c_str() {
append(0);
return _start;
}
private:
DynamicJsonBufferBase* _parent;
char* _start;
int _length;
};
String startString() {
return String(this);
}
private:
void alignNextAlloc() {
if (_head) _head->size = this->round_size_up(_head->size);
}
bool canAllocInHead(size_t bytes) const {
return _head != NULL && _head->size + bytes <= _head->capacity;
}
void* allocInHead(size_t bytes) {
void* p = _head->data + _head->size;
_head->size += bytes;
return p;
}
void* allocInNewBlock(size_t bytes) {
size_t capacity = _nextBlockCapacity;
if (bytes > capacity) capacity = bytes;
if (!addNewBlock(capacity)) return NULL;
_nextBlockCapacity *= 2;
return allocInHead(bytes);
}
bool addNewBlock(size_t capacity) {
size_t bytes = sizeof(EmptyBlock) + capacity;
Block* block = static_cast<Block*>(_allocator.allocate(bytes));
if (block == NULL) return false;
block->capacity = capacity;
block->size = 0;
block->next = _head;
_head = block;
return true;
}
TAllocator _allocator;
Block* _head;
size_t _nextBlockCapacity;
};
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop
#endif
#endif
// Implements a JsonBuffer with dynamic memory allocation.
// You are strongly encouraged to consider using StaticJsonBuffer which is much
// more suitable for embedded systems.
typedef Internals::BlockJsonBuffer<Internals::DefaultAllocator>
DynamicJsonBuffer;
typedef DynamicJsonBufferBase<DefaultAllocator> DynamicJsonBuffer;
}

View File

@ -1,115 +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 "../JsonBuffer.hpp"
#include <stdlib.h>
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
namespace ArduinoJson {
namespace Internals {
class DefaultAllocator {
public:
void* allocate(size_t size) {
return malloc(size);
}
void deallocate(void* pointer) {
free(pointer);
}
};
template <typename TAllocator>
class BlockJsonBuffer : public JsonBuffer {
struct Block;
struct EmptyBlock {
Block* next;
size_t capacity;
size_t size;
};
struct Block : EmptyBlock {
uint8_t data[1];
};
public:
BlockJsonBuffer(size_t initialSize = 256)
: _head(NULL), _nextBlockSize(initialSize) {}
~BlockJsonBuffer() {
Block* currentBlock = _head;
while (currentBlock != NULL) {
Block* nextBlock = currentBlock->next;
_allocator.deallocate(currentBlock);
currentBlock = nextBlock;
}
}
size_t size() const {
size_t total = 0;
for (const Block* b = _head; b; b = b->next) total += b->size;
return total;
}
virtual void* alloc(size_t bytes) {
return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
}
private:
bool canAllocInHead(size_t bytes) const {
return _head != NULL && _head->size + bytes <= _head->capacity;
}
void* allocInHead(size_t bytes) {
void* p = _head->data + _head->size;
_head->size += round_size_up(bytes);
return p;
}
void* allocInNewBlock(size_t bytes) {
size_t capacity = _nextBlockSize;
if (bytes > capacity) capacity = bytes;
if (!addNewBlock(capacity)) return NULL;
_nextBlockSize *= 2;
return allocInHead(bytes);
}
bool addNewBlock(size_t capacity) {
size_t bytes = sizeof(EmptyBlock) + capacity;
Block* block = static_cast<Block*>(_allocator.allocate(bytes));
if (block == NULL) return false;
block->capacity = capacity;
block->size = 0;
block->next = _head;
_head = block;
return true;
}
TAllocator _allocator;
Block* _head;
size_t _nextBlockSize;
};
}
}
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop
#endif
#endif

View File

@ -1,56 +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
namespace ArduinoJson {
namespace Internals {
inline const char *skipCStyleComment(const char *ptr) {
ptr += 2;
for (;;) {
if (ptr[0] == '\0') return ptr;
if (ptr[0] == '*' && ptr[1] == '/') return ptr + 2;
ptr++;
}
}
inline const char *skipCppStyleComment(const char *ptr) {
ptr += 2;
for (;;) {
if (ptr[0] == '\0' || ptr[0] == '\n') return ptr;
ptr++;
}
}
inline const char *skipSpacesAndComments(const char *ptr) {
for (;;) {
switch (ptr[0]) {
case ' ':
case '\t':
case '\r':
case '\n':
ptr++;
continue;
case '/':
switch (ptr[1]) {
case '*':
ptr = skipCStyleComment(ptr);
break;
case '/':
ptr = skipCppStyleComment(ptr);
break;
default:
return ptr;
}
break;
default:
return ptr;
}
}
}
}
}

View File

@ -1,66 +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 "../JsonBuffer.hpp"
#include "../JsonVariant.hpp"
namespace ArduinoJson {
namespace Internals {
// Parse JSON string to create JsonArrays and JsonObjects
// This internal class is not indended to be used directly.
// Instead, use JsonBuffer.parseArray() or .parseObject()
class JsonParser {
public:
JsonParser(JsonBuffer *buffer, char *json, uint8_t nestingLimit)
: _buffer(buffer),
_readPtr(json ? json : ""),
_writePtr(json),
_nestingLimit(nestingLimit) {}
JsonArray &parseArray();
JsonObject &parseObject();
JsonVariant parseVariant() {
JsonVariant result;
parseAnythingTo(&result);
return result;
}
private:
bool skip(char charToSkip);
const char *parseString();
bool parseAnythingTo(JsonVariant *destination);
FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination);
inline bool parseArrayTo(JsonVariant *destination);
inline bool parseObjectTo(JsonVariant *destination);
inline bool parseStringTo(JsonVariant *destination);
static inline bool isInRange(char c, char min, char max) {
return min <= c && c <= max;
}
static inline bool isLetterOrNumber(char c) {
return isInRange(c, '0', '9') || isInRange(c, 'a', 'z') ||
isInRange(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
}
static inline bool isQuote(char c) {
return c == '\'' || c == '\"';
}
JsonBuffer *_buffer;
const char *_readPtr;
char *_writePtr;
uint8_t _nestingLimit;
};
}
}

View File

@ -1,94 +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 {
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 should_duplicate = false;
};
template <>
struct StringFuncs<const char*> : CharPtrFuncs {};
template <>
struct StringFuncs<char*> : CharPtrFuncs {};
template <size_t N>
struct StringFuncs<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);
}
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 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
}
}

View File

@ -7,13 +7,13 @@
#pragma once
#include "Internals/JsonBufferAllocated.hpp"
#include "Internals/JsonPrintable.hpp"
#include "Internals/List.hpp"
#include "Internals/ReferenceType.hpp"
#include "Internals/StringFuncs.hpp"
#include "Internals/ValueSetter.hpp"
#include "Data/JsonBufferAllocated.hpp"
#include "Data/List.hpp"
#include "Data/ReferenceType.hpp"
#include "Data/ValueSetter.hpp"
#include "JsonVariant.hpp"
#include "Serialization/JsonPrintable.hpp"
#include "StringTraits/StringTraits.hpp"
#include "TypeTraits/ConstRefOrConstPtr.hpp"
#include "TypeTraits/EnableIf.hpp"
#include "TypeTraits/IsFloatingPoint.hpp"
@ -227,4 +227,13 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
value);
}
};
namespace Internals {
template <>
struct JsonVariantDefault<JsonArray> {
static JsonArray &get() {
return JsonArray::invalid();
}
};
}
}

View File

@ -1,62 +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 "JsonArray.hpp"
#include "JsonArraySubscript.hpp"
#include "JsonObject.hpp"
namespace ArduinoJson {
inline JsonVariant::JsonVariant(const JsonArray &array) {
if (array.success()) {
_type = Internals::JSON_ARRAY;
_content.asArray = const_cast<JsonArray *>(&array);
} else {
_type = Internals::JSON_UNDEFINED;
}
}
inline JsonVariant::JsonVariant(const JsonObject &object) {
if (object.success()) {
_type = Internals::JSON_OBJECT;
_content.asObject = const_cast<JsonObject *>(&object);
} else {
_type = Internals::JSON_UNDEFINED;
}
}
namespace Internals {
template <>
struct JsonVariantDefault<JsonArray> {
static JsonArray &get() {
return JsonArray::invalid();
}
};
}
inline JsonArray &JsonVariant::asArray() const {
if (_type == Internals::JSON_ARRAY) return *_content.asArray;
return JsonArray::invalid();
}
inline JsonArray &JsonArray::createNestedArray() {
if (!_buffer) return JsonArray::invalid();
JsonArray &array = _buffer->createArray();
add(array);
return array;
}
template <typename TString>
inline JsonArray &JsonObject::createNestedArray(const TString &key) {
if (!_buffer) return JsonArray::invalid();
JsonArray &array = _buffer->createArray();
set(key, array);
return array;
}
}

View File

@ -0,0 +1,29 @@
// 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 "JsonArray.hpp"
#include "JsonArraySubscript.hpp"
#include "JsonObject.hpp"
namespace ArduinoJson {
inline JsonArray &JsonArray::createNestedArray() {
if (!_buffer) return JsonArray::invalid();
JsonArray &array = _buffer->createArray();
add(array);
return array;
}
inline JsonObject &JsonArray::createNestedObject() {
if (!_buffer) return JsonObject::invalid();
JsonObject &object = _buffer->createObject();
add(object);
return object;
}
}

View File

@ -67,6 +67,11 @@ inline JsonArraySubscript JsonArray::operator[](size_t index) {
return JsonArraySubscript(*this, index);
}
template <typename TImplem>
inline JsonArraySubscript JsonVariantBase<TImplem>::operator[](int index) {
return asArray()[index];
}
template <typename TImplem>
inline const JsonArraySubscript JsonVariantBase<TImplem>::operator[](
int index) const {

View File

@ -51,58 +51,6 @@ class JsonBuffer {
// allocation fails.
JsonObject &createObject();
// Allocates and populate a JsonArray from a JSON string.
//
// The First argument is a pointer to the JSON string, the memory must be
// writable
// because the parser will insert null-terminators and replace escaped chars.
//
// The second argument set the nesting limit
//
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
// allocation fails.
JsonArray &parseArray(
char *json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT);
// With this overload, the JsonBuffer will make a copy of the string
template <typename TString>
JsonArray &parseArray(const TString &json,
uint8_t nesting = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
return parseArray(strdup(json), nesting);
}
// Allocates and populate a JsonObject from a JSON string.
//
// The First argument is a pointer to the JSON string, the memory must be
// writable
// because the parser will insert null-terminators and replace escaped chars.
//
// The second argument set the nesting limit
//
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
// allocation fails.
JsonObject &parseObject(
char *json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT);
// With this overload, the JsonBuffer will make a copy of the string
template <typename TString>
JsonObject &parseObject(const TString &json,
uint8_t nesting = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
return parseObject(strdup(json), nesting);
}
// Generalized version of parseArray() and parseObject(), also works for
// integral types.
JsonVariant parse(char *json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT);
// With this overload, the JsonBuffer will make a copy of the string
template <typename TString>
JsonVariant parse(const TString &json,
uint8_t nesting = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
return parse(strdup(json), nesting);
}
// Duplicate a string
template <typename TString>
char *strdup(const TString &src) {
@ -114,7 +62,7 @@ class JsonBuffer {
virtual void *alloc(size_t size) = 0;
protected:
// Preserve aligment if nessary
// Preserve aligment if necessary
static FORCE_INLINE size_t round_size_up(size_t bytes) {
#if ARDUINOJSON_ENABLE_ALIGNMENT
const size_t x = sizeof(void *) - 1;

View File

@ -1,38 +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 "Internals/JsonParser.hpp"
inline ArduinoJson::JsonArray &ArduinoJson::JsonBuffer::createArray() {
JsonArray *ptr = new (this) JsonArray(this);
return ptr ? *ptr : JsonArray::invalid();
}
inline ArduinoJson::JsonObject &ArduinoJson::JsonBuffer::createObject() {
JsonObject *ptr = new (this) JsonObject(this);
return ptr ? *ptr : JsonObject::invalid();
}
inline ArduinoJson::JsonArray &ArduinoJson::JsonBuffer::parseArray(
char *json, uint8_t nestingLimit) {
Internals::JsonParser parser(this, json, nestingLimit);
return parser.parseArray();
}
inline ArduinoJson::JsonObject &ArduinoJson::JsonBuffer::parseObject(
char *json, uint8_t nestingLimit) {
Internals::JsonParser parser(this, json, nestingLimit);
return parser.parseObject();
}
inline ArduinoJson::JsonVariant ArduinoJson::JsonBuffer::parse(
char *json, uint8_t nestingLimit) {
Internals::JsonParser parser(this, json, nestingLimit);
return parser.parseVariant();
}

View File

@ -0,0 +1,97 @@
// 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 "Deserialization/JsonParser.hpp"
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
namespace ArduinoJson {
template <typename TDerived>
class JsonBufferBase : public JsonBuffer {
public:
// Allocates and populate a JsonArray from a JSON string.
//
// The First argument is a pointer to the JSON string, the memory must be
// writable
// because the parser will insert null-terminators and replace escaped chars.
//
// The second argument set the nesting limit
//
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
// allocation fails.
// With this overload, the JsonBuffer will make a copy of the string
template <typename TString>
JsonArray &parseArray(
const TString &json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
return Internals::makeParser(that(), json, nestingLimit).parseArray();
}
template <typename TString>
JsonArray &parseArray(
TString &json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
return Internals::makeParser(that(), json, nestingLimit).parseArray();
}
// Allocates and populate a JsonObject from a JSON string.
//
// The First argument is a pointer to the JSON string, the memory must be
// writable
// because the parser will insert null-terminators and replace escaped chars.
//
// The second argument set the nesting limit
//
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
// allocation fails.
template <typename TString>
JsonObject &parseObject(
const TString &json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
return Internals::makeParser(that(), json, nestingLimit).parseObject();
}
template <typename TString>
JsonObject &parseObject(
TString &json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
return Internals::makeParser(that(), json, nestingLimit).parseObject();
}
// Generalized version of parseArray() and parseObject(), also works for
// integral types.
template <typename TString>
JsonVariant parse(const TString &json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
return Internals::makeParser(that(), json, nestingLimit).parseVariant();
}
template <typename TString>
JsonVariant parse(TString &json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
return Internals::makeParser(that(), json, nestingLimit).parseVariant();
}
private:
TDerived *that() {
return static_cast<TDerived *>(this);
}
};
}
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop
#endif
#endif

View File

@ -0,0 +1,20 @@
// 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 "Deserialization/JsonParser.hpp"
inline ArduinoJson::JsonArray &ArduinoJson::JsonBuffer::createArray() {
JsonArray *ptr = new (this) JsonArray(this);
return ptr ? *ptr : JsonArray::invalid();
}
inline ArduinoJson::JsonObject &ArduinoJson::JsonBuffer::createObject() {
JsonObject *ptr = new (this) JsonObject(this);
return ptr ? *ptr : JsonObject::invalid();
}

View File

@ -7,13 +7,13 @@
#pragma once
#include "Internals/JsonBufferAllocated.hpp"
#include "Internals/JsonPrintable.hpp"
#include "Internals/List.hpp"
#include "Internals/ReferenceType.hpp"
#include "Internals/StringFuncs.hpp"
#include "Internals/ValueSetter.hpp"
#include "Data/JsonBufferAllocated.hpp"
#include "Data/List.hpp"
#include "Data/ReferenceType.hpp"
#include "Data/ValueSetter.hpp"
#include "JsonPair.hpp"
#include "Serialization/JsonPrintable.hpp"
#include "StringTraits/StringTraits.hpp"
#include "TypeTraits/ConstRefOrConstPtr.hpp"
#include "TypeTraits/EnableIf.hpp"
#include "TypeTraits/IsFloatingPoint.hpp"
@ -165,4 +165,13 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
value);
}
};
namespace Internals {
template <>
struct JsonVariantDefault<JsonObject> {
static JsonObject& get() {
return JsonObject::invalid();
}
};
}
}

View File

@ -13,20 +13,6 @@
namespace ArduinoJson {
namespace Internals {
template <>
struct JsonVariantDefault<JsonObject> {
static JsonObject &get() {
return JsonObject::invalid();
}
};
}
inline JsonObject &JsonVariant::asObject() const {
if (_type == Internals::JSON_OBJECT) return *_content.asObject;
return JsonObject::invalid();
}
template <typename TString>
inline JsonObject &JsonObject::createNestedObject(const TString &key) {
if (!_buffer) return JsonObject::invalid();
@ -35,10 +21,11 @@ inline JsonObject &JsonObject::createNestedObject(const TString &key) {
return object;
}
inline JsonObject &JsonArray::createNestedObject() {
if (!_buffer) return JsonObject::invalid();
JsonObject &object = _buffer->createObject();
add(object);
return object;
template <typename TString>
inline JsonArray &JsonObject::createNestedArray(const TString &key) {
if (!_buffer) return JsonArray::invalid();
JsonArray &array = _buffer->createArray();
set(key, array);
return array;
}
}

View File

@ -84,13 +84,6 @@ template <typename TString>
inline JsonObjectSubscript<TString> JsonObject::operator[](const TString& key) {
return JsonObjectSubscript<TString>(*this, key);
}
template <typename TImplem>
template <class TString>
inline const JsonObjectSubscript<TString> JsonVariantBase<TImplem>::operator[](
const TString& key) const {
return asObject()[key];
}
} // namespace ArduinoJson
#ifdef _MSC_VER

View File

@ -10,12 +10,12 @@
#include <stddef.h>
#include <stdint.h> // for uint8_t
#include "Internals/JsonPrintable.hpp"
#include "Internals/JsonVariantContent.hpp"
#include "Internals/JsonVariantDefault.hpp"
#include "Internals/JsonVariantType.hpp"
#include "Data/JsonVariantContent.hpp"
#include "Data/JsonVariantDefault.hpp"
#include "Data/JsonVariantType.hpp"
#include "JsonVariantBase.hpp"
#include "RawJson.hpp"
#include "Serialization/JsonPrintable.hpp"
#include "TypeTraits/EnableIf.hpp"
#include "TypeTraits/IsFloatingPoint.hpp"
#include "TypeTraits/IsIntegral.hpp"

View File

@ -7,8 +7,9 @@
#pragma once
#include "Internals/JsonVariantAs.hpp"
#include "Data/JsonVariantAs.hpp"
#include "Polyfills/attributes.hpp"
#include "Serialization/JsonPrintable.hpp"
namespace ArduinoJson {
@ -71,78 +72,30 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
// Returns the element at specified index if the variant is an array.
// Returns JsonVariant::invalid() if the variant is not an array.
FORCE_INLINE const JsonArraySubscript operator[](int index) const;
FORCE_INLINE JsonArraySubscript operator[](int index);
// Mimics an object.
// Returns the value associated with the specified key if the variant is
// an object.
// Return JsonVariant::invalid() if the variant is not an object.
template <typename TString>
FORCE_INLINE const JsonObjectSubscript<TString> operator[](
const TString &key) const;
FORCE_INLINE
typename TypeTraits::EnableIf<Internals::StringFuncs<TString>::has_equals,
const JsonObjectSubscript<TString> >::type
operator[](const TString &key) const {
return asObject()[key];
}
template <typename TString>
FORCE_INLINE
typename TypeTraits::EnableIf<Internals::StringFuncs<TString>::has_equals,
JsonObjectSubscript<TString> >::type
operator[](const TString &key) {
return asObject()[key];
}
private:
const TImpl *impl() const {
return static_cast<const TImpl *>(this);
}
};
template <typename TImpl, typename TComparand>
inline bool operator==(const JsonVariantBase<TImpl> &left, TComparand right) {
return left.template as<TComparand>() == right;
}
template <typename TImpl, typename TComparand>
inline bool operator==(TComparand left, const JsonVariantBase<TImpl> &right) {
return left == right.template as<TComparand>();
}
template <typename TImpl, typename TComparand>
inline bool operator!=(const JsonVariantBase<TImpl> &left, TComparand right) {
return left.template as<TComparand>() != right;
}
template <typename TImpl, typename TComparand>
inline bool operator!=(TComparand left, const JsonVariantBase<TImpl> &right) {
return left != right.template as<TComparand>();
}
template <typename TImpl, typename TComparand>
inline bool operator<=(const JsonVariantBase<TImpl> &left, TComparand right) {
return left.template as<TComparand>() <= right;
}
template <typename TImpl, typename TComparand>
inline bool operator<=(TComparand left, const JsonVariantBase<TImpl> &right) {
return left <= right.template as<TComparand>();
}
template <typename TImpl, typename TComparand>
inline bool operator>=(const JsonVariantBase<TImpl> &left, TComparand right) {
return left.template as<TComparand>() >= right;
}
template <typename TImpl, typename TComparand>
inline bool operator>=(TComparand left, const JsonVariantBase<TImpl> &right) {
return left >= right.template as<TComparand>();
}
template <typename TImpl, typename TComparand>
inline bool operator<(const JsonVariantBase<TImpl> &left, TComparand right) {
return left.template as<TComparand>() < right;
}
template <typename TImpl, typename TComparand>
inline bool operator<(TComparand left, const JsonVariantBase<TImpl> &right) {
return left < right.template as<TComparand>();
}
template <typename TImpl, typename TComparand>
inline bool operator>(const JsonVariantBase<TImpl> &left, TComparand right) {
return left.template as<TComparand>() > right;
}
template <typename TImpl, typename TComparand>
inline bool operator>(TComparand left, const JsonVariantBase<TImpl> &right) {
return left > right.template as<TComparand>();
}
}

View File

@ -0,0 +1,106 @@
// 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 "JsonVariantBase.hpp"
#include "StringTraits/StringTraits.hpp"
#include "TypeTraits/EnableIf.hpp"
namespace ArduinoJson {
template <typename TVariant, typename TComparand, typename Enable = void>
struct JsonVariantComparer {
static bool equals(const TVariant &variant, const TComparand &comparand) {
return variant.template as<TComparand>() == comparand;
}
};
template <typename TVariant, typename TString>
struct JsonVariantComparer<
TVariant, TString, typename TypeTraits::EnableIf<
Internals::StringFuncs<TString>::has_equals>::type> {
static bool equals(const TVariant &variant, const TString &comparand) {
const char *value = variant.template as<const char *>();
return Internals::StringFuncs<TString>::equals(comparand, value);
}
};
template <typename TImpl, typename TComparand>
inline bool operator==(const JsonVariantBase<TImpl> &variant,
TComparand comparand) {
typedef JsonVariantBase<TImpl> TVariant;
return JsonVariantComparer<TVariant, TComparand>::equals(variant, comparand);
}
template <typename TImpl, typename TComparand>
inline bool operator==(TComparand comparand,
const JsonVariantBase<TImpl> &variant) {
typedef JsonVariantBase<TImpl> TVariant;
return JsonVariantComparer<TVariant, TComparand>::equals(variant, comparand);
}
template <typename TImpl, typename TComparand>
inline bool operator!=(const JsonVariantBase<TImpl> &variant,
TComparand comparand) {
typedef JsonVariantBase<TImpl> TVariant;
return !JsonVariantComparer<TVariant, TComparand>::equals(variant, comparand);
}
template <typename TImpl, typename TComparand>
inline bool operator!=(TComparand comparand,
const JsonVariantBase<TImpl> &variant) {
typedef JsonVariantBase<TImpl> TVariant;
return !JsonVariantComparer<TVariant, TComparand>::equals(variant, comparand);
}
template <typename TImpl, typename TComparand>
inline bool operator<=(const JsonVariantBase<TImpl> &left, TComparand right) {
return left.template as<TComparand>() <= right;
}
template <typename TImpl, typename TComparand>
inline bool operator<=(TComparand comparand,
const JsonVariantBase<TImpl> &variant) {
return comparand <= variant.template as<TComparand>();
}
template <typename TImpl, typename TComparand>
inline bool operator>=(const JsonVariantBase<TImpl> &variant,
TComparand comparand) {
return variant.template as<TComparand>() >= comparand;
}
template <typename TImpl, typename TComparand>
inline bool operator>=(TComparand comparand,
const JsonVariantBase<TImpl> &variant) {
return comparand >= variant.template as<TComparand>();
}
template <typename TImpl, typename TComparand>
inline bool operator<(const JsonVariantBase<TImpl> &varian,
TComparand comparand) {
return varian.template as<TComparand>() < comparand;
}
template <typename TImpl, typename TComparand>
inline bool operator<(TComparand comparand,
const JsonVariantBase<TImpl> &variant) {
return comparand < variant.template as<TComparand>();
}
template <typename TImpl, typename TComparand>
inline bool operator>(const JsonVariantBase<TImpl> &variant,
TComparand comparand) {
return variant.template as<TComparand>() > comparand;
}
template <typename TImpl, typename TComparand>
inline bool operator>(TComparand comparand,
const JsonVariantBase<TImpl> &variant) {
return comparand > variant.template as<TComparand>();
}
}

View File

@ -8,7 +8,7 @@
#pragma once
#include "Configuration.hpp"
#include "Internals/Parse.hpp"
#include "Data/Parse.hpp"
#include "JsonArray.hpp"
#include "JsonObject.hpp"
#include "JsonVariant.hpp"
@ -19,6 +19,34 @@
namespace ArduinoJson {
inline JsonVariant::JsonVariant(const JsonArray &array) {
if (array.success()) {
_type = Internals::JSON_ARRAY;
_content.asArray = const_cast<JsonArray *>(&array);
} else {
_type = Internals::JSON_UNDEFINED;
}
}
inline JsonVariant::JsonVariant(const JsonObject &object) {
if (object.success()) {
_type = Internals::JSON_OBJECT;
_content.asObject = const_cast<JsonObject *>(&object);
} else {
_type = Internals::JSON_UNDEFINED;
}
}
inline JsonArray &JsonVariant::asArray() const {
if (_type == Internals::JSON_ARRAY) return *_content.asArray;
return JsonArray::invalid();
}
inline JsonObject &JsonVariant::asObject() const {
if (_type == Internals::JSON_OBJECT) return *_content.asObject;
return JsonObject::invalid();
}
inline Internals::JsonInteger JsonVariant::asInteger() const {
using namespace Internals;
switch (_type) {

View File

@ -8,7 +8,7 @@
#pragma once
#include "../Print.hpp"
#include "StringFuncs.hpp"
#include "../StringTraits/StringTraits.hpp"
namespace ArduinoJson {
namespace Internals {

View File

@ -50,6 +50,11 @@ class JsonPrintable {
return printTo(sb);
}
template <size_t N>
size_t printTo(char (&buffer)[N]) const {
return printTo(buffer, N);
}
template <typename TString>
typename TypeTraits::EnableIf<StringFuncs<TString>::has_append, size_t>::type
printTo(TString &str) const {
@ -67,6 +72,11 @@ class JsonPrintable {
return prettyPrintTo(sb);
}
template <size_t N>
size_t prettyPrintTo(char (&buffer)[N]) const {
return prettyPrintTo(buffer, N);
}
size_t prettyPrintTo(Print &print) const {
IndentedPrint indentedPrint = IndentedPrint(print);
return prettyPrintTo(indentedPrint);

View File

@ -7,13 +7,13 @@
#pragma once
#include "../Data/Encoding.hpp"
#include "../Data/JsonFloat.hpp"
#include "../Data/JsonInteger.hpp"
#include "../Polyfills/attributes.hpp"
#include "../Polyfills/math.hpp"
#include "../Polyfills/normalize.hpp"
#include "../Print.hpp"
#include "Encoding.hpp"
#include "JsonFloat.hpp"
#include "JsonInteger.hpp"
namespace ArduinoJson {
namespace Internals {

View File

@ -7,7 +7,7 @@
#pragma once
#include "JsonBuffer.hpp"
#include "JsonBufferBase.hpp"
#if defined(__clang__)
#pragma clang diagnostic push
@ -21,32 +21,87 @@
namespace ArduinoJson {
// Implements a JsonBuffer with fixed memory allocation.
// The template paramenter CAPACITY specifies the capacity of the buffer in
// bytes.
template <size_t CAPACITY>
class StaticJsonBuffer : public JsonBuffer {
class StaticJsonBufferBase : public JsonBufferBase<StaticJsonBufferBase> {
public:
explicit StaticJsonBuffer() : _size(0) {}
class String {
public:
String(StaticJsonBufferBase* parent) : _parent(parent) {
_start = parent->_buffer + parent->_size;
}
void append(char c) {
if (_parent->canAlloc(1)) {
char* last = static_cast<char*>(_parent->doAlloc(1));
*last = c;
}
}
const char* c_str() const {
if (_parent->canAlloc(1)) {
char* last = static_cast<char*>(_parent->doAlloc(1));
*last = '\0';
return _start;
} else {
return NULL;
}
}
private:
StaticJsonBufferBase* _parent;
char* _start;
};
StaticJsonBufferBase(char* buffer, size_t capa)
: _buffer(buffer), _capacity(capa), _size(0) {}
size_t capacity() const {
return CAPACITY;
return _capacity;
}
size_t size() const {
return _size;
}
virtual void* alloc(size_t bytes) {
if (_size + bytes > CAPACITY) return NULL;
void* p = &_buffer[_size];
_size += round_size_up(bytes);
return p;
alignNextAlloc();
if (!canAlloc(bytes)) return NULL;
return doAlloc(bytes);
}
String startString() {
return String(this);
}
private:
uint8_t _buffer[CAPACITY];
void alignNextAlloc() {
_size = round_size_up(_size);
}
bool canAlloc(size_t bytes) const {
return _size + bytes <= _capacity;
}
void* doAlloc(size_t bytes) {
void* p = &_buffer[_size];
_size += bytes;
return p;
}
char* _buffer;
size_t _capacity;
size_t _size;
};
// Implements a JsonBuffer with fixed memory allocation.
// The template paramenter CAPACITY specifies the capacity of the buffer in
// bytes.
template <size_t CAPACITY>
class StaticJsonBuffer : public StaticJsonBufferBase {
public:
explicit StaticJsonBuffer() : StaticJsonBufferBase(_buffer, CAPACITY) {}
private:
char _buffer[CAPACITY];
};
}
#if defined(__clang__)

View 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 {};
}
}

View 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 {};
}
}

View 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;
};
}
}

View 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 {};
}
}

View 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
}
}

View 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

View 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)
};
};
}
}

View File

@ -2,6 +2,7 @@ JsonArray KEYWORD1
JsonObject KEYWORD1
JsonVariant KEYWORD1
StaticJsonBuffer KEYWORD1
DynamicJsonBuffer KEYWORD1
add KEYWORD2
createArray KEYWORD2
createNestedArray KEYWORD2

View File

@ -6,7 +6,7 @@
"type": "git",
"url": "https://github.com/bblanchon/ArduinoJson.git"
},
"version": "5.7.0",
"version": "5.8.0",
"authors": {
"name": "Benoit Blanchon",
"url": "http://blog.benoitblanchon.fr"

View File

@ -1,5 +1,5 @@
name=ArduinoJson
version=5.7.0
version=5.8.0
author=Benoit Blanchon <blog.benoitblanchon.fr>
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
sentence=An efficient and elegant JSON library for Arduino.

View File

@ -1,143 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>ArduinoJson - JsonBuffer size calculator</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div class="container">
<div class="jumbotron">
<h1>JsonBuffer size calculator</h1>
</div>
<div id='error' class="alert alert-danger" role="alert">
Please paste your JSON in the "input" box
</div>
<div class="row">
<div class="col-md-6">
<h2>Input</h2>
<textarea class="form-control" rows=30 id='input'></textarea><br>
</div>
<div id='results' class="col-md-6" style='display:none'>
<h2>Result</h2>
<h3>Expression</h3>
<p><code id='resultexpr'></code></p>
<table class="table">
<thead>
<th>Platform</th>
<th>Size (in bytes)</th>
</thead>
<tbody>
<tr>
<td>AVR 8-bit</td>
<td id='sizeavr8'></td>
</tr>
<tr>
<td>ESP8266</td>
<td id='sizeesp8266'></td>
</tr>
<tr>
<td>x86</td>
<td id='sizex86'></td>
</tr>
<tr>
<td>x64</td>
<td id='sizex64'></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</body>
<script type="text/javascript">
function Recipe() {
var arrays = [];
var objects = [];
this.addJsonArray = function(size) {
if (arrays[size])
arrays[size]++;
else
arrays[size] = 1;
}
this.addJsonObject = function(size) {
if (objects[size])
objects[size]++;
else
objects[size] = 1;
}
this.getExpression = function() {
var elements = [];
for (var size in arrays) {
var count = arrays[size];
if (count > 1)
elements.push(count + "*JSON_ARRAY_SIZE("+size+")");
else
elements.push("JSON_ARRAY_SIZE("+size+")");
}
for (var size in objects) {
var count = objects[size];
if (count > 1)
elements.push(count + "*JSON_OBJECT_SIZE("+size+")");
else
elements.push("JSON_OBJECT_SIZE("+size+")");
}
return elements.join(" + ");
}
}
function scanJson(recipe, obj) {
if (obj instanceof Array) {
recipe.addJsonArray(obj.length);
for (var i = 0; i<obj.length; i++)
scanJson(recipe, obj[i]);
}
else if (obj instanceof Object) {
recipe.addJsonObject(Object.keys(obj).length);
for (var key in obj)
scanJson(recipe, obj[key]);
}
}
input.oninput = function(e) {
results.style.display = 'none';
error.style.visibility = 'hidden';
try {
var recipe = new Recipe();
scanJson(recipe, JSON.parse(input.value));
var expression = recipe.getExpression();
resultexpr.innerText = expression;
sizeavr8.innerText = eval(
"function JSON_ARRAY_SIZE(n) { return 4 + 8*n }" +
"function JSON_OBJECT_SIZE(n) { return 4 + 10*n }" +
expression
);
sizeesp8266.innerText = eval(
"function JSON_ARRAY_SIZE(n) { return 8 + 12*n }" +
"function JSON_OBJECT_SIZE(n) { return 8 + 16*n }" +
expression
);
sizex86.innerText = eval(
"function JSON_ARRAY_SIZE(n) { return 12 + 24*n }" +
"function JSON_OBJECT_SIZE(n) { return 12 + 32*n }" +
expression
);
sizex64.innerText = eval(
"function JSON_ARRAY_SIZE(n) { return 24 + 24*n }" +
"function JSON_OBJECT_SIZE(n) { return 24 + 32*n }" +
expression
);
results.style.display = 'block';
}
catch (ex) {
error.innerText = "ERROR: " + ex.message;
error.style.visibility = 'visible';
}
}
</script>
</html>

View File

@ -6,5 +6,5 @@ curl https://cmake.org/files/v3.4/cmake-3.4.0-Linux-x86_64.tar.gz | tar xz -C /t
make
make test
pip install --user cpp-coveralls
pip install --user cpp-coveralls 'requests[security]'
coveralls --exclude third-party --gcov-options '\-lp'; fi

View File

@ -4,7 +4,7 @@ pip install --user platformio
rm -r test
for EXAMPLE in JsonParserExample JsonGeneratorExample
for EXAMPLE in $PWD/examples/*/*.ino;
do
platformio ci examples/$EXAMPLE/$EXAMPLE.ino -l '.' -b $BOARD
platformio ci $EXAMPLE -l '.' -b $BOARD
done

7
scripts/travis/sanitize.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh -eux
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 .
cmake --build .
ctest -VV .

View File

@ -12,7 +12,6 @@ file(GLOB TESTS_FILES *.hpp *.cpp)
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
add_compile_options(
-fno-exceptions
-fno-rtti
-pedantic
-Wall
-Wcast-align

View File

@ -30,13 +30,19 @@ TEST_F(DynamicJsonBuffer_Basic_Tests, ReturnDifferentPointer) {
ASSERT_NE(p1, p2);
}
TEST_F(DynamicJsonBuffer_Basic_Tests, Alignment) {
size_t mask = sizeof(void*) - 1;
static bool isAligned(void* ptr) {
const size_t mask = sizeof(void*) - 1;
size_t addr = reinterpret_cast<size_t>(ptr);
return (addr & mask) == 0;
}
for (size_t size = 1; size <= sizeof(void*); size++) {
size_t addr = reinterpret_cast<size_t>(buffer.alloc(1));
ASSERT_EQ(0, addr & mask);
}
TEST_F(DynamicJsonBuffer_Basic_Tests, Alignment) {
// make room for tow but not three
buffer = DynamicJsonBuffer(2 * sizeof(void*) + 1);
ASSERT_TRUE(isAligned(buffer.alloc(1))); // this on is aligned by design
ASSERT_TRUE(isAligned(buffer.alloc(1))); // this one fits in the first block
ASSERT_TRUE(isAligned(buffer.alloc(1))); // this one requires a new block
}
TEST_F(DynamicJsonBuffer_Basic_Tests, strdup) {

View File

@ -5,18 +5,20 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#include <gtest/gtest.h>
class NoMemoryAllocator {
public:
void* allocate(size_t) { return NULL; }
void* allocate(size_t) {
return NULL;
}
void deallocate(void*) {}
};
class DynamicJsonBuffer_NoMemory_Tests : public ::testing::Test {
protected:
Internals::BlockJsonBuffer<NoMemoryAllocator> _jsonBuffer;
DynamicJsonBufferBase<NoMemoryAllocator> _jsonBuffer;
};
TEST_F(DynamicJsonBuffer_NoMemory_Tests, FixCodeCoverage) {

View File

@ -0,0 +1,48 @@
// 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>
TEST(DynamicJsonBuffer_String_Tests, WorksWhenBufferIsBigEnough) {
DynamicJsonBuffer jsonBuffer(6);
DynamicJsonBuffer::String str = jsonBuffer.startString();
str.append('h');
str.append('e');
str.append('l');
str.append('l');
str.append('o');
ASSERT_STREQ("hello", str.c_str());
}
TEST(DynamicJsonBuffer_String_Tests, GrowsWhenBufferIsTooSmall) {
DynamicJsonBuffer jsonBuffer(5);
DynamicJsonBuffer::String str = jsonBuffer.startString();
str.append('h');
str.append('e');
str.append('l');
str.append('l');
str.append('o');
ASSERT_STREQ("hello", str.c_str());
}
TEST(DynamicJsonBuffer_String_Tests, SizeIncreases) {
DynamicJsonBuffer jsonBuffer(5);
DynamicJsonBuffer::String str = jsonBuffer.startString();
ASSERT_EQ(0, jsonBuffer.size());
str.append('h');
ASSERT_EQ(1, jsonBuffer.size());
str.c_str();
ASSERT_EQ(2, jsonBuffer.size());
}

View File

@ -5,8 +5,8 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#include <gtest/gtest.h>
class JsonArray_PrettyPrintTo_Tests : public testing::Test {
public:
@ -19,7 +19,7 @@ class JsonArray_PrettyPrintTo_Tests : public testing::Test {
void outputMustBe(const char* expected) {
char actual[256];
size_t actualLen = array.prettyPrintTo(actual, sizeof(actual));
size_t actualLen = array.prettyPrintTo(actual);
size_t measuredLen = array.measurePrettyLength();
EXPECT_STREQ(expected, actual);
@ -28,7 +28,9 @@ class JsonArray_PrettyPrintTo_Tests : public testing::Test {
}
};
TEST_F(JsonArray_PrettyPrintTo_Tests, Empty) { outputMustBe("[]"); }
TEST_F(JsonArray_PrettyPrintTo_Tests, Empty) {
outputMustBe("[]");
}
TEST_F(JsonArray_PrettyPrintTo_Tests, OneElement) {
array.add(1);

View File

@ -5,8 +5,8 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#include <gtest/gtest.h>
class JsonArray_PrintTo_Tests : public testing::Test {
public:
@ -17,7 +17,7 @@ class JsonArray_PrintTo_Tests : public testing::Test {
JsonArray &array;
void outputMustBe(const char *expected) {
size_t actualLen = array.printTo(buffer, sizeof(buffer));
size_t actualLen = array.printTo(buffer);
size_t measuredLen = array.measureLength();
EXPECT_STREQ(expected, buffer);
@ -29,7 +29,9 @@ class JsonArray_PrintTo_Tests : public testing::Test {
char buffer[256];
};
TEST_F(JsonArray_PrintTo_Tests, Empty) { outputMustBe("[]"); }
TEST_F(JsonArray_PrintTo_Tests, Empty) {
outputMustBe("[]");
}
TEST_F(JsonArray_PrintTo_Tests, Null) {
array.add(static_cast<char *>(0));

View File

@ -5,8 +5,8 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#include <gtest/gtest.h>
class JsonObject_PrettyPrintTo_Tests : public testing::Test {
public:
@ -19,7 +19,7 @@ class JsonObject_PrettyPrintTo_Tests : public testing::Test {
void outputMustBe(const char *expected) {
char buffer[256];
size_t actualLen = _object.prettyPrintTo(buffer, sizeof(buffer));
size_t actualLen = _object.prettyPrintTo(buffer);
size_t measuredLen = _object.measurePrettyLength();
EXPECT_STREQ(expected, buffer);
@ -28,7 +28,9 @@ class JsonObject_PrettyPrintTo_Tests : public testing::Test {
}
};
TEST_F(JsonObject_PrettyPrintTo_Tests, EmptyObject) { outputMustBe("{}"); }
TEST_F(JsonObject_PrettyPrintTo_Tests, EmptyObject) {
outputMustBe("{}");
}
TEST_F(JsonObject_PrettyPrintTo_Tests, OneMember) {
_object["key"] = "value";

View File

@ -15,7 +15,7 @@ class JsonObject_PrintTo_Tests : public testing::Test {
protected:
void outputMustBe(const char *expected) {
char actual[256];
size_t actualLen = _object.printTo(actual, sizeof(actual));
size_t actualLen = _object.printTo(actual);
size_t measuredLen = _object.measureLength();
EXPECT_STREQ(expected, actual);
@ -27,7 +27,9 @@ class JsonObject_PrintTo_Tests : public testing::Test {
JsonObject &_object;
};
TEST_F(JsonObject_PrintTo_Tests, EmptyObject) { outputMustBe("{}"); }
TEST_F(JsonObject_PrintTo_Tests, EmptyObject) {
outputMustBe("{}");
}
TEST_F(JsonObject_PrintTo_Tests, TwoStrings) {
_object["key1"] = "value1";

View File

@ -5,8 +5,8 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#include <gtest/gtest.h>
class JsonObject_Subscript_Tests : public ::testing::Test {
public:

View File

@ -351,6 +351,16 @@ TEST_F(JsonParser_Array_Tests, UnfinishedCComment) {
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) {
whenInputIs("[[[[[[[[[[[[[[[[[[[\"Not too deep\"]]]]]]]]]]]]]]]]]]]");
parseMustSucceed();

View File

@ -5,8 +5,8 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#include <gtest/gtest.h>
class JsonParser_Variant_Test : public testing::Test {
protected:
@ -92,7 +92,14 @@ TEST_F(JsonParser_Variant_Test, True) {
verify("false", false);
}
TEST_F(JsonParser_Variant_Test, Invalid) {
TEST_F(JsonParser_Variant_Test, OpenBrace) {
whenInputIs("{");
resultMustBeInvalid();
}
TEST_F(JsonParser_Variant_Test, IncompleteStrings) {
verify("\"", "");
verify("\"hello", "hello");
verify("\'", "");
verify("\'world", "world");
}

View File

@ -5,8 +5,8 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#include <gtest/gtest.h>
class JsonVariant_Comparison_Tests : public ::testing::Test {
protected:
@ -92,3 +92,37 @@ TEST_F(JsonVariant_Comparison_Tests, ULong) {
TEST_F(JsonVariant_Comparison_Tests, UShort) {
testValue<unsigned short>(122, 123, 124);
}
TEST_F(JsonVariant_Comparison_Tests, StringLiteral) {
DynamicJsonBuffer jsonBuffer;
JsonVariant variant = jsonBuffer.parse("\"hello\"");
ASSERT_TRUE(variant == "hello");
ASSERT_FALSE(variant != "hello");
ASSERT_TRUE(variant != "world");
ASSERT_FALSE(variant == "world");
ASSERT_TRUE("hello" == variant);
ASSERT_FALSE("hello" != variant);
ASSERT_TRUE("world" != variant);
ASSERT_FALSE("world" == variant);
}
TEST_F(JsonVariant_Comparison_Tests, String) {
DynamicJsonBuffer jsonBuffer;
JsonVariant variant = jsonBuffer.parse("\"hello\"");
ASSERT_TRUE(variant == std::string("hello"));
ASSERT_FALSE(variant != std::string("hello"));
ASSERT_TRUE(variant != std::string("world"));
ASSERT_FALSE(variant == std::string("world"));
ASSERT_TRUE(std::string("hello") == variant);
ASSERT_FALSE(std::string("hello") != variant);
ASSERT_TRUE(std::string("world") != variant);
ASSERT_FALSE(std::string("world") == variant);
}

View File

@ -5,8 +5,8 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#include <gtest/gtest.h>
class JsonVariant_Subscript_Tests : public ::testing::Test {
protected:
@ -24,6 +24,9 @@ TEST_F(JsonVariant_Subscript_Tests, Array) {
EXPECT_EQ(2, _variant.size());
EXPECT_STREQ("element at index 0", _variant[0].asString());
EXPECT_STREQ("element at index 1", _variant[1].asString());
EXPECT_STREQ(
"element at index 0",
_variant[static_cast<unsigned char>(0)].asString()); // issue #381
EXPECT_FALSE(_variant[-1].success());
EXPECT_FALSE(_variant[3].success());
EXPECT_FALSE(_variant["0"].success());
@ -56,3 +59,25 @@ TEST_F(JsonVariant_Subscript_Tests, String) {
EXPECT_FALSE(_variant["0"].success());
EXPECT_FALSE(_variant[0].success());
}
TEST_F(JsonVariant_Subscript_Tests, ObjectSetValue) {
_variant = _jsonBuffer.createObject();
_variant["hello"] = "world";
EXPECT_EQ(1, _variant.size());
EXPECT_STREQ("world", _variant["hello"]);
}
TEST_F(JsonVariant_Subscript_Tests, ArraySetValue) {
_variant = _jsonBuffer.parseArray("[\"hello\"]");
_variant[0] = "world";
EXPECT_EQ(1, _variant.size());
EXPECT_STREQ("world", _variant[0]);
}
TEST_F(JsonVariant_Subscript_Tests, NestedObjectSetValue) {
_variant = _jsonBuffer.parseArray("[{}]");
_variant[0]["hello"] = "world";
EXPECT_EQ(1, _variant.size());
EXPECT_EQ(1, _variant[0].size());
EXPECT_STREQ("world", _variant[0]["hello"]);
}

View File

@ -8,8 +8,8 @@
#include <gtest/gtest.h>
#include <limits>
#include <ArduinoJson/Internals/JsonWriter.hpp>
#include <ArduinoJson/Internals/StaticStringBuilder.hpp>
#include <ArduinoJson/Serialization/JsonWriter.hpp>
#include <ArduinoJson/Serialization/StaticStringBuilder.hpp>
using namespace ArduinoJson::Internals;

View File

@ -7,8 +7,8 @@
#include <gtest/gtest.h>
#include <ArduinoJson/Internals/JsonWriter.hpp>
#include <ArduinoJson/Internals/StaticStringBuilder.hpp>
#include <ArduinoJson/Serialization/JsonWriter.hpp>
#include <ArduinoJson/Serialization/StaticStringBuilder.hpp>
using namespace ArduinoJson::Internals;

View File

@ -5,12 +5,12 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#include <gtest/gtest.h>
class StaticJsonBuffer_ParseArray_Tests : public testing::Test {
protected:
void with(JsonBuffer& jsonBuffer) {
void with(StaticJsonBufferBase& jsonBuffer) {
_jsonBuffer = &jsonBuffer;
}
@ -27,7 +27,7 @@ class StaticJsonBuffer_ParseArray_Tests : public testing::Test {
}
private:
JsonBuffer* _jsonBuffer;
StaticJsonBufferBase* _jsonBuffer;
char _jsonString[256];
};
@ -86,3 +86,11 @@ TEST_F(StaticJsonBuffer_ParseArray_Tests, ConstCharPtrNull) {
.parseArray(static_cast<const char*>(0))
.success());
}
TEST_F(StaticJsonBuffer_ParseArray_Tests, CopyStringNotSpaces) {
StaticJsonBuffer<100> jsonBuffer;
jsonBuffer.parseArray(" [ \"1234567\" ] ");
ASSERT_EQ(JSON_ARRAY_SIZE(1) + sizeof("1234567"), jsonBuffer.size());
// note we use a string of 8 bytes to be sure that the StaticJsonBuffer
// will not insert bytes to enforce alignement
}

View File

@ -10,7 +10,7 @@
class StaticJsonBuffer_ParseObject_Tests : public testing::Test {
protected:
void with(JsonBuffer& jsonBuffer) {
void with(StaticJsonBufferBase& jsonBuffer) {
_jsonBuffer = &jsonBuffer;
}
@ -27,7 +27,7 @@ class StaticJsonBuffer_ParseObject_Tests : public testing::Test {
}
private:
JsonBuffer* _jsonBuffer;
StaticJsonBufferBase* _jsonBuffer;
char _jsonString[256];
};

View File

@ -0,0 +1,48 @@
// 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>
TEST(StaticJsonBuffer_String_Tests, WorksWhenBufferIsBigEnough) {
StaticJsonBuffer<6> jsonBuffer;
StaticJsonBufferBase::String str = jsonBuffer.startString();
str.append('h');
str.append('e');
str.append('l');
str.append('l');
str.append('o');
ASSERT_STREQ("hello", str.c_str());
}
TEST(StaticJsonBuffer_String_Tests, ReturnsNullWhenTooSmall) {
StaticJsonBuffer<5> jsonBuffer;
StaticJsonBufferBase::String str = jsonBuffer.startString();
str.append('h');
str.append('e');
str.append('l');
str.append('l');
str.append('o');
ASSERT_EQ(NULL, str.c_str());
}
TEST(StaticJsonBuffer_String_Tests, SizeIncreases) {
StaticJsonBuffer<5> jsonBuffer;
StaticJsonBufferBase::String str = jsonBuffer.startString();
ASSERT_EQ(0, jsonBuffer.size());
str.append('h');
ASSERT_EQ(1, jsonBuffer.size());
str.c_str();
ASSERT_EQ(2, jsonBuffer.size());
}

View File

@ -5,25 +5,25 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <sstream>
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#include <gtest/gtest.h>
#include <sstream>
TEST(StdStream, JsonVariantFalse) {
TEST(StdStream_Tests, JsonVariantFalse) {
std::ostringstream os;
JsonVariant variant = false;
os << variant;
ASSERT_EQ("false", os.str());
}
TEST(StdStream, JsonVariantString) {
TEST(StdStream_Tests, JsonVariantString) {
std::ostringstream os;
JsonVariant variant = "coucou";
os << variant;
ASSERT_EQ("\"coucou\"", os.str());
}
TEST(StdStream, JsonObject) {
TEST(StdStream_Tests, JsonObject) {
std::ostringstream os;
DynamicJsonBuffer jsonBuffer;
JsonObject& object = jsonBuffer.createObject();
@ -32,7 +32,7 @@ TEST(StdStream, JsonObject) {
ASSERT_EQ("{\"key\":\"value\"}", os.str());
}
TEST(StdStream, JsonObjectSubscript) {
TEST(StdStream_Tests, JsonObjectSubscript) {
std::ostringstream os;
DynamicJsonBuffer jsonBuffer;
JsonObject& object = jsonBuffer.createObject();
@ -41,7 +41,7 @@ TEST(StdStream, JsonObjectSubscript) {
ASSERT_EQ("\"value\"", os.str());
}
TEST(StdStream, JsonArray) {
TEST(StdStream_Tests, JsonArray) {
std::ostringstream os;
DynamicJsonBuffer jsonBuffer;
JsonArray& array = jsonBuffer.createArray();
@ -50,7 +50,7 @@ TEST(StdStream, JsonArray) {
ASSERT_EQ("[\"value\"]", os.str());
}
TEST(StdStream, JsonArraySubscript) {
TEST(StdStream_Tests, JsonArraySubscript) {
std::ostringstream os;
DynamicJsonBuffer jsonBuffer;
JsonArray& array = jsonBuffer.createArray();
@ -58,3 +58,21 @@ TEST(StdStream, JsonArraySubscript) {
os << array[0];
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
View 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));
}