Compare commits

..

20 Commits
v4.1 ... v4.6

Author SHA1 Message Date
2524a00a96 Fixed segmentation fault in DynamicJsonBuffer when memory allocation fails (issue #92) 2015-08-01 16:31:59 +02:00
f5b83f9314 Added greeting to Giancarlo Canales Barreto 2015-06-14 15:26:33 +02:00
5e7b9ec688 Fix buffer overflow (pull request #81) 2015-06-10 21:33:20 +02:00
08d05df00e Added JsonPrintable::measureLength() (issue #75) 2015-05-09 16:53:48 +02:00
c385862be1 Updated change log for v4.3 2015-05-03 15:49:44 +02:00
0eff567910 Added JsonArray::removeAt() (issue #58) 2015-05-02 15:16:18 +02:00
94d38c0680 Added issue #68 in changelog 2015-04-27 16:01:05 +02:00
81285f49fe Fixed issue #68 2015-04-27 15:57:40 +02:00
877096d49d Fixed issue #67 2015-04-23 21:27:58 +02:00
bfe60243a4 Fixed issue #65 2015-04-18 15:37:15 +02:00
ca9d606e72 Added example JsonUdpBeacon 2015-02-25 22:27:30 +01:00
24d21467dd Updated change log for v4.2 2015-02-07 20:49:05 +01:00
41651136bf Switched back to old library layout (issues #39, #43 and #45) 2015-02-07 20:46:46 +01:00
5e5f060fc0 Updated copyright for 2015 2015-02-07 16:05:48 +01:00
29ab5fc9c2 Reduced code size by 12 bytes 2015-02-07 16:01:09 +01:00
80913b8044 Fixed Visual Studio's warnings 2015-02-07 15:05:46 +01:00
02960f28e4 Fix coveralls command line 2015-02-03 14:38:44 +01:00
8db338ba14 Removed global new operator overload (issue #40, #45 and #46) 2015-02-01 20:59:31 +01:00
dadd8986dc Mute compiler warning (issue #47) 2015-01-15 21:05:14 +01:00
e2016cf65b Added an example with EthernetServer 2015-01-10 15:25:27 +01:00
90 changed files with 849 additions and 291 deletions

3
.clang-format Normal file
View File

@ -0,0 +1,3 @@
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
BasedOnStyle: Google

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
*.sh text eol=lf

View File

@ -9,4 +9,4 @@ before_script:
script: script:
- make && make test - make && make test
after_success: after_success:
- coveralls --include include --include src --gcov-options '\-lp' - coveralls --exclude test --exclude third-party --gcov-options '\-lp'

24
ArduinoJson.cpp Normal file
View File

@ -0,0 +1,24 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#ifdef ARDUINO
// This file is here to help the Arduino IDE find the other files.
#include "src/Arduino/Print.cpp"
#include "src/DynamicJsonBuffer.cpp"
#include "src/Internals/IndentedPrint.cpp"
#include "src/Internals/JsonParser.cpp"
#include "src/Internals/List.cpp"
#include "src/Internals/Prettyfier.cpp"
#include "src/Internals/QuotedString.cpp"
#include "src/Internals/StringBuilder.cpp"
#include "src/JsonArray.cpp"
#include "src/JsonBuffer.cpp"
#include "src/JsonObject.cpp"
#include "src/JsonVariant.cpp"
#endif

13
ArduinoJson.h Normal file
View File

@ -0,0 +1,13 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#ifdef ARDUINO
// This file is here to help the Arduino IDE find the other files.
#include "include/ArduinoJson.h"
#endif

View File

@ -1,6 +1,39 @@
Arduino JSON: change log Arduino JSON: change log
======================== ========================
v4.6
----
* Fixed segmentation fault in `DynamicJsonBuffer` when memory allocation fails (issue #92)
v4.5
----
* Fixed buffer overflow when input contains a backslash followed by a terminator (issue #81)
**Upgrading is recommended** since previous versions contain a potential security risk.
Special thanks to [Giancarlo Canales Barreto](https://github.com/gcanalesb) for finding this nasty bug.
v4.4
----
* Added `JsonArray::measureLength()` and `JsonObject::measureLength()` (issue #75)
v4.3
----
* Added `JsonArray::removeAt()` to remove an element of an array (issue #58)
* Fixed stack-overflow in `DynamicJsonBuffer` when parsing huge JSON files (issue #65)
* Fixed wrong return value of `parseArray()` and `parseObject()` when allocation fails (issue #68)
v4.2
----
* Switched back to old library layout (issues #39, #43 and #45)
* Removed global new operator overload (issue #40, #45 and #46)
* Added an example with EthernetServer
v4.1 v4.1
---- ----

View File

@ -0,0 +1,74 @@
// Sample Arduino Json Web Server
// Created by Benoit Blanchon.
// Heavily inspired by "Web Server" from David A. Mellis and Tom Igoe
#include <SPI.h>
#include <Ethernet.h>
#include <ArduinoJson.h>
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 0, 177);
EthernetServer server(80);
bool readRequest(EthernetClient& client) {
bool currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
if (c == '\n' && currentLineIsBlank) {
return true;
} else if (c == '\n') {
currentLineIsBlank = true;
} else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
return false;
}
JsonObject& prepareResponse(JsonBuffer& jsonBuffer) {
JsonObject& root = jsonBuffer.createObject();
JsonArray& analogValues = root.createNestedArray("analog");
for (int pin = 0; pin < 6; pin++) {
int value = analogRead(pin);
analogValues.add(value);
}
JsonArray& digitalValues = root.createNestedArray("digital");
for (int pin = 0; pin < 14; pin++) {
int value = digitalRead(pin);
digitalValues.add(value);
}
return root;
}
void writeResponse(EthernetClient& client, JsonObject& json) {
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: application/json");
client.println("Connection: close");
client.println();
json.prettyPrintTo(client);
}
void setup() {
Ethernet.begin(mac, ip);
server.begin();
}
void loop() {
EthernetClient client = server.available();
if (client) {
bool success = readRequest(client);
if (success) {
StaticJsonBuffer<500> jsonBuffer;
JsonObject& json = prepareResponse(jsonBuffer);
writeResponse(client, json);
}
delay(1);
client.stop();
}
}

View File

@ -0,0 +1,55 @@
// Send a JSON object on UDP at regular interval
//
// You can easily test this program with netcat:
// $ nc -ulp 8888
//
// by Benoit Blanchon, MIT License 2015
#include <SPI.h>
#include <Ethernet.h>
#include <ArduinoJson.h>
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress localIp(192, 168, 0, 177);
IPAddress remoteIp(192, 168, 0, 109);
unsigned int remotePort = 8888;
unsigned localPort = 8888;
EthernetUDP udp;
JsonObject& buildJson(JsonBuffer& jsonBuffer) {
JsonObject& root = jsonBuffer.createObject();
JsonArray& analogValues = root.createNestedArray("analog");
for (int pin = 0; pin < 6; pin++) {
int value = analogRead(pin);
analogValues.add(value);
}
JsonArray& digitalValues = root.createNestedArray("digital");
for (int pin = 0; pin < 14; pin++) {
int value = digitalRead(pin);
digitalValues.add(value);
}
return root;
}
void sendJson(JsonObject& json) {
udp.beginPacket(remoteIp, remotePort);
json.printTo(udp);
udp.println();
udp.endPacket();
}
void setup() {
Ethernet.begin(mac, localIp);
udp.begin(localPort);
}
void loop() {
delay(1000);
StaticJsonBuffer<300> jsonBuffer;
JsonObject& json = buildJson(jsonBuffer);
sendJson(json);
}

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -6,62 +6,12 @@
#pragma once #pragma once
#include "JsonBuffer.hpp" #include "Internals/BlockJsonBuffer.hpp"
namespace ArduinoJson { namespace ArduinoJson {
// Implements a JsonBuffer with dynamic memory allocation. // Implements a JsonBuffer with dynamic memory allocation.
// You are strongly encouraged to consider using StaticJsonBuffer which is much // You are strongly encouraged to consider using StaticJsonBuffer which is much
// more suitable for embedded systems. // more suitable for embedded systems.
class DynamicJsonBuffer : public JsonBuffer { typedef Internals::BlockJsonBuffer<Internals::DefaultAllocator>
public: DynamicJsonBuffer;
DynamicJsonBuffer() : _next(NULL), _size(0) {}
~DynamicJsonBuffer() { delete _next; }
size_t size() const { return _size + (_next ? _next->size() : 0); }
size_t blockCount() const { return 1 + (_next ? _next->blockCount() : 0); }
static const size_t BLOCK_CAPACITY = 32;
protected:
virtual void* alloc(size_t bytes) {
if (canAllocInThisBlock(bytes))
return allocInThisBlock(bytes);
else if (canAllocInOtherBlocks(bytes))
return allocInOtherBlocks(bytes);
else
return NULL;
}
private:
bool canAllocInThisBlock(size_t bytes) const {
return _size + bytes <= BLOCK_CAPACITY;
}
void* allocInThisBlock(size_t bytes) {
void* p = _buffer + _size;
_size += bytes;
return p;
}
bool canAllocInOtherBlocks(size_t bytes) const {
// by design a DynamicJsonBuffer can't alloc a block bigger than
// BLOCK_CAPACITY
return bytes <= BLOCK_CAPACITY;
}
void* allocInOtherBlocks(size_t bytes) {
if (!_next) {
_next = new DynamicJsonBuffer();
if (!_next) return NULL;
}
return _next->alloc(bytes);
}
DynamicJsonBuffer* _next;
size_t _size;
uint8_t _buffer[BLOCK_CAPACITY];
};
} }

View File

@ -0,0 +1,93 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../JsonBuffer.hpp"
#include <stdlib.h>
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() : _head(NULL) {}
~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;
}
protected:
virtual void* alloc(size_t bytes) {
return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
}
private:
static const size_t FIRST_BLOCK_CAPACITY = 32;
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 = FIRST_BLOCK_CAPACITY;
if (_head != NULL) capacity = _head->capacity * 2;
if (bytes > capacity) capacity = bytes;
if (!addNewBlock(capacity)) return NULL;
return allocInHead(bytes);
}
bool addNewBlock(size_t capacity) {
size_t size = sizeof(EmptyBlock) + capacity;
Block* block = static_cast<Block*>(_allocator.allocate(size));
if (block == NULL) return false;
block->capacity = capacity;
block->size = 0;
block->next = _head;
_head = block;
return true;
}
Block* _head;
TAllocator _allocator;
};
}
}

View File

@ -0,0 +1,20 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../Arduino/Print.hpp"
namespace ArduinoJson {
namespace Internals {
// A dummy Print implementation used in JsonPrintable::measureLength()
class DummyPrint : public Print {
public:
virtual size_t write(uint8_t) { return 1; }
};
}
}

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -0,0 +1,23 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../JsonBuffer.hpp"
namespace ArduinoJson {
namespace Internals {
class JsonBufferAllocated {
public:
void *operator new(size_t n, JsonBuffer *jsonBuffer) throw() {
return jsonBuffer->alloc(n);
}
void operator delete(void *, JsonBuffer *) throw() {}
};
}
}

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -6,6 +6,7 @@
#pragma once #pragma once
#include "DummyPrint.hpp"
#include "IndentedPrint.hpp" #include "IndentedPrint.hpp"
#include "JsonWriter.hpp" #include "JsonWriter.hpp"
#include "Prettyfier.hpp" #include "Prettyfier.hpp"
@ -47,6 +48,16 @@ class JsonPrintable {
return prettyPrintTo(indentedPrint); return prettyPrintTo(indentedPrint);
} }
size_t measureLength() const {
DummyPrint dp;
return printTo(dp);
}
size_t measurePrettyLength() const {
DummyPrint dp;
return prettyPrintTo(dp);
}
private: private:
const T &downcast() const { return *static_cast<const T *>(this); } const T &downcast() const { return *static_cast<const T *>(this); }
}; };

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -9,7 +9,6 @@
#include "../JsonBuffer.hpp" #include "../JsonBuffer.hpp"
#include "ListConstIterator.hpp" #include "ListConstIterator.hpp"
#include "ListIterator.hpp" #include "ListIterator.hpp"
#include "PlacementNew.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
@ -51,8 +50,7 @@ class List {
protected: protected:
node_type *createNode() { node_type *createNode() {
if (!_buffer) return NULL; if (!_buffer) return NULL;
void *ptr = _buffer->alloc(sizeof(node_type)); return new (_buffer) node_type();
return ptr ? new (ptr) node_type() : NULL;
} }
void addNode(node_type *nodeToAdd) { void addNode(node_type *nodeToAdd) {

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -8,16 +8,18 @@
#include <stddef.h> // for NULL #include <stddef.h> // for NULL
#include "JsonBufferAllocated.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
// A node for a singly-linked list. // A node for a singly-linked list.
// Used by List<T> and its iterators. // Used by List<T> and its iterators.
template <typename T> template <typename T>
struct ListNode { struct ListNode : public Internals::JsonBufferAllocated {
ListNode() : next(NULL) {} ListNode() : next(NULL) {}
ListNode<T>* next; ListNode<T> *next;
T content; T content;
}; };
} }

View File

@ -1,19 +0,0 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#ifdef ARDUINO
// Declares the placement new as in <new>.
// This is required for Arduino IDE because it doesn't include the <new> header.
inline void *operator new(size_t, void *p) throw() { return p; }
#else
#include <new>
#endif

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -6,6 +6,7 @@
#pragma once #pragma once
#include "Internals/JsonBufferAllocated.hpp"
#include "Internals/JsonPrintable.hpp" #include "Internals/JsonPrintable.hpp"
#include "Internals/List.hpp" #include "Internals/List.hpp"
#include "Internals/ReferenceType.hpp" #include "Internals/ReferenceType.hpp"
@ -30,7 +31,8 @@ class JsonBuffer;
// It can also be deserialized from a JSON string via JsonBuffer::parseArray(). // It can also be deserialized from a JSON string via JsonBuffer::parseArray().
class JsonArray : public Internals::JsonPrintable<JsonArray>, class JsonArray : public Internals::JsonPrintable<JsonArray>,
public Internals::ReferenceType, public Internals::ReferenceType,
public Internals::List<JsonVariant> { public Internals::List<JsonVariant>,
public Internals::JsonBufferAllocated {
// JsonBuffer is a friend because it needs to call the private constructor. // JsonBuffer is a friend because it needs to call the private constructor.
friend class JsonBuffer; friend class JsonBuffer;
@ -69,6 +71,9 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
// It's a shortcut for JsonBuffer::createObject() and JsonArray::add() // It's a shortcut for JsonBuffer::createObject() and JsonArray::add()
JsonObject &createNestedObject(); JsonObject &createNestedObject();
// Removes element at specified index.
void removeAt(int index);
// Returns a reference an invalid JsonArray. // Returns a reference an invalid JsonArray.
// This object is meant to replace a NULL pointer. // This object is meant to replace a NULL pointer.
// This is used when memory allocation or JSON parsing fail. // This is used when memory allocation or JSON parsing fail.
@ -82,6 +87,8 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
explicit JsonArray(JsonBuffer *buffer) explicit JsonArray(JsonBuffer *buffer)
: Internals::List<JsonVariant>(buffer) {} : Internals::List<JsonVariant>(buffer) {}
node_type *getNodeAt(int index) const;
// The instance returned by JsonArray::invalid() // The instance returned by JsonArray::invalid()
static JsonArray _invalid; static JsonArray _invalid;
}; };

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -9,6 +9,12 @@
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
#include <stdint.h> // for uint8_t #include <stdint.h> // for uint8_t
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
namespace ArduinoJson { namespace ArduinoJson {
class JsonArray; class JsonArray;
class JsonObject; class JsonObject;

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -6,6 +6,7 @@
#pragma once #pragma once
#include "Internals/JsonBufferAllocated.hpp"
#include "Internals/JsonPrintable.hpp" #include "Internals/JsonPrintable.hpp"
#include "Internals/List.hpp" #include "Internals/List.hpp"
#include "Internals/ReferenceType.hpp" #include "Internals/ReferenceType.hpp"
@ -30,7 +31,8 @@ class JsonBuffer;
// It can also be deserialized from a JSON string via JsonBuffer::parseObject(). // It can also be deserialized from a JSON string via JsonBuffer::parseObject().
class JsonObject : public Internals::JsonPrintable<JsonObject>, class JsonObject : public Internals::JsonPrintable<JsonObject>,
public Internals::ReferenceType, public Internals::ReferenceType,
public Internals::List<JsonPair> { public Internals::List<JsonPair>,
public Internals::JsonBufferAllocated {
// JsonBuffer is a friend because it needs to call the private constructor. // JsonBuffer is a friend because it needs to call the private constructor.
friend class JsonBuffer; friend class JsonBuffer;

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,8 +0,0 @@
name=ArduinoJson
version=4.0
author=Benoit Blanchon <http://blog.benoitblanchon.fr/>
maintainer=Benoit Blanchon <http://blog.benoitblanchon.fr/>
sentence=An efficient and elegant JSON library for Arduino
paragraph=Supports JSON parsing and formatting. Uses fixed memory allocation.
url=https://github.com/bblanchon/ArduinoJson
architectures=*

View File

@ -1,21 +1,22 @@
#!/bin/bash #!/bin/bash
ZIP="C:\Program Files\7-Zip\7z.exe" TAG=$(git describe)
TAG=$(git describe) OUTPUT="ArduinoJson-$TAG.zip"
OUTPUT="ArduinoJson-$TAG.zip"
cd ../..
cd ../..
# remove existing file
# remove existing file rm -f $OUTPUT
rm -f $OUTPUT
# create zip
# create zip 7z a $OUTPUT \
"$ZIP" a $OUTPUT \ ArduinoJson/CHANGELOG.md \
ArduinoJson/CHANGELOG.md \ ArduinoJson/examples \
ArduinoJson/examples \ ArduinoJson/include \
ArduinoJson/include \ ArduinoJson/keywords.txt \
ArduinoJson/keywords.txt \ ArduinoJson/LICENSE.md \
ArduinoJson/library.properties \ ArduinoJson/README.md \
ArduinoJson/LICENSE.md \ ArduinoJson/src \
ArduinoJson/README.md \ ArduinoJson/ArduinoJson.h \
ArduinoJson/src ArduinoJson/ArduinoJson.cpp \
-x!ArduinoJson/src/CMakeLists.txt

View File

@ -20,10 +20,10 @@ build-env()
if [[ $(uname) == MINGW* ]] if [[ $(uname) == MINGW* ]]
then then
build-env "Make" "MinGW Makefiles" build-env "Make" "MinGW Makefiles"
build-env "SublimeText" "Sublime Text 2 - MinGW Makefiles" build-env "SublimeText" "Sublime Text 2 - Ninja"
build-env "VisualStudio" "Visual Studio 12 2013" build-env "VisualStudio" "Visual Studio 12 2013"
else else
build-env "SublimeText" "Sublime Text 2 - Unix Makefiles" build-env "SublimeText" "Sublime Text 2 - Ninja"
build-env "Make" "Unix Makefiles" build-env "Make" "Unix Makefiles"
build-env "Xcode" "Xcode" build-env "Xcode" "Xcode"
fi fi

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -8,7 +8,8 @@
#include "../../include/ArduinoJson/Arduino/Print.hpp" #include "../../include/ArduinoJson/Arduino/Print.hpp"
#include <stdio.h> // for sprintf #include <math.h> // for isnan() and isinf()
#include <stdio.h> // for sprintf()
size_t Print::print(const char s[]) { size_t Print::print(const char s[]) {
size_t n = 0; size_t n = 0;
@ -19,8 +20,24 @@ size_t Print::print(const char s[]) {
} }
size_t Print::print(double value, int digits) { size_t Print::print(double value, int digits) {
// https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware/arduino/sam/cores/arduino/Print.cpp#L218
if (isnan(value)) return print("nan");
if (isinf(value)) return print("inf");
char tmp[32]; char tmp[32];
sprintf(tmp, "%.*f", digits, value);
// https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware/arduino/sam/cores/arduino/Print.cpp#L220
bool isBigDouble = value > 4294967040.0 || value < -4294967040.0;
if (isBigDouble) {
// Arduino's implementation prints "ovf"
// We prefer trying to use scientific notation, since we have sprintf
sprintf(tmp, "%g", value);
} else {
// Here we have the exact same output as Arduino's implementation
sprintf(tmp, "%.*f", digits, value);
}
return print(tmp); return print(tmp);
} }

View File

@ -1,13 +0,0 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// About this file
// ---------------
// This file is here to please the Arduino IDE. It must be present in the src/
// for the IDE to find it. Feel free to ignore this file if your working in
// another environment
#include "../include/ArduinoJson.h"

View File

@ -20,6 +20,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
-Wno-sign-conversion -Wno-sign-conversion
-Wno-unused -Wno-unused
-Wno-variadic-macros -Wno-variadic-macros
-Wnon-virtual-dtor
-Wold-style-cast -Wold-style-cast
-Woverloaded-virtual -Woverloaded-virtual
-Wredundant-decls -Wredundant-decls

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -6,7 +6,6 @@
#include "../../include/ArduinoJson/Internals/List.hpp" #include "../../include/ArduinoJson/Internals/List.hpp"
#include "../../include/ArduinoJson/Internals/PlacementNew.hpp"
#include "../../include/ArduinoJson/JsonPair.hpp" #include "../../include/ArduinoJson/JsonPair.hpp"
#include "../../include/ArduinoJson/JsonVariant.hpp" #include "../../include/ArduinoJson/JsonVariant.hpp"

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -8,16 +8,21 @@
using namespace ArduinoJson::Internals; using namespace ArduinoJson::Internals;
// How to escape special chars:
// specialChars[2*i+1] => the special char
// specialChars[2*i] => the char to use instead
static const char specialChars[] = "\"\"\\\\b\bf\fn\nr\rt\t";
static inline char getSpecialChar(char c) { static inline char getSpecialChar(char c) {
// Optimized for code size on a 8-bit AVR // Optimized for code size on a 8-bit AVR
const char *p = "\"\"\\\\\bb\ff\nn\rr\tt\0"; const char *p = specialChars;
while (p[0] && p[0] != c) { while (p[0] && p[1] != c) {
p += 2; p += 2;
} }
return p[1]; return p[0];
} }
static inline size_t printCharTo(char c, Print &p) { static inline size_t printCharTo(char c, Print &p) {
@ -41,7 +46,7 @@ size_t QuotedString::printTo(const char *s, Print &p) {
static char unescapeChar(char c) { static char unescapeChar(char c) {
// Optimized for code size on a 8-bit AVR // Optimized for code size on a 8-bit AVR
const char *p = "b\bf\fn\nr\rt\t"; const char *p = specialChars + 4;
for (;;) { for (;;) {
if (p[0] == '\0') return c; if (p[0] == '\0') return c;
@ -53,46 +58,44 @@ static char unescapeChar(char c) {
static inline bool isQuote(char c) { return c == '\"' || c == '\''; } static inline bool isQuote(char c) { return c == '\"' || c == '\''; }
char *QuotedString::extractFrom(char *input, char **endPtr) { char *QuotedString::extractFrom(char *input, char **endPtr) {
char firstChar = *input;
if (!isQuote(firstChar)) {
// must start with a quote
return NULL;
}
char stopChar = firstChar; // closing quote is the same as opening quote
char *startPtr = input + 1; // skip the quote char *startPtr = input + 1; // skip the quote
char *readPtr = startPtr; char *readPtr = startPtr;
char *writePtr = startPtr; char *writePtr = startPtr;
char c; char c;
char firstChar = *input;
char stopChar = firstChar; // closing quote is the same as opening quote
if (!isQuote(firstChar)) goto ERROR_OPENING_QUOTE_MISSING;
for (;;) { for (;;) {
c = *readPtr++; c = *readPtr++;
if (c == '\0') { if (c == '\0') goto ERROR_CLOSING_QUOTE_MISSING;
// premature ending
return NULL;
}
if (c == stopChar) { if (c == stopChar) goto SUCCESS;
// closing quote
break;
}
if (c == '\\') { if (c == '\\') {
// replace char // replace char
c = unescapeChar(*readPtr++); c = unescapeChar(*readPtr++);
if (c == '\0') goto ERROR_ESCAPE_SEQUENCE_INTERRUPTED;
} }
*writePtr++ = c; *writePtr++ = c;
} }
SUCCESS:
// end the string here // end the string here
*writePtr = '\0'; *writePtr = '\0';
// update end ptr // update end ptr
*endPtr = readPtr; *endPtr = readPtr;
// return pointer to unquoted string
return startPtr; return startPtr;
ERROR_OPENING_QUOTE_MISSING:
ERROR_CLOSING_QUOTE_MISSING:
ERROR_ESCAPE_SEQUENCE_INTERRUPTED:
return NULL;
} }

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -15,8 +15,7 @@ using namespace ArduinoJson::Internals;
JsonArray JsonArray::_invalid(NULL); JsonArray JsonArray::_invalid(NULL);
JsonVariant &JsonArray::at(int index) const { JsonVariant &JsonArray::at(int index) const {
node_type *node = _firstNode; node_type *node = getNodeAt(index);
while (node && index--) node = node->next;
return node ? node->content : JsonVariant::invalid(); return node ? node->content : JsonVariant::invalid();
} }
@ -43,6 +42,14 @@ JsonObject &JsonArray::createNestedObject() {
return object; return object;
} }
JsonArray::node_type *JsonArray::getNodeAt(int index) const {
node_type *node = _firstNode;
while (node && index--) node = node->next;
return node;
}
void JsonArray::removeAt(int index) { removeNode(getNodeAt(index)); }
void JsonArray::writeTo(JsonWriter &writer) const { void JsonArray::writeTo(JsonWriter &writer) const {
writer.beginArray(); writer.beginArray();

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -7,7 +7,6 @@
#include "../include/ArduinoJson/JsonBuffer.hpp" #include "../include/ArduinoJson/JsonBuffer.hpp"
#include "../include/ArduinoJson/Internals/JsonParser.hpp" #include "../include/ArduinoJson/Internals/JsonParser.hpp"
#include "../include/ArduinoJson/Internals/PlacementNew.hpp"
#include "../include/ArduinoJson/JsonArray.hpp" #include "../include/ArduinoJson/JsonArray.hpp"
#include "../include/ArduinoJson/JsonObject.hpp" #include "../include/ArduinoJson/JsonObject.hpp"
@ -15,15 +14,13 @@ using namespace ArduinoJson;
using namespace ArduinoJson::Internals; using namespace ArduinoJson::Internals;
JsonArray &JsonBuffer::createArray() { JsonArray &JsonBuffer::createArray() {
void *ptr = alloc(sizeof(JsonArray)); JsonArray *ptr = new (this) JsonArray(this);
if (ptr) return *new (ptr) JsonArray(this); return ptr ? *ptr : JsonArray::invalid();
return JsonArray::invalid();
} }
JsonObject &JsonBuffer::createObject() { JsonObject &JsonBuffer::createObject() {
void *ptr = alloc(sizeof(JsonObject)); JsonObject *ptr = new (this) JsonObject(this);
if (ptr) return *new (ptr) JsonObject(this); return ptr ? *ptr : JsonObject::invalid();
return JsonObject::invalid();
} }
JsonArray &JsonBuffer::parseArray(char *json, uint8_t nestingLimit) { JsonArray &JsonBuffer::parseArray(char *json, uint8_t nestingLimit) {

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -8,7 +8,6 @@
#include <string.h> // for strcmp #include <string.h> // for strcmp
#include "../include/ArduinoJson/Internals/PlacementNew.hpp"
#include "../include/ArduinoJson/Internals/StringBuilder.hpp" #include "../include/ArduinoJson/Internals/StringBuilder.hpp"
#include "../include/ArduinoJson/JsonArray.hpp" #include "../include/ArduinoJson/JsonArray.hpp"
#include "../include/ArduinoJson/JsonBuffer.hpp" #include "../include/ArduinoJson/JsonBuffer.hpp"

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -64,13 +64,13 @@ void JsonVariant::set(long value) {
void JsonVariant::set(JsonArray &array) { void JsonVariant::set(JsonArray &array) {
if (_type == JSON_INVALID) return; if (_type == JSON_INVALID) return;
_type = JSON_ARRAY; _type = array.success() ? JSON_ARRAY : JSON_INVALID;
_content.asArray = &array; _content.asArray = &array;
} }
void JsonVariant::set(JsonObject &object) { void JsonVariant::set(JsonObject &object) {
if (_type == JSON_INVALID) return; if (_type == JSON_INVALID) return;
_type = JSON_OBJECT; _type = object.success() ? JSON_OBJECT : JSON_INVALID;
_content.asObject = &object; _content.asObject = &object;
} }

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -20,40 +20,11 @@ TEST_F(DynamicJsonBuffer_Basic_Tests, InitialSizeIsZero) {
ASSERT_EQ(0, buffer.size()); ASSERT_EQ(0, buffer.size());
} }
TEST_F(DynamicJsonBuffer_Basic_Tests, InitialBlockCountIsOne) {
ASSERT_EQ(1, buffer.blockCount());
}
TEST_F(DynamicJsonBuffer_Basic_Tests, SizeIncreasesAfterAlloc) { TEST_F(DynamicJsonBuffer_Basic_Tests, SizeIncreasesAfterAlloc) {
buffer.alloc(1); buffer.alloc(1);
ASSERT_EQ(1, buffer.size()); ASSERT_EQ(1, buffer.size());
buffer.alloc(1); buffer.alloc(1);
ASSERT_EQ(2, buffer.size()); ASSERT_EQ(2, buffer.size());
buffer.alloc(DynamicJsonBuffer::BLOCK_CAPACITY);
ASSERT_EQ(2 + DynamicJsonBuffer::BLOCK_CAPACITY, buffer.size());
}
TEST_F(DynamicJsonBuffer_Basic_Tests, BlockCountDoesntChangeWhenNotFull) {
buffer.alloc(DynamicJsonBuffer::BLOCK_CAPACITY);
ASSERT_EQ(1, buffer.blockCount());
}
TEST_F(DynamicJsonBuffer_Basic_Tests, BlockCountChangesWhenFull) {
buffer.alloc(DynamicJsonBuffer::BLOCK_CAPACITY);
buffer.alloc(1);
ASSERT_EQ(2, buffer.blockCount());
}
TEST_F(DynamicJsonBuffer_Basic_Tests, CanAllocLessThanBlockCapacity) {
void* p1 = buffer.alloc(DynamicJsonBuffer::BLOCK_CAPACITY);
ASSERT_TRUE(p1);
void* p2 = buffer.alloc(DynamicJsonBuffer::BLOCK_CAPACITY);
ASSERT_TRUE(p2);
}
TEST_F(DynamicJsonBuffer_Basic_Tests, CantAllocMoreThanBlockCapacity) {
void* p = buffer.alloc(DynamicJsonBuffer::BLOCK_CAPACITY + 1);
ASSERT_FALSE(p);
} }
TEST_F(DynamicJsonBuffer_Basic_Tests, ReturnDifferentPointer) { TEST_F(DynamicJsonBuffer_Basic_Tests, ReturnDifferentPointer) {

View File

@ -0,0 +1,37 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include <gtest/gtest.h>
#include <ArduinoJson.h>
class DynamicJsonBuffer_NoMemory_Tests : public ::testing::Test {
class NoMemoryAllocator {
public:
void* allocate(size_t) { return NULL; }
void deallocate(void*) {}
};
protected:
Internals::BlockJsonBuffer<NoMemoryAllocator> _jsonBuffer;
};
TEST_F(DynamicJsonBuffer_NoMemory_Tests, CreateArray) {
ASSERT_FALSE(_jsonBuffer.createArray().success());
}
TEST_F(DynamicJsonBuffer_NoMemory_Tests, CreateObject) {
ASSERT_FALSE(_jsonBuffer.createObject().success());
}
TEST_F(DynamicJsonBuffer_NoMemory_Tests, ParseArray) {
char json[] = "[]";
ASSERT_FALSE(_jsonBuffer.parseArray(json).success());
}
TEST_F(DynamicJsonBuffer_NoMemory_Tests, ParseObject) {
char json[] = "{}";
ASSERT_FALSE(_jsonBuffer.parseObject(json).success());
}

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

47
test/Issue67.cpp Normal file
View File

@ -0,0 +1,47 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include <gtest/gtest.h>
#include <ArduinoJson.h>
class Issue67 : public testing::Test {
public:
void whenInputIs(double value) { _variant = value; }
void outputMustBe(const char* expected) {
char buffer[1024];
_variant.printTo(buffer, sizeof(buffer));
ASSERT_STREQ(expected, buffer);
}
private:
JsonVariant _variant;
};
TEST_F(Issue67, BigPositiveDouble) {
whenInputIs(1e100);
outputMustBe("1e+100");
}
TEST_F(Issue67, BigNegativeDouble) {
whenInputIs(-1e100);
outputMustBe("-1e+100");
}
TEST_F(Issue67, Zero) {
whenInputIs(0.0);
outputMustBe("0.00");
}
TEST_F(Issue67, SmallPositiveDouble) {
whenInputIs(111.111);
outputMustBe("111.11");
}
TEST_F(Issue67, SmallNegativeDouble) {
whenInputIs(-111.111);
outputMustBe("-111.11");
}

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -48,6 +48,11 @@ class JsonArray_Container_Tests : public ::testing::Test {
} }
}; };
template <>
void JsonArray_Container_Tests::itemMustEqual(int index, const char* expected) {
EXPECT_STREQ(expected, _array[index].asString());
}
TEST_F(JsonArray_Container_Tests, SuccessIsTrue) { TEST_F(JsonArray_Container_Tests, SuccessIsTrue) {
EXPECT_TRUE(_array.success()); EXPECT_TRUE(_array.success());
} }
@ -87,14 +92,11 @@ TEST_F(JsonArray_Container_Tests, CanStoreBooleans) {
} }
TEST_F(JsonArray_Container_Tests, CanStoreStrings) { TEST_F(JsonArray_Container_Tests, CanStoreStrings) {
const char* firstString = "h3110"; _array.add("hello");
const char* secondString = "w0r1d"; _array.add("world");
_array.add(firstString); firstMustEqual("hello");
_array.add(secondString); secondMustEqual("world");
firstMustEqual(firstString);
secondMustEqual(secondString);
} }
TEST_F(JsonArray_Container_Tests, CanStoreNestedArrays) { TEST_F(JsonArray_Container_Tests, CanStoreNestedArrays) {
@ -134,3 +136,39 @@ TEST_F(JsonArray_Container_Tests, CanCreateNestedObjects) {
firstMustReference(innerObject1); firstMustReference(innerObject1);
secondMustReference(innerObject2); secondMustReference(innerObject2);
} }
TEST_F(JsonArray_Container_Tests, RemoveFirstElement) {
_array.add("one");
_array.add("two");
_array.add("three");
_array.removeAt(0);
sizeMustBe(2);
firstMustEqual("two");
secondMustEqual("three");
}
TEST_F(JsonArray_Container_Tests, RemoveMiddleElement) {
_array.add("one");
_array.add("two");
_array.add("three");
_array.removeAt(1);
sizeMustBe(2);
firstMustEqual("one");
secondMustEqual("three");
}
TEST_F(JsonArray_Container_Tests, RemoveLastElement) {
_array.add("one");
_array.add("two");
_array.add("three");
_array.removeAt(2);
sizeMustBe(2);
firstMustEqual("one");
secondMustEqual("two");
}

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -16,13 +16,15 @@ class JsonArray_PrettyPrintTo_Tests : public testing::Test {
JsonArray& array; JsonArray& array;
void outputMustBe(const char* expected) { void outputMustBe(const char* expected) {
size_t n = array.prettyPrintTo(_buffer, sizeof(_buffer)); char actual[256];
EXPECT_STREQ(expected, _buffer);
EXPECT_EQ(strlen(expected), n);
}
private: size_t actualLen = array.prettyPrintTo(actual, sizeof(actual));
char _buffer[256]; size_t measuredLen = array.measurePrettyLength();
EXPECT_STREQ(expected, actual);
EXPECT_EQ(strlen(expected), actualLen);
EXPECT_EQ(strlen(expected), measuredLen);
}
}; };
TEST_F(JsonArray_PrettyPrintTo_Tests, Empty) { outputMustBe("[]"); } TEST_F(JsonArray_PrettyPrintTo_Tests, Empty) { outputMustBe("[]"); }

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -16,9 +16,12 @@ class JsonArray_PrintTo_Tests : public testing::Test {
JsonArray &array; JsonArray &array;
void outputMustBe(const char *expected) { void outputMustBe(const char *expected) {
size_t n = array.printTo(buffer, sizeof(buffer)); size_t actualLen = array.printTo(buffer, sizeof(buffer));
size_t measuredLen = array.measureLength();
EXPECT_STREQ(expected, buffer); EXPECT_STREQ(expected, buffer);
EXPECT_EQ(strlen(expected), n); EXPECT_EQ(strlen(expected), actualLen);
EXPECT_EQ(strlen(expected), measuredLen);
} }
private: private:

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -16,13 +16,15 @@ class JsonObject_PrettyPrintTo_Tests : public testing::Test {
JsonObject &_object; JsonObject &_object;
void outputMustBe(const char *expected) { void outputMustBe(const char *expected) {
size_t n = _object.prettyPrintTo(buffer, sizeof(buffer)); char buffer[256];
EXPECT_STREQ(expected, buffer);
EXPECT_EQ(strlen(expected), n);
}
private: size_t actualLen = _object.prettyPrintTo(buffer, sizeof(buffer));
char buffer[256]; size_t measuredLen = _object.measurePrettyLength();
EXPECT_STREQ(expected, buffer);
EXPECT_EQ(strlen(expected), actualLen);
EXPECT_EQ(strlen(expected), measuredLen);
}
}; };
TEST_F(JsonObject_PrettyPrintTo_Tests, EmptyObject) { outputMustBe("{}"); } TEST_F(JsonObject_PrettyPrintTo_Tests, EmptyObject) { outputMustBe("{}"); }

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -16,10 +16,12 @@ class JsonObject_PrintTo_Tests : public testing::Test {
protected: protected:
void outputMustBe(const char *expected) { void outputMustBe(const char *expected) {
char actual[256]; char actual[256];
int result = object.printTo(actual, sizeof(actual)); size_t actualLen = object.printTo(actual, sizeof(actual));
size_t measuredLen = object.measureLength();
EXPECT_STREQ(expected, actual); EXPECT_STREQ(expected, actual);
EXPECT_EQ(strlen(expected), result); EXPECT_EQ(strlen(expected), actualLen);
EXPECT_EQ(strlen(expected), measuredLen);
} }
StaticJsonBuffer<JSON_OBJECT_SIZE(2)> json; StaticJsonBuffer<JSON_OBJECT_SIZE(2)> json;

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -62,11 +62,13 @@ TEST_F(JsonVariant_Undefined_Tests, CanBeSetToBool) {
} }
TEST_F(JsonVariant_Undefined_Tests, CanBeSetToArray) { TEST_F(JsonVariant_Undefined_Tests, CanBeSetToArray) {
variant = JsonArray::invalid(); DynamicJsonBuffer jsonBuffer;
variant = jsonBuffer.createArray();
EXPECT_TRUE(variant.success()); EXPECT_TRUE(variant.success());
} }
TEST_F(JsonVariant_Undefined_Tests, CanBeSetToObject) { TEST_F(JsonVariant_Undefined_Tests, CanBeSetToObject) {
variant = JsonObject::invalid(); DynamicJsonBuffer jsonBuffer;
variant = jsonBuffer.createObject();
EXPECT_TRUE(variant.success()); EXPECT_TRUE(variant.success());
} }

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -16,6 +16,11 @@ class QuotedString_ExtractFrom_Tests : public testing::Test {
_result = QuotedString::extractFrom(_jsonString, &_trailing); _result = QuotedString::extractFrom(_jsonString, &_trailing);
} }
void whenInputIs(const char *json, size_t len) {
memcpy(_jsonString, json, len);
_result = QuotedString::extractFrom(_jsonString, &_trailing);
}
void resultMustBe(const char *expected) { EXPECT_STREQ(expected, _result); } void resultMustBe(const char *expected) { EXPECT_STREQ(expected, _result); }
void trailingMustBe(const char *expected) { void trailingMustBe(const char *expected) {
@ -134,3 +139,8 @@ TEST_F(QuotedString_ExtractFrom_Tests, AllEscapedCharsTogether) {
whenInputIs("\"1\\\"2\\\\3\\/4\\b5\\f6\\n7\\r8\\t9\""); whenInputIs("\"1\\\"2\\\\3\\/4\\b5\\f6\\n7\\r8\\t9\"");
resultMustBe("1\"2\\3/4\b5\f6\n7\r8\t9"); resultMustBe("1\"2\\3/4\b5\f6\n7\r8\t9");
} }
TEST_F(QuotedString_ExtractFrom_Tests, UnterminatedEscapeSequence) {
whenInputIs("\"\\\0\"", 4);
resultMustBe(0);
}

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -7,7 +7,7 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
TEST(StaticJsonBuffer_Array_Tests, GrowsWithArray) { TEST(StaticJsonBuffer_CreateArray_Tests, GrowsWithArray) {
StaticJsonBuffer<JSON_ARRAY_SIZE(2)> json; StaticJsonBuffer<JSON_ARRAY_SIZE(2)> json;
JsonArray &array = json.createArray(); JsonArray &array = json.createArray();
@ -20,21 +20,21 @@ TEST(StaticJsonBuffer_Array_Tests, GrowsWithArray) {
ASSERT_EQ(JSON_ARRAY_SIZE(2), json.size()); ASSERT_EQ(JSON_ARRAY_SIZE(2), json.size());
} }
TEST(StaticJsonBuffer_Array_Tests, SucceedWhenBigEnough) { TEST(StaticJsonBuffer_CreateArray_Tests, SucceedWhenBigEnough) {
StaticJsonBuffer<JSON_ARRAY_SIZE(0)> json; StaticJsonBuffer<JSON_ARRAY_SIZE(0)> json;
JsonArray &array = json.createArray(); JsonArray &array = json.createArray();
ASSERT_TRUE(array.success()); ASSERT_TRUE(array.success());
} }
TEST(StaticJsonBuffer_Array_Tests, FailsWhenTooSmall) { TEST(StaticJsonBuffer_CreateArray_Tests, FailsWhenTooSmall) {
StaticJsonBuffer<JSON_ARRAY_SIZE(0) - 1> json; StaticJsonBuffer<JSON_ARRAY_SIZE(0) - 1> json;
JsonArray &array = json.createArray(); JsonArray &array = json.createArray();
ASSERT_FALSE(array.success()); ASSERT_FALSE(array.success());
} }
TEST(StaticJsonBuffer_Array_Tests, ArrayDoesntGrowWhenFull) { TEST(StaticJsonBuffer_CreateArray_Tests, ArrayDoesntGrowWhenFull) {
StaticJsonBuffer<JSON_ARRAY_SIZE(1)> json; StaticJsonBuffer<JSON_ARRAY_SIZE(1)> json;
JsonArray &array = json.createArray(); JsonArray &array = json.createArray();

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
@ -7,7 +7,7 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
TEST(StaticJsonBuffer_Object_Tests, GrowsWithObject) { TEST(StaticJsonBuffer_CreateObject_Tests, GrowsWithObject) {
StaticJsonBuffer<JSON_OBJECT_SIZE(3)> json; StaticJsonBuffer<JSON_OBJECT_SIZE(3)> json;
JsonObject &obj = json.createObject(); JsonObject &obj = json.createObject();
@ -23,21 +23,21 @@ TEST(StaticJsonBuffer_Object_Tests, GrowsWithObject) {
ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size()); ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size());
} }
TEST(StaticJsonBuffer_Object_Tests, SucceedWhenBigEnough) { TEST(StaticJsonBuffer_CreateObject_Tests, SucceedWhenBigEnough) {
StaticJsonBuffer<JSON_OBJECT_SIZE(0)> json; StaticJsonBuffer<JSON_OBJECT_SIZE(0)> json;
JsonObject &object = json.createObject(); JsonObject &object = json.createObject();
ASSERT_TRUE(object.success()); ASSERT_TRUE(object.success());
} }
TEST(StaticJsonBuffer_Object_Tests, FailsWhenTooSmall) { TEST(StaticJsonBuffer_CreateObject_Tests, FailsWhenTooSmall) {
StaticJsonBuffer<JSON_OBJECT_SIZE(0) - 1> json; StaticJsonBuffer<JSON_OBJECT_SIZE(0) - 1> json;
JsonObject &object = json.createObject(); JsonObject &object = json.createObject();
ASSERT_FALSE(object.success()); ASSERT_FALSE(object.success());
} }
TEST(StaticJsonBuffer_Object_Tests, ObjectDoesntGrowWhenFull) { TEST(StaticJsonBuffer_CreateObject_Tests, ObjectDoesntGrowWhenFull) {
StaticJsonBuffer<JSON_OBJECT_SIZE(1)> json; StaticJsonBuffer<JSON_OBJECT_SIZE(1)> json;
JsonObject &obj = json.createObject(); JsonObject &obj = json.createObject();

View File

@ -0,0 +1,72 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include <gtest/gtest.h>
#include <ArduinoJson.h>
class StaticJsonBuffer_ParseArray_Tests : public testing::Test {
protected:
void with(JsonBuffer& jsonBuffer) { _jsonBuffer = &jsonBuffer; }
void whenInputIs(const char* json) { strcpy(_jsonString, json); }
void parseMustSucceed() {
EXPECT_TRUE(_jsonBuffer->parseArray(_jsonString).success());
}
void parseMustFail() {
EXPECT_FALSE(_jsonBuffer->parseArray(_jsonString).success());
}
private:
JsonBuffer* _jsonBuffer;
char _jsonString[256];
};
TEST_F(StaticJsonBuffer_ParseArray_Tests, TooSmallBufferForEmptyArray) {
StaticJsonBuffer<JSON_ARRAY_SIZE(0) - 1> bufferTooSmall;
with(bufferTooSmall);
whenInputIs("[]");
parseMustFail();
}
TEST_F(StaticJsonBuffer_ParseArray_Tests, BufferOfTheRightSizeForEmptyArray) {
StaticJsonBuffer<JSON_ARRAY_SIZE(0)> bufferOfRightSize;
with(bufferOfRightSize);
whenInputIs("[]");
parseMustSucceed();
}
TEST_F(StaticJsonBuffer_ParseArray_Tests, TooSmallBufferForArrayWithOneValue) {
StaticJsonBuffer<JSON_ARRAY_SIZE(1) - 1> bufferTooSmall;
with(bufferTooSmall);
whenInputIs("[1]");
parseMustFail();
}
TEST_F(StaticJsonBuffer_ParseArray_Tests,
BufferOfTheRightSizeForArrayWithOneValue) {
StaticJsonBuffer<JSON_ARRAY_SIZE(1)> bufferOfRightSize;
with(bufferOfRightSize);
whenInputIs("[1]");
parseMustSucceed();
}
TEST_F(StaticJsonBuffer_ParseArray_Tests,
TooSmallBufferForArrayWithNestedObject) {
StaticJsonBuffer<JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(0) - 1> bufferTooSmall;
with(bufferTooSmall);
whenInputIs("[{}]");
parseMustFail();
}
TEST_F(StaticJsonBuffer_ParseArray_Tests,
BufferOfTheRightSizeForArrayWithNestedObject) {
StaticJsonBuffer<JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(0)> bufferOfRightSize;
with(bufferOfRightSize);
whenInputIs("[{}]");
parseMustSucceed();
}

View File

@ -0,0 +1,73 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include <gtest/gtest.h>
#include <ArduinoJson.h>
class StaticJsonBuffer_ParseObject_Tests : public testing::Test {
protected:
void with(JsonBuffer& jsonBuffer) { _jsonBuffer = &jsonBuffer; }
void whenInputIs(const char* json) { strcpy(_jsonString, json); }
void parseMustSucceed() {
EXPECT_TRUE(_jsonBuffer->parseObject(_jsonString).success());
}
void parseMustFail() {
EXPECT_FALSE(_jsonBuffer->parseObject(_jsonString).success());
}
private:
JsonBuffer* _jsonBuffer;
char _jsonString[256];
};
TEST_F(StaticJsonBuffer_ParseObject_Tests, TooSmallBufferForEmptyObject) {
StaticJsonBuffer<JSON_OBJECT_SIZE(0) - 1> bufferTooSmall;
with(bufferTooSmall);
whenInputIs("{}");
parseMustFail();
}
TEST_F(StaticJsonBuffer_ParseObject_Tests, BufferOfTheRightSizeForEmptyObject) {
StaticJsonBuffer<JSON_OBJECT_SIZE(0)> bufferOfRightSize;
with(bufferOfRightSize);
whenInputIs("{}");
parseMustSucceed();
}
TEST_F(StaticJsonBuffer_ParseObject_Tests,
TooSmallBufferForObjectWithOneValue) {
StaticJsonBuffer<JSON_OBJECT_SIZE(1) - 1> bufferTooSmall;
with(bufferTooSmall);
whenInputIs("{\"a\":1}");
parseMustFail();
}
TEST_F(StaticJsonBuffer_ParseObject_Tests,
BufferOfTheRightSizeForObjectWithOneValue) {
StaticJsonBuffer<JSON_OBJECT_SIZE(1)> bufferOfRightSize;
with(bufferOfRightSize);
whenInputIs("{\"a\":1}");
parseMustSucceed();
}
TEST_F(StaticJsonBuffer_ParseObject_Tests,
TooSmallBufferForObjectWithNestedObject) {
StaticJsonBuffer<JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(0) - 1> bufferTooSmall;
with(bufferTooSmall);
whenInputIs("{\"a\":[]}");
parseMustFail();
}
TEST_F(StaticJsonBuffer_ParseObject_Tests,
BufferOfTheRightSizeForObjectWithNestedObject) {
StaticJsonBuffer<JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(0)> bufferOfRightSize;
with(bufferOfRightSize);
whenInputIs("{\"a\":[]}");
parseMustSucceed();
}

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014 // Copyright Benoit Blanchon 2014-2015
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library