Compare commits

...

44 Commits
v4.0 ... v4.3

Author SHA1 Message Date
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
1b214a60fa Fixed a typo 2014-12-21 15:25:42 +01:00
8560583ee7 Fixed GCC warning 2014-12-21 10:52:30 +01:00
2932c4ee43 Removed std::nothrow because it's not supported in Arduino 2014-12-21 10:46:32 +01:00
e8c127a894 Fixed memory leak in test fixture 2014-12-20 19:19:48 +01:00
d7ac7ff9a3 Added DynamicJsonBuffer 2014-12-20 15:45:09 +01:00
aef7e43c48 Use DynamicJsonBuffer instead of arbitrary sized StaticJsonBuffer 2014-12-20 15:42:43 +01:00
d855b0f98c Test object allocation with DynamicJsonBuffer 2014-12-20 15:16:06 +01:00
c726506b47 Added std::nothrow 2014-12-20 15:15:41 +01:00
c32e306be9 Test DynamicJsonBuffer behavior with arrays 2014-12-14 17:57:44 +01:00
13e907c894 Test that DynamicJsonBuffer.size() is the sum of all blocks 2014-12-13 21:02:42 +01:00
d19a34152f Test that DynamicJsonBuffer.blockCount() increases as expected 2014-12-13 20:52:59 +01:00
19cce08b2b Test initial value of DynamicJsonBuffer.blockCount() 2014-12-13 20:22:52 +01:00
3cd6f66067 Test that DynamicJsonBuffer can't alloc more than BLOCK_CAPACITY 2014-12-13 10:13:24 +01:00
ada588c112 Test that DynamicJsonBuffer returns a different pointer after each alloc() 2014-12-13 10:03:01 +01:00
0d57fe5a7e Test that DynamicJsonBuffer grows after each alloc 2014-12-13 09:54:04 +01:00
5a74beb7e2 Test initial size() of DynamicJsonBuffer 2014-12-11 21:05:45 +01:00
e2d591b9ff Fixed build in travis 2014-12-09 22:53:05 +01:00
8082185ac4 Fixed template instantiation warning (issue #35) 2014-12-09 20:46:45 +01:00
85ebc8a1ec Fixed shadowing warning (issue #36) 2014-12-09 20:23:49 +01:00
9ca32e664e Added unit tests for issue #34 2014-12-08 20:22:01 +01:00
566b76121a Fix test of ListConstIterator 2014-12-05 22:28:37 +01:00
562080f22d Added conversion from ListIterator to ListConstIterator 2014-12-05 22:28:16 +01:00
bb8bddc758 Test const itertor 2014-12-05 22:11:45 +01:00
9eb8842dda Test operator*() 2014-12-05 21:54:49 +01:00
97558abc29 Test with a missing closing quote 2014-12-05 21:46:51 +01:00
160ce092ff Added code coverage badge 2014-11-30 15:11:19 +01:00
d6974127b4 Moved documentation to the wiki 2014-11-29 17:00:38 +01:00
092660db52 Moved documentation to the wiki 2014-11-29 16:59:22 +01:00
96 changed files with 1138 additions and 1010 deletions

View File

@ -2,5 +2,11 @@ language: c++
compiler:
- gcc
- clang
before_script: cmake .
script: make && make test
before_install:
- sudo pip install cpp-coveralls
before_script:
- cmake -DCOVERAGE=true .
script:
- make && make test
after_success:
- 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,20 +1,39 @@
Arduino JSON: change log
========================
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
----
* Added DynamicJsonBuffer (issue #19)
v4.0
----
* Unified parser and generator API (issue #23)
* Updated library layout, now requires Arduino 1.0.6 or newer
**BREAKING CHANGE**: API changed significantly, see `doc/Migrating to the new API.md`.
**BREAKING CHANGE**: API changed significantly, see [Migrating code to the new API](https://github.com/bblanchon/ArduinoJson/wiki/Migrating-code-to-the-new-API).
v3.4
----
* Fixed escaped char parsing (issue #16)
v3.3
----

View File

@ -11,5 +11,10 @@ if(MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS -W4)
endif()
if(${COVERAGE})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -coverage")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -coverage")
endif()
add_subdirectory(src)
add_subdirectory(test)

View File

@ -1,7 +1,7 @@
Arduino JSON library
====================
[![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=master)](https://travis-ci.org/bblanchon/ArduinoJson)
[![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=master)](https://travis-ci.org/bblanchon/ArduinoJson) [![Coverage Status](https://img.shields.io/coveralls/bblanchon/ArduinoJson.svg)](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master)
*An elegant and efficient JSON library for embedded systems.*
@ -35,8 +35,6 @@ Quick start
double latitude = root["data"][0];
double longitude = root["data"][1];
[See complete guide](/doc/Decoding JSON.md)
#### Encoding / Generating
StaticJsonBuffer<200> jsonBuffer;
@ -53,7 +51,11 @@ Quick start
// This prints:
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
[See complete guide](/doc/Encoding JSON.md)
Documentation
-------------
The documentation is available online in the [Arduino JSON wiki](https://github.com/bblanchon/ArduinoJson/wiki)
Testimonials
------------

View File

@ -1,102 +0,0 @@
Avoiding common pitfalls in Arduino JSON
========================================
As `StaticJsonBuffer` is the corner stone of this library, you'll see that every pitfall listed here are related to a wrong understanding of the memory model.
Make sure you read [Arduino JSON memory model](Memory model.md) before going further.
## 1. Make `StaticJsonBuffer` big enough
By design, the library has no way to tell you why `parseArray()` or `parseObject()` failed.
There are basically two reasons why they may fail:
1. the JSON string is invalid,
2. the JSON string contains more values that the buffer can store.
So, if you are sure the JSON string is correct and you still can't parse it, you should try to increase the size of the `StaticJsonBuffer`.
## 2. Make sure everything fits in memory
You may go into unpredictable trouble if you allocate more memory than your processor really has.
It's a very common issue in embedded development.
To diagnose this, look at every big objects in you code and sum their size to check that they fit in RAM.
For example, don't do this:
char json[1024]; // 1 KB
StaticJsonBuffer<512> buffer; // 514 B
because it may be too big for a processor with only 2 KB: you need free memory to store other variables and the call stack.
That is why an 8-bit processor is not able to parse long and complex JSON strings.
## 3. Keep the `StaticJsonBuffer` in memory long enough
Remember that `StaticJsonBuffer`'s function return references.
References don't contain data, they are just pointer to the actual.
So they can only work if the actual data is in memory.
For example, don't do this:
JsonArray& getArray(char* json)
{
StaticJsonBuffer<200> buffer;
return buffer.parseArray(json);
}
because the local variable `buffer` will be *removed* from memory when the function `parseArray()` returns, and the `JsonArray&` will point to an invalid location.
## 4. Don't reuse the same `StaticJsonBuffer`
During is lifetime a `StaticJsonBuffer` growth until it's discarded. If you try to reuse the same instance several time, it will rapidly get full.
For this reason, you should not use a global variable for your `StaticJsonBuffer`. I don't think there is any scenario in which a global `StaticJsonBuffer` would be a valid option.
The best practice is to declare it in a local scope, so that it's discarded as soon as possible. My advice it to declare it in a function which unique role is to handle the JSON serialization.
## 5. Keep the JSON string in memory long enough
The library never make memory duplication.
This has an important implication on string values, it means that the library will return pointer to chunks of the string.
For instance, let's imagine that you parse `["hello","world"]`, like this:
char[] json = "[\"hello\",\"world\"]";
StaticJsonBuffer<32> buffer;
JsonArray& array = buffer.parseArray(json);
const char* first = array[0];
const char* second = array[1];
In that case, both `first` and `second` are pointers to the content of the original string `json`.
So this will only work if `json` is still in memory.
## 6. JSON string is altered
If you read carefully the previous section, you may have come to the conclusion that the JSON parser modifies the JSON string.
Indeed, the parser modifies the string for two reasons:
1. it inserts `\0` to terminate substrings,
2. it translate escaped characters like `\n` or `\t`.
Most of the time this wont be an issue, but there are some corner cases that can be problematic.
Let take the example bellow:
char[] json = "[\"hello\",\"world\"]";
StaticJsonBuffer<32> buffer;
JsonArray& array = buffer.parseArray(json);
If you replace it by:
char* json = "[\"hello\",\"world\"]";
StaticJsonBuffer<32> buffer;
JsonArray& array = buffer.parseArray(json);
Depending on your platform, you may have an exception because the parser tries to write at a location that is read-only.
In the first case `char json[]` declares an array of `char` initialized to the specified string.
In the second case `char* json` declares a pointer to a read-only string, in fact it should be a `const char*` instead of a `char*`.

View File

@ -1,15 +0,0 @@
Contributing to Arduino JSON
============================
If you want to contribute to the project, please:
1. Use GitHub pull request feature
2. Follow the coding conventions
3. Write tests
About the coding conventions: I try to follow the [Google C++ Style Guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.html) with few variations to match the Arduino conventions.
I use [ClangFormat](http://clang.llvm.org/docs/ClangFormat.html) to format the code for me.
I use [CppLint](http://google-styleguide.googlecode.com/svn/trunk/cpplint/cpplint.py) to detect non-compliant stuff.
You should have a look at the `scripts/` folder as it contains a few helpers scripts.

View File

@ -1,148 +0,0 @@
Decoding JSON with Arduino JSON
===============================
Before writing any code, don't forget to include the header:
#include <ArduinoJson.h>
For instructions on how to install the library, please read [Using the library with Arduino](Using the library with Arduino.md) or [Using the library without Arduino](Using the library without Arduino.md).
## Example
Here an example that parse the string `{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}`:
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
//
// Step 1: Reserve memory space
//
StaticJsonBuffer<200> jsonBuffer;
//
// Step 2: Deserialize the JSON string
//
JsonObject& root = jsonBuffer.parseObject(json);
if (!root.success())
{
Serial.println("parseObject() failed");
return;
}
//
// Step 3: Retrieve the values
//
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
## Step 1: Reserve memory space
Arduino JSON uses a preallocated memory pool to store the object tree, this is done by the `StaticJsonBuffer`.
Before continuing please read the page [Arduino JSON memory model](Memory model.md) that explains everything you need to know about `StaticJsonBuffer`.
## Step 2: Parse the JSON string
You invoke the JSON parser through the instance of `StaticJsonBuffer`.
It exposes two functions for parsing JSON:
1. `parseArray()` that returns a reference to a `JsonArray`
2. `parseObject()` that returns a reference to a `JsonObject`
Let's see an example.
Say we want to parse `{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}`, it's an object so we call `parseObject()` as follows:
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
JsonObject& root = jsonBuffer.parseObject(json);
As you can see `parseObject()` takes a `char*` as a parameter.
Be careful, it's not a `const char*`, the memory must be writable.
Indeed, the parser will modify the string in two cases:
1. to insert string endings (character `\0`),
2. to translate escaped characters (like `\n` or `\t`).
Another thing that you must keep in mind is that the string (`char json[]` in the example above) must stay in memory during the whole parsing process.
That is because the in memory object tree will store pointer to chunks of the string, so as to avoid any memory duplication.
Now, to check if the parsing was successful, you can call `JsonObject::success()`:
if (!root.success())
{
// Parsing fail
}
The result can be `false` for tree reasons:
1. the JSON string is invalid,
2. the JSON string doesn't represent an object,
3. the `StaticJsonBuffer` is too small.
We just saw how to parse an object, there is nothing more to say for arrays, the procedure is exactly the same.
## Step 3: Retrieve the values
Now that the object or array is in memory, you can extract the data very easily.
In this section, we'll see how to do it with a `JsonObject`.
Once again, there is nothing more to say about arrays, `JsonArray` works exactly the same as `JsonObject`.
#### Subscript operator
The simplest way is to use the subscript operator of `JsonObject`:
const char* sensor = root["sensor"];
long time = root["time"];
You can chain the subscript operator if you have nested arrays or objects:
double latitude = root["data"][0];
double longitude = root["data"][1];
But alternatively, you can get a reference to the nested array:
JsonArray& nestedArray = root["data"];
#### Casting values
In the previous examples, the values were implicitly casted to the target type.
You can also do this explicitly
const char* sensor = root["sensor"].asString();
long time = root["time"].as<long>();
JsonArray& nestedArray = root["data"].asArray();
If the actual value doesn't match the target type, a default value will be return:
1. `false` for boolean values
2. `0` for integer values
3. `NULL` for string values
4. `JsonArray::invalid()` for nested arrays
5. `JsonObject::invalid()` for nested object
#### Check values
If you want to know if some value is present, call `containsKey()`:
if (root.contains("extra"))
{
// root["extra"] is valid
}
If you want to check the type value has a certain type, call `is<T>()`:
if (root["extra"].is<JsonArray&>())
{
// root["extra"] is an array
}
You can also iterate through the key-value pairs of the object:
for (JsonObject::itertor it=root.begin(); it!=root.end(); ++it)
{
Serial.println(it->key);
Serial.println(i->value.asString());
}

View File

@ -1,140 +0,0 @@
Encoding JSON with Arduino JSON
===============================
Before writing any code, don't forget to include the header:
#include <ArduinoJson.h>
For instructions on how to install the library, please read [Using the library with Arduino](Using the library with Arduino.md) or [Using the library without Arduino](Using the library without Arduino.md).
## Example
Here is an example to generate `{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}`
//
// Step 1: Reserve memory space
//
StaticJsonBuffer<200> jsonBuffer;
//
// Step 2: Build object tree in memory
//
JsonObject& root = jsonBuffer.createObject();
root["sensor"] = "gps";
root["time"] = 1351824120;
JsonArray& data = root.createNestedArray("data");
data.add(48.756080, 6); // 6 is the number of decimals to print
data.add(2.302038, 6); // if not specified, 2 digits are printed
//
// Step 3: Generate the JSON string
//
root.printTo(Serial);
## Step 1: Reserve memory space
Arduino JSON uses a preallocated memory pool to store the object tree, this is done by the `StaticJsonBuffer`.
Before continuing please read the page [Arduino JSON memory model](Memory model.md) that explains everything you need to know about `StaticJsonBuffer`.
## Step 2: Build object tree in memory
Now that you have enough memory hold by the `StaticJsonBuffer`, you can use it to build your in-memory representation of the JSON string.
#### Arrays
You create an array like this:
JsonArray& array = jsonBuffer.createArray();
Don't forget the `&` after `JsonArray`, it needs to be a reference to the array.
Then you can add strings, integer, booleans, etc:
array.add("bazinga!");
array.add(42);
array.add(true);
There are two syntaxes for floating point values:
array.add(3.1415, 4); // 4 digits: "3.1415"
array.add(3.1415); // 2 digits: "3.14"
> ##### About floating point precision
> The overload of `add()` with 2 parameters allows you to specify the number of decimals to save in the JSON string.
> When you use the overload with one parameter, you use the default number of decimals which is 2.
> Note that this behavior is the exact same as Arduino's `Print::print(double,int);` which is implemented by `Serial`, so you may already be familiar with this behavior.
You can add a nested array or object if you have a reference to it.
Or simpler, you can create nested array or nested objects from the array:
JsonArray& nestedArray = array.createNestedArray();
JsonObject& nestedObject = array.createNestedObject();
#### Objects
You create an object like this:
JsonObject& object = jsonBuffer.createObject();
Again, don't forget the `&` after `JsonObject`, it needs to be a reference to the object.
Then you can add strings, integer, booleans, etc:
object["key1"] = "bazinga!";
object["key2"] = 42;
object["key3"] = true;
As for the arrays, there are two syntaxes for the floating point values:
object["key4"].set(3.1415, 4); // 4 digits "3.1415"
object["key5"] = 3.1415; // default: 2 digits "3.14"
You can add a nested array or object if you have a reference to it.
Or simpler, you can create nested array or nested objects from the object:
JsonArray& nestedArray = object.createNestedArray("key6");
JsonObject& nestedObject = object.createNestedObject("key7");
> ##### Other JsonObject functions
> * `object.add(key, value)` is a synonym for `object[key] = value`
> * `object.containsKey(key)` returns `true` is the `key` is present in `object`
> * `object.remove(key)` removes the `value` associated with `key`
## Step 3: Generate the JSON string
There are two ways tho get the resulting JSON string.
Depending on your project, you may need to dump the string in a classic `char[]` or send it to a `Print` implementation like `Serial` or `EthernetClient `.
Both ways are the easy way :-)
#### Use a classic `char[]`
Whether you have a `JsonArray&` or a `JsonObject&`, simply call `printTo()` with the destination buffer, like so:
char buffer[256];
array.printTo(buffer, sizeof(buffer));
> ##### Want an indented output?
> By default the generated JSON is as small as possible. It contains no extra space, nor line break.
> But if you want an indented, more readable output, you can.
> Simply call `prettyPrintTo` instead of `printTo()`:
>
> array.prettyPrintTo(buffer, sizeof(buffer));
#### Send to a `Print` implementation
It's very likely that the generated JSON will end up in a stream like `Serial` or `EthernetClient `, so you can save some time and memory by doing this:
array.printTo(Serial);
And, of course if you need an indented JSON string:
array.prettyPrintTo(Serial);
> ##### About the Print interface
> The library is designed to send the JSON string to an implementation of the `Print` interface that is part of Arduino.
> In the example above we used `Serial`, but they are many other implementations that would work as well, including: `HardwareSerial`, `SoftwareSerial`, `LiquidCrystal`, `EthernetClient`, `WiFiClient`, `Wire`...
> When you use this library out of the Arduino environment, it will use it's own implementation of `Print` and everything will be the same.

View File

@ -1,58 +0,0 @@
Arduino JSON memory model
=========================
## Fixed memory allocation
### Introducing `StaticJsonBuffer`
Arduino JSON uses a preallocated memory pool to store the object tree, this is done by the `StaticJsonBuffer` class.
Before using any function of the library you need to create a `StaticJsonBuffer`. Then you can use this instance to create arrays and objects, or parse a JSON string.
`StaticJsonBuffer` has a template parameter that determines its capacity. For example, the following line create a `StaticJsonBuffer` with a capacity of 200 bytes:
StaticJsonBuffer<200> jsonBuffer;
The bigger the buffer is, the more complex the object tree can be, but also the more memory you need.
### How to determine the buffer size?
So the big question you should have in mind right now is *How can I determine the size?*.
There are basically two approaches here:
1. either you can predict the content of the object tree,
2. or, you know how much memory is available.
In the first case, you know some constraints on the object tree. For instance, let's say that your know in advance (and by that I mean "at compilation time") that you want to generate an object with 3 values, one of them being an array with 2 values, like the following:
{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
To determine the memory usage of this object tree, you use the two macros `JSON_ARRAY_SIZE(n)` and `JSON_OBJECT_SIZE(n)`, both take the number of elements as an argument.
For the example above, it would be:
const int BUFFER_SIZE = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2);
StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
In the second case, let's say you dynamically generate a JSON object tree of a random complexity so you can't put a limit based on that. But on the other hand, you don't want your program to crash because the object tree doesn't fit in memory.
The solution here is to determine how much memory is available, or in other words how much memory you can afford for the JSON object tree.
### Why choosing fixed allocation?
This fixed allocation approach may seem a bit strange, especially if your a desktop application developer used to dynamic allocation, but it make a lot of sense in an embedded context:
1. the code is smaller
2. it uses less memory
3. it doesn't create memory fragmentation
4. it predictable
Don't forget that the memory is "freed" as soon as the `StaticJsonBuffer` is out of scope, like any other variable. It only hold the memory for a short amount of time.
## Memory usage
#### Object size for 8-bit AVR
| Type | Size |
|-------------------------|------------|
| JsonArray of N element | 4 + 8 * N |
| JsonObject of N element | 4 + 10 * N |

View File

@ -1,80 +0,0 @@
Migrating code written for Arduino JSON v3 to v4
================================================
Arduino JSON v4 was a major rewrite of the library, and the API changed significantly.
## Includes
Arduino JSON v3 had two include files:
#include <JsonParser.h>
#include <JsonGenerator.h>
Arduino JSON v4 only has one:
#include <ArduinoJson.h>
## Namespaces
Arduino JSON v3 had two namespaces:
using namespace ArduinoJson::Parser;
using namespace ArduinoJson::Generator;
Arduino JSON v4 doesn't require the `using namespace` statement.
It has a namespace but the `using namespace` is done in the header file.
## StaticJsonBuffer
Arduino JSON v3 had different memory allocation models for the parser:
JsonParser<16> parser; // 16 being the capacity in "tokens"
and for the generator:
JsonArray<4> array; // 4 being the number of element
JsonObject<4> object;
Arduino JSON v4 only has one memory allocation model:
StaticJsonBuffer<128> buffer; // 128 being the capacity in bytes
## Return values for the parser
Arduino JSON v3 returned value types:
JsonArray array = parser.parseArray(json);
JsonObject object = parser.parseObject(json);
Arduino JSON v4 returns references types:
JsonArray& array = buffer.parseArray(json);
JsonObject& object = buffer.parseObject(json);
Everything else is compatible
## Creating arrays and objects
Arduino JSON v3 allowed to create `JsonArray` and `JsonObject` directly:
JsonArray<4> array;
JsonObject<4> object;
Arduino JSON v4 requires that you use a `StaticJsonBuffer` for that:
JsonArray& array = buffer.createArray();
JsonObject& object = buffer.createObject();
Note: you don't have to specify the capacity anymore.
## Printable interface
Arduino JSON v3 used to implement the Printable interface, which allowed statements like:
Serial.print(array);
But Arduino JSON v4 doesn't, instead you need to write this:
array.printTo(Serial);
Note: there was a good reason for removing that feature, and it's reducing the size of `JsonArray` and `JsonObject`.

View File

@ -1,30 +0,0 @@
Using the library with Arduino
==============================
This library is primarily design to be used with the Arduino IDE and therefore has a simplified setup procedure for that environment.
If you don't use the Arduino IDE, please read [Using the library without Arduino](Using the library without Arduino.md).
## Install the library
[Download the zip package](https://github.com/bblanchon/ArduinoJson/releases) and extract it to:
<your Arduino Sketch folder>/libraries/ArduinoJson
Then restart the Arduino IDE.
## Run the examples sketches
Click `File` / `Example` / `ArduinoJson`.
![Screen capture of Arduino IDE](http://i.imgur.com/g5UwkVh.png)
## Use the library in your sketches
Just add the following line at the top of your program:
#include <ArduinoJson.h>
Then follow the instructions:
1. [Parsing JSON](Parsin JSON.md)
2. [Generating JSON](Generating JSON.md)

View File

@ -1,37 +0,0 @@
Using the library without Arduino
=================================
This library is primarily design to be used with the Arduino IDE and therefore has a simplified setup procedure for that environment.
If you use the Arduino IDE, please read [Using the library with Arduino](Using the library with Arduino.md).
However, it can be used without Arduino IDE with very little effort.
## Compiling the library
Step 1: Download source code:
git clone https://github.com/bblanchon/ArduinoJson.git
Step 2: Generate the `Makefile` for your environment
cd ArduinoJson
cmake .
Step 3: Build
make
## File paths
Assuming you installed the library into `<arduino-json>`, you need to add:
1. `<arduino-json>/include` to your include path
2. `<arduino-json>/lib` to your library path
----------
You are now ready to follow the instructions:
1. [Parsing JSON](Parsin JSON.md)
2. [Generating JSON](Generating JSON.md)

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

@ -4,6 +4,7 @@
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include "../include/ArduinoJson/DynamicJsonBuffer.hpp"
#include "../include/ArduinoJson/JsonArray.hpp"
#include "../include/ArduinoJson/JsonObject.hpp"
#include "../include/ArduinoJson/StaticJsonBuffer.hpp"

View File

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

View File

@ -0,0 +1,46 @@
// 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 {
// Forward declaration
namespace Internals {
struct DynamicJsonBufferBlock;
}
// Implements a JsonBuffer with dynamic memory allocation.
// You are strongly encouraged to consider using StaticJsonBuffer which is much
// more suitable for embedded systems.
class DynamicJsonBuffer : public JsonBuffer {
public:
DynamicJsonBuffer();
~DynamicJsonBuffer();
size_t size() const;
protected:
virtual void* alloc(size_t bytes);
private:
typedef Internals::DynamicJsonBufferBlock Block;
static const size_t FIRST_BLOCK_CAPACITY = 32;
static Block* createBlock(size_t capacity);
inline bool canAllocInHead(size_t bytes) const;
inline void* allocInHead(size_t bytes);
inline void addNewBlock();
Block* _head;
};
}

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// 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
//
// Arduino JSON library

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -7,6 +7,7 @@
#pragma once
#include "ListNode.hpp"
#include "ListConstIterator.hpp"
namespace ArduinoJson {
namespace Internals {
@ -33,6 +34,8 @@ class ListIterator {
return *this;
}
operator ListConstIterator<T>() const { return ListConstIterator<T>(_node); }
private:
ListNode<T> *_node;
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -9,6 +9,12 @@
#include <stddef.h> // for size_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 {
class JsonArray;
class JsonObject;

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -6,6 +6,7 @@
#pragma once
#include "Internals/JsonBufferAllocated.hpp"
#include "Internals/JsonPrintable.hpp"
#include "Internals/List.hpp"
#include "Internals/ReferenceType.hpp"
@ -30,7 +31,8 @@ class JsonBuffer;
// It can also be deserialized from a JSON string via JsonBuffer::parseObject().
class JsonObject : public Internals::JsonPrintable<JsonObject>,
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.
friend class JsonBuffer;

View File

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

View File

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

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -22,10 +22,10 @@ class StaticJsonBuffer : public JsonBuffer {
size_t size() const { return _size; }
protected:
virtual void* alloc(size_t size) {
if (_size + size > CAPACITY) return NULL;
virtual void* alloc(size_t bytes) {
if (_size + bytes > CAPACITY) return NULL;
void* p = &_buffer[_size];
_size += size;
_size += bytes;
return p;
}

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

@ -12,11 +12,12 @@ rm -f $OUTPUT
# create zip
"$ZIP" a $OUTPUT \
ArduinoJson/CHANGELOG.md \
ArduinoJson/doc \
ArduinoJson/examples \
ArduinoJson/include \
ArduinoJson/keywords.txt \
ArduinoJson/library.properties \
ArduinoJson/LICENSE.md \
ArduinoJson/README.md \
ArduinoJson/src
ArduinoJson/src \
ArduinoJson/ArduinoJson.h \
ArduinoJson/ArduinoJson.cpp \
-x!ArduinoJson/src/CMakeLists.txt

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -8,7 +8,8 @@
#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 n = 0;
@ -19,8 +20,24 @@ size_t Print::print(const char s[]) {
}
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];
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);
}

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-unused
-Wno-variadic-macros
-Wnon-virtual-dtor
-Wold-style-cast
-Woverloaded-virtual
-Wredundant-decls
@ -38,5 +39,10 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU)")
)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_definitions(
-Wc++11-compat
)
endif()
add_library(ArduinoJson ${SRC_FILES} ${INC_FILES})

79
src/DynamicJsonBuffer.cpp Normal file
View File

@ -0,0 +1,79 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include "../include/ArduinoJson/DynamicJsonBuffer.hpp"
namespace ArduinoJson {
namespace Internals {
struct DynamicJsonBufferBlockWithoutData {
DynamicJsonBufferBlock* next;
size_t capacity;
size_t size;
};
struct DynamicJsonBufferBlock : DynamicJsonBufferBlockWithoutData {
uint8_t data[1];
};
}
}
using namespace ArduinoJson;
using namespace ArduinoJson::Internals;
DynamicJsonBuffer::DynamicJsonBuffer() {
_head = createBlock(FIRST_BLOCK_CAPACITY);
}
DynamicJsonBuffer::~DynamicJsonBuffer() {
Block* currentBlock = _head;
while (currentBlock != NULL) {
Block* nextBlock = currentBlock->next;
free(currentBlock);
currentBlock = nextBlock;
}
}
size_t DynamicJsonBuffer::size() const {
size_t total = 0;
for (const Block* b = _head; b != NULL; b = b->next) {
total += b->size;
}
return total;
}
void* DynamicJsonBuffer::alloc(size_t bytes) {
if (!canAllocInHead(bytes)) addNewBlock();
return allocInHead(bytes);
}
bool DynamicJsonBuffer::canAllocInHead(size_t bytes) const {
return _head->size + bytes <= _head->capacity;
}
void* DynamicJsonBuffer::allocInHead(size_t bytes) {
void* p = _head->data + _head->size;
_head->size += bytes;
return p;
}
void DynamicJsonBuffer::addNewBlock() {
Block* block = createBlock(_head->capacity * 2);
block->next = _head;
_head = block;
}
DynamicJsonBuffer::Block* DynamicJsonBuffer::createBlock(size_t capacity) {
size_t blkSize = sizeof(DynamicJsonBufferBlockWithoutData) + capacity;
Block* block = static_cast<Block*>(malloc(blkSize));
block->capacity = capacity;
block->size = 0;
block->next = NULL;
return block;
}

View File

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

View File

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

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -6,7 +6,6 @@
#include "../../include/ArduinoJson/Internals/List.hpp"
#include "../../include/ArduinoJson/Internals/PlacementNew.hpp"
#include "../../include/ArduinoJson/JsonPair.hpp"
#include "../../include/ArduinoJson/JsonVariant.hpp"
@ -31,5 +30,5 @@ void List<T>::removeNode(node_type *nodeToRemove) {
}
}
template class List<JsonPair>;
template class List<JsonVariant>;
template class ArduinoJson::Internals::List<JsonPair>;
template class ArduinoJson::Internals::List<JsonVariant>;

View File

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

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -8,16 +8,21 @@
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) {
// 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;
}
return p[1];
return p[0];
}
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) {
// Optimized for code size on a 8-bit AVR
const char *p = "b\bf\fn\nr\rt\t";
const char *p = specialChars + 4;
for (;;) {
if (p[0] == '\0') return c;

View File

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

View File

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

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -7,7 +7,6 @@
#include "../include/ArduinoJson/JsonBuffer.hpp"
#include "../include/ArduinoJson/Internals/JsonParser.hpp"
#include "../include/ArduinoJson/Internals/PlacementNew.hpp"
#include "../include/ArduinoJson/JsonArray.hpp"
#include "../include/ArduinoJson/JsonObject.hpp"
@ -15,15 +14,13 @@ using namespace ArduinoJson;
using namespace ArduinoJson::Internals;
JsonArray &JsonBuffer::createArray() {
void *ptr = alloc(sizeof(JsonArray));
if (ptr) return *new (ptr) JsonArray(this);
return JsonArray::invalid();
JsonArray *ptr = new (this) JsonArray(this);
return ptr ? *ptr : JsonArray::invalid();
}
JsonObject &JsonBuffer::createObject() {
void *ptr = alloc(sizeof(JsonObject));
if (ptr) return *new (ptr) JsonObject(this);
return JsonObject::invalid();
JsonObject *ptr = new (this) JsonObject(this);
return ptr ? *ptr : JsonObject::invalid();
}
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
//
// Arduino JSON library
@ -8,7 +8,6 @@
#include <string.h> // for strcmp
#include "../include/ArduinoJson/Internals/PlacementNew.hpp"
#include "../include/ArduinoJson/Internals/StringBuilder.hpp"
#include "../include/ArduinoJson/JsonArray.hpp"
#include "../include/ArduinoJson/JsonBuffer.hpp"

View File

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

View File

@ -0,0 +1,32 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include <gtest/gtest.h>
#include <ArduinoJson.h>
TEST(DynamicJsonBuffer_Array_Tests, GrowsWithArray) {
DynamicJsonBuffer jsonBuffer;
JsonArray &array = jsonBuffer.createArray();
ASSERT_EQ(JSON_ARRAY_SIZE(0), jsonBuffer.size());
array.add("hello");
ASSERT_EQ(JSON_ARRAY_SIZE(1), jsonBuffer.size());
array.add("world");
ASSERT_EQ(JSON_ARRAY_SIZE(2), jsonBuffer.size());
}
TEST(DynamicJsonBuffer_Array_Tests, CanAdd1000Values) {
DynamicJsonBuffer jsonBuffer;
JsonArray &array = jsonBuffer.createArray();
for (int i = 1; i <= 1000; i++) {
array.add("hello");
ASSERT_EQ(array.size(), i);
}
}

View File

@ -0,0 +1,34 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include <gtest/gtest.h>
#define protected public
#include <ArduinoJson/DynamicJsonBuffer.hpp>
using namespace ArduinoJson;
class DynamicJsonBuffer_Basic_Tests : public testing::Test {
protected:
DynamicJsonBuffer buffer;
};
TEST_F(DynamicJsonBuffer_Basic_Tests, InitialSizeIsZero) {
ASSERT_EQ(0, buffer.size());
}
TEST_F(DynamicJsonBuffer_Basic_Tests, SizeIncreasesAfterAlloc) {
buffer.alloc(1);
ASSERT_EQ(1, buffer.size());
buffer.alloc(1);
ASSERT_EQ(2, buffer.size());
}
TEST_F(DynamicJsonBuffer_Basic_Tests, ReturnDifferentPointer) {
void* p1 = buffer.alloc(1);
void* p2 = buffer.alloc(2);
ASSERT_NE(p1, p2);
}

View File

@ -0,0 +1,24 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include <gtest/gtest.h>
#include <ArduinoJson.h>
TEST(DynamicJsonBuffer_Object_Tests, GrowsWithObject) {
DynamicJsonBuffer json;
JsonObject &obj = json.createObject();
ASSERT_EQ(JSON_OBJECT_SIZE(0), json.size());
obj["hello"];
ASSERT_EQ(JSON_OBJECT_SIZE(1), json.size());
obj["world"];
ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size());
obj["world"]; // <- same value, should not grow
ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size());
}

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -10,16 +10,16 @@
class GbathreeBug : public testing::Test {
public:
GbathreeBug() : object(buffer.parseObject(getJson())) {}
GbathreeBug() : _object(_buffer.parseObject(getJson())) {}
protected:
char json[1024];
StaticJsonBuffer<10000> buffer;
const JsonObject& object;
char _json[1024];
DynamicJsonBuffer _buffer;
const JsonObject& _object;
private:
char* getJson() {
strcpy(json,
strcpy(_json,
"{\"protocol_name\":\"fluorescence\",\"repeats\":1,\"wait\":0,"
"\"averages\":1,\"measurements\":3,\"meas2_light\":15,\"meas1_"
"baseline\":0,\"act_light\":20,\"pulsesize\":25,\"pulsedistance\":"
@ -30,46 +30,46 @@ class GbathreeBug : public testing::Test {
"\"measlights\":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,"
"15,15]],\"measlights2\":[[15,15,15,15],[15,15,15,15],[15,15,15,15],"
"[15,15,15,15]],\"altc\":[2,2,2,2],\"altd\":[2,2,2,2]}");
return json;
return _json;
}
};
TEST_F(GbathreeBug, Success) { EXPECT_TRUE(object.success()); }
TEST_F(GbathreeBug, Success) { EXPECT_TRUE(_object.success()); }
TEST_F(GbathreeBug, ProtocolName) {
EXPECT_STREQ("fluorescence", object.at("protocol_name").asString());
EXPECT_STREQ("fluorescence", _object.at("protocol_name").asString());
}
TEST_F(GbathreeBug, Repeats) { EXPECT_EQ(1, object["repeats"]); }
TEST_F(GbathreeBug, Repeats) { EXPECT_EQ(1, _object["repeats"]); }
TEST_F(GbathreeBug, Wait) { EXPECT_EQ(0, object["wait"]); }
TEST_F(GbathreeBug, Wait) { EXPECT_EQ(0, _object["wait"]); }
TEST_F(GbathreeBug, Measurements) { EXPECT_EQ(3, object["measurements"]); }
TEST_F(GbathreeBug, Measurements) { EXPECT_EQ(3, _object["measurements"]); }
TEST_F(GbathreeBug, Meas2_Light) { EXPECT_EQ(15, object["meas2_light"]); }
TEST_F(GbathreeBug, Meas2_Light) { EXPECT_EQ(15, _object["meas2_light"]); }
TEST_F(GbathreeBug, Meas1_Baseline) { EXPECT_EQ(0, object["meas1_baseline"]); }
TEST_F(GbathreeBug, Meas1_Baseline) { EXPECT_EQ(0, _object["meas1_baseline"]); }
TEST_F(GbathreeBug, Act_Light) { EXPECT_EQ(20, object["act_light"]); }
TEST_F(GbathreeBug, Act_Light) { EXPECT_EQ(20, _object["act_light"]); }
TEST_F(GbathreeBug, Pulsesize) { EXPECT_EQ(25, object["pulsesize"]); }
TEST_F(GbathreeBug, Pulsesize) { EXPECT_EQ(25, _object["pulsesize"]); }
TEST_F(GbathreeBug, Pulsedistance) {
EXPECT_EQ(10000, object["pulsedistance"]);
EXPECT_EQ(10000, _object["pulsedistance"]);
}
TEST_F(GbathreeBug, Actintensity1) { EXPECT_EQ(50, object["actintensity1"]); }
TEST_F(GbathreeBug, Actintensity1) { EXPECT_EQ(50, _object["actintensity1"]); }
TEST_F(GbathreeBug, Actintensity2) { EXPECT_EQ(255, object["actintensity2"]); }
TEST_F(GbathreeBug, Actintensity2) { EXPECT_EQ(255, _object["actintensity2"]); }
TEST_F(GbathreeBug, Measintensity) { EXPECT_EQ(255, object["measintensity"]); }
TEST_F(GbathreeBug, Measintensity) { EXPECT_EQ(255, _object["measintensity"]); }
TEST_F(GbathreeBug, Calintensity) { EXPECT_EQ(255, object["calintensity"]); }
TEST_F(GbathreeBug, Calintensity) { EXPECT_EQ(255, _object["calintensity"]); }
TEST_F(GbathreeBug, Pulses) {
// "pulses":[50,50,50]
JsonArray& array = object.at("pulses");
JsonArray& array = _object.at("pulses");
EXPECT_TRUE(array.success());
EXPECT_EQ(3, array.size());
@ -82,7 +82,7 @@ TEST_F(GbathreeBug, Pulses) {
TEST_F(GbathreeBug, Act) {
// "act":[2,1,2,2]
JsonArray& array = object.at("act");
JsonArray& array = _object.at("act");
EXPECT_TRUE(array.success());
EXPECT_EQ(4, array.size());
@ -95,7 +95,7 @@ TEST_F(GbathreeBug, Act) {
TEST_F(GbathreeBug, Detectors) {
// "detectors":[[34,34,34,34],[34,34,34,34],[34,34,34,34],[34,34,34,34]]
JsonArray& array = object.at("detectors");
JsonArray& array = _object.at("detectors");
EXPECT_TRUE(array.success());
EXPECT_EQ(4, array.size());
@ -110,7 +110,7 @@ TEST_F(GbathreeBug, Detectors) {
TEST_F(GbathreeBug, Alta) {
// alta:[2,2,2,2]
JsonArray& array = object.at("alta");
JsonArray& array = _object.at("alta");
EXPECT_TRUE(array.success());
EXPECT_EQ(4, array.size());
@ -123,7 +123,7 @@ TEST_F(GbathreeBug, Alta) {
TEST_F(GbathreeBug, Altb) {
// altb:[2,2,2,2]
JsonArray& array = object.at("altb");
JsonArray& array = _object.at("altb");
EXPECT_TRUE(array.success());
EXPECT_EQ(4, array.size());
@ -136,7 +136,7 @@ TEST_F(GbathreeBug, Altb) {
TEST_F(GbathreeBug, Measlights) {
// "measlights":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]]
JsonArray& array = object.at("measlights");
JsonArray& array = _object.at("measlights");
EXPECT_TRUE(array.success());
EXPECT_EQ(4, array.size());
@ -152,7 +152,7 @@ TEST_F(GbathreeBug, Measlights) {
TEST_F(GbathreeBug, Measlights2) {
// "measlights2":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]]
JsonArray& array = object.at("measlights2");
JsonArray& array = _object.at("measlights2");
EXPECT_TRUE(array.success());
EXPECT_EQ(4, array.size());
@ -167,7 +167,7 @@ TEST_F(GbathreeBug, Measlights2) {
TEST_F(GbathreeBug, Altc) {
// altc:[2,2,2,2]
JsonArray& array = object.at("altc");
JsonArray& array = _object.at("altc");
EXPECT_TRUE(array.success());
EXPECT_EQ(4, array.size());
@ -180,7 +180,7 @@ TEST_F(GbathreeBug, Altc) {
TEST_F(GbathreeBug, Altd) {
// altd:[2,2,2,2]
JsonArray& array = object.at("altd");
JsonArray& array = _object.at("altd");
EXPECT_TRUE(array.success());
EXPECT_EQ(4, array.size());

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -13,34 +13,34 @@ class IntegrationTests : public testing::TestWithParam<const char*> {
protected:
virtual void SetUp() {
_input = GetParam();
strcpy(inputBuffer, _input);
strcpy(_inputBuffer, _input);
}
void parseThenPrint(char* input, char* output) {
StaticJsonBuffer<10000> json;
json.parseObject(input).printTo(output, MAX_JSON_SIZE);
DynamicJsonBuffer buffer;
buffer.parseObject(input).printTo(output, MAX_JSON_SIZE);
}
void parseThenPrettyPrint(char* input, char* output) {
StaticJsonBuffer<10000> json;
json.parseObject(input).prettyPrintTo(output, MAX_JSON_SIZE);
DynamicJsonBuffer buffer;
buffer.parseObject(input).prettyPrintTo(output, MAX_JSON_SIZE);
}
const char* _input;
char inputBuffer[MAX_JSON_SIZE];
char outputBuffer[MAX_JSON_SIZE];
char intermediateBuffer[MAX_JSON_SIZE];
char _inputBuffer[MAX_JSON_SIZE];
char _outputBuffer[MAX_JSON_SIZE];
char _intermediateBuffer[MAX_JSON_SIZE];
};
TEST_P(IntegrationTests, ParseThenPrint) {
parseThenPrint(inputBuffer, outputBuffer);
ASSERT_STREQ(_input, outputBuffer);
parseThenPrint(_inputBuffer, _outputBuffer);
ASSERT_STREQ(_input, _outputBuffer);
}
TEST_P(IntegrationTests, ParseThenPrettyPrintThenParseThenPrint) {
parseThenPrettyPrint(inputBuffer, intermediateBuffer);
parseThenPrint(intermediateBuffer, outputBuffer);
ASSERT_STREQ(_input, outputBuffer);
parseThenPrettyPrint(_inputBuffer, _intermediateBuffer);
parseThenPrint(_intermediateBuffer, _outputBuffer);
ASSERT_STREQ(_input, _outputBuffer);
}
INSTANTIATE_TEST_CASE_P(

View File

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

39
test/Issue34.cpp Normal file
View File

@ -0,0 +1,39 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include <gtest/gtest.h>
#include <ArduinoJson.h>
class Issue34 : public testing::Test {
protected:
template <typename T>
void test_with_value(T expected) {
StaticJsonBuffer<JSON_OBJECT_SIZE(1)> jsonBuffer;
JsonObject& jsonObject = jsonBuffer.createObject();
jsonObject["key"] = expected;
T actual = jsonObject["key"];
ASSERT_EQ(expected, actual);
}
};
TEST_F(Issue34, int8_t) { test_with_value<int8_t>(1); }
TEST_F(Issue34, uint8_t) { test_with_value<uint8_t>(2); }
TEST_F(Issue34, int16_t) { test_with_value<int16_t>(3); }
TEST_F(Issue34, uint16_t) { test_with_value<uint16_t>(4); }
TEST_F(Issue34, int32_t) { test_with_value<int32_t>(5); }
TEST_F(Issue34, uint32_t) { test_with_value<uint32_t>(6); }
TEST_F(Issue34, float) { test_with_value<float>(7); }
TEST_F(Issue34, double) { test_with_value<double>(8); }

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
//
// Arduino JSON library
@ -9,7 +9,7 @@
class JsonArray_Container_Tests : public ::testing::Test {
protected:
JsonArray_Container_Tests() : array(json.createArray()) {}
JsonArray_Container_Tests() : _array(_jsonBuffer.createArray()) {}
template <typename T>
void firstMustEqual(T expected) {
@ -31,106 +31,144 @@ class JsonArray_Container_Tests : public ::testing::Test {
itemMustReference(1, expected);
}
void sizeMustBe(int expected) { EXPECT_EQ(expected, array.size()); }
void sizeMustBe(int expected) { EXPECT_EQ(expected, _array.size()); }
StaticJsonBuffer<256> json;
JsonArray& array;
DynamicJsonBuffer _jsonBuffer;
JsonArray& _array;
private:
template <typename T>
void itemMustEqual(int index, T expected) {
EXPECT_EQ(expected, array[index].as<T>());
EXPECT_EQ(expected, _array[index].as<T>());
}
template <typename T>
void itemMustReference(int index, const T& expected) {
EXPECT_EQ(&expected, &array[index].as<T&>());
EXPECT_EQ(&expected, &_array[index].as<T&>());
}
};
template <>
void JsonArray_Container_Tests::itemMustEqual(int index, const char* expected) {
EXPECT_STREQ(expected, _array[index].asString());
}
TEST_F(JsonArray_Container_Tests, SuccessIsTrue) {
EXPECT_TRUE(array.success());
EXPECT_TRUE(_array.success());
}
TEST_F(JsonArray_Container_Tests, InitialSizeIsZero) { sizeMustBe(0); }
TEST_F(JsonArray_Container_Tests, Grow_WhenValuesAreAdded) {
array.add("hello");
_array.add("hello");
sizeMustBe(1);
array.add("world");
_array.add("world");
sizeMustBe(2);
}
TEST_F(JsonArray_Container_Tests, CanStoreIntegers) {
array.add(123);
array.add(456);
_array.add(123);
_array.add(456);
firstMustEqual(123);
secondMustEqual(456);
}
TEST_F(JsonArray_Container_Tests, CanStoreDoubles) {
array.add(123.45);
array.add(456.78);
_array.add(123.45);
_array.add(456.78);
firstMustEqual(123.45);
secondMustEqual(456.78);
}
TEST_F(JsonArray_Container_Tests, CanStoreBooleans) {
array.add(true);
array.add(false);
_array.add(true);
_array.add(false);
firstMustEqual(true);
secondMustEqual(false);
}
TEST_F(JsonArray_Container_Tests, CanStoreStrings) {
const char* firstString = "h3110";
const char* secondString = "w0r1d";
_array.add("hello");
_array.add("world");
array.add(firstString);
array.add(secondString);
firstMustEqual(firstString);
secondMustEqual(secondString);
firstMustEqual("hello");
secondMustEqual("world");
}
TEST_F(JsonArray_Container_Tests, CanStoreNestedArrays) {
JsonArray& innerarray1 = json.createArray();
JsonArray& innerarray2 = json.createArray();
JsonArray& inner_array1 = _jsonBuffer.createArray();
JsonArray& inner_array2 = _jsonBuffer.createArray();
array.add(innerarray1);
array.add(innerarray2);
_array.add(inner_array1);
_array.add(inner_array2);
firstMustReference(innerarray1);
secondMustReference(innerarray2);
firstMustReference(inner_array1);
secondMustReference(inner_array2);
}
TEST_F(JsonArray_Container_Tests, CanStoreNestedObjects) {
JsonObject& innerObject1 = json.createObject();
JsonObject& innerObject2 = json.createObject();
JsonObject& innerObject1 = _jsonBuffer.createObject();
JsonObject& innerObject2 = _jsonBuffer.createObject();
array.add(innerObject1);
array.add(innerObject2);
_array.add(innerObject1);
_array.add(innerObject2);
firstMustReference(innerObject1);
secondMustReference(innerObject2);
}
TEST_F(JsonArray_Container_Tests, CanCreateNestedArrays) {
JsonArray& innerarray1 = array.createNestedArray();
JsonArray& innerarray2 = array.createNestedArray();
JsonArray& inner_array1 = _array.createNestedArray();
JsonArray& inner_array2 = _array.createNestedArray();
firstMustReference(innerarray1);
secondMustReference(innerarray2);
firstMustReference(inner_array1);
secondMustReference(inner_array2);
}
TEST_F(JsonArray_Container_Tests, CanCreateNestedObjects) {
JsonObject& innerObject1 = array.createNestedObject();
JsonObject& innerObject2 = array.createNestedObject();
JsonObject& innerObject1 = _array.createNestedObject();
JsonObject& innerObject2 = _array.createNestedObject();
firstMustReference(innerObject1);
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
//
// Arduino JSON library

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -7,21 +7,32 @@
#include <gtest/gtest.h>
#include <ArduinoJson.h>
TEST(JsonArray_Iterator_Test, SimpleTest) {
StaticJsonBuffer<100> jsonBuffer;
template <typename TIterator>
static void run_iterator_test() {
StaticJsonBuffer<JSON_ARRAY_SIZE(2)> jsonBuffer;
JsonArray &array = jsonBuffer.createArray();
array.add(12);
array.add(34);
JsonArray::iterator it = array.begin();
JsonArray::iterator end = array.end();
TIterator it = array.begin();
TIterator end = array.end();
EXPECT_NE(end, it);
EXPECT_EQ(12, it->as<int>());
EXPECT_EQ(12, it->template as<int>());
EXPECT_EQ(12, static_cast<int>(*it));
++it;
EXPECT_NE(end, it);
EXPECT_EQ(34, it->as<int>());
EXPECT_EQ(34, it->template as<int>());
EXPECT_EQ(34, static_cast<int>(*it));
++it;
EXPECT_EQ(end, it);
}
TEST(JsonArray_Iterator_Test, RunItertorToEnd) {
run_iterator_test<JsonArray::iterator>();
}
TEST(JsonArray_Iterator_Test, RunConstItertorToEnd) {
run_iterator_test<JsonArray::const_iterator>();
}

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -9,20 +9,20 @@
class JsonArray_PrettyPrintTo_Tests : public testing::Test {
public:
JsonArray_PrettyPrintTo_Tests() : array(json.createArray()) {}
JsonArray_PrettyPrintTo_Tests() : array(jsonBuffer.createArray()) {}
protected:
StaticJsonBuffer<200> json;
DynamicJsonBuffer jsonBuffer;
JsonArray& array;
void outputMustBe(const char* expected) {
size_t n = array.prettyPrintTo(buffer, sizeof(buffer));
EXPECT_STREQ(expected, buffer);
size_t n = array.prettyPrintTo(_buffer, sizeof(_buffer));
EXPECT_STREQ(expected, _buffer);
EXPECT_EQ(strlen(expected), n);
}
private:
char buffer[256];
char _buffer[256];
};
TEST_F(JsonArray_PrettyPrintTo_Tests, Empty) { outputMustBe("[]"); }

View File

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

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -9,118 +9,118 @@
class JsonObject_Container_Tests : public ::testing::Test {
public:
JsonObject_Container_Tests() : object(json.createObject()) {}
JsonObject_Container_Tests() : _object(_jsonBuffer.createObject()) {}
protected:
StaticJsonBuffer<256> json;
JsonObject& object;
DynamicJsonBuffer _jsonBuffer;
JsonObject& _object;
};
TEST_F(JsonObject_Container_Tests, InitialSizeIsZero) {
EXPECT_EQ(0, object.size());
EXPECT_EQ(0, _object.size());
}
TEST_F(JsonObject_Container_Tests, Grow_WhenValuesAreAdded) {
object["hello"];
EXPECT_EQ(1, object.size());
_object["hello"];
EXPECT_EQ(1, _object.size());
object["world"];
EXPECT_EQ(2, object.size());
_object["world"];
EXPECT_EQ(2, _object.size());
}
TEST_F(JsonObject_Container_Tests, DoNotGrow_WhenSameValueIsAdded) {
object["hello"];
EXPECT_EQ(1, object.size());
_object["hello"];
EXPECT_EQ(1, _object.size());
object["hello"];
EXPECT_EQ(1, object.size());
_object["hello"];
EXPECT_EQ(1, _object.size());
}
TEST_F(JsonObject_Container_Tests, Shrink_WhenValuesAreRemoved) {
object["hello"];
object["world"];
_object["hello"];
_object["world"];
object.remove("hello");
EXPECT_EQ(1, object.size());
_object.remove("hello");
EXPECT_EQ(1, _object.size());
object.remove("world");
EXPECT_EQ(0, object.size());
_object.remove("world");
EXPECT_EQ(0, _object.size());
}
TEST_F(JsonObject_Container_Tests,
DoNotShrink_WhenRemoveIsCalledWithAWrongKey) {
object["hello"];
object["world"];
_object["hello"];
_object["world"];
object.remove(":-P");
_object.remove(":-P");
EXPECT_EQ(2, object.size());
EXPECT_EQ(2, _object.size());
}
TEST_F(JsonObject_Container_Tests, CanStoreIntegers) {
object["hello"] = 123;
object["world"] = 456;
_object["hello"] = 123;
_object["world"] = 456;
EXPECT_EQ(123, object["hello"].as<int>());
EXPECT_EQ(456, object["world"].as<int>());
EXPECT_EQ(123, _object["hello"].as<int>());
EXPECT_EQ(456, _object["world"].as<int>());
}
TEST_F(JsonObject_Container_Tests, CanStoreDoubles) {
object["hello"] = 123.45;
object["world"] = 456.78;
_object["hello"] = 123.45;
_object["world"] = 456.78;
EXPECT_EQ(123.45, object["hello"].as<double>());
EXPECT_EQ(456.78, object["world"].as<double>());
EXPECT_EQ(123.45, _object["hello"].as<double>());
EXPECT_EQ(456.78, _object["world"].as<double>());
}
TEST_F(JsonObject_Container_Tests, CanStoreBooleans) {
object["hello"] = true;
object["world"] = false;
_object["hello"] = true;
_object["world"] = false;
EXPECT_TRUE(object["hello"].as<bool>());
EXPECT_FALSE(object["world"].as<bool>());
EXPECT_TRUE(_object["hello"].as<bool>());
EXPECT_FALSE(_object["world"].as<bool>());
}
TEST_F(JsonObject_Container_Tests, CanStoreStrings) {
object["hello"] = "h3110";
object["world"] = "w0r1d";
_object["hello"] = "h3110";
_object["world"] = "w0r1d";
EXPECT_STREQ("h3110", object["hello"].as<const char*>());
EXPECT_STREQ("w0r1d", object["world"].as<const char*>());
EXPECT_STREQ("h3110", _object["hello"].as<const char*>());
EXPECT_STREQ("w0r1d", _object["world"].as<const char*>());
}
TEST_F(JsonObject_Container_Tests, CanStoreInnerArrays) {
JsonArray& innerarray1 = json.createArray();
JsonArray& innerarray2 = json.createArray();
JsonArray& innerarray1 = _jsonBuffer.createArray();
JsonArray& innerarray2 = _jsonBuffer.createArray();
object["hello"] = innerarray1;
object["world"] = innerarray2;
_object["hello"] = innerarray1;
_object["world"] = innerarray2;
EXPECT_EQ(&innerarray1, &object["hello"].asArray());
EXPECT_EQ(&innerarray2, &object["world"].asArray());
EXPECT_EQ(&innerarray1, &_object["hello"].asArray());
EXPECT_EQ(&innerarray2, &_object["world"].asArray());
}
TEST_F(JsonObject_Container_Tests, CanStoreInnerObjects) {
JsonObject& innerObject1 = json.createObject();
JsonObject& innerObject2 = json.createObject();
JsonObject& innerObject1 = _jsonBuffer.createObject();
JsonObject& innerObject2 = _jsonBuffer.createObject();
object["hello"] = innerObject1;
object["world"] = innerObject2;
_object["hello"] = innerObject1;
_object["world"] = innerObject2;
EXPECT_EQ(&innerObject1, &object["hello"].asObject());
EXPECT_EQ(&innerObject2, &object["world"].asObject());
EXPECT_EQ(&innerObject1, &_object["hello"].asObject());
EXPECT_EQ(&innerObject2, &_object["world"].asObject());
}
TEST_F(JsonObject_Container_Tests, ContainsKeyReturnFalseForNonExistingKey) {
EXPECT_FALSE(object.containsKey("hello"));
EXPECT_FALSE(_object.containsKey("hello"));
}
TEST_F(JsonObject_Container_Tests, ContainsKeyReturnTrueForDefinedValue) {
object.add("hello", 42);
EXPECT_TRUE(object.containsKey("hello"));
_object.add("hello", 42);
EXPECT_TRUE(_object.containsKey("hello"));
}
TEST_F(JsonObject_Container_Tests, ContainsKeyReturnFalseForUndefinedValue) {
object.add("hello");
EXPECT_FALSE(object.containsKey("hello"));
_object.add("hello");
EXPECT_FALSE(_object.containsKey("hello"));
}

View File

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

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -10,39 +10,39 @@
class JsonObject_Iterator_Test : public testing::Test {
public:
JsonObject_Iterator_Test() : object(_buffer.createObject()) {
object["ab"] = 12;
object["cd"] = 34;
JsonObject_Iterator_Test() : _object(_buffer.createObject()) {
_object["ab"] = 12;
_object["cd"] = 34;
}
protected:
StaticJsonBuffer<256> _buffer;
JsonObject& object;
StaticJsonBuffer<JSON_OBJECT_SIZE(2)> _buffer;
JsonObject& _object;
};
TEST_F(JsonObject_Iterator_Test, NonConstIterator) {
JsonObject::iterator it = object.begin();
ASSERT_NE(object.end(), it);
JsonObject::iterator it = _object.begin();
ASSERT_NE(_object.end(), it);
EXPECT_STREQ("ab", it->key);
EXPECT_EQ(12, it->value);
it->key = "a.b";
it->value = 1.2;
++it;
ASSERT_NE(object.end(), it);
ASSERT_NE(_object.end(), it);
EXPECT_STREQ("cd", it->key);
EXPECT_EQ(34, it->value);
it->key = "c.d";
it->value = 3.4;
++it;
ASSERT_EQ(object.end(), it);
ASSERT_EQ(_object.end(), it);
ASSERT_EQ(2, object.size());
EXPECT_EQ(1.2, object["a.b"]);
EXPECT_EQ(3.4, object["c.d"]);
ASSERT_EQ(2, _object.size());
EXPECT_EQ(1.2, _object["a.b"]);
EXPECT_EQ(3.4, _object["c.d"]);
}
TEST_F(JsonObject_Iterator_Test, ConstIterator) {
const JsonObject& const_object = object;
const JsonObject& const_object = _object;
JsonObject::const_iterator it = const_object.begin();
ASSERT_NE(const_object.end(), it);

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -9,14 +9,14 @@
class JsonObject_PrettyPrintTo_Tests : public testing::Test {
public:
JsonObject_PrettyPrintTo_Tests() : object(json.createObject()) {}
JsonObject_PrettyPrintTo_Tests() : _object(_jsonBuffer.createObject()) {}
protected:
StaticJsonBuffer<300> json;
JsonObject &object;
DynamicJsonBuffer _jsonBuffer;
JsonObject &_object;
void outputMustBe(const char *expected) {
size_t n = object.prettyPrintTo(buffer, sizeof(buffer));
size_t n = _object.prettyPrintTo(buffer, sizeof(buffer));
EXPECT_STREQ(expected, buffer);
EXPECT_EQ(strlen(expected), n);
}
@ -28,7 +28,7 @@ class JsonObject_PrettyPrintTo_Tests : public testing::Test {
TEST_F(JsonObject_PrettyPrintTo_Tests, EmptyObject) { outputMustBe("{}"); }
TEST_F(JsonObject_PrettyPrintTo_Tests, OneMember) {
object["key"] = "value";
_object["key"] = "value";
outputMustBe(
"{\r\n"
@ -37,8 +37,8 @@ TEST_F(JsonObject_PrettyPrintTo_Tests, OneMember) {
}
TEST_F(JsonObject_PrettyPrintTo_Tests, TwoMembers) {
object["key1"] = "value1";
object["key2"] = "value2";
_object["key1"] = "value1";
_object["key2"] = "value2";
outputMustBe(
"{\r\n"
@ -48,8 +48,8 @@ TEST_F(JsonObject_PrettyPrintTo_Tests, TwoMembers) {
}
TEST_F(JsonObject_PrettyPrintTo_Tests, EmptyNestedContainers) {
object.createNestedObject("key1");
object.createNestedArray("key2");
_object.createNestedObject("key1");
_object.createNestedArray("key2");
outputMustBe(
"{\r\n"
@ -59,10 +59,10 @@ TEST_F(JsonObject_PrettyPrintTo_Tests, EmptyNestedContainers) {
}
TEST_F(JsonObject_PrettyPrintTo_Tests, NestedContainers) {
JsonObject &nested1 = object.createNestedObject("key1");
JsonObject &nested1 = _object.createNestedObject("key1");
nested1["a"] = 1;
JsonArray &nested2 = object.createNestedArray("key2");
JsonArray &nested2 = _object.createNestedArray("key2");
nested2.add(2);
outputMustBe(

View File

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

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -42,7 +42,7 @@ class JsonParser_Array_Tests : public testing::Test {
EXPECT_STREQ(expected, _array->at(index).as<const char *>());
}
StaticJsonBuffer<256> _jsonBuffer;
DynamicJsonBuffer _jsonBuffer;
JsonArray *_array;
char _jsonString[256];
};

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -8,7 +8,7 @@
#include <ArduinoJson.h>
TEST(JsonParser_Nested_Tests, ArrayNestedInObject) {
StaticJsonBuffer<256> jsonBuffer;
DynamicJsonBuffer jsonBuffer;
char jsonString[] = " { \"ab\" : [ 1 , 2 ] , \"cd\" : [ 3 , 4 ] } ";
JsonObject &object = jsonBuffer.parseObject(jsonString);
@ -31,7 +31,7 @@ TEST(JsonParser_Nested_Tests, ArrayNestedInObject) {
}
TEST(JsonParser_Nested_Tests, ObjectNestedInArray) {
StaticJsonBuffer<256> jsonBuffer;
DynamicJsonBuffer jsonBuffer;
char jsonString[] =
" [ { \"a\" : 1 , \"b\" : 2 } , { \"c\" : 3 , \"d\" : 4 } ] ";

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -31,14 +31,14 @@ class JsonParser_NestingLimit_Tests : public testing::Test {
private:
bool tryParseArray(const char *json) {
StaticJsonBuffer<256> buffer;
DynamicJsonBuffer buffer;
char s[256];
strcpy(s, json);
return buffer.parseArray(s, _nestingLimit).success();
}
bool tryParseObject(const char *json) {
StaticJsonBuffer<256> buffer;
DynamicJsonBuffer buffer;
char s[256];
strcpy(s, json);
return buffer.parseObject(s, _nestingLimit).success();

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -30,7 +30,7 @@ class JsonParser_Object_Test : public testing::Test {
}
private:
StaticJsonBuffer<256> _jsonBuffer;
DynamicJsonBuffer _jsonBuffer;
JsonObject *_object;
char _jsonString[256];
};

View File

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

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -9,59 +9,59 @@
class JsonVariant_Copy_Tests : public ::testing::Test {
protected:
StaticJsonBuffer<200> json;
JsonVariant variant1;
JsonVariant variant2;
DynamicJsonBuffer _jsonBuffer;
JsonVariant _variant1;
JsonVariant _variant2;
};
TEST_F(JsonVariant_Copy_Tests, IntegersAreCopiedByValue) {
variant1 = 123;
variant2 = variant1;
variant1 = 456;
_variant1 = 123;
_variant2 = _variant1;
_variant1 = 456;
EXPECT_EQ(123, variant2.as<int>());
EXPECT_EQ(123, _variant2.as<int>());
}
TEST_F(JsonVariant_Copy_Tests, DoublesAreCopiedByValue) {
variant1 = 123.45;
variant2 = variant1;
variant1 = 456.78;
_variant1 = 123.45;
_variant2 = _variant1;
_variant1 = 456.78;
EXPECT_EQ(123.45, variant2.as<double>());
EXPECT_EQ(123.45, _variant2.as<double>());
}
TEST_F(JsonVariant_Copy_Tests, BooleansAreCopiedByValue) {
variant1 = true;
variant2 = variant1;
variant1 = false;
_variant1 = true;
_variant2 = _variant1;
_variant1 = false;
EXPECT_TRUE(variant2.as<bool>());
EXPECT_TRUE(_variant2.as<bool>());
}
TEST_F(JsonVariant_Copy_Tests, StringsAreCopiedByValue) {
variant1 = "hello";
variant2 = variant1;
variant1 = "world";
_variant1 = "hello";
_variant2 = _variant1;
_variant1 = "world";
EXPECT_STREQ("hello", variant2.as<const char *>());
EXPECT_STREQ("hello", _variant2.as<const char *>());
}
TEST_F(JsonVariant_Copy_Tests, ObjectsAreCopiedByReference) {
JsonObject &object = json.createObject();
JsonObject &object = _jsonBuffer.createObject();
variant1 = object;
_variant1 = object;
object["hello"] = "world";
EXPECT_EQ(1, variant1.asObject().size());
EXPECT_EQ(1, _variant1.asObject().size());
}
TEST_F(JsonVariant_Copy_Tests, ArraysAreCopiedByReference) {
JsonArray &array = json.createArray();
JsonArray &array = _jsonBuffer.createArray();
variant1 = array;
_variant1 = array;
array.add("world");
EXPECT_EQ(1, variant1.asArray().size());
EXPECT_EQ(1, _variant1.asArray().size());
}

View File

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

View File

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

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -11,18 +11,18 @@ class JsonVariant_Storage_Tests : public ::testing::Test {
protected:
template <typename T>
void testValue(T expected) {
actual.set(expected);
EXPECT_EQ(expected, actual.as<T>());
_actual.set(expected);
EXPECT_EQ(expected, _actual.as<T>());
}
template <typename T>
void testReference(T &expected) {
actual.set(expected);
EXPECT_EQ(expected, actual.as<T &>());
_actual.set(expected);
EXPECT_EQ(expected, _actual.as<T &>());
}
private:
JsonVariant actual;
JsonVariant _actual;
};
TEST_F(JsonVariant_Storage_Tests, Double) { testValue<double>(123.45); }
@ -41,8 +41,8 @@ TEST_F(JsonVariant_Storage_Tests, ULong) { testValue<unsigned long>(123UL); }
TEST_F(JsonVariant_Storage_Tests, UShort) { testValue<unsigned short>(123); }
TEST_F(JsonVariant_Storage_Tests, CanStoreObject) {
StaticJsonBuffer<200> json;
JsonObject &object = json.createObject();
DynamicJsonBuffer jsonBuffer;
JsonObject &object = jsonBuffer.createObject();
testReference(object);
}

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -9,56 +9,56 @@
class JsonVariant_Subscript_Tests : public ::testing::Test {
protected:
StaticJsonBuffer<200> buffer;
JsonVariant variant;
DynamicJsonBuffer _jsonBuffer;
JsonVariant _variant;
};
TEST_F(JsonVariant_Subscript_Tests, Array) {
JsonArray &array = buffer.createArray();
JsonArray &array = _jsonBuffer.createArray();
array.add("element at index 0");
array.add("element at index 1");
variant = array;
_variant = 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_FALSE(variant[-1].success());
EXPECT_FALSE(variant[3].success());
EXPECT_FALSE(variant["0"].success());
EXPECT_EQ(2, _variant.size());
EXPECT_STREQ("element at index 0", _variant[0].asString());
EXPECT_STREQ("element at index 1", _variant[1].asString());
EXPECT_FALSE(_variant[-1].success());
EXPECT_FALSE(_variant[3].success());
EXPECT_FALSE(_variant["0"].success());
}
TEST_F(JsonVariant_Subscript_Tests, Object) {
JsonObject &object = buffer.createObject();
JsonObject &object = _jsonBuffer.createObject();
object["a"] = "element at key \"a\"";
object["b"] = "element at key \"b\"";
variant = object;
_variant = object;
EXPECT_EQ(2, variant.size());
EXPECT_STREQ("element at key \"a\"", variant["a"].asString());
EXPECT_STREQ("element at key \"b\"", variant["b"].asString());
EXPECT_FALSE(variant["c"].success());
EXPECT_FALSE(variant[0].success());
EXPECT_EQ(2, _variant.size());
EXPECT_STREQ("element at key \"a\"", _variant["a"].asString());
EXPECT_STREQ("element at key \"b\"", _variant["b"].asString());
EXPECT_FALSE(_variant["c"].success());
EXPECT_FALSE(_variant[0].success());
}
TEST_F(JsonVariant_Subscript_Tests, Undefined) {
variant = JsonVariant();
EXPECT_EQ(0, variant.size());
EXPECT_FALSE(variant["0"].success());
EXPECT_FALSE(variant[0].success());
_variant = JsonVariant();
EXPECT_EQ(0, _variant.size());
EXPECT_FALSE(_variant["0"].success());
EXPECT_FALSE(_variant[0].success());
}
TEST_F(JsonVariant_Subscript_Tests, Invalid) {
variant = JsonVariant::invalid();
EXPECT_EQ(0, variant.size());
EXPECT_FALSE(variant["0"].success());
EXPECT_FALSE(variant[0].success());
_variant = JsonVariant::invalid();
EXPECT_EQ(0, _variant.size());
EXPECT_FALSE(_variant["0"].success());
EXPECT_FALSE(_variant[0].success());
}
TEST_F(JsonVariant_Subscript_Tests, String) {
variant = "hello world";
EXPECT_EQ(0, variant.size());
EXPECT_FALSE(variant["0"].success());
EXPECT_FALSE(variant[0].success());
_variant = "hello world";
EXPECT_EQ(0, _variant.size());
EXPECT_FALSE(_variant["0"].success());
EXPECT_FALSE(_variant[0].success());
}

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -41,6 +41,12 @@ TEST_F(QuotedString_ExtractFrom_Tests, NoQuotes) {
resultMustBe(0);
}
TEST_F(QuotedString_ExtractFrom_Tests, MissingClosingQuote) {
whenInputIs("\"hello world");
resultMustBe(0);
}
TEST_F(QuotedString_ExtractFrom_Tests, EmptySingleQuotedString) {
whenInputIs("''");

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
@ -7,7 +7,7 @@
#include <gtest/gtest.h>
#include <ArduinoJson.h>
TEST(StaticJsonBuffer_Object_Tests, GrowsWithObject) {
TEST(StaticJsonBuffer_CreateObject_Tests, GrowsWithObject) {
StaticJsonBuffer<JSON_OBJECT_SIZE(3)> json;
JsonObject &obj = json.createObject();
@ -23,21 +23,21 @@ TEST(StaticJsonBuffer_Object_Tests, GrowsWithObject) {
ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size());
}
TEST(StaticJsonBuffer_Object_Tests, SucceedWhenBigEnough) {
TEST(StaticJsonBuffer_CreateObject_Tests, SucceedWhenBigEnough) {
StaticJsonBuffer<JSON_OBJECT_SIZE(0)> json;
JsonObject &object = json.createObject();
ASSERT_TRUE(object.success());
}
TEST(StaticJsonBuffer_Object_Tests, FailsWhenTooSmall) {
TEST(StaticJsonBuffer_CreateObject_Tests, FailsWhenTooSmall) {
StaticJsonBuffer<JSON_OBJECT_SIZE(0) - 1> json;
JsonObject &object = json.createObject();
ASSERT_FALSE(object.success());
}
TEST(StaticJsonBuffer_Object_Tests, ObjectDoesntGrowWhenFull) {
TEST(StaticJsonBuffer_CreateObject_Tests, ObjectDoesntGrowWhenFull) {
StaticJsonBuffer<JSON_OBJECT_SIZE(1)> json;
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
//
// Arduino JSON library
@ -11,18 +11,22 @@ using namespace ArduinoJson::Internals;
class StringBuilderTests : public testing::Test {
protected:
virtual void SetUp() { sb = new StringBuilder(buffer, sizeof(buffer)); }
virtual void SetUp() {
_stringBuilder = new StringBuilder(_buffer, sizeof(_buffer));
}
void print(const char *value) { returnValue = sb->print(value); }
virtual void TearDown() { delete _stringBuilder; }
void outputMustBe(const char *expected) { EXPECT_STREQ(expected, buffer); }
void print(const char *value) { _returnValue = _stringBuilder->print(value); }
void resultMustBe(size_t expected) { EXPECT_EQ(expected, returnValue); }
void outputMustBe(const char *expected) { EXPECT_STREQ(expected, _buffer); }
void resultMustBe(size_t expected) { EXPECT_EQ(expected, _returnValue); }
private:
char buffer[20];
Print *sb;
size_t returnValue;
char _buffer[20];
Print *_stringBuilder;
size_t _returnValue;
};
TEST_F(StringBuilderTests, InitialState) { outputMustBe(""); }