Compare commits

...

61 Commits
v4.6 ... v5.1.0

Author SHA1 Message Date
564c62f3b3 Set version to 5.1.0 2016-02-14 16:20:33 +01:00
8733f95e51 Added support of long long (issue #171)
Moved all build settings to `ArduinoJson/Configuration.hpp`
Added AppVeyor settings in source tree
2016-02-14 16:18:13 +01:00
ce63e9c3c3 Added comments in examples 2016-02-01 13:31:07 +01:00
77b7124cf1 Set version to 5.0.8 2016-01-31 21:57:08 +01:00
6a608d4b49 Fixed JsonVariant::is<bool>() that was incorrectly returning false (issue #214) 2016-01-31 21:56:04 +01:00
01924618bd Merge pull request #215 from ivankravets/patch-1
Use tagged source code from repo
2016-01-31 21:00:46 +01:00
666e2fd0ce Use tagged source code from repo
http://docs.platformio.org/en/latest/librarymanager/config.html#version
2016-01-31 21:24:37 +02:00
0cfc25d751 Added Johann Stieger to the list of donators 2016-01-07 22:40:12 +01:00
b6d8e6c989 Updated copyright year from 2015 to 2016 2016-01-07 22:39:57 +01:00
ab2502f7b8 Fix misspelled PlatformIO 2015-12-23 14:42:22 +01:00
c57e6f3bd8 Made the library compatible with platform.io (issue #181) 2015-12-22 23:43:44 +01:00
b54f1ffc1d Travis: build with Arduino 1.5.8 and 1.6.7 2015-12-22 22:01:30 +01:00
bd0ea42277 Added a badge with the number of stars 2015-11-25 21:22:49 +01:00
7ae43bc4f8 Set version to 5.0.7 2015-11-25 21:15:11 +01:00
056682327b Changed String to be a typedef of std::string (issues #142 and #161) 2015-11-25 21:09:18 +01:00
8b66a25f66 Removed a useless line of code 2015-11-22 10:18:21 +01:00
96245dd3b4 Made library easier to use from a CMake project: simply add_subdirectory(ArduinoJson/src) 2015-11-19 21:53:27 +01:00
9cc49da68a Moved to the new Travis infrastructure 2015-11-19 21:31:23 +01:00
224918b463 Set version to 5.0.6 2015-11-09 23:10:14 +01:00
cbeefa2503 Examples: Added a loop to wait for serial port to be ready (issue #156) 2015-11-09 22:56:49 +01:00
6d68806633 Added donators list 2015-11-09 22:55:29 +01:00
ba3617c22f Added parameter to DynamicJsonBuffer constructor to set initial size (issue #152) 2015-11-09 21:37:40 +01:00
b7d9bb2765 Merge pull request #150 from marvinroger/patch-1
Add library category
2015-11-06 14:50:18 +01:00
74b42e2251 Add library category 2015-11-06 14:30:20 +01:00
c0cf9c3fcc Use float instead of double to reduce the size of JsonVariant (issue #134) 2015-10-30 23:03:16 +01:00
9f3ce18f06 Add overload JsonObjectSuscript::set(value, decimals) (issue #143) 2015-10-30 22:29:47 +01:00
b9e3255c9e Reached 100.00% code coverage :-) 2015-09-29 22:20:36 +02:00
e657396f65 Added -fno-rtti 2015-09-29 21:51:21 +02:00
929f608f2f Added list of supported platforms 2015-09-29 21:49:19 +02:00
c6a4bfa886 Fixed ambiguous overload with JsonArraySubscript and JsonObjectSubscript (issue #122) 2015-09-28 22:14:50 +02:00
d5e25b12b8 Added a comment to prevent issue #112 2015-09-27 14:18:14 +02:00
7cf6fe6d62 Fixed return type of JsonArray::is<T>() and some others (issue #121) 2015-09-19 16:25:18 +02:00
155dd653e7 Fixed printTo(String) which wrote numbers instead of strings (issue #120) 2015-09-19 16:23:09 +02:00
b5c8cd1766 Set version to 5.0.3 2015-09-19 16:20:06 +02:00
4967e389c5 Added a script to create the package with the old layout (issues #97, #114, #116) 2015-09-13 21:04:30 +02:00
ffbaebd198 Added testimonials from Reddit users erm_what_ and makerhacks 2015-09-06 22:11:53 +02:00
04b8781c8d Fixed GCC warning "declaration shadows a member" (issue #103) 2015-09-01 22:26:51 +02:00
5a4d993f7d Fixed memory alignment, which made ESP8266 crash (issue #104) 2015-09-01 22:21:50 +02:00
823a172681 Fixed segmentation fault in StaticJsonBuffer (issue #104) 2015-08-29 22:51:17 +02:00
a1943e21ed Fixed compilation on Visual Studio 2010 and 2012 (issue #107) 2015-08-27 21:47:49 +02:00
01c287bc89 Removed -Wdeprecated-register for GCC 2015-08-26 21:00:28 +02:00
0cf8249b14 Fixed Clang warning "register specifier is deprecated" (issue #102) 2015-08-26 20:49:24 +02:00
a8265a799d Merge pull request #100 from Eriatolc/master
Fix typo in Readme & clean file
2015-08-24 18:18:05 +02:00
18bb653f10 fix typo 2015-08-24 18:10:10 +02:00
a003a31952 Fixed compilation with Arduino 1.0.6 (issue #99) 2015-08-24 15:20:40 +02:00
0a1c27f873 Updated copyright year 2015-08-20 15:24:35 +02:00
75f8e25aed Added a script to measure the size of the sample programs 2015-08-19 22:12:20 +02:00
39c506b419 Reduced generator size. Fixed Visual Studio warnings 2015-08-19 16:08:19 +02:00
ef2641b49b Store parsed token as string and allow conversion between various types (issues #64, #69, #90, #93) 2015-08-10 17:22:22 +02:00
bce101578d Merge branch 'master' into 5.0 2015-08-02 14:28:20 +02:00
10e466426a Removed the wrong #include 2015-08-02 09:20:21 +02:00
9b90aeffa5 Added call to arduino compiler in travis 2015-08-02 09:20:08 +02:00
601b51890f Fixed segmentation fault in when memory allocation fails (issue #92) 2015-08-01 16:57:29 +02:00
e31d667bec Added support of comments in JSON input (issue #88) 2015-07-27 22:18:54 +02:00
c161f698fc Implicitly duplicate String in the JsonBuffer (issue #84, #87) 2015-07-25 15:38:12 +02:00
92e687303d Added support of non standard JSON input (issue #44) 2015-07-10 22:11:26 +02:00
78ae0b8aee Updated changelog 2015-05-31 14:42:09 +02:00
283dffc035 Switched to the new library layout 2015-05-31 14:31:41 +02:00
0aded2a798 Reduced code size 2015-05-31 14:25:01 +02:00
1b5be892b9 Added support of String class (issue #55, #56, #70, #77) 2015-05-25 15:38:58 +02:00
756c279cdc Redesigned JsonVariant to leverage converting constructors instead of assignment operators 2015-05-23 15:32:50 +02:00
146 changed files with 4550 additions and 1798 deletions

View File

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

3
.gitignore vendored
View File

@ -3,3 +3,6 @@
/build
/bin
/lib
/sftp-config.json
.tags
.tags_sorted_by_file

View File

@ -1,12 +1,15 @@
language: c++
compiler:
- gcc
- clang
before_install:
- sudo pip install cpp-coveralls
before_script:
- cmake -DCOVERAGE=true .
script:
- make && make test
after_success:
- coveralls --exclude test --exclude third-party --gcov-options '\-lp'
sudo: false
language: cpp
cache:
directories:
- "~/.platformio"
env:
- COMPILER=gcc
- COMPILER=clang
- COMPILER=arduino VERSION=1.5.8 BOARD=arduino:avr:uno
- COMPILER=arduino VERSION=1.6.7 BOARD=arduino:avr:uno
- COMPILER=platformio BOARD=uno
- COMPILER=platformio BOARD=due
- COMPILER=platformio BOARD=esp01
- COMPILER=platformio BOARD=teensy31
script: scripts/travis/$COMPILER.sh

View File

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

View File

@ -1,13 +1,14 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#ifdef ARDUINO
// This file is here to help the Arduino IDE find the other files.
// About this file
// ---------------
// This file is here for [PlatformIO](http://platformio.org/).
// It must be present in the root for the tool to find it.
// Feel free to ignore this file if your working in another environment.
#include "include/ArduinoJson.h"
#endif

View File

@ -1,5 +1,94 @@
Arduino JSON: change log
========================
ArduinoJson: change log
=======================
v5.1.0
------
* Added support of `long long` (issue #171)
* Moved all build settings to `ArduinoJson/Configuration.hpp`
**BREAKING CHANGE**:
If you defined `ARDUINOJSON_ENABLE_STD_STREAM`, you now need to define it to `1`.
v5.0.8
------
* Made the library compatible with [PlatformIO](http://platformio.org/) (issue #181)
* Fixed `JsonVariant::is<bool>()` that was incorrectly returning false (issue #214)
v5.0.7
------
* Made library easier to use from a CMake project: simply `add_subdirectory(ArduinoJson/src)`
* Changed `String` to be a `typedef` of `std::string` (issues #142 and #161)
**BREAKING CHANGES**:
- `JsonVariant(true).as<String>()` now returns `"true"` instead of `"1"`
- `JsonVariant(false).as<String>()` now returns `"false"` instead of `"0"`
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
----
@ -147,4 +236,4 @@ v1.1
v1.0
----
Initial release
Initial release

View File

@ -1,4 +1,11 @@
cmake_minimum_required(VERSION 2.8.4)
# Copyright Benoit Blanchon 2014-2016
# MIT License
#
# Arduino JSON library
# https://github.com/bblanchon/ArduinoJson
# If you like this project, please add a star!
cmake_minimum_required(VERSION 2.8.12)
project(ArduinoJson)
enable_testing()
@ -7,14 +14,9 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
if(MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS -W4)
endif()
if(${COVERAGE})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -coverage")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -coverage")
set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
endif()
add_subdirectory(src)
add_subdirectory(test)
add_subdirectory(test)

View File

@ -1,10 +1,10 @@
The MIT License (MIT)
---------------------
Copyright © 2014 Benoit BLANCHON
Copyright © 2014-2016 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.

View File

@ -1,67 +1,86 @@
Arduino JSON library
====================
[![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=master)](https://travis-ci.org/bblanchon/ArduinoJson) [![Coverage Status](https://img.shields.io/coveralls/bblanchon/ArduinoJson.svg)](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master)
[![Build status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/master?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master) [![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=master)](https://travis-ci.org/bblanchon/ArduinoJson) [![Coverage Status](https://img.shields.io/coveralls/bblanchon/ArduinoJson.svg)](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master) [![Star this project](http://githubbadges.com/star.svg?user=bblanchon&repo=ArduinoJson&style=flat&color=fff&background=007ec6)](https://github.com/bblanchon/ArduinoJson)
*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
* Intel Edison
* PlatformIO
* Energia
* Computers (Windows, Linux, OSX...)
See [FAQ: Compatibility issues](https://github.com/bblanchon/ArduinoJson/wiki/Compatibility-issues)
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 +95,27 @@ 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
* Johann Stieger
---
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&currency_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&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted) :smile:

16
appveyor.yml Normal file
View File

@ -0,0 +1,16 @@
version: 5.1.0.{build}
environment:
matrix:
- CMAKE_GENERATOR: Visual Studio 14 2015
- CMAKE_GENERATOR: Visual Studio 12 2013
- CMAKE_GENERATOR: Visual Studio 11 2012
- CMAKE_GENERATOR: Visual Studio 10 2010
- CMAKE_GENERATOR: MinGW Makefiles
configuration: Debug
before_build:
- set PATH=C:\MinGW\bin;%PATH:C:\Program Files\Git\usr\bin;=% # Workaround for CMake not wanting sh.exe on PATH for MinGW
- cmake -DCMAKE_BUILD_TYPE=%CONFIGURATION% -G "%CMAKE_GENERATOR%" .
build_script:
- cmake --build . --config %CONFIGURATION%
test_script:
- ctest -V .

View File

@ -1,7 +1,9 @@
/*
* Arduino JSON library - IndentedPrint example
* Benoit Blanchon 2014 - MIT License
*/
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <ArduinoJson.h>
@ -9,6 +11,9 @@ using namespace ArduinoJson::Internals;
void setup() {
Serial.begin(9600);
while (!Serial) {
// wait serial port initialization
}
IndentedPrint serial(Serial);
serial.setTabSize(4);
@ -27,4 +32,4 @@ void setup() {
void loop() {
// not used in this example
}
}

View File

@ -1,23 +1,51 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <ArduinoJson.h>
void setup() {
Serial.begin(9600);
while (!Serial) {
// wait serial port initialization
}
// Memory pool for JSON object tree.
//
// Inside the brackets, 200 is the size of the pool in bytes.
// If the JSON object is more complex, you need to increase that value.
StaticJsonBuffer<200> jsonBuffer;
// StaticJsonBuffer allocates memory on the stack, it can be
// replaced by DynamicJsonBuffer which allocates in the heap.
// It's simpler but less efficient.
//
// DynamicJsonBuffer jsonBuffer;
// Create the root of the object tree.
//
// It's a reference to the JsonObject, the actual bytes are inside the
// JsonBuffer with all the other nodes of the object tree.
// Memory is freed when jsonBuffer goes out of scope.
JsonObject& root = jsonBuffer.createObject();
// Add values in the object
//
// Most of the time, you can rely on the implicit casts.
// In other case, you can do root.set<long>("time", 1351824120);
root["sensor"] = "gps";
root["time"] = 1351824120;
// Add a nested array.
//
// It's also possible to create the array separately and add it to the
// JsonObject but it's less efficient.
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 +67,4 @@ void setup() {
void loop() {
// not used in this example
}
}

View File

@ -1,31 +1,61 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <ArduinoJson.h>
void setup() {
Serial.begin(9600);
while (!Serial) {
// wait serial port initialization
}
// Memory pool for JSON object tree.
//
// Inside the brackets, 200 is the size of the pool in bytes,
// If the JSON object is more complex, you need to increase that value.
StaticJsonBuffer<200> jsonBuffer;
// StaticJsonBuffer allocates memory on the stack, it can be
// replaced by DynamicJsonBuffer which allocates in the heap.
// It's simpler but less efficient.
//
// DynamicJsonBuffer jsonBuffer;
// JSON input string.
//
// It's better to use a char[] as shown here.
// If you use a const char* or a String, ArduinoJson will
// have to make a copy of the input in the JsonBuffer.
char json[] =
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
// Root of the object tree.
//
// It's a reference to the JsonObject, the actual bytes are inside the
// JsonBuffer with all the other nodes of the object tree.
// Memory is freed when jsonBuffer goes out of scope.
JsonObject& root = jsonBuffer.parseObject(json);
// Test if parsing succeeds.
if (!root.success()) {
Serial.println("parseObject() failed");
return;
}
// Fetch values.
//
// Most of the time, you can rely on the implicit casts.
// In other case, you can do root["time"].as<long>();
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
// Print values.
Serial.println(sensor);
Serial.println(time);
Serial.println(latitude, 6);
@ -34,4 +64,4 @@ void setup() {
void loop() {
// not used in this example
}
}

View File

@ -3,7 +3,7 @@
// You can easily test this program with netcat:
// $ nc -ulp 8888
//
// by Benoit Blanchon, MIT License 2015
// by Benoit Blanchon, MIT License 2015-2016
#include <SPI.h>
#include <Ethernet.h>

View File

@ -1,12 +1,13 @@
// Copyright Benoit Blanchon 2014
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../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;

View File

@ -1,27 +1,85 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#ifndef ARDUINO
#include "../Internals/JsonFloat.hpp"
#include "../Internals/JsonInteger.hpp"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
// This class reproduces Arduino's Print
#if defined(_MSC_VER) && _MSC_VER <= 1800
// snprintf has been added in Visual Studio 2015
#define ARDUINOJSON_SNPRINTF _snprintf
#else
#define ARDUINOJSON_SNPRINTF snprintf
#endif
// This class reproduces Arduino's Print class
class Print {
public:
virtual ~Print() {}
virtual size_t write(uint8_t) = 0;
size_t print(const char[]);
size_t print(double, int = 2);
size_t print(long);
size_t println();
size_t print(const char* s) {
size_t n = 0;
while (*s) {
n += write(*s++);
}
return n;
}
size_t print(ArduinoJson::Internals::JsonFloat value, int digits = 2) {
char tmp[32];
// 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 using the scientific notation, since we have sprintf
ARDUINOJSON_SNPRINTF(tmp, sizeof(tmp), "%g", value);
} else {
// Here we have the exact same output as Arduino's implementation
ARDUINOJSON_SNPRINTF(tmp, sizeof(tmp), "%.*f", digits, value);
}
return print(tmp);
}
size_t print(ArduinoJson::Internals::JsonInteger value) {
// see http://clc-wiki.net/wiki/K%26R2_solutions:Chapter_3:Exercise_4
char buffer[22];
size_t n = 0;
if (value < 0) {
value = -value;
n += write('-');
}
uint8_t i = 0;
do {
ArduinoJson::Internals::JsonInteger digit = value % 10;
value /= 10;
buffer[i++] = static_cast<char>(digit >= 0 ? '0' + digit : '0' - digit);
} while (value);
while (i > 0) {
n += write(buffer[--i]);
}
return n;
}
size_t println() { return write('\r') + write('\n'); }
};
#else

View File

@ -0,0 +1,19 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#ifndef ARDUINO
#include <string>
typedef std::string String;
#else
#include <WString.h>
#endif

View File

@ -0,0 +1,79 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#ifdef ARDUINO // assume this is an embedded platform
// store using float instead of double to reduce the memory usage (issue #134)
#ifndef ARDUINOJSON_USE_DOUBLE
#define ARDUINOJSON_USE_DOUBLE 0
#endif
// store using a long because it usually match the size of a float.
#ifndef ARDUINOJSON_USE_LONG_LONG
#define ARDUINOJSON_USE_LONG_LONG 0
#endif
#ifndef ARDUINOJSON_USE_INT64
#define ARDUINOJSON_USE_INT64 0
#endif
// arduino doesn't support STL stream
#ifndef ARDUINOJSON_ENABLE_STD_STREAM
#define ARDUINOJSON_ENABLE_STD_STREAM 0
#endif
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
#ifdef ARDUINO_ARCH_AVR
// alignment isn't needed for 8-bit AVR
#define ARDUINOJSON_ENABLE_ALIGNMENT 0
#else
// but must processor needs pointer to be align on word size
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
#endif
#endif
#else // assume this is a computer
// on a computer we have plenty of memory so we can use doubles
#ifndef ARDUINOJSON_USE_DOUBLE
#define ARDUINOJSON_USE_DOUBLE 1
#endif
// use long long when available
#ifndef ARDUINOJSON_USE_LONG_LONG
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
#define ARDUINOJSON_USE_LONG_LONG 1
#else
#define ARDUINOJSON_USE_LONG_LONG 0
#endif
#endif
// use _int64 on old versions of Visual Studio
#ifndef ARDUINOJSON_USE_INT64
#if defined(_MSC_VER) && _MSC_VER <= 1700
#define ARDUINOJSON_USE_INT64 1
#else
#define ARDUINOJSON_USE_INT64 0
#endif
#endif
// on a computer, we can assume that the STL is there
#ifndef ARDUINOJSON_ENABLE_STD_STREAM
#define ARDUINOJSON_ENABLE_STD_STREAM 1
#endif
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
// even if not required, most cpu's are faster with aligned pointers
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
#endif
#endif
#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64
#error ARDUINOJSON_USE_LONG_LONG and ARDUINOJSON_USE_INT64 cannot be set together
#endif

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
@ -31,7 +32,8 @@ class BlockJsonBuffer : public JsonBuffer {
};
public:
BlockJsonBuffer() : _head(NULL) {}
BlockJsonBuffer(size_t initialSize = 256)
: _head(NULL), _nextBlockSize(initialSize) {}
~BlockJsonBuffer() {
Block* currentBlock = _head;
@ -55,29 +57,27 @@ class BlockJsonBuffer : public JsonBuffer {
}
private:
static const size_t FIRST_BLOCK_CAPACITY = 32;
bool canAllocInHead(size_t bytes) const {
return _head != NULL && _head->size + bytes <= _head->capacity;
}
void* allocInHead(size_t bytes) {
void* p = _head->data + _head->size;
_head->size += bytes;
_head->size += round_size_up(bytes);
return p;
}
void* allocInNewBlock(size_t bytes) {
size_t capacity = FIRST_BLOCK_CAPACITY;
if (_head != NULL) capacity = _head->capacity * 2;
size_t capacity = _nextBlockSize;
if (bytes > capacity) capacity = bytes;
if (!addNewBlock(capacity)) return NULL;
_nextBlockSize *= 2;
return allocInHead(bytes);
}
bool addNewBlock(size_t capacity) {
size_t size = sizeof(EmptyBlock) + capacity;
Block* block = static_cast<Block*>(_allocator.allocate(size));
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;
@ -86,8 +86,9 @@ class BlockJsonBuffer : public JsonBuffer {
return true;
}
Block* _head;
TAllocator _allocator;
Block* _head;
size_t _nextBlockSize;
};
}
}

View File

@ -0,0 +1,14 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
namespace ArduinoJson {
namespace Internals {
const char *skipSpacesAndComments(const char *ptr);
}
}

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once

View File

@ -0,0 +1,33 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "../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;
};
}
}

View File

@ -0,0 +1,40 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "../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[];
};
}
}

View File

@ -0,0 +1,14 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#ifdef _MSC_VER
#define FORCE_INLINE __forceinline
#else
#define FORCE_INLINE __attribute__((always_inline))
#endif

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
@ -14,6 +15,7 @@ namespace Internals {
class JsonBufferAllocated {
public:
void *operator new(size_t n, JsonBuffer *jsonBuffer) throw() {
if (!jsonBuffer) return NULL;
return jsonBuffer->alloc(n);
}

View File

@ -0,0 +1,21 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "../Configuration.hpp"
namespace ArduinoJson {
namespace Internals {
#if ARDUINOJSON_USE_DOUBLE
typedef double JsonFloat;
#else
typedef float JsonFloat;
#endif
}
}

View File

@ -0,0 +1,23 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "../Configuration.hpp"
namespace ArduinoJson {
namespace Internals {
#if ARDUINOJSON_USE_LONG_LONG
typedef long long JsonInteger;
#elif ARDUINOJSON_USE_INT64
typedef __int64 JsonInteger;
#else
typedef long JsonInteger;
#endif
}
}

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
@ -18,24 +19,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;
};
}

View File

@ -1,16 +1,23 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "../Configuration.hpp"
#include "DummyPrint.hpp"
#include "IndentedPrint.hpp"
#include "JsonWriter.hpp"
#include "Prettyfier.hpp"
#include "StringBuilder.hpp"
#include "StaticStringBuilder.hpp"
#include "DynamicStringBuilder.hpp"
#if ARDUINOJSON_ENABLE_STD_STREAM
#include "StreamPrintAdapter.hpp"
#endif
namespace ArduinoJson {
namespace Internals {
@ -28,8 +35,21 @@ class JsonPrintable {
return writer.bytesWritten();
}
#if 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);
}
@ -39,7 +59,7 @@ class JsonPrintable {
}
size_t prettyPrintTo(char *buffer, size_t bufferSize) const {
StringBuilder sb(buffer, bufferSize);
StaticStringBuilder sb(buffer, bufferSize);
return prettyPrintTo(sb);
}
@ -48,6 +68,11 @@ 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);
@ -61,5 +86,12 @@ class JsonPrintable {
private:
const T &downcast() const { return *static_cast<const T *>(this); }
};
#if ARDUINOJSON_ENABLE_STD_STREAM
template <typename T>
inline std::ostream &operator<<(std::ostream &os, const JsonPrintable<T> &v) {
return v.printTo(os);
}
#endif
}
}

View File

@ -1,11 +1,15 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "JsonFloat.hpp"
#include "JsonInteger.hpp"
namespace ArduinoJson {
// Forward declarations
@ -13,16 +17,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
};
}
}

View File

@ -1,32 +1,36 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
namespace ArduinoJson {
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
// ...
};
}

View File

@ -1,13 +1,17 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "../Arduino/Print.hpp"
#include "QuotedString.hpp"
#include "Encoding.hpp"
#include "ForceInline.hpp"
#include "JsonFloat.hpp"
#include "JsonInteger.hpp"
namespace ArduinoJson {
namespace Internals {
@ -26,7 +30,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 +41,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;

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
@ -39,7 +40,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); }
@ -48,21 +49,7 @@ class List {
const_iterator end() const { return const_iterator(NULL); }
protected:
node_type *createNode() {
if (!_buffer) return NULL;
return new (_buffer) node_type();
}
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;

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once

View File

@ -0,0 +1,51 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include <stdlib.h>
namespace ArduinoJson {
namespace Internals {
template <typename TFloat>
TFloat parse(const char *);
template <>
inline float parse<float>(const char *s) {
return static_cast<float>(strtod(s, NULL));
}
template <>
inline double parse<double>(const char *s) {
return strtod(s, NULL);
}
template <>
inline long parse<long>(const char *s) {
return strtol(s, NULL, 10);
}
template <>
inline int parse<int>(const char *s) {
return atoi(s);
}
#if ARDUINOJSON_USE_LONG_LONG
template <>
inline long long parse<long long>(const char *s) {
return strtoll(s, NULL, 10);
}
#endif
#if ARDUINOJSON_USE_INT64
template <>
inline __int64 parse<__int64>(const char *s) {
return _strtoi64(s, NULL, 10);
}
#endif
}
}

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
@ -31,7 +32,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);

View File

@ -1,29 +0,0 @@
// 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 {
// 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);
};
}
}

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
@ -12,9 +13,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 +24,8 @@ class StringBuilder : public Print {
private:
char *buffer;
int capacity;
int length;
size_t capacity;
size_t length;
};
}
}

View File

@ -0,0 +1,39 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "../Configuration.hpp"
#if ARDUINOJSON_ENABLE_STD_STREAM
#include "../Arduino/Print.hpp"
#include <ostream>
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

View File

@ -0,0 +1,21 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
namespace ArduinoJson {
namespace Internals {
class Unparsed {
public:
explicit Unparsed(const char* str) : _str(str) {}
operator const char*() const { return _str; }
private:
const char* _str;
};
}
}

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
@ -11,6 +12,10 @@
#include "Internals/List.hpp"
#include "Internals/ReferenceType.hpp"
#include "JsonVariant.hpp"
#include "TypeTraits/EnableIf.hpp"
#include "TypeTraits/IsFloatingPoint.hpp"
#include "TypeTraits/IsReference.hpp"
#include "TypeTraits/IsSame.hpp"
// Returns the size (in bytes) of an array with n elements.
// Can be very handy to determine the size of a StaticJsonBuffer.
@ -22,6 +27,7 @@ namespace ArduinoJson {
// Forward declarations
class JsonObject;
class JsonBuffer;
class JsonArraySubscript;
// An array of JsonVariant.
//
@ -33,35 +39,108 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
public Internals::ReferenceType,
public Internals::List<JsonVariant>,
public Internals::JsonBufferAllocated {
// JsonBuffer is a friend because it needs to call the private constructor.
friend class JsonBuffer;
public:
// Returns the JsonVariant at the specified index (synonym for operator[])
JsonVariant &at(int index) const;
// A meta-function that returns true if type T can be used in
// JsonArray::set()
template <typename T>
struct CanSet {
static const bool value = JsonVariant::IsConstructibleFrom<T>::value ||
TypeTraits::IsSame<T, String &>::value ||
TypeTraits::IsSame<T, const String &>::value;
};
// Returns the JsonVariant at the specified index (synonym for at())
JsonVariant &operator[](int index) const { return at(index); }
// 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) {}
// Adds an uninitialized JsonVariant at the end of the array.
// Return a reference or JsonVariant::invalid() if allocation fails.
JsonVariant &add();
// Gets the value at the specified index
FORCE_INLINE JsonVariant operator[](size_t index) const;
// 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.
//
// bool add(bool);
// bool add(char);
// bool add(long);
// bool add(int);
// bool add(short);
// bool add(float value);
// bool add(double value);
// bool add(const char*);
template <typename T>
void add(T value) {
add().set(value);
FORCE_INLINE bool add(
T value,
typename TypeTraits::EnableIf<
CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) {
return addNode<T>(value);
}
// bool add(const String&)
// bool add(const JsonVariant&);
// bool add(JsonArray&);
// bool add(JsonObject&);
template <typename T>
FORCE_INLINE bool add(
const T &value,
typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) {
return addNode<T &>(const_cast<T &>(value));
}
// bool add(float value, uint8_t decimals);
// bool add(double value, uint8_t decimals);
template <typename T>
FORCE_INLINE bool add(
T value, uint8_t decimals,
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value>::type
* = 0) {
return addNode<JsonVariant>(JsonVariant(value, decimals));
}
// 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.
//
// bool set(size_t index, bool value);
// bool set(size_t index, long value);
// bool set(size_t index, int value);
// bool set(size_t index, short value);
template <typename T>
FORCE_INLINE bool set(
size_t index, T value,
typename TypeTraits::EnableIf<
CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) {
return setNodeAt<T>(index, value);
}
// bool set(size_t index, const String&)
// bool set(size_t index, const JsonVariant&);
// bool set(size_t index, JsonArray&);
// bool set(size_t index, JsonObject&);
template <typename T>
FORCE_INLINE bool set(
size_t index, const T &value,
typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) {
return setNodeAt<T &>(index, const_cast<T &>(value));
}
// bool set(size_t index, float value, uint8_t decimals = 2);
// bool set(size_t index, double value, uint8_t decimals = 2);
template <typename T>
FORCE_INLINE bool set(
size_t index, T value, uint8_t decimals,
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value>::type
* = 0) {
return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals));
}
// 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()
@ -72,7 +151,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
JsonObject &createNestedObject();
// Removes element at specified index.
void removeAt(int index);
void removeAt(size_t index);
// Returns a reference an invalid JsonArray.
// This object is meant to replace a NULL pointer.
@ -83,13 +162,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;
node_type *getNodeAt(int index) const;
template <typename TValue>
bool setNodeAt(size_t index, TValue value);
template <typename TValue>
bool addNode(TValue);
template <typename T>
FORCE_INLINE bool setNodeValue(node_type *, T value);
// The instance returned by JsonArray::invalid()
static JsonArray _invalid;
};
}
#include "JsonArray.ipp"

View File

@ -0,0 +1,101 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "JsonArray.hpp"
#include "JsonObject.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);
}
template <typename TValue>
inline bool JsonArray::addNode(TValue value) {
node_type *node = addNewNode();
return node != NULL && setNodeValue<TValue>(node, value);
}
template <typename TValue>
inline bool JsonArray::setNodeAt(size_t index, TValue value) {
node_type *node = getNodeAt(index);
return node != NULL && setNodeValue<TValue>(node, value);
}
template <typename TValue>
inline bool JsonArray::setNodeValue(node_type *node, TValue value) {
node->content = value;
return true;
}
template <>
inline bool JsonArray::setNodeValue(node_type *node, String &value) {
const char *copy = _buffer->strdup(value);
if (!copy) return false;
node->content = copy;
return true;
}
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();
}
inline JsonArray &JsonVariant::asArray() const {
if (_type == Internals::JSON_ARRAY) return *_content.asArray;
return JsonArray::invalid();
}
inline JsonArray &JsonArray::createNestedArray() {
if (!_buffer) return JsonArray::invalid();
JsonArray &array = _buffer->createArray();
add(array);
return array;
}
inline JsonArray &JsonObject::createNestedArray(JsonObjectKey key) {
if (!_buffer) return JsonArray::invalid();
JsonArray &array = _buffer->createArray();
setNodeAt<const JsonVariant &>(key, array);
return array;
}
}

View File

@ -0,0 +1,84 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "Configuration.hpp"
#include "JsonVariantBase.hpp"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4522)
#endif
namespace ArduinoJson {
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
public:
FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
: _array(array), _index(index) {}
JsonArraySubscript& operator=(const JsonArraySubscript& src) {
_array.set<const JsonVariant&>(_index, src);
return *this;
}
template <typename T>
typename TypeTraits::EnableIf<JsonArray::CanSet<T&>::value,
JsonArraySubscript>::type&
operator=(const T& src) {
_array.set<T&>(_index, const_cast<T&>(src));
return *this;
}
template <typename T>
typename TypeTraits::EnableIf<JsonArray::CanSet<T>::value,
JsonArraySubscript>::type&
operator=(T src) {
_array.set<T>(_index, src);
return *this;
}
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;
};
#if 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

View File

@ -1,13 +1,18 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include <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"
@ -55,6 +60,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
@ -67,20 +83,53 @@ 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 ARDUINOJSON_ENABLE_ALIGNMENT
const size_t x = sizeof(void *) - 1;
return (bytes + x) & ~x;
#else
return bytes;
#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;
};

View File

@ -1,16 +1,22 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "Arduino/String.hpp"
#include "Internals/JsonBufferAllocated.hpp"
#include "Internals/JsonPrintable.hpp"
#include "Internals/List.hpp"
#include "Internals/ReferenceType.hpp"
#include "JsonPair.hpp"
#include "TypeTraits/EnableIf.hpp"
#include "TypeTraits/IsFloatingPoint.hpp"
#include "TypeTraits/IsReference.hpp"
#include "TypeTraits/IsSame.hpp"
// Returns the size (in bytes) of an object with n elements.
// Can be very handy to determine the size of a StaticJsonBuffer.
@ -33,75 +39,115 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
public Internals::ReferenceType,
public Internals::List<JsonPair>,
public Internals::JsonBufferAllocated {
// JsonBuffer is a friend because it needs to call the private constructor.
friend class JsonBuffer;
public:
typedef const char *key_type;
typedef JsonPair value_type;
// Gets the JsonVariant associated with the specified key.
// Returns a reference or JsonVariant::invalid() if not found.
JsonVariant &at(key_type 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 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.
// A meta-function that returns true if type T can be used in
// JsonObject::set()
template <typename T>
void add(key_type key, T value) {
add(key).set(value);
struct CanSet {
static const bool value = JsonVariant::IsConstructibleFrom<T>::value ||
TypeTraits::IsSame<T, String&>::value ||
TypeTraits::IsSame<T, const String&>::value;
};
// 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 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 value associated with the specified key.
FORCE_INLINE JsonVariant operator[](JsonObjectKey key) const;
// Sets the specified key with the specified value.
// bool set(TKey key, bool value);
// bool set(TKey key, char value);
// bool set(TKey key, long value);
// bool set(TKey key, int value);
// bool set(TKey key, short value);
// bool set(TKey key, float value);
// bool set(TKey key, double value);
// bool set(TKey key, const char* value);
template <typename T>
FORCE_INLINE bool set(
JsonObjectKey key, T value,
typename TypeTraits::EnableIf<
CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type* = 0) {
return setNodeAt<T>(key, value);
}
// bool set(Key, String&);
// bool set(Key, JsonArray&);
// bool set(Key, JsonObject&);
// bool set(Key, JsonVariant&);
template <typename T>
FORCE_INLINE bool set(
JsonObjectKey key, const T& value,
typename TypeTraits::EnableIf<CanSet<T&>::value>::type* = 0) {
return setNodeAt<T&>(key, const_cast<T&>(value));
}
// bool set(Key, float value, uint8_t decimals);
// bool set(Key, double value, uint8_t decimals);
template <typename TValue>
FORCE_INLINE bool set(
JsonObjectKey key, TValue value, uint8_t decimals,
typename TypeTraits::EnableIf<
TypeTraits::IsFloatingPoint<TValue>::value>::type* = 0) {
return setNodeAt<const JsonVariant&>(key, JsonVariant(value, decimals));
}
// Adds the specified key with a reference to the specified JsonArray.
void add(key_type key, JsonArray &array) { add(key).set(array); }
// Gets the value associated with the specified key.
FORCE_INLINE JsonVariant get(JsonObjectKey) const;
// 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.
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(JsonObjectKey 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(JsonObjectKey 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(const char* key) const;
node_type* getOrCreateNodeAt(const char* key);
template <typename T>
FORCE_INLINE bool setNodeAt(JsonObjectKey key, T value);
FORCE_INLINE bool setNodeKey(node_type*, JsonObjectKey key);
template <typename T>
FORCE_INLINE bool setNodeValue(node_type*, T value);
// The instance returned by JsonObject::invalid()
static JsonObject _invalid;
};
}
#include "JsonObject.ipp"

View File

@ -0,0 +1,130 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "JsonArray.hpp"
#include "JsonObject.hpp"
#include "JsonObjectSubscript.hpp"
namespace ArduinoJson {
inline JsonVariant JsonObject::get(JsonObjectKey key) const {
node_type *node = getNodeAt(key.c_str());
return node ? node->content.value : JsonVariant();
}
template <typename T>
inline T JsonObject::get(JsonObjectKey key) const {
node_type *node = getNodeAt(key.c_str());
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.c_str());
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.c_str()) != NULL;
}
inline void JsonObject::remove(JsonObjectKey key) {
removeNode(getNodeAt(key.c_str()));
}
template <typename T>
inline bool JsonObject::setNodeAt(JsonObjectKey key, T value) {
node_type *node = getNodeAt(key.c_str());
if (!node) node = addNewNode();
return node && setNodeKey(node, key) && setNodeValue<T>(node, value);
}
inline bool JsonObject::setNodeKey(node_type *node, JsonObjectKey key) {
if (key.needs_copy()) {
node->content.key = _buffer->strdup(key.c_str());
if (node->content.key == NULL) return false;
} else {
node->content.key = key.c_str();
}
return true;
}
template <typename TValue>
inline bool JsonObject::setNodeValue(node_type *node, TValue value) {
node->content.value = value;
return true;
}
template <>
inline bool JsonObject::setNodeValue(node_type *node, String &value) {
node->content.value = _buffer->strdup(value);
return node->content.value;
}
template <>
inline bool JsonObject::setNodeValue(node_type *node, const String &value) {
node->content.value = _buffer->strdup(value);
return node->content.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();
}
inline JsonObject &JsonVariant::asObject() const {
if (_type == Internals::JSON_OBJECT) return *_content.asObject;
return JsonObject::invalid();
}
inline JsonObject &JsonObject::createNestedObject(JsonObjectKey key) {
if (!_buffer) return JsonObject::invalid();
JsonObject &array = _buffer->createObject();
setNodeAt<const JsonVariant &>(key, array);
return array;
}
inline JsonObject &JsonArray::createNestedObject() {
if (!_buffer) return JsonObject::invalid();
JsonObject &object = _buffer->createObject();
add(object);
return object;
}
}

View File

@ -0,0 +1,27 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "Arduino/String.hpp"
namespace ArduinoJson {
// Represents a key in a JsonObject
class JsonObjectKey {
public:
JsonObjectKey(const char* key) : _value(key), _needs_copy(false) {}
JsonObjectKey(const String& key) : _value(key.c_str()), _needs_copy(true) {}
const char* c_str() const { return _value; }
bool needs_copy() const { return _needs_copy; }
private:
const char* _value;
bool _needs_copy;
};
}

View File

@ -0,0 +1,99 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "Configuration.hpp"
#include "JsonVariantBase.hpp"
#include "TypeTraits/EnableIf.hpp"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4522)
#endif
namespace ArduinoJson {
template <typename TKey>
class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > {
public:
FORCE_INLINE JsonObjectSubscript(JsonObject& object, TKey key)
: _object(object), _key(key) {}
JsonObjectSubscript<TKey>& operator=(const JsonObjectSubscript<TKey>& src) {
_object.set<const JsonVariant&>(_key, src);
return *this;
}
template <typename T>
typename TypeTraits::EnableIf<JsonObject::CanSet<T&>::value,
JsonObjectSubscript<TKey> >::type&
operator=(const T& src) {
_object.set<T&>(_key, const_cast<T&>(src));
return *this;
}
template <typename T>
typename TypeTraits::EnableIf<JsonObject::CanSet<T>::value,
JsonObjectSubscript<TKey> >::type&
operator=(T src) {
_object.set<T>(_key, src);
return *this;
}
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<TValue>(_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;
};
#if 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

View File

@ -1,11 +1,13 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "JsonObjectKey.hpp"
#include "JsonVariant.hpp"
namespace ArduinoJson {

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
@ -12,6 +13,14 @@
#include "Internals/JsonPrintable.hpp"
#include "Internals/JsonVariantContent.hpp"
#include "Internals/JsonVariantType.hpp"
#include "Internals/Unparsed.hpp"
#include "JsonVariantBase.hpp"
#include "TypeTraits/EnableIf.hpp"
#include "TypeTraits/IsFloatingPoint.hpp"
#include "TypeTraits/IsIntegral.hpp"
#include "TypeTraits/IsSame.hpp"
#include "TypeTraits/RemoveConst.hpp"
#include "TypeTraits/RemoveReference.hpp"
namespace ArduinoJson {
@ -26,261 +35,183 @@ 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) {}
// Initializes a JsonVariant with the specified value.
template <typename T>
explicit JsonVariant(T value) {
set(value);
}
struct IsConstructibleFrom;
// Tells weither the variant is valid.
bool success() const {
return _type != Internals::JSON_INVALID &&
_type != Internals::JSON_UNDEFINED;
}
// Creates an uninitialized JsonVariant
FORCE_INLINE JsonVariant() : _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);
// 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)); }
// Sets the variant to be a string.
void set(const char *value);
// Sets the variant to be a reference to an array.
void set(JsonArray &array);
// Sets the variant to be a reference to an object.
void set(JsonObject &object);
// Sets the variant to the specified value.
// JsonVariant(double value, uint8_t decimals);
// JsonVariant(float value, uint8_t decimals);
template <typename T>
JsonVariant &operator=(T value) {
set(value);
return *this;
FORCE_INLINE JsonVariant(
T value, uint8_t decimals = 2,
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value>::type
* = 0) {
using namespace Internals;
_type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals);
_content.asFloat = static_cast<JsonFloat>(value);
}
// Sets the variant to be a reference to an array.
JsonVariant &operator=(JsonArray &array) {
set(array);
return *this;
// Create a JsonVariant containing an integer value.
// JsonVariant(short)
// JsonVariant(int)
// JsonVariant(long)
template <typename T>
FORCE_INLINE JsonVariant(
T value,
typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value>::type * =
0) {
using namespace Internals;
_type = JSON_INTEGER;
_content.asInteger = static_cast<JsonInteger>(value);
}
// Sets the variant to be a reference to an object.
JsonVariant &operator=(JsonObject &object) {
set(object);
return *this;
}
// Create a JsonVariant containing a string.
FORCE_INLINE JsonVariant(const char *value);
// Gets the variant as a boolean value.
// Returns false if the variant is not a boolean value.
operator bool() const;
// Create a JsonVariant containing an unparsed string
FORCE_INLINE JsonVariant(Internals::Unparsed value);
// 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>()); }
// Create a JsonVariant containing a reference to an array.
FORCE_INLINE JsonVariant(JsonArray &array);
// 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.
// short as<short>() const;
// int as<int>() const;
// long as<long>() const;
template <typename T>
T as() const {
return static_cast<T>(*this);
const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value, T>::type
as() const {
return static_cast<T>(asInteger());
}
// double as<double>() const;
// float as<float>() const;
template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
T>::type
as() const {
return static_cast<T>(asFloat());
}
// const String as<String>() const;
template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, String>::value,
T>::type
as() const {
return toString();
}
// const char* as<const char*>() const;
// const char* as<char*>() const;
template <typename T>
typename TypeTraits::EnableIf<TypeTraits::IsSame<T, const char *>::value,
const char *>::type
as() const {
return asString();
}
// const bool as<bool>() const
template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
T>::type
as() const {
return asInteger() != 0;
}
// JsonArray& as<JsonArray> const;
// JsonArray& as<JsonArray&> const;
// JsonArray& as<const JsonArray&> const;
template <typename T>
typename TypeTraits::EnableIf<
TypeTraits::IsSame<
typename TypeTraits::RemoveConst<
typename TypeTraits::RemoveReference<T>::type>::type,
JsonArray>::value,
JsonArray &>::type
as() const {
return asArray();
}
// JsonObject& as<JsonObject> const;
// JsonObject& as<JsonObject&> const;
// JsonObject& as<const JsonObject&> const;
template <typename T>
typename TypeTraits::EnableIf<
TypeTraits::IsSame<
typename TypeTraits::RemoveConst<
typename TypeTraits::RemoveReference<T>::type>::type,
JsonObject>::value,
JsonObject &>::type
as() const {
return asObject();
}
// 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;
// TODO: rename
template <typename T>
static T invalid();
// 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);
const char *asString() const;
JsonArray &asArray() const;
JsonObject &asObject() const;
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>());
}
String toString() const;
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;
}
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;
inline JsonVariant double_with_n_digits(double value, uint8_t digits) {
return JsonVariant(value, digits);
}
template <typename T>
inline bool operator==(const JsonVariant &left, T right) {
return left.as<T>() == right;
struct JsonVariant::IsConstructibleFrom {
static const bool value =
TypeTraits::IsIntegral<T>::value ||
TypeTraits::IsFloatingPoint<T>::value ||
TypeTraits::IsSame<T, bool>::value ||
TypeTraits::IsSame<T, char *>::value ||
TypeTraits::IsSame<T, const char *>::value ||
TypeTraits::IsSame<T, JsonArray &>::value ||
TypeTraits::IsSame<T, const JsonArray &>::value ||
TypeTraits::IsSame<T, JsonArraySubscript &>::value ||
TypeTraits::IsSame<T, const JsonArraySubscript &>::value ||
TypeTraits::IsSame<T, JsonObject &>::value ||
TypeTraits::IsSame<T, const JsonObject &>::value ||
TypeTraits::IsSame<T, JsonObjectSubscript<const char *> &>::value ||
TypeTraits::IsSame<T, const JsonObjectSubscript<const char *> &>::value ||
TypeTraits::IsSame<T, JsonObjectSubscript<String> &>::value ||
TypeTraits::IsSame<T, const JsonObjectSubscript<String> &>::value ||
TypeTraits::IsSame<T, JsonVariant &>::value ||
TypeTraits::IsSame<T, const JsonVariant &>::value;
};
}
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"

View File

@ -0,0 +1,150 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "Configuration.hpp"
#include "JsonVariant.hpp"
#include "Internals/Parse.hpp"
#include <string.h>
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(JsonArray &array) {
_type = Internals::JSON_ARRAY;
_content.asArray = &array;
}
inline JsonVariant::JsonVariant(JsonObject &object) {
_type = Internals::JSON_OBJECT;
_content.asObject = &object;
}
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 <> // int .cpp
bool JsonVariant::is<bool>() const;
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>();
}
inline Internals::JsonInteger JsonVariant::asInteger() const {
if (_type == Internals::JSON_INTEGER || _type == Internals::JSON_BOOLEAN)
return _content.asInteger;
if (_type >= Internals::JSON_FLOAT_0_DECIMALS)
return static_cast<Internals::JsonInteger>(_content.asFloat);
if ((_type == Internals::JSON_STRING || _type == Internals::JSON_UNPARSED) &&
_content.asString) {
if (!strcmp("true", _content.asString)) return 1;
return Internals::parse<Internals::JsonInteger>(_content.asString);
}
return 0L;
}
#if ARDUINOJSON_ENABLE_STD_STREAM
inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) {
return source.printTo(os);
}
#endif
} // namespace ArduinoJson

View File

@ -0,0 +1,133 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "Internals/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:
FORCE_INLINE 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.
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 operator T() const {
return as<T>();
}
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>();
}
}

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
@ -21,11 +22,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;
}

View File

@ -0,0 +1,22 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
namespace ArduinoJson {
namespace TypeTraits {
// A meta-function that return the type T if Condition is true.
template <bool Condition, typename T = void>
struct EnableIf {};
template <typename T>
struct EnableIf<true, T> {
typedef T type;
};
}
}

View File

@ -0,0 +1,21 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "IsSame.hpp"
namespace ArduinoJson {
namespace TypeTraits {
// A meta-function that returns true if T is a floating point type
template <typename T>
struct IsFloatingPoint {
static const bool value = IsSame<T, float>::value || IsSame<T, double>::value;
};
}
}

View File

@ -0,0 +1,41 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "../Configuration.hpp"
#include "IsSame.hpp"
#include <stdint.h>
namespace ArduinoJson {
namespace TypeTraits {
// A meta-function that returns true if T is an integral type.
template <typename T>
struct IsIntegral {
static const bool value = TypeTraits::IsSame<T, signed char>::value ||
TypeTraits::IsSame<T, unsigned char>::value ||
TypeTraits::IsSame<T, signed short>::value ||
TypeTraits::IsSame<T, unsigned short>::value ||
TypeTraits::IsSame<T, signed int>::value ||
TypeTraits::IsSame<T, unsigned int>::value ||
TypeTraits::IsSame<T, signed long>::value ||
TypeTraits::IsSame<T, unsigned long>::value ||
#if ARDUINOJSON_USE_LONG_LONG
TypeTraits::IsSame<T, long long>::value ||
TypeTraits::IsSame<T, unsigned long long>::value ||
#endif
#if ARDUINOJSON_USE_INT64
TypeTraits::IsSame<T, __int64>::value ||
TypeTraits::IsSame<T, unsigned __int64>::value ||
#endif
TypeTraits::IsSame<T, char>::value;
};
}
}

View File

@ -0,0 +1,24 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
namespace ArduinoJson {
namespace TypeTraits {
// A meta-function that returns true if T is a reference
template <typename T>
struct IsReference {
static const bool value = false;
};
template <typename T>
struct IsReference<T&> {
static const bool value = true;
};
}
}

View File

@ -0,0 +1,24 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
namespace ArduinoJson {
namespace TypeTraits {
// A meta-function that returns true if types T and U are the same.
template <typename T, typename U>
struct IsSame {
static const bool value = false;
};
template <typename T>
struct IsSame<T, T> {
static const bool value = true;
};
}
}

View File

@ -0,0 +1,23 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
namespace ArduinoJson {
namespace TypeTraits {
// A meta-function that return the type T without the const modifier
template <typename T>
struct RemoveConst {
typedef T type;
};
template <typename T>
struct RemoveConst<const T> {
typedef T type;
};
}
}

View File

@ -0,0 +1,23 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
namespace ArduinoJson {
namespace TypeTraits {
// A meta-function that return the type T without the reference modifier.
template <typename T>
struct RemoveReference {
typedef T type;
};
template <typename T>
struct RemoveReference<T&> {
typedef T type;
};
}
}

View File

@ -2,16 +2,21 @@
"name": "Json",
"keywords": "json, rest, http, web",
"description": "An elegant and efficient JSON library for embedded systems",
"repository":
{
"repository": {
"type": "git",
"url": "https://github.com/bblanchon/ArduinoJson.git"
},
"authors":
{
"version": "5.1.0",
"authors": {
"name": "Benoit Blanchon",
"url": "http://blog.benoitblanchon.fr"
},
"exclude": [
"scripts",
"src/ArduinoJson.h",
"test",
"third-party"
],
"frameworks": "arduino",
"platforms": "atmelavr"
}
"platforms": "*"
}

9
library.properties Normal file
View File

@ -0,0 +1,9 @@
name=ArduinoJson
version=5.1.0
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=*

View File

@ -3,7 +3,7 @@
TAG=$(git describe)
OUTPUT="ArduinoJson-$TAG.zip"
cd ../..
cd $(dirname $0)/../..
# remove existing file
rm -f $OUTPUT
@ -14,9 +14,8 @@ rm -f $OUTPUT
ArduinoJson/examples \
ArduinoJson/include \
ArduinoJson/keywords.txt \
ArduinoJson/library.properties \
ArduinoJson/LICENSE.md \
ArduinoJson/README.md \
ArduinoJson/src \
ArduinoJson/ArduinoJson.h \
ArduinoJson/ArduinoJson.cpp \
-x!ArduinoJson/src/CMakeLists.txt
-x!ArduinoJson/src/CMakeLists.txt

View 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

42
scripts/create-size-graph.sh Executable file
View 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

15
scripts/travis/arduino.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/sh -eux
/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
mkdir -p /tmp/arduino
curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tar.xz | tar xJ -C /tmp/arduino --strip 1 ||
curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tgz | tar xz -C /tmp/arduino --strip 1
export PATH=$PATH:/tmp/arduino/
ln -s $PWD /tmp/arduino/libraries/ArduinoJson
arduino --verify --board $BOARD $PWD/examples/JsonParserExample/JsonParserExample.ino
arduino --verify --board $BOARD $PWD/examples/JsonGeneratorExample/JsonGeneratorExample.ino

10
scripts/travis/clang.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh -eux
export CC=clang
export CXX=clang++
curl -sS https://cmake.org/files/v3.4/cmake-3.4.0-Linux-x86_64.tar.gz | tar xz -C /tmp --strip 1
/tmp/bin/cmake .
make
make test

13
scripts/travis/gcc.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/sh -eux
export CC=gcc
export CXX=g++
curl https://cmake.org/files/v3.4/cmake-3.4.0-Linux-x86_64.tar.gz | tar xz -C /tmp --strip 1
/tmp/bin/cmake -DCOVERAGE=true .
make
make test
pip install --user cpp-coveralls
coveralls --exclude third-party --gcov-options '\-lp'; fi

10
scripts/travis/platformio.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh -eux
pip install --user platformio
rm -r test
for EXAMPLE in JsonParserExample JsonGeneratorExample
do
platformio ci examples/$EXAMPLE/$EXAMPLE.ino -l '.' -b $BOARD
done

View File

@ -1,52 +0,0 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#ifndef ARDUINO
#include "../../include/ArduinoJson/Arduino/Print.hpp"
#include <math.h> // for isnan() and isinf()
#include <stdio.h> // for sprintf()
size_t Print::print(const char s[]) {
size_t n = 0;
while (*s) {
n += write(*s++);
}
return n;
}
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];
// 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);
}
size_t Print::print(long value) {
char tmp[32];
sprintf(tmp, "%ld", value);
return print(tmp);
}
size_t Print::println() { return write('\r') + write('\n'); }
#endif

14
src/ArduinoJson.h Normal file
View File

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

View File

@ -1,9 +1,18 @@
file(GLOB_RECURSE INC_FILES ../include/*.hpp)
file(GLOB_RECURSE SRC_FILES *.cpp)
# Copyright Benoit Blanchon 2014-2016
# MIT License
#
# Arduino JSON library
# https://github.com/bblanchon/ArduinoJson
# If you like this project, please add a star!
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
@ -42,7 +51,16 @@ endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_definitions(
-Wc++11-compat
-Wdeprecated-register
)
endif()
add_library(ArduinoJson ${SRC_FILES} ${INC_FILES})
if(MSVC)
add_definitions(
-D_CRT_SECURE_NO_WARNINGS
-W4)
endif()
add_library(ArduinoJson ${CPP_FILES} ${HPP_FILES} ${IPP_FILES})
target_include_directories(ArduinoJson INTERFACE ${CMAKE_CURRENT_LIST_DIR}/../include)

View File

@ -0,0 +1,52 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../../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;
}
}
}

View File

@ -0,0 +1,14 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../../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";

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../../include/ArduinoJson/Internals/IndentedPrint.hpp"

View File

@ -1,15 +1,14 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../../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 +16,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 +58,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 +74,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 +102,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 +120,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;
}

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../../include/ArduinoJson/Internals/List.hpp"
@ -13,12 +14,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;

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../../include/ArduinoJson/Internals/Prettyfier.hpp"
@ -33,7 +34,7 @@ inline size_t Prettyfier::handleMarkupChar(uint8_t c) {
return handleBlockClose(c);
case ':':
return handleColumn();
return handleColon();
case ',':
return handleComma();
@ -54,7 +55,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(' ');
}

View File

@ -1,101 +0,0 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include "../../include/ArduinoJson/Internals/QuotedString.hpp"
using namespace ArduinoJson::Internals;
// How to escape special chars:
// specialChars[2*i+1] => the special char
// specialChars[2*i] => the char to use instead
static const char specialChars[] = "\"\"\\\\b\bf\fn\nr\rt\t";
static inline char getSpecialChar(char c) {
// Optimized for code size on a 8-bit AVR
const char *p = specialChars;
while (p[0] && p[1] != c) {
p += 2;
}
return p[0];
}
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 = specialChars + 4;
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 *startPtr = input + 1; // skip the quote
char *readPtr = startPtr;
char *writePtr = startPtr;
char c;
char firstChar = *input;
char stopChar = firstChar; // closing quote is the same as opening quote
if (!isQuote(firstChar)) goto ERROR_OPENING_QUOTE_MISSING;
for (;;) {
c = *readPtr++;
if (c == '\0') goto ERROR_CLOSING_QUOTE_MISSING;
if (c == stopChar) goto SUCCESS;
if (c == '\\') {
// replace char
c = unescapeChar(*readPtr++);
if (c == '\0') goto ERROR_ESCAPE_SEQUENCE_INTERRUPTED;
}
*writePtr++ = c;
}
SUCCESS:
// end the string here
*writePtr = '\0';
// update end ptr
*endPtr = readPtr;
// return pointer to unquoted string
return startPtr;
ERROR_OPENING_QUOTE_MISSING:
ERROR_CLOSING_QUOTE_MISSING:
ERROR_ESCAPE_SEQUENCE_INTERRUPTED:
return NULL;
}

View File

@ -1,14 +1,15 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../../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;

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../include/ArduinoJson/JsonArray.hpp"
@ -14,41 +15,13 @@ using namespace ArduinoJson::Internals;
JsonArray JsonArray::_invalid(NULL);
JsonVariant &JsonArray::at(int index) const {
node_type *node = getNodeAt(index);
return node ? node->content : JsonVariant::invalid();
}
JsonVariant &JsonArray::add() {
node_type *node = createNode();
if (!node) return JsonVariant::invalid();
addNode(node);
return node->content;
}
JsonArray &JsonArray::createNestedArray() {
if (!_buffer) return JsonArray::invalid();
JsonArray &array = _buffer->createArray();
add(array);
return array;
}
JsonObject &JsonArray::createNestedObject() {
if (!_buffer) return JsonObject::invalid();
JsonObject &object = _buffer->createObject();
add(object);
return object;
}
JsonArray::node_type *JsonArray::getNodeAt(int index) const {
JsonArray::node_type *JsonArray::getNodeAt(size_t index) const {
node_type *node = _firstNode;
while (node && index--) node = node->next;
return node;
}
void JsonArray::removeAt(int index) { removeNode(getNodeAt(index)); }
void JsonArray::removeAt(size_t index) { removeNode(getNodeAt(index)); }
void JsonArray::writeTo(JsonWriter &writer) const {
writer.beginArray();

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../include/ArduinoJson/JsonBuffer.hpp"
@ -32,3 +33,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;
}

View File

@ -1,14 +1,15 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../include/ArduinoJson/JsonObject.hpp"
#include <string.h> // for strcmp
#include "../include/ArduinoJson/Internals/StringBuilder.hpp"
#include "../include/ArduinoJson/Internals/StaticStringBuilder.hpp"
#include "../include/ArduinoJson/JsonArray.hpp"
#include "../include/ArduinoJson/JsonBuffer.hpp"
@ -17,48 +18,6 @@ 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();
}
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) {
if (!_buffer) return JsonArray::invalid();
JsonArray &array = _buffer->createArray();
add(key, array);
return array;
}
JsonObject &JsonObject::createNestedObject(const char *key) {
if (!_buffer) return JsonObject::invalid();
JsonObject &object = _buffer->createObject();
add(key, object);
return object;
}
JsonObject::node_type *JsonObject::getNodeAt(const char *key) const {
for (node_type *node = _firstNode; node; node = node->next) {
if (!strcmp(node->content.key, key)) return node;

View File

@ -1,108 +1,110 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../include/ArduinoJson/JsonVariant.hpp"
#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();
const char *JsonVariant::asString() 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 JsonObject &() const {
return _type == JSON_OBJECT ? *_content.asObject : JsonObject::invalid();
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;
}
JsonVariant::operator bool() const {
return _type == JSON_BOOLEAN ? _content.asBoolean : false;
String JsonVariant::toString() const {
String s;
if ((_type == JSON_STRING || _type == JSON_UNPARSED) &&
_content.asString != NULL)
s = _content.asString;
else
printTo(s);
return s;
}
JsonVariant::operator const char *() const {
return _type == JSON_STRING ? _content.asString : NULL;
template <>
bool JsonVariant::is<bool>() const {
if (_type == JSON_BOOLEAN) return true;
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
return !strcmp(_content.asString, "true") ||
!strcmp(_content.asString, "false");
}
JsonVariant::operator double() const {
return _type >= JSON_DOUBLE_0_DECIMALS ? _content.asDouble : 0;
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;
}
JsonVariant::operator long() const {
return _type == JSON_LONG ? _content.asLong : 0;
}
template <>
bool JsonVariant::is<double>() const {
if (_type >= JSON_FLOAT_0_DECIMALS) return true;
void JsonVariant::set(bool value) {
if (_type == JSON_INVALID) return;
_type = Internals::JSON_BOOLEAN;
_content.asBoolean = value;
}
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
void JsonVariant::set(const char *value) {
if (_type == JSON_INVALID) return;
_type = JSON_STRING;
_content.asString = value;
}
char *end;
errno = 0;
strtod(_content.asString, &end);
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;
}
void JsonVariant::set(long value) {
if (_type == JSON_INVALID) return;
_type = JSON_LONG;
_content.asLong = value;
}
void JsonVariant::set(JsonArray &array) {
if (_type == JSON_INVALID) return;
_type = array.success() ? JSON_ARRAY : JSON_INVALID;
_content.asArray = &array;
}
void JsonVariant::set(JsonObject &object) {
if (_type == JSON_INVALID) return;
_type = object.success() ? JSON_OBJECT : JSON_INVALID;
_content.asObject = &object;
}
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);
}
}
}

View File

@ -0,0 +1,221 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <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);
}

View File

@ -1,21 +1,35 @@
# Copyright Benoit Blanchon 2014-2016
# MIT License
#
# Arduino JSON library
# https://github.com/bblanchon/ArduinoJson
# If you like this project, please add a star!
set(GTEST_DIR ../third-party/gtest-1.7.0)
file(GLOB_RECURSE INC_FILES ../include/*.h)
file(GLOB TESTS_FILES *.hpp *.cpp)
include_directories(
../include
${GTEST_DIR}
${GTEST_DIR}/include)
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()
if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
add_executable(ArduinoJsonTests
${TESTS_FILES}
${INC_FILES}
${GTEST_DIR}/src/gtest-all.cc
${GTEST_DIR}/src/gtest_main.cc)
target_link_libraries(ArduinoJsonTests ArduinoJson)
add_test(ArduinoJsonTests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ArduinoJsonTests)
add_test(ArduinoJsonTests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ArduinoJsonTests)

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
@ -22,9 +23,9 @@ TEST_F(DynamicJsonBuffer_Basic_Tests, InitialSizeIsZero) {
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());
ASSERT_LE(2U, buffer.size());
}
TEST_F(DynamicJsonBuffer_Basic_Tests, ReturnDifferentPointer) {
@ -32,3 +33,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);
}
}

View File

@ -1,23 +1,29 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
class DynamicJsonBuffer_NoMemory_Tests : public ::testing::Test {
class NoMemoryAllocator {
public:
void* allocate(size_t) { return NULL; }
void deallocate(void*) {}
};
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());
}

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
@ -13,12 +14,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());
}

View File

@ -1,12 +1,12 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#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());

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>

16
test/Issue214.cpp Normal file
View File

@ -0,0 +1,16 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <ArduinoJson.h>
#include <gtest/gtest.h>
TEST(Issue214, IsBool) {
char json[] = "{\"ota\": {\"enabled\": true}}";
StaticJsonBuffer<JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(1)> jsonBuffer;
JsonObject& parsedJson = jsonBuffer.parseObject(json);
ASSERT_TRUE(parsedJson["ota"]["enabled"].is<bool>());
}

View File

@ -1,8 +1,9 @@
// Copyright Benoit Blanchon 2014-2015
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>

Some files were not shown because too many files have changed in this diff Show More