mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-06-28 02:41:01 +02:00
Compare commits
63 Commits
Author | SHA1 | Date | |
---|---|---|---|
224918b463 | |||
cbeefa2503 | |||
6d68806633 | |||
ba3617c22f | |||
b7d9bb2765 | |||
74b42e2251 | |||
c0cf9c3fcc | |||
9f3ce18f06 | |||
b9e3255c9e | |||
e657396f65 | |||
929f608f2f | |||
c6a4bfa886 | |||
d5e25b12b8 | |||
7cf6fe6d62 | |||
155dd653e7 | |||
b5c8cd1766 | |||
4967e389c5 | |||
ffbaebd198 | |||
04b8781c8d | |||
5a4d993f7d | |||
823a172681 | |||
a1943e21ed | |||
01c287bc89 | |||
0cf8249b14 | |||
a8265a799d | |||
18bb653f10 | |||
a003a31952 | |||
0a1c27f873 | |||
75f8e25aed | |||
39c506b419 | |||
ef2641b49b | |||
bce101578d | |||
10e466426a | |||
9b90aeffa5 | |||
601b51890f | |||
2524a00a96 | |||
e31d667bec | |||
c161f698fc | |||
92e687303d | |||
f5b83f9314 | |||
5e7b9ec688 | |||
78ae0b8aee | |||
283dffc035 | |||
0aded2a798 | |||
1b5be892b9 | |||
756c279cdc | |||
08d05df00e | |||
c385862be1 | |||
0eff567910 | |||
94d38c0680 | |||
81285f49fe | |||
877096d49d | |||
bfe60243a4 | |||
ca9d606e72 | |||
24d21467dd | |||
41651136bf | |||
5e5f060fc0 | |||
29ab5fc9c2 | |||
80913b8044 | |||
02960f28e4 | |||
8db338ba14 | |||
dadd8986dc | |||
e2016cf65b |
3
.clang-format
Normal file
3
.clang-format
Normal file
@ -0,0 +1,3 @@
|
||||
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
|
||||
BasedOnStyle: Google
|
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.sh text eol=lf
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -3,3 +3,6 @@
|
||||
/build
|
||||
/bin
|
||||
/lib
|
||||
/sftp-config.json
|
||||
.tags
|
||||
.tags_sorted_by_file
|
||||
|
16
.travis.yml
16
.travis.yml
@ -3,10 +3,18 @@ compiler:
|
||||
- gcc
|
||||
- clang
|
||||
before_install:
|
||||
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16"
|
||||
- sleep 3
|
||||
- export DISPLAY=:1.0
|
||||
- wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz
|
||||
- tar xf arduino-1.6.5-linux64.tar.xz
|
||||
- sudo mv arduino-1.6.5 /usr/local/share/arduino
|
||||
- sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino
|
||||
- sudo ln -s $PWD /usr/local/share/arduino/libraries/ArduinoJson
|
||||
- sudo pip install cpp-coveralls
|
||||
before_script:
|
||||
- cmake -DCOVERAGE=true .
|
||||
script:
|
||||
- make && make test
|
||||
- cmake -DCOVERAGE=true . && make && make test
|
||||
- arduino --verify --board arduino:avr:uno $PWD/examples/JsonParserExample/JsonParserExample.ino
|
||||
- arduino --verify --board arduino:avr:uno $PWD/examples/JsonGeneratorExample/JsonGeneratorExample.ino
|
||||
after_success:
|
||||
- coveralls --include include --include src --gcov-options '\-lp'
|
||||
- if [ "$CC" = "gcc" ]; then coveralls --exclude third-party --gcov-options '\-lp'; fi
|
||||
|
103
CHANGELOG.md
103
CHANGELOG.md
@ -1,5 +1,102 @@
|
||||
Arduino JSON: change log
|
||||
========================
|
||||
ArduinoJson: change log
|
||||
=======================
|
||||
|
||||
v5.0.6
|
||||
------
|
||||
|
||||
* Added parameter to `DynamicJsonBuffer` constructor to set initial size (issue #152)
|
||||
* Fixed warning about library category in Arduino 1.6.6 (issue #147)
|
||||
* Examples: Added a loop to wait for serial port to be ready (issue #156)
|
||||
|
||||
v5.0.5
|
||||
------
|
||||
|
||||
* Added overload `JsonObjectSuscript::set(value, decimals)` (issue #143)
|
||||
* Use `float` instead of `double` to reduce the size of `JsonVariant` (issue #134)
|
||||
|
||||
v5.0.4
|
||||
------
|
||||
|
||||
* Fixed ambiguous overload with `JsonArraySubscript` and `JsonObjectSubscript` (issue #122)
|
||||
|
||||
v5.0.3
|
||||
------
|
||||
|
||||
* Fixed `printTo(String)` which wrote numbers instead of strings (issue #120)
|
||||
* Fixed return type of `JsonArray::is<T>()` and some others (issue #121)
|
||||
|
||||
v5.0.2
|
||||
------
|
||||
|
||||
* Fixed segmentation fault in `parseObject(String)` and `parseArray(String)`, when the
|
||||
`StaticJsonBuffer` is too small to hold a copy of the string
|
||||
* Fixed Clang warning "register specifier is deprecated" (issue #102)
|
||||
* Fixed GCC warning "declaration shadows a member" (issue #103)
|
||||
* Fixed memory alignment, which made ESP8266 crash (issue #104)
|
||||
* Fixed compilation on Visual Studio 2010 and 2012 (issue #107)
|
||||
|
||||
v5.0.1
|
||||
------
|
||||
|
||||
* Fixed compilation with Arduino 1.0.6 (issue #99)
|
||||
|
||||
v5.0.0
|
||||
------
|
||||
|
||||
* Added support of `String` class (issues #55, #56, #70, #77)
|
||||
* Added `JsonBuffer::strdup()` to make a copy of a string (issues #10, #57)
|
||||
* Implicitly call `strdup()` for `String` but not for `char*` (issues #84, #87)
|
||||
* Added support of non standard JSON input (issue #44)
|
||||
* Added support of comments in JSON input (issue #88)
|
||||
* Added implicit cast between numerical types (issues #64, #69, #93)
|
||||
* Added ability to read number values as string (issue #90)
|
||||
* Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66)
|
||||
* Switched to new the library layout (requires Arduino 1.0.6 or above)
|
||||
|
||||
**BREAKING CHANGES**:
|
||||
- `JsonObject::add()` was renamed to `set()`
|
||||
- `JsonArray::at()` and `JsonObject::at()` were renamed to `get()`
|
||||
- Number of digits of floating point value are now set with `double_with_n_digits()`
|
||||
|
||||
**Personal note about the `String` class**:
|
||||
Support of the `String` class has been added to the library because many people use it in their programs.
|
||||
However, you should not see this as an invitation to use the `String` class.
|
||||
The `String` class is **bad** because it uses dynamic memory allocation.
|
||||
Compared to static allocation, it compiles to a bigger, slower program, and is less predictable.
|
||||
You certainly don't want that in an embedded environment!
|
||||
|
||||
v4.6
|
||||
----
|
||||
|
||||
* Fixed segmentation fault in `DynamicJsonBuffer` when memory allocation fails (issue #92)
|
||||
|
||||
v4.5
|
||||
----
|
||||
|
||||
* Fixed buffer overflow when input contains a backslash followed by a terminator (issue #81)
|
||||
|
||||
**Upgrading is recommended** since previous versions contain a potential security risk.
|
||||
|
||||
Special thanks to [Giancarlo Canales Barreto](https://github.com/gcanalesb) for finding this nasty bug.
|
||||
|
||||
v4.4
|
||||
----
|
||||
|
||||
* Added `JsonArray::measureLength()` and `JsonObject::measureLength()` (issue #75)
|
||||
|
||||
v4.3
|
||||
----
|
||||
|
||||
* Added `JsonArray::removeAt()` to remove an element of an array (issue #58)
|
||||
* Fixed stack-overflow in `DynamicJsonBuffer` when parsing huge JSON files (issue #65)
|
||||
* Fixed wrong return value of `parseArray()` and `parseObject()` when allocation fails (issue #68)
|
||||
|
||||
v4.2
|
||||
----
|
||||
|
||||
* Switched back to old library layout (issues #39, #43 and #45)
|
||||
* Removed global new operator overload (issue #40, #45 and #46)
|
||||
* Added an example with EthernetServer
|
||||
|
||||
v4.1
|
||||
----
|
||||
@ -114,4 +211,4 @@ v1.1
|
||||
v1.0
|
||||
----
|
||||
|
||||
Initial release
|
||||
Initial release
|
||||
|
@ -12,9 +12,8 @@ if(MSVC)
|
||||
endif()
|
||||
|
||||
if(${COVERAGE})
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -coverage")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -coverage")
|
||||
set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(test)
|
||||
|
@ -1,10 +1,10 @@
|
||||
The MIT License (MIT)
|
||||
---------------------
|
||||
|
||||
Copyright © 2014 Benoit BLANCHON
|
||||
Copyright © 2014-2015 Benoit BLANCHON
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
88
README.md
88
README.md
@ -1,67 +1,81 @@
|
||||
Arduino JSON library
|
||||
====================
|
||||
|
||||
[](https://travis-ci.org/bblanchon/ArduinoJson) [](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master)
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master) [](https://travis-ci.org/bblanchon/ArduinoJson) [](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master)
|
||||
|
||||
*An elegant and efficient JSON library for embedded systems.*
|
||||
|
||||
It's design to have the most intuitive API, the smallest footprint and works without any allocation on the heap (no malloc).
|
||||
It's designed to have the most intuitive API, the smallest footprint and works without any allocation on the heap (no malloc).
|
||||
|
||||
It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* JSON decoding
|
||||
* JSON decoding (comments are supported)
|
||||
* JSON encoding (with optional indentation)
|
||||
* Elegant API, very easy to use
|
||||
* Fixed memory allocation (no malloc)
|
||||
* Elegant API, very easy to use
|
||||
* Efficient (no malloc, nor copy)
|
||||
* Portable (written in C++98)
|
||||
* Self-contained (no external dependency)
|
||||
* Small footprint
|
||||
* MIT License
|
||||
|
||||
Works on
|
||||
--------
|
||||
|
||||
* All Arduino boards
|
||||
* ESP8266
|
||||
* Teensy
|
||||
* Computers (Windows, Linux, OSX...)
|
||||
|
||||
Quick start
|
||||
-----------
|
||||
|
||||
#### Decoding / Parsing
|
||||
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
```c++
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
```
|
||||
|
||||
#### Encoding / Generating
|
||||
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
```c++
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
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
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
root.printTo(Serial);
|
||||
// This prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
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
|
||||
|
||||
root.printTo(Serial);
|
||||
// This prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
```
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
The documentation is available online in the [Arduino JSON wiki](https://github.com/bblanchon/ArduinoJson/wiki)
|
||||
The documentation is available online in the [Arduino JSON wiki](https://github.com/bblanchon/ArduinoJson/wiki)
|
||||
|
||||
Testimonials
|
||||
------------
|
||||
|
||||
From Arduino's Forum user `jflaplante`:
|
||||
> I tried aJson json-arduino before trying your library. I always ran into memory problem after a while.
|
||||
> I tried aJson json-arduino before trying your library. I always ran into memory problem after a while.
|
||||
> I have no such problem so far with your library. It is working perfectly with my web services.
|
||||
|
||||
From Arduino's Forum user `gbathree`:
|
||||
@ -76,6 +90,26 @@ From GitHub user `zacsketches`:
|
||||
> I've been watching you consistently develop this library over the past six months, and I used it today for a publish and subscribe architecture designed to help hobbyists move into more advanced robotics. Your library allowed me to implement remote subscription in order to facilitate multi-processor robots.
|
||||
> ArduinoJson saved me a week's worth of time!!
|
||||
|
||||
[From Reddit user `erm_what_`](https://www.reddit.com/r/arduino/comments/3jj6ep/announcing_arduinojson_50/cusjk8c):
|
||||
|
||||
> This is a great library and I wouldn't be able to do the project I'm doing without it. I completely recommend it.
|
||||
|
||||
[From Reddit user `makerhacks`](https://www.reddit.com/r/arduino/comments/3jj6ep/announcing_arduinojson_50/cusqg7b):
|
||||
|
||||
> I am just starting an ESP8266 clock project and now I can output JSON from my server script and interpret it painlessly.
|
||||
|
||||
Donators
|
||||
--------
|
||||
|
||||
Special thanks to the following persons and companies who made generous donations to the library author:
|
||||
|
||||
* Robert Murphy
|
||||
* Surge Communications
|
||||
* Alex Scott
|
||||
* Firepick Services LLC
|
||||
* A B Doodkorte
|
||||
* Scott Smith
|
||||
|
||||
---
|
||||
|
||||
Found this library useful? [Help me back with a donation!](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=donate%40benoitblanchon%2efr&lc=GB&item_name=Benoit%20Blanchon&item_number=Arduino%20JSON¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted) :smile:
|
||||
Found this library useful? Please star this project or [help me back with a donation!](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=donate%40benoitblanchon%2efr&lc=GB&item_name=Benoit%20Blanchon&item_number=Arduino%20JSON¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted) :smile:
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* Arduino JSON library - IndentedPrint example
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
@ -9,6 +10,9 @@ using namespace ArduinoJson::Internals;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
// wait serial port initialization
|
||||
}
|
||||
|
||||
IndentedPrint serial(Serial);
|
||||
serial.setTabSize(4);
|
||||
@ -27,4 +31,4 @@ void setup() {
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -8,6 +8,9 @@
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
// wait serial port initialization
|
||||
}
|
||||
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
@ -16,8 +19,8 @@ void setup() {
|
||||
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
|
||||
data.add(double_with_n_digits(48.756080, 6));
|
||||
data.add(double_with_n_digits(2.302038, 6));
|
||||
|
||||
root.printTo(Serial);
|
||||
// This prints:
|
||||
@ -39,4 +42,4 @@ void setup() {
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -8,6 +8,9 @@
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
// wait serial port initialization
|
||||
}
|
||||
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
@ -34,4 +37,4 @@ void setup() {
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
}
|
||||
|
74
examples/JsonServer/JsonServer.ino
Normal file
74
examples/JsonServer/JsonServer.ino
Normal 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();
|
||||
}
|
||||
}
|
55
examples/JsonUdpBeacon/JsonUdpBeacon.ino
Normal file
55
examples/JsonUdpBeacon/JsonUdpBeacon.ino
Normal 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);
|
||||
}
|
@ -4,9 +4,9 @@
|
||||
// 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"
|
||||
#include "ArduinoJson/DynamicJsonBuffer.hpp"
|
||||
#include "ArduinoJson/JsonArray.hpp"
|
||||
#include "ArduinoJson/JsonObject.hpp"
|
||||
#include "ArduinoJson/StaticJsonBuffer.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -11,7 +11,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// This class reproduces Arduino's Print
|
||||
// This class reproduces Arduino's Print class
|
||||
class Print {
|
||||
public:
|
||||
virtual ~Print() {}
|
||||
@ -20,6 +20,7 @@ class Print {
|
||||
|
||||
size_t print(const char[]);
|
||||
size_t print(double, int = 2);
|
||||
size_t print(int);
|
||||
size_t print(long);
|
||||
size_t println();
|
||||
};
|
||||
|
27
include/ArduinoJson/Arduino/String.hpp
Normal file
27
include/ArduinoJson/Arduino/String.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef ARDUINO
|
||||
|
||||
#include <string>
|
||||
|
||||
// This class reproduces Arduino's String class
|
||||
class String : public std::string {
|
||||
public:
|
||||
String(const char *cstr = "") : std::string(cstr) {}
|
||||
String(const String &str) : std::string(str) {}
|
||||
explicit String(long);
|
||||
explicit String(int);
|
||||
explicit String(double, unsigned char decimalPlaces = 2);
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#include <WString.h>
|
||||
|
||||
#endif
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -6,62 +6,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonBuffer.hpp"
|
||||
#include "Internals/BlockJsonBuffer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// 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() : _next(NULL), _size(0) {}
|
||||
|
||||
~DynamicJsonBuffer() { delete _next; }
|
||||
|
||||
size_t size() const { return _size + (_next ? _next->size() : 0); }
|
||||
|
||||
size_t blockCount() const { return 1 + (_next ? _next->blockCount() : 0); }
|
||||
|
||||
static const size_t BLOCK_CAPACITY = 32;
|
||||
|
||||
protected:
|
||||
virtual void* alloc(size_t bytes) {
|
||||
if (canAllocInThisBlock(bytes))
|
||||
return allocInThisBlock(bytes);
|
||||
else if (canAllocInOtherBlocks(bytes))
|
||||
return allocInOtherBlocks(bytes);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
bool canAllocInThisBlock(size_t bytes) const {
|
||||
return _size + bytes <= BLOCK_CAPACITY;
|
||||
}
|
||||
|
||||
void* allocInThisBlock(size_t bytes) {
|
||||
void* p = _buffer + _size;
|
||||
_size += bytes;
|
||||
return p;
|
||||
}
|
||||
|
||||
bool canAllocInOtherBlocks(size_t bytes) const {
|
||||
// by design a DynamicJsonBuffer can't alloc a block bigger than
|
||||
// BLOCK_CAPACITY
|
||||
return bytes <= BLOCK_CAPACITY;
|
||||
}
|
||||
|
||||
void* allocInOtherBlocks(size_t bytes) {
|
||||
if (!_next) {
|
||||
_next = new DynamicJsonBuffer();
|
||||
if (!_next) return NULL;
|
||||
}
|
||||
return _next->alloc(bytes);
|
||||
}
|
||||
|
||||
DynamicJsonBuffer* _next;
|
||||
size_t _size;
|
||||
uint8_t _buffer[BLOCK_CAPACITY];
|
||||
};
|
||||
typedef Internals::BlockJsonBuffer<Internals::DefaultAllocator>
|
||||
DynamicJsonBuffer;
|
||||
}
|
||||
|
94
include/ArduinoJson/Internals/BlockJsonBuffer.hpp
Normal file
94
include/ArduinoJson/Internals/BlockJsonBuffer.hpp
Normal file
@ -0,0 +1,94 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
class DefaultAllocator {
|
||||
public:
|
||||
void* allocate(size_t size) { return malloc(size); }
|
||||
void deallocate(void* pointer) { free(pointer); }
|
||||
};
|
||||
|
||||
template <typename TAllocator>
|
||||
class BlockJsonBuffer : public JsonBuffer {
|
||||
struct Block;
|
||||
struct EmptyBlock {
|
||||
Block* next;
|
||||
size_t capacity;
|
||||
size_t size;
|
||||
};
|
||||
struct Block : EmptyBlock {
|
||||
uint8_t data[1];
|
||||
};
|
||||
|
||||
public:
|
||||
BlockJsonBuffer(size_t initialSize = 256)
|
||||
: _head(NULL), _nextBlockSize(initialSize) {}
|
||||
|
||||
~BlockJsonBuffer() {
|
||||
Block* currentBlock = _head;
|
||||
|
||||
while (currentBlock != NULL) {
|
||||
Block* nextBlock = currentBlock->next;
|
||||
_allocator.deallocate(currentBlock);
|
||||
currentBlock = nextBlock;
|
||||
}
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
size_t total = 0;
|
||||
for (const Block* b = _head; b; b = b->next) total += b->size;
|
||||
return total;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void* alloc(size_t bytes) {
|
||||
return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
|
||||
}
|
||||
|
||||
private:
|
||||
bool canAllocInHead(size_t bytes) const {
|
||||
return _head != NULL && _head->size + bytes <= _head->capacity;
|
||||
}
|
||||
|
||||
void* allocInHead(size_t bytes) {
|
||||
void* p = _head->data + _head->size;
|
||||
_head->size += round_size_up(bytes);
|
||||
return p;
|
||||
}
|
||||
|
||||
void* allocInNewBlock(size_t bytes) {
|
||||
size_t capacity = _nextBlockSize;
|
||||
if (_head != NULL) capacity = _head->capacity * 2;
|
||||
if (bytes > capacity) capacity = bytes;
|
||||
if (!addNewBlock(capacity)) return NULL;
|
||||
_nextBlockSize *= 2;
|
||||
return allocInHead(bytes);
|
||||
}
|
||||
|
||||
bool addNewBlock(size_t capacity) {
|
||||
size_t bytes = sizeof(EmptyBlock) + capacity;
|
||||
Block* block = static_cast<Block*>(_allocator.allocate(bytes));
|
||||
if (block == NULL) return false;
|
||||
block->capacity = capacity;
|
||||
block->size = 0;
|
||||
block->next = _head;
|
||||
_head = block;
|
||||
return true;
|
||||
}
|
||||
|
||||
TAllocator _allocator;
|
||||
Block* _head;
|
||||
size_t _nextBlockSize;
|
||||
};
|
||||
}
|
||||
}
|
13
include/ArduinoJson/Internals/Comments.hpp
Normal file
13
include/ArduinoJson/Internals/Comments.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
const char *skipSpacesAndComments(const char *ptr);
|
||||
}
|
||||
}
|
20
include/ArduinoJson/Internals/DummyPrint.hpp
Normal file
20
include/ArduinoJson/Internals/DummyPrint.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A dummy Print implementation used in JsonPrintable::measureLength()
|
||||
class DummyPrint : public Print {
|
||||
public:
|
||||
virtual size_t write(uint8_t) { return 1; }
|
||||
};
|
||||
}
|
||||
}
|
32
include/ArduinoJson/Internals/DynamicStringBuilder.hpp
Normal file
32
include/ArduinoJson/Internals/DynamicStringBuilder.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
#include "../Arduino/String.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A Print implementation that allows to write in a String
|
||||
class DynamicStringBuilder : public Print {
|
||||
public:
|
||||
DynamicStringBuilder(String &str) : _str(str) {}
|
||||
|
||||
virtual size_t write(uint8_t c) {
|
||||
// Need to cast to char, otherwise String will print a number (issue #120)
|
||||
_str += static_cast<char>(c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private:
|
||||
DynamicStringBuilder &operator=(const DynamicStringBuilder &);
|
||||
|
||||
String &_str;
|
||||
};
|
||||
}
|
||||
}
|
39
include/ArduinoJson/Internals/Encoding.hpp
Normal file
39
include/ArduinoJson/Internals/Encoding.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class Encoding {
|
||||
public:
|
||||
// Optimized for code size on a 8-bit AVR
|
||||
static char escapeChar(char c) {
|
||||
const char *p = _escapeTable;
|
||||
while (p[0] && p[1] != c) {
|
||||
p += 2;
|
||||
}
|
||||
return p[0];
|
||||
}
|
||||
|
||||
// Optimized for code size on a 8-bit AVR
|
||||
static char unescapeChar(char c) {
|
||||
const char *p = _escapeTable + 4;
|
||||
for (;;) {
|
||||
if (p[0] == '\0') return c;
|
||||
if (p[0] == c) return p[1];
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static const char _escapeTable[];
|
||||
};
|
||||
}
|
||||
}
|
13
include/ArduinoJson/Internals/ForceInline.hpp
Normal file
13
include/ArduinoJson/Internals/ForceInline.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define FORCE_INLINE __forceinline
|
||||
#else
|
||||
#define FORCE_INLINE __attribute__((always_inline))
|
||||
#endif
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
|
24
include/ArduinoJson/Internals/JsonBufferAllocated.hpp
Normal file
24
include/ArduinoJson/Internals/JsonBufferAllocated.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
// 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() {
|
||||
if (!jsonBuffer) return NULL;
|
||||
return jsonBuffer->alloc(n);
|
||||
}
|
||||
|
||||
void operator delete(void *, JsonBuffer *) throw() {}
|
||||
};
|
||||
}
|
||||
}
|
20
include/ArduinoJson/Internals/JsonFloat.hpp
Normal file
20
include/ArduinoJson/Internals/JsonFloat.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
#ifdef ARDUINO
|
||||
// On embedded platform, we with use float instead of double to keep JsonVariant
|
||||
// small (issue #134)
|
||||
typedef float JsonFloat;
|
||||
#else
|
||||
typedef double JsonFloat;
|
||||
#endif
|
||||
}
|
||||
}
|
13
include/ArduinoJson/Internals/JsonInteger.hpp
Normal file
13
include/ArduinoJson/Internals/JsonInteger.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
typedef long JsonInteger;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -18,24 +18,28 @@ namespace Internals {
|
||||
class JsonParser {
|
||||
public:
|
||||
JsonParser(JsonBuffer *buffer, char *json, uint8_t nestingLimit)
|
||||
: _buffer(buffer), _ptr(json), _nestingLimit(nestingLimit) {}
|
||||
: _buffer(buffer),
|
||||
_readPtr(json ? json : ""),
|
||||
_writePtr(json),
|
||||
_nestingLimit(nestingLimit) {}
|
||||
|
||||
JsonArray &parseArray();
|
||||
JsonObject &parseObject();
|
||||
|
||||
private:
|
||||
bool skip(char charToSkip);
|
||||
bool skip(const char *wordToSkip);
|
||||
void skipSpaces();
|
||||
|
||||
void parseAnythingTo(JsonVariant &destination);
|
||||
inline void parseBooleanTo(JsonVariant &destination);
|
||||
inline void parseNullTo(JsonVariant &destination);
|
||||
inline void parseNumberTo(JsonVariant &destination);
|
||||
inline const char *parseString();
|
||||
const char *parseString();
|
||||
bool parseAnythingTo(JsonVariant *destination);
|
||||
FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination);
|
||||
|
||||
inline bool parseArrayTo(JsonVariant *destination);
|
||||
inline bool parseObjectTo(JsonVariant *destination);
|
||||
inline bool parseStringTo(JsonVariant *destination);
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
char *_ptr;
|
||||
const char *_readPtr;
|
||||
char *_writePtr;
|
||||
uint8_t _nestingLimit;
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -6,10 +6,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DummyPrint.hpp"
|
||||
#include "IndentedPrint.hpp"
|
||||
#include "JsonWriter.hpp"
|
||||
#include "Prettyfier.hpp"
|
||||
#include "StringBuilder.hpp"
|
||||
#include "StaticStringBuilder.hpp"
|
||||
#include "DynamicStringBuilder.hpp"
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include "StreamPrintAdapter.hpp"
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
@ -27,8 +33,21 @@ class JsonPrintable {
|
||||
return writer.bytesWritten();
|
||||
}
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
std::ostream &printTo(std::ostream &os) const {
|
||||
StreamPrintAdapter adapter(os);
|
||||
printTo(adapter);
|
||||
return os;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t printTo(char *buffer, size_t bufferSize) const {
|
||||
StringBuilder sb(buffer, bufferSize);
|
||||
StaticStringBuilder sb(buffer, bufferSize);
|
||||
return printTo(sb);
|
||||
}
|
||||
|
||||
size_t printTo(String &str) const {
|
||||
DynamicStringBuilder sb(str);
|
||||
return printTo(sb);
|
||||
}
|
||||
|
||||
@ -38,7 +57,7 @@ class JsonPrintable {
|
||||
}
|
||||
|
||||
size_t prettyPrintTo(char *buffer, size_t bufferSize) const {
|
||||
StringBuilder sb(buffer, bufferSize);
|
||||
StaticStringBuilder sb(buffer, bufferSize);
|
||||
return prettyPrintTo(sb);
|
||||
}
|
||||
|
||||
@ -47,8 +66,30 @@ class JsonPrintable {
|
||||
return prettyPrintTo(indentedPrint);
|
||||
}
|
||||
|
||||
size_t prettyPrintTo(String &str) const {
|
||||
DynamicStringBuilder sb(str);
|
||||
return prettyPrintTo(sb);
|
||||
}
|
||||
|
||||
size_t measureLength() const {
|
||||
DummyPrint dp;
|
||||
return printTo(dp);
|
||||
}
|
||||
|
||||
size_t measurePrettyLength() const {
|
||||
DummyPrint dp;
|
||||
return prettyPrintTo(dp);
|
||||
}
|
||||
|
||||
private:
|
||||
const T &downcast() const { return *static_cast<const T *>(this); }
|
||||
};
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
template <typename T>
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonPrintable<T> &v) {
|
||||
return v.printTo(os);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -6,6 +6,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonFloat.hpp"
|
||||
#include "JsonInteger.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations
|
||||
@ -13,16 +16,14 @@ class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
// A union that defines the actual content of a JsonVariant.
|
||||
// The enum JsonVariantType determines which member is in use.
|
||||
union JsonVariantContent {
|
||||
bool asBoolean;
|
||||
double asDouble; // asDouble is also used for float
|
||||
long asLong; // asLong is also used for char, short and int
|
||||
const char* asString; // asString can be null
|
||||
JsonArray* asArray; // asArray cannot be null
|
||||
JsonObject* asObject; // asObject cannot be null
|
||||
JsonFloat asFloat; // used for double and float
|
||||
JsonInteger asInteger; // used for bool, char, short, int and longs
|
||||
const char* asString; // asString can be null
|
||||
JsonArray* asArray; // asArray cannot be null
|
||||
JsonObject* asObject; // asObject cannot be null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -7,26 +7,29 @@
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
// Enumerated type to know the current type of a JsonVariant.
|
||||
// The value determines which member of JsonVariantContent is used.
|
||||
enum JsonVariantType {
|
||||
JSON_INVALID, // a special state for JsonVariant::invalid()
|
||||
JSON_UNDEFINED, // the JsonVariant has not been initialized
|
||||
JSON_UNPARSED, // the JsonVariant contains an unparsed string
|
||||
JSON_STRING, // the JsonVariant stores a const char*
|
||||
JSON_BOOLEAN, // the JsonVariant stores a bool
|
||||
JSON_INTEGER, // the JsonVariant stores an integer
|
||||
JSON_ARRAY, // the JsonVariant stores a pointer to a JsonArray
|
||||
JSON_OBJECT, // the JsonVariant stores a pointer to a JsonObject
|
||||
JSON_BOOLEAN, // the JsonVariant stores a bool
|
||||
JSON_STRING, // the JsonVariant stores a const char*
|
||||
JSON_LONG, // the JsonVariant stores a long
|
||||
|
||||
// The following values are reserved for double values
|
||||
// The following values are reserved for float values
|
||||
// Multiple values are used for double, depending on the number of decimal
|
||||
// digits that must be printed in the JSON output.
|
||||
// This little trick allow to save one extra member in JsonVariant
|
||||
JSON_DOUBLE_0_DECIMALS
|
||||
// JSON_DOUBLE_1_DECIMAL
|
||||
// JSON_DOUBLE_2_DECIMALS
|
||||
JSON_FLOAT_0_DECIMALS
|
||||
// JSON_FLOAT_1_DECIMAL
|
||||
// JSON_FLOAT_2_DECIMALS
|
||||
// ...
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -7,7 +7,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
#include "QuotedString.hpp"
|
||||
#include "Encoding.hpp"
|
||||
#include "ForceInline.hpp"
|
||||
#include "JsonFloat.hpp"
|
||||
#include "JsonInteger.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
@ -26,7 +29,7 @@ class JsonWriter {
|
||||
// Returns the number of bytes sent to the Print implementation.
|
||||
// This is very handy for implementations of printTo() that must return the
|
||||
// number of bytes written.
|
||||
size_t bytesWritten() { return _length; }
|
||||
size_t bytesWritten() const { return _length; }
|
||||
|
||||
void beginArray() { write('['); }
|
||||
void endArray() { write(']'); }
|
||||
@ -37,22 +40,39 @@ class JsonWriter {
|
||||
void writeColon() { write(':'); }
|
||||
void writeComma() { write(','); }
|
||||
|
||||
void writeBoolean(bool value) { write(value ? "true" : "false"); }
|
||||
|
||||
void writeString(const char *value) {
|
||||
_length += QuotedString::printTo(value, _sink);
|
||||
if (!value) {
|
||||
write("null");
|
||||
} else {
|
||||
write('\"');
|
||||
while (*value) writeChar(*value++);
|
||||
write('\"');
|
||||
}
|
||||
}
|
||||
|
||||
void writeLong(long value) { _length += _sink.print(value); }
|
||||
|
||||
void writeBoolean(bool value) {
|
||||
_length += _sink.print(value ? "true" : "false");
|
||||
void writeChar(char c) {
|
||||
char specialChar = Encoding::escapeChar(c);
|
||||
if (specialChar) {
|
||||
write('\\');
|
||||
write(specialChar);
|
||||
} else {
|
||||
write(c);
|
||||
}
|
||||
}
|
||||
void writeDouble(double value, uint8_t decimals) {
|
||||
|
||||
void writeInteger(JsonInteger value) { _length += _sink.print(value); }
|
||||
|
||||
void writeFloat(JsonFloat value, uint8_t decimals) {
|
||||
_length += _sink.print(value, decimals);
|
||||
}
|
||||
|
||||
void writeRaw(const char *s) { return write(s); }
|
||||
|
||||
protected:
|
||||
void write(char c) { _length += _sink.write(c); }
|
||||
void write(const char *s) { _length += _sink.print(s); }
|
||||
FORCE_INLINE void write(const char *s) { _length += _sink.print(s); }
|
||||
|
||||
Print &_sink;
|
||||
size_t _length;
|
||||
|
@ -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 {
|
||||
@ -40,7 +39,7 @@ class List {
|
||||
|
||||
// Returns the numbers of elements in the list.
|
||||
// For a JsonObject, it would return the number of key-value pairs
|
||||
int size() const;
|
||||
size_t size() const;
|
||||
|
||||
iterator begin() { return iterator(_firstNode); }
|
||||
iterator end() { return iterator(NULL); }
|
||||
@ -49,22 +48,7 @@ class List {
|
||||
const_iterator end() const { return const_iterator(NULL); }
|
||||
|
||||
protected:
|
||||
node_type *createNode() {
|
||||
if (!_buffer) return NULL;
|
||||
void *ptr = _buffer->alloc(sizeof(node_type));
|
||||
return ptr ? new (ptr) node_type() : NULL;
|
||||
}
|
||||
|
||||
void addNode(node_type *nodeToAdd) {
|
||||
if (_firstNode) {
|
||||
node_type *lastNode = _firstNode;
|
||||
while (lastNode->next) lastNode = lastNode->next;
|
||||
lastNode->next = nodeToAdd;
|
||||
} else {
|
||||
_firstNode = nodeToAdd;
|
||||
}
|
||||
}
|
||||
|
||||
node_type *addNewNode();
|
||||
void removeNode(node_type *nodeToRemove);
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -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
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -31,7 +31,7 @@ class Prettyfier : public Print {
|
||||
|
||||
size_t handleBlockClose(uint8_t);
|
||||
size_t handleBlockOpen(uint8_t);
|
||||
size_t handleColumn();
|
||||
size_t handleColon();
|
||||
size_t handleComma();
|
||||
size_t handleQuoteOpen();
|
||||
size_t handleNormalChar(uint8_t);
|
||||
|
@ -1,29 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// An helper class to print and extract doubly-quoted strings
|
||||
class QuotedString {
|
||||
public:
|
||||
// Writes a doubly-quote string to a Print implementation.
|
||||
// It adds the double quotes (") at the beginning and the end of the string.
|
||||
// It escapes the special characters as required by the JSON specifications.
|
||||
static size_t printTo(const char *, Print &);
|
||||
|
||||
// Reads a doubly-quoted string from a buffer.
|
||||
// It removes the double quotes (").
|
||||
// It unescapes the special character as required by the JSON specification,
|
||||
// with the exception of the Unicode characters (\u0000).
|
||||
static char *extractFrom(char *input, char **end);
|
||||
};
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -12,9 +12,9 @@ namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A Print implementation that allows to write in a char[]
|
||||
class StringBuilder : public Print {
|
||||
class StaticStringBuilder : public Print {
|
||||
public:
|
||||
StringBuilder(char *buf, int size)
|
||||
StaticStringBuilder(char *buf, size_t size)
|
||||
: buffer(buf), capacity(size - 1), length(0) {
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
@ -23,8 +23,8 @@ class StringBuilder : public Print {
|
||||
|
||||
private:
|
||||
char *buffer;
|
||||
int capacity;
|
||||
int length;
|
||||
size_t capacity;
|
||||
size_t length;
|
||||
};
|
||||
}
|
||||
}
|
34
include/ArduinoJson/Internals/StreamPrintAdapter.hpp
Normal file
34
include/ArduinoJson/Internals/StreamPrintAdapter.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class StreamPrintAdapter : public Print {
|
||||
public:
|
||||
explicit StreamPrintAdapter(std::ostream& os) : _os(os) {}
|
||||
|
||||
virtual size_t write(uint8_t c) {
|
||||
_os << static_cast<char>(c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private:
|
||||
// cannot be assigned
|
||||
StreamPrintAdapter& operator=(const StreamPrintAdapter&);
|
||||
|
||||
std::ostream& _os;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ARDUINOJSON_ENABLE_STD_STREAM
|
20
include/ArduinoJson/Internals/Unparsed.hpp
Normal file
20
include/ArduinoJson/Internals/Unparsed.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
class Unparsed {
|
||||
public:
|
||||
explicit Unparsed(const char* str) : _str(str) {}
|
||||
operator const char*() const { return _str; }
|
||||
|
||||
private:
|
||||
const char* _str;
|
||||
};
|
||||
}
|
||||
}
|
@ -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"
|
||||
@ -21,6 +22,7 @@ namespace ArduinoJson {
|
||||
// Forward declarations
|
||||
class JsonObject;
|
||||
class JsonBuffer;
|
||||
class JsonArraySubscript;
|
||||
|
||||
// An array of JsonVariant.
|
||||
//
|
||||
@ -30,36 +32,69 @@ 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> {
|
||||
// JsonBuffer is a friend because it needs to call the private constructor.
|
||||
friend class JsonBuffer;
|
||||
|
||||
public Internals::List<JsonVariant>,
|
||||
public Internals::JsonBufferAllocated {
|
||||
public:
|
||||
// Returns the JsonVariant at the specified index (synonym for operator[])
|
||||
JsonVariant &at(int index) const;
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
// You should not call this constructor directly.
|
||||
// Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray().
|
||||
explicit JsonArray(JsonBuffer *buffer)
|
||||
: Internals::List<JsonVariant>(buffer) {}
|
||||
|
||||
// Returns the JsonVariant at the specified index (synonym for at())
|
||||
JsonVariant &operator[](int index) const { return at(index); }
|
||||
// Gets the value at the specified index
|
||||
FORCE_INLINE JsonVariant operator[](size_t index) const;
|
||||
|
||||
// Adds an uninitialized JsonVariant at the end of the array.
|
||||
// Return a reference or JsonVariant::invalid() if allocation fails.
|
||||
JsonVariant &add();
|
||||
// Gets or sets the value at specified index
|
||||
FORCE_INLINE JsonArraySubscript operator[](size_t index);
|
||||
|
||||
// Adds the specified value at the end of the array.
|
||||
FORCE_INLINE bool add(bool value);
|
||||
FORCE_INLINE bool add(float value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool add(double value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool add(signed char value);
|
||||
FORCE_INLINE bool add(signed long value);
|
||||
FORCE_INLINE bool add(signed int value);
|
||||
FORCE_INLINE bool add(signed short value);
|
||||
FORCE_INLINE bool add(unsigned char value);
|
||||
FORCE_INLINE bool add(unsigned long value);
|
||||
FORCE_INLINE bool add(unsigned int value);
|
||||
FORCE_INLINE bool add(unsigned short value);
|
||||
FORCE_INLINE bool add(const char *value);
|
||||
FORCE_INLINE bool add(const String &value);
|
||||
FORCE_INLINE bool add(JsonArray &array);
|
||||
FORCE_INLINE bool add(JsonObject &object);
|
||||
template <typename T>
|
||||
void add(T value) {
|
||||
add().set(value);
|
||||
}
|
||||
FORCE_INLINE bool add(const T &value);
|
||||
|
||||
// Adds the specified double value at the end of the array.
|
||||
// The value will be printed with the specified number of decimal digits.
|
||||
void add(double value, uint8_t decimals) { add().set(value, decimals); }
|
||||
// Sets the value at specified index.
|
||||
FORCE_INLINE void set(size_t index, bool value);
|
||||
FORCE_INLINE void set(size_t index, float value, uint8_t decimals = 2);
|
||||
FORCE_INLINE void set(size_t index, double value, uint8_t decimals = 2);
|
||||
FORCE_INLINE void set(size_t index, signed char value);
|
||||
FORCE_INLINE void set(size_t index, signed long value);
|
||||
FORCE_INLINE void set(size_t index, signed int value);
|
||||
FORCE_INLINE void set(size_t index, signed short value);
|
||||
FORCE_INLINE void set(size_t index, unsigned char value);
|
||||
FORCE_INLINE void set(size_t index, unsigned long value);
|
||||
FORCE_INLINE void set(size_t index, unsigned int value);
|
||||
FORCE_INLINE void set(size_t index, unsigned short value);
|
||||
FORCE_INLINE void set(size_t index, const char *value);
|
||||
FORCE_INLINE void set(size_t index, const String &value);
|
||||
FORCE_INLINE void set(size_t index, JsonArray &array);
|
||||
FORCE_INLINE void set(size_t index, JsonObject &object);
|
||||
template <typename T>
|
||||
FORCE_INLINE void set(size_t index, const T &value);
|
||||
|
||||
// Adds a reference to the specified JsonArray at the end of the array.
|
||||
void add(JsonArray &array) { add().set(array); }
|
||||
// Gets the value at the specified index.
|
||||
FORCE_INLINE JsonVariant get(size_t index) const;
|
||||
|
||||
// Adds a reference to the specified JsonObject at the end of the array.
|
||||
void add(JsonObject &obejct) { add().set(obejct); }
|
||||
// Gets the value at the specified index.
|
||||
template <typename T>
|
||||
FORCE_INLINE T get(size_t index) const;
|
||||
|
||||
// Check the type of the value at specified index.
|
||||
template <typename T>
|
||||
FORCE_INLINE bool is(size_t index) const;
|
||||
|
||||
// Creates a JsonArray and adds a reference at the end of the array.
|
||||
// It's a shortcut for JsonBuffer::createArray() and JsonArray::add()
|
||||
@ -69,6 +104,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(size_t 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.
|
||||
@ -78,11 +116,20 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
void writeTo(Internals::JsonWriter &writer) const;
|
||||
|
||||
private:
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
explicit JsonArray(JsonBuffer *buffer)
|
||||
: Internals::List<JsonVariant>(buffer) {}
|
||||
node_type *getNodeAt(size_t index) const;
|
||||
|
||||
template <typename TValue>
|
||||
void setNodeAt(size_t index, TValue value);
|
||||
|
||||
template <typename TValue>
|
||||
bool addNode(TValue);
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE void setNodeValue(node_type *, T value);
|
||||
|
||||
// The instance returned by JsonArray::invalid()
|
||||
static JsonArray _invalid;
|
||||
};
|
||||
}
|
||||
|
||||
#include "JsonArray.ipp"
|
||||
|
219
include/ArduinoJson/JsonArray.ipp
Normal file
219
include/ArduinoJson/JsonArray.ipp
Normal file
@ -0,0 +1,219 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonArraySubscript.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
inline JsonArraySubscript JsonArray::operator[](size_t index) {
|
||||
return JsonArraySubscript(*this, index);
|
||||
}
|
||||
|
||||
inline JsonVariant JsonArray::operator[](size_t index) const {
|
||||
return get(index);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(bool value) { return addNode<bool>(value); }
|
||||
|
||||
inline bool JsonArray::add(float value, uint8_t decimals) {
|
||||
return addNode<const JsonVariant &>(JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(double value, uint8_t decimals) {
|
||||
return addNode<const JsonVariant &>(JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(signed char value) {
|
||||
return addNode<signed char>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(signed long value) {
|
||||
return addNode<signed long>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(signed int value) {
|
||||
return addNode<signed int>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(signed short value) {
|
||||
return addNode<signed short>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(unsigned char value) {
|
||||
return addNode<unsigned char>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(unsigned long value) {
|
||||
return addNode<unsigned long>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(unsigned int value) {
|
||||
return addNode<unsigned int>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(unsigned short value) {
|
||||
return addNode<unsigned short>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(const char *value) {
|
||||
return addNode<const char *>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(const String &value) {
|
||||
return addNode<const String &>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(JsonArray &array) {
|
||||
return addNode<JsonArray &>(array);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(JsonObject &object) {
|
||||
return addNode<JsonObject &>(object);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool JsonArray::add(const T &variant) {
|
||||
return addNode<const JsonVariant &>(variant);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
inline bool JsonArray::addNode(TValue value) {
|
||||
node_type *node = addNewNode();
|
||||
if (node == NULL) return false;
|
||||
setNodeValue<TValue>(node, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, bool value) {
|
||||
return setNodeAt<bool>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, float value, uint8_t decimals) {
|
||||
return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, double value, uint8_t decimals) {
|
||||
return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, signed char value) {
|
||||
return setNodeAt<signed char>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, signed long value) {
|
||||
return setNodeAt<signed long>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, signed int value) {
|
||||
return setNodeAt<signed int>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, signed short value) {
|
||||
return setNodeAt<signed short>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, unsigned char value) {
|
||||
return setNodeAt<unsigned char>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, unsigned long value) {
|
||||
return setNodeAt<unsigned long>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, unsigned int value) {
|
||||
return setNodeAt<unsigned int>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, unsigned short value) {
|
||||
return setNodeAt<unsigned short>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, const char *value) {
|
||||
return setNodeAt<const char *>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, const String &value) {
|
||||
return setNodeAt<const String &>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, JsonArray &array) {
|
||||
return setNodeAt<JsonArray &>(index, array);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, JsonObject &object) {
|
||||
return setNodeAt<JsonObject &>(index, object);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void JsonArray::set(size_t index, const T &variant) {
|
||||
return setNodeAt<const JsonVariant &>(index, variant);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
inline void JsonArray::setNodeAt(size_t index, TValue value) {
|
||||
node_type *node = getNodeAt(index);
|
||||
if (node == NULL) return;
|
||||
setNodeValue<TValue>(node, value);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
inline void JsonArray::setNodeValue(node_type *node, TValue value) {
|
||||
node->content = value;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void JsonArray::setNodeValue(node_type *node, const String &value) {
|
||||
node->content = _buffer->strdup(value);
|
||||
}
|
||||
|
||||
inline JsonVariant JsonArray::get(size_t index) const {
|
||||
node_type *node = getNodeAt(index);
|
||||
return node ? node->content : JsonVariant();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T JsonArray::get(size_t index) const {
|
||||
node_type *node = getNodeAt(index);
|
||||
return node ? node->content.as<T>() : JsonVariant::invalid<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool JsonArray::is(size_t index) const {
|
||||
node_type *node = getNodeAt(index);
|
||||
return node ? node->content.is<T>() : false;
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline const JsonArraySubscript JsonVariantBase<TImplem>::operator[](
|
||||
int index) const {
|
||||
return asArray()[index];
|
||||
}
|
||||
|
||||
template <>
|
||||
inline JsonArray &JsonVariant::invalid<JsonArray &>() {
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline JsonArray const &JsonVariant::invalid<JsonArray const &>() {
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline JsonArray &JsonVariant::as<JsonArray &>() const {
|
||||
if (_type == Internals::JSON_ARRAY) return *_content.asArray;
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const JsonArray &JsonVariant::as<const JsonArray &>() const {
|
||||
if (_type == Internals::JSON_ARRAY) return *_content.asArray;
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
}
|
72
include/ArduinoJson/JsonArraySubscript.hpp
Normal file
72
include/ArduinoJson/JsonArraySubscript.hpp
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonSubscriptBase.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4522)
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArraySubscript : public JsonSubscriptBase<JsonArraySubscript> {
|
||||
public:
|
||||
FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
|
||||
: _array(array), _index(index) {}
|
||||
|
||||
using JsonSubscriptBase<JsonArraySubscript>::operator=;
|
||||
|
||||
JsonArraySubscript& operator=(const JsonArraySubscript& src) {
|
||||
return assign<const JsonVariant&>(src);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
JsonArraySubscript& operator=(const T& src) {
|
||||
return assign<const JsonVariant&>(src);
|
||||
}
|
||||
|
||||
FORCE_INLINE bool success() const { return _index < _array.size(); }
|
||||
|
||||
FORCE_INLINE operator JsonVariant() const { return _array.get(_index); }
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE T as() const {
|
||||
return _array.get<T>(_index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE bool is() const {
|
||||
return _array.is<T>(_index);
|
||||
}
|
||||
|
||||
void writeTo(Internals::JsonWriter& writer) const {
|
||||
_array.get(_index).writeTo(writer);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
void set(TValue value) {
|
||||
_array.set(_index, value);
|
||||
}
|
||||
|
||||
private:
|
||||
JsonArray& _array;
|
||||
const size_t _index;
|
||||
};
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream& operator<<(std::ostream& os,
|
||||
const JsonArraySubscript& source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -8,6 +8,16 @@
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
#include <stdint.h> // for uint8_t
|
||||
#include <string.h>
|
||||
|
||||
#include "Arduino/String.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
#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;
|
||||
@ -49,6 +59,17 @@ class JsonBuffer {
|
||||
// allocation fails.
|
||||
JsonArray &parseArray(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
|
||||
|
||||
// Same with a const char*.
|
||||
// With this overload, the JsonBuffer will make a copy of the string
|
||||
JsonArray &parseArray(const char *json, uint8_t nesting = DEFAULT_LIMIT) {
|
||||
return parseArray(strdup(json), nesting);
|
||||
}
|
||||
|
||||
// Same as above with a String class
|
||||
JsonArray &parseArray(const String &json, uint8_t nesting = DEFAULT_LIMIT) {
|
||||
return parseArray(json.c_str(), nesting);
|
||||
}
|
||||
|
||||
// Allocates and populate a JsonObject from a JSON string.
|
||||
//
|
||||
// The First argument is a pointer to the JSON string, the memory must be
|
||||
@ -61,20 +82,54 @@ class JsonBuffer {
|
||||
// allocation fails.
|
||||
JsonObject &parseObject(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
|
||||
|
||||
// Same with a const char*.
|
||||
// With this overload, the JsonBuffer will make a copy of the string
|
||||
JsonObject &parseObject(const char *json, uint8_t nesting = DEFAULT_LIMIT) {
|
||||
return parseObject(strdup(json), nesting);
|
||||
}
|
||||
|
||||
// Same as above with a String class
|
||||
JsonObject &parseObject(const String &json, uint8_t nesting = DEFAULT_LIMIT) {
|
||||
return parseObject(json.c_str(), nesting);
|
||||
}
|
||||
|
||||
// Duplicate a string
|
||||
char *strdup(const char *src) {
|
||||
return src ? strdup(src, strlen(src)) : NULL;
|
||||
}
|
||||
char *strdup(const String &src) { return strdup(src.c_str(), src.length()); }
|
||||
|
||||
// Allocates n bytes in the JsonBuffer.
|
||||
// Return a pointer to the allocated memory or NULL if allocation fails.
|
||||
virtual void *alloc(size_t size) = 0;
|
||||
|
||||
protected:
|
||||
// Preserve aligment if nessary
|
||||
static FORCE_INLINE size_t round_size_up(size_t bytes) {
|
||||
#if defined ARDUINO_ARCH_AVR
|
||||
// alignment isn't needed for 8-bit AVR
|
||||
return bytes;
|
||||
#else
|
||||
const size_t x = sizeof(void *) - 1;
|
||||
return (bytes + x) & ~x;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
char *strdup(const char *, size_t);
|
||||
|
||||
// Default value of nesting limit of parseArray() and parseObject().
|
||||
//
|
||||
// The nesting limit is a contain on the level of nesting allowed in the JSON
|
||||
// The nesting limit is a contain on the level of nesting allowed in the
|
||||
// JSON
|
||||
// string.
|
||||
// If set to 0, only a flat array or objects can be parsed.
|
||||
// If set to 1, the object can contain nested arrays or objects but only 1
|
||||
// level deep.
|
||||
// And bigger values will allow more level of nesting.
|
||||
//
|
||||
// The purpose of this feature is to prevent stack overflow that could lead to
|
||||
// The purpose of this feature is to prevent stack overflow that could
|
||||
// lead to
|
||||
// a security risk.
|
||||
static const uint8_t DEFAULT_LIMIT = 10;
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -6,6 +6,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino/String.hpp"
|
||||
#include "Internals/JsonBufferAllocated.hpp"
|
||||
#include "Internals/JsonPrintable.hpp"
|
||||
#include "Internals/List.hpp"
|
||||
#include "Internals/ReferenceType.hpp"
|
||||
@ -30,76 +32,120 @@ 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> {
|
||||
// JsonBuffer is a friend because it needs to call the private constructor.
|
||||
friend class JsonBuffer;
|
||||
|
||||
public Internals::List<JsonPair>,
|
||||
public Internals::JsonBufferAllocated {
|
||||
public:
|
||||
typedef const char *key_type;
|
||||
typedef JsonPair value_type;
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
// You should not use this constructor directly.
|
||||
// Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject().
|
||||
FORCE_INLINE explicit JsonObject(JsonBuffer* buffer)
|
||||
: Internals::List<JsonPair>(buffer) {}
|
||||
|
||||
// Gets the JsonVariant associated with the specified key.
|
||||
// Returns a reference or JsonVariant::invalid() if not found.
|
||||
JsonVariant &at(key_type key);
|
||||
// Gets or sets the value associated with the specified key.
|
||||
FORCE_INLINE JsonObjectSubscript<const char*> operator[](const char* key);
|
||||
FORCE_INLINE JsonObjectSubscript<const String&> operator[](const String& key);
|
||||
|
||||
// Gets the JsonVariant associated with the specified key.
|
||||
// Returns a constant reference or JsonVariant::invalid() if not found.
|
||||
const JsonVariant &at(key_type key) const;
|
||||
// Gets the value associated with the specified key.
|
||||
FORCE_INLINE JsonVariant operator[](JsonObjectKey key) const;
|
||||
|
||||
// Gets or create the JsonVariant associated with the specified key.
|
||||
// Returns a reference or JsonVariant::invalid() if allocation failed.
|
||||
JsonVariant &operator[](key_type key);
|
||||
|
||||
// Gets the JsonVariant associated with the specified key.
|
||||
// Returns a constant reference or JsonVariant::invalid() if not found.
|
||||
const JsonVariant &operator[](key_type key) const { return at(key); }
|
||||
|
||||
// Adds an uninitialized JsonVariant associated with the specified key.
|
||||
// Return a reference or JsonVariant::invalid() if allocation fails.
|
||||
JsonVariant &add(key_type key) { return (*this)[key]; }
|
||||
|
||||
// Adds the specified key with the specified value.
|
||||
// Sets the specified key with the specified value.
|
||||
FORCE_INLINE bool set(const char* key, bool value);
|
||||
FORCE_INLINE bool set(const char* key, float value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool set(const char* key, double value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool set(const char* key, signed char value);
|
||||
FORCE_INLINE bool set(const char* key, signed long value);
|
||||
FORCE_INLINE bool set(const char* key, signed int value);
|
||||
FORCE_INLINE bool set(const char* key, signed short value);
|
||||
FORCE_INLINE bool set(const char* key, unsigned char value);
|
||||
FORCE_INLINE bool set(const char* key, unsigned long value);
|
||||
FORCE_INLINE bool set(const char* key, unsigned int value);
|
||||
FORCE_INLINE bool set(const char* key, unsigned short value);
|
||||
FORCE_INLINE bool set(const char* key, const char* value);
|
||||
FORCE_INLINE bool set(const char* key, const String& value);
|
||||
FORCE_INLINE bool set(const char* key, JsonArray& array);
|
||||
FORCE_INLINE bool set(const char* key, JsonObject& object);
|
||||
FORCE_INLINE bool set(const char* key, const JsonVariant& value);
|
||||
template <typename T>
|
||||
void add(key_type key, T value) {
|
||||
add(key).set(value);
|
||||
}
|
||||
FORCE_INLINE bool set(const char* key, const T& value);
|
||||
|
||||
// Adds the specified key with a reference to the specified JsonArray.
|
||||
void add(key_type key, JsonArray &array) { add(key).set(array); }
|
||||
FORCE_INLINE bool set(const String& key, bool value);
|
||||
FORCE_INLINE bool set(const String& key, float value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool set(const String& key, double value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool set(const String& key, signed char value);
|
||||
FORCE_INLINE bool set(const String& key, signed long value);
|
||||
FORCE_INLINE bool set(const String& key, signed int value);
|
||||
FORCE_INLINE bool set(const String& key, signed short value);
|
||||
FORCE_INLINE bool set(const String& key, unsigned char value);
|
||||
FORCE_INLINE bool set(const String& key, unsigned long value);
|
||||
FORCE_INLINE bool set(const String& key, unsigned int value);
|
||||
FORCE_INLINE bool set(const String& key, unsigned short value);
|
||||
FORCE_INLINE bool set(const String& key, const char* value);
|
||||
FORCE_INLINE bool set(const String& key, const String& value);
|
||||
FORCE_INLINE bool set(const String& key, JsonArray& array);
|
||||
FORCE_INLINE bool set(const String& key, JsonObject& object);
|
||||
FORCE_INLINE bool set(const String& key, const JsonVariant& value);
|
||||
template <typename T>
|
||||
FORCE_INLINE bool set(const String& key, const T& value);
|
||||
|
||||
// Adds the specified key with a reference to the specified JsonObject.
|
||||
void add(key_type key, JsonObject &object) { add(key).set(object); }
|
||||
// Gets the value associated with the specified key.
|
||||
FORCE_INLINE JsonVariant get(JsonObjectKey) const;
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
template <typename T>
|
||||
FORCE_INLINE T get(JsonObjectKey) const;
|
||||
|
||||
// Checks the type of the value associated with the specified key.
|
||||
template <typename T>
|
||||
FORCE_INLINE bool is(JsonObjectKey) const;
|
||||
|
||||
// Creates and adds a JsonArray.
|
||||
// This is a shortcut for JsonBuffer::createArray() and JsonObject::add().
|
||||
JsonArray &createNestedArray(key_type key);
|
||||
FORCE_INLINE JsonArray& createNestedArray(const char* key);
|
||||
FORCE_INLINE JsonArray& createNestedArray(const String& key);
|
||||
|
||||
// Creates and adds a JsonObject.
|
||||
// This is a shortcut for JsonBuffer::createObject() and JsonObject::add().
|
||||
JsonObject &createNestedObject(key_type key);
|
||||
FORCE_INLINE JsonObject& createNestedObject(const char* key);
|
||||
FORCE_INLINE JsonObject& createNestedObject(const String& key);
|
||||
|
||||
// Tells weither the specified key is present and associated with a value.
|
||||
bool containsKey(key_type key) const { return at(key).success(); }
|
||||
FORCE_INLINE bool containsKey(JsonObjectKey key) const;
|
||||
|
||||
// Removes the specified key and the associated value.
|
||||
void remove(key_type key);
|
||||
void remove(JsonObjectKey key);
|
||||
|
||||
// Returns a reference an invalid JsonObject.
|
||||
// This object is meant to replace a NULL pointer.
|
||||
// This is used when memory allocation or JSON parsing fail.
|
||||
static JsonObject &invalid() { return _invalid; }
|
||||
static JsonObject& invalid() { return _invalid; }
|
||||
|
||||
// Serialize the object to the specified JsonWriter
|
||||
void writeTo(Internals::JsonWriter &writer) const;
|
||||
void writeTo(Internals::JsonWriter& writer) const;
|
||||
|
||||
private:
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
explicit JsonObject(JsonBuffer *buffer) : Internals::List<JsonPair>(buffer) {}
|
||||
|
||||
// Returns the list node that matches the specified key.
|
||||
node_type *getNodeAt(key_type key) const;
|
||||
node_type* getNodeAt(JsonObjectKey key) const;
|
||||
|
||||
node_type* getOrCreateNodeAt(JsonObjectKey key);
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
FORCE_INLINE bool setNodeAt(TKey key, TValue value);
|
||||
|
||||
template <typename TKey>
|
||||
JsonArray& createArrayAt(TKey key);
|
||||
|
||||
template <typename TKey>
|
||||
JsonObject& createObjectAt(TKey key);
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE void setNodeKey(node_type*, T key);
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE void setNodeValue(node_type*, T value);
|
||||
|
||||
// The instance returned by JsonObject::invalid()
|
||||
static JsonObject _invalid;
|
||||
};
|
||||
}
|
||||
|
||||
#include "JsonObject.ipp"
|
||||
|
240
include/ArduinoJson/JsonObject.ipp
Normal file
240
include/ArduinoJson/JsonObject.ipp
Normal file
@ -0,0 +1,240 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonObject.hpp"
|
||||
#include "JsonObjectSubscript.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
inline JsonVariant JsonObject::get(JsonObjectKey key) const {
|
||||
node_type *node = getNodeAt(key);
|
||||
return node ? node->content.value : JsonVariant();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T JsonObject::get(JsonObjectKey key) const {
|
||||
node_type *node = getNodeAt(key);
|
||||
return node ? node->content.value.as<T>() : JsonVariant::invalid<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool JsonObject::is(JsonObjectKey key) const {
|
||||
node_type *node = getNodeAt(key);
|
||||
return node ? node->content.value.is<T>() : false;
|
||||
}
|
||||
|
||||
inline JsonObjectSubscript<const char *> JsonObject::operator[](
|
||||
const char *key) {
|
||||
return JsonObjectSubscript<const char *>(*this, key);
|
||||
}
|
||||
|
||||
inline JsonObjectSubscript<const String &> JsonObject::operator[](
|
||||
const String &key) {
|
||||
return JsonObjectSubscript<const String &>(*this, key);
|
||||
}
|
||||
|
||||
inline JsonVariant JsonObject::operator[](JsonObjectKey key) const {
|
||||
return get(key);
|
||||
}
|
||||
|
||||
inline bool JsonObject::containsKey(JsonObjectKey key) const {
|
||||
return getNodeAt(key) != NULL;
|
||||
}
|
||||
|
||||
inline JsonArray &JsonObject::createNestedArray(const char *key) {
|
||||
return createArrayAt<const char *>(key);
|
||||
}
|
||||
|
||||
inline JsonArray &JsonObject::createNestedArray(const String &key) {
|
||||
return createArrayAt<const String &>(key);
|
||||
}
|
||||
|
||||
inline JsonObject &JsonObject::createNestedObject(const char *key) {
|
||||
return createObjectAt<const char *>(key);
|
||||
}
|
||||
|
||||
inline JsonObject &JsonObject::createNestedObject(const String &key) {
|
||||
return createObjectAt<const String &>(key);
|
||||
}
|
||||
|
||||
inline void JsonObject::remove(JsonObjectKey key) {
|
||||
removeNode(getNodeAt(key));
|
||||
}
|
||||
|
||||
inline bool JsonObject::set(const char *key, bool value) {
|
||||
return setNodeAt<const char *, bool>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, float value, uint8_t decimals) {
|
||||
return setNodeAt<const char *, const JsonVariant &>(
|
||||
key, JsonVariant(value, decimals));
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, double value, uint8_t decimals) {
|
||||
return setNodeAt<const char *, const JsonVariant &>(
|
||||
key, JsonVariant(value, decimals));
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, signed char value) {
|
||||
return setNodeAt<const char *, signed char>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, signed long value) {
|
||||
return setNodeAt<const char *, signed long>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, signed int value) {
|
||||
return setNodeAt<const char *, signed int>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, signed short value) {
|
||||
return setNodeAt<const char *, signed short>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, unsigned char value) {
|
||||
return setNodeAt<const char *, unsigned char>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, unsigned long value) {
|
||||
return setNodeAt<const char *, unsigned long>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, unsigned int value) {
|
||||
return setNodeAt<const char *, unsigned int>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, unsigned short value) {
|
||||
return setNodeAt<const char *, unsigned short>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, const char *value) {
|
||||
return setNodeAt<const char *, const char *>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, const String &value) {
|
||||
return setNodeAt<const char *, const String &>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, JsonArray &array) {
|
||||
return setNodeAt<const char *, JsonArray &>(key, array);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, JsonObject &object) {
|
||||
return setNodeAt<const char *, JsonObject &>(key, object);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, const JsonVariant &value) {
|
||||
return setNodeAt<const char *, const JsonVariant &>(key, value);
|
||||
}
|
||||
template <typename T>
|
||||
inline bool JsonObject::set(const char *key, const T &value) {
|
||||
return setNodeAt<const char *, JsonVariant>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, bool value) {
|
||||
return setNodeAt<const String &, bool>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, float value, uint8_t decimals) {
|
||||
return setNodeAt<const String &, const JsonVariant &>(
|
||||
key, JsonVariant(value, decimals));
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, double value, uint8_t decimals) {
|
||||
return setNodeAt<const String &, const JsonVariant &>(
|
||||
key, JsonVariant(value, decimals));
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, signed char value) {
|
||||
return setNodeAt<const String &, signed char>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, signed long value) {
|
||||
return setNodeAt<const String &, signed long>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, signed int value) {
|
||||
return setNodeAt<const String &, signed int>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, signed short value) {
|
||||
return setNodeAt<const String &, signed short>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, unsigned char value) {
|
||||
return setNodeAt<const String &, unsigned char>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, unsigned long value) {
|
||||
return setNodeAt<const String &, unsigned long>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, unsigned int value) {
|
||||
return setNodeAt<const String &, unsigned int>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, unsigned short value) {
|
||||
return setNodeAt<const String &, unsigned short>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, const char *value) {
|
||||
return setNodeAt<const String &, const char *>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, const String &value) {
|
||||
return setNodeAt<const String &, const String &>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, JsonArray &array) {
|
||||
return setNodeAt<const String &, JsonArray &>(key, array);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, JsonObject &object) {
|
||||
return setNodeAt<const String &, JsonObject &>(key, object);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, const JsonVariant &value) {
|
||||
return setNodeAt<const String &, const JsonVariant &>(key, value);
|
||||
}
|
||||
template <typename T>
|
||||
inline bool JsonObject::set(const String &key, const T &value) {
|
||||
return setNodeAt<const String &, JsonVariant>(key, value);
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
inline bool JsonObject::setNodeAt(TKey key, TValue value) {
|
||||
node_type *node = getOrCreateNodeAt(key);
|
||||
if (!node) return false;
|
||||
setNodeKey<TKey>(node, key);
|
||||
setNodeValue<TValue>(node, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void JsonObject::setNodeKey(node_type *node, const char *key) {
|
||||
node->content.key = key;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void JsonObject::setNodeKey(node_type *node, const String &key) {
|
||||
node->content.key = _buffer->strdup(key);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
inline void JsonObject::setNodeValue(node_type *node, TValue value) {
|
||||
node->content.value = value;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void JsonObject::setNodeValue(node_type *node, const String &value) {
|
||||
node->content.value = _buffer->strdup(value);
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline const JsonObjectSubscript<const char *> JsonVariantBase<TImplem>::
|
||||
operator[](const char *key) const {
|
||||
return asObject()[key];
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline const JsonObjectSubscript<const String &> JsonVariantBase<TImplem>::
|
||||
operator[](const String &key) const {
|
||||
return asObject()[key];
|
||||
}
|
||||
|
||||
template <>
|
||||
inline JsonObject const &JsonVariant::invalid<JsonObject const &>() {
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline JsonObject &JsonVariant::invalid<JsonObject &>() {
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline JsonObject &JsonVariant::as<JsonObject &>() const {
|
||||
if (_type == Internals::JSON_OBJECT) return *_content.asObject;
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const JsonObject &JsonVariant::as<const JsonObject &>() const {
|
||||
if (_type == Internals::JSON_OBJECT) return *_content.asObject;
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
}
|
24
include/ArduinoJson/JsonObjectKey.hpp
Normal file
24
include/ArduinoJson/JsonObjectKey.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino/String.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
class JsonObjectKey {
|
||||
public:
|
||||
JsonObjectKey() {}
|
||||
JsonObjectKey(const char* key) : _data(key) {}
|
||||
JsonObjectKey(const String& key) : _data(key.c_str()) {}
|
||||
|
||||
operator const char*() const { return _data; }
|
||||
|
||||
private:
|
||||
const char* _data;
|
||||
};
|
||||
}
|
88
include/ArduinoJson/JsonObjectSubscript.hpp
Normal file
88
include/ArduinoJson/JsonObjectSubscript.hpp
Normal file
@ -0,0 +1,88 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonSubscriptBase.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4522)
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
template <typename TKey>
|
||||
class JsonObjectSubscript
|
||||
: public JsonSubscriptBase<JsonObjectSubscript<TKey> > {
|
||||
public:
|
||||
FORCE_INLINE JsonObjectSubscript(JsonObject& object, TKey key)
|
||||
: _object(object), _key(key) {}
|
||||
|
||||
using JsonSubscriptBase<JsonObjectSubscript<TKey> >::operator=;
|
||||
|
||||
JsonObjectSubscript<TKey>& operator=(const JsonObjectSubscript<TKey>& src) {
|
||||
return JsonSubscriptBase<JsonObjectSubscript<TKey> >::template assign<
|
||||
JsonVariant>(src);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
JsonObjectSubscript<TKey>& operator=(const T& src) {
|
||||
return JsonSubscriptBase<JsonObjectSubscript<TKey> >::template assign<
|
||||
JsonVariant>(src);
|
||||
}
|
||||
|
||||
FORCE_INLINE bool success() const { return _object.containsKey(_key); }
|
||||
|
||||
FORCE_INLINE operator JsonVariant() const { return _object.get(_key); }
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE TValue as() const {
|
||||
return _object.get<TValue>(_key);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool is() const {
|
||||
return _object.is<TValue>(_key);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(TValue value) {
|
||||
return _object.set(_key, value);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(TValue value, uint8_t decimals) {
|
||||
return _object.set(_key, value, decimals);
|
||||
}
|
||||
|
||||
FORCE_INLINE JsonVariant get() { return _object.get(_key); }
|
||||
|
||||
void writeTo(Internals::JsonWriter& writer) const {
|
||||
_object.get(_key).writeTo(writer);
|
||||
}
|
||||
|
||||
private:
|
||||
JsonObject& _object;
|
||||
TKey _key;
|
||||
};
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream& operator<<(
|
||||
std::ostream& os, const JsonObjectSubscript<const String&>& source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(
|
||||
std::ostream& os, const JsonObjectSubscript<const char*>& source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
#endif
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -6,13 +6,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonObjectKey.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// A key value pair for JsonObject.
|
||||
struct JsonPair {
|
||||
const char* key;
|
||||
JsonObjectKey key;
|
||||
JsonVariant value;
|
||||
};
|
||||
}
|
||||
|
82
include/ArduinoJson/JsonSubscriptBase.hpp
Normal file
82
include/ArduinoJson/JsonSubscriptBase.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariantBase.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonSubscriptBase : public JsonVariantBase<TImpl> {
|
||||
public:
|
||||
FORCE_INLINE TImpl& operator=(bool value) { return assign<bool>(value); }
|
||||
|
||||
FORCE_INLINE TImpl& operator=(float value) { return assign<float>(value); }
|
||||
|
||||
FORCE_INLINE TImpl& operator=(double value) { return assign<double>(value); }
|
||||
|
||||
FORCE_INLINE TImpl& operator=(signed char value) {
|
||||
return assign<signed char>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(signed long value) {
|
||||
return assign<signed long>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(signed int value) {
|
||||
return assign<signed int>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(signed short value) {
|
||||
return assign<signed short>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(unsigned char value) {
|
||||
return assign<unsigned char>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(unsigned long value) {
|
||||
return assign<unsigned long>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(unsigned int value) {
|
||||
return assign<unsigned int>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(unsigned short value) {
|
||||
return assign<unsigned short>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(const char* value) {
|
||||
return assign<const char*>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(const String& value) {
|
||||
return assign<const String&>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(JsonArray& array) {
|
||||
return assign<JsonArray&>(array);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(JsonObject& object) {
|
||||
return assign<JsonObject&>(object);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(JsonVariant value) {
|
||||
return assign<const JsonVariant&>(value);
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename TValue>
|
||||
FORCE_INLINE TImpl& assign(TValue value) {
|
||||
TImpl* that = static_cast<TImpl*>(this);
|
||||
that->template set<TValue>(value);
|
||||
return *that;
|
||||
}
|
||||
};
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -12,6 +12,8 @@
|
||||
#include "Internals/JsonPrintable.hpp"
|
||||
#include "Internals/JsonVariantContent.hpp"
|
||||
#include "Internals/JsonVariantType.hpp"
|
||||
#include "Internals/Unparsed.hpp"
|
||||
#include "JsonVariantBase.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
@ -26,261 +28,79 @@ class JsonObject;
|
||||
// - a char, short, int or a long (signed or unsigned)
|
||||
// - a string (const char*)
|
||||
// - a reference to a JsonArray or JsonObject
|
||||
class JsonVariant : public Internals::JsonPrintable<JsonVariant> {
|
||||
class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
public:
|
||||
// Creates an uninitialized JsonVariant
|
||||
JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
|
||||
FORCE_INLINE JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
|
||||
|
||||
// Initializes a JsonVariant with the specified value.
|
||||
template <typename T>
|
||||
explicit JsonVariant(T value) {
|
||||
set(value);
|
||||
}
|
||||
|
||||
// Tells weither the variant is valid.
|
||||
bool success() const {
|
||||
return _type != Internals::JSON_INVALID &&
|
||||
_type != Internals::JSON_UNDEFINED;
|
||||
}
|
||||
|
||||
// Sets the variant to a boolean value.
|
||||
// Create a JsonVariant containing a boolean value.
|
||||
// It will be serialized as "true" or "false" in JSON.
|
||||
void set(bool value);
|
||||
FORCE_INLINE JsonVariant(bool value);
|
||||
|
||||
// Sets the variant to a floating point value.
|
||||
// Create a JsonVariant containing a floating point value.
|
||||
// The second argument specifies the number of decimal digits to write in
|
||||
// the JSON string.
|
||||
void set(double value, uint8_t decimals = 2);
|
||||
FORCE_INLINE JsonVariant(float value, uint8_t decimals = 2);
|
||||
FORCE_INLINE JsonVariant(double value, uint8_t decimals = 2);
|
||||
|
||||
// Sets the variant to be an integer value.
|
||||
void set(signed long value);
|
||||
void set(signed char value) { set(static_cast<long>(value)); }
|
||||
void set(signed int value) { set(static_cast<long>(value)); }
|
||||
void set(signed short value) { set(static_cast<long>(value)); }
|
||||
void set(unsigned char value) { set(static_cast<long>(value)); }
|
||||
void set(unsigned int value) { set(static_cast<long>(value)); }
|
||||
void set(unsigned long value) { set(static_cast<long>(value)); }
|
||||
void set(unsigned short value) { set(static_cast<long>(value)); }
|
||||
// Create a JsonVariant containing an integer value.
|
||||
FORCE_INLINE JsonVariant(signed char value);
|
||||
FORCE_INLINE JsonVariant(signed long value);
|
||||
FORCE_INLINE JsonVariant(signed int value);
|
||||
FORCE_INLINE JsonVariant(signed short value);
|
||||
FORCE_INLINE JsonVariant(unsigned char value);
|
||||
FORCE_INLINE JsonVariant(unsigned long value);
|
||||
FORCE_INLINE JsonVariant(unsigned int value);
|
||||
FORCE_INLINE JsonVariant(unsigned short value);
|
||||
|
||||
// Sets the variant to be a string.
|
||||
void set(const char *value);
|
||||
// Create a JsonVariant containing a string.
|
||||
FORCE_INLINE JsonVariant(const char *value);
|
||||
|
||||
// Sets the variant to be a reference to an array.
|
||||
void set(JsonArray &array);
|
||||
// Create a JsonVariant containing an unparsed string
|
||||
FORCE_INLINE JsonVariant(Internals::Unparsed value);
|
||||
|
||||
// Sets the variant to be a reference to an object.
|
||||
void set(JsonObject &object);
|
||||
// Create a JsonVariant containing a reference to an array.
|
||||
FORCE_INLINE JsonVariant(JsonArray &array);
|
||||
|
||||
// Sets the variant to the specified value.
|
||||
template <typename T>
|
||||
JsonVariant &operator=(T value) {
|
||||
set(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Sets the variant to be a reference to an array.
|
||||
JsonVariant &operator=(JsonArray &array) {
|
||||
set(array);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Sets the variant to be a reference to an object.
|
||||
JsonVariant &operator=(JsonObject &object) {
|
||||
set(object);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Gets the variant as a boolean value.
|
||||
// Returns false if the variant is not a boolean value.
|
||||
operator bool() const;
|
||||
|
||||
// Gets the variant as a floating-point value.
|
||||
// Returns 0.0 if the variant is not a floating-point value
|
||||
operator double() const;
|
||||
operator float() const { return static_cast<float>(as<double>()); }
|
||||
|
||||
// Gets the variant as an integer value.
|
||||
// Returns 0 if the variant is not an integer value.
|
||||
operator signed long() const;
|
||||
operator signed char() const { return cast_long_to<signed char>(); }
|
||||
operator signed int() const { return cast_long_to<signed int>(); }
|
||||
operator signed short() const { return cast_long_to<signed short>(); }
|
||||
operator unsigned char() const { return cast_long_to<unsigned char>(); }
|
||||
operator unsigned int() const { return cast_long_to<unsigned int>(); }
|
||||
operator unsigned long() const { return cast_long_to<unsigned long>(); }
|
||||
operator unsigned short() const { return cast_long_to<unsigned short>(); }
|
||||
|
||||
// Gets the variant as a string.
|
||||
// Returns NULL if variant is not a string.
|
||||
operator const char *() const;
|
||||
const char *asString() const { return as<const char *>(); }
|
||||
|
||||
// Gets the variant as an array.
|
||||
// Returns a reference to the JsonArray or JsonArray::invalid() if the variant
|
||||
// is not an array.
|
||||
operator JsonArray &() const;
|
||||
JsonArray &asArray() const { return as<JsonArray &>(); }
|
||||
|
||||
// Gets the variant as an object.
|
||||
// Returns a reference to the JsonObject or JsonObject::invalid() if the
|
||||
// variant is not an object.
|
||||
operator JsonObject &() const;
|
||||
JsonObject &asObject() const { return as<JsonObject &>(); }
|
||||
// Create a JsonVariant containing a reference to an object.
|
||||
FORCE_INLINE JsonVariant(JsonObject &object);
|
||||
|
||||
// Get the variant as the specified type.
|
||||
// See cast operators for details.
|
||||
template <typename T>
|
||||
T as() const {
|
||||
return static_cast<T>(*this);
|
||||
}
|
||||
T as() const;
|
||||
|
||||
// Tells weither the variant has the specified type.
|
||||
// Returns true if the variant has type type T, false otherwise.
|
||||
template <typename T>
|
||||
bool is() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns an invalid variant.
|
||||
// This is meant to replace a NULL pointer.
|
||||
static JsonVariant &invalid() { return _invalid; }
|
||||
bool is() const;
|
||||
|
||||
// Serialize the variant to a JsonWriter
|
||||
void writeTo(Internals::JsonWriter &writer) const;
|
||||
|
||||
// Mimics an array or an object.
|
||||
// Returns the size of the array or object if the variant has that type.
|
||||
// Returns 0 if the variant is neither an array nor an object
|
||||
size_t size() const;
|
||||
|
||||
// Mimics an array.
|
||||
// Returns the element at specified index if the variant is an array.
|
||||
// Returns JsonVariant::invalid() if the variant is not an array.
|
||||
JsonVariant &operator[](int index);
|
||||
|
||||
// Mimics an object.
|
||||
// Returns the value associated with the specified key if the variant is an
|
||||
// object.
|
||||
// Return JsonVariant::invalid() if the variant is not an object.
|
||||
JsonVariant &operator[](const char *key);
|
||||
// TODO: rename
|
||||
template <typename T>
|
||||
static T invalid();
|
||||
|
||||
private:
|
||||
// Special constructor used only to create _invalid.
|
||||
explicit JsonVariant(Internals::JsonVariantType type) : _type(type) {}
|
||||
|
||||
// Helper for interger cast operators
|
||||
template <typename T>
|
||||
T cast_long_to() const {
|
||||
return static_cast<T>(as<long>());
|
||||
}
|
||||
Internals::JsonFloat asFloat() const;
|
||||
Internals::JsonInteger asInteger() const;
|
||||
|
||||
// The current type of the variant
|
||||
Internals::JsonVariantType _type;
|
||||
|
||||
// The various alternatives for the value of the variant.
|
||||
Internals::JsonVariantContent _content;
|
||||
|
||||
// The instance returned by JsonVariant::invalid()
|
||||
static JsonVariant _invalid;
|
||||
};
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<long>() const {
|
||||
return _type == Internals::JSON_LONG;
|
||||
inline JsonVariant float_with_n_digits(float value, uint8_t digits) {
|
||||
return JsonVariant(value, digits);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<double>() const {
|
||||
return _type >= Internals::JSON_DOUBLE_0_DECIMALS;
|
||||
inline JsonVariant double_with_n_digits(double value, uint8_t digits) {
|
||||
return JsonVariant(value, digits);
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<bool>() const {
|
||||
return _type == Internals::JSON_BOOLEAN;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<const char *>() const {
|
||||
return _type == Internals::JSON_STRING;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<JsonArray &>() const {
|
||||
return _type == Internals::JSON_ARRAY;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<const JsonArray &>() const {
|
||||
return _type == Internals::JSON_ARRAY;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<JsonObject &>() const {
|
||||
return _type == Internals::JSON_OBJECT;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<const JsonObject &>() const {
|
||||
return _type == Internals::JSON_OBJECT;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator==(const JsonVariant &left, T right) {
|
||||
return left.as<T>() == right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator==(T left, const JsonVariant &right) {
|
||||
return left == right.as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator!=(const JsonVariant &left, T right) {
|
||||
return left.as<T>() != right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator!=(T left, const JsonVariant &right) {
|
||||
return left != right.as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator<=(const JsonVariant &left, T right) {
|
||||
return left.as<T>() <= right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator<=(T left, const JsonVariant &right) {
|
||||
return left <= right.as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator>=(const JsonVariant &left, T right) {
|
||||
return left.as<T>() >= right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator>=(T left, const JsonVariant &right) {
|
||||
return left >= right.as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator<(const JsonVariant &left, T right) {
|
||||
return left.as<T>() < right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator<(T left, const JsonVariant &right) {
|
||||
return left < right.as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator>(const JsonVariant &left, T right) {
|
||||
return left.as<T>() > right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator>(T left, const JsonVariant &right) {
|
||||
return left > right.as<T>();
|
||||
}
|
||||
}
|
||||
// Include inline implementations
|
||||
#include "JsonVariant.ipp"
|
||||
|
252
include/ArduinoJson/JsonVariant.ipp
Normal file
252
include/ArduinoJson/JsonVariant.ipp
Normal file
@ -0,0 +1,252 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
inline JsonVariant::JsonVariant(bool value) {
|
||||
using namespace Internals;
|
||||
_type = JSON_BOOLEAN;
|
||||
_content.asInteger = static_cast<JsonInteger>(value);
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(const char *value) {
|
||||
_type = Internals::JSON_STRING;
|
||||
_content.asString = value;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(Internals::Unparsed value) {
|
||||
_type = Internals::JSON_UNPARSED;
|
||||
_content.asString = value;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(double value, uint8_t decimals) {
|
||||
using namespace Internals;
|
||||
_type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals);
|
||||
_content.asFloat = static_cast<JsonFloat>(value);
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(float value, uint8_t decimals) {
|
||||
using namespace Internals;
|
||||
_type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals);
|
||||
_content.asFloat = static_cast<JsonFloat>(value);
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(JsonArray &array) {
|
||||
_type = Internals::JSON_ARRAY;
|
||||
_content.asArray = &array;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(JsonObject &object) {
|
||||
_type = Internals::JSON_OBJECT;
|
||||
_content.asObject = &object;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(signed char value) {
|
||||
using namespace Internals;
|
||||
_type = JSON_INTEGER;
|
||||
_content.asInteger = static_cast<JsonInteger>(value);
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(signed int value) {
|
||||
using namespace Internals;
|
||||
_type = JSON_INTEGER;
|
||||
_content.asInteger = static_cast<JsonInteger>(value);
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(signed long value) {
|
||||
using namespace Internals;
|
||||
_type = JSON_INTEGER;
|
||||
_content.asInteger = static_cast<JsonInteger>(value);
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(signed short value) {
|
||||
using namespace Internals;
|
||||
_type = JSON_INTEGER;
|
||||
_content.asInteger = static_cast<JsonInteger>(value);
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(unsigned char value) {
|
||||
using namespace Internals;
|
||||
_type = JSON_INTEGER;
|
||||
_content.asInteger = static_cast<JsonInteger>(value);
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(unsigned int value) {
|
||||
using namespace Internals;
|
||||
_type = JSON_INTEGER;
|
||||
_content.asInteger = static_cast<JsonInteger>(value);
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(unsigned long value) {
|
||||
using namespace Internals;
|
||||
_type = JSON_INTEGER;
|
||||
_content.asInteger = static_cast<JsonInteger>(value);
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(unsigned short value) {
|
||||
using namespace Internals;
|
||||
_type = JSON_INTEGER;
|
||||
_content.asInteger = static_cast<JsonInteger>(value);
|
||||
}
|
||||
|
||||
template <>
|
||||
String JsonVariant::as<String>() const;
|
||||
|
||||
template <>
|
||||
const char *JsonVariant::as<const char *>() const;
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::as<bool>() const {
|
||||
return asInteger() != 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline signed char JsonVariant::as<signed char>() const {
|
||||
return static_cast<signed char>(asInteger());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline unsigned char JsonVariant::as<unsigned char>() const {
|
||||
return static_cast<unsigned char>(asInteger());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline signed short JsonVariant::as<signed short>() const {
|
||||
return static_cast<signed short>(asInteger());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline unsigned short JsonVariant::as<unsigned short>() const {
|
||||
return static_cast<unsigned short>(asInteger());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline signed int JsonVariant::as<signed int>() const {
|
||||
return static_cast<signed int>(asInteger());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline unsigned int JsonVariant::as<unsigned int>() const {
|
||||
return static_cast<unsigned int>(asInteger());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline unsigned long JsonVariant::as<unsigned long>() const {
|
||||
return static_cast<unsigned long>(asInteger());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline signed long JsonVariant::as<signed long>() const {
|
||||
return static_cast<unsigned long>(asInteger());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline double JsonVariant::as<double>() const {
|
||||
return static_cast<double>(asFloat());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline float JsonVariant::as<float>() const {
|
||||
return static_cast<float>(asFloat());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T JsonVariant::invalid() {
|
||||
return T();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool JsonVariant::is() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <> // in .cpp
|
||||
bool JsonVariant::is<signed long>() const;
|
||||
|
||||
template <> // in .cpp
|
||||
bool JsonVariant::is<double>() const;
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<bool>() const {
|
||||
return _type == Internals::JSON_BOOLEAN;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<char const *>() const {
|
||||
return _type == Internals::JSON_STRING;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<float>() const {
|
||||
return is<double>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<JsonArray &>() const {
|
||||
return _type == Internals::JSON_ARRAY;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<JsonArray const &>() const {
|
||||
return _type == Internals::JSON_ARRAY;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<JsonObject &>() const {
|
||||
return _type == Internals::JSON_OBJECT;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<JsonObject const &>() const {
|
||||
return _type == Internals::JSON_OBJECT;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<signed char>() const {
|
||||
return is<signed long>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<signed int>() const {
|
||||
return is<signed long>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<signed short>() const {
|
||||
return is<signed long>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<unsigned char>() const {
|
||||
return is<signed long>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<unsigned int>() const {
|
||||
return is<signed long>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<unsigned long>() const {
|
||||
return is<signed long>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<unsigned short>() const {
|
||||
return is<signed long>();
|
||||
}
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ArduinoJson
|
151
include/ArduinoJson/JsonVariantBase.hpp
Normal file
151
include/ArduinoJson/JsonVariantBase.hpp
Normal file
@ -0,0 +1,151 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Internals/ForceInline.hpp"
|
||||
#include "JsonObjectKey.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations.
|
||||
class JsonArraySubscript;
|
||||
template <typename TKey>
|
||||
class JsonObjectSubscript;
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
|
||||
public:
|
||||
// Gets the variant as a boolean value.
|
||||
// Returns false if the variant is not a boolean value.
|
||||
FORCE_INLINE operator bool() const { return as<bool>(); }
|
||||
|
||||
// Gets the variant as a floating-point value.
|
||||
// Returns 0.0 if the variant is not a floating-point value
|
||||
FORCE_INLINE operator double() const { return as<double>(); }
|
||||
FORCE_INLINE operator float() const { return as<float>(); }
|
||||
|
||||
// Gets the variant as an integer value.
|
||||
// Returns 0 if the variant is not an integer value.
|
||||
FORCE_INLINE operator signed long() const { return as<signed long>(); }
|
||||
FORCE_INLINE operator signed char() const { return as<signed char>(); }
|
||||
FORCE_INLINE operator signed int() const { return as<signed int>(); }
|
||||
FORCE_INLINE operator signed short() const { return as<signed short>(); }
|
||||
FORCE_INLINE operator unsigned char() const { return as<unsigned char>(); }
|
||||
FORCE_INLINE operator unsigned int() const { return as<unsigned int>(); }
|
||||
FORCE_INLINE operator unsigned long() const { return as<unsigned long>(); }
|
||||
FORCE_INLINE operator unsigned short() const { return as<unsigned short>(); }
|
||||
|
||||
// Gets the variant as a string.
|
||||
// Returns NULL if variant is not a string.
|
||||
FORCE_INLINE operator const char *() const { return as<const char *>(); }
|
||||
FORCE_INLINE const char *asString() const { return as<const char *>(); }
|
||||
FORCE_INLINE operator String() const { return as<String>(); }
|
||||
|
||||
// Gets the variant as an array.
|
||||
// Returns a reference to the JsonArray or JsonArray::invalid() if the
|
||||
// variant
|
||||
// is not an array.
|
||||
FORCE_INLINE operator JsonArray &() const { return as<JsonArray &>(); }
|
||||
FORCE_INLINE JsonArray &asArray() const { return as<JsonArray &>(); }
|
||||
|
||||
// Gets the variant as an object.
|
||||
// Returns a reference to the JsonObject or JsonObject::invalid() if the
|
||||
// variant is not an object.
|
||||
FORCE_INLINE operator JsonObject &() const { return as<JsonObject &>(); }
|
||||
FORCE_INLINE JsonObject &asObject() const { return as<JsonObject &>(); }
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE const T as() const {
|
||||
return impl()->template as<T>();
|
||||
}
|
||||
|
||||
// Mimics an array or an object.
|
||||
// Returns the size of the array or object if the variant has that type.
|
||||
// Returns 0 if the variant is neither an array nor an object
|
||||
size_t size() const { return asArray().size() + asObject().size(); }
|
||||
|
||||
// Mimics an array.
|
||||
// Returns the element at specified index if the variant is an array.
|
||||
// Returns JsonVariant::invalid() if the variant is not an array.
|
||||
FORCE_INLINE const JsonArraySubscript operator[](int index) const;
|
||||
|
||||
// Mimics an object.
|
||||
// Returns the value associated with the specified key if the variant is
|
||||
// an object.
|
||||
// Return JsonVariant::invalid() if the variant is not an object.
|
||||
FORCE_INLINE const JsonObjectSubscript<const char *> operator[](
|
||||
const char *key) const;
|
||||
FORCE_INLINE const JsonObjectSubscript<const String &> operator[](
|
||||
const String &key) const;
|
||||
|
||||
// Serialize the variant to a JsonWriter
|
||||
void writeTo(Internals::JsonWriter &writer) const;
|
||||
|
||||
private:
|
||||
const TImpl *impl() const { return static_cast<const TImpl *>(this); }
|
||||
};
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator==(const JsonVariantBase<TImpl> &left, TComparand right) {
|
||||
return left.template as<TComparand>() == right;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator==(TComparand left, const JsonVariantBase<TImpl> &right) {
|
||||
return left == right.template as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator!=(const JsonVariantBase<TImpl> &left, TComparand right) {
|
||||
return left.template as<TComparand>() != right;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator!=(TComparand left, const JsonVariantBase<TImpl> &right) {
|
||||
return left != right.template as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator<=(const JsonVariantBase<TImpl> &left, TComparand right) {
|
||||
return left.template as<TComparand>() <= right;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator<=(TComparand left, const JsonVariantBase<TImpl> &right) {
|
||||
return left <= right.template as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator>=(const JsonVariantBase<TImpl> &left, TComparand right) {
|
||||
return left.template as<TComparand>() >= right;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator>=(TComparand left, const JsonVariantBase<TImpl> &right) {
|
||||
return left >= right.template as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator<(const JsonVariantBase<TImpl> &left, TComparand right) {
|
||||
return left.template as<TComparand>() < right;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator<(TComparand left, const JsonVariantBase<TImpl> &right) {
|
||||
return left < right.template as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator>(const JsonVariantBase<TImpl> &left, TComparand right) {
|
||||
return left.template as<TComparand>() > right;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator>(TComparand left, const JsonVariantBase<TImpl> &right) {
|
||||
return left > right.template as<TComparand>();
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -21,11 +21,10 @@ class StaticJsonBuffer : public JsonBuffer {
|
||||
size_t capacity() const { return CAPACITY; }
|
||||
size_t size() const { return _size; }
|
||||
|
||||
protected:
|
||||
virtual void* alloc(size_t bytes) {
|
||||
if (_size + bytes > CAPACITY) return NULL;
|
||||
void* p = &_buffer[_size];
|
||||
_size += bytes;
|
||||
_size += round_size_up(bytes);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
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.
|
||||
version=5.0.6
|
||||
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
sentence=An efficient and elegant JSON library for Arduino.
|
||||
paragraph=Like this project? Please star it on GitHub!
|
||||
category=Data Processing
|
||||
url=https://github.com/bblanchon/ArduinoJson
|
||||
architectures=*
|
||||
architectures=*
|
||||
|
@ -1,21 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
ZIP="C:\Program Files\7-Zip\7z.exe"
|
||||
TAG=$(git describe)
|
||||
OUTPUT="ArduinoJson-$TAG.zip"
|
||||
|
||||
cd ../..
|
||||
|
||||
# remove existing file
|
||||
rm -f $OUTPUT
|
||||
|
||||
# create zip
|
||||
"$ZIP" a $OUTPUT \
|
||||
ArduinoJson/CHANGELOG.md \
|
||||
ArduinoJson/examples \
|
||||
ArduinoJson/include \
|
||||
ArduinoJson/keywords.txt \
|
||||
ArduinoJson/library.properties \
|
||||
ArduinoJson/LICENSE.md \
|
||||
ArduinoJson/README.md \
|
||||
ArduinoJson/src
|
||||
#!/bin/bash
|
||||
|
||||
TAG=$(git describe)
|
||||
OUTPUT="ArduinoJson-$TAG.zip"
|
||||
|
||||
cd $(dirname $0)/../..
|
||||
|
||||
# remove existing file
|
||||
rm -f $OUTPUT
|
||||
|
||||
# create zip
|
||||
7z a $OUTPUT \
|
||||
ArduinoJson/CHANGELOG.md \
|
||||
ArduinoJson/examples \
|
||||
ArduinoJson/include \
|
||||
ArduinoJson/keywords.txt \
|
||||
ArduinoJson/library.properties \
|
||||
ArduinoJson/LICENSE.md \
|
||||
ArduinoJson/README.md \
|
||||
ArduinoJson/src \
|
||||
-x!ArduinoJson/src/CMakeLists.txt
|
||||
|
52
scripts/build-old-arduino-package.sh
Normal file
52
scripts/build-old-arduino-package.sh
Normal file
@ -0,0 +1,52 @@
|
||||
#!/bin/bash
|
||||
|
||||
TAG=$(git describe)
|
||||
OUTPUT="ArduinoJson-$TAG-old-layout.zip"
|
||||
|
||||
cd $(dirname $0)/..
|
||||
|
||||
cat > ArduinoJson.h <<END
|
||||
// WARNING:
|
||||
// --------
|
||||
// This file is a workaround for old version of the Arduino IDE.
|
||||
// If you are using Arduino IDE 1.0.6 or above, then you installed the wrong
|
||||
// package of ArduinoJson.
|
||||
// In that case, just delete the current installation and install the package.
|
||||
|
||||
END
|
||||
cp ArduinoJson.h ArduinoJson.cpp
|
||||
|
||||
cat "include/ArduinoJson.h" | sed 's!include "!include "include/!g' >> ArduinoJson.h
|
||||
|
||||
find src -name "*.cpp" |
|
||||
while read FILE; do
|
||||
echo >> ArduinoJson.cpp
|
||||
echo "// $FILE" >> ArduinoJson.cpp
|
||||
echo "//" >> ArduinoJson.cpp
|
||||
cat "$FILE" | sed 's!\.\./!!g' >> ArduinoJson.cpp
|
||||
done
|
||||
|
||||
unix2dos ArduinoJson.cpp
|
||||
unix2dos ArduinoJson.h
|
||||
|
||||
pushd ..
|
||||
|
||||
# remove existing file
|
||||
rm -f $OUTPUT
|
||||
|
||||
# create zipman dos2
|
||||
7z a $OUTPUT \
|
||||
ArduinoJson/CHANGELOG.md \
|
||||
ArduinoJson/examples \
|
||||
ArduinoJson/include/ArduinoJson \
|
||||
ArduinoJson/keywords.txt \
|
||||
ArduinoJson/LICENSE.md \
|
||||
ArduinoJson/README.md \
|
||||
ArduinoJson/ArduinoJson.h \
|
||||
ArduinoJson/ArduinoJson.cpp \
|
||||
-x!ArduinoJson/src/CMakeLists.txt
|
||||
|
||||
popd
|
||||
|
||||
rm ArduinoJson.h
|
||||
rm ArduinoJson.cpp
|
@ -20,10 +20,10 @@ build-env()
|
||||
if [[ $(uname) == MINGW* ]]
|
||||
then
|
||||
build-env "Make" "MinGW Makefiles"
|
||||
build-env "SublimeText" "Sublime Text 2 - MinGW Makefiles"
|
||||
build-env "SublimeText" "Sublime Text 2 - Ninja"
|
||||
build-env "VisualStudio" "Visual Studio 12 2013"
|
||||
else
|
||||
build-env "SublimeText" "Sublime Text 2 - Unix Makefiles"
|
||||
build-env "SublimeText" "Sublime Text 2 - Ninja"
|
||||
build-env "Make" "Unix Makefiles"
|
||||
build-env "Xcode" "Xcode"
|
||||
fi
|
42
scripts/create-size-graph.sh
Executable file
42
scripts/create-size-graph.sh
Executable file
@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
OUTPUT="$(pwd)/sizes.csv"
|
||||
|
||||
echo "Tag;Date;Parser;Generator" > $OUTPUT
|
||||
|
||||
cd $(dirname $(dirname $0))
|
||||
|
||||
git tag | while read TAG
|
||||
do
|
||||
|
||||
git checkout -q tags/$TAG
|
||||
|
||||
DATE=$(git log -1 --date=short --pretty=format:%cd)
|
||||
PARSER_SIZE=$(arduino --verify examples/JsonParserExample/JsonParserExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
|
||||
|
||||
if [ -e 'examples/JsonGeneratorExample/JsonGeneratorExample.ino' ]; then
|
||||
GENERATOR_SIZE=$(arduino --verify examples/JsonGeneratorExample/JsonGeneratorExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
|
||||
else
|
||||
GENERATOR_SIZE=""
|
||||
fi
|
||||
|
||||
echo $TAG
|
||||
if [ ! -z "$PARSER_SIZE" ]
|
||||
then
|
||||
echo "JsonParserExample = $PARSER_SIZE bytes"
|
||||
else
|
||||
echo "JsonParserExample compilation failed."
|
||||
fi
|
||||
|
||||
if [ ! -z "$GENERATOR_SIZE" ]
|
||||
then
|
||||
echo "JsonGeneratorExample = $GENERATOR_SIZE bytes"
|
||||
else
|
||||
echo "JsonGeneratorExample compilation failed."
|
||||
fi
|
||||
|
||||
echo "$TAG;$DATE;$PARSER_SIZE;$GENERATOR_SIZE" >> $OUTPUT
|
||||
|
||||
done
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -8,7 +8,21 @@
|
||||
|
||||
#include "../../include/ArduinoJson/Arduino/Print.hpp"
|
||||
|
||||
#include <stdio.h> // for sprintf
|
||||
#include <math.h> // for isnan() and isinf()
|
||||
#include <stdio.h> // for sprintf()
|
||||
|
||||
// only for GCC 4.9+
|
||||
#if defined(__GNUC__) && \
|
||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))
|
||||
#pragma GCC diagnostic ignored "-Wfloat-conversion"
|
||||
#endif
|
||||
|
||||
// Visual Studo 2012 didn't have isnan, nor isinf
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1700
|
||||
#include <float.h>
|
||||
#define isnan(x) _isnan(x)
|
||||
#define isinf(x) (!_finite(x))
|
||||
#endif
|
||||
|
||||
size_t Print::print(const char s[]) {
|
||||
size_t n = 0;
|
||||
@ -19,8 +33,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);
|
||||
}
|
||||
|
||||
@ -30,6 +60,12 @@ size_t Print::print(long value) {
|
||||
return print(tmp);
|
||||
}
|
||||
|
||||
size_t Print::print(int value) {
|
||||
char tmp[32];
|
||||
sprintf(tmp, "%d", value);
|
||||
return print(tmp);
|
||||
}
|
||||
|
||||
size_t Print::println() { return write('\r') + write('\n'); }
|
||||
|
||||
#endif
|
||||
|
31
src/Arduino/String.cpp
Normal file
31
src/Arduino/String.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#ifndef ARDUINO
|
||||
|
||||
#include "../../include/ArduinoJson/Arduino/String.hpp"
|
||||
|
||||
#include <stdio.h> // for sprintf()
|
||||
|
||||
String::String(double value, unsigned char digits) {
|
||||
char tmp[32];
|
||||
sprintf(tmp, "%.*f", digits, value);
|
||||
*this = tmp;
|
||||
}
|
||||
|
||||
String::String(long value) {
|
||||
char tmp[32];
|
||||
sprintf(tmp, "%ld", value);
|
||||
*this = tmp;
|
||||
}
|
||||
|
||||
String::String(int value) {
|
||||
char tmp[32];
|
||||
sprintf(tmp, "%d", value);
|
||||
*this = tmp;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
|
@ -1,9 +1,11 @@
|
||||
file(GLOB_RECURSE INC_FILES ../include/*.hpp)
|
||||
file(GLOB_RECURSE SRC_FILES *.cpp)
|
||||
file(GLOB_RECURSE HPP_FILES ../include/*.hpp)
|
||||
file(GLOB_RECURSE IPP_FILES ../include/*.ipp)
|
||||
file(GLOB_RECURSE CPP_FILES *.cpp)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||
add_definitions(
|
||||
-fno-exceptions
|
||||
-fno-rtti
|
||||
-pedantic
|
||||
-Wall
|
||||
-Wcast-align
|
||||
@ -20,6 +22,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
|
||||
@ -41,7 +44,8 @@ endif()
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_definitions(
|
||||
-Wc++11-compat
|
||||
-Wdeprecated-register
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(ArduinoJson ${SRC_FILES} ${INC_FILES})
|
||||
add_library(ArduinoJson ${CPP_FILES} ${HPP_FILES} ${IPP_FILES})
|
||||
|
51
src/Internals/Comments.cpp
Normal file
51
src/Internals/Comments.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../../include/ArduinoJson/Internals/Comments.hpp"
|
||||
|
||||
inline static const char *skipCStyleComment(const char *ptr) {
|
||||
ptr += 2;
|
||||
for (;;) {
|
||||
if (ptr[0] == '\0') return ptr;
|
||||
if (ptr[0] == '*' && ptr[1] == '/') return ptr + 2;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
inline static const char *skipCppStyleComment(const char *ptr) {
|
||||
ptr += 2;
|
||||
for (;;) {
|
||||
if (ptr[0] == '\0' || ptr[0] == '\n') return ptr;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
const char *ArduinoJson::Internals::skipSpacesAndComments(const char *ptr) {
|
||||
for (;;) {
|
||||
switch (ptr[0]) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
ptr++;
|
||||
continue;
|
||||
case '/':
|
||||
switch (ptr[1]) {
|
||||
case '*':
|
||||
ptr = skipCStyleComment(ptr);
|
||||
break;
|
||||
case '/':
|
||||
ptr = skipCppStyleComment(ptr);
|
||||
break;
|
||||
default:
|
||||
return ptr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
}
|
12
src/Internals/Encoding.cpp
Normal file
12
src/Internals/Encoding.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../../include/ArduinoJson/Internals/Encoding.hpp"
|
||||
|
||||
// How to escape special chars:
|
||||
// _escapeTable[2*i+1] => the special char
|
||||
// _escapeTable[2*i] => the char to use instead
|
||||
const char ArduinoJson::Internals::Encoding::_escapeTable[] = "\"\"\\\\b\bf\fn\nr\rt\t";
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -6,10 +6,8 @@
|
||||
|
||||
#include "../../include/ArduinoJson/Internals/JsonParser.hpp"
|
||||
|
||||
#include <stdlib.h> // for strtol, strtod
|
||||
#include <ctype.h>
|
||||
|
||||
#include "../../include/ArduinoJson/Internals/QuotedString.hpp"
|
||||
#include "../../include/ArduinoJson/Internals/Comments.hpp"
|
||||
#include "../../include/ArduinoJson/Internals/Encoding.hpp"
|
||||
#include "../../include/ArduinoJson/JsonArray.hpp"
|
||||
#include "../../include/ArduinoJson/JsonBuffer.hpp"
|
||||
#include "../../include/ArduinoJson/JsonObject.hpp"
|
||||
@ -17,73 +15,35 @@
|
||||
using namespace ArduinoJson;
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
void JsonParser::skipSpaces() {
|
||||
while (isspace(*_ptr)) _ptr++;
|
||||
}
|
||||
|
||||
bool JsonParser::skip(char charToSkip) {
|
||||
skipSpaces();
|
||||
if (*_ptr != charToSkip) return false;
|
||||
_ptr++;
|
||||
skipSpaces();
|
||||
const char *ptr = skipSpacesAndComments(_readPtr);
|
||||
if (*ptr != charToSkip) return false;
|
||||
ptr++;
|
||||
_readPtr = skipSpacesAndComments(ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonParser::skip(const char *wordToSkip) {
|
||||
const char *charToSkip = wordToSkip;
|
||||
while (*charToSkip && *_ptr == *charToSkip) {
|
||||
charToSkip++;
|
||||
_ptr++;
|
||||
}
|
||||
return *charToSkip == '\0';
|
||||
bool JsonParser::parseAnythingTo(JsonVariant *destination) {
|
||||
if (_nestingLimit == 0) return false;
|
||||
_nestingLimit--;
|
||||
bool success = parseAnythingToUnsafe(destination);
|
||||
_nestingLimit++;
|
||||
return success;
|
||||
}
|
||||
|
||||
void JsonParser::parseAnythingTo(JsonVariant &destination) {
|
||||
if (_nestingLimit == 0) return;
|
||||
_nestingLimit--;
|
||||
inline bool JsonParser::parseAnythingToUnsafe(JsonVariant *destination) {
|
||||
_readPtr = skipSpacesAndComments(_readPtr);
|
||||
|
||||
skipSpaces();
|
||||
|
||||
switch (*_ptr) {
|
||||
switch (*_readPtr) {
|
||||
case '[':
|
||||
destination = parseArray();
|
||||
break;
|
||||
return parseArrayTo(destination);
|
||||
|
||||
case '{':
|
||||
destination = parseObject();
|
||||
break;
|
||||
return parseObjectTo(destination);
|
||||
|
||||
case 't':
|
||||
case 'f':
|
||||
parseBooleanTo(destination);
|
||||
break;
|
||||
|
||||
case '-':
|
||||
case '.':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
parseNumberTo(destination);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
parseNullTo(destination);
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
case '\"':
|
||||
destination = parseString();
|
||||
break;
|
||||
default:
|
||||
return parseStringTo(destination);
|
||||
}
|
||||
|
||||
_nestingLimit++;
|
||||
}
|
||||
|
||||
JsonArray &JsonParser::parseArray() {
|
||||
@ -97,9 +57,9 @@ JsonArray &JsonParser::parseArray() {
|
||||
// Read each value
|
||||
for (;;) {
|
||||
// 1 - Parse value
|
||||
JsonVariant &value = array.add();
|
||||
parseAnythingTo(value);
|
||||
if (!value.success()) goto ERROR_INVALID_VALUE;
|
||||
JsonVariant value;
|
||||
if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE;
|
||||
if (!array.add(value)) goto ERROR_NO_MEMORY;
|
||||
|
||||
// 2 - More values?
|
||||
if (skip(']')) goto SUCCES_NON_EMPTY_ARRAY;
|
||||
@ -113,9 +73,18 @@ SUCCES_NON_EMPTY_ARRAY:
|
||||
ERROR_INVALID_VALUE:
|
||||
ERROR_MISSING_BRACKET:
|
||||
ERROR_MISSING_COMMA:
|
||||
ERROR_NO_MEMORY:
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
|
||||
bool JsonParser::parseArrayTo(JsonVariant *destination) {
|
||||
JsonArray &array = parseArray();
|
||||
if (!array.success()) return false;
|
||||
|
||||
*destination = array;
|
||||
return true;
|
||||
}
|
||||
|
||||
JsonObject &JsonParser::parseObject() {
|
||||
// Create an empty object
|
||||
JsonObject &object = _buffer->createObject();
|
||||
@ -132,9 +101,9 @@ JsonObject &JsonParser::parseObject() {
|
||||
if (!skip(':')) goto ERROR_MISSING_COLON;
|
||||
|
||||
// 2 - Parse value
|
||||
JsonVariant &value = object.add(key);
|
||||
parseAnythingTo(value);
|
||||
if (!value.success()) goto ERROR_INVALID_VALUE;
|
||||
JsonVariant value;
|
||||
if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE;
|
||||
if (!object.set(key, value)) goto ERROR_NO_MEMORY;
|
||||
|
||||
// 3 - More keys/values?
|
||||
if (skip('}')) goto SUCCESS_NON_EMPTY_OBJECT;
|
||||
@ -150,48 +119,82 @@ ERROR_INVALID_VALUE:
|
||||
ERROR_MISSING_BRACE:
|
||||
ERROR_MISSING_COLON:
|
||||
ERROR_MISSING_COMMA:
|
||||
ERROR_NO_MEMORY:
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
|
||||
void JsonParser::parseBooleanTo(JsonVariant &destination) {
|
||||
if (skip("true"))
|
||||
destination = true;
|
||||
else if (skip("false"))
|
||||
destination = false;
|
||||
else
|
||||
destination = JsonVariant::invalid();
|
||||
bool JsonParser::parseObjectTo(JsonVariant *destination) {
|
||||
JsonObject &object = parseObject();
|
||||
if (!object.success()) return false;
|
||||
|
||||
*destination = object;
|
||||
return true;
|
||||
}
|
||||
|
||||
void JsonParser::parseNumberTo(JsonVariant &destination) {
|
||||
char *endOfLong;
|
||||
long longValue = strtol(_ptr, &endOfLong, 10);
|
||||
char stopChar = *endOfLong;
|
||||
|
||||
// Could it be a floating point value?
|
||||
bool couldBeFloat = stopChar == '.' || stopChar == 'e' || stopChar == 'E';
|
||||
|
||||
if (couldBeFloat) {
|
||||
// Yes => parse it as a double
|
||||
double doubleValue = strtod(_ptr, &_ptr);
|
||||
// Count the decimal digits
|
||||
uint8_t decimals = static_cast<uint8_t>(_ptr - endOfLong - 1);
|
||||
// Set the variant as a double
|
||||
destination.set(doubleValue, decimals);
|
||||
} else {
|
||||
// No => set the variant as a long
|
||||
_ptr = endOfLong;
|
||||
destination = longValue;
|
||||
}
|
||||
static inline bool isInRange(char c, char min, char max) {
|
||||
return min <= c && c <= max;
|
||||
}
|
||||
|
||||
void JsonParser::parseNullTo(JsonVariant &destination) {
|
||||
const char *NULL_STRING = NULL;
|
||||
if (skip("null"))
|
||||
destination = NULL_STRING;
|
||||
else
|
||||
destination = JsonVariant::invalid();
|
||||
static inline bool isLetterOrNumber(char c) {
|
||||
return isInRange(c, '0', '9') || isInRange(c, 'a', 'z') ||
|
||||
isInRange(c, 'A', 'Z') || c == '-' || c == '.';
|
||||
}
|
||||
|
||||
static inline bool isQuote(char c) { return c == '\'' || c == '\"'; }
|
||||
|
||||
const char *JsonParser::parseString() {
|
||||
return QuotedString::extractFrom(_ptr, &_ptr);
|
||||
const char *readPtr = _readPtr;
|
||||
char *writePtr = _writePtr;
|
||||
|
||||
char c = *readPtr;
|
||||
|
||||
if (isQuote(c)) { // quotes
|
||||
char stopChar = c;
|
||||
for (;;) {
|
||||
c = *++readPtr;
|
||||
if (c == '\0') break;
|
||||
|
||||
if (c == stopChar) {
|
||||
readPtr++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '\\') {
|
||||
// replace char
|
||||
c = Encoding::unescapeChar(*++readPtr);
|
||||
if (c == '\0') break;
|
||||
}
|
||||
|
||||
*writePtr++ = c;
|
||||
}
|
||||
} else { // no quotes
|
||||
for (;;) {
|
||||
if (!isLetterOrNumber(c)) break;
|
||||
*writePtr++ = c;
|
||||
c = *++readPtr;
|
||||
}
|
||||
}
|
||||
// end the string here
|
||||
*writePtr++ = '\0';
|
||||
|
||||
const char *startPtr = _writePtr;
|
||||
|
||||
// update end ptr
|
||||
_readPtr = readPtr;
|
||||
_writePtr = writePtr;
|
||||
|
||||
// return pointer to unquoted string
|
||||
return startPtr;
|
||||
}
|
||||
|
||||
bool JsonParser::parseStringTo(JsonVariant *destination) {
|
||||
bool hasQuotes = isQuote(_readPtr[0]);
|
||||
const char *value = parseString();
|
||||
if (value == NULL) return false;
|
||||
if (hasQuotes) {
|
||||
*destination = value;
|
||||
} else {
|
||||
*destination = Unparsed(value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -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"
|
||||
|
||||
@ -14,12 +13,27 @@ using namespace ArduinoJson;
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
template <typename T>
|
||||
int List<T>::size() const {
|
||||
int nodeCount = 0;
|
||||
size_t List<T>::size() const {
|
||||
size_t nodeCount = 0;
|
||||
for (node_type *node = _firstNode; node; node = node->next) nodeCount++;
|
||||
return nodeCount;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename List<T>::node_type *List<T>::addNewNode() {
|
||||
node_type *newNode = new (_buffer) node_type();
|
||||
|
||||
if (_firstNode) {
|
||||
node_type *lastNode = _firstNode;
|
||||
while (lastNode->next) lastNode = lastNode->next;
|
||||
lastNode->next = newNode;
|
||||
} else {
|
||||
_firstNode = newNode;
|
||||
}
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void List<T>::removeNode(node_type *nodeToRemove) {
|
||||
if (!nodeToRemove) return;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -33,7 +33,7 @@ inline size_t Prettyfier::handleMarkupChar(uint8_t c) {
|
||||
return handleBlockClose(c);
|
||||
|
||||
case ':':
|
||||
return handleColumn();
|
||||
return handleColon();
|
||||
|
||||
case ',':
|
||||
return handleComma();
|
||||
@ -54,7 +54,7 @@ inline size_t Prettyfier::handleBlockClose(uint8_t c) {
|
||||
return unindentIfNeeded() + _sink.write(c);
|
||||
}
|
||||
|
||||
inline size_t Prettyfier::handleColumn() {
|
||||
inline size_t Prettyfier::handleColon() {
|
||||
return _sink.write(':') + _sink.write(' ');
|
||||
}
|
||||
|
||||
|
@ -1,98 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../../include/ArduinoJson/Internals/QuotedString.hpp"
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
static inline char getSpecialChar(char c) {
|
||||
// Optimized for code size on a 8-bit AVR
|
||||
|
||||
const char *p = "\"\"\\\\\bb\ff\nn\rr\tt\0";
|
||||
|
||||
while (p[0] && p[0] != c) {
|
||||
p += 2;
|
||||
}
|
||||
|
||||
return p[1];
|
||||
}
|
||||
|
||||
static inline size_t printCharTo(char c, Print &p) {
|
||||
char specialChar = getSpecialChar(c);
|
||||
|
||||
return specialChar ? p.write('\\') + p.write(specialChar) : p.write(c);
|
||||
}
|
||||
|
||||
size_t QuotedString::printTo(const char *s, Print &p) {
|
||||
if (!s) return p.print("null");
|
||||
|
||||
size_t n = p.write('\"');
|
||||
|
||||
while (*s) {
|
||||
n += printCharTo(*s++, p);
|
||||
}
|
||||
|
||||
return n + p.write('\"');
|
||||
}
|
||||
|
||||
static char unescapeChar(char c) {
|
||||
// Optimized for code size on a 8-bit AVR
|
||||
|
||||
const char *p = "b\bf\fn\nr\rt\t";
|
||||
|
||||
for (;;) {
|
||||
if (p[0] == '\0') return c;
|
||||
if (p[0] == c) return p[1];
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool isQuote(char c) { return c == '\"' || c == '\''; }
|
||||
|
||||
char *QuotedString::extractFrom(char *input, char **endPtr) {
|
||||
char firstChar = *input;
|
||||
|
||||
if (!isQuote(firstChar)) {
|
||||
// must start with a quote
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char stopChar = firstChar; // closing quote is the same as opening quote
|
||||
|
||||
char *startPtr = input + 1; // skip the quote
|
||||
char *readPtr = startPtr;
|
||||
char *writePtr = startPtr;
|
||||
char c;
|
||||
|
||||
for (;;) {
|
||||
c = *readPtr++;
|
||||
|
||||
if (c == '\0') {
|
||||
// premature ending
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (c == stopChar) {
|
||||
// closing quote
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '\\') {
|
||||
// replace char
|
||||
c = unescapeChar(*readPtr++);
|
||||
}
|
||||
|
||||
*writePtr++ = c;
|
||||
}
|
||||
|
||||
// end the string here
|
||||
*writePtr = '\0';
|
||||
|
||||
// update end ptr
|
||||
*endPtr = readPtr;
|
||||
|
||||
return startPtr;
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../../include/ArduinoJson/Internals/StringBuilder.hpp"
|
||||
#include "../../include/ArduinoJson/Internals/StaticStringBuilder.hpp"
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
size_t StringBuilder::write(uint8_t c) {
|
||||
size_t StaticStringBuilder::write(uint8_t c) {
|
||||
if (length >= capacity) return 0;
|
||||
|
||||
buffer[length++] = c;
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -14,19 +14,10 @@ using namespace ArduinoJson::Internals;
|
||||
|
||||
JsonArray JsonArray::_invalid(NULL);
|
||||
|
||||
JsonVariant &JsonArray::at(int index) const {
|
||||
JsonArray::node_type *JsonArray::getNodeAt(size_t index) const {
|
||||
node_type *node = _firstNode;
|
||||
while (node && index--) node = node->next;
|
||||
return node ? node->content : JsonVariant::invalid();
|
||||
}
|
||||
|
||||
JsonVariant &JsonArray::add() {
|
||||
node_type *node = createNode();
|
||||
if (!node) return JsonVariant::invalid();
|
||||
|
||||
addNode(node);
|
||||
|
||||
return node->content;
|
||||
return node;
|
||||
}
|
||||
|
||||
JsonArray &JsonArray::createNestedArray() {
|
||||
@ -43,6 +34,8 @@ JsonObject &JsonArray::createNestedObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
void JsonArray::removeAt(size_t index) { removeNode(getNodeAt(index)); }
|
||||
|
||||
void JsonArray::writeTo(JsonWriter &writer) const {
|
||||
writer.beginArray();
|
||||
|
||||
|
@ -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) {
|
||||
@ -35,3 +32,10 @@ JsonObject &JsonBuffer::parseObject(char *json, uint8_t nestingLimit) {
|
||||
JsonParser parser(this, json, nestingLimit);
|
||||
return parser.parseObject();
|
||||
}
|
||||
|
||||
char *JsonBuffer::strdup(const char *source, size_t length) {
|
||||
size_t size = length + 1;
|
||||
char *dest = static_cast<char *>(alloc(size));
|
||||
if (dest != NULL) memcpy(dest, source, size);
|
||||
return dest;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -8,8 +8,7 @@
|
||||
|
||||
#include <string.h> // for strcmp
|
||||
|
||||
#include "../include/ArduinoJson/Internals/PlacementNew.hpp"
|
||||
#include "../include/ArduinoJson/Internals/StringBuilder.hpp"
|
||||
#include "../include/ArduinoJson/Internals/StaticStringBuilder.hpp"
|
||||
#include "../include/ArduinoJson/JsonArray.hpp"
|
||||
#include "../include/ArduinoJson/JsonBuffer.hpp"
|
||||
|
||||
@ -18,49 +17,35 @@ using namespace ArduinoJson::Internals;
|
||||
|
||||
JsonObject JsonObject::_invalid(NULL);
|
||||
|
||||
JsonVariant &JsonObject::at(const char *key) {
|
||||
node_type *node = getNodeAt(key);
|
||||
return node ? node->content.value : JsonVariant::invalid();
|
||||
JsonObject::node_type *JsonObject::getOrCreateNodeAt(JsonObjectKey key) {
|
||||
node_type *existingNode = getNodeAt(key);
|
||||
if (existingNode) return existingNode;
|
||||
|
||||
node_type *newNode = addNewNode();
|
||||
return newNode;
|
||||
}
|
||||
|
||||
const JsonVariant &JsonObject::at(const char *key) const {
|
||||
node_type *node = getNodeAt(key);
|
||||
return node ? node->content.value : JsonVariant::invalid();
|
||||
}
|
||||
|
||||
JsonVariant &JsonObject::operator[](const char *key) {
|
||||
// try to find an existing node
|
||||
node_type *node = getNodeAt(key);
|
||||
|
||||
// not fount => create a new one
|
||||
if (!node) {
|
||||
node = createNode();
|
||||
if (!node) return JsonVariant::invalid();
|
||||
|
||||
node->content.key = key;
|
||||
addNode(node);
|
||||
}
|
||||
|
||||
return node->content.value;
|
||||
}
|
||||
|
||||
void JsonObject::remove(char const *key) { removeNode(getNodeAt(key)); }
|
||||
|
||||
JsonArray &JsonObject::createNestedArray(char const *key) {
|
||||
template <typename TKey>
|
||||
JsonArray &JsonObject::createArrayAt(TKey key) {
|
||||
if (!_buffer) return JsonArray::invalid();
|
||||
JsonArray &array = _buffer->createArray();
|
||||
add(key, array);
|
||||
setNodeAt<TKey, const JsonVariant &>(key, array);
|
||||
return array;
|
||||
}
|
||||
template JsonArray &JsonObject::createArrayAt<const char *>(const char *);
|
||||
template JsonArray &JsonObject::createArrayAt<const String &>(const String &);
|
||||
|
||||
JsonObject &JsonObject::createNestedObject(const char *key) {
|
||||
template <typename TKey>
|
||||
JsonObject &JsonObject::createObjectAt(TKey key) {
|
||||
if (!_buffer) return JsonObject::invalid();
|
||||
JsonObject &object = _buffer->createObject();
|
||||
add(key, object);
|
||||
return object;
|
||||
JsonObject &array = _buffer->createObject();
|
||||
setNodeAt<TKey, const JsonVariant &>(key, array);
|
||||
return array;
|
||||
}
|
||||
template JsonObject &JsonObject::createObjectAt<const char *>(const char *);
|
||||
template JsonObject &JsonObject::createObjectAt<const String &>(const String &);
|
||||
|
||||
JsonObject::node_type *JsonObject::getNodeAt(const char *key) const {
|
||||
JsonObject::node_type *JsonObject::getNodeAt(JsonObjectKey key) const {
|
||||
for (node_type *node = _firstNode; node; node = node->next) {
|
||||
if (!strcmp(node->content.key, key)) return node;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -9,100 +9,138 @@
|
||||
#include "../include/ArduinoJson/JsonArray.hpp"
|
||||
#include "../include/ArduinoJson/JsonObject.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
||||
#include <errno.h> // for errno
|
||||
#include <stdlib.h> // for strtol, strtod
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
JsonVariant JsonVariant::_invalid(JSON_INVALID);
|
||||
namespace ArduinoJson {
|
||||
|
||||
JsonVariant::operator JsonArray &() const {
|
||||
return _type == JSON_ARRAY ? *_content.asArray : JsonArray::invalid();
|
||||
template <typename TFloat>
|
||||
static TFloat parse(const char *);
|
||||
|
||||
template <>
|
||||
float parse<float>(const char *s) {
|
||||
return static_cast<float>(strtod(s, NULL));
|
||||
}
|
||||
|
||||
JsonVariant::operator JsonObject &() const {
|
||||
return _type == JSON_OBJECT ? *_content.asObject : JsonObject::invalid();
|
||||
template <>
|
||||
double parse<double>(const char *s) {
|
||||
return strtod(s, NULL);
|
||||
}
|
||||
|
||||
JsonVariant::operator bool() const {
|
||||
return _type == JSON_BOOLEAN ? _content.asBoolean : false;
|
||||
template <>
|
||||
long parse<long>(const char *s) {
|
||||
return strtol(s, NULL, 10);
|
||||
}
|
||||
|
||||
JsonVariant::operator const char *() const {
|
||||
return _type == JSON_STRING ? _content.asString : NULL;
|
||||
template <>
|
||||
int parse<int>(const char *s) {
|
||||
return atoi(s);
|
||||
}
|
||||
|
||||
JsonVariant::operator double() const {
|
||||
return _type >= JSON_DOUBLE_0_DECIMALS ? _content.asDouble : 0;
|
||||
template <>
|
||||
const char *JsonVariant::as<const char *>() const {
|
||||
if (_type == JSON_UNPARSED && _content.asString &&
|
||||
!strcmp("null", _content.asString))
|
||||
return NULL;
|
||||
if (_type == JSON_STRING || _type == JSON_UNPARSED) return _content.asString;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JsonVariant::operator long() const {
|
||||
return _type == JSON_LONG ? _content.asLong : 0;
|
||||
JsonFloat JsonVariant::asFloat() const {
|
||||
if (_type >= JSON_FLOAT_0_DECIMALS) return _content.asFloat;
|
||||
|
||||
if (_type == JSON_INTEGER || _type == JSON_BOOLEAN)
|
||||
return static_cast<JsonFloat>(_content.asInteger);
|
||||
|
||||
if ((_type == JSON_STRING || _type == JSON_UNPARSED) && _content.asString)
|
||||
return parse<JsonFloat>(_content.asString);
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void JsonVariant::set(bool value) {
|
||||
if (_type == JSON_INVALID) return;
|
||||
_type = Internals::JSON_BOOLEAN;
|
||||
_content.asBoolean = value;
|
||||
JsonInteger JsonVariant::asInteger() const {
|
||||
if (_type == JSON_INTEGER || _type == JSON_BOOLEAN) return _content.asInteger;
|
||||
|
||||
if (_type >= JSON_FLOAT_0_DECIMALS)
|
||||
return static_cast<JsonInteger>(_content.asFloat);
|
||||
|
||||
if ((_type == JSON_STRING || _type == JSON_UNPARSED) && _content.asString) {
|
||||
if (!strcmp("true", _content.asString)) return 1;
|
||||
return parse<JsonInteger>(_content.asString);
|
||||
}
|
||||
|
||||
return 0L;
|
||||
}
|
||||
|
||||
void JsonVariant::set(const char *value) {
|
||||
if (_type == JSON_INVALID) return;
|
||||
_type = JSON_STRING;
|
||||
_content.asString = value;
|
||||
template <>
|
||||
String JsonVariant::as<String>() const {
|
||||
if ((_type == JSON_STRING || _type == JSON_UNPARSED) &&
|
||||
_content.asString != NULL)
|
||||
return String(_content.asString);
|
||||
|
||||
if (_type == JSON_INTEGER || _type == JSON_BOOLEAN)
|
||||
return String(_content.asInteger);
|
||||
|
||||
if (_type >= JSON_FLOAT_0_DECIMALS) {
|
||||
uint8_t decimals = static_cast<uint8_t>(_type - JSON_FLOAT_0_DECIMALS);
|
||||
return String(_content.asFloat, decimals);
|
||||
}
|
||||
|
||||
String s;
|
||||
printTo(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
void JsonVariant::set(double value, uint8_t decimals) {
|
||||
if (_type == JSON_INVALID) return;
|
||||
_type = static_cast<JsonVariantType>(JSON_DOUBLE_0_DECIMALS + decimals);
|
||||
_content.asDouble = value;
|
||||
template <>
|
||||
bool JsonVariant::is<signed long>() const {
|
||||
if (_type == JSON_INTEGER) return true;
|
||||
|
||||
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
|
||||
|
||||
char *end;
|
||||
errno = 0;
|
||||
strtol(_content.asString, &end, 10);
|
||||
|
||||
return *end == '\0' && errno == 0;
|
||||
}
|
||||
|
||||
void JsonVariant::set(long value) {
|
||||
if (_type == JSON_INVALID) return;
|
||||
_type = JSON_LONG;
|
||||
_content.asLong = value;
|
||||
}
|
||||
template <>
|
||||
bool JsonVariant::is<double>() const {
|
||||
if (_type >= JSON_FLOAT_0_DECIMALS) return true;
|
||||
|
||||
void JsonVariant::set(JsonArray &array) {
|
||||
if (_type == JSON_INVALID) return;
|
||||
_type = JSON_ARRAY;
|
||||
_content.asArray = &array;
|
||||
}
|
||||
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
|
||||
|
||||
void JsonVariant::set(JsonObject &object) {
|
||||
if (_type == JSON_INVALID) return;
|
||||
_type = JSON_OBJECT;
|
||||
_content.asObject = &object;
|
||||
}
|
||||
char *end;
|
||||
errno = 0;
|
||||
strtod(_content.asString, &end);
|
||||
|
||||
size_t JsonVariant::size() const {
|
||||
if (_type == JSON_ARRAY) return _content.asArray->size();
|
||||
if (_type == JSON_OBJECT) return _content.asObject->size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JsonVariant &JsonVariant::operator[](int index) {
|
||||
if (_type != JSON_ARRAY) return JsonVariant::invalid();
|
||||
return _content.asArray->operator[](index);
|
||||
}
|
||||
|
||||
JsonVariant &JsonVariant::operator[](const char *key) {
|
||||
if (_type != JSON_OBJECT) return JsonVariant::invalid();
|
||||
return _content.asObject->operator[](key);
|
||||
return *end == '\0' && errno == 0 && !is<long>();
|
||||
}
|
||||
|
||||
void JsonVariant::writeTo(JsonWriter &writer) const {
|
||||
if (is<const JsonArray &>())
|
||||
as<const JsonArray &>().writeTo(writer);
|
||||
else if (is<const JsonObject &>())
|
||||
as<const JsonObject &>().writeTo(writer);
|
||||
else if (is<const char *>())
|
||||
writer.writeString(as<const char *>());
|
||||
else if (is<long>())
|
||||
writer.writeLong(as<long>());
|
||||
else if (is<bool>())
|
||||
writer.writeBoolean(as<bool>());
|
||||
else if (is<double>()) {
|
||||
uint8_t decimals = static_cast<uint8_t>(_type - JSON_DOUBLE_0_DECIMALS);
|
||||
writer.writeDouble(as<double>(), decimals);
|
||||
if (_type == JSON_ARRAY)
|
||||
_content.asArray->writeTo(writer);
|
||||
|
||||
else if (_type == JSON_OBJECT)
|
||||
_content.asObject->writeTo(writer);
|
||||
|
||||
else if (_type == JSON_STRING)
|
||||
writer.writeString(_content.asString);
|
||||
|
||||
else if (_type == JSON_UNPARSED)
|
||||
writer.writeRaw(_content.asString);
|
||||
|
||||
else if (_type == JSON_INTEGER)
|
||||
writer.writeInteger(_content.asInteger);
|
||||
|
||||
else if (_type == JSON_BOOLEAN)
|
||||
writer.writeBoolean(_content.asInteger != 0);
|
||||
|
||||
else if (_type >= JSON_FLOAT_0_DECIMALS) {
|
||||
uint8_t decimals = static_cast<uint8_t>(_type - JSON_FLOAT_0_DECIMALS);
|
||||
writer.writeFloat(_content.asFloat, decimals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
220
test/ArduinoString_Tests.cpp
Normal file
220
test/ArduinoString_Tests.cpp
Normal file
@ -0,0 +1,220 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class ArduinoStringTests : public ::testing::Test {
|
||||
protected:
|
||||
static void eraseString(String &str) {
|
||||
char *p = const_cast<char *>(str.c_str());
|
||||
while (*p) *p++ = '*';
|
||||
}
|
||||
|
||||
DynamicJsonBuffer _jsonBuffer;
|
||||
};
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonBuffer_ParseArray) {
|
||||
String json("[\"hello\"]");
|
||||
JsonArray &array = _jsonBuffer.parseArray(json);
|
||||
eraseString(json);
|
||||
ASSERT_TRUE(array.success());
|
||||
ASSERT_STREQ("hello", array[0]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonBuffer_ParseObject) {
|
||||
String json("{\"hello\":\"world\"}");
|
||||
JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
eraseString(json);
|
||||
ASSERT_TRUE(object.success());
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_Subscript) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
ASSERT_STREQ("value", object[String("key")]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_ConstSubscript) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
const JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
ASSERT_STREQ("value", object[String("key")]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_SetKey) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
String key("hello");
|
||||
object.set(key, "world");
|
||||
eraseString(key);
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_SetValue) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
String value("world");
|
||||
object.set("hello", value);
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_SetKeyValue) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
String key("hello");
|
||||
String value("world");
|
||||
object.set(key, value);
|
||||
eraseString(key);
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_SetToArraySubscript) {
|
||||
JsonArray &arr = _jsonBuffer.createArray();
|
||||
arr.add("world");
|
||||
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
object.set(String("hello"), arr[0]);
|
||||
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_SetToObjectSubscript) {
|
||||
JsonObject &arr = _jsonBuffer.createObject();
|
||||
arr.set("x", "world");
|
||||
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
object.set(String("hello"), arr["x"]);
|
||||
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_Get) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
const JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
ASSERT_STREQ("value", object.get(String("key")));
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_GetT) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
const JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
ASSERT_STREQ("value", object.get<const char *>(String("key")));
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_IsT) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
const JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
ASSERT_TRUE(object.is<const char *>(String("key")));
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_CreateNestedObject) {
|
||||
String key = "key";
|
||||
char json[64];
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
object.createNestedObject(key);
|
||||
eraseString(key);
|
||||
object.printTo(json, sizeof(json));
|
||||
ASSERT_STREQ("{\"key\":{}}", json);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_CreateNestedArray) {
|
||||
String key = "key";
|
||||
char json[64];
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
object.createNestedArray(key);
|
||||
eraseString(key);
|
||||
object.printTo(json, sizeof(json));
|
||||
ASSERT_STREQ("{\"key\":[]}", json);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_ContainsKey) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
const JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
ASSERT_TRUE(object.containsKey(String("key")));
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_Remove) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
ASSERT_EQ(1, object.size());
|
||||
object.remove(String("key"));
|
||||
ASSERT_EQ(0, object.size());
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObjectSubscript_SetKey) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
String key("hello");
|
||||
object[key] = "world";
|
||||
eraseString(key);
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObjectSubscript_SetValue) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
String value("world");
|
||||
object["hello"] = value;
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonArray_Add) {
|
||||
JsonArray &array = _jsonBuffer.createArray();
|
||||
String value("hello");
|
||||
array.add(value);
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("hello", array[0]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonArray_Set) {
|
||||
JsonArray &array = _jsonBuffer.createArray();
|
||||
String value("world");
|
||||
array.add("hello");
|
||||
array.set(0, value);
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("world", array[0]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonArraySubscript) {
|
||||
JsonArray &array = _jsonBuffer.createArray();
|
||||
String value("world");
|
||||
array.add("hello");
|
||||
array[0] = value;
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("world", array[0]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonArray_PrintTo) {
|
||||
JsonArray &array = _jsonBuffer.createArray();
|
||||
array.add(4);
|
||||
array.add(2);
|
||||
String json;
|
||||
array.printTo(json);
|
||||
ASSERT_EQ(String("[4,2]"), json);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonArray_PrettyPrintTo) {
|
||||
JsonArray &array = _jsonBuffer.createArray();
|
||||
array.add(4);
|
||||
array.add(2);
|
||||
String json;
|
||||
array.prettyPrintTo(json);
|
||||
ASSERT_EQ(String("[\r\n 4,\r\n 2\r\n]"), json);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_PrintTo) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
object["key"] = "value";
|
||||
String json;
|
||||
object.printTo(json);
|
||||
ASSERT_EQ(String("{\"key\":\"value\"}"), json);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_PrettyPrintTo) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
object["key"] = "value";
|
||||
String json;
|
||||
object.prettyPrintTo(json);
|
||||
ASSERT_EQ(String("{\r\n \"key\": \"value\"\r\n}"), json);
|
||||
}
|
@ -10,6 +10,11 @@ include_directories(
|
||||
|
||||
add_definitions(-DGTEST_HAS_PTHREAD=0)
|
||||
|
||||
# Workaround for Visual Studio 2012
|
||||
if (MSVC AND MSVC_VERSION EQUAL 1700)
|
||||
add_definitions(-D_VARIADIC_MAX=10)
|
||||
endif()
|
||||
|
||||
add_executable(ArduinoJsonTests
|
||||
${TESTS_FILES}
|
||||
${INC_FILES}
|
||||
@ -18,4 +23,4 @@ add_executable(ArduinoJsonTests
|
||||
|
||||
target_link_libraries(ArduinoJsonTests ArduinoJson)
|
||||
|
||||
add_test(ArduinoJsonTests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ArduinoJsonTests)
|
||||
add_test(ArduinoJsonTests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ArduinoJsonTests)
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -20,40 +20,11 @@ TEST_F(DynamicJsonBuffer_Basic_Tests, InitialSizeIsZero) {
|
||||
ASSERT_EQ(0, buffer.size());
|
||||
}
|
||||
|
||||
TEST_F(DynamicJsonBuffer_Basic_Tests, InitialBlockCountIsOne) {
|
||||
ASSERT_EQ(1, buffer.blockCount());
|
||||
}
|
||||
|
||||
TEST_F(DynamicJsonBuffer_Basic_Tests, SizeIncreasesAfterAlloc) {
|
||||
buffer.alloc(1);
|
||||
ASSERT_EQ(1, buffer.size());
|
||||
ASSERT_LE(1U, buffer.size());
|
||||
buffer.alloc(1);
|
||||
ASSERT_EQ(2, buffer.size());
|
||||
buffer.alloc(DynamicJsonBuffer::BLOCK_CAPACITY);
|
||||
ASSERT_EQ(2 + DynamicJsonBuffer::BLOCK_CAPACITY, buffer.size());
|
||||
}
|
||||
|
||||
TEST_F(DynamicJsonBuffer_Basic_Tests, BlockCountDoesntChangeWhenNotFull) {
|
||||
buffer.alloc(DynamicJsonBuffer::BLOCK_CAPACITY);
|
||||
ASSERT_EQ(1, buffer.blockCount());
|
||||
}
|
||||
|
||||
TEST_F(DynamicJsonBuffer_Basic_Tests, BlockCountChangesWhenFull) {
|
||||
buffer.alloc(DynamicJsonBuffer::BLOCK_CAPACITY);
|
||||
buffer.alloc(1);
|
||||
ASSERT_EQ(2, buffer.blockCount());
|
||||
}
|
||||
|
||||
TEST_F(DynamicJsonBuffer_Basic_Tests, CanAllocLessThanBlockCapacity) {
|
||||
void* p1 = buffer.alloc(DynamicJsonBuffer::BLOCK_CAPACITY);
|
||||
ASSERT_TRUE(p1);
|
||||
void* p2 = buffer.alloc(DynamicJsonBuffer::BLOCK_CAPACITY);
|
||||
ASSERT_TRUE(p2);
|
||||
}
|
||||
|
||||
TEST_F(DynamicJsonBuffer_Basic_Tests, CantAllocMoreThanBlockCapacity) {
|
||||
void* p = buffer.alloc(DynamicJsonBuffer::BLOCK_CAPACITY + 1);
|
||||
ASSERT_FALSE(p);
|
||||
ASSERT_LE(2U, buffer.size());
|
||||
}
|
||||
|
||||
TEST_F(DynamicJsonBuffer_Basic_Tests, ReturnDifferentPointer) {
|
||||
@ -61,3 +32,12 @@ TEST_F(DynamicJsonBuffer_Basic_Tests, ReturnDifferentPointer) {
|
||||
void* p2 = buffer.alloc(2);
|
||||
ASSERT_NE(p1, p2);
|
||||
}
|
||||
|
||||
TEST_F(DynamicJsonBuffer_Basic_Tests, Alignment) {
|
||||
size_t mask = sizeof(void*) - 1;
|
||||
|
||||
for (size_t size = 1; size <= sizeof(void*); size++) {
|
||||
size_t addr = reinterpret_cast<size_t>(buffer.alloc(1));
|
||||
ASSERT_EQ(0, addr & mask);
|
||||
}
|
||||
}
|
||||
|
42
test/DynamicJsonBuffer_NoMemory_Tests.cpp
Normal file
42
test/DynamicJsonBuffer_NoMemory_Tests.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class NoMemoryAllocator {
|
||||
public:
|
||||
void* allocate(size_t) { return NULL; }
|
||||
void deallocate(void*) {}
|
||||
};
|
||||
|
||||
class DynamicJsonBuffer_NoMemory_Tests : public ::testing::Test {
|
||||
protected:
|
||||
Internals::BlockJsonBuffer<NoMemoryAllocator> _jsonBuffer;
|
||||
};
|
||||
|
||||
TEST_F(DynamicJsonBuffer_NoMemory_Tests, FixCodeCoverage) {
|
||||
// call this function to fix code coverage
|
||||
NoMemoryAllocator().deallocate(NULL);
|
||||
}
|
||||
|
||||
TEST_F(DynamicJsonBuffer_NoMemory_Tests, CreateArray) {
|
||||
ASSERT_FALSE(_jsonBuffer.createArray().success());
|
||||
}
|
||||
|
||||
TEST_F(DynamicJsonBuffer_NoMemory_Tests, CreateObject) {
|
||||
ASSERT_FALSE(_jsonBuffer.createObject().success());
|
||||
}
|
||||
|
||||
TEST_F(DynamicJsonBuffer_NoMemory_Tests, ParseArray) {
|
||||
char json[] = "[]";
|
||||
ASSERT_FALSE(_jsonBuffer.parseArray(json).success());
|
||||
}
|
||||
|
||||
TEST_F(DynamicJsonBuffer_NoMemory_Tests, ParseObject) {
|
||||
char json[] = "{}";
|
||||
ASSERT_FALSE(_jsonBuffer.parseObject(json).success());
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -13,12 +13,12 @@ TEST(DynamicJsonBuffer_Object_Tests, GrowsWithObject) {
|
||||
JsonObject &obj = json.createObject();
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(0), json.size());
|
||||
|
||||
obj["hello"];
|
||||
obj["hello"] = 1;
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(1), json.size());
|
||||
|
||||
obj["world"];
|
||||
obj["world"] = 2;
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size());
|
||||
|
||||
obj["world"]; // <- same value, should not grow
|
||||
obj["world"] = 3; // <- same key, should not grow
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size());
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#define ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include <ArduinoJson.h>
|
||||
#include "Printers.hpp"
|
||||
|
||||
class GbathreeBug : public testing::Test {
|
||||
public:
|
||||
@ -37,7 +37,7 @@ class GbathreeBug : public testing::Test {
|
||||
TEST_F(GbathreeBug, Success) { EXPECT_TRUE(_object.success()); }
|
||||
|
||||
TEST_F(GbathreeBug, ProtocolName) {
|
||||
EXPECT_STREQ("fluorescence", _object.at("protocol_name").asString());
|
||||
EXPECT_STREQ("fluorescence", _object["protocol_name"]);
|
||||
}
|
||||
|
||||
TEST_F(GbathreeBug, Repeats) { EXPECT_EQ(1, _object["repeats"]); }
|
||||
@ -69,7 +69,7 @@ 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["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["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["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["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["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["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["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["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["altd"];
|
||||
EXPECT_TRUE(array.success());
|
||||
|
||||
EXPECT_EQ(4, array.size());
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
|
47
test/Issue67.cpp
Normal file
47
test/Issue67.cpp
Normal 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");
|
||||
}
|
28
test/Issue90.cpp
Normal file
28
test/Issue90.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <limits.h> // for LONG_MAX
|
||||
#define ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#define SUITE Issue90
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
static const char* superLong =
|
||||
"12345678901234567890123456789012345678901234567890123456789012345678901234"
|
||||
"5678901234567890123456789012345678901234567890123456789012345678901234567";
|
||||
|
||||
static const JsonVariant variant = Unparsed(superLong);
|
||||
|
||||
TEST(SUITE, IsNotALong) { ASSERT_FALSE(variant.is<long>()); }
|
||||
|
||||
TEST(SUITE, AsLong) { ASSERT_EQ(LONG_MAX, variant.as<long>()); }
|
||||
|
||||
TEST(SUITE, IsAString) { ASSERT_FALSE(variant.is<const char*>()); }
|
||||
|
||||
TEST(SUITE, AsString) { ASSERT_STREQ(superLong, variant.as<const char*>()); }
|
90
test/JsonArray_Add_Tests.cpp
Normal file
90
test/JsonArray_Add_Tests.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#define ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonArray_Add_Tests : public ::testing::Test {
|
||||
protected:
|
||||
JsonArray_Add_Tests() : _array(_jsonBuffer.createArray()) {}
|
||||
|
||||
DynamicJsonBuffer _jsonBuffer;
|
||||
JsonArray& _array;
|
||||
};
|
||||
|
||||
#define TEST_(name) TEST_F(JsonArray_Add_Tests, name)
|
||||
|
||||
TEST_(SizeIncreased_WhenValuesAreAdded) {
|
||||
_array.add("hello");
|
||||
EXPECT_EQ(1U, _array.size());
|
||||
}
|
||||
|
||||
TEST_(StoreInteger) {
|
||||
_array.add(123);
|
||||
EXPECT_EQ(123, _array[0].as<int>());
|
||||
EXPECT_TRUE(_array[0].is<int>());
|
||||
EXPECT_FALSE(_array[0].is<double>());
|
||||
}
|
||||
|
||||
TEST_(StoreDouble) {
|
||||
_array.add(123.45);
|
||||
EXPECT_EQ(123.45, _array[0].as<double>());
|
||||
EXPECT_TRUE(_array[0].is<double>());
|
||||
EXPECT_FALSE(_array[0].is<int>());
|
||||
}
|
||||
|
||||
TEST_(StoreBoolean) {
|
||||
_array.add(true);
|
||||
EXPECT_EQ(true, _array[0].as<bool>());
|
||||
EXPECT_TRUE(_array[0].is<bool>());
|
||||
EXPECT_FALSE(_array[0].is<int>());
|
||||
}
|
||||
|
||||
TEST_(StoreString) {
|
||||
_array.add("hello");
|
||||
EXPECT_STREQ("hello", _array[0].as<const char*>());
|
||||
EXPECT_TRUE(_array[0].is<const char*>());
|
||||
EXPECT_FALSE(_array[0].is<int>());
|
||||
}
|
||||
|
||||
TEST_(StoreNestedArray) {
|
||||
JsonArray& arr = _jsonBuffer.createArray();
|
||||
|
||||
_array.add(arr);
|
||||
|
||||
EXPECT_EQ(&arr, &_array[0].as<JsonArray&>());
|
||||
EXPECT_TRUE(_array[0].is<JsonArray&>());
|
||||
EXPECT_FALSE(_array[0].is<int>());
|
||||
}
|
||||
|
||||
TEST_(StoreNestedObject) {
|
||||
JsonObject& obj = _jsonBuffer.createObject();
|
||||
|
||||
_array.add(obj);
|
||||
|
||||
EXPECT_EQ(&obj, &_array[0].as<JsonObject&>());
|
||||
EXPECT_TRUE(_array[0].is<JsonObject&>());
|
||||
EXPECT_FALSE(_array[0].is<int>());
|
||||
}
|
||||
|
||||
TEST_(StoreArraySubscript) {
|
||||
JsonArray& arr = _jsonBuffer.createArray();
|
||||
arr.add("hello");
|
||||
|
||||
_array.add(arr[0]);
|
||||
|
||||
EXPECT_STREQ("hello", _array[0]);
|
||||
}
|
||||
|
||||
TEST_(StoreObjectSubscript) {
|
||||
JsonObject& obj = _jsonBuffer.createObject();
|
||||
obj["x"] = "hello";
|
||||
|
||||
_array.add(obj["x"]);
|
||||
|
||||
EXPECT_STREQ("hello", _array[0]);
|
||||
}
|
41
test/JsonArray_Basic_Tests.cpp
Normal file
41
test/JsonArray_Basic_Tests.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#define ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#define TEST_(name) TEST(JsonArray_Basic_Tests, name)
|
||||
|
||||
TEST_(SuccessIsTrue) {
|
||||
DynamicJsonBuffer _jsonBuffer;
|
||||
JsonArray& array = _jsonBuffer.createArray();
|
||||
|
||||
EXPECT_TRUE(array.success());
|
||||
}
|
||||
|
||||
TEST_(InitialSizeIsZero) {
|
||||
DynamicJsonBuffer _jsonBuffer;
|
||||
JsonArray& array = _jsonBuffer.createArray();
|
||||
|
||||
EXPECT_EQ(0U, array.size());
|
||||
}
|
||||
|
||||
TEST_(CreateNestedArray) {
|
||||
DynamicJsonBuffer _jsonBuffer;
|
||||
JsonArray& array = _jsonBuffer.createArray();
|
||||
|
||||
JsonArray& arr = array.createNestedArray();
|
||||
EXPECT_EQ(&arr, &array[0].as<JsonArray&>());
|
||||
}
|
||||
|
||||
TEST_(CreateNestedObject) {
|
||||
DynamicJsonBuffer _jsonBuffer;
|
||||
JsonArray& array = _jsonBuffer.createArray();
|
||||
|
||||
JsonObject& obj = array.createNestedObject();
|
||||
EXPECT_EQ(&obj, &array[0].as<JsonObject&>());
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonArray_Container_Tests : public ::testing::Test {
|
||||
protected:
|
||||
JsonArray_Container_Tests() : _array(_jsonBuffer.createArray()) {}
|
||||
|
||||
template <typename T>
|
||||
void firstMustEqual(T expected) {
|
||||
itemMustEqual(0, expected);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void secondMustEqual(T expected) {
|
||||
itemMustEqual(1, expected);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void firstMustReference(const T& expected) {
|
||||
itemMustReference(0, expected);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void secondMustReference(const T& expected) {
|
||||
itemMustReference(1, expected);
|
||||
}
|
||||
|
||||
void sizeMustBe(int expected) { EXPECT_EQ(expected, _array.size()); }
|
||||
|
||||
DynamicJsonBuffer _jsonBuffer;
|
||||
JsonArray& _array;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void itemMustEqual(int index, T expected) {
|
||||
EXPECT_EQ(expected, _array[index].as<T>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void itemMustReference(int index, const T& expected) {
|
||||
EXPECT_EQ(&expected, &_array[index].as<T&>());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, SuccessIsTrue) {
|
||||
EXPECT_TRUE(_array.success());
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, InitialSizeIsZero) { sizeMustBe(0); }
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, Grow_WhenValuesAreAdded) {
|
||||
_array.add("hello");
|
||||
sizeMustBe(1);
|
||||
|
||||
_array.add("world");
|
||||
sizeMustBe(2);
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, CanStoreIntegers) {
|
||||
_array.add(123);
|
||||
_array.add(456);
|
||||
|
||||
firstMustEqual(123);
|
||||
secondMustEqual(456);
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, CanStoreDoubles) {
|
||||
_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);
|
||||
|
||||
firstMustEqual(true);
|
||||
secondMustEqual(false);
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, CanStoreStrings) {
|
||||
const char* firstString = "h3110";
|
||||
const char* secondString = "w0r1d";
|
||||
|
||||
_array.add(firstString);
|
||||
_array.add(secondString);
|
||||
|
||||
firstMustEqual(firstString);
|
||||
secondMustEqual(secondString);
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, CanStoreNestedArrays) {
|
||||
JsonArray& inner_array1 = _jsonBuffer.createArray();
|
||||
JsonArray& inner_array2 = _jsonBuffer.createArray();
|
||||
|
||||
_array.add(inner_array1);
|
||||
_array.add(inner_array2);
|
||||
|
||||
firstMustReference(inner_array1);
|
||||
secondMustReference(inner_array2);
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, CanStoreNestedObjects) {
|
||||
JsonObject& innerObject1 = _jsonBuffer.createObject();
|
||||
JsonObject& innerObject2 = _jsonBuffer.createObject();
|
||||
|
||||
_array.add(innerObject1);
|
||||
_array.add(innerObject2);
|
||||
|
||||
firstMustReference(innerObject1);
|
||||
secondMustReference(innerObject2);
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, CanCreateNestedArrays) {
|
||||
JsonArray& inner_array1 = _array.createNestedArray();
|
||||
JsonArray& inner_array2 = _array.createNestedArray();
|
||||
|
||||
firstMustReference(inner_array1);
|
||||
secondMustReference(inner_array2);
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, CanCreateNestedObjects) {
|
||||
JsonObject& innerObject1 = _array.createNestedObject();
|
||||
JsonObject& innerObject2 = _array.createNestedObject();
|
||||
|
||||
firstMustReference(innerObject1);
|
||||
secondMustReference(innerObject2);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -7,10 +7,6 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
TEST(JsonArray_Invalid_Tests, AtFails) {
|
||||
ASSERT_FALSE(JsonArray::invalid().at(0).success());
|
||||
}
|
||||
|
||||
TEST(JsonArray_Invalid_Tests, SubscriptFails) {
|
||||
ASSERT_FALSE(JsonArray::invalid()[0].success());
|
||||
}
|
||||
@ -33,4 +29,4 @@ TEST(JsonArray_Invalid_Tests, PrintToWritesBrackets) {
|
||||
char buffer[32];
|
||||
JsonArray::invalid().printTo(buffer, sizeof(buffer));
|
||||
ASSERT_STREQ("[]", buffer);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -16,13 +16,15 @@ class JsonArray_PrettyPrintTo_Tests : public testing::Test {
|
||||
JsonArray& array;
|
||||
|
||||
void outputMustBe(const char* expected) {
|
||||
size_t n = array.prettyPrintTo(_buffer, sizeof(_buffer));
|
||||
EXPECT_STREQ(expected, _buffer);
|
||||
EXPECT_EQ(strlen(expected), n);
|
||||
}
|
||||
char actual[256];
|
||||
|
||||
private:
|
||||
char _buffer[256];
|
||||
size_t actualLen = array.prettyPrintTo(actual, sizeof(actual));
|
||||
size_t measuredLen = array.measurePrettyLength();
|
||||
|
||||
EXPECT_STREQ(expected, actual);
|
||||
EXPECT_EQ(strlen(expected), actualLen);
|
||||
EXPECT_EQ(strlen(expected), measuredLen);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(JsonArray_PrettyPrintTo_Tests, Empty) { outputMustBe("[]"); }
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
@ -16,9 +16,12 @@ class JsonArray_PrintTo_Tests : public testing::Test {
|
||||
JsonArray &array;
|
||||
|
||||
void outputMustBe(const char *expected) {
|
||||
size_t n = array.printTo(buffer, sizeof(buffer));
|
||||
size_t actualLen = array.printTo(buffer, sizeof(buffer));
|
||||
size_t measuredLen = array.measureLength();
|
||||
|
||||
EXPECT_STREQ(expected, buffer);
|
||||
EXPECT_EQ(strlen(expected), n);
|
||||
EXPECT_EQ(strlen(expected), actualLen);
|
||||
EXPECT_EQ(strlen(expected), measuredLen);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -60,7 +63,7 @@ TEST_F(JsonArray_PrintTo_Tests, OneDoubleDefaultDigits) {
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, OneDoubleFourDigits) {
|
||||
array.add(3.14159265358979323846, 4);
|
||||
array.add(double_with_n_digits(3.14159265358979323846, 4));
|
||||
outputMustBe("[3.1416]");
|
||||
}
|
||||
|
||||
|
46
test/JsonArray_Remove_Tests.cpp
Normal file
46
test/JsonArray_Remove_Tests.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonArray_Remove_Tests : public ::testing::Test {
|
||||
protected:
|
||||
JsonArray_Remove_Tests() : _array(_jsonBuffer.createArray()) {
|
||||
_array.add("one");
|
||||
_array.add("two");
|
||||
_array.add("three");
|
||||
}
|
||||
|
||||
DynamicJsonBuffer _jsonBuffer;
|
||||
JsonArray& _array;
|
||||
};
|
||||
|
||||
#define TEST_(name) TEST_F(JsonArray_Remove_Tests, name)
|
||||
|
||||
TEST_(RemoveFirstElement) {
|
||||
_array.removeAt(0);
|
||||
|
||||
EXPECT_EQ(2, _array.size());
|
||||
EXPECT_STREQ("two", _array[0]);
|
||||
EXPECT_STREQ("three", _array[1]);
|
||||
}
|
||||
|
||||
TEST_(RemoveMiddleElement) {
|
||||
_array.removeAt(1);
|
||||
|
||||
EXPECT_EQ(2, _array.size());
|
||||
EXPECT_STREQ("one", _array[0]);
|
||||
EXPECT_STREQ("three", _array[1]);
|
||||
}
|
||||
|
||||
TEST_(RemoveLastElement) {
|
||||
_array.removeAt(2);
|
||||
|
||||
EXPECT_EQ(2, _array.size());
|
||||
EXPECT_STREQ("one", _array[0]);
|
||||
EXPECT_STREQ("two", _array[1]);
|
||||
}
|
90
test/JsonArray_Set_Tests.cpp
Normal file
90
test/JsonArray_Set_Tests.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#define ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonArray_Set_Tests : public ::testing::Test {
|
||||
protected:
|
||||
JsonArray_Set_Tests() : _array(_jsonBuffer.createArray()) { _array.add(0); }
|
||||
|
||||
DynamicJsonBuffer _jsonBuffer;
|
||||
JsonArray& _array;
|
||||
};
|
||||
|
||||
#define TEST_(name) TEST_F(JsonArray_Set_Tests, name)
|
||||
|
||||
TEST_(SizeIsUnchanged) {
|
||||
_array.set(0, "hello");
|
||||
EXPECT_EQ(1U, _array.size());
|
||||
}
|
||||
|
||||
TEST_(StoreInteger) {
|
||||
_array.set(0, 123);
|
||||
EXPECT_EQ(123, _array[0].as<int>());
|
||||
EXPECT_TRUE(_array[0].is<int>());
|
||||
EXPECT_FALSE(_array[0].is<double>());
|
||||
}
|
||||
|
||||
TEST_(StoreDouble) {
|
||||
_array.set(0, 123.45);
|
||||
EXPECT_EQ(123.45, _array[0].as<double>());
|
||||
EXPECT_TRUE(_array[0].is<double>());
|
||||
EXPECT_FALSE(_array[0].is<int>());
|
||||
}
|
||||
|
||||
TEST_(StoreBoolean) {
|
||||
_array.set(0, true);
|
||||
EXPECT_EQ(true, _array[0].as<bool>());
|
||||
EXPECT_TRUE(_array[0].is<bool>());
|
||||
EXPECT_FALSE(_array[0].is<int>());
|
||||
}
|
||||
|
||||
TEST_(StoreString) {
|
||||
_array.set(0, "hello");
|
||||
EXPECT_STREQ("hello", _array[0].as<const char*>());
|
||||
EXPECT_TRUE(_array[0].is<const char*>());
|
||||
EXPECT_FALSE(_array[0].is<int>());
|
||||
}
|
||||
|
||||
TEST_(StoreNestedArray) {
|
||||
JsonArray& arr = _jsonBuffer.createArray();
|
||||
|
||||
_array.set(0, arr);
|
||||
|
||||
EXPECT_EQ(&arr, &_array[0].as<JsonArray&>());
|
||||
EXPECT_TRUE(_array[0].is<JsonArray&>());
|
||||
EXPECT_FALSE(_array[0].is<int>());
|
||||
}
|
||||
|
||||
TEST_(StoreNestedObject) {
|
||||
JsonObject& obj = _jsonBuffer.createObject();
|
||||
|
||||
_array.set(0, obj);
|
||||
|
||||
EXPECT_EQ(&obj, &_array[0].as<JsonObject&>());
|
||||
EXPECT_TRUE(_array[0].is<JsonObject&>());
|
||||
EXPECT_FALSE(_array[0].is<int>());
|
||||
}
|
||||
|
||||
TEST_(StoreArraySubscript) {
|
||||
JsonArray& arr = _jsonBuffer.createArray();
|
||||
arr.add("hello");
|
||||
|
||||
_array.set(0, arr[0]);
|
||||
|
||||
EXPECT_STREQ("hello", _array[0]);
|
||||
}
|
||||
|
||||
TEST_(StoreObjectSubscript) {
|
||||
JsonObject& obj = _jsonBuffer.createObject();
|
||||
obj["x"] = "hello";
|
||||
|
||||
_array.set(0, obj["x"]);
|
||||
|
||||
EXPECT_STREQ("hello", _array[0]);
|
||||
}
|
92
test/JsonArray_Subscript_Tests.cpp
Normal file
92
test/JsonArray_Subscript_Tests.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#define ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonArray_Subscript_Tests : public ::testing::Test {
|
||||
protected:
|
||||
JsonArray_Subscript_Tests() : _array(_jsonBuffer.createArray()) {
|
||||
_array.add(0);
|
||||
}
|
||||
|
||||
DynamicJsonBuffer _jsonBuffer;
|
||||
JsonArray& _array;
|
||||
};
|
||||
|
||||
#define TEST_(name) TEST_F(JsonArray_Subscript_Tests, name)
|
||||
|
||||
TEST_(SizeIsUnchanged) {
|
||||
_array[0] = "hello";
|
||||
EXPECT_EQ(1U, _array.size());
|
||||
}
|
||||
|
||||
TEST_(StoreInteger) {
|
||||
_array[0] = 123;
|
||||
EXPECT_EQ(123, _array[0].as<int>());
|
||||
EXPECT_TRUE(_array[0].is<int>());
|
||||
EXPECT_FALSE(_array[0].is<double>());
|
||||
}
|
||||
|
||||
TEST_(StoreDouble) {
|
||||
_array[0] = 123.45;
|
||||
EXPECT_EQ(123.45, _array[0].as<double>());
|
||||
EXPECT_TRUE(_array[0].is<double>());
|
||||
EXPECT_FALSE(_array[0].is<int>());
|
||||
}
|
||||
|
||||
TEST_(StoreBoolean) {
|
||||
_array[0] = true;
|
||||
EXPECT_EQ(true, _array[0].as<bool>());
|
||||
EXPECT_TRUE(_array[0].is<bool>());
|
||||
EXPECT_FALSE(_array[0].is<int>());
|
||||
}
|
||||
|
||||
TEST_(StoreString) {
|
||||
_array[0] = "hello";
|
||||
EXPECT_STREQ("hello", _array[0].as<const char*>());
|
||||
EXPECT_TRUE(_array[0].is<const char*>());
|
||||
EXPECT_FALSE(_array[0].is<int>());
|
||||
}
|
||||
|
||||
TEST_(StoreNestedArray) {
|
||||
JsonArray& arr = _jsonBuffer.createArray();
|
||||
|
||||
_array[0] = arr;
|
||||
|
||||
EXPECT_EQ(&arr, &_array[0].as<JsonArray&>());
|
||||
EXPECT_TRUE(_array[0].is<JsonArray&>());
|
||||
EXPECT_FALSE(_array[0].is<int>());
|
||||
}
|
||||
|
||||
TEST_(StoreNestedObject) {
|
||||
JsonObject& obj = _jsonBuffer.createObject();
|
||||
|
||||
_array[0] = obj;
|
||||
|
||||
EXPECT_EQ(&obj, &_array[0].as<JsonObject&>());
|
||||
EXPECT_TRUE(_array[0].is<JsonObject&>());
|
||||
EXPECT_FALSE(_array[0].is<int>());
|
||||
}
|
||||
|
||||
TEST_(StoreArraySubscript) {
|
||||
JsonArray& arr = _jsonBuffer.createArray();
|
||||
arr.add("hello");
|
||||
|
||||
_array[0] = arr[0];
|
||||
|
||||
EXPECT_STREQ("hello", _array[0]);
|
||||
}
|
||||
|
||||
TEST_(StoreObjectSubscript) {
|
||||
JsonObject& obj = _jsonBuffer.createObject();
|
||||
obj["x"] = "hello";
|
||||
|
||||
_array[0] = obj["x"];
|
||||
|
||||
EXPECT_STREQ("hello", _array[0]);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user