5.10.0 20171201
 * Upgrade library ArduinoJson to 5.11.2
 * Upgrade
library IRRemoteEsp8266 to 2.2.1 + 2 commits but disabled some protocols
(code size reduction)
 * Upgrade library NeoPixelBus to 2.2.9
 * Upgrade
library OneWire to 2.3.3 + 6 commits and disabled CRC lookup-table
(#define ONEWIRE_CRC8_TABLE 0) (code size reduction)
 * Update library
PubSubClient to 2.6 + 9 commits and additional delay (#790)
 * Update
core_esp8266_wiring_digital.c to latest (staged) level
 * Patch library
I2Cdevlib-Core for esp8266-core 2.4.0-rc2 compatibility
 * Remove
command EnergyReset 1..3 now replaced by ENergyReset1 to EnergyReset3
 *
Remove spaces in JSON messages (code size reduction)
 * Renamed
xsns_05_ds18x20.ino to xsns_05_ds18x20_legacy.ino still using library
OneWire and providing dynamic sensor scan
 * Fix possible iram1_0_seg
compile error by shrinking ICACHE_RAM_ATTR code usage
 * Fix PWM
watchdog timeout if Dimmer is set to 100 or Color set to 0xFF (#1146)
 *
Fix Sonoff Bridge Learn Mode hang caused by unrecognised RF code
(#1181)
 * Fix blank console log window by using XML character encoding
(#1187)
 * Fix wrong response name for command HlwISet (#1214)
 * Fix
DHT type sensor timeout recognition by distinguish "signal already
there" from "timeout" (#1233)
 * Add fixed color options 1..12 to
command Color
 * Add + (plus) and - (minus) to commands Dimmer
(+10/-10), Speed and Scheme
 * Add + (plus) and - (minus) to command
Color to select 1 out of 12 preset colors
 * Add + (plus) and - (minus)
to command Ct to control ColdWarm led ColorTemperature (+34/-34)
 * Add
commands EnergyReset1 0..42500, EnergyReset2 0..42500 and EnergyReset3
0..42500000
 *  to (Re)set Energy Today, Yesterday or Total respectively
in Wh (#406, #685, #1202)
 * Add optional ADS1115 driver as alternative
for unsupported I2Cdevlib in esp8266-core 2.4.0-rc2
 * Add support for
INA219 Voltage and Current sensor to be enabled in user_config.h with
define USE_INA219
 * Add support for Arilux LC11 (Clearing RF home code
when selecting no Arilux module)
 * Add support for WS2812 RGBW
ledstrips to be enabled in user_config.h with define USE_WS2812_CTYPE
(#1156)
 * Add SettingsSaveAll routine to command SaveData to be used
before controlled power down (#1202)
 * Add option PUSHBUTTON_TOGGLE
(SwitchMode 7) to allow toggling on any switch change (#1221)
 * Add new
xdrv_05_ds18x20.ino free from library OneWire and add the following
features:
 *  Add support for DS1822
 *  Add forced setting of 12-bit
resolution for selected device types (#1222)
 *  Add read temperature
retry counter (#1215)
 *  Fix lost sensors by performing sensor probe at
restart only thereby removing dynamic sensor probe (#1215)
 *  Fix
sensor address sorting using ascending sort on sensor type followed by
sensor address
 *  Rewrite JSON resulting in shorter message allowing
more sensors in default firmware image:
 *
"DS18B20-1":{"Id":"00000483C23A","Temperature":19.5},"DS18B20-2":{"Id":"0000048EC44C","Temperature":19.6}

* Add additional define in user_config.h to select either single sensor
(defines disabled), new multi sensor (USE_DS18X20) or legacy multi
sensor (USE_DS18X20_LEGACY)
 * Add clock support for more different
pixel counts (#1226)
 * Add support for Sonoff Dual R2 (#1249)
 * Add
FriendlyName to web page tab and add program information to web page
footer (#1275)
This commit is contained in:
arendst 2017-12-01 14:42:22 +01:00
parent fe2d7c63ec
commit 3403ca1e0a
683 changed files with 25807 additions and 157532 deletions

View File

@ -1,7 +1,7 @@
## Sonoff-Tasmota ## Sonoff-Tasmota
Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE. Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE.
Current version is **5.9.1** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. Current version is **5.10.0** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information.
### ATTENTION All versions ### ATTENTION All versions
@ -37,13 +37,13 @@ The following devices are supported:
- [iTead Sonoff RF](https://www.itead.cc/smart-home/sonoff-rf.html) - [iTead Sonoff RF](https://www.itead.cc/smart-home/sonoff-rf.html)
- [iTead Sonoff SV](https://www.itead.cc/smart-home/sonoff-sv.html)<img src="https://github.com/arendst/arendst.github.io/blob/master/media/sonoff_th.jpg" width="250" align="right" /> - [iTead Sonoff SV](https://www.itead.cc/smart-home/sonoff-sv.html)<img src="https://github.com/arendst/arendst.github.io/blob/master/media/sonoff_th.jpg" width="250" align="right" />
- [iTead Sonoff TH10/TH16 with temperature sensor](https://www.itead.cc/smart-home/sonoff-th.html) - [iTead Sonoff TH10/TH16 with temperature sensor](https://www.itead.cc/smart-home/sonoff-th.html)
- [iTead Sonoff Dual](https://www.itead.cc/smart-home/sonoff-dual.html) - [iTead Sonoff Dual (R2)](https://www.itead.cc/smart-home/sonoff-dual.html)
- [iTead Sonoff Pow](https://www.itead.cc/smart-home/sonoff-pow.html) - [iTead Sonoff Pow](https://www.itead.cc/smart-home/sonoff-pow.html)
- [iTead Sonoff 4CH](https://www.itead.cc/smart-home/sonoff-4ch.html) - [iTead Sonoff 4CH](https://www.itead.cc/smart-home/sonoff-4ch.html)
- [iTead Sonoff 4CH Pro](https://www.itead.cc/smart-home/sonoff-4ch-pro.html) - [iTead Sonoff 4CH Pro](https://www.itead.cc/smart-home/sonoff-4ch-pro.html)
- [iTead S20 Smart Socket](https://www.itead.cc/smart-socket.html) - [iTead S20 Smart Socket](https://www.itead.cc/smart-socket.html)
- [iTead Slampher](https://www.itead.cc/slampher.html) - [iTead Slampher](https://www.itead.cc/slampher.html)
- [iTead Sonoff Touch](https://www.itead.cc/sonoff-touch-eu-local.html) - [iTead Sonoff Touch](https://www.itead.cc/sonoff-touch.html)
- [iTead Sonoff T1](https://www.itead.cc/sonoff-t1.html) - [iTead Sonoff T1](https://www.itead.cc/sonoff-t1.html)
- [iTead Sonoff SC](https://www.itead.cc/sonoff-sc.html) - [iTead Sonoff SC](https://www.itead.cc/sonoff-sc.html)
- [iTead Sonoff Led](https://www.itead.cc/sonoff-led.html)<img src="https://github.com/arendst/arendst.github.io/blob/master/media/sonoff4ch.jpg" height="250" align="right" /> - [iTead Sonoff Led](https://www.itead.cc/sonoff-led.html)<img src="https://github.com/arendst/arendst.github.io/blob/master/media/sonoff4ch.jpg" height="250" align="right" />

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#include "include/ArduinoJson.h" #include "src/ArduinoJson.h"

View File

@ -1,6 +1,88 @@
ArduinoJson: change log ArduinoJson: change log
======================= =======================
v5.11.2
-------
* Fixed `DynamicJsonBuffer::clear()` not resetting allocation size (issue #561)
* Fixed incorrect rounding for float values (issue #588)
v5.11.1
-------
* Removed dependency on `PGM_P` as Particle 0.6.2 doesn't define it (issue #546)
* Fixed warning "dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]"
* Fixed warning "floating constant exceeds range of 'float' [-Woverflow]" (issue #544)
* Fixed warning "this statement may fall through" [-Wimplicit-fallthrough=] (issue #539)
* Removed `ARDUINOJSON_DOUBLE_IS_64BITS` as it became useless.
* Fixed too many decimals places in float serialization (issue #543)
v5.11.0
-------
* Made `JsonBuffer` non-copyable (PR #524 by @luisrayas3)
* Added `StaticJsonBuffer::clear()`
* Added `DynamicJsonBuffer::clear()`
v5.10.1
-------
* Fixed IntelliSense errors in Visual Micro (issue #483)
* Fixed compilation in IAR Embedded Workbench (issue #515)
* Fixed reading "true" as a float (issue #516)
* Added `ARDUINOJSON_DOUBLE_IS_64BITS`
* Added `ARDUINOJSON_EMBEDDED_MODE`
v5.10.0
-------
* Removed configurable number of decimal places (issues #288, #427 and #506)
* Changed exponentiation thresholds to `1e7` and `1e-5` (issues #288, #427 and #506)
* `JsonVariant::is<double>()` now returns `true` for integers
* Fixed error `IsBaseOf is not a member of ArduinoJson::TypeTraits` (issue #495)
* Fixed error `forming reference to reference` (issue #495)
### BREAKING CHANGES :warning:
| Old syntax | New syntax |
|---------------------------------|---------------------|
| `double_with_n_digits(3.14, 2)` | `3.14` |
| `float_with_n_digits(3.14, 2)` | `3.14f` |
| `obj.set("key", 3.14, 2)` | `obj["key"] = 3.14` |
| `arr.add(3.14, 2)` | `arr.add(3.14)` |
| Input | Old output | New output |
|-----------|------------|------------|
| `3.14159` | `3.14` | `3.14159` |
| `42.0` | `42.00` | `42` |
| `0.0` | `0.00` | `0` |
| Expression | Old result | New result |
|--------------------------------|------------|------------|
| `JsonVariant(42).is<int>()` | `true` | `true` |
| `JsonVariant(42).is<float>()` | `false` | `true` |
| `JsonVariant(42).is<double>()` | `false` | `true` |
v5.9.0
------
* Added `JsonArray::remove(iterator)` (issue #479)
* Added `JsonObject::remove(iterator)`
* Renamed `JsonArray::removeAt(size_t)` into `remove(size_t)`
* Renamed folder `include/` to `src/`
* Fixed warnings `floating constant exceeds range of float`and `floating constant truncated to zero` (issue #483)
* Removed `Print` class and converted `printTo()` to a template method (issue #276)
* Removed example `IndentedPrintExample.ino`
* Now compatible with Particle 0.6.1, thanks to Jacob Nite (issue #294 and PR #461 by @foodbag)
v5.8.4
------
* Added custom implementation of `strtod()` (issue #453)
* Added custom implementation of `strtol()` (issue #465)
* `char` is now treated as an integral type (issue #337, #370)
v5.8.3 v5.8.3
------ ------
@ -34,7 +116,7 @@ v5.8.0
* Added support for `Stream` (issue #300) * Added support for `Stream` (issue #300)
* Reduced memory consumption by not duplicating spaces and comments * Reduced memory consumption by not duplicating spaces and comments
**BREAKING CHANGES**: ### BREAKING CHANGES :warning:
`JsonBuffer::parseObject()` and `JsonBuffer::parseArray()` have been pulled down to the derived classes `DynamicJsonBuffer` and `StaticJsonBufferBase`. `JsonBuffer::parseObject()` and `JsonBuffer::parseArray()` have been pulled down to the derived classes `DynamicJsonBuffer` and `StaticJsonBufferBase`.
@ -52,6 +134,7 @@ void myFunction(StaticJsonBufferBase& jsonBuffer);
template<typename TJsonBuffer> void myFunction(TJsonBuffer& jsonBuffer); template<typename TJsonBuffer> void myFunction(TJsonBuffer& jsonBuffer);
``` ```
v5.7.3 v5.7.3
------ ------
@ -83,7 +166,7 @@ v5.7.0
* Added example `StringExample.ino` to show where `String` can be used * Added example `StringExample.ino` to show where `String` can be used
* Increased default nesting limit to 50 when compiled for a computer (issue #349) * Increased default nesting limit to 50 when compiled for a computer (issue #349)
**BREAKING CHANGES**: ### BREAKING CHANGES :warning:
The non-template functions `JsonObject::get()` and `JsonArray.get()` have been removed. This means that you need to explicitely tell the type you expect in return. The non-template functions `JsonObject::get()` and `JsonArray.get()` have been removed. This means that you need to explicitely tell the type you expect in return.
@ -210,7 +293,8 @@ v5.0.7
* Made library easier to use from a CMake project: simply `add_subdirectory(ArduinoJson/src)` * 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) * Changed `String` to be a `typedef` of `std::string` (issues #142 and #161)
**BREAKING CHANGES**: ### BREAKING CHANGES :warning:
- `JsonVariant(true).as<String>()` now returns `"true"` instead of `"1"` - `JsonVariant(true).as<String>()` now returns `"true"` instead of `"1"`
- `JsonVariant(false).as<String>()` now returns `"false"` instead of `"0"` - `JsonVariant(false).as<String>()` now returns `"false"` instead of `"0"`
@ -266,7 +350,8 @@ v5.0.0
* Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66) * 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) * Switched to new the library layout (requires Arduino 1.0.6 or above)
**BREAKING CHANGES**: ### BREAKING CHANGES :warning:
- `JsonObject::add()` was renamed to `set()` - `JsonObject::add()` was renamed to `set()`
- `JsonArray::at()` and `JsonObject::at()` were renamed to `get()` - `JsonArray::at()` and `JsonObject::at()` were renamed to `get()`
- Number of digits of floating point value are now set with `double_with_n_digits()` - Number of digits of floating point value are now set with `double_with_n_digits()`

View File

@ -1,8 +1,10 @@
[![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)
![ArduinoJson's logo](banner.svg)
ArduinoJson - C++ JSON library for IoT ArduinoJson - C++ JSON library for IoT
==================== ====================
[![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.* *An elegant and efficient JSON library for embedded systems.*
It's designed to have the most intuitive API, the smallest footprint and is able to work without any allocation on the heap (no malloc). It's designed to have the most intuitive API, the smallest footprint and is able to work without any allocation on the heap (no malloc).
@ -27,16 +29,16 @@ Features
Works on Works on
-------- --------
* All Arduino boards (Uno, Due, Mini, Micro, Yun...) * Arduino boards: Uno, Due, Mini, Micro, Yun...
* ESP8266 * ESP8266, ESP32
* Teensy * Teensy
* Intel Edison and Galileo
* PlatformIO
* Energia
* RedBearLab boards (BLE Nano...) * RedBearLab boards (BLE Nano...)
* Computers (Windows, Linux, OSX...) * Intel Edison and Galileo
* WeMos boards: D1...
See [FAQ: Compatibility issues](https://bblanchon.github.io/ArduinoJson/faq/compilation-fails-device-crashes-nothing-on-serial-console) * Computers: Windows, Linux, OSX...
* PlatformIO
* Particle
* Energia
Quick start Quick start
----------- -----------
@ -58,6 +60,8 @@ double longitude = root["data"][1];
[See JsonParserExample.ino](examples/JsonParserExample/JsonParserExample.ino) [See JsonParserExample.ino](examples/JsonParserExample/JsonParserExample.ino)
Use [ArduinoJson Assistant](https://bblanchon.github.io/ArduinoJson/assistant/) to compute the buffer size.
#### Encoding / Generating #### Encoding / Generating
```c++ ```c++
@ -68,8 +72,8 @@ root["sensor"] = "gps";
root["time"] = 1351824120; root["time"] = 1351824120;
JsonArray& data = root.createNestedArray("data"); JsonArray& data = root.createNestedArray("data");
data.add(48.756080, 6); // 6 is the number of decimals to print data.add(48.756080);
data.add(2.302038, 6); // if not specified, 2 digits are printed data.add(2.302038);
root.printTo(Serial); root.printTo(Serial);
// This prints: // This prints:
@ -78,42 +82,17 @@ root.printTo(Serial);
[See JsonGeneratorExample.ino](examples/JsonGeneratorExample/JsonGeneratorExample.ino) [See JsonGeneratorExample.ino](examples/JsonGeneratorExample/JsonGeneratorExample.ino)
Use [ArduinoJson Assistant](https://bblanchon.github.io/ArduinoJson/assistant/) to compute the buffer size.
Documentation Documentation
------------- -------------
The documentation is available online in the [ArduinoJson wiki](https://github.com/bblanchon/ArduinoJson/wiki). The documentation is available online in the [ArduinoJson Website](https://bblanchon.github.io/ArduinoJson/).
The [ArduinoJson Assistant](https://bblanchon.github.io/ArduinoJson/assistant/) helps you get started with the library. The [ArduinoJson Assistant](https://bblanchon.github.io/ArduinoJson/assistant/) helps you get started with the library.
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 have no such problem so far with your library. It is working perfectly with my web services.
From StackOverflow user `thegreendroid`:
> It has a really elegant, simple API and it works like a charm on embedded and Windows/Linux platforms. We recently started using this on an embedded project and I can vouch for its quality.
From GitHub user `zacsketches`:
> Thanks for a great library!!!
> 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.
[From Twitter user `@hemalchevli`](https://twitter.com/hemalchevli/status/715788439397011456):
> ArduinoJson library should be used as a benchmark/reference for making libraries. Truly elegant.
[From GitHub user `sticilface`](https://github.com/bblanchon/ArduinoJson/issues/381#issuecomment-260203594):
> its a great lib:) and i use it in everything!
Donators Donators
-------- --------
@ -136,7 +115,15 @@ Special thanks to the following persons and companies who made generous donation
* Yoeri Kroon <img alt='Netherlands' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1f1.svg' width='18' height='18'> * Yoeri Kroon <img alt='Netherlands' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1f1.svg' width='18' height='18'>
* Andrew Melvin <img alt='United Kingdom' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1ec-1f1e7.svg' width='18' height='18'> * Andrew Melvin <img alt='United Kingdom' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1ec-1f1e7.svg' width='18' height='18'>
* Doanh Luong <img alt ='Vietnam' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fb-1f1f3.svg' width='18' height='18'> * Doanh Luong <img alt ='Vietnam' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fb-1f1f3.svg' width='18' height='18'>
* Christoph Schmidt <img alt ='Germany' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1e9-1f1ea.svg' width='18' height='18'> * Christoph Schmidt <img alt='Germany' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1e9-1f1ea.svg' width='18' height='18'>
* OpenEVSE LLC <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
* Prokhoryatov Alexey <img alt='Russia' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f7-1f1fa.svg' width='18' height='18'>
* Google Inc. <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
* Charles Haynes <img alt='Australia' src='https://d1j8pt39hxlh3d.cloudfront.net/development/emojione/2.2/989/2546.svg' width='18' height='18'>
* Charles Walker <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
* Günther Jehle <img alt='Liechtenstein' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f1-1f1ee.svg' width='18' height='18'>
* Patrick Elliott
--- ---

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#include <ArduinoJson.h> #include <ArduinoJson.h>
@ -17,13 +17,13 @@ void setup() {
// //
// Inside the brackets, 200 is the size of the pool in bytes. // 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. // If the JSON object is more complex, you need to increase that value.
// See https://bblanchon.github.io/ArduinoJson/assistant/
StaticJsonBuffer<200> jsonBuffer; StaticJsonBuffer<200> jsonBuffer;
// StaticJsonBuffer allocates memory on the stack, it can be // StaticJsonBuffer allocates memory on the stack, it can be
// replaced by DynamicJsonBuffer which allocates in the heap. // replaced by DynamicJsonBuffer which allocates in the heap.
// It's simpler but less efficient.
// //
// DynamicJsonBuffer jsonBuffer; // DynamicJsonBuffer jsonBuffer(200);
// Create the root of the object tree. // Create the root of the object tree.
// //
@ -44,8 +44,8 @@ void setup() {
// It's also possible to create the array separately and add it to the // It's also possible to create the array separately and add it to the
// JsonObject but it's less efficient. // JsonObject but it's less efficient.
JsonArray& data = root.createNestedArray("data"); JsonArray& data = root.createNestedArray("data");
data.add(double_with_n_digits(48.756080, 6)); data.add(48.756080);
data.add(double_with_n_digits(2.302038, 6)); data.add(2.302038);
root.printTo(Serial); root.printTo(Serial);
// This prints: // This prints:

View File

@ -5,7 +5,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#include <ArduinoJson.h> #include <ArduinoJson.h>
@ -135,7 +135,7 @@ bool skipResponseHeaders() {
// } // }
bool readReponseContent(struct UserData* userData) { bool readReponseContent(struct UserData* userData) {
// Compute optimal size of the JSON buffer according to what we need to parse. // Compute optimal size of the JSON buffer according to what we need to parse.
// This is only required if you use StaticJsonBuffer. // See https://bblanchon.github.io/ArduinoJson/assistant/
const size_t BUFFER_SIZE = const size_t BUFFER_SIZE =
JSON_OBJECT_SIZE(8) // the root object has 8 elements JSON_OBJECT_SIZE(8) // the root object has 8 elements
+ JSON_OBJECT_SIZE(5) // the "address" object has 5 elements + JSON_OBJECT_SIZE(5) // the "address" object has 5 elements

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#include <ArduinoJson.h> #include <ArduinoJson.h>
@ -17,13 +17,13 @@ void setup() {
// //
// Inside the brackets, 200 is the size of the pool in bytes, // 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. // If the JSON object is more complex, you need to increase that value.
// See https://bblanchon.github.io/ArduinoJson/assistant/
StaticJsonBuffer<200> jsonBuffer; StaticJsonBuffer<200> jsonBuffer;
// StaticJsonBuffer allocates memory on the stack, it can be // StaticJsonBuffer allocates memory on the stack, it can be
// replaced by DynamicJsonBuffer which allocates in the heap. // replaced by DynamicJsonBuffer which allocates in the heap.
// It's simpler but less efficient.
// //
// DynamicJsonBuffer jsonBuffer; // DynamicJsonBuffer jsonBuffer(200);
// JSON input string. // JSON input string.
// //

View File

@ -2,9 +2,9 @@
// Created by Benoit Blanchon. // Created by Benoit Blanchon.
// Heavily inspired by "Web Server" from David A. Mellis and Tom Igoe // Heavily inspired by "Web Server" from David A. Mellis and Tom Igoe
#include <SPI.h>
#include <Ethernet.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <Ethernet.h>
#include <SPI.h>
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 0, 177); IPAddress ip(192, 168, 0, 177);
@ -64,6 +64,8 @@ void loop() {
if (client) { if (client) {
bool success = readRequest(client); bool success = readRequest(client);
if (success) { if (success) {
// Use https://bblanchon.github.io/ArduinoJson/assistant/ to
// compute the right size for the buffer
StaticJsonBuffer<500> jsonBuffer; StaticJsonBuffer<500> jsonBuffer;
JsonObject& json = prepareResponse(jsonBuffer); JsonObject& json = prepareResponse(jsonBuffer);
writeResponse(client, json); writeResponse(client, json);

View File

@ -49,6 +49,8 @@ void setup() {
void loop() { void loop() {
delay(1000); delay(1000);
// Use https://bblanchon.github.io/ArduinoJson/assistant/ to
// compute the right size for the buffer
StaticJsonBuffer<300> jsonBuffer; StaticJsonBuffer<300> jsonBuffer;
JsonObject& json = buildJson(jsonBuffer); JsonObject& json = buildJson(jsonBuffer);
sendJson(json); sendJson(json);

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#include <ArduinoJson.h> #include <ArduinoJson.h>

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#include <ArduinoJson.h> #include <ArduinoJson.h>

View File

@ -1,9 +1,9 @@
name=ArduinoJson name=ArduinoJson
version=5.8.3 version=5.11.2
author=Benoit Blanchon <blog.benoitblanchon.fr> author=Benoit Blanchon <blog.benoitblanchon.fr>
maintainer=Benoit Blanchon <blog.benoitblanchon.fr> maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
sentence=An efficient and elegant JSON library for Arduino. sentence=An efficient and elegant JSON library for Arduino.
paragraph=Like this project? Please star it on GitHub! paragraph=Like this project? Please star it on GitHub!
category=Data Processing category=Data Processing
url=https://github.com/bblanchon/ArduinoJson url=https://bblanchon.github.io/ArduinoJson/
architectures=* architectures=*

View File

@ -2,8 +2,11 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once
#include "ArduinoJson.hpp" #include "ArduinoJson.hpp"
using namespace ArduinoJson; using namespace ArduinoJson;

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -10,7 +10,6 @@
#include "ArduinoJson/DynamicJsonBuffer.hpp" #include "ArduinoJson/DynamicJsonBuffer.hpp"
#include "ArduinoJson/JsonArray.hpp" #include "ArduinoJson/JsonArray.hpp"
#include "ArduinoJson/JsonObject.hpp" #include "ArduinoJson/JsonObject.hpp"
#include "ArduinoJson/JsonVariantComparisons.hpp"
#include "ArduinoJson/StaticJsonBuffer.hpp" #include "ArduinoJson/StaticJsonBuffer.hpp"
#include "ArduinoJson/Deserialization/JsonParserImpl.hpp" #include "ArduinoJson/Deserialization/JsonParserImpl.hpp"
@ -19,5 +18,3 @@
#include "ArduinoJson/JsonObjectImpl.hpp" #include "ArduinoJson/JsonObjectImpl.hpp"
#include "ArduinoJson/JsonVariantImpl.hpp" #include "ArduinoJson/JsonVariantImpl.hpp"
#include "ArduinoJson/Serialization/JsonSerializerImpl.hpp" #include "ArduinoJson/Serialization/JsonSerializerImpl.hpp"
using namespace ArduinoJson;

View File

@ -2,24 +2,28 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
// enable deprecated functions by default // Small or big machine?
#ifndef ARDUINOJSON_ENABLE_DEPRECATED #ifndef ARDUINOJSON_EMBEDDED_MODE
#define ARDUINOJSON_ENABLE_DEPRECATED 1 #if defined(ARDUINO) || defined(__IAR_SYSTEMS_ICC__)
#define ARDUINOJSON_EMBEDDED_MODE 1
#else
#define ARDUINOJSON_EMBEDDED_MODE 0
#endif
#endif #endif
#ifdef ARDUINO // assume this is an embedded platform #if ARDUINOJSON_EMBEDDED_MODE
// store using float instead of double to reduce the memory usage (issue #134) // Store floats by default to reduce the memory usage (issue #134)
#ifndef ARDUINOJSON_USE_DOUBLE #ifndef ARDUINOJSON_USE_DOUBLE
#define ARDUINOJSON_USE_DOUBLE 0 #define ARDUINOJSON_USE_DOUBLE 0
#endif #endif
// store using a long because it usually match the size of a float. // Store longs by default, because they usually match the size of a float.
#ifndef ARDUINOJSON_USE_LONG_LONG #ifndef ARDUINOJSON_USE_LONG_LONG
#define ARDUINOJSON_USE_LONG_LONG 0 #define ARDUINOJSON_USE_LONG_LONG 0
#endif #endif
@ -27,57 +31,29 @@
#define ARDUINOJSON_USE_INT64 0 #define ARDUINOJSON_USE_INT64 0
#endif #endif
// Arduino has its own implementation of String to replace std::string // Embedded systems usually don't have std::string
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
#endif
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
#endif
// On AVR archiecture, we can use PROGMEM
#ifndef ARDUINOJSON_ENABLE_PROGMEM
#ifdef PROGMEM
#define ARDUINOJSON_ENABLE_PROGMEM 1
#else
#define ARDUINOJSON_ENABLE_PROGMEM 0
#endif
#endif
// Arduino doesn't have std::string
#ifndef ARDUINOJSON_ENABLE_STD_STRING #ifndef ARDUINOJSON_ENABLE_STD_STRING
#define ARDUINOJSON_ENABLE_STD_STRING 0 #define ARDUINOJSON_ENABLE_STD_STRING 0
#endif #endif
// Arduino doesn't support STL stream // Embedded systems usually don't have std::stream
#ifndef ARDUINOJSON_ENABLE_STD_STREAM #ifndef ARDUINOJSON_ENABLE_STD_STREAM
#define ARDUINOJSON_ENABLE_STD_STREAM 0 #define ARDUINOJSON_ENABLE_STD_STREAM 0
#endif #endif
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT // Limit nesting as the stack is likely to be small
#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
// low value to prevent stack overflow
#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT #ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10 #define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
#endif #endif
#else // assume this is a computer #else // ARDUINOJSON_EMBEDDED_MODE
// on a computer we have plenty of memory so we can use doubles // On a computer we have plenty of memory so we can use doubles
#ifndef ARDUINOJSON_USE_DOUBLE #ifndef ARDUINOJSON_USE_DOUBLE
#define ARDUINOJSON_USE_DOUBLE 1 #define ARDUINOJSON_USE_DOUBLE 1
#endif #endif
// use long long when available // Use long long when available
#ifndef ARDUINOJSON_USE_LONG_LONG #ifndef ARDUINOJSON_USE_LONG_LONG
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
#define ARDUINOJSON_USE_LONG_LONG 1 #define ARDUINOJSON_USE_LONG_LONG 1
@ -86,7 +62,7 @@
#endif #endif
#endif #endif
// use _int64 on old versions of Visual Studio // Use _int64 on old versions of Visual Studio
#ifndef ARDUINOJSON_USE_INT64 #ifndef ARDUINOJSON_USE_INT64
#if defined(_MSC_VER) && _MSC_VER <= 1700 #if defined(_MSC_VER) && _MSC_VER <= 1700
#define ARDUINOJSON_USE_INT64 1 #define ARDUINOJSON_USE_INT64 1
@ -95,41 +71,81 @@
#endif #endif
#endif #endif
// on a computer, we can use std::string // On a computer, we can use std::string
#ifndef ARDUINOJSON_ENABLE_STD_STRING #ifndef ARDUINOJSON_ENABLE_STD_STRING
#define ARDUINOJSON_ENABLE_STD_STRING 1 #define ARDUINOJSON_ENABLE_STD_STRING 1
#endif #endif
// on a computer, there is no reason to beleive Arduino String is available // On a computer, we can assume std::stream
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
#endif
// PROGMEM is only available on AVR architecture
#ifndef ARDUINOJSON_ENABLE_PROGMEM
#define ARDUINOJSON_ENABLE_PROGMEM 0
#endif
// on a computer, we can assume that the STL is there
#ifndef ARDUINOJSON_ENABLE_STD_STREAM #ifndef ARDUINOJSON_ENABLE_STD_STREAM
#define ARDUINOJSON_ENABLE_STD_STREAM 1 #define ARDUINOJSON_ENABLE_STD_STREAM 1
#endif #endif
// on a computer, there is no reason to beleive Arduino Stream is available // On a computer, the stack is large so we can increase nesting limit
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
#endif
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
// even if not required, most cpu's are faster with aligned pointers
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
#endif
// on a computer, we should have a lot of space on the stack
#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT #ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50 #define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50
#endif #endif
#endif // ARDUINOJSON_EMBEDDED_MODE
#ifdef ARDUINO
// Enable support for Arduino String
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
#endif
// Enable support for Arduino Stream
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
#endif
#else // ARDUINO
// Disable support for Arduino String
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
#endif
// Disable support for Arduino Stream
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
#endif
#endif // ARDUINO
#ifndef ARDUINOJSON_ENABLE_PROGMEM
#ifdef PROGMEM
#define ARDUINOJSON_ENABLE_PROGMEM 1
#else
#define ARDUINOJSON_ENABLE_PROGMEM 0
#endif
#endif
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
#ifdef ARDUINO_ARCH_AVR
// alignment isn't needed for 8-bit AVR
#define ARDUINOJSON_ENABLE_ALIGNMENT 0
#else
// but most processors need pointers to be align on word size
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
#endif
#endif
// Enable deprecated functions by default
#ifndef ARDUINOJSON_ENABLE_DEPRECATED
#define ARDUINOJSON_ENABLE_DEPRECATED 1
#endif
// Control the exponentiation threshold for big numbers
// CAUTION: cannot be more that 1e9 !!!!
#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD
#define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7
#endif
// Control the exponentiation threshold for small numbers
#ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD
#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
#endif #endif
#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64 #if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64

View File

@ -2,13 +2,11 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#include "../Print.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -19,7 +19,7 @@ class JsonBufferAllocated {
return jsonBuffer->alloc(n); return jsonBuffer->alloc(n);
} }
void operator delete(void *, JsonBuffer *)throw() {} void operator delete(void *, JsonBuffer *)throw();
}; };
} }
} }

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -20,20 +20,11 @@ enum JsonVariantType {
JSON_UNPARSED, // JsonVariant contains an unparsed string JSON_UNPARSED, // JsonVariant contains an unparsed string
JSON_STRING, // JsonVariant stores a const char* JSON_STRING, // JsonVariant stores a const char*
JSON_BOOLEAN, // JsonVariant stores a bool JSON_BOOLEAN, // JsonVariant stores a bool
JSON_POSITIVE_INTEGER, // JsonVariant stores an unsigned long JSON_POSITIVE_INTEGER, // JsonVariant stores an JsonUInt
JSON_NEGATIVE_INTEGER, // JsonVariant stores an unsigned long that must be JSON_NEGATIVE_INTEGER, // JsonVariant stores an JsonUInt that must be negated
// negated
JSON_ARRAY, // JsonVariant stores a pointer to a JsonArray JSON_ARRAY, // JsonVariant stores a pointer to a JsonArray
JSON_OBJECT, // JsonVariant stores a pointer to a JsonObject JSON_OBJECT, // JsonVariant stores a pointer to a JsonObject
JSON_FLOAT // JsonVariant stores a JsonFloat
// 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_FLOAT_0_DECIMALS
// JSON_FLOAT_1_DECIMAL
// JSON_FLOAT_2_DECIMALS
// ...
}; };
} }
} }

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -48,6 +48,20 @@ class List {
return nodeCount; return nodeCount;
} }
iterator add() {
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 iterator(newNode);
}
iterator begin() { iterator begin() {
return iterator(_firstNode); return iterator(_firstNode);
} }
@ -62,22 +76,8 @@ class List {
return const_iterator(NULL); return const_iterator(NULL);
} }
protected: void remove(iterator it) {
node_type *addNewNode() { node_type *nodeToRemove = it._node;
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;
}
void removeNode(node_type *nodeToRemove) {
if (!nodeToRemove) return; if (!nodeToRemove) return;
if (nodeToRemove == _firstNode) { if (nodeToRemove == _firstNode) {
_firstNode = nodeToRemove->next; _firstNode = nodeToRemove->next;
@ -87,7 +87,10 @@ class List {
} }
} }
protected:
JsonBuffer *_buffer; JsonBuffer *_buffer;
private:
node_type *_firstNode; node_type *_firstNode;
}; };
} }

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -38,6 +38,14 @@ class ListConstIterator {
return *this; return *this;
} }
ListConstIterator<T> &operator+=(size_t distance) {
while (_node && distance) {
_node = _node->next;
--distance;
}
return *this;
}
private: private:
const ListNode<T> *_node; const ListNode<T> *_node;
}; };

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -13,9 +13,14 @@
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
template <typename T>
class List;
// A read-write forward iterator for List<T> // A read-write forward iterator for List<T>
template <typename T> template <typename T>
class ListIterator { class ListIterator {
friend class List<T>;
public: public:
explicit ListIterator(ListNode<T> *node = NULL) : _node(node) {} explicit ListIterator(ListNode<T> *node = NULL) : _node(node) {}
@ -39,6 +44,14 @@ class ListIterator {
return *this; return *this;
} }
ListIterator<T> &operator+=(size_t distance) {
while (_node && distance) {
_node = _node->next;
--distance;
}
return *this;
}
operator ListConstIterator<T>() const { operator ListConstIterator<T>() const {
return ListConstIterator<T>(_node); return ListConstIterator<T>(_node);
} }

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -18,7 +18,7 @@ namespace Internals {
// Used by List<T> and its iterators. // Used by List<T> and its iterators.
template <typename T> template <typename T>
struct ListNode : public Internals::JsonBufferAllocated { struct ListNode : public Internals::JsonBufferAllocated {
ListNode() : next(NULL) {} ListNode() throw() : next(NULL) {}
ListNode<T> *next; ListNode<T> *next;
T content; T content;

View File

@ -0,0 +1,26 @@
// Copyright Benoit Blanchon 2014-2017
// MIT License
//
// Arduino JSON library
// https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star!
#pragma once
namespace ArduinoJson {
namespace Internals {
// A type that cannot be copied
class NonCopyable {
protected:
NonCopyable() {}
private:
// copy constructor is private
NonCopyable(const NonCopyable&);
// copy operator is private
NonCopyable& operator=(const NonCopyable&);
};
}
}

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -22,16 +22,6 @@ class ReferenceType {
bool operator!=(const ReferenceType& other) const { bool operator!=(const ReferenceType& other) const {
return this != &other; return this != &other;
} }
protected:
ReferenceType() {}
private:
// copy constructor is private
ReferenceType(const ReferenceType&);
// copy operator is private
ReferenceType& operator=(const ReferenceType&);
}; };
} }
} }

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -15,22 +15,21 @@
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
template <typename TSource, typename Enable = void> template <typename TSourceRef, typename Enable = void>
struct ValueSetter { struct ValueSetter {
template <typename TDestination> template <typename TDestination>
static bool set(JsonBuffer*, TDestination& destination, static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) {
const TSource& source) {
destination = source; destination = source;
return true; return true;
} }
}; };
template <typename TSource> template <typename TSourceRef>
struct ValueSetter<TSource, typename TypeTraits::EnableIf<StringTraits< struct ValueSetter<TSourceRef, typename TypeTraits::EnableIf<StringTraits<
TSource>::should_duplicate>::type> { TSourceRef>::should_duplicate>::type> {
template <typename TDestination> template <typename TDestination>
static bool set(JsonBuffer* buffer, TDestination& destination, static bool set(JsonBuffer* buffer, TDestination& destination,
const TSource& source) { TSourceRef source) {
const char* copy = buffer->strdup(source); const char* copy = buffer->strdup(source);
if (!copy) return false; if (!copy) return false;
destination = copy; destination = copy;
@ -38,12 +37,11 @@ struct ValueSetter<TSource, typename TypeTraits::EnableIf<StringTraits<
} }
}; };
template <typename TSource> template <typename TSourceRef>
struct ValueSetter<TSource, typename TypeTraits::EnableIf<!StringTraits< struct ValueSetter<TSourceRef, typename TypeTraits::EnableIf<!StringTraits<
TSource>::should_duplicate>::type> { TSourceRef>::should_duplicate>::type> {
template <typename TDestination> template <typename TDestination>
static bool set(JsonBuffer*, TDestination& destination, static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) {
const TSource& source) {
// unsigned char* -> char* // unsigned char* -> char*
destination = reinterpret_cast<const char*>(source); destination = reinterpret_cast<const char*>(source);
return true; return true;

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -20,9 +20,8 @@ inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::eat(
} }
template <typename TReader, typename TWriter> template <typename TReader, typename TWriter>
inline bool inline bool ArduinoJson::Internals::JsonParser<
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseAnythingTo( TReader, TWriter>::parseAnythingTo(JsonVariant *destination) {
JsonVariant *destination) {
if (_nestingLimit == 0) return false; if (_nestingLimit == 0) return false;
_nestingLimit--; _nestingLimit--;
bool success = parseAnythingToUnsafe(destination); bool success = parseAnythingToUnsafe(destination);
@ -31,9 +30,8 @@ ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseAnythingTo(
} }
template <typename TReader, typename TWriter> template <typename TReader, typename TWriter>
inline bool inline bool ArduinoJson::Internals::JsonParser<
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseAnythingToUnsafe( TReader, TWriter>::parseAnythingToUnsafe(JsonVariant *destination) {
JsonVariant *destination) {
skipSpacesAndComments(_reader); skipSpacesAndComments(_reader);
switch (_reader.current()) { switch (_reader.current()) {

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -17,8 +17,8 @@ class StringWriter {
public: public:
String(TChar** ptr) : _writePtr(ptr), _startPtr(*ptr) {} String(TChar** ptr) : _writePtr(ptr), _startPtr(*ptr) {}
void append(TChar c) { void append(char c) {
*(*_writePtr)++ = c; *(*_writePtr)++ = TChar(c);
} }
const char* c_str() const { const char* c_str() const {

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -46,30 +46,41 @@ class DynamicJsonBufferBase
}; };
public: public:
enum { EmptyBlockSize = sizeof(EmptyBlock) };
DynamicJsonBufferBase(size_t initialSize = 256) DynamicJsonBufferBase(size_t initialSize = 256)
: _head(NULL), _nextBlockCapacity(initialSize) {} : _head(NULL), _nextBlockCapacity(initialSize) {}
~DynamicJsonBufferBase() { ~DynamicJsonBufferBase() {
Block* currentBlock = _head; clear();
while (currentBlock != NULL) {
Block* nextBlock = currentBlock->next;
_allocator.deallocate(currentBlock);
currentBlock = nextBlock;
}
} }
// Gets the number of bytes occupied in the buffer
size_t size() const { size_t size() const {
size_t total = 0; size_t total = 0;
for (const Block* b = _head; b; b = b->next) total += b->size; for (const Block* b = _head; b; b = b->next) total += b->size;
return total; return total;
} }
// Allocates the specified amount of bytes in the buffer
virtual void* alloc(size_t bytes) { virtual void* alloc(size_t bytes) {
alignNextAlloc(); alignNextAlloc();
return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes); return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
} }
// Resets the buffer.
// USE WITH CAUTION: this invalidates all previously allocated data
void clear() {
Block* currentBlock = _head;
while (currentBlock != NULL) {
_nextBlockCapacity = currentBlock->capacity;
Block* nextBlock = currentBlock->next;
_allocator.deallocate(currentBlock);
currentBlock = nextBlock;
}
_head = 0;
}
class String { class String {
public: public:
String(DynamicJsonBufferBase* parent) String(DynamicJsonBufferBase* parent)
@ -98,7 +109,7 @@ class DynamicJsonBufferBase
private: private:
DynamicJsonBufferBase* _parent; DynamicJsonBufferBase* _parent;
char* _start; char* _start;
int _length; size_t _length;
}; };
String startString() { String startString() {
@ -129,7 +140,7 @@ class DynamicJsonBufferBase
} }
bool addNewBlock(size_t capacity) { bool addNewBlock(size_t capacity) {
size_t bytes = sizeof(EmptyBlock) + capacity; size_t bytes = EmptyBlockSize + capacity;
Block* block = static_cast<Block*>(_allocator.allocate(bytes)); Block* block = static_cast<Block*>(_allocator.allocate(bytes));
if (block == NULL) return false; if (block == NULL) return false;
block->capacity = capacity; block->capacity = capacity;

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -39,13 +39,14 @@ class JsonArraySubscript;
// It can also be deserialized from a JSON string via JsonBuffer::parseArray(). // It can also be deserialized from a JSON string via JsonBuffer::parseArray().
class JsonArray : public Internals::JsonPrintable<JsonArray>, class JsonArray : public Internals::JsonPrintable<JsonArray>,
public Internals::ReferenceType, public Internals::ReferenceType,
public Internals::NonCopyable,
public Internals::List<JsonVariant>, public Internals::List<JsonVariant>,
public Internals::JsonBufferAllocated { public Internals::JsonBufferAllocated {
public: public:
// Create an empty JsonArray attached to the specified JsonBuffer. // Create an empty JsonArray attached to the specified JsonBuffer.
// You should not call this constructor directly. // You should not call this constructor directly.
// Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray(). // Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray().
explicit JsonArray(JsonBuffer *buffer) explicit JsonArray(JsonBuffer *buffer) throw()
: Internals::List<JsonVariant>(buffer) {} : Internals::List<JsonVariant>(buffer) {}
// Gets the value at the specified index // Gets the value at the specified index
@ -76,8 +77,9 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
// bool add(TValue value, uint8_t decimals); // bool add(TValue value, uint8_t decimals);
// TValue = float, double // TValue = float, double
template <typename T> template <typename T>
bool add(T value, uint8_t decimals) { DEPRECATED("Second argument is not supported anymore")
return add_impl<const JsonVariant &>(JsonVariant(value, decimals)); bool add(T value, uint8_t) {
return add_impl<const JsonVariant &>(JsonVariant(value));
} }
// Sets the value at specified index. // Sets the value at specified index.
@ -111,16 +113,15 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
// Gets the value at the specified index. // Gets the value at the specified index.
template <typename T> template <typename T>
typename Internals::JsonVariantAs<T>::type get(size_t index) const { typename Internals::JsonVariantAs<T>::type get(size_t index) const {
node_type *node = findNode(index); const_iterator it = begin() += index;
return node ? node->content.as<T>() return it != end() ? it->as<T>() : Internals::JsonVariantDefault<T>::get();
: Internals::JsonVariantDefault<T>::get();
} }
// Check the type of the value at specified index. // Check the type of the value at specified index.
template <typename T> template <typename T>
bool is(size_t index) const { bool is(size_t index) const {
node_type *node = findNode(index); const_iterator it = begin() += index;
return node ? node->content.is<T>() : false; return it != end() ? it->is<T>() : false;
} }
// Creates a JsonArray and adds a reference at the end of the array. // Creates a JsonArray and adds a reference at the end of the array.
@ -132,9 +133,10 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
JsonObject &createNestedObject(); JsonObject &createNestedObject();
// Removes element at specified index. // Removes element at specified index.
void removeAt(size_t index) { void remove(size_t index) {
removeNode(findNode(index)); remove(begin() += index);
} }
using Internals::List<JsonVariant>::remove;
// Returns a reference an invalid JsonArray. // Returns a reference an invalid JsonArray.
// This object is meant to replace a NULL pointer. // This object is meant to replace a NULL pointer.
@ -197,29 +199,26 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
} }
} }
private: #if ARDUINOJSON_ENABLE_DEPRECATED
node_type *findNode(size_t index) const { DEPRECATED("use remove() instead")
node_type *node = _firstNode; FORCE_INLINE void removeAt(size_t index) {
while (node && index--) node = node->next; return remove(index);
return node;
} }
#endif
private:
template <typename TValueRef> template <typename TValueRef>
bool set_impl(size_t index, TValueRef value) { bool set_impl(size_t index, TValueRef value) {
node_type *node = findNode(index); iterator it = begin() += index;
if (!node) return false; if (it == end()) return false;
return Internals::ValueSetter<TValueRef>::set(_buffer, *it, value);
return Internals::ValueSetter<TValueRef>::set(_buffer, node->content,
value);
} }
template <typename TValueRef> template <typename TValueRef>
bool add_impl(TValueRef value) { bool add_impl(TValueRef value) {
node_type *node = addNewNode(); iterator it = Internals::List<JsonVariant>::add();
if (!node) return false; if (it == end()) return false;
return Internals::ValueSetter<TValueRef>::set(_buffer, *it, value);
return Internals::ValueSetter<TValueRef>::set(_buffer, node->content,
value);
} }
}; };

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -81,8 +81,9 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
// bool set(TValue, uint8_t decimals); // bool set(TValue, uint8_t decimals);
// TValue = float, double // TValue = float, double
template <typename TValue> template <typename TValue>
FORCE_INLINE bool set(const TValue& value, uint8_t decimals) { DEPRECATED("Second argument is not supported anymore")
return _array.set(_index, value, decimals); FORCE_INLINE bool set(const TValue& value, uint8_t) {
return _array.set(_index, value);
} }
private: private:
@ -105,15 +106,16 @@ inline const JsonArraySubscript JsonArray::operator[](size_t index) const {
return JsonArraySubscript(*const_cast<JsonArray*>(this), index); return JsonArraySubscript(*const_cast<JsonArray*>(this), index);
} }
template <typename TImplem> template <typename TImpl>
inline JsonArraySubscript JsonVariantBase<TImplem>::operator[](int index) { inline JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
return as<JsonArray>()[index]; size_t index) {
return impl()->template as<JsonArray>()[index];
} }
template <typename TImplem> template <typename TImpl>
inline const JsonArraySubscript JsonVariantBase<TImplem>::operator[]( inline const JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
int index) const { size_t index) const {
return as<JsonArray>()[index]; return impl()->template as<JsonArray>()[index];
} }
} // namespace ArduinoJson } // namespace ArduinoJson

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -11,20 +11,11 @@
#include <stdint.h> // for uint8_t #include <stdint.h> // for uint8_t
#include <string.h> #include <string.h>
#include "Data/NonCopyable.hpp"
#include "JsonVariant.hpp" #include "JsonVariant.hpp"
#include "TypeTraits/EnableIf.hpp" #include "TypeTraits/EnableIf.hpp"
#include "TypeTraits/IsArray.hpp" #include "TypeTraits/IsArray.hpp"
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
namespace ArduinoJson { namespace ArduinoJson {
class JsonArray; class JsonArray;
class JsonObject; class JsonObject;
@ -34,13 +25,8 @@ class JsonObject;
// Handle the memory management (done in derived classes) and calls the parser. // Handle the memory management (done in derived classes) and calls the parser.
// This abstract class is implemented by StaticJsonBuffer which implements a // This abstract class is implemented by StaticJsonBuffer which implements a
// fixed memory allocation. // fixed memory allocation.
class JsonBuffer { class JsonBuffer : Internals::NonCopyable {
public: public:
// CAUTION: NO VIRTUAL DESTRUCTOR!
// If we add a virtual constructor the Arduino compiler will add malloc() and
// free() to the binary, adding 706 useless bytes.
// virtual ~JsonBuffer() {}
// Allocates an empty JsonArray. // Allocates an empty JsonArray.
// //
// Returns a reference to the new JsonArray or JsonArray::invalid() if the // Returns a reference to the new JsonArray or JsonArray::invalid() if the
@ -76,6 +62,11 @@ class JsonBuffer {
virtual void *alloc(size_t size) = 0; virtual void *alloc(size_t size) = 0;
protected: protected:
// CAUTION: NO VIRTUAL DESTRUCTOR!
// If we add a virtual constructor the Arduino compiler will add malloc()
// and free() to the binary, adding 706 useless bytes.
~JsonBuffer() {}
// Preserve aligment if necessary // Preserve aligment if necessary
static FORCE_INLINE size_t round_size_up(size_t bytes) { static FORCE_INLINE size_t round_size_up(size_t bytes) {
#if ARDUINOJSON_ENABLE_ALIGNMENT #if ARDUINOJSON_ENABLE_ALIGNMENT
@ -87,11 +78,3 @@ class JsonBuffer {
} }
}; };
} }
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop
#endif
#endif

View File

@ -2,23 +2,13 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#include "Deserialization/JsonParser.hpp" #include "Deserialization/JsonParser.hpp"
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
namespace ArduinoJson { namespace ArduinoJson {
template <typename TDerived> template <typename TDerived>
class JsonBufferBase : public JsonBuffer { class JsonBufferBase : public JsonBuffer {
@ -127,17 +117,12 @@ class JsonBufferBase : public JsonBuffer {
return Internals::makeParser(that(), json, nestingLimit).parseVariant(); return Internals::makeParser(that(), json, nestingLimit).parseVariant();
} }
protected:
~JsonBufferBase() {}
private: private:
TDerived *that() { TDerived *that() {
return static_cast<TDerived *>(this); return static_cast<TDerived *>(this);
} }
}; };
} }
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop
#endif
#endif

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -38,13 +38,15 @@ class JsonBuffer;
// It can also be deserialized from a JSON string via JsonBuffer::parseObject(). // It can also be deserialized from a JSON string via JsonBuffer::parseObject().
class JsonObject : public Internals::JsonPrintable<JsonObject>, class JsonObject : public Internals::JsonPrintable<JsonObject>,
public Internals::ReferenceType, public Internals::ReferenceType,
public Internals::NonCopyable,
public Internals::List<JsonPair>, public Internals::List<JsonPair>,
public Internals::JsonBufferAllocated { public Internals::JsonBufferAllocated {
public: public:
// Create an empty JsonArray attached to the specified JsonBuffer. // Create an empty JsonArray attached to the specified JsonBuffer.
// You should not use this constructor directly. // You should not use this constructor directly.
// Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject(). // Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject().
explicit JsonObject(JsonBuffer* buffer) : Internals::List<JsonPair>(buffer) {} explicit JsonObject(JsonBuffer* buffer) throw()
: Internals::List<JsonPair>(buffer) {}
// Gets or sets the value associated with the specified key. // Gets or sets the value associated with the specified key.
// //
@ -134,23 +136,25 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
// TKey = const std::string&, const String& // TKey = const std::string&, const String&
// TValue = float, double // TValue = float, double
template <typename TValue, typename TString> template <typename TValue, typename TString>
DEPRECATED("Second argument is not supported anymore")
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value && typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value &&
!TypeTraits::IsArray<TString>::value, !TypeTraits::IsArray<TString>::value,
bool>::type bool>::type
set(const TString& key, TValue value, uint8_t decimals) { set(const TString& key, TValue value, uint8_t) {
return set_impl<const TString&, const JsonVariant&>( return set_impl<const TString&, const JsonVariant&>(key,
key, JsonVariant(value, decimals)); JsonVariant(value));
} }
// //
// bool set(TKey, TValue, uint8_t decimals); // bool set(TKey, TValue, uint8_t decimals);
// TKey = const char*, const char[N], const FlashStringHelper* // TKey = const char*, const char[N], const FlashStringHelper*
// TValue = float, double // TValue = float, double
template <typename TValue, typename TString> template <typename TValue, typename TString>
DEPRECATED("Second argument is not supported anymore")
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value, typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value,
bool>::type bool>::type
set(const TString* key, TValue value, uint8_t decimals) { set(const TString* key, TValue value, uint8_t) {
return set_impl<const TString*, const JsonVariant&>( return set_impl<const TString*, const JsonVariant&>(key,
key, JsonVariant(value, decimals)); JsonVariant(value));
} }
// Gets the value associated with the specified key. // Gets the value associated with the specified key.
@ -247,14 +251,14 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
bool>::type bool>::type
containsKey(const TString& key) const { containsKey(const TString& key) const {
return findNode<const TString&>(key) != NULL; return findKey<const TString&>(key) != end();
} }
// //
// bool containsKey(TKey); // bool containsKey(TKey);
// TKey = const char*, const char[N], const FlashStringHelper* // TKey = const char*, const char[N], const FlashStringHelper*
template <typename TString> template <typename TString>
bool containsKey(const TString* key) const { bool containsKey(const TString* key) const {
return findNode<const TString*>(key) != NULL; return findKey<const TString*>(key) != end();
} }
// Removes the specified key and the associated value. // Removes the specified key and the associated value.
@ -265,15 +269,18 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
void>::type void>::type
remove(const TString& key) { remove(const TString& key) {
removeNode(findNode<const TString&>(key)); remove(findKey<const TString&>(key));
} }
// //
// void remove(TKey); // void remove(TKey);
// TKey = const char*, const char[N], const FlashStringHelper* // TKey = const char*, const char[N], const FlashStringHelper*
template <typename TString> template <typename TString>
void remove(const TString* key) { void remove(const TString* key) {
removeNode(findNode<const TString*>(key)); remove(findKey<const TString*>(key));
} }
//
// void remove(iterator)
using Internals::List<JsonPair>::remove;
// Returns a reference an invalid JsonObject. // Returns a reference an invalid JsonObject.
// This object is meant to replace a NULL pointer. // This object is meant to replace a NULL pointer.
@ -286,41 +293,44 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
private: private:
// Returns the list node that matches the specified key. // Returns the list node that matches the specified key.
template <typename TStringRef> template <typename TStringRef>
node_type* findNode(TStringRef key) const { iterator findKey(TStringRef key) {
for (node_type* node = _firstNode; node; node = node->next) { iterator it;
if (Internals::StringTraits<TStringRef>::equals(key, node->content.key)) for (it = begin(); it != end(); ++it) {
return node; if (Internals::StringTraits<TStringRef>::equals(key, it->key)) break;
} }
return NULL; return it;
}
template <typename TStringRef>
const_iterator findKey(TStringRef key) const {
return const_cast<JsonObject*>(this)->findKey<TStringRef>(key);
} }
template <typename TStringRef, typename TValue> template <typename TStringRef, typename TValue>
typename Internals::JsonVariantAs<TValue>::type get_impl( typename Internals::JsonVariantAs<TValue>::type get_impl(
TStringRef key) const { TStringRef key) const {
node_type* node = findNode<TStringRef>(key); const_iterator it = findKey<TStringRef>(key);
return node ? node->content.value.as<TValue>() return it != end() ? it->value.as<TValue>()
: Internals::JsonVariantDefault<TValue>::get(); : Internals::JsonVariantDefault<TValue>::get();
} }
template <typename TStringRef, typename TValueRef> template <typename TStringRef, typename TValueRef>
bool set_impl(TStringRef key, TValueRef value) { bool set_impl(TStringRef key, TValueRef value) {
node_type* node = findNode<TStringRef>(key); iterator it = findKey<TStringRef>(key);
if (!node) { if (it == end()) {
node = addNewNode(); it = Internals::List<JsonPair>::add();
if (!node) return false; if (it == end()) return false;
bool key_ok = Internals::ValueSetter<TStringRef>::set( bool key_ok =
_buffer, node->content.key, key); Internals::ValueSetter<TStringRef>::set(_buffer, it->key, key);
if (!key_ok) return false; if (!key_ok) return false;
} }
return Internals::ValueSetter<TValueRef>::set(_buffer, node->content.value, return Internals::ValueSetter<TValueRef>::set(_buffer, it->value, value);
value);
} }
template <typename TStringRef, typename TValue> template <typename TStringRef, typename TValue>
bool is_impl(TStringRef key) const { bool is_impl(TStringRef key) const {
node_type* node = findNode<TStringRef>(key); const_iterator it = findKey<TStringRef>(key);
return node ? node->content.value.is<TValue>() : false; return it != end() ? it->value.is<TValue>() : false;
} }
template <typename TStringRef> template <typename TStringRef>

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -93,8 +93,9 @@ class JsonObjectSubscript
// bool set(TValue, uint8_t decimals); // bool set(TValue, uint8_t decimals);
// TValue = float, double // TValue = float, double
template <typename TValue> template <typename TValue>
FORCE_INLINE bool set(const TValue& value, uint8_t decimals) { DEPRECATED("Second argument is not supported anymore")
return _object.set(_key, value, decimals); FORCE_INLINE bool set(const TValue& value, uint8_t) {
return _object.set(_key, value);
} }
private: private:

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -40,8 +40,8 @@ class JsonObject;
// - a string (const char*) // - a string (const char*)
// - a reference to a JsonArray or JsonObject // - a reference to a JsonArray or JsonObject
class JsonVariant : public JsonVariantBase<JsonVariant> { class JsonVariant : public JsonVariantBase<JsonVariant> {
friend void Internals::JsonSerializer::serialize(const JsonVariant &, template <typename Print>
JsonWriter &); friend class Internals::JsonSerializer;
public: public:
// Creates an uninitialized JsonVariant // Creates an uninitialized JsonVariant
@ -52,31 +52,39 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
JsonVariant(bool value) { JsonVariant(bool value) {
using namespace Internals; using namespace Internals;
_type = JSON_BOOLEAN; _type = JSON_BOOLEAN;
_content.asInteger = static_cast<JsonInteger>(value); _content.asInteger = static_cast<JsonUInt>(value);
} }
// Create a JsonVariant containing a floating point value. // Create a JsonVariant containing a floating point value.
// The second argument specifies the number of decimal digits to write in // JsonVariant(double value);
// the JSON string. // JsonVariant(float value);
// JsonVariant(double value, uint8_t decimals);
// JsonVariant(float value, uint8_t decimals);
template <typename T> template <typename T>
JsonVariant(T value, uint8_t decimals = 2, JsonVariant(T value, typename TypeTraits::EnableIf<
TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
using namespace Internals;
_type = JSON_FLOAT;
_content.asFloat = static_cast<JsonFloat>(value);
}
template <typename T>
DEPRECATED("Second argument is not supported anymore")
JsonVariant(T value, uint8_t,
typename TypeTraits::EnableIf< typename TypeTraits::EnableIf<
TypeTraits::IsFloatingPoint<T>::value>::type * = 0) { TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
using namespace Internals; using namespace Internals;
_type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals); _type = JSON_FLOAT;
_content.asFloat = static_cast<JsonFloat>(value); _content.asFloat = static_cast<JsonFloat>(value);
} }
// Create a JsonVariant containing an integer value. // Create a JsonVariant containing an integer value.
// JsonVariant(char)
// JsonVariant(signed short) // JsonVariant(signed short)
// JsonVariant(signed int) // JsonVariant(signed int)
// JsonVariant(signed long) // JsonVariant(signed long)
// JsonVariant(signed char)
template <typename T> template <typename T>
JsonVariant(T value, JsonVariant(T value, typename TypeTraits::EnableIf<
typename TypeTraits::EnableIf< TypeTraits::IsSignedIntegral<T>::value ||
TypeTraits::IsSignedIntegral<T>::value>::type * = 0) { TypeTraits::IsSame<T, char>::value>::type * = 0) {
using namespace Internals; using namespace Internals;
if (value >= 0) { if (value >= 0) {
_type = JSON_POSITIVE_INTEGER; _type = JSON_POSITIVE_INTEGER;
@ -129,24 +137,26 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
// Get the variant as the specified type. // Get the variant as the specified type.
// //
// short as<signed short>() const; // char as<char>() const;
// int as<signed int>() const; // signed char as<signed char>() const;
// long as<signed long>() const; // signed short as<signed short>() const;
// signed int as<signed int>() const;
// signed long as<signed long>() const;
// unsigned char as<unsigned char>() const;
// unsigned short as<unsigned short>() const;
// unsigned int as<unsigned int>() const;
// unsigned long as<unsigned long>() const;
template <typename T> template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsSignedIntegral<T>::value, const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value, T>::type
T>::type
as() const { as() const {
return static_cast<T>(variantAsInteger()); return variantAsInteger<T>();
} }
// // bool as<bool>() const
// short as<unsigned short>() const;
// int as<unsigned int>() const;
// long as<unsigned long>() const;
template <typename T> template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsUnsignedIntegral<T>::value, const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
T>::type T>::type
as() const { as() const {
return static_cast<T>(asUnsignedInteger()); return variantAsInteger<int>() != 0;
} }
// //
// double as<double>() const; // double as<double>() const;
@ -155,7 +165,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value, const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
T>::type T>::type
as() const { as() const {
return static_cast<T>(variantAsFloat()); return variantAsFloat<T>();
} }
// //
// const char* as<const char*>() const; // const char* as<const char*>() const;
@ -180,14 +190,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
return s; return s;
} }
// //
// const bool as<bool>() const
template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
T>::type
as() const {
return variantAsInteger() != 0;
}
//
// JsonArray& as<JsonArray> const; // JsonArray& as<JsonArray> const;
// JsonArray& as<JsonArray&> const; // JsonArray& as<JsonArray&> const;
template <typename T> template <typename T>
@ -242,32 +244,35 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
// Tells weither the variant has the specified type. // Tells weither the variant has the specified type.
// Returns true if the variant has type type T, false otherwise. // Returns true if the variant has type type T, false otherwise.
// //
// short as<short>() const; // bool is<char>() const;
// int as<int>() const; // bool is<signed char>() const;
// long as<long>() const; // bool is<signed short>() const;
// bool is<signed int>() const;
// bool is<signed long>() const;
// bool is<unsigned char>() const;
// bool is<unsigned short>() const;
// bool is<unsigned int>() const;
// bool is<unsigned long>() const;
template <typename T> template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value && typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value, bool>::type
!TypeTraits::IsSame<T, bool>::value,
bool>::type
is() const { is() const {
return isInteger(); return variantIsInteger();
} }
// //
// double is<double>() const; // bool is<double>() const;
// float is<float>() const; // bool is<float>() const;
template <typename T> template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value, typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
bool>::type bool>::type
is() const { is() const {
return isFloat(); return variantIsFloat();
} }
// //
// const bool is<bool>() const // bool is<bool>() const
template <typename T> template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value, typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value, bool>::type
bool>::type
is() const { is() const {
return isBoolean(); return variantIsBoolean();
} }
// //
// bool is<const char*>() const; // bool is<const char*>() const;
@ -277,7 +282,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
TypeTraits::IsSame<T, char *>::value, TypeTraits::IsSame<T, char *>::value,
bool>::type bool>::type
is() const { is() const {
return isString(); return variantIsString();
} }
// //
// bool is<JsonArray> const; // bool is<JsonArray> const;
@ -291,7 +296,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
JsonArray>::value, JsonArray>::value,
bool>::type bool>::type
is() const { is() const {
return isArray(); return variantIsArray();
} }
// //
// bool is<JsonObject> const; // bool is<JsonObject> const;
@ -305,7 +310,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
JsonObject>::value, JsonObject>::value,
bool>::type bool>::type
is() const { is() const {
return isObject(); return variantIsObject();
} }
// Returns true if the variant has a value // Returns true if the variant has a value
@ -314,27 +319,23 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
} }
private: private:
// It's not allowed to store a char
template <typename T>
JsonVariant(T value, typename TypeTraits::EnableIf<
TypeTraits::IsSame<T, char>::value>::type * = 0);
JsonArray &variantAsArray() const; JsonArray &variantAsArray() const;
JsonObject &variantAsObject() const; JsonObject &variantAsObject() const;
const char *variantAsString() const; const char *variantAsString() const;
Internals::JsonFloat variantAsFloat() const; template <typename T>
Internals::JsonInteger variantAsInteger() const; T variantAsFloat() const;
Internals::JsonUInt asUnsignedInteger() const; template <typename T>
bool isBoolean() const; T variantAsInteger() const;
bool isFloat() const; bool variantIsBoolean() const;
bool isInteger() const; bool variantIsFloat() const;
bool isArray() const { bool variantIsInteger() const;
bool variantIsArray() const {
return _type == Internals::JSON_ARRAY; return _type == Internals::JSON_ARRAY;
} }
bool isObject() const { bool variantIsObject() const {
return _type == Internals::JSON_OBJECT; return _type == Internals::JSON_OBJECT;
} }
bool isString() const { bool variantIsString() const {
return _type == Internals::JSON_STRING || return _type == Internals::JSON_STRING ||
(_type == Internals::JSON_UNPARSED && _content.asString && (_type == Internals::JSON_UNPARSED && _content.asString &&
!strcmp("null", _content.asString)); !strcmp("null", _content.asString));
@ -347,11 +348,13 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
Internals::JsonVariantContent _content; Internals::JsonVariantContent _content;
}; };
inline JsonVariant float_with_n_digits(float value, uint8_t digits) { DEPRECATED("Decimal places are ignored, use the float value instead")
return JsonVariant(value, digits); inline JsonVariant float_with_n_digits(float value, uint8_t) {
return JsonVariant(value);
} }
inline JsonVariant double_with_n_digits(double value, uint8_t digits) { DEPRECATED("Decimal places are ignored, use the double value instead")
return JsonVariant(value, digits); inline JsonVariant double_with_n_digits(double value, uint8_t) {
return JsonVariant(value);
} }
} }

View File

@ -0,0 +1,23 @@
// Copyright Benoit Blanchon 2014-2017
// MIT License
//
// Arduino JSON library
// https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star!
#pragma once
#include "JsonVariantCasts.hpp"
#include "JsonVariantComparisons.hpp"
#include "JsonVariantSubscripts.hpp"
#include "Serialization/JsonPrintable.hpp"
namespace ArduinoJson {
template <typename TImpl>
class JsonVariantBase : public Internals::JsonPrintable<TImpl>,
public JsonVariantCasts<TImpl>,
public JsonVariantComparisons<TImpl>,
public JsonVariantSubscripts<TImpl>,
public TypeTraits::JsonVariantTag {};
}

View File

@ -0,0 +1,60 @@
// Copyright Benoit Blanchon 2014-2017
// MIT License
//
// Arduino JSON library
// https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star!
#pragma once
#include "Data/JsonVariantAs.hpp"
#include "Polyfills/attributes.hpp"
namespace ArduinoJson {
template <typename TImpl>
class JsonVariantCasts {
public:
#if ARDUINOJSON_ENABLE_DEPRECATED
DEPRECATED("use as<JsonArray>() instead")
FORCE_INLINE JsonArray &asArray() const {
return impl()->template as<JsonArray>();
}
DEPRECATED("use as<JsonObject>() instead")
FORCE_INLINE JsonObject &asObject() const {
return impl()->template as<JsonObject>();
}
DEPRECATED("use as<char*>() instead")
FORCE_INLINE const char *asString() const {
return impl()->template as<const char *>();
}
#endif
// 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 impl()->template 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 impl()->template as<JsonObject &>();
}
template <typename T>
FORCE_INLINE operator T() const {
return impl()->template as<T>();
}
private:
const TImpl *impl() const {
return static_cast<const TImpl *>(this);
}
};
}

View File

@ -0,0 +1,144 @@
// Copyright Benoit Blanchon 2014-2017
// MIT License
//
// Arduino JSON library
// https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star!
#pragma once
#include "StringTraits/StringTraits.hpp"
#include "TypeTraits/EnableIf.hpp"
#include "TypeTraits/IsVariant.hpp"
namespace ArduinoJson {
template <typename TImpl>
class JsonVariantComparisons {
public:
template <typename TComparand>
friend bool operator==(const JsonVariantComparisons &variant,
TComparand comparand) {
return variant.equals(comparand);
}
template <typename TComparand>
friend
typename TypeTraits::EnableIf<!TypeTraits::IsVariant<TComparand>::value,
bool>::type
operator==(TComparand comparand, const JsonVariantComparisons &variant) {
return variant.equals(comparand);
}
template <typename TComparand>
friend bool operator!=(const JsonVariantComparisons &variant,
TComparand comparand) {
return !variant.equals(comparand);
}
template <typename TComparand>
friend
typename TypeTraits::EnableIf<!TypeTraits::IsVariant<TComparand>::value,
bool>::type
operator!=(TComparand comparand, const JsonVariantComparisons &variant) {
return !variant.equals(comparand);
}
template <typename TComparand>
friend bool operator<=(const JsonVariantComparisons &left, TComparand right) {
return left.as<TComparand>() <= right;
}
template <typename TComparand>
friend bool operator<=(TComparand comparand,
const JsonVariantComparisons &variant) {
return comparand <= variant.as<TComparand>();
}
template <typename TComparand>
friend bool operator>=(const JsonVariantComparisons &variant,
TComparand comparand) {
return variant.as<TComparand>() >= comparand;
}
template <typename TComparand>
friend bool operator>=(TComparand comparand,
const JsonVariantComparisons &variant) {
return comparand >= variant.as<TComparand>();
}
template <typename TComparand>
friend bool operator<(const JsonVariantComparisons &varian,
TComparand comparand) {
return varian.as<TComparand>() < comparand;
}
template <typename TComparand>
friend bool operator<(TComparand comparand,
const JsonVariantComparisons &variant) {
return comparand < variant.as<TComparand>();
}
template <typename TComparand>
friend bool operator>(const JsonVariantComparisons &variant,
TComparand comparand) {
return variant.as<TComparand>() > comparand;
}
template <typename TComparand>
friend bool operator>(TComparand comparand,
const JsonVariantComparisons &variant) {
return comparand > variant.as<TComparand>();
}
private:
const TImpl *impl() const {
return static_cast<const TImpl *>(this);
}
template <typename T>
const typename Internals::JsonVariantAs<T>::type as() const {
return impl()->template as<T>();
}
template <typename T>
bool is() const {
return impl()->template is<T>();
}
template <typename TString>
typename TypeTraits::EnableIf<TypeTraits::IsString<TString>::value,
bool>::type
equals(const TString &comparand) const {
const char *value = as<const char *>();
return Internals::StringTraits<TString>::equals(comparand, value);
}
template <typename TComparand>
typename TypeTraits::EnableIf<!TypeTraits::IsVariant<TComparand>::value &&
!TypeTraits::IsString<TComparand>::value,
bool>::type
equals(const TComparand &comparand) const {
return as<TComparand>() == comparand;
}
template <typename TVariant2>
bool equals(const JsonVariantComparisons<TVariant2> &right) const {
using namespace Internals;
if (is<bool>() && right.template is<bool>())
return as<bool>() == right.template as<bool>();
if (is<JsonInteger>() && right.template is<JsonInteger>())
return as<JsonInteger>() == right.template as<JsonInteger>();
if (is<JsonFloat>() && right.template is<JsonFloat>())
return as<JsonFloat>() == right.template as<JsonFloat>();
if (is<JsonArray>() && right.template is<JsonArray>())
return as<JsonArray>() == right.template as<JsonArray>();
if (is<JsonObject>() && right.template is<JsonObject>())
return as<JsonObject>() == right.template as<JsonObject>();
if (is<char *>() && right.template is<char *>())
return strcmp(as<char *>(), right.template as<char *>()) == 0;
return false;
}
};
}

View File

@ -2,19 +2,20 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#include "Configuration.hpp" #include "Configuration.hpp"
#include "Data/Parse.hpp"
#include "JsonArray.hpp" #include "JsonArray.hpp"
#include "JsonObject.hpp" #include "JsonObject.hpp"
#include "JsonVariant.hpp" #include "JsonVariant.hpp"
#include "Polyfills/isFloat.hpp"
#include "Polyfills/isInteger.hpp"
#include "Polyfills/parseFloat.hpp"
#include "Polyfills/parseInteger.hpp"
#include <errno.h> // for errno
#include <stdlib.h> // for strtol, strtod
#include <string.h> // for strcmp #include <string.h> // for strcmp
namespace ArduinoJson { namespace ArduinoJson {
@ -47,42 +48,22 @@ inline JsonObject &JsonVariant::variantAsObject() const {
return JsonObject::invalid(); return JsonObject::invalid();
} }
inline Internals::JsonInteger JsonVariant::variantAsInteger() const { template <typename T>
inline T JsonVariant::variantAsInteger() const {
using namespace Internals; using namespace Internals;
switch (_type) { switch (_type) {
case JSON_UNDEFINED: case JSON_UNDEFINED:
return 0; return 0;
case JSON_POSITIVE_INTEGER: case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN: case JSON_BOOLEAN:
return _content.asInteger; return T(_content.asInteger);
case JSON_NEGATIVE_INTEGER: case JSON_NEGATIVE_INTEGER:
return -static_cast<Internals::JsonInteger>(_content.asInteger); return T(~_content.asInteger + 1);
case JSON_STRING: case JSON_STRING:
case JSON_UNPARSED: case JSON_UNPARSED:
if (!_content.asString) return 0; return Polyfills::parseInteger<T>(_content.asString);
if (!strcmp("true", _content.asString)) return 1;
return parse<Internals::JsonInteger>(_content.asString);
default: default:
return static_cast<Internals::JsonInteger>(_content.asFloat); return T(_content.asFloat);
}
}
inline Internals::JsonUInt JsonVariant::asUnsignedInteger() const {
using namespace Internals;
switch (_type) {
case JSON_UNDEFINED:
return 0;
case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN:
case JSON_NEGATIVE_INTEGER:
return _content.asInteger;
case JSON_STRING:
case JSON_UNPARSED:
if (!_content.asString) return 0;
if (!strcmp("true", _content.asString)) return 1;
return parse<Internals::JsonUInt>(_content.asString);
default:
return static_cast<Internals::JsonUInt>(_content.asFloat);
} }
} }
@ -95,25 +76,26 @@ inline const char *JsonVariant::variantAsString() const {
return NULL; return NULL;
} }
inline Internals::JsonFloat JsonVariant::variantAsFloat() const { template <typename T>
inline T JsonVariant::variantAsFloat() const {
using namespace Internals; using namespace Internals;
switch (_type) { switch (_type) {
case JSON_UNDEFINED: case JSON_UNDEFINED:
return 0; return 0;
case JSON_POSITIVE_INTEGER: case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN: case JSON_BOOLEAN:
return static_cast<JsonFloat>(_content.asInteger); return static_cast<T>(_content.asInteger);
case JSON_NEGATIVE_INTEGER: case JSON_NEGATIVE_INTEGER:
return -static_cast<JsonFloat>(_content.asInteger); return -static_cast<T>(_content.asInteger);
case JSON_STRING: case JSON_STRING:
case JSON_UNPARSED: case JSON_UNPARSED:
return _content.asString ? parse<JsonFloat>(_content.asString) : 0; return Polyfills::parseFloat<T>(_content.asString);
default: default:
return _content.asFloat; return static_cast<T>(_content.asFloat);
} }
} }
inline bool JsonVariant::isBoolean() const { inline bool JsonVariant::variantIsBoolean() const {
using namespace Internals; using namespace Internals;
if (_type == JSON_BOOLEAN) return true; if (_type == JSON_BOOLEAN) return true;
@ -123,31 +105,19 @@ inline bool JsonVariant::isBoolean() const {
!strcmp(_content.asString, "false"); !strcmp(_content.asString, "false");
} }
inline bool JsonVariant::isInteger() const { inline bool JsonVariant::variantIsInteger() const {
using namespace Internals; using namespace Internals;
if (_type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER)
return true;
if (_type != JSON_UNPARSED || _content.asString == NULL) return false; return _type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER ||
(_type == JSON_UNPARSED && Polyfills::isInteger(_content.asString));
char *end;
errno = 0;
strtol(_content.asString, &end, 10);
return *end == '\0' && errno == 0;
} }
inline bool JsonVariant::isFloat() const { inline bool JsonVariant::variantIsFloat() const {
using namespace Internals; using namespace Internals;
if (_type >= JSON_FLOAT_0_DECIMALS) return true;
if (_type != JSON_UNPARSED || _content.asString == NULL) return false; return _type == JSON_FLOAT || _type == JSON_POSITIVE_INTEGER ||
_type == JSON_NEGATIVE_INTEGER ||
char *end; (_type == JSON_UNPARSED && Polyfills::isFloat(_content.asString));
errno = 0;
strtod(_content.asString, &end);
return *end == '\0' && errno == 0 && !is<long>();
} }
#if ARDUINOJSON_ENABLE_STD_STREAM #if ARDUINOJSON_ENABLE_STD_STREAM

View File

@ -2,14 +2,15 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#include "Data/JsonVariantAs.hpp" #include "Data/JsonVariantAs.hpp"
#include "Polyfills/attributes.hpp" #include "Polyfills/attributes.hpp"
#include "Serialization/JsonPrintable.hpp" #include "StringTraits/StringTraits.hpp"
#include "TypeTraits/EnableIf.hpp"
namespace ArduinoJson { namespace ArduinoJson {
@ -19,67 +20,21 @@ template <typename TKey>
class JsonObjectSubscript; class JsonObjectSubscript;
template <typename TImpl> template <typename TImpl>
class JsonVariantBase : public Internals::JsonPrintable<TImpl> { class JsonVariantSubscripts {
public: public:
#if ARDUINOJSON_ENABLE_DEPRECATED
DEPRECATED("use as<JsonArray>() instead")
FORCE_INLINE JsonArray &asArray() const {
return as<JsonArray>();
}
DEPRECATED("use as<JsonObject>() instead")
FORCE_INLINE JsonObject &asObject() const {
return as<JsonObject>();
}
DEPRECATED("use as<char*>() instead")
FORCE_INLINE const char *asString() const {
return as<const char *>();
}
#endif
// 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 &>();
}
// 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 &>();
}
template <typename T>
FORCE_INLINE operator T() const {
return as<T>();
}
template <typename T>
FORCE_INLINE const typename Internals::JsonVariantAs<T>::type as() const {
return impl()->template as<T>();
}
template <typename T>
FORCE_INLINE bool is() const {
return impl()->template is<T>();
}
// Mimics an array or an object. // Mimics an array or an object.
// Returns the size of the array or object if the variant has that type. // 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 // Returns 0 if the variant is neither an array nor an object
size_t size() const { size_t size() const {
return as<JsonArray>().size() + as<JsonObject>().size(); return impl()->template as<JsonArray>().size() +
impl()->template as<JsonObject>().size();
} }
// Mimics an array. // Mimics an array.
// Returns the element at specified index if the variant is an array. // Returns the element at specified index if the variant is an array.
// Returns JsonVariant::invalid() if the variant is not an array. // Returns JsonVariant::invalid() if the variant is not an array.
FORCE_INLINE const JsonArraySubscript operator[](int index) const; FORCE_INLINE const JsonArraySubscript operator[](size_t index) const;
FORCE_INLINE JsonArraySubscript operator[](int index); FORCE_INLINE JsonArraySubscript operator[](size_t index);
// Mimics an object. // Mimics an object.
// Returns the value associated with the specified key if the variant is // Returns the value associated with the specified key if the variant is
@ -93,7 +48,7 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
Internals::StringTraits<TString>::has_equals, Internals::StringTraits<TString>::has_equals,
const JsonObjectSubscript<const TString &> >::type const JsonObjectSubscript<const TString &> >::type
operator[](const TString &key) const { operator[](const TString &key) const {
return as<JsonObject>()[key]; return impl()->template as<JsonObject>()[key];
} }
// //
// const JsonObjectSubscript operator[](TKey) const; // const JsonObjectSubscript operator[](TKey) const;
@ -103,7 +58,7 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
Internals::StringTraits<TString>::has_equals, Internals::StringTraits<TString>::has_equals,
JsonObjectSubscript<const TString &> >::type JsonObjectSubscript<const TString &> >::type
operator[](const TString &key) { operator[](const TString &key) {
return as<JsonObject>()[key]; return impl()->template as<JsonObject>()[key];
} }
// //
// JsonObjectSubscript operator[](TKey); // JsonObjectSubscript operator[](TKey);
@ -113,7 +68,7 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
Internals::StringTraits<const TString *>::has_equals, Internals::StringTraits<const TString *>::has_equals,
JsonObjectSubscript<const TString *> >::type JsonObjectSubscript<const TString *> >::type
operator[](const TString *key) { operator[](const TString *key) {
return as<JsonObject>()[key]; return impl()->template as<JsonObject>()[key];
} }
// //
// JsonObjectSubscript operator[](TKey); // JsonObjectSubscript operator[](TKey);
@ -123,7 +78,7 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
Internals::StringTraits<TString *>::has_equals, Internals::StringTraits<TString *>::has_equals,
const JsonObjectSubscript<const TString *> >::type const JsonObjectSubscript<const TString *> >::type
operator[](const TString *key) const { operator[](const TString *key) const {
return as<JsonObject>()[key]; return impl()->template as<JsonObject>()[key];
} }
private: private:
@ -131,9 +86,4 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
return static_cast<const TImpl *>(this); return static_cast<const TImpl *>(this);
} }
}; };
namespace TypeTraits {
template <typename T>
struct IsVariant : IsBaseOf<JsonVariantBase<T>, T> {};
}
} }

View File

@ -2,16 +2,19 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#ifdef _MSC_VER #ifdef _MSC_VER // Visual Studio
#define FORCE_INLINE __forceinline #define FORCE_INLINE __forceinline
#define NO_INLINE __declspec(noinline) #define NO_INLINE __declspec(noinline)
#define DEPRECATED(msg) __declspec(deprecated(msg)) #define DEPRECATED(msg) __declspec(deprecated(msg))
#else
#elif defined(__GNUC__) // GCC or Clang
#define FORCE_INLINE __attribute__((always_inline)) #define FORCE_INLINE __attribute__((always_inline))
#define NO_INLINE __attribute__((noinline)) #define NO_INLINE __attribute__((noinline))
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
@ -19,4 +22,11 @@
#else #else
#define DEPRECATED(msg) __attribute__((deprecated)) #define DEPRECATED(msg) __attribute__((deprecated))
#endif #endif
#else // Other compilers
#define FORCE_INLINE
#define NO_INLINE
#define DEPRECATED(msg)
#endif #endif

View File

@ -0,0 +1,21 @@
// Copyright Benoit Blanchon 2014-2017
// MIT License
//
// Arduino JSON library
// https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star!
#pragma once
namespace ArduinoJson {
namespace Polyfills {
inline bool isdigit(char c) {
return '0' <= c && c <= '9';
}
inline bool issign(char c) {
return '-' == c || c == '+';
}
}
}

View File

@ -0,0 +1,41 @@
// Copyright Benoit Blanchon 2014-2017
// MIT License
//
// Arduino JSON library
// https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star!
#pragma once
#include <string.h> // for strcmp
#include "./ctype.hpp"
namespace ArduinoJson {
namespace Polyfills {
inline bool isFloat(const char* s) {
if (!s) return false;
if (!strcmp(s, "NaN")) return true;
if (issign(*s)) s++;
if (!strcmp(s, "Infinity")) return true;
if (*s == '\0') return false;
while (isdigit(*s)) s++;
if (*s == '.') {
s++;
while (isdigit(*s)) s++;
}
if (*s == 'e' || *s == 'E') {
s++;
if (issign(*s)) s++;
if (!isdigit(*s)) return false;
while (isdigit(*s)) s++;
}
return *s == '\0';
}
}
}

View File

@ -0,0 +1,22 @@
// Copyright Benoit Blanchon 2014-2017
// MIT License
//
// Arduino JSON library
// https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star!
#pragma once
#include "./ctype.hpp"
namespace ArduinoJson {
namespace Polyfills {
inline bool isInteger(const char* s) {
if (!s) return false;
if (issign(*s)) s++;
while (isdigit(*s)) s++;
return *s == '\0';
}
}
}

View File

@ -0,0 +1,22 @@
// Copyright Benoit Blanchon 2014-2017
// MIT License
//
// Arduino JSON library
// https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star!
#pragma once
namespace ArduinoJson {
namespace Polyfills {
template <typename T>
bool isNaN(T x) {
return x != x;
}
template <typename T>
bool isInfinity(T x) {
return x != 0.0 && x * 2 == x;
}
}
}

View File

@ -0,0 +1,93 @@
// Copyright Benoit Blanchon 2014-2017
// MIT License
//
// Arduino JSON library
// https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star!
#pragma once
#include "../TypeTraits/FloatTraits.hpp"
#include "./ctype.hpp"
#include "./math.hpp"
namespace ArduinoJson {
namespace Polyfills {
template <typename T>
inline T parseFloat(const char* s) {
typedef TypeTraits::FloatTraits<T> traits;
typedef typename traits::mantissa_type mantissa_t;
typedef typename traits::exponent_type exponent_t;
if (!s) return 0; // NULL
bool negative_result = false;
switch (*s) {
case '-':
negative_result = true;
s++;
break;
case '+':
s++;
break;
}
if (*s == 't') return 1; // true
if (*s == 'n' || *s == 'N') return traits::nan();
if (*s == 'i' || *s == 'I')
return negative_result ? -traits::inf() : traits::inf();
mantissa_t mantissa = 0;
exponent_t exponent_offset = 0;
while (isdigit(*s)) {
if (mantissa < traits::mantissa_max / 10)
mantissa = mantissa * 10 + (*s - '0');
else
exponent_offset++;
s++;
}
if (*s == '.') {
s++;
while (isdigit(*s)) {
if (mantissa < traits::mantissa_max / 10) {
mantissa = mantissa * 10 + (*s - '0');
exponent_offset--;
}
s++;
}
}
int exponent = 0;
if (*s == 'e' || *s == 'E') {
s++;
bool negative_exponent = false;
if (*s == '-') {
negative_exponent = true;
s++;
} else if (*s == '+') {
s++;
}
while (isdigit(*s)) {
exponent = exponent * 10 + (*s - '0');
if (exponent + exponent_offset > traits::exponent_max) {
if (negative_exponent)
return negative_result ? -0.0f : 0.0f;
else
return negative_result ? -traits::inf() : traits::inf();
}
s++;
}
if (negative_exponent) exponent = -exponent;
}
exponent += exponent_offset;
T result = traits::make_float(static_cast<T>(mantissa), exponent);
return negative_result ? -result : result;
}
}
}

View File

@ -0,0 +1,44 @@
// Copyright Benoit Blanchon 2014-2017
// MIT License
//
// Arduino JSON library
// https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star!
#pragma once
#include <stdlib.h>
#include "../Configuration.hpp"
#include "./ctype.hpp"
namespace ArduinoJson {
namespace Polyfills {
template <typename T>
T parseInteger(const char *s) {
if (!s) return 0; // NULL
if (*s == 't') return 1; // "true"
T result = 0;
bool negative_result = false;
switch (*s) {
case '-':
negative_result = true;
s++;
break;
case '+':
s++;
break;
}
while (isdigit(*s)) {
result = T(result * 10 + T(*s - '0'));
s++;
}
return negative_result ? T(~result + 1) : result;
}
}
}

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,22 +2,24 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#include "../Print.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
// A dummy Print implementation used in JsonPrintable::measureLength() // A dummy Print implementation used in JsonPrintable::measureLength()
class DummyPrint : public Print { class DummyPrint {
public: public:
virtual size_t write(uint8_t) { size_t print(char) {
return 1; return 1;
} }
size_t print(const char* s) {
return strlen(s);
}
}; };
} }
} }

View File

@ -2,12 +2,11 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#include "../Print.hpp"
#include "../StringTraits/StringTraits.hpp" #include "../StringTraits/StringTraits.hpp"
namespace ArduinoJson { namespace ArduinoJson {
@ -15,15 +14,21 @@ namespace Internals {
// A Print implementation that allows to write in a String // A Print implementation that allows to write in a String
template <typename TString> template <typename TString>
class DynamicStringBuilder : public Print { class DynamicStringBuilder {
public: public:
DynamicStringBuilder(TString &str) : _str(str) {} DynamicStringBuilder(TString &str) : _str(str) {}
virtual size_t write(uint8_t c) { size_t print(char c) {
StringTraits<TString>::append(_str, static_cast<char>(c)); StringTraits<TString>::append(_str, c);
return 1; return 1;
} }
size_t print(const char *s) {
size_t initialLen = _str.length();
StringTraits<TString>::append(_str, s);
return _str.length() - initialLen;
}
private: private:
DynamicStringBuilder &operator=(const DynamicStringBuilder &); DynamicStringBuilder &operator=(const DynamicStringBuilder &);

View File

@ -0,0 +1,92 @@
// Copyright Benoit Blanchon 2014-2017
// MIT License
//
// Arduino JSON library
// https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star!
#pragma once
#include "../Configuration.hpp"
#include "../Polyfills/math.hpp"
#include "../TypeTraits/FloatTraits.hpp"
namespace ArduinoJson {
namespace Internals {
template <typename TFloat>
struct FloatParts {
uint32_t integral;
uint32_t decimal;
int16_t exponent;
int8_t decimalPlaces;
FloatParts(TFloat value) {
uint32_t maxDecimalPart = sizeof(TFloat) >= 8 ? 1000000000 : 1000000;
decimalPlaces = sizeof(TFloat) >= 8 ? 9 : 6;
exponent = normalize(value);
integral = uint32_t(value);
// reduce number of decimal places by the number of integral places
for (uint32_t tmp = integral; tmp >= 10; tmp /= 10) {
maxDecimalPart /= 10;
decimalPlaces--;
}
TFloat remainder = (value - TFloat(integral)) * TFloat(maxDecimalPart);
decimal = uint32_t(remainder);
remainder = remainder - TFloat(decimal);
// rounding:
// increment by 1 if remainder >= 0.5
decimal += uint32_t(remainder * 2);
if (decimal >= maxDecimalPart) {
decimal = 0;
integral++;
if (exponent && integral >= 10) {
exponent++;
integral = 1;
}
}
// remove trailing zeros
while (decimal % 10 == 0 && decimalPlaces > 0) {
decimal /= 10;
decimalPlaces--;
}
}
static int16_t normalize(TFloat& value) {
typedef TypeTraits::FloatTraits<TFloat> traits;
int16_t powersOf10 = 0;
int8_t index = sizeof(TFloat) == 8 ? 8 : 5;
int bit = 1 << index;
if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) {
for (; index >= 0; index--) {
if (value >= traits::positiveBinaryPowerOfTen(index)) {
value *= traits::negativeBinaryPowerOfTen(index);
powersOf10 = int16_t(powersOf10 + bit);
}
bit >>= 1;
}
}
if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) {
for (; index >= 0; index--) {
if (value < traits::negativeBinaryPowerOfTenPlusOne(index)) {
value *= traits::positiveBinaryPowerOfTen(index);
powersOf10 = int16_t(powersOf10 - bit);
}
bit >>= 1;
}
}
return powersOf10;
}
};
}
}

View File

@ -2,20 +2,19 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#include "../Print.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
// Decorator on top of Print to allow indented output. // Decorator on top of Print to allow indented output.
// This class is used by JsonPrintable::prettyPrintTo() but can also be used // This class is used by JsonPrintable::prettyPrintTo() but can also be used
// for your own purpose, like logging. // for your own purpose, like logging.
class IndentedPrint : public Print { template <typename Print>
class IndentedPrint {
public: public:
explicit IndentedPrint(Print &p) : sink(&p) { explicit IndentedPrint(Print &p) : sink(&p) {
level = 0; level = 0;
@ -23,14 +22,21 @@ class IndentedPrint : public Print {
isNewLine = true; isNewLine = true;
} }
virtual size_t write(uint8_t c) { size_t print(char c) {
size_t n = 0; size_t n = 0;
if (isNewLine) n += writeTabs(); if (isNewLine) n += writeTabs();
n += sink->write(c); n += sink->print(c);
isNewLine = c == '\n'; isNewLine = c == '\n';
return n; return n;
} }
size_t print(const char *s) {
// TODO: optimize
size_t n = 0;
while (*s) n += print(*s++);
return n;
}
// Adds one level of indentation // Adds one level of indentation
void indent() { void indent() {
if (level < MAX_LEVEL) level++; if (level < MAX_LEVEL) level++;
@ -54,7 +60,7 @@ class IndentedPrint : public Print {
size_t writeTabs() { size_t writeTabs() {
size_t n = 0; size_t n = 0;
for (int i = 0; i < level * tabSize; i++) n += sink->write(' '); for (int i = 0; i < level * tabSize; i++) n += sink->print(' ');
return n; return n;
} }

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -31,9 +31,12 @@ namespace Internals {
template <typename T> template <typename T>
class JsonPrintable { class JsonPrintable {
public: public:
size_t printTo(Print &print) const { template <typename Print>
JsonWriter writer(print); typename TypeTraits::EnableIf<!TypeTraits::IsString<Print>::value,
JsonSerializer::serialize(downcast(), writer); size_t>::type
printTo(Print &print) const {
JsonWriter<Print> writer(print);
JsonSerializer<JsonWriter<Print> >::serialize(downcast(), writer);
return writer.bytesWritten(); return writer.bytesWritten();
} }
@ -62,8 +65,9 @@ class JsonPrintable {
return printTo(sb); return printTo(sb);
} }
size_t prettyPrintTo(IndentedPrint &print) const { template <typename Print>
Prettyfier p(print); size_t prettyPrintTo(IndentedPrint<Print> &print) const {
Prettyfier<Print> p(print);
return printTo(p); return printTo(p);
} }
@ -77,8 +81,11 @@ class JsonPrintable {
return prettyPrintTo(buffer, N); return prettyPrintTo(buffer, N);
} }
size_t prettyPrintTo(Print &print) const { template <typename Print>
IndentedPrint indentedPrint = IndentedPrint(print); typename TypeTraits::EnableIf<!TypeTraits::IsString<Print>::value,
size_t>::type
prettyPrintTo(Print &print) const {
IndentedPrint<Print> indentedPrint(print);
return prettyPrintTo(indentedPrint); return prettyPrintTo(indentedPrint);
} }

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -20,14 +20,15 @@ class JsonVariant;
namespace Internals { namespace Internals {
template <typename Writer>
class JsonSerializer { class JsonSerializer {
public: public:
static void serialize(const JsonArray &, JsonWriter &); static void serialize(const JsonArray &, Writer &);
static void serialize(const JsonArraySubscript &, JsonWriter &); static void serialize(const JsonArraySubscript &, Writer &);
static void serialize(const JsonObject &, JsonWriter &); static void serialize(const JsonObject &, Writer &);
template <typename TKey> template <typename TKey>
static void serialize(const JsonObjectSubscript<TKey> &, JsonWriter &); static void serialize(const JsonObjectSubscript<TKey> &, Writer &);
static void serialize(const JsonVariant &, JsonWriter &); static void serialize(const JsonVariant &, Writer &);
}; };
} }
} }

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -14,8 +14,9 @@
#include "../JsonVariant.hpp" #include "../JsonVariant.hpp"
#include "JsonSerializer.hpp" #include "JsonSerializer.hpp"
inline void ArduinoJson::Internals::JsonSerializer::serialize( template <typename Writer>
const JsonArray& array, JsonWriter& writer) { inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonArray& array, Writer& writer) {
writer.beginArray(); writer.beginArray();
JsonArray::const_iterator it = array.begin(); JsonArray::const_iterator it = array.begin();
@ -31,13 +32,15 @@ inline void ArduinoJson::Internals::JsonSerializer::serialize(
writer.endArray(); writer.endArray();
} }
inline void ArduinoJson::Internals::JsonSerializer::serialize( template <typename Writer>
const JsonArraySubscript& arraySubscript, JsonWriter& writer) { inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonArraySubscript& arraySubscript, Writer& writer) {
serialize(arraySubscript.as<JsonVariant>(), writer); serialize(arraySubscript.as<JsonVariant>(), writer);
} }
inline void ArduinoJson::Internals::JsonSerializer::serialize( template <typename Writer>
const JsonObject& object, JsonWriter& writer) { inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonObject& object, Writer& writer) {
writer.beginObject(); writer.beginObject();
JsonObject::const_iterator it = object.begin(); JsonObject::const_iterator it = object.begin();
@ -55,16 +58,19 @@ inline void ArduinoJson::Internals::JsonSerializer::serialize(
writer.endObject(); writer.endObject();
} }
template <typename Writer>
template <typename TKey> template <typename TKey>
inline void ArduinoJson::Internals::JsonSerializer::serialize( inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonObjectSubscript<TKey>& objectSubscript, JsonWriter& writer) { const JsonObjectSubscript<TKey>& objectSubscript, Writer& writer) {
serialize(objectSubscript.template as<JsonVariant>(), writer); serialize(objectSubscript.template as<JsonVariant>(), writer);
} }
inline void ArduinoJson::Internals::JsonSerializer::serialize( template <typename Writer>
const JsonVariant& variant, JsonWriter& writer) { inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonVariant& variant, Writer& writer) {
switch (variant._type) { switch (variant._type) {
case JSON_UNDEFINED: case JSON_FLOAT:
writer.writeFloat(variant._content.asFloat);
return; return;
case JSON_ARRAY: case JSON_ARRAY:
@ -84,7 +90,8 @@ inline void ArduinoJson::Internals::JsonSerializer::serialize(
return; return;
case JSON_NEGATIVE_INTEGER: case JSON_NEGATIVE_INTEGER:
writer.writeRaw('-'); writer.writeRaw('-'); // Falls through.
case JSON_POSITIVE_INTEGER: case JSON_POSITIVE_INTEGER:
writer.writeInteger(variant._content.asInteger); writer.writeInteger(variant._content.asInteger);
return; return;
@ -93,9 +100,7 @@ inline void ArduinoJson::Internals::JsonSerializer::serialize(
writer.writeBoolean(variant._content.asInteger != 0); writer.writeBoolean(variant._content.asInteger != 0);
return; return;
default: default: // JSON_UNDEFINED
uint8_t decimals = return;
static_cast<uint8_t>(variant._type - JSON_FLOAT_0_DECIMALS);
writer.writeFloat(variant._content.asFloat, decimals);
} }
} }

View File

@ -2,18 +2,16 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#include <stdint.h>
#include "../Data/Encoding.hpp" #include "../Data/Encoding.hpp"
#include "../Data/JsonFloat.hpp"
#include "../Data/JsonInteger.hpp" #include "../Data/JsonInteger.hpp"
#include "../Polyfills/attributes.hpp" #include "../Polyfills/attributes.hpp"
#include "../Polyfills/math.hpp" #include "../Serialization/FloatParts.hpp"
#include "../Polyfills/normalize.hpp"
#include "../Print.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
@ -25,6 +23,7 @@ namespace Internals {
// - JsonVariant::writeTo() // - JsonVariant::writeTo()
// Its derived by PrettyJsonWriter that overrides some members to add // Its derived by PrettyJsonWriter that overrides some members to add
// indentation. // indentation.
template <typename Print>
class JsonWriter { class JsonWriter {
public: public:
explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {} explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {}
@ -81,7 +80,8 @@ class JsonWriter {
} }
} }
void writeFloat(JsonFloat value, uint8_t digits = 2) { template <typename TFloat>
void writeFloat(TFloat value) {
if (Polyfills::isNaN(value)) return writeRaw("NaN"); if (Polyfills::isNaN(value)) return writeRaw("NaN");
if (value < 0.0) { if (value < 0.0) {
@ -91,66 +91,60 @@ class JsonWriter {
if (Polyfills::isInfinity(value)) return writeRaw("Infinity"); if (Polyfills::isInfinity(value)) return writeRaw("Infinity");
short powersOf10; FloatParts<TFloat> parts(value);
if (value > 1000 || value < 0.001) {
powersOf10 = Polyfills::normalize(value);
} else {
powersOf10 = 0;
}
// Round up last digit (so that print(1.999, 2) prints as "2.00") writeInteger(parts.integral);
value += getRoundingBias(digits); if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces);
// Extract the integer part of the value and print it if (parts.exponent < 0) {
JsonUInt int_part = static_cast<JsonUInt>(value);
JsonFloat remainder = value - static_cast<JsonFloat>(int_part);
writeInteger(int_part);
// Print the decimal point, but only if there are digits beyond
if (digits > 0) {
writeRaw('.');
}
// Extract digits from the remainder one at a time
while (digits-- > 0) {
// Extract digit
remainder *= 10.0;
char currentDigit = char(remainder);
remainder -= static_cast<JsonFloat>(currentDigit);
// Print
writeRaw(char('0' + currentDigit));
}
if (powersOf10 < 0) {
writeRaw("e-"); writeRaw("e-");
writeInteger(-powersOf10); writeInteger(-parts.exponent);
} }
if (powersOf10 > 0) { if (parts.exponent > 0) {
writeRaw('e'); writeRaw('e');
writeInteger(powersOf10); writeInteger(parts.exponent);
} }
} }
void writeInteger(JsonUInt value) { template <typename UInt>
void writeInteger(UInt value) {
char buffer[22]; char buffer[22];
char *ptr = buffer + sizeof(buffer) - 1; char *end = buffer + sizeof(buffer) - 1;
char *ptr = end;
*ptr = 0; *ptr = 0;
do { do {
*--ptr = static_cast<char>(value % 10 + '0'); *--ptr = char(value % 10 + '0');
value /= 10; value = UInt(value / 10);
} while (value); } while (value);
writeRaw(ptr); writeRaw(ptr);
} }
void writeDecimals(uint32_t value, int8_t width) {
// buffer should be big enough for all digits, the dot and the null
// terminator
char buffer[16];
char *ptr = buffer + sizeof(buffer) - 1;
// write the string in reverse order
*ptr = 0;
while (width--) {
*--ptr = char(value % 10 + '0');
value /= 10;
}
*--ptr = '.';
// and dump it in the right order
writeRaw(ptr);
}
void writeRaw(const char *s) { void writeRaw(const char *s) {
_length += _sink.print(s); _length += _sink.print(s);
} }
void writeRaw(char c) { void writeRaw(char c) {
_length += _sink.write(c); _length += _sink.print(c);
} }
protected: protected:
@ -159,26 +153,6 @@ class JsonWriter {
private: private:
JsonWriter &operator=(const JsonWriter &); // cannot be assigned JsonWriter &operator=(const JsonWriter &); // cannot be assigned
static JsonFloat getLastDigit(uint8_t digits) {
// Designed as a compromise between code size and speed
switch (digits) {
case 0:
return 1e-0;
case 1:
return 1e-1;
case 2:
return 1e-2;
case 3:
return 1e-3;
default:
return getLastDigit(uint8_t(digits - 4)) * 1e-4;
}
}
FORCE_INLINE static JsonFloat getRoundingBias(uint8_t digits) {
return 0.5 * getLastDigit(digits);
}
}; };
} }
} }

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -13,19 +13,27 @@ namespace ArduinoJson {
namespace Internals { namespace Internals {
// Converts a compact JSON string into an indented one. // Converts a compact JSON string into an indented one.
class Prettyfier : public Print { template <typename Print>
class Prettyfier {
public: public:
explicit Prettyfier(IndentedPrint& p) : _sink(p) { explicit Prettyfier(IndentedPrint<Print>& p) : _sink(p) {
_previousChar = 0; _previousChar = 0;
_inString = false; _inString = false;
} }
virtual size_t write(uint8_t c) { size_t print(char c) {
size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c); size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c);
_previousChar = c; _previousChar = c;
return n; return n;
} }
size_t print(const char* s) {
// TODO: optimize
size_t n = 0;
while (*s) n += print(*s++);
return n;
}
private: private:
Prettyfier& operator=(const Prettyfier&); // cannot be assigned Prettyfier& operator=(const Prettyfier&); // cannot be assigned
@ -33,15 +41,15 @@ class Prettyfier : public Print {
return _previousChar == '{' || _previousChar == '['; return _previousChar == '{' || _previousChar == '[';
} }
size_t handleStringChar(uint8_t c) { size_t handleStringChar(char c) {
bool isQuote = c == '"' && _previousChar != '\\'; bool isQuote = c == '"' && _previousChar != '\\';
if (isQuote) _inString = false; if (isQuote) _inString = false;
return _sink.write(c); return _sink.print(c);
} }
size_t handleMarkupChar(uint8_t c) { size_t handleMarkupChar(char c) {
switch (c) { switch (c) {
case '{': case '{':
case '[': case '[':
@ -65,31 +73,29 @@ class Prettyfier : public Print {
} }
} }
size_t writeBlockClose(uint8_t c) { size_t writeBlockClose(char c) {
size_t n = 0; size_t n = 0;
n += unindentIfNeeded(); n += unindentIfNeeded();
n += _sink.write(c); n += _sink.print(c);
return n; return n;
} }
size_t writeBlockOpen(uint8_t c) { size_t writeBlockOpen(char c) {
size_t n = 0; size_t n = 0;
n += indentIfNeeded(); n += indentIfNeeded();
n += _sink.write(c); n += _sink.print(c);
return n; return n;
} }
size_t writeColon() { size_t writeColon() {
size_t n = 0; size_t n = 0;
n += _sink.write(':'); n += _sink.print(": ");
n += _sink.write(' ');
return n; return n;
} }
size_t writeComma() { size_t writeComma() {
size_t n = 0; size_t n = 0;
n += _sink.write(','); n += _sink.print(",\r\n");
n += _sink.println();
return n; return n;
} }
@ -97,14 +103,14 @@ class Prettyfier : public Print {
_inString = true; _inString = true;
size_t n = 0; size_t n = 0;
n += indentIfNeeded(); n += indentIfNeeded();
n += _sink.write('"'); n += _sink.print('"');
return n; return n;
} }
size_t writeNormalChar(uint8_t c) { size_t writeNormalChar(char c) {
size_t n = 0; size_t n = 0;
n += indentIfNeeded(); n += indentIfNeeded();
n += _sink.write(c); n += _sink.print(c);
return n; return n;
} }
@ -112,18 +118,18 @@ class Prettyfier : public Print {
if (!inEmptyBlock()) return 0; if (!inEmptyBlock()) return 0;
_sink.indent(); _sink.indent();
return _sink.println(); return _sink.print("\r\n");
} }
size_t unindentIfNeeded() { size_t unindentIfNeeded() {
if (inEmptyBlock()) return 0; if (inEmptyBlock()) return 0;
_sink.unindent(); _sink.unindent();
return _sink.println(); return _sink.print("\r\n");
} }
uint8_t _previousChar; char _previousChar;
IndentedPrint& _sink; IndentedPrint<Print>& _sink;
bool _inString; bool _inString;
}; };
} }

View File

@ -0,0 +1,39 @@
// Copyright Benoit Blanchon 2014-2017
// MIT License
//
// Arduino JSON library
// https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star!
#pragma once
namespace ArduinoJson {
namespace Internals {
// A Print implementation that allows to write in a char[]
class StaticStringBuilder {
public:
StaticStringBuilder(char *buf, size_t size) : end(buf + size - 1), p(buf) {
*p = '\0';
}
size_t print(char c) {
if (p >= end) return 0;
*p++ = c;
*p = '\0';
return 1;
}
size_t print(const char *s) {
char *begin = p;
while (p < end && *s) *p++ = *s++;
*p = '\0';
return size_t(p - begin);
}
private:
char *end;
char *p;
};
}
}

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -11,22 +11,25 @@
#if ARDUINOJSON_ENABLE_STD_STREAM #if ARDUINOJSON_ENABLE_STD_STREAM
#include "../Print.hpp"
#include <ostream> #include <ostream>
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
class StreamPrintAdapter : public Print { class StreamPrintAdapter {
public: public:
explicit StreamPrintAdapter(std::ostream& os) : _os(os) {} explicit StreamPrintAdapter(std::ostream& os) : _os(os) {}
virtual size_t write(uint8_t c) { size_t print(char c) {
_os << static_cast<char>(c); _os << c;
return 1; return 1;
} }
size_t print(const char* s) {
_os << s;
return strlen(s);
}
private: private:
// cannot be assigned // cannot be assigned
StreamPrintAdapter& operator=(const StreamPrintAdapter&); StreamPrintAdapter& operator=(const StreamPrintAdapter&);

View File

@ -2,23 +2,13 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#include "JsonBufferBase.hpp" #include "JsonBufferBase.hpp"
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
namespace ArduinoJson { namespace ArduinoJson {
class StaticJsonBufferBase : public JsonBufferBase<StaticJsonBufferBase> { class StaticJsonBufferBase : public JsonBufferBase<StaticJsonBufferBase> {
@ -54,23 +44,36 @@ class StaticJsonBufferBase : public JsonBufferBase<StaticJsonBufferBase> {
StaticJsonBufferBase(char* buffer, size_t capa) StaticJsonBufferBase(char* buffer, size_t capa)
: _buffer(buffer), _capacity(capa), _size(0) {} : _buffer(buffer), _capacity(capa), _size(0) {}
// Gets the capacity of the buffer in bytes
size_t capacity() const { size_t capacity() const {
return _capacity; return _capacity;
} }
// Gets the current usage of the buffer in bytes
size_t size() const { size_t size() const {
return _size; return _size;
} }
// Allocates the specified amount of bytes in the buffer
virtual void* alloc(size_t bytes) { virtual void* alloc(size_t bytes) {
alignNextAlloc(); alignNextAlloc();
if (!canAlloc(bytes)) return NULL; if (!canAlloc(bytes)) return NULL;
return doAlloc(bytes); return doAlloc(bytes);
} }
// Resets the buffer.
// USE WITH CAUTION: this invalidates all previously allocated data
void clear() {
_size = 0;
}
String startString() { String startString() {
return String(this); return String(this);
} }
protected:
~StaticJsonBufferBase() {}
private: private:
void alignNextAlloc() { void alignNextAlloc() {
_size = round_size_up(_size); _size = round_size_up(_size);
@ -91,6 +94,16 @@ class StaticJsonBufferBase : public JsonBufferBase<StaticJsonBufferBase> {
size_t _size; size_t _size;
}; };
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
// Implements a JsonBuffer with fixed memory allocation. // Implements a JsonBuffer with fixed memory allocation.
// The template paramenter CAPACITY specifies the capacity of the buffer in // The template paramenter CAPACITY specifies the capacity of the buffer in
// bytes. // bytes.

View File

@ -2,16 +2,14 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#include <Stream.h> #if ARDUINOJSON_ENABLE_ARDUINO_STREAM
#include "../TypeTraits/EnableIf.hpp" #include <Stream.h>
#include "../TypeTraits/IsBaseOf.hpp"
#include "../TypeTraits/RemoveReference.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
@ -59,3 +57,5 @@ struct StringTraits<TStream,
: ArduinoStreamTraits {}; : ArduinoStreamTraits {};
} }
} }
#endif

View File

@ -2,14 +2,11 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#include "../TypeTraits/EnableIf.hpp"
#include "../TypeTraits/IsChar.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
@ -26,12 +23,12 @@ struct CharPointerTraits {
++_ptr; ++_ptr;
} }
TChar current() const { char current() const {
return _ptr[0]; return char(_ptr[0]);
} }
TChar next() const { char next() const {
return _ptr[1]; return char(_ptr[1]);
} }
}; };

View File

@ -2,11 +2,13 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#if ARDUINOJSON_ENABLE_PROGMEM
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
template <> template <>
@ -32,15 +34,15 @@ struct StringTraits<const __FlashStringHelper*, void> {
}; };
static bool equals(const __FlashStringHelper* str, const char* expected) { static bool equals(const __FlashStringHelper* str, const char* expected) {
return strcmp_P(expected, (PGM_P)str) == 0; return strcmp_P(expected, (const char*)str) == 0;
} }
template <typename Buffer> template <typename Buffer>
static char* duplicate(const __FlashStringHelper* str, Buffer* buffer) { static char* duplicate(const __FlashStringHelper* str, Buffer* buffer) {
if (!str) return NULL; if (!str) return NULL;
size_t size = strlen_P((PGM_P)str) + 1; size_t size = strlen_P((const char*)str) + 1;
void* dup = buffer->alloc(size); void* dup = buffer->alloc(size);
if (dup != NULL) memcpy_P(dup, (PGM_P)str, size); if (dup != NULL) memcpy_P(dup, (const char*)str, size);
return static_cast<char*>(dup); return static_cast<char*>(dup);
} }
@ -50,3 +52,5 @@ struct StringTraits<const __FlashStringHelper*, void> {
}; };
} }
} }
#endif

View File

@ -2,15 +2,14 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#if ARDUINOJSON_ENABLE_STD_STREAM
#include <istream> #include <istream>
#include "../TypeTraits/EnableIf.hpp"
#include "../TypeTraits/IsBaseOf.hpp"
#include "../TypeTraits/RemoveReference.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
@ -57,3 +56,5 @@ struct StringTraits<TStream,
: StdStreamTraits {}; : StdStreamTraits {};
} }
} }
#endif

View File

@ -2,11 +2,13 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#if ARDUINOJSON_ENABLE_STD_STRING || ARDUINOJSON_ENABLE_ARDUINO_STRING
#if ARDUINOJSON_ENABLE_ARDUINO_STRING #if ARDUINOJSON_ENABLE_ARDUINO_STRING
#include <WString.h> #include <WString.h>
#endif #endif
@ -41,6 +43,10 @@ struct StdStringTraits {
str += c; str += c;
} }
static void append(TString& str, const char* s) {
str += s;
}
static const bool has_append = true; static const bool has_append = true;
static const bool has_equals = true; static const bool has_equals = true;
static const bool should_duplicate = true; static const bool should_duplicate = true;
@ -60,3 +66,5 @@ struct StringTraits<std::string, void> : StdStringTraits<std::string> {};
#endif #endif
} }
} }
#endif

View File

@ -2,12 +2,17 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
#include <string.h>
#include "../Configuration.hpp" #include "../Configuration.hpp"
#include "../TypeTraits/EnableIf.hpp"
#include "../TypeTraits/IsBaseOf.hpp"
#include "../TypeTraits/IsChar.hpp"
#include "../TypeTraits/RemoveReference.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {
@ -23,23 +28,11 @@ struct StringTraits<TString&, void> : StringTraits<TString> {};
} }
} }
#include "CharPointer.hpp"
#if ARDUINOJSON_ENABLE_STD_STRING || ARDUINOJSON_ENABLE_ARDUINO_STRING
#include "StdString.hpp"
#endif
#if ARDUINOJSON_ENABLE_STD_STREAM
#include "StdStream.hpp"
#endif
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
#include "ArduinoStream.hpp" #include "ArduinoStream.hpp"
#endif #include "CharPointer.hpp"
#if ARDUINOJSON_ENABLE_PROGMEM
#include "FlashString.hpp" #include "FlashString.hpp"
#endif #include "StdStream.hpp"
#include "StdString.hpp"
namespace ArduinoJson { namespace ArduinoJson {
namespace TypeTraits { namespace TypeTraits {

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -0,0 +1,153 @@
// Copyright Benoit Blanchon 2014-2017
// MIT License
//
// Arduino JSON library
// https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star!
#pragma once
#include <stdint.h>
#include <stdlib.h> // for size_t
#include "../Configuration.hpp"
#include "../Polyfills/math.hpp"
namespace ArduinoJson {
namespace TypeTraits {
template <typename T, size_t = sizeof(T)>
struct FloatTraits {};
template <typename T>
struct FloatTraits<T, 8 /*64bits*/> {
typedef int64_t mantissa_type;
static const short mantissa_bits = 52;
static const mantissa_type mantissa_max =
(static_cast<mantissa_type>(1) << mantissa_bits) - 1;
typedef int16_t exponent_type;
static const exponent_type exponent_max = 308;
template <typename TExponent>
static T make_float(T m, TExponent e) {
if (e > 0) {
for (uint8_t index = 0; e != 0; index++) {
if (e & 1) m *= positiveBinaryPowerOfTen(index);
e >>= 1;
}
} else {
e = TExponent(-e);
for (uint8_t index = 0; e != 0; index++) {
if (e & 1) m *= negativeBinaryPowerOfTen(index);
e >>= 1;
}
}
return m;
}
static T positiveBinaryPowerOfTen(int index) {
static T factors[] = {
1e1, 1e2, 1e4, 1e8, 1e16, 1e32,
// workaround to support platforms with single precision literals
forge(0x4D384F03, 0xE93FF9F5), forge(0x5A827748, 0xF9301D32),
forge(0x75154FDD, 0x7F73BF3C)};
return factors[index];
}
static T negativeBinaryPowerOfTen(int index) {
static T factors[] = {
1e-1, 1e-2, 1e-4, 1e-8, 1e-16, 1e-32,
// workaround to support platforms with single precision literals
forge(0x32A50FFD, 0x44F4A73D), forge(0x255BBA08, 0xCF8C979D),
forge(0x0AC80628, 0x64AC6F43)};
return factors[index];
}
static T negativeBinaryPowerOfTenPlusOne(int index) {
static T factors[] = {
1e0, 1e-1, 1e-3, 1e-7, 1e-15, 1e-31,
// workaround to support platforms with single precision literals
forge(0x32DA53FC, 0x9631D10D), forge(0x25915445, 0x81B7DEC2),
forge(0x0AFE07B2, 0x7DD78B14)};
return factors[index];
}
static T nan() {
return forge(0x7ff80000, 0x00000000);
}
static T inf() {
return forge(0x7ff00000, 0x00000000);
}
static T forge(uint32_t msb, uint32_t lsb) {
union {
uint64_t integerBits;
T floatBits;
};
integerBits = (uint64_t(msb) << 32) | lsb;
return floatBits;
}
};
template <typename T>
struct FloatTraits<T, 4 /*32bits*/> {
typedef int32_t mantissa_type;
static const short mantissa_bits = 23;
static const mantissa_type mantissa_max =
(static_cast<mantissa_type>(1) << mantissa_bits) - 1;
typedef int8_t exponent_type;
static const exponent_type exponent_max = 38;
template <typename TExponent>
static T make_float(T m, TExponent e) {
if (e > 0) {
for (uint8_t index = 0; e != 0; index++) {
if (e & 1) m *= positiveBinaryPowerOfTen(index);
e >>= 1;
}
} else {
e = -e;
for (uint8_t index = 0; e != 0; index++) {
if (e & 1) m *= negativeBinaryPowerOfTen(index);
e >>= 1;
}
}
return m;
}
static T positiveBinaryPowerOfTen(int index) {
static T factors[] = {1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f};
return factors[index];
}
static T negativeBinaryPowerOfTen(int index) {
static T factors[] = {1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f};
return factors[index];
}
static T negativeBinaryPowerOfTenPlusOne(int index) {
static T factors[] = {1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f};
return factors[index];
}
static T forge(uint32_t bits) {
union {
uint32_t integerBits;
T floatBits;
};
integerBits = bits;
return floatBits;
}
static T nan() {
return forge(0x7fc00000);
}
static T inf() {
return forge(0x7f800000);
}
};
}
}

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once
@ -19,8 +19,8 @@ template <typename T>
struct IsIntegral { struct IsIntegral {
static const bool value = TypeTraits::IsSignedIntegral<T>::value || static const bool value = TypeTraits::IsSignedIntegral<T>::value ||
TypeTraits::IsUnsignedIntegral<T>::value || TypeTraits::IsUnsignedIntegral<T>::value ||
TypeTraits::IsSame<T, char>::value || TypeTraits::IsSame<T, char>::value;
TypeTraits::IsSame<T, bool>::value; // CAUTION: differs from std::is_integral as it doesn't include bool
}; };
template <typename T> template <typename T>

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -0,0 +1,20 @@
// Copyright Benoit Blanchon 2014-2017
// MIT License
//
// Arduino JSON library
// https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star!
#pragma once
#include "IsBaseOf.hpp"
namespace ArduinoJson {
namespace TypeTraits {
class JsonVariantTag {};
template <typename T>
struct IsVariant : IsBaseOf<JsonVariantTag, T> {};
}
}

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -2,7 +2,7 @@
// MIT License // MIT License
// //
// Arduino JSON library // Arduino JSON library
// https://github.com/bblanchon/ArduinoJson // https://bblanchon.github.io/ArduinoJson/
// If you like this project, please add a star! // If you like this project, please add a star!
#pragma once #pragma once

View File

@ -1,21 +0,0 @@
# Copyright Benoit Blanchon 2014-2017
# MIT License
#
# Arduino JSON library
# https://github.com/bblanchon/ArduinoJson
# If you like this project, please add a star!
cmake_minimum_required(VERSION 3.0)
project(ArduinoJson)
enable_testing()
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(${COVERAGE})
set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
endif()
add_subdirectory(test)

View File

@ -1,18 +0,0 @@
version: 5.8.3.{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
# Note: Disabled because of unexplicated error -1073741511
# This used to work fine with GCC 4.8.2 then failed after they upgraded to GCC 4.9.3
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,35 +0,0 @@
// Copyright Benoit Blanchon 2014-2017
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <ArduinoJson.h>
using namespace ArduinoJson::Internals;
void setup() {
Serial.begin(9600);
while (!Serial) {
// wait serial port initialization
}
IndentedPrint serial(Serial);
serial.setTabSize(4);
serial.println("This is at indentation 0");
serial.indent();
serial.println("This is at indentation 1");
serial.println("This is also at indentation 1");
serial.indent();
serial.println("This is at indentation 2");
serial.unindent();
serial.unindent();
serial.println("This is back at indentation 0");
}
void loop() {
// not used in this example
}

View File

@ -1,19 +0,0 @@
# CAUTION: this file is invoked by https://github.com/google/oss-fuzz
CXXFLAGS += -I../include
all: \
$(OUT)/json_fuzzer \
$(OUT)/json_fuzzer_seed_corpus.zip \
$(OUT)/json_fuzzer.options
$(OUT)/json_fuzzer: fuzzer.cpp
$(CXX) $(CXXFLAGS) $< -o$@ $(LIB_FUZZING_ENGINE)
$(OUT)/json_fuzzer_seed_corpus.zip: seed_corpus/*
zip -j $@ $?
$(OUT)/json_fuzzer.options:
@echo "[libfuzzer]" > $@
@echo "max_len = 256" >> $@
@echo "timeout = 10" >> $@

View File

@ -1,8 +0,0 @@
#!/bin/bash
# This script mimics an invocation from https://github.com/google/oss-fuzz
export CXX='clang++'
export CXXFLAGS='-fsanitize-coverage=trace-pc-guard -fsanitize=address'
export LIB_FUZZING_ENGINE=-lFuzzer
make OUT=.
./json_fuzzer my_corpus seed_corpus

View File

@ -1,23 +0,0 @@
#include <ArduinoJson.h>
class memstream : public std::istream {
struct membuf : std::streambuf {
membuf(const uint8_t *p, size_t l) {
setg((char *)p, (char *)p, (char *)p + l);
}
};
membuf _buffer;
public:
memstream(const uint8_t *p, size_t l)
: std::istream(&_buffer), _buffer(p, l) {
rdbuf(&_buffer);
}
};
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
DynamicJsonBuffer jsonBuffer;
memstream json(data, size);
jsonBuffer.parse(json);
return 0;
}

View File

@ -1,2 +0,0 @@
*
!.gitignore

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