Compare commits

..

2 Commits

Author SHA1 Message Date
5f589d3836 Set version to 5.1.0-beta.1 2016-02-01 21:26:15 +01:00
ed4ec6ed2e Added support of long long (issue #171) 2016-02-01 21:17:32 +01:00
106 changed files with 1470 additions and 2558 deletions

View File

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

View File

@ -1,11 +0,0 @@
<!--
Thanks for using ArduinoJson :-)
Before opening an issue, please make sure you've read these:
https://github.com/bblanchon/ArduinoJson/wiki/FAQ
https://github.com/bblanchon/ArduinoJson/wiki/Avoiding-pitfalls
Next, make sure you provide all the relevant information: platform, code snippet, and error messages.
Please be concise!
-->

View File

@ -1,118 +1,15 @@
sudo: false
language: cpp
matrix:
include:
- compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.4']
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.4
- compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.5']
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.5
- compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.6']
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.6
- compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.7']
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.7
- compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.8']
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.8
- compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.9']
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.9
- compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-5']
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-5
- compiler: clang
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++
- compiler: clang
addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5']
packages: ['clang-3.5']
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++-3.5
- compiler: clang
addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.6']
packages: ['clang-3.6']
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++-3.6
- compiler: clang
addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.7']
packages: ['clang-3.7']
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++-3.7
- compiler: clang
addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.8']
packages: ['clang-3.8']
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++-3.8
- compiler: gcc
env: SCRIPT=coverage
- os: osx
osx_image: beta-xcode6.1
compiler: clang
env: SCRIPT=cmake-osx
- os: osx
osx_image: beta-xcode6.2
compiler: clang
env: SCRIPT=cmake-osx
- os: osx
osx_image: beta-xcode6.3
compiler: clang
env: SCRIPT=cmake-osx
- os: osx
osx_image: xcode6.4
compiler: clang
env: SCRIPT=cmake-osx
- os: osx
osx_image: xcode7
compiler: clang
env: SCRIPT=cmake-osx
- os: osx
osx_image: xcode7.1
compiler: clang
env: SCRIPT=cmake-osx
- os: osx
osx_image: xcode7.2
compiler: clang
env: SCRIPT=cmake-osx
- os: osx
osx_image: xcode7.3
compiler: clang
env: SCRIPT=cmake-osx
- env: SCRIPT=arduino VERSION=1.5.8 BOARD=arduino:avr:uno
- env: SCRIPT=arduino VERSION=1.6.7 BOARD=arduino:avr:uno
- env: SCRIPT=arduino VERSION=1.6.8 BOARD=arduino:avr:uno
- env: SCRIPT=arduino VERSION=1.6.9 BOARD=arduino:avr:uno
- env: SCRIPT=platformio BOARD=uno
- env: SCRIPT=platformio BOARD=due
- env: SCRIPT=platformio BOARD=esp01
- env: SCRIPT=platformio BOARD=teensy31
cache:
directories:
- "~/.platformio"
script: scripts/travis/$SCRIPT.sh
env:
- COMPILER=gcc
- COMPILER=clang
- COMPILER=arduino VERSION=1.5.8 BOARD=arduino:avr:uno
- COMPILER=arduino VERSION=1.6.7 BOARD=arduino:avr:uno
- COMPILER=platformio BOARD=uno
- COMPILER=platformio BOARD=due
- COMPILER=platformio BOARD=esp01
- COMPILER=platformio BOARD=teensy31
script: scripts/travis/$COMPILER.sh

View File

@ -5,4 +5,10 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
// About this file
// ---------------
// This file is here for [PlatformIO](http://platformio.org/).
// It must be present in the root for the tool to find it.
// Feel free to ignore this file if your working in another environment.
#include "include/ArduinoJson.h"

View File

@ -1,65 +1,6 @@
ArduinoJson: change log
=======================
v5.6.3
------
* Improved speed of float serialization (about twice faster)
* Added `as<JsonArray>()` as a synonym for `as<JsonArray&>()`... (issue #291)
* Fixed `call of overloaded isinf(double&) is ambiguous` (issue #284)
v5.6.2
------
* Fixed build when another lib does `#undef isnan` (issue #284)
v5.6.1
------
* Added missing `#pragma once` (issue #310)
v5.6.0
------
* ArduinoJson is now a header-only library (issue #199)
v5.5.1
------
* Fixed compilation error with Intel Galileo (issue #299)
v5.5.0
------
* Added `JsonVariant::success()` (issue #279)
* Renamed `JsonVariant::invalid<T>()` to `JsonVariant::defaultValue<T>()`
v5.4.0
------
* Changed `::String` to `ArduinoJson::String` (issue #275)
* Changed `::Print` to `ArduinoJson::Print` too
v5.3.0
------
* Added custom implementation of `ftoa` (issues #266, #267, #269 and #270)
* Added `JsonVariant JsonBuffer::parse()` (issue #265)
* Fixed `unsigned long` printed as `signed long` (issue #170)
v5.2.0
------
* Added `JsonVariant::as<char*>()` as a synonym for `JsonVariant::as<const char*>()` (issue #257)
* Added example `JsonHttpClient` (issue #256)
* Added `JsonArray::copyTo()` and `JsonArray::copyFrom()` (issue #254)
* Added `RawJson()` to insert pregenerated JSON portions (issue #259)
v5.1.1
------
* Removed `String` duplication when one replaces a value in a `JsonObject` (PR #232 by @ulion)
v5.1.0
------

View File

@ -5,7 +5,7 @@
# https://github.com/bblanchon/ArduinoJson
# If you like this project, please add a star!
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 2.8.12)
project(ArduinoJson)
enable_testing()
@ -18,4 +18,5 @@ if(${COVERAGE})
set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
endif()
add_subdirectory(src)
add_subdirectory(test)

View File

@ -15,24 +15,21 @@ Features
* JSON decoding (comments are supported)
* JSON encoding (with optional indentation)
* Elegant API, very easy to use
* Fixed memory allocation (zero malloc)
* No data duplication (zero copy)
* Efficient (no malloc, nor copy)
* Portable (written in C++98)
* Self-contained (no external dependency)
* Small footprint
* Header-only library
* MIT License
Works on
--------
* All Arduino boards (Uno, Due, Mini, Micro, Yun...)
* All Arduino boards
* ESP8266
* Teensy
* Intel Edison and Galileo
* Intel Edison
* PlatformIO
* Energia
* RedBearLab boards (BLE Nano...)
* Computers (Windows, Linux, OSX...)
See [FAQ: Compatibility issues](https://github.com/bblanchon/ArduinoJson/wiki/Compatibility-issues)
@ -93,37 +90,31 @@ 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.
> I am just starting an ESP8266 clock project and now I can output JSON from my server script and interpret it painlessly.
Donators
--------
Special thanks to the following persons and companies who made generous donations to the library author:
* Robert Murphy <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
* Surge Communications <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
* Alex Scott <img alt='United Kingdom' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1ec-1f1e7.svg' width='18' height='18'>
* Firepick Services LLC <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
* A B Doodkorte <img alt='Netherlands' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1f1.svg' width='18' height='18'>
* Scott Smith <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
* Johann Stieger <img alt='Austria' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1e6-1f1f9.svg' width='18' height='18'>
* Gustavo Donizeti Gini <img alt='Brazil' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1e7-1f1f7.svg' width='18' height='18'>
* Charles-Henri Hallard <img alt='France' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1eb-1f1f7.svg' width='18' height='18'>
* Martijn van den Burg <img alt='Netherlands' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1f1.svg' width='18' height='18'>
* Nick Koumaris <img alt='Greece' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1ec-1f1f7.svg' width='18' height='18'>
* Jon Williams <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
* Kestutis Liaugminas <img alt='Lithuania' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f1-1f1f9.svg' width='18' height='18'>
* Robert Murphy
* Surge Communications
* Alex Scott
* Firepick Services LLC
* A B Doodkorte
* Scott Smith
* Johann Stieger
---

View File

@ -1,18 +0,0 @@
version: 5.6.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,195 +0,0 @@
// Sample Arduino Json Web Client
// Downloads and parse http://jsonplaceholder.typicode.com/users/1
//
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <ArduinoJson.h>
#include <SPI.h>
#include <Ethernet.h>
EthernetClient client;
const char* server = "jsonplaceholder.typicode.com"; // server's address
const char* resource = "/users/1"; // http resource
const unsigned long BAUD_RATE = 9600; // serial connection speed
const unsigned long HTTP_TIMEOUT = 10000; // max respone time from server
const size_t MAX_CONTENT_SIZE = 512; // max size of the HTTP response
// The type of data that we want to extract from the page
struct UserData {
char name[32];
char company[32];
};
// ARDUINO entry point #1: runs once when you press reset or power the board
void setup() {
initSerial();
initEthernet();
}
// ARDUINO entry point #2: runs over and over again forever
void loop() {
if (connect(server)) {
if (sendRequest(server, resource) && skipResponseHeaders()) {
char response[MAX_CONTENT_SIZE];
readReponseContent(response, sizeof(response));
UserData userData;
if (parseUserData(response, &userData)) {
printUserData(&userData);
}
}
disconnect();
}
wait();
}
// Initialize Serial port
void initSerial() {
Serial.begin(BAUD_RATE);
while (!Serial) {
; // wait for serial port to initialize
}
Serial.println("Serial ready");
}
// Initialize Ethernet library
void initEthernet() {
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
if (!Ethernet.begin(mac)) {
Serial.println("Failed to configure Ethernet");
return;
}
Serial.println("Ethernet ready");
delay(1000);
}
// Open connection to the HTTP server
bool connect(const char* hostName) {
Serial.print("Connect to ");
Serial.println(hostName);
bool ok = client.connect(hostName, 80);
Serial.println(ok ? "Connected" : "Connection Failed!");
return ok;
}
// Send the HTTP GET request to the server
bool sendRequest(const char* host, const char* resource) {
Serial.print("GET ");
Serial.println(resource);
client.print("GET ");
client.print(resource);
client.println(" HTTP/1.1");
client.print("Host: ");
client.println(server);
client.println("Connection: close");
client.println();
return true;
}
// Skip HTTP headers so that we are at the beginning of the response's body
bool skipResponseHeaders() {
// HTTP headers end with an empty line
char endOfHeaders[] = "\r\n\r\n";
client.setTimeout(HTTP_TIMEOUT);
bool ok = client.find(endOfHeaders);
if (!ok) {
Serial.println("No response or invalid response!");
}
return ok;
}
// Read the body of the response from the HTTP server
void readReponseContent(char* content, size_t maxSize) {
size_t length = client.readBytes(content, maxSize);
content[length] = 0;
Serial.println(content);
}
// Parse the JSON from the input string and extract the interesting values
// Here is the JSON we need to parse
// {
// "id": 1,
// "name": "Leanne Graham",
// "username": "Bret",
// "email": "Sincere@april.biz",
// "address": {
// "street": "Kulas Light",
// "suite": "Apt. 556",
// "city": "Gwenborough",
// "zipcode": "92998-3874",
// "geo": {
// "lat": "-37.3159",
// "lng": "81.1496"
// }
// },
// "phone": "1-770-736-8031 x56442",
// "website": "hildegard.org",
// "company": {
// "name": "Romaguera-Crona",
// "catchPhrase": "Multi-layered client-server neural-net",
// "bs": "harness real-time e-markets"
// }
// }
bool parseUserData(char* content, struct UserData* userData) {
// Compute optimal size of the JSON buffer according to what we need to parse.
// This is only required if you use StaticJsonBuffer.
const size_t BUFFER_SIZE =
JSON_OBJECT_SIZE(8) // the root object has 8 elements
+ JSON_OBJECT_SIZE(5) // the "address" object has 5 elements
+ JSON_OBJECT_SIZE(2) // the "geo" object has 2 elements
+ JSON_OBJECT_SIZE(3); // the "company" object has 3 elements
// Allocate a temporary memory pool on the stack
StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
// If the memory pool is too big for the stack, use this instead:
// DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(content);
if (!root.success()) {
Serial.println("JSON parsing failed!");
return false;
}
// Here were copy the strings we're interested in
strcpy(userData->name, root["name"]);
strcpy(userData->company, root["company"]["name"]);
// It's not mandatory to make a copy, you could just use the pointers
// Since, they are pointing inside the "content" buffer, so you need to make
// sure it's still in memory when you read the string
return true;
}
// Print the data extracted from the JSON
void printUserData(const struct UserData* userData) {
Serial.print("Name = ");
Serial.println(userData->name);
Serial.print("Company = ");
Serial.println(userData->company);
}
// Close the connection with the HTTP server
void disconnect() {
Serial.println("Disconnect");
client.stop();
}
// Pause for a 1 minute
void wait() {
Serial.println("Wait 60 seconds");
delay(60000);
}

View File

@ -5,5 +5,9 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "ArduinoJson.hpp"
#include "ArduinoJson/DynamicJsonBuffer.hpp"
#include "ArduinoJson/JsonArray.hpp"
#include "ArduinoJson/JsonObject.hpp"
#include "ArduinoJson/StaticJsonBuffer.hpp"
using namespace ArduinoJson;

View File

@ -1,21 +0,0 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "ArduinoJson/DynamicJsonBuffer.hpp"
#include "ArduinoJson/JsonArray.hpp"
#include "ArduinoJson/JsonObject.hpp"
#include "ArduinoJson/StaticJsonBuffer.hpp"
#include "ArduinoJson/Internals/JsonParser.ipp"
#include "ArduinoJson/JsonArray.ipp"
#include "ArduinoJson/JsonBuffer.ipp"
#include "ArduinoJson/JsonObject.ipp"
#include "ArduinoJson/JsonVariant.ipp"
using namespace ArduinoJson;

View File

@ -0,0 +1,61 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#ifndef ARDUINO
#include "../TypeTraits/EnableIf.hpp"
#include "../TypeTraits/IsIntegral.hpp"
#include <stddef.h>
#include <stdint.h>
// This class reproduces Arduino's Print class
class Print {
public:
virtual ~Print() {}
virtual size_t write(uint8_t) = 0;
size_t print(const char[]);
size_t print(double, int = 2);
template <typename TIntegral>
typename ArduinoJson::TypeTraits::EnableIf<
ArduinoJson::TypeTraits::IsIntegral<TIntegral>::value, size_t>::type
print(TIntegral value) {
// see http://clc-wiki.net/wiki/K%26R2_solutions:Chapter_3:Exercise_4
char buffer[22];
size_t n = 0;
if (value < 0) {
value = -value;
n += write('-');
}
uint8_t i = 0;
do {
TIntegral digit = value % 10;
value /= 10;
buffer[i++] = static_cast<char>(digit >= 0 ? '0' + digit : '0' - digit);
} while (value);
while (i > 0) {
n += write(buffer[--i]);
}
return n;
}
size_t println();
};
#else
#include <Print.h>
#endif

View File

@ -7,18 +7,13 @@
#pragma once
#include "Configuration.hpp"
#ifndef ARDUINO
#if ARDUINOJSON_USE_ARDUINO_STRING
#include <WString.h>
#include <string>
typedef std::string String;
#else
#include <string>
namespace ArduinoJson {
typedef std::string String;
}
#include <WString.h>
#endif

View File

@ -22,11 +22,6 @@
#define ARDUINOJSON_USE_INT64 0
#endif
// arduino has its own implementation of String to replace std::string
#ifndef ARDUINOJSON_USE_ARDUINO_STRING
#define ARDUINOJSON_USE_ARDUINO_STRING 1
#endif
// arduino doesn't support STL stream
#ifndef ARDUINOJSON_ENABLE_STD_STREAM
#define ARDUINOJSON_ENABLE_STD_STREAM 0
@ -67,11 +62,6 @@
#endif
#endif
// on a computer, we can use std::string
#ifndef ARDUINOJSON_USE_ARDUINO_STRING
#define ARDUINOJSON_USE_ARDUINO_STRING 0
#endif
// on a computer, we can assume that the STL is there
#ifndef ARDUINOJSON_ENABLE_STD_STREAM
#define ARDUINOJSON_ENABLE_STD_STREAM 1

View File

@ -11,26 +11,12 @@
#include <stdlib.h>
#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 Internals {
class DefaultAllocator {
public:
void* allocate(size_t size) {
return malloc(size);
}
void deallocate(void* pointer) {
free(pointer);
}
void* allocate(size_t size) { return malloc(size); }
void deallocate(void* pointer) { free(pointer); }
};
template <typename TAllocator>
@ -65,6 +51,7 @@ class BlockJsonBuffer : public JsonBuffer {
return total;
}
protected:
virtual void* alloc(size_t bytes) {
return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
}
@ -105,11 +92,3 @@ class BlockJsonBuffer : public 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

@ -9,48 +9,6 @@
namespace ArduinoJson {
namespace Internals {
inline const char *skipCStyleComment(const char *ptr) {
ptr += 2;
for (;;) {
if (ptr[0] == '\0') return ptr;
if (ptr[0] == '*' && ptr[1] == '/') return ptr + 2;
ptr++;
}
}
inline const char *skipCppStyleComment(const char *ptr) {
ptr += 2;
for (;;) {
if (ptr[0] == '\0' || ptr[0] == '\n') return ptr;
ptr++;
}
}
inline const char *skipSpacesAndComments(const char *ptr) {
for (;;) {
switch (ptr[0]) {
case ' ':
case '\t':
case '\r':
case '\n':
ptr++;
continue;
case '/':
switch (ptr[1]) {
case '*':
ptr = skipCStyleComment(ptr);
break;
case '/':
ptr = skipCppStyleComment(ptr);
break;
default:
return ptr;
}
break;
default:
return ptr;
}
}
}
const char *skipSpacesAndComments(const char *ptr);
}
}

View File

@ -7,7 +7,7 @@
#pragma once
#include "../Print.hpp"
#include "../Arduino/Print.hpp"
namespace ArduinoJson {
namespace Internals {

View File

@ -7,8 +7,8 @@
#pragma once
#include "../Print.hpp"
#include "../String.hpp"
#include "../Arduino/Print.hpp"
#include "../Arduino/String.hpp"
namespace ArduinoJson {
namespace Internals {

View File

@ -7,7 +7,7 @@
#pragma once
#include "../Print.hpp"
#include "../Arduino/Print.hpp"
namespace ArduinoJson {
namespace Internals {
@ -16,7 +16,7 @@ class Encoding {
public:
// Optimized for code size on a 8-bit AVR
static char escapeChar(char c) {
const char *p = escapeTable(false);
const char *p = _escapeTable;
while (p[0] && p[1] != c) {
p += 2;
}
@ -25,7 +25,7 @@ class Encoding {
// Optimized for code size on a 8-bit AVR
static char unescapeChar(char c) {
const char *p = escapeTable(true);
const char *p = _escapeTable + 4;
for (;;) {
if (p[0] == '\0') return c;
if (p[0] == c) return p[1];
@ -34,9 +34,7 @@ class Encoding {
}
private:
static const char *escapeTable(bool excludeIdenticals) {
return &"\"\"\\\\b\bf\fn\nr\rt\t"[excludeIdenticals ? 4 : 0];
}
static const char _escapeTable[];
};
}
}

View File

@ -9,8 +9,6 @@
#ifdef _MSC_VER
#define FORCE_INLINE __forceinline
#define NO_INLINE __declspec(noinline)
#else
#define FORCE_INLINE __attribute__((always_inline))
#define NO_INLINE __attribute__((noinline))
#endif

View File

@ -7,7 +7,7 @@
#pragma once
#include "../Print.hpp"
#include "../Arduino/Print.hpp"
namespace ArduinoJson {
namespace Internals {
@ -23,13 +23,7 @@ class IndentedPrint : public Print {
isNewLine = true;
}
virtual size_t write(uint8_t c) {
size_t n = 0;
if (isNewLine) n += writeTabs();
n += sink->write(c);
isNewLine = c == '\n';
return n;
}
virtual size_t write(uint8_t);
// Adds one level of indentation
void indent() {
@ -52,11 +46,7 @@ class IndentedPrint : public Print {
uint8_t tabSize : 3;
bool isNewLine : 1;
size_t writeTabs() {
size_t n = 0;
for (int i = 0; i < level * tabSize; i++) n += sink->write(' ');
return n;
}
size_t writeTabs();
static const int MAX_LEVEL = 15; // because it's only 4 bits
static const int MAX_TAB_SIZE = 7; // because it's only 3 bits

View File

@ -14,13 +14,10 @@ namespace Internals {
#if ARDUINOJSON_USE_LONG_LONG
typedef long long JsonInteger;
typedef unsigned long long JsonUInt;
#elif ARDUINOJSON_USE_INT64
typedef __int64 JsonInteger;
typedef unsigned _int64 JsonUInt;
#else
typedef long JsonInteger;
typedef unsigned long JsonUInt;
#endif
}
}

View File

@ -27,12 +27,6 @@ class JsonParser {
JsonArray &parseArray();
JsonObject &parseObject();
JsonVariant parseVariant() {
JsonVariant result;
parseAnythingTo(&result);
return result;
}
private:
bool skip(char charToSkip);
@ -44,19 +38,6 @@ class JsonParser {
inline bool parseObjectTo(JsonVariant *destination);
inline bool parseStringTo(JsonVariant *destination);
static inline bool isInRange(char c, char min, char max) {
return min <= c && c <= max;
}
static inline bool isLetterOrNumber(char c) {
return isInRange(c, '0', '9') || isInRange(c, 'a', 'z') ||
isInRange(c, 'A', 'Z') || c == '-' || c == '.';
}
static inline bool isQuote(char c) {
return c == '\'' || c == '\"';
}
JsonBuffer *_buffer;
const char *_readPtr;
char *_writePtr;

View File

@ -1,45 +0,0 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
namespace ArduinoJson {
namespace Internals {
// A metafunction that returns the type of the value returned by
// JsonVariant::as<T>()
template <typename T>
struct JsonVariantAs {
typedef T type;
};
template <>
struct JsonVariantAs<char*> {
typedef const char* type;
};
template <>
struct JsonVariantAs<JsonArray> {
typedef JsonArray& type;
};
template <>
struct JsonVariantAs<const JsonArray> {
typedef const JsonArray& type;
};
template <>
struct JsonVariantAs<JsonObject> {
typedef JsonObject& type;
};
template <>
struct JsonVariantAs<const JsonObject> {
typedef const JsonObject& type;
};
}
}

View File

@ -20,11 +20,11 @@ namespace Internals {
// A union that defines the actual content of a JsonVariant.
// The enum JsonVariantType determines which member is in use.
union JsonVariantContent {
JsonFloat asFloat; // used for double and float
JsonUInt asInteger; // used for bool, char, short, int and longs
const char* asString; // asString can be null
JsonArray* asArray; // asArray cannot be null
JsonObject* asObject; // asObject cannot be null
JsonFloat asFloat; // used for double and float
JsonInteger asInteger; // used for bool, char, short, int and longs
const char* asString; // asString can be null
JsonArray* asArray; // asArray cannot be null
JsonObject* asObject; // asObject cannot be null
};
}
}

View File

@ -16,15 +16,13 @@ namespace Internals {
// Enumerated type to know the current type of a JsonVariant.
// The value determines which member of JsonVariantContent is used.
enum JsonVariantType {
JSON_UNDEFINED, // JsonVariant has not been initialized
JSON_UNPARSED, // JsonVariant contains an unparsed string
JSON_STRING, // JsonVariant stores a const char*
JSON_BOOLEAN, // JsonVariant stores a bool
JSON_POSITIVE_INTEGER, // JsonVariant stores an unsigned long
JSON_NEGATIVE_INTEGER, // JsonVariant stores an unsigned long that must be
// negated
JSON_ARRAY, // JsonVariant stores a pointer to a JsonArray
JSON_OBJECT, // JsonVariant stores a pointer to a JsonObject
JSON_UNDEFINED, // the JsonVariant has not been initialized
JSON_UNPARSED, // the JsonVariant contains an unparsed string
JSON_STRING, // the JsonVariant stores a const char*
JSON_BOOLEAN, // the JsonVariant stores a bool
JSON_INTEGER, // the JsonVariant stores an integer
JSON_ARRAY, // the JsonVariant stores a pointer to a JsonArray
JSON_OBJECT, // the JsonVariant stores a pointer to a JsonObject
// The following values are reserved for float values
// Multiple values are used for double, depending on the number of decimal

View File

@ -7,11 +7,9 @@
#pragma once
#include "../Polyfills/attributes.hpp"
#include "../Polyfills/math.hpp"
#include "../Polyfills/normalize.hpp"
#include "../Print.hpp"
#include "../Arduino/Print.hpp"
#include "Encoding.hpp"
#include "ForceInline.hpp"
#include "JsonFloat.hpp"
#include "JsonInteger.hpp"
@ -32,129 +30,51 @@ class JsonWriter {
// Returns the number of bytes sent to the Print implementation.
// This is very handy for implementations of printTo() that must return the
// number of bytes written.
size_t bytesWritten() const {
return _length;
}
size_t bytesWritten() const { return _length; }
void beginArray() {
writeRaw('[');
}
void endArray() {
writeRaw(']');
}
void beginArray() { write('['); }
void endArray() { write(']'); }
void beginObject() {
writeRaw('{');
}
void endObject() {
writeRaw('}');
}
void beginObject() { write('{'); }
void endObject() { write('}'); }
void writeColon() {
writeRaw(':');
}
void writeComma() {
writeRaw(',');
}
void writeColon() { write(':'); }
void writeComma() { write(','); }
void writeBoolean(bool value) {
writeRaw(value ? "true" : "false");
}
void writeBoolean(bool value) { write(value ? "true" : "false"); }
void writeString(const char *value) {
if (!value) {
writeRaw("null");
write("null");
} else {
writeRaw('\"');
write('\"');
while (*value) writeChar(*value++);
writeRaw('\"');
write('\"');
}
}
void writeChar(char c) {
char specialChar = Encoding::escapeChar(c);
if (specialChar) {
writeRaw('\\');
writeRaw(specialChar);
write('\\');
write(specialChar);
} else {
writeRaw(c);
write(c);
}
}
void writeFloat(JsonFloat value, int digits = 2) {
if (Polyfills::isNaN(value)) return writeRaw("NaN");
void writeInteger(JsonInteger value) { _length += _sink.print(value); }
if (value < 0.0) {
writeRaw('-');
value = -value;
}
if (Polyfills::isInfinity(value)) return writeRaw("Infinity");
short powersOf10;
if (value > 1000 || value < 0.001) {
powersOf10 = Polyfills::normalize(value);
} else {
powersOf10 = 0;
}
// Extract the integer part of the value and print it
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);
// Round up last digit (so that print(1.999, 2) prints as "2.00")
if (digits == 0 && remainder >= 0.5) currentDigit++;
// Print
writeRaw(char('0' + currentDigit));
}
if (powersOf10 < 0) {
writeRaw("e-");
writeInteger(-powersOf10);
}
if (powersOf10 > 0) {
writeRaw('e');
writeInteger(powersOf10);
}
void writeFloat(JsonFloat value, uint8_t decimals) {
_length += _sink.print(value, decimals);
}
void writeInteger(JsonUInt value) {
char buffer[22];
uint8_t i = 0;
do {
buffer[i++] = static_cast<char>(value % 10 + '0');
value /= 10;
} while (value);
while (i > 0) {
writeRaw(buffer[--i]);
}
}
void writeRaw(const char *s) {
_length += _sink.print(s);
}
void writeRaw(char c) {
_length += _sink.write(c);
}
void writeRaw(const char *s) { return write(s); }
protected:
void write(char c) { _length += _sink.write(c); }
FORCE_INLINE void write(const char *s) { _length += _sink.print(s); }
Print &_sink;
size_t _length;

View File

@ -36,56 +36,21 @@ class List {
// Would return false in the following situation:
// - the memory allocation failed (StaticJsonBuffer was too small)
// - the JSON parsing failed
bool success() const {
return _buffer != NULL;
}
bool success() const { return _buffer != NULL; }
// Returns the numbers of elements in the list.
// For a JsonObject, it would return the number of key-value pairs
size_t size() const {
size_t nodeCount = 0;
for (node_type *node = _firstNode; node; node = node->next) nodeCount++;
return nodeCount;
}
size_t size() const;
iterator begin() {
return iterator(_firstNode);
}
iterator end() {
return iterator(NULL);
}
iterator begin() { return iterator(_firstNode); }
iterator end() { return iterator(NULL); }
const_iterator begin() const {
return const_iterator(_firstNode);
}
const_iterator end() const {
return const_iterator(NULL);
}
const_iterator begin() const { return const_iterator(_firstNode); }
const_iterator end() const { return const_iterator(NULL); }
protected:
node_type *addNewNode() {
node_type *newNode = new (_buffer) node_type();
if (_firstNode) {
node_type *lastNode = _firstNode;
while (lastNode->next) lastNode = lastNode->next;
lastNode->next = newNode;
} else {
_firstNode = newNode;
}
return newNode;
}
void removeNode(node_type *nodeToRemove) {
if (!nodeToRemove) return;
if (nodeToRemove == _firstNode) {
_firstNode = nodeToRemove->next;
} else {
for (node_type *node = _firstNode; node; node = node->next)
if (node->next == nodeToRemove) node->next = nodeToRemove->next;
}
}
node_type *addNewNode();
void removeNode(node_type *nodeToRemove);
JsonBuffer *_buffer;
node_type *_firstNode;

View File

@ -29,11 +29,6 @@ inline long parse<long>(const char *s) {
return strtol(s, NULL, 10);
}
template <>
inline unsigned long parse<unsigned long>(const char *s) {
return strtoul(s, NULL, 10);
}
template <>
inline int parse<int>(const char *s) {
return atoi(s);
@ -44,11 +39,6 @@ template <>
inline long long parse<long long>(const char *s) {
return strtoll(s, NULL, 10);
}
template <>
inline unsigned long long parse<unsigned long long>(const char *s) {
return strtoull(s, NULL, 10);
}
#endif
#if ARDUINOJSON_USE_INT64
@ -56,11 +46,6 @@ template <>
inline __int64 parse<__int64>(const char *s) {
return _strtoi64(s, NULL, 10);
}
template <>
inline unsigned __int64 parse<unsigned __int64>(const char *s) {
return _strtoui64(s, NULL, 10);
}
#endif
}
}

View File

@ -20,89 +20,24 @@ class Prettyfier : public Print {
_inString = false;
}
virtual size_t write(uint8_t c) {
size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c);
_previousChar = c;
return n;
}
virtual size_t write(uint8_t);
private:
Prettyfier& operator=(const Prettyfier&); // cannot be assigned
bool inEmptyBlock() {
return _previousChar == '{' || _previousChar == '[';
}
bool inEmptyBlock() { return _previousChar == '{' || _previousChar == '['; }
size_t handleStringChar(uint8_t c) {
bool isQuote = c == '"' && _previousChar != '\\';
size_t handleStringChar(uint8_t);
size_t handleMarkupChar(uint8_t);
if (isQuote) _inString = false;
return _sink.write(c);
}
size_t handleMarkupChar(uint8_t c) {
switch (c) {
case '{':
case '[':
return writeBlockOpen(c);
case '}':
case ']':
return writeBlockClose(c);
case ':':
return writeColon();
case ',':
return writeComma();
case '"':
return writeQuoteOpen();
default:
return writeNormalChar(c);
}
}
size_t writeBlockClose(uint8_t c) {
return unindentIfNeeded() + _sink.write(c);
}
size_t writeBlockOpen(uint8_t c) {
return indentIfNeeded() + _sink.write(c);
}
size_t writeColon() {
return _sink.write(':') + _sink.write(' ');
}
size_t writeComma() {
return _sink.write(',') + _sink.println();
}
size_t writeQuoteOpen() {
_inString = true;
return indentIfNeeded() + _sink.write('"');
}
size_t writeNormalChar(uint8_t c) {
return indentIfNeeded() + _sink.write(c);
}
size_t indentIfNeeded() {
if (!inEmptyBlock()) return 0;
_sink.indent();
return _sink.println();
}
size_t unindentIfNeeded() {
if (inEmptyBlock()) return 0;
_sink.unindent();
return _sink.println();
}
size_t handleBlockClose(uint8_t);
size_t handleBlockOpen(uint8_t);
size_t handleColon();
size_t handleComma();
size_t handleQuoteOpen();
size_t handleNormalChar(uint8_t);
size_t indentIfNeeded();
size_t unindentIfNeeded();
uint8_t _previousChar;
IndentedPrint& _sink;

View File

@ -7,7 +7,7 @@
#pragma once
#include "../Print.hpp"
#include "../Arduino/Print.hpp"
namespace ArduinoJson {
namespace Internals {
@ -20,13 +20,7 @@ class StaticStringBuilder : public Print {
buffer[0] = '\0';
}
virtual size_t write(uint8_t c) {
if (length >= capacity) return 0;
buffer[length++] = c;
buffer[length] = '\0';
return 1;
}
virtual size_t write(uint8_t c);
private:
char *buffer;

View File

@ -11,7 +11,7 @@
#if ARDUINOJSON_ENABLE_STD_STREAM
#include "../Print.hpp"
#include "../Arduino/Print.hpp"
#include <ostream>

View File

@ -8,14 +8,14 @@
#pragma once
namespace ArduinoJson {
// A special type of data that can be used to insert pregenerated JSON portions.
class RawJson {
namespace Internals {
class Unparsed {
public:
explicit RawJson(const char* str) : _str(str) {}
explicit Unparsed(const char* str) : _str(str) {}
operator const char*() const { return _str; }
private:
const char* _str;
};
}
}

View File

@ -12,10 +12,6 @@
#include "Internals/List.hpp"
#include "Internals/ReferenceType.hpp"
#include "JsonVariant.hpp"
#include "TypeTraits/EnableIf.hpp"
#include "TypeTraits/IsFloatingPoint.hpp"
#include "TypeTraits/IsReference.hpp"
#include "TypeTraits/IsSame.hpp"
// Returns the size (in bytes) of an array with n elements.
// Can be very handy to determine the size of a StaticJsonBuffer.
@ -56,12 +52,10 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
: Internals::List<JsonVariant>(buffer) {}
// Gets the value at the specified index
JsonVariant operator[](size_t index) const {
return get(index);
}
FORCE_INLINE JsonVariant operator[](size_t index) const;
// Gets or sets the value at specified index
JsonArraySubscript operator[](size_t index);
FORCE_INLINE JsonArraySubscript operator[](size_t index);
// Adds the specified value at the end of the array.
//
@ -74,10 +68,9 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
// bool add(double value);
// bool add(const char*);
template <typename T>
bool add(
FORCE_INLINE bool add(
T value,
typename TypeTraits::EnableIf<
CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) {
typename TypeTraits::EnableIf<CanSet<T>::value, void>::type * = 0) {
return addNode<T>(value);
}
// bool add(const String&)
@ -85,16 +78,18 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
// bool add(JsonArray&);
// bool add(JsonObject&);
template <typename T>
bool add(const T &value,
typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) {
FORCE_INLINE bool add(
const T &value,
typename TypeTraits::EnableIf<CanSet<T &>::value, T>::type * = 0) {
return addNode<T &>(const_cast<T &>(value));
}
// bool add(float value, uint8_t decimals);
// bool add(double value, uint8_t decimals);
template <typename T>
bool add(T value, uint8_t decimals,
typename TypeTraits::EnableIf<
TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
FORCE_INLINE bool add(
T value,
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
uint8_t>::type decimals) {
return addNode<JsonVariant>(JsonVariant(value, decimals));
}
@ -105,10 +100,9 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
// bool set(size_t index, int value);
// bool set(size_t index, short value);
template <typename T>
bool set(
FORCE_INLINE bool set(
size_t index, T value,
typename TypeTraits::EnableIf<
CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) {
typename TypeTraits::EnableIf<CanSet<T>::value, void>::type * = 0) {
return setNodeAt<T>(index, value);
}
// bool set(size_t index, const String&)
@ -116,38 +110,31 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
// bool set(size_t index, JsonArray&);
// bool set(size_t index, JsonObject&);
template <typename T>
bool set(size_t index, const T &value,
typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) {
FORCE_INLINE bool set(
size_t index, const T &value,
typename TypeTraits::EnableIf<CanSet<T &>::value, T>::type * = 0) {
return setNodeAt<T &>(index, const_cast<T &>(value));
}
// bool set(size_t index, float value, uint8_t decimals = 2);
// bool set(size_t index, double value, uint8_t decimals = 2);
template <typename T>
bool set(size_t index, T value, uint8_t decimals,
typename TypeTraits::EnableIf<
TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
FORCE_INLINE bool set(
size_t index, T value,
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
uint8_t>::type decimals) {
return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals));
}
// Gets the value at the specified index.
JsonVariant get(size_t index) const {
node_type *node = getNodeAt(index);
return node ? node->content : JsonVariant();
}
FORCE_INLINE JsonVariant get(size_t index) const;
// Gets the value at the specified index.
template <typename T>
typename Internals::JsonVariantAs<T>::type get(size_t index) const {
node_type *node = getNodeAt(index);
return node ? node->content.as<T>() : JsonVariant::defaultValue<T>();
}
FORCE_INLINE T get(size_t index) const;
// Check the type of the value at specified index.
template <typename T>
bool is(size_t index) const {
node_type *node = getNodeAt(index);
return node ? node->content.is<T>() : false;
}
FORCE_INLINE bool is(size_t index) const;
// Creates a JsonArray and adds a reference at the end of the array.
// It's a shortcut for JsonBuffer::createArray() and JsonArray::add()
@ -158,111 +145,31 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
JsonObject &createNestedObject();
// Removes element at specified index.
void removeAt(size_t index) {
removeNode(getNodeAt(index));
}
void removeAt(size_t index);
// Returns a reference an invalid JsonArray.
// This object is meant to replace a NULL pointer.
// This is used when memory allocation or JSON parsing fail.
static JsonArray &invalid() {
static JsonArray instance(NULL);
return instance;
}
static JsonArray &invalid() { return _invalid; }
// Serialize the array to the specified JsonWriter.
void writeTo(Internals::JsonWriter &writer) const {
writer.beginArray();
const node_type *child = _firstNode;
while (child) {
child->content.writeTo(writer);
child = child->next;
if (!child) break;
writer.writeComma();
}
writer.endArray();
}
// Imports a 1D array
template <typename T, size_t N>
bool copyFrom(T(&array)[N]) {
return copyFrom(array, N);
}
// Imports a 1D array
template <typename T>
bool copyFrom(T *array, size_t len) {
bool ok = true;
for (size_t i = 0; i < len; i++) {
ok &= add(array[i]);
}
return ok;
}
// Imports a 2D array
template <typename T, size_t N1, size_t N2>
bool copyFrom(T(&array)[N1][N2]) {
bool ok = true;
for (size_t i = 0; i < N1; i++) {
JsonArray &nestedArray = createNestedArray();
for (size_t j = 0; j < N2; j++) {
ok &= nestedArray.add(array[i][j]);
}
}
return ok;
}
// Exports a 1D array
template <typename T, size_t N>
size_t copyTo(T(&array)[N]) const {
return copyTo(array, N);
}
// Exports a 1D array
template <typename T>
size_t copyTo(T *array, size_t len) const {
size_t i = 0;
for (const_iterator it = begin(); it != end() && i < len; ++it)
array[i++] = *it;
return i;
}
// Exports a 2D array
template <typename T, size_t N1, size_t N2>
void copyTo(T(&array)[N1][N2]) const {
size_t i = 0;
for (const_iterator it = begin(); it != end() && i < N1; ++it) {
it->asArray().copyTo(array[i++]);
}
}
void writeTo(Internals::JsonWriter &writer) const;
private:
node_type *getNodeAt(size_t index) const {
node_type *node = _firstNode;
while (node && index--) node = node->next;
return node;
}
node_type *getNodeAt(size_t index) const;
template <typename TValue>
bool setNodeAt(size_t index, TValue value) {
node_type *node = getNodeAt(index);
return node != NULL && setNodeValue<TValue>(node, value);
}
bool setNodeAt(size_t index, TValue value);
template <typename TValue>
bool addNode(TValue value) {
node_type *node = addNewNode();
return node != NULL && setNodeValue<TValue>(node, value);
}
bool addNode(TValue);
template <typename T>
bool setNodeValue(node_type *node, T value) {
node->content = value;
return true;
}
FORCE_INLINE bool setNodeValue(node_type *, T value);
// The instance returned by JsonArray::invalid()
static JsonArray _invalid;
};
}
#include "JsonArray.ipp"

View File

@ -13,6 +13,32 @@
namespace ArduinoJson {
inline JsonArraySubscript JsonArray::operator[](size_t index) {
return JsonArraySubscript(*this, index);
}
inline JsonVariant JsonArray::operator[](size_t index) const {
return get(index);
}
template <typename TValue>
inline bool JsonArray::addNode(TValue value) {
node_type *node = addNewNode();
return node != NULL && setNodeValue<TValue>(node, value);
}
template <typename TValue>
inline bool JsonArray::setNodeAt(size_t index, TValue value) {
node_type *node = getNodeAt(index);
return node != NULL && setNodeValue<TValue>(node, value);
}
template <typename TValue>
inline bool JsonArray::setNodeValue(node_type *node, TValue value) {
node->content = value;
return true;
}
template <>
inline bool JsonArray::setNodeValue(node_type *node, String &value) {
const char *copy = _buffer->strdup(value);
@ -21,23 +47,36 @@ inline bool JsonArray::setNodeValue(node_type *node, String &value) {
return true;
}
inline JsonVariant JsonArray::get(size_t index) const {
node_type *node = getNodeAt(index);
return node ? node->content : JsonVariant();
}
template <typename T>
inline T JsonArray::get(size_t index) const {
node_type *node = getNodeAt(index);
return node ? node->content.as<T>() : JsonVariant::invalid<T>();
}
template <typename T>
inline bool JsonArray::is(size_t index) const {
node_type *node = getNodeAt(index);
return node ? node->content.is<T>() : false;
}
template <typename TImplem>
inline const JsonArraySubscript JsonVariantBase<TImplem>::operator[](
int index) const {
return asArray()[index];
}
template <>
inline JsonArray &JsonVariant::defaultValue<JsonArray>() {
inline JsonArray &JsonVariant::invalid<JsonArray &>() {
return JsonArray::invalid();
}
template <>
inline JsonArray &JsonVariant::defaultValue<JsonArray &>() {
return JsonArray::invalid();
}
template <>
inline const JsonArray &JsonVariant::defaultValue<const JsonArray>() {
return JsonArray::invalid();
}
template <>
inline const JsonArray &JsonVariant::defaultValue<const JsonArray &>() {
inline JsonArray const &JsonVariant::invalid<JsonArray const &>() {
return JsonArray::invalid();
}

View File

@ -42,16 +42,12 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
return *this;
}
FORCE_INLINE bool success() const {
return _index < _array.size();
}
FORCE_INLINE bool success() const { return _index < _array.size(); }
FORCE_INLINE operator JsonVariant() const {
return _array.get(_index);
}
FORCE_INLINE operator JsonVariant() const { return _array.get(_index); }
template <typename T>
FORCE_INLINE typename Internals::JsonVariantAs<T>::type as() const {
FORCE_INLINE T as() const {
return _array.get<T>(_index);
}
@ -81,15 +77,10 @@ inline std::ostream& operator<<(std::ostream& os,
}
#endif
inline JsonArraySubscript JsonArray::operator[](size_t index) {
return JsonArraySubscript(*this, index);
}
template <typename TImplem>
inline const JsonArraySubscript JsonVariantBase<TImplem>::operator[](
int index) const {
return asArray()[index];
}
template <>
struct JsonVariant::IsConstructibleFrom<JsonArraySubscript> {
static const bool value = true;
};
} // namespace ArduinoJson

View File

@ -11,16 +11,12 @@
#include <stdint.h> // for uint8_t
#include <string.h>
#include "Arduino/String.hpp"
#include "JsonVariant.hpp"
#include "String.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
@ -98,21 +94,6 @@ class JsonBuffer {
return parseObject(json.c_str(), nesting);
}
// Generalized version of parseArray() and parseObject(), also works for
// integral types.
JsonVariant parse(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
// Same with a const char*.
// With this overload, the JsonBuffer will make a copy of the string
JsonVariant parse(const char *json, uint8_t nesting = DEFAULT_LIMIT) {
return parse(strdup(json), nesting);
}
// Same as above with a String class
JsonVariant parse(const String &json, uint8_t nesting = DEFAULT_LIMIT) {
return parse(json.c_str(), nesting);
}
// Duplicate a string
char *strdup(const char *src) {
return src ? strdup(src, strlen(src)) : NULL;
@ -153,11 +134,3 @@ class JsonBuffer {
static const uint8_t DEFAULT_LIMIT = 10;
};
}
#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

@ -1,46 +0,0 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "Internals/JsonParser.hpp"
inline ArduinoJson::JsonArray &ArduinoJson::JsonBuffer::createArray() {
JsonArray *ptr = new (this) JsonArray(this);
return ptr ? *ptr : JsonArray::invalid();
}
inline ArduinoJson::JsonObject &ArduinoJson::JsonBuffer::createObject() {
JsonObject *ptr = new (this) JsonObject(this);
return ptr ? *ptr : JsonObject::invalid();
}
inline ArduinoJson::JsonArray &ArduinoJson::JsonBuffer::parseArray(
char *json, uint8_t nestingLimit) {
Internals::JsonParser parser(this, json, nestingLimit);
return parser.parseArray();
}
inline ArduinoJson::JsonObject &ArduinoJson::JsonBuffer::parseObject(
char *json, uint8_t nestingLimit) {
Internals::JsonParser parser(this, json, nestingLimit);
return parser.parseObject();
}
inline ArduinoJson::JsonVariant ArduinoJson::JsonBuffer::parse(
char *json, uint8_t nestingLimit) {
Internals::JsonParser parser(this, json, nestingLimit);
return parser.parseVariant();
}
inline char *ArduinoJson::JsonBuffer::strdup(const char *source,
size_t length) {
size_t size = length + 1;
char *dest = static_cast<char *>(alloc(size));
if (dest != NULL) memcpy(dest, source, size);
return dest;
}

View File

@ -7,16 +7,12 @@
#pragma once
#include "String.hpp"
#include "Arduino/String.hpp"
#include "Internals/JsonBufferAllocated.hpp"
#include "Internals/JsonPrintable.hpp"
#include "Internals/List.hpp"
#include "Internals/ReferenceType.hpp"
#include "JsonPair.hpp"
#include "TypeTraits/EnableIf.hpp"
#include "TypeTraits/IsFloatingPoint.hpp"
#include "TypeTraits/IsReference.hpp"
#include "TypeTraits/IsSame.hpp"
// Returns the size (in bytes) of an object with n elements.
// Can be very handy to determine the size of a StaticJsonBuffer.
@ -52,16 +48,15 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
// Create an empty JsonArray attached to the specified JsonBuffer.
// You should not use this constructor directly.
// Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject().
explicit JsonObject(JsonBuffer* buffer) : Internals::List<JsonPair>(buffer) {}
FORCE_INLINE explicit JsonObject(JsonBuffer* buffer)
: Internals::List<JsonPair>(buffer) {}
// Gets or sets the value associated with the specified key.
JsonObjectSubscript<const char*> operator[](const char* key);
JsonObjectSubscript<const String&> operator[](const String& key);
FORCE_INLINE JsonObjectSubscript<const char*> operator[](const char* key);
FORCE_INLINE JsonObjectSubscript<const String&> operator[](const String& key);
// Gets the value associated with the specified key.
JsonVariant operator[](JsonObjectKey key) const {
return get(key);
}
FORCE_INLINE JsonVariant operator[](JsonObjectKey key) const;
// Sets the specified key with the specified value.
// bool set(TKey key, bool value);
@ -72,12 +67,10 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
// bool set(TKey key, float value);
// bool set(TKey key, double value);
// bool set(TKey key, const char* value);
// bool set(TKey key, RawJson value);
template <typename T>
bool set(
FORCE_INLINE bool set(
JsonObjectKey key, T value,
typename TypeTraits::EnableIf<
CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type* = 0) {
typename TypeTraits::EnableIf<CanSet<T>::value, void>::type* = 0) {
return setNodeAt<T>(key, value);
}
// bool set(Key, String&);
@ -85,117 +78,71 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
// bool set(Key, JsonObject&);
// bool set(Key, JsonVariant&);
template <typename T>
bool set(JsonObjectKey key, const T& value,
typename TypeTraits::EnableIf<CanSet<T&>::value>::type* = 0) {
FORCE_INLINE bool set(
JsonObjectKey key, const T& value,
typename TypeTraits::EnableIf<CanSet<T&>::value, T>::type* = 0) {
return setNodeAt<T&>(key, const_cast<T&>(value));
}
// bool set(Key, float value, uint8_t decimals);
// bool set(Key, double value, uint8_t decimals);
template <typename TValue>
bool set(JsonObjectKey key, TValue value, uint8_t decimals,
typename TypeTraits::EnableIf<
TypeTraits::IsFloatingPoint<TValue>::value>::type* = 0) {
FORCE_INLINE bool set(
JsonObjectKey key, TValue value,
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value,
uint8_t>::type decimals) {
return setNodeAt<const JsonVariant&>(key, JsonVariant(value, decimals));
}
// Gets the value associated with the specified key.
JsonVariant get(JsonObjectKey key) const {
node_type* node = getNodeAt(key.c_str());
return node ? node->content.value : JsonVariant();
}
FORCE_INLINE JsonVariant get(JsonObjectKey) const;
// Gets the value associated with the specified key.
template <typename T>
typename Internals::JsonVariantAs<T>::type get(JsonObjectKey key) const {
node_type* node = getNodeAt(key.c_str());
return node ? node->content.value.as<T>() : JsonVariant::defaultValue<T>();
}
FORCE_INLINE T get(JsonObjectKey) const;
// Checks the type of the value associated with the specified key.
template <typename T>
bool is(JsonObjectKey key) const {
node_type* node = getNodeAt(key.c_str());
return node ? node->content.value.is<T>() : false;
}
FORCE_INLINE bool is(JsonObjectKey) const;
// Creates and adds a JsonArray.
// This is a shortcut for JsonBuffer::createArray() and JsonObject::add().
JsonArray& createNestedArray(JsonObjectKey key);
FORCE_INLINE JsonArray& createNestedArray(JsonObjectKey key);
// Creates and adds a JsonObject.
// This is a shortcut for JsonBuffer::createObject() and JsonObject::add().
JsonObject& createNestedObject(JsonObjectKey key);
FORCE_INLINE JsonObject& createNestedObject(JsonObjectKey key);
// Tells weither the specified key is present and associated with a value.
bool containsKey(JsonObjectKey key) const {
return getNodeAt(key.c_str()) != NULL;
}
FORCE_INLINE bool containsKey(JsonObjectKey key) const;
// Removes the specified key and the associated value.
void remove(JsonObjectKey key) {
removeNode(getNodeAt(key.c_str()));
}
void remove(JsonObjectKey key);
// Returns a reference an invalid JsonObject.
// This object is meant to replace a NULL pointer.
// This is used when memory allocation or JSON parsing fail.
static JsonObject& invalid() {
static JsonObject instance(NULL);
return instance;
}
static JsonObject& invalid() { return _invalid; }
// Serialize the object to the specified JsonWriter
void writeTo(Internals::JsonWriter& writer) const {
writer.beginObject();
const node_type* node = _firstNode;
while (node) {
writer.writeString(node->content.key);
writer.writeColon();
node->content.value.writeTo(writer);
node = node->next;
if (!node) break;
writer.writeComma();
}
writer.endObject();
}
void writeTo(Internals::JsonWriter& writer) const;
private:
// Returns the list node that matches the specified key.
node_type* getNodeAt(const char* key) const {
for (node_type* node = _firstNode; node; node = node->next) {
if (!strcmp(node->content.key, key)) return node;
}
return NULL;
}
node_type* getNodeAt(const char* key) const;
node_type* getOrCreateNodeAt(const char* key);
template <typename T>
bool setNodeAt(JsonObjectKey key, T value) {
node_type* node = getNodeAt(key.c_str());
if (!node) {
node = addNewNode();
if (!node || !setNodeKey(node, key)) return false;
}
return setNodeValue<T>(node, value);
}
FORCE_INLINE bool setNodeAt(JsonObjectKey key, T value);
bool setNodeKey(node_type* node, JsonObjectKey key) {
if (key.needs_copy()) {
node->content.key = _buffer->strdup(key.c_str());
if (node->content.key == NULL) return false;
} else {
node->content.key = key.c_str();
}
return true;
}
FORCE_INLINE bool setNodeKey(node_type*, JsonObjectKey key);
template <typename T>
bool setNodeValue(node_type* node, T value) {
node->content.value = value;
return true;
}
FORCE_INLINE bool setNodeValue(node_type*, T value);
// The instance returned by JsonObject::invalid()
static JsonObject _invalid;
};
}
#include "JsonObject.ipp"

View File

@ -13,6 +13,68 @@
namespace ArduinoJson {
inline JsonVariant JsonObject::get(JsonObjectKey key) const {
node_type *node = getNodeAt(key.c_str());
return node ? node->content.value : JsonVariant();
}
template <typename T>
inline T JsonObject::get(JsonObjectKey key) const {
node_type *node = getNodeAt(key.c_str());
return node ? node->content.value.as<T>() : JsonVariant::invalid<T>();
}
template <typename T>
inline bool JsonObject::is(JsonObjectKey key) const {
node_type *node = getNodeAt(key.c_str());
return node ? node->content.value.is<T>() : false;
}
inline JsonObjectSubscript<const char *> JsonObject::operator[](
const char *key) {
return JsonObjectSubscript<const char *>(*this, key);
}
inline JsonObjectSubscript<const String &> JsonObject::operator[](
const String &key) {
return JsonObjectSubscript<const String &>(*this, key);
}
inline JsonVariant JsonObject::operator[](JsonObjectKey key) const {
return get(key);
}
inline bool JsonObject::containsKey(JsonObjectKey key) const {
return getNodeAt(key.c_str()) != NULL;
}
inline void JsonObject::remove(JsonObjectKey key) {
removeNode(getNodeAt(key.c_str()));
}
template <typename T>
inline bool JsonObject::setNodeAt(JsonObjectKey key, T value) {
node_type *node = getNodeAt(key.c_str());
if (!node) node = addNewNode();
return node && setNodeKey(node, key) && setNodeValue<T>(node, value);
}
inline bool JsonObject::setNodeKey(node_type *node, JsonObjectKey key) {
if (key.needs_copy()) {
node->content.key = _buffer->strdup(key.c_str());
if (node->content.key == NULL) return false;
} else {
node->content.key = key.c_str();
}
return true;
}
template <typename TValue>
inline bool JsonObject::setNodeValue(node_type *node, TValue value) {
node->content.value = value;
return true;
}
template <>
inline bool JsonObject::setNodeValue(node_type *node, String &value) {
node->content.value = _buffer->strdup(value);
@ -25,23 +87,25 @@ inline bool JsonObject::setNodeValue(node_type *node, const String &value) {
return node->content.value;
}
template <typename TImplem>
inline const JsonObjectSubscript<const char *> JsonVariantBase<TImplem>::
operator[](const char *key) const {
return asObject()[key];
}
template <typename TImplem>
inline const JsonObjectSubscript<const String &> JsonVariantBase<TImplem>::
operator[](const String &key) const {
return asObject()[key];
}
template <>
inline const JsonObject &JsonVariant::defaultValue<const JsonObject &>() {
inline JsonObject const &JsonVariant::invalid<JsonObject const &>() {
return JsonObject::invalid();
}
template <>
inline const JsonObject &JsonVariant::defaultValue<const JsonObject>() {
return JsonObject::invalid();
}
template <>
inline JsonObject &JsonVariant::defaultValue<JsonObject &>() {
return JsonObject::invalid();
}
template <>
inline JsonObject &JsonVariant::defaultValue<JsonObject>() {
inline JsonObject &JsonVariant::invalid<JsonObject &>() {
return JsonObject::invalid();
}

View File

@ -7,7 +7,7 @@
#pragma once
#include "String.hpp"
#include "Arduino/String.hpp"
namespace ArduinoJson {

View File

@ -45,16 +45,12 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > {
return *this;
}
FORCE_INLINE bool success() const {
return _object.containsKey(_key);
}
FORCE_INLINE bool success() const { return _object.containsKey(_key); }
FORCE_INLINE operator JsonVariant() const {
return _object.get(_key);
}
FORCE_INLINE operator JsonVariant() const { return _object.get(_key); }
template <typename TValue>
FORCE_INLINE typename Internals::JsonVariantAs<TValue>::type as() const {
FORCE_INLINE TValue as() const {
return _object.get<TValue>(_key);
}
@ -73,9 +69,7 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > {
return _object.set(_key, value, decimals);
}
FORCE_INLINE JsonVariant get() {
return _object.get(_key);
}
FORCE_INLINE JsonVariant get() { return _object.get(_key); }
void writeTo(Internals::JsonWriter& writer) const {
_object.get(_key).writeTo(writer);
@ -98,28 +92,10 @@ inline std::ostream& operator<<(
}
#endif
inline JsonObjectSubscript<const char*> JsonObject::operator[](
const char* key) {
return JsonObjectSubscript<const char*>(*this, key);
}
inline JsonObjectSubscript<const String&> JsonObject::operator[](
const String& key) {
return JsonObjectSubscript<const String&>(*this, key);
}
template <typename TImplem>
inline const JsonObjectSubscript<const char*> JsonVariantBase<TImplem>::
operator[](const char* key) const {
return asObject()[key];
}
template <typename TImplem>
inline const JsonObjectSubscript<const String&> JsonVariantBase<TImplem>::
operator[](const String& key) const {
return asObject()[key];
}
template <typename T>
struct JsonVariant::IsConstructibleFrom<JsonObjectSubscript<T> > {
static const bool value = true;
};
} // namespace ArduinoJson
#ifdef _MSC_VER

View File

@ -13,14 +13,14 @@
#include "Internals/JsonPrintable.hpp"
#include "Internals/JsonVariantContent.hpp"
#include "Internals/JsonVariantType.hpp"
#include "Internals/Unparsed.hpp"
#include "JsonVariantBase.hpp"
#include "RawJson.hpp"
#include "TypeTraits/EnableIf.hpp"
#include "TypeTraits/IsFloatingPoint.hpp"
#include "TypeTraits/IsIntegral.hpp"
#include "TypeTraits/IsSame.hpp"
#include "TypeTraits/RemoveConst.hpp"
#include "TypeTraits/RemoveReference.hpp"
#include "TypeTraits/IsSame.hpp"
namespace ArduinoJson {
@ -41,15 +41,11 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
struct IsConstructibleFrom;
// Creates an uninitialized JsonVariant
JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
FORCE_INLINE JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
// Create a JsonVariant containing a boolean value.
// It will be serialized as "true" or "false" in JSON.
JsonVariant(bool value) {
using namespace Internals;
_type = JSON_BOOLEAN;
_content.asInteger = static_cast<JsonInteger>(value);
}
FORCE_INLINE JsonVariant(bool value);
// Create a JsonVariant containing a floating point value.
// The second argument specifies the number of decimal digits to write in
@ -57,89 +53,49 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
// JsonVariant(double value, uint8_t decimals);
// JsonVariant(float value, uint8_t decimals);
template <typename T>
JsonVariant(T value, uint8_t decimals = 2,
typename TypeTraits::EnableIf<
TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
FORCE_INLINE JsonVariant(
T value, uint8_t decimals = 2,
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
T>::type * = 0) {
using namespace Internals;
_type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals);
_content.asFloat = static_cast<JsonFloat>(value);
}
// Create a JsonVariant containing an integer value.
// JsonVariant(signed short)
// JsonVariant(signed int)
// JsonVariant(signed long)
// JsonVariant(short)
// JsonVariant(int)
// JsonVariant(long)
template <typename T>
JsonVariant(T value,
typename TypeTraits::EnableIf<
TypeTraits::IsSignedIntegral<T>::value>::type * = 0) {
FORCE_INLINE JsonVariant(
T value, typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value,
T>::type * = 0) {
using namespace Internals;
if (value >= 0) {
_type = JSON_POSITIVE_INTEGER;
_content.asInteger = static_cast<JsonUInt>(value);
} else {
_type = JSON_NEGATIVE_INTEGER;
_content.asInteger = static_cast<JsonUInt>(-value);
}
}
// JsonVariant(unsigned short)
// JsonVariant(unsigned int)
// JsonVariant(unsigned long)
template <typename T>
JsonVariant(T value,
typename TypeTraits::EnableIf<
TypeTraits::IsUnsignedIntegral<T>::value>::type * = 0) {
using namespace Internals;
_type = JSON_POSITIVE_INTEGER;
_content.asInteger = static_cast<JsonUInt>(value);
_type = JSON_INTEGER;
_content.asInteger = static_cast<JsonInteger>(value);
}
// Create a JsonVariant containing a string.
JsonVariant(const char *value) {
_type = Internals::JSON_STRING;
_content.asString = value;
}
FORCE_INLINE JsonVariant(const char *value);
// Create a JsonVariant containing an unparsed string
JsonVariant(RawJson value) {
_type = Internals::JSON_UNPARSED;
_content.asString = value;
}
FORCE_INLINE JsonVariant(Internals::Unparsed value);
// Create a JsonVariant containing a reference to an array.
JsonVariant(JsonArray &array) {
_type = Internals::JSON_ARRAY;
_content.asArray = &array;
}
FORCE_INLINE JsonVariant(JsonArray &array);
// Create a JsonVariant containing a reference to an object.
JsonVariant(JsonObject &object) {
_type = Internals::JSON_OBJECT;
_content.asObject = &object;
}
FORCE_INLINE JsonVariant(JsonObject &object);
// Get the variant as the specified type.
//
// short as<signed short>() const;
// int as<signed int>() const;
// long as<signed long>() const;
// short as<short>() const;
// int as<int>() const;
// long as<long>() const;
template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsSignedIntegral<T>::value,
T>::type
const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value, T>::type
as() const {
return static_cast<T>(asInteger());
}
//
// short as<unsigned short>() const;
// int as<unsigned int>() const;
// long as<unsigned long>() const;
template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsUnsignedIntegral<T>::value,
T>::type
as() const {
return static_cast<T>(asUnsignedInteger());
}
//
// double as<double>() const;
// float as<float>() const;
template <typename T>
@ -148,7 +104,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
as() const {
return static_cast<T>(asFloat());
}
//
// const String as<String>() const;
template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, String>::value,
@ -156,17 +111,14 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
as() const {
return toString();
}
//
// const char* as<const char*>() const;
// const char* as<char*>() const;
template <typename T>
typename TypeTraits::EnableIf<TypeTraits::IsSame<T, const char *>::value ||
TypeTraits::IsSame<T, char *>::value,
typename TypeTraits::EnableIf<TypeTraits::IsSame<T, const char *>::value,
const char *>::type
as() const {
return asString();
}
//
// const bool as<bool>() const
template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
@ -174,104 +126,19 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
as() const {
return asInteger() != 0;
}
//
// JsonArray& as<JsonArray> const;
// JsonArray& as<JsonArray&> const;
template <typename T>
typename TypeTraits::EnableIf<
TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
JsonArray>::value,
JsonArray &>::type
as() const {
return asArray();
}
//
// const JsonArray& as<const JsonArray&> const;
template <typename T>
typename TypeTraits::EnableIf<
TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
const JsonArray>::value,
const JsonArray &>::type
as() const {
return asArray();
}
//
// JsonObject& as<JsonObject> const;
// JsonObject& as<JsonObject&> const;
template <typename T>
typename TypeTraits::EnableIf<
TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
JsonObject>::value,
JsonObject &>::type
as() const {
return asObject();
}
//
// JsonObject& as<const JsonObject> const;
// JsonObject& as<const JsonObject&> const;
template <typename T>
typename TypeTraits::EnableIf<
TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
const JsonObject>::value,
const JsonObject &>::type
as() const {
return asObject();
}
// Tells weither the variant has the specified type.
// Returns true if the variant has type type T, false otherwise.
//
// short as<short>() const;
// int as<int>() const;
// long as<long>() const;
template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value,
bool>::type
is() const {
return isInteger();
}
//
// double is<double>() const;
// float is<float>() const;
template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
bool>::type
is() const {
return isFloat();
}
//
// const bool is<bool>() const
template <typename T>
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
bool>::type
is() const {
return isBoolean();
}
//
// bool is<const char*>() const;
// bool is<char*>() const;
template <typename T>
typename TypeTraits::EnableIf<TypeTraits::IsSame<T, const char *>::value ||
TypeTraits::IsSame<T, char *>::value,
bool>::type
is() const {
return isString();
}
//
// bool is<JsonArray> const;
// bool is<JsonArray&> const;
// bool is<const JsonArray&> const;
// JsonArray& as<const JsonArray&> const;
template <typename T>
typename TypeTraits::EnableIf<
TypeTraits::IsSame<
typename TypeTraits::RemoveConst<
typename TypeTraits::RemoveReference<T>::type>::type,
JsonArray>::value,
bool>::type
is() const {
return isArray();
JsonArray &>::type
as() const {
return asArray();
}
//
// JsonObject& as<JsonObject> const;
// JsonObject& as<JsonObject&> const;
// JsonObject& as<const JsonObject&> const;
@ -281,51 +148,31 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
typename TypeTraits::RemoveConst<
typename TypeTraits::RemoveReference<T>::type>::type,
JsonObject>::value,
bool>::type
is() const {
return isObject();
JsonObject &>::type
as() const {
return asObject();
}
// Returns true if the variant has a value
bool success() const {
return _type != Internals::JSON_UNDEFINED;
}
// Tells weither the variant has the specified type.
// Returns true if the variant has type type T, false otherwise.
template <typename T>
bool is() const;
// Serialize the variant to a JsonWriter
void writeTo(Internals::JsonWriter &writer) const;
// Value returned if the variant has an incompatible type
// TODO: rename
template <typename T>
static typename Internals::JsonVariantAs<T>::type defaultValue() {
return T();
}
static T invalid();
const char *asString() const;
JsonArray &asArray() const;
JsonObject &asObject() const;
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);
String toString() const;
Internals::JsonFloat asFloat() const;
Internals::JsonInteger asInteger() const;
Internals::JsonUInt asUnsignedInteger() const;
bool isBoolean() const;
bool isFloat() const;
bool isInteger() const;
bool isArray() const {
return _type == Internals::JSON_ARRAY;
}
bool isObject() const {
return _type == Internals::JSON_OBJECT;
}
bool isString() const {
return _type == Internals::JSON_STRING;
}
// The current type of the variant
Internals::JsonVariantType _type;
@ -344,24 +191,19 @@ inline JsonVariant double_with_n_digits(double value, uint8_t digits) {
template <typename T>
struct JsonVariant::IsConstructibleFrom {
static const bool value =
TypeTraits::IsIntegral<T>::value ||
TypeTraits::IsFloatingPoint<T>::value ||
TypeTraits::IsSame<T, bool>::value ||
TypeTraits::IsSame<T, char *>::value ||
TypeTraits::IsSame<T, const char *>::value ||
TypeTraits::IsSame<T, RawJson>::value ||
TypeTraits::IsSame<T, JsonArray &>::value ||
TypeTraits::IsSame<T, const JsonArray &>::value ||
TypeTraits::IsSame<T, JsonArraySubscript &>::value ||
TypeTraits::IsSame<T, const JsonArraySubscript &>::value ||
TypeTraits::IsSame<T, JsonObject &>::value ||
TypeTraits::IsSame<T, const JsonObject &>::value ||
TypeTraits::IsSame<T, JsonObjectSubscript<const char *> &>::value ||
TypeTraits::IsSame<T, const JsonObjectSubscript<const char *> &>::value ||
TypeTraits::IsSame<T, JsonObjectSubscript<String> &>::value ||
TypeTraits::IsSame<T, const JsonObjectSubscript<String> &>::value ||
TypeTraits::IsSame<T, JsonVariant &>::value ||
TypeTraits::IsSame<T, const JsonVariant &>::value;
static const bool value = TypeTraits::IsIntegral<T>::value ||
TypeTraits::IsFloatingPoint<T>::value ||
TypeTraits::IsSame<T, bool>::value ||
TypeTraits::IsSame<T, char *>::value ||
TypeTraits::IsSame<T, const char *>::value ||
TypeTraits::IsSame<T, JsonArray &>::value ||
TypeTraits::IsSame<T, const JsonArray &>::value ||
TypeTraits::IsSame<T, JsonObject &>::value ||
TypeTraits::IsSame<T, const JsonObject &>::value ||
TypeTraits::IsSame<T, JsonVariant &>::value ||
TypeTraits::IsSame<T, const JsonVariant &>::value;
};
}
// Include inline implementations
#include "JsonVariant.ipp"

View File

@ -10,165 +10,135 @@
#include "Configuration.hpp"
#include "JsonVariant.hpp"
#include "Internals/Parse.hpp"
#include "JsonArray.hpp"
#include "JsonObject.hpp"
#include <string.h> // for strcmp
#include <errno.h> // for errno
#include <stdlib.h> // for strtol, strtod
#include <string.h>
namespace ArduinoJson {
inline JsonVariant::JsonVariant(bool value) {
using namespace Internals;
_type = JSON_BOOLEAN;
_content.asInteger = static_cast<JsonInteger>(value);
}
inline JsonVariant::JsonVariant(const char *value) {
_type = Internals::JSON_STRING;
_content.asString = value;
}
inline JsonVariant::JsonVariant(Internals::Unparsed value) {
_type = Internals::JSON_UNPARSED;
_content.asString = value;
}
inline JsonVariant::JsonVariant(JsonArray &array) {
_type = Internals::JSON_ARRAY;
_content.asArray = &array;
}
inline JsonVariant::JsonVariant(JsonObject &object) {
_type = Internals::JSON_OBJECT;
_content.asObject = &object;
}
template <typename T>
inline T JsonVariant::invalid() {
return T();
}
template <typename T>
inline bool JsonVariant::is() const {
return false;
}
template <> // in .cpp
bool JsonVariant::is<signed long>() const;
template <> // in .cpp
bool JsonVariant::is<double>() const;
template <> // int .cpp
bool JsonVariant::is<bool>() const;
template <>
inline bool JsonVariant::is<char const *>() const {
return _type == Internals::JSON_STRING;
}
template <>
inline bool JsonVariant::is<float>() const {
return is<double>();
}
template <>
inline bool JsonVariant::is<JsonArray &>() const {
return _type == Internals::JSON_ARRAY;
}
template <>
inline bool JsonVariant::is<JsonArray const &>() const {
return _type == Internals::JSON_ARRAY;
}
template <>
inline bool JsonVariant::is<JsonObject &>() const {
return _type == Internals::JSON_OBJECT;
}
template <>
inline bool JsonVariant::is<JsonObject const &>() const {
return _type == Internals::JSON_OBJECT;
}
template <>
inline bool JsonVariant::is<signed char>() const {
return is<signed long>();
}
template <>
inline bool JsonVariant::is<signed int>() const {
return is<signed long>();
}
template <>
inline bool JsonVariant::is<signed short>() const {
return is<signed long>();
}
template <>
inline bool JsonVariant::is<unsigned char>() const {
return is<signed long>();
}
template <>
inline bool JsonVariant::is<unsigned int>() const {
return is<signed long>();
}
template <>
inline bool JsonVariant::is<unsigned long>() const {
return is<signed long>();
}
template <>
inline bool JsonVariant::is<unsigned short>() const {
return is<signed long>();
}
inline Internals::JsonInteger JsonVariant::asInteger() const {
using namespace Internals;
switch (_type) {
case JSON_UNDEFINED:
return 0;
case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN:
return _content.asInteger;
case JSON_NEGATIVE_INTEGER:
return -static_cast<Internals::JsonInteger>(_content.asInteger);
case JSON_STRING:
case JSON_UNPARSED:
if (!_content.asString) return 0;
if (!strcmp("true", _content.asString)) return 1;
return parse<Internals::JsonInteger>(_content.asString);
default:
return static_cast<Internals::JsonInteger>(_content.asFloat);
if (_type == Internals::JSON_INTEGER || _type == Internals::JSON_BOOLEAN)
return _content.asInteger;
if (_type >= Internals::JSON_FLOAT_0_DECIMALS)
return static_cast<Internals::JsonInteger>(_content.asFloat);
if ((_type == Internals::JSON_STRING || _type == Internals::JSON_UNPARSED) &&
_content.asString) {
if (!strcmp("true", _content.asString)) return 1;
return Internals::parse<Internals::JsonInteger>(_content.asString);
}
}
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);
}
}
inline const char *JsonVariant::asString() const {
using namespace Internals;
if (_type == JSON_UNPARSED && _content.asString &&
!strcmp("null", _content.asString))
return NULL;
if (_type == JSON_STRING || _type == JSON_UNPARSED) return _content.asString;
return NULL;
}
inline Internals::JsonFloat JsonVariant::asFloat() const {
using namespace Internals;
switch (_type) {
case JSON_UNDEFINED:
return 0;
case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN:
return static_cast<JsonFloat>(_content.asInteger);
case JSON_NEGATIVE_INTEGER:
return -static_cast<JsonFloat>(_content.asInteger);
case JSON_STRING:
case JSON_UNPARSED:
return _content.asString ? parse<JsonFloat>(_content.asString) : 0;
default:
return _content.asFloat;
}
}
inline String JsonVariant::toString() const {
using namespace Internals;
String s;
if ((_type == JSON_STRING || _type == JSON_UNPARSED) &&
_content.asString != NULL)
s = _content.asString;
else
printTo(s);
return s;
}
inline bool JsonVariant::isBoolean() const {
using namespace Internals;
if (_type == JSON_BOOLEAN) return true;
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
return !strcmp(_content.asString, "true") ||
!strcmp(_content.asString, "false");
}
inline bool JsonVariant::isInteger() const {
using namespace Internals;
if (_type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER)
return true;
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
char *end;
errno = 0;
strtol(_content.asString, &end, 10);
return *end == '\0' && errno == 0;
}
inline bool JsonVariant::isFloat() const {
using namespace Internals;
if (_type >= JSON_FLOAT_0_DECIMALS) return true;
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
char *end;
errno = 0;
strtod(_content.asString, &end);
return *end == '\0' && errno == 0 && !is<long>();
}
inline void JsonVariant::writeTo(Internals::JsonWriter &writer) const {
using namespace Internals;
switch (_type) {
case JSON_UNDEFINED:
return;
case JSON_ARRAY:
_content.asArray->writeTo(writer);
return;
case JSON_OBJECT:
_content.asObject->writeTo(writer);
return;
case JSON_STRING:
writer.writeString(_content.asString);
return;
case JSON_UNPARSED:
writer.writeRaw(_content.asString);
return;
case JSON_NEGATIVE_INTEGER:
writer.writeRaw('-');
case JSON_POSITIVE_INTEGER:
writer.writeInteger(_content.asInteger);
return;
case JSON_BOOLEAN:
writer.writeBoolean(_content.asInteger != 0);
return;
default:
uint8_t decimals = static_cast<uint8_t>(_type - JSON_FLOAT_0_DECIMALS);
writer.writeFloat(_content.asFloat, decimals);
}
return 0L;
}
#if ARDUINOJSON_ENABLE_STD_STREAM

View File

@ -7,9 +7,8 @@
#pragma once
#include "Internals/JsonVariantAs.hpp"
#include "Internals/ForceInline.hpp"
#include "JsonObjectKey.hpp"
#include "Polyfills/attributes.hpp"
namespace ArduinoJson {
@ -21,35 +20,20 @@ class JsonObjectSubscript;
template <typename TImpl>
class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
public:
// DEPRECATED: use as<char*>() instead
FORCE_INLINE const char *asString() const {
return as<const char *>();
}
FORCE_INLINE const char *asString() const { return as<const char *>(); }
// Gets the variant as an array.
// Returns a reference to the JsonArray or JsonArray::invalid() if the
// variant
// is not an array.
FORCE_INLINE operator JsonArray &() const {
return as<JsonArray &>();
}
// DEPRECATED: use as<JsonArray>() instead
FORCE_INLINE JsonArray &asArray() const {
return as<JsonArray &>();
}
FORCE_INLINE operator JsonArray &() const { return as<JsonArray &>(); }
FORCE_INLINE JsonArray &asArray() const { return as<JsonArray &>(); }
// Gets the variant as an object.
// Returns a reference to the JsonObject or JsonObject::invalid() if the
// variant is not an object.
FORCE_INLINE operator JsonObject &() const {
return as<JsonObject &>();
}
// DEPRECATED: use as<JsonObject>() instead
FORCE_INLINE JsonObject &asObject() const {
return as<JsonObject &>();
}
FORCE_INLINE operator JsonObject &() const { return as<JsonObject &>(); }
FORCE_INLINE JsonObject &asObject() const { return as<JsonObject &>(); }
template <typename T>
FORCE_INLINE operator T() const {
@ -57,16 +41,14 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
}
template <typename T>
FORCE_INLINE const typename Internals::JsonVariantAs<T>::type as() const {
FORCE_INLINE const T as() const {
return impl()->template as<T>();
}
// Mimics an array or an object.
// Returns the size of the array or object if the variant has that type.
// Returns 0 if the variant is neither an array nor an object
size_t size() const {
return asArray().size() + asObject().size();
}
size_t size() const { return asArray().size() + asObject().size(); }
// Mimics an array.
// Returns the element at specified index if the variant is an array.
@ -86,9 +68,7 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
void writeTo(Internals::JsonWriter &writer) const;
private:
const TImpl *impl() const {
return static_cast<const TImpl *>(this);
}
const TImpl *impl() const { return static_cast<const TImpl *>(this); }
};
template <typename TImpl, typename TComparand>

View File

@ -1,111 +0,0 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
// If Visual Studo <= 2012
#if defined(_MSC_VER) && _MSC_VER <= 1700
#include <float.h>
namespace ArduinoJson {
namespace Polyfills {
template <typename T>
bool isNaN(T x) {
return _isnan(x) != 0;
}
template <typename T>
bool isInfinity(T x) {
return !_finite(x);
}
}
}
#else
#include <math.h>
// GCC warning: "conversion to 'float' from 'double' may alter its value"
#ifdef __GNUC__
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#endif
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
#pragma GCC diagnostic ignored "-Wfloat-conversion"
#else
#pragma GCC diagnostic ignored "-Wconversion"
#endif
#endif
// Workaround for libs that #undef isnan or isinf
// https://github.com/bblanchon/ArduinoJson/issues/284
#if !defined(isnan) || !defined(isinf)
namespace std {}
#endif
namespace ArduinoJson {
namespace Polyfills {
template <typename T>
bool isNaN(T x) {
// Workaround for libs that #undef isnan
// https://github.com/bblanchon/ArduinoJson/issues/284
#ifndef isnan
using namespace std;
#endif
return isnan(x);
}
#if defined(_GLIBCXX_HAVE_ISNANL) && _GLIBCXX_HAVE_ISNANL
template <>
inline bool isNaN<double>(double x) {
return isnanl(x);
}
#endif
#if defined(_GLIBCXX_HAVE_ISNANF) && _GLIBCXX_HAVE_ISNANF
template <>
inline bool isNaN<float>(float x) {
return isnanf(x);
}
#endif
template <typename T>
bool isInfinity(T x) {
// Workaround for libs that #undef isinf
// https://github.com/bblanchon/ArduinoJson/issues/284
#ifndef isinf
using namespace std;
#endif
return isinf(x);
}
#if defined(_GLIBCXX_HAVE_ISINFL) && _GLIBCXX_HAVE_ISINFL
template <>
inline bool isInfinity<double>(double x) {
return isinfl(x);
}
#endif
#if defined(_GLIBCXX_HAVE_ISINFF) && _GLIBCXX_HAVE_ISINFF
template <>
inline bool isInfinity<float>(float x) {
return isinff(x);
}
#endif
#if defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop
#endif
#endif
}
}
#endif

View File

@ -1,47 +0,0 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
namespace ArduinoJson {
namespace Polyfills {
#ifdef ARDUINO
// on embedded platform, favor code size over speed
template <typename T>
short normalize(T& value) {
short powersOf10 = 0;
while (value && value < 1) {
powersOf10--;
value *= 10;
}
while (value > 10) {
powersOf10++;
value /= 10;
}
return powersOf10;
}
#else
// on non-embedded platform, favor speed over code size
template <typename T>
short normalize(T& value) {
if (value == 0.0) return 0;
short powersOf10 = static_cast<short>(floor(log10(value)));
value /= pow(T(10), powersOf10);
return powersOf10;
}
#endif
}
}

View File

@ -1,39 +0,0 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#ifndef ARDUINO
#include <stddef.h>
#include <stdint.h>
namespace ArduinoJson {
// This class reproduces Arduino's Print class
class Print {
public:
virtual ~Print() {}
virtual size_t write(uint8_t) = 0;
size_t print(const char* s) {
size_t n = 0;
while (*s) {
n += write(*s++);
}
return n;
}
size_t println() { return write('\r') + write('\n'); }
};
}
#else
#include <Print.h>
#endif

View File

@ -9,16 +9,6 @@
#include "JsonBuffer.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 {
// Implements a JsonBuffer with fixed memory allocation.
@ -29,12 +19,8 @@ class StaticJsonBuffer : public JsonBuffer {
public:
explicit StaticJsonBuffer() : _size(0) {}
size_t capacity() const {
return CAPACITY;
}
size_t size() const {
return _size;
}
size_t capacity() const { return CAPACITY; }
size_t size() const { return _size; }
virtual void* alloc(size_t bytes) {
if (_size + bytes > CAPACITY) return NULL;
@ -48,11 +34,3 @@ class StaticJsonBuffer : public JsonBuffer {
size_t _size;
};
}
#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

@ -11,7 +11,7 @@ namespace ArduinoJson {
namespace TypeTraits {
// A meta-function that return the type T if Condition is true.
template <bool Condition, typename T = void>
template <bool Condition, typename T>
struct EnableIf {};
template <typename T>

View File

@ -7,10 +7,9 @@
#pragma once
#include "../Configuration.hpp"
#include "IsSame.hpp"
#include "IsSignedIntegral.hpp"
#include "IsUnsignedIntegral.hpp"
#include <stdint.h>
namespace ArduinoJson {
namespace TypeTraits {
@ -18,8 +17,19 @@ namespace TypeTraits {
// A meta-function that returns true if T is an integral type.
template <typename T>
struct IsIntegral {
static const bool value = TypeTraits::IsSignedIntegral<T>::value ||
TypeTraits::IsUnsignedIntegral<T>::value ||
static const bool value = TypeTraits::IsSame<T, signed char>::value ||
TypeTraits::IsSame<T, unsigned char>::value ||
TypeTraits::IsSame<T, signed short>::value ||
TypeTraits::IsSame<T, unsigned short>::value ||
TypeTraits::IsSame<T, signed int>::value ||
TypeTraits::IsSame<T, unsigned int>::value ||
TypeTraits::IsSame<T, signed long>::value ||
TypeTraits::IsSame<T, unsigned long>::value ||
#ifndef ARDUINO
// on a computer add support for 64 bit
TypeTraits::IsSame<T, int64_t>::value ||
TypeTraits::IsSame<T, uint64_t>::value ||
#endif
TypeTraits::IsSame<T, char>::value;
};
}

View File

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

View File

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

View File

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

View File

@ -6,7 +6,7 @@
"type": "git",
"url": "https://github.com/bblanchon/ArduinoJson.git"
},
"version": "5.6.3",
"version": "5.1.0-beta.1",
"authors": {
"name": "Benoit Blanchon",
"url": "http://blog.benoitblanchon.fr"

View File

@ -1,5 +1,5 @@
name=ArduinoJson
version=5.6.3
version=5.1.0-beta.1
author=Benoit Blanchon <blog.benoitblanchon.fr>
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
sentence=An efficient and elegant JSON library for Arduino.

View File

@ -17,4 +17,5 @@ rm -f $OUTPUT
ArduinoJson/library.properties \
ArduinoJson/LICENSE.md \
ArduinoJson/README.md \
ArduinoJson/ArduinoJson.h
ArduinoJson/src \
-x!ArduinoJson/src/CMakeLists.txt

View File

@ -0,0 +1,52 @@
#!/bin/bash
TAG=$(git describe)
OUTPUT="ArduinoJson-$TAG-old-layout.zip"
cd $(dirname $0)/..
cat > ArduinoJson.h <<END
// WARNING:
// --------
// This file is a workaround for old version of the Arduino IDE.
// If you are using Arduino IDE 1.0.6 or above, then you installed the wrong
// package of ArduinoJson.
// In that case, just delete the current installation and install the package.
END
cp ArduinoJson.h ArduinoJson.cpp
cat "include/ArduinoJson.h" | sed 's!include "!include "include/!g' >> ArduinoJson.h
find src -name "*.cpp" |
while read FILE; do
echo >> ArduinoJson.cpp
echo "// $FILE" >> ArduinoJson.cpp
echo "//" >> ArduinoJson.cpp
cat "$FILE" | sed 's!\.\./!!g' >> ArduinoJson.cpp
done
unix2dos ArduinoJson.cpp
unix2dos ArduinoJson.h
pushd ..
# remove existing file
rm -f $OUTPUT
# create zipman dos2
7z a $OUTPUT \
ArduinoJson/CHANGELOG.md \
ArduinoJson/examples \
ArduinoJson/include/ArduinoJson \
ArduinoJson/keywords.txt \
ArduinoJson/LICENSE.md \
ArduinoJson/README.md \
ArduinoJson/ArduinoJson.h \
ArduinoJson/ArduinoJson.cpp \
-x!ArduinoJson/src/CMakeLists.txt
popd
rm ArduinoJson.h
rm ArduinoJson.cpp

View File

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

View File

@ -11,6 +11,5 @@ export PATH=$PATH:/tmp/arduino/
ln -s $PWD /tmp/arduino/libraries/ArduinoJson
for EXAMPLE in $PWD/examples/*/*.ino; do
arduino --verify --board $BOARD $EXAMPLE
done
arduino --verify --board $BOARD $PWD/examples/JsonParserExample/JsonParserExample.ino
arduino --verify --board $BOARD $PWD/examples/JsonGeneratorExample/JsonGeneratorExample.ino

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

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

View File

@ -1,9 +0,0 @@
#!/bin/sh -eux
URL=https://cmake.org/files/v3.4/cmake-3.4.3-Darwin-x86_64.tar.gz
curl -sS $URL | tar xz -C /tmp --strip 1
/tmp/CMake.app/Contents/bin/cmake .
make
make test

View File

@ -1,9 +0,0 @@
#!/bin/sh -eux
URL=https://cmake.org/files/v3.4/cmake-3.4.3-Linux-x86_64.tar.gz
curl -sS $URL | tar xz -C /tmp --strip 1
/tmp/bin/cmake -DCMAKE_CXX_COMPILER=$CMAKE_CXX_COMPILER .
make
make test

View File

@ -1,5 +1,8 @@
#!/bin/sh -eux
export CC=gcc
export CXX=g++
curl https://cmake.org/files/v3.4/cmake-3.4.0-Linux-x86_64.tar.gz | tar xz -C /tmp --strip 1
/tmp/bin/cmake -DCOVERAGE=true .

60
src/Arduino/Print.cpp Normal file
View File

@ -0,0 +1,60 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#ifndef ARDUINO
#include "../../include/ArduinoJson/Arduino/Print.hpp"
#include <stdio.h>
#include <math.h> // for isnan() and isinf()
// only for GCC 4.9+
#if defined(__GNUC__) && \
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))
#pragma GCC diagnostic ignored "-Wfloat-conversion"
#endif
// Visual Studo 2012 didn't have isnan, nor isinf
#if defined(_MSC_VER) && _MSC_VER <= 1700
#include <float.h>
#define isnan(x) _isnan(x)
#define isinf(x) (!_finite(x))
#endif
size_t Print::print(const char s[]) {
size_t n = 0;
while (*s) {
n += write(*s++);
}
return n;
}
size_t Print::print(double value, int digits) {
// https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware/arduino/sam/cores/arduino/Print.cpp#L218
if (isnan(value)) return print("nan");
if (isinf(value)) return print("inf");
char tmp[32];
// https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware/arduino/sam/cores/arduino/Print.cpp#L220
bool isBigDouble = value > 4294967040.0 || value < -4294967040.0;
if (isBigDouble) {
// Arduino's implementation prints "ovf"
// We prefer trying to use scientific notation, since we have sprintf
sprintf(tmp, "%g", value);
} else {
// Here we have the exact same output as Arduino's implementation
sprintf(tmp, "%.*f", digits, value);
}
return print(tmp);
}
size_t Print::println() { return write('\r') + write('\n'); }
#endif

14
src/ArduinoJson.h Normal file
View File

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

66
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,66 @@
# Copyright Benoit Blanchon 2014-2016
# MIT License
#
# Arduino JSON library
# https://github.com/bblanchon/ArduinoJson
# If you like this project, please add a star!
file(GLOB_RECURSE HPP_FILES ../include/*.hpp)
file(GLOB_RECURSE IPP_FILES ../include/*.ipp)
file(GLOB_RECURSE CPP_FILES *.cpp)
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
add_definitions(
-fno-exceptions
-fno-rtti
-pedantic
-Wall
-Wcast-align
-Wcast-qual
-Wconversion
-Wctor-dtor-privacy
-Wdisabled-optimization
-Werror
-Wextra
-Wformat=2
-Winit-self
-Wmissing-include-dirs
-Wno-parentheses
-Wno-sign-conversion
-Wno-unused
-Wno-variadic-macros
-Wnon-virtual-dtor
-Wold-style-cast
-Woverloaded-virtual
-Wredundant-decls
-Wshadow
-Wsign-promo
-Wstrict-overflow=5
-Wundef
)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU)")
add_definitions(
-Wlogical-op
-Wnoexcept
-Wstrict-null-sentinel
)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_definitions(
-Wc++11-compat
-Wdeprecated-register
)
endif()
if(MSVC)
add_definitions(
-D_CRT_SECURE_NO_WARNINGS
-W4)
endif()
add_library(ArduinoJson ${CPP_FILES} ${HPP_FILES} ${IPP_FILES})
target_include_directories(ArduinoJson INTERFACE ${CMAKE_CURRENT_LIST_DIR}/../include)

View File

@ -0,0 +1,52 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../../include/ArduinoJson/Internals/Comments.hpp"
inline static const char *skipCStyleComment(const char *ptr) {
ptr += 2;
for (;;) {
if (ptr[0] == '\0') return ptr;
if (ptr[0] == '*' && ptr[1] == '/') return ptr + 2;
ptr++;
}
}
inline static const char *skipCppStyleComment(const char *ptr) {
ptr += 2;
for (;;) {
if (ptr[0] == '\0' || ptr[0] == '\n') return ptr;
ptr++;
}
}
const char *ArduinoJson::Internals::skipSpacesAndComments(const char *ptr) {
for (;;) {
switch (ptr[0]) {
case ' ':
case '\t':
case '\r':
case '\n':
ptr++;
continue;
case '/':
switch (ptr[1]) {
case '*':
ptr = skipCStyleComment(ptr);
break;
case '/':
ptr = skipCppStyleComment(ptr);
break;
default:
return ptr;
}
break;
default:
return ptr;
}
}
}

View File

@ -0,0 +1,14 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../../include/ArduinoJson/Internals/Encoding.hpp"
// How to escape special chars:
// _escapeTable[2*i+1] => the special char
// _escapeTable[2*i] => the char to use instead
const char ArduinoJson::Internals::Encoding::_escapeTable[] =
"\"\"\\\\b\bf\fn\nr\rt\t";

View File

@ -0,0 +1,30 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../../include/ArduinoJson/Internals/IndentedPrint.hpp"
using namespace ArduinoJson::Internals;
size_t IndentedPrint::write(uint8_t c) {
size_t n = 0;
if (isNewLine) n += writeTabs();
n += sink->write(c);
isNewLine = c == '\n';
return n;
}
inline size_t IndentedPrint::writeTabs() {
size_t n = 0;
for (int i = 0; i < level * tabSize; i++) n += sink->write(' ');
return n;
}

View File

@ -5,12 +5,18 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#pragma once
#include "../../include/ArduinoJson/Internals/JsonParser.hpp"
#include "Comments.hpp"
#include "JsonParser.hpp"
#include "../../include/ArduinoJson/Internals/Comments.hpp"
#include "../../include/ArduinoJson/Internals/Encoding.hpp"
#include "../../include/ArduinoJson/JsonArray.hpp"
#include "../../include/ArduinoJson/JsonBuffer.hpp"
#include "../../include/ArduinoJson/JsonObject.hpp"
inline bool ArduinoJson::Internals::JsonParser::skip(char charToSkip) {
using namespace ArduinoJson;
using namespace ArduinoJson::Internals;
bool JsonParser::skip(char charToSkip) {
const char *ptr = skipSpacesAndComments(_readPtr);
if (*ptr != charToSkip) return false;
ptr++;
@ -18,8 +24,7 @@ inline bool ArduinoJson::Internals::JsonParser::skip(char charToSkip) {
return true;
}
inline bool ArduinoJson::Internals::JsonParser::parseAnythingTo(
JsonVariant *destination) {
bool JsonParser::parseAnythingTo(JsonVariant *destination) {
if (_nestingLimit == 0) return false;
_nestingLimit--;
bool success = parseAnythingToUnsafe(destination);
@ -27,8 +32,7 @@ inline bool ArduinoJson::Internals::JsonParser::parseAnythingTo(
return success;
}
inline bool ArduinoJson::Internals::JsonParser::parseAnythingToUnsafe(
JsonVariant *destination) {
inline bool JsonParser::parseAnythingToUnsafe(JsonVariant *destination) {
_readPtr = skipSpacesAndComments(_readPtr);
switch (*_readPtr) {
@ -43,8 +47,7 @@ inline bool ArduinoJson::Internals::JsonParser::parseAnythingToUnsafe(
}
}
inline ArduinoJson::JsonArray &
ArduinoJson::Internals::JsonParser::parseArray() {
JsonArray &JsonParser::parseArray() {
// Create an empty array
JsonArray &array = _buffer->createArray();
@ -75,8 +78,7 @@ ERROR_NO_MEMORY:
return JsonArray::invalid();
}
inline bool ArduinoJson::Internals::JsonParser::parseArrayTo(
JsonVariant *destination) {
bool JsonParser::parseArrayTo(JsonVariant *destination) {
JsonArray &array = parseArray();
if (!array.success()) return false;
@ -84,8 +86,7 @@ inline bool ArduinoJson::Internals::JsonParser::parseArrayTo(
return true;
}
inline ArduinoJson::JsonObject &
ArduinoJson::Internals::JsonParser::parseObject() {
JsonObject &JsonParser::parseObject() {
// Create an empty object
JsonObject &object = _buffer->createObject();
@ -123,8 +124,7 @@ ERROR_NO_MEMORY:
return JsonObject::invalid();
}
inline bool ArduinoJson::Internals::JsonParser::parseObjectTo(
JsonVariant *destination) {
bool JsonParser::parseObjectTo(JsonVariant *destination) {
JsonObject &object = parseObject();
if (!object.success()) return false;
@ -132,7 +132,18 @@ inline bool ArduinoJson::Internals::JsonParser::parseObjectTo(
return true;
}
inline const char *ArduinoJson::Internals::JsonParser::parseString() {
static inline bool isInRange(char c, char min, char max) {
return min <= c && c <= max;
}
static inline bool isLetterOrNumber(char c) {
return isInRange(c, '0', '9') || isInRange(c, 'a', 'z') ||
isInRange(c, 'A', 'Z') || c == '-' || c == '.';
}
static inline bool isQuote(char c) { return c == '\'' || c == '\"'; }
const char *JsonParser::parseString() {
const char *readPtr = _readPtr;
char *writePtr = _writePtr;
@ -177,15 +188,14 @@ inline const char *ArduinoJson::Internals::JsonParser::parseString() {
return startPtr;
}
inline bool ArduinoJson::Internals::JsonParser::parseStringTo(
JsonVariant *destination) {
bool JsonParser::parseStringTo(JsonVariant *destination) {
bool hasQuotes = isQuote(_readPtr[0]);
const char *value = parseString();
if (value == NULL) return false;
if (hasQuotes) {
*destination = value;
} else {
*destination = RawJson(value);
*destination = Unparsed(value);
}
return true;
}

50
src/Internals/List.cpp Normal file
View File

@ -0,0 +1,50 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../../include/ArduinoJson/Internals/List.hpp"
#include "../../include/ArduinoJson/JsonPair.hpp"
#include "../../include/ArduinoJson/JsonVariant.hpp"
using namespace ArduinoJson;
using namespace ArduinoJson::Internals;
template <typename T>
size_t List<T>::size() const {
size_t nodeCount = 0;
for (node_type *node = _firstNode; node; node = node->next) nodeCount++;
return nodeCount;
}
template <typename T>
typename List<T>::node_type *List<T>::addNewNode() {
node_type *newNode = new (_buffer) node_type();
if (_firstNode) {
node_type *lastNode = _firstNode;
while (lastNode->next) lastNode = lastNode->next;
lastNode->next = newNode;
} else {
_firstNode = newNode;
}
return newNode;
}
template <typename T>
void List<T>::removeNode(node_type *nodeToRemove) {
if (!nodeToRemove) return;
if (nodeToRemove == _firstNode) {
_firstNode = nodeToRemove->next;
} else {
for (node_type *node = _firstNode; node; node = node->next)
if (node->next == nodeToRemove) node->next = nodeToRemove->next;
}
}
template class ArduinoJson::Internals::List<JsonPair>;
template class ArduinoJson::Internals::List<JsonVariant>;

View File

@ -0,0 +1,87 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../../include/ArduinoJson/Internals/Prettyfier.hpp"
using namespace ArduinoJson::Internals;
size_t Prettyfier::write(uint8_t c) {
size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c);
_previousChar = c;
return n;
}
inline size_t Prettyfier::handleStringChar(uint8_t c) {
bool isQuote = c == '"' && _previousChar != '\\';
if (isQuote) _inString = false;
return _sink.write(c);
}
inline size_t Prettyfier::handleMarkupChar(uint8_t c) {
switch (c) {
case '{':
case '[':
return handleBlockOpen(c);
case '}':
case ']':
return handleBlockClose(c);
case ':':
return handleColon();
case ',':
return handleComma();
case '"':
return handleQuoteOpen();
default:
return handleNormalChar(c);
}
}
inline size_t Prettyfier::handleBlockOpen(uint8_t c) {
return indentIfNeeded() + _sink.write(c);
}
inline size_t Prettyfier::handleBlockClose(uint8_t c) {
return unindentIfNeeded() + _sink.write(c);
}
inline size_t Prettyfier::handleColon() {
return _sink.write(':') + _sink.write(' ');
}
inline size_t Prettyfier::handleComma() {
return _sink.write(',') + _sink.println();
}
inline size_t Prettyfier::handleQuoteOpen() {
_inString = true;
return indentIfNeeded() + _sink.write('"');
}
inline size_t Prettyfier::handleNormalChar(uint8_t c) {
return indentIfNeeded() + _sink.write(c);
}
size_t Prettyfier::indentIfNeeded() {
if (!inEmptyBlock()) return 0;
_sink.indent();
return _sink.println();
}
size_t Prettyfier::unindentIfNeeded() {
if (inEmptyBlock()) return 0;
_sink.unindent();
return _sink.println();
}

View File

@ -0,0 +1,18 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../../include/ArduinoJson/Internals/StaticStringBuilder.hpp"
using namespace ArduinoJson::Internals;
size_t StaticStringBuilder::write(uint8_t c) {
if (length >= capacity) return 0;
buffer[length++] = c;
buffer[length] = '\0';
return 1;
}

40
src/JsonArray.cpp Normal file
View File

@ -0,0 +1,40 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../include/ArduinoJson/JsonArray.hpp"
#include "../include/ArduinoJson/JsonBuffer.hpp"
#include "../include/ArduinoJson/JsonObject.hpp"
using namespace ArduinoJson;
using namespace ArduinoJson::Internals;
JsonArray JsonArray::_invalid(NULL);
JsonArray::node_type *JsonArray::getNodeAt(size_t index) const {
node_type *node = _firstNode;
while (node && index--) node = node->next;
return node;
}
void JsonArray::removeAt(size_t index) { removeNode(getNodeAt(index)); }
void JsonArray::writeTo(JsonWriter &writer) const {
writer.beginArray();
const node_type *child = _firstNode;
while (child) {
child->content.writeTo(writer);
child = child->next;
if (!child) break;
writer.writeComma();
}
writer.endArray();
}

42
src/JsonBuffer.cpp Normal file
View File

@ -0,0 +1,42 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../include/ArduinoJson/JsonBuffer.hpp"
#include "../include/ArduinoJson/Internals/JsonParser.hpp"
#include "../include/ArduinoJson/JsonArray.hpp"
#include "../include/ArduinoJson/JsonObject.hpp"
using namespace ArduinoJson;
using namespace ArduinoJson::Internals;
JsonArray &JsonBuffer::createArray() {
JsonArray *ptr = new (this) JsonArray(this);
return ptr ? *ptr : JsonArray::invalid();
}
JsonObject &JsonBuffer::createObject() {
JsonObject *ptr = new (this) JsonObject(this);
return ptr ? *ptr : JsonObject::invalid();
}
JsonArray &JsonBuffer::parseArray(char *json, uint8_t nestingLimit) {
JsonParser parser(this, json, nestingLimit);
return parser.parseArray();
}
JsonObject &JsonBuffer::parseObject(char *json, uint8_t nestingLimit) {
JsonParser parser(this, json, nestingLimit);
return parser.parseObject();
}
char *JsonBuffer::strdup(const char *source, size_t length) {
size_t size = length + 1;
char *dest = static_cast<char *>(alloc(size));
if (dest != NULL) memcpy(dest, source, size);
return dest;
}

44
src/JsonObject.cpp Normal file
View File

@ -0,0 +1,44 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../include/ArduinoJson/JsonObject.hpp"
#include <string.h> // for strcmp
#include "../include/ArduinoJson/Internals/StaticStringBuilder.hpp"
#include "../include/ArduinoJson/JsonArray.hpp"
#include "../include/ArduinoJson/JsonBuffer.hpp"
using namespace ArduinoJson;
using namespace ArduinoJson::Internals;
JsonObject JsonObject::_invalid(NULL);
JsonObject::node_type *JsonObject::getNodeAt(const char *key) const {
for (node_type *node = _firstNode; node; node = node->next) {
if (!strcmp(node->content.key, key)) return node;
}
return NULL;
}
void JsonObject::writeTo(JsonWriter &writer) const {
writer.beginObject();
const node_type *node = _firstNode;
while (node) {
writer.writeString(node->content.key);
writer.writeColon();
node->content.value.writeTo(writer);
node = node->next;
if (!node) break;
writer.writeComma();
}
writer.endObject();
}

110
src/JsonVariant.cpp Normal file
View File

@ -0,0 +1,110 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include "../include/ArduinoJson/JsonVariant.hpp"
#include "../include/ArduinoJson/JsonArray.hpp"
#include "../include/ArduinoJson/JsonObject.hpp"
#include <errno.h> // for errno
#include <stdlib.h> // for strtol, strtod
using namespace ArduinoJson::Internals;
namespace ArduinoJson {
const char *JsonVariant::asString() const {
if (_type == JSON_UNPARSED && _content.asString &&
!strcmp("null", _content.asString))
return NULL;
if (_type == JSON_STRING || _type == JSON_UNPARSED) return _content.asString;
return NULL;
}
JsonFloat JsonVariant::asFloat() const {
if (_type >= JSON_FLOAT_0_DECIMALS) return _content.asFloat;
if (_type == JSON_INTEGER || _type == JSON_BOOLEAN)
return static_cast<JsonFloat>(_content.asInteger);
if ((_type == JSON_STRING || _type == JSON_UNPARSED) && _content.asString)
return parse<JsonFloat>(_content.asString);
return 0.0;
}
String JsonVariant::toString() const {
String s;
if ((_type == JSON_STRING || _type == JSON_UNPARSED) &&
_content.asString != NULL)
s = _content.asString;
else
printTo(s);
return s;
}
template <>
bool JsonVariant::is<bool>() const {
if (_type == JSON_BOOLEAN) return true;
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
return !strcmp(_content.asString, "true") ||
!strcmp(_content.asString, "false");
}
template <>
bool JsonVariant::is<signed long>() const {
if (_type == JSON_INTEGER) return true;
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
char *end;
errno = 0;
strtol(_content.asString, &end, 10);
return *end == '\0' && errno == 0;
}
template <>
bool JsonVariant::is<double>() const {
if (_type >= JSON_FLOAT_0_DECIMALS) return true;
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
char *end;
errno = 0;
strtod(_content.asString, &end);
return *end == '\0' && errno == 0 && !is<long>();
}
void JsonVariant::writeTo(JsonWriter &writer) const {
if (_type == JSON_ARRAY)
_content.asArray->writeTo(writer);
else if (_type == JSON_OBJECT)
_content.asObject->writeTo(writer);
else if (_type == JSON_STRING)
writer.writeString(_content.asString);
else if (_type == JSON_UNPARSED)
writer.writeRaw(_content.asString);
else if (_type == JSON_INTEGER)
writer.writeInteger(_content.asInteger);
else if (_type == JSON_BOOLEAN)
writer.writeBoolean(_content.asInteger != 0);
else if (_type >= JSON_FLOAT_0_DECIMALS) {
uint8_t decimals = static_cast<uint8_t>(_type - JSON_FLOAT_0_DECIMALS);
writer.writeFloat(_content.asFloat, decimals);
}
}
}

View File

@ -219,27 +219,3 @@ TEST_F(ArduinoStringTests, JsonObject_PrettyPrintTo) {
object.prettyPrintTo(json);
ASSERT_EQ(String("{\r\n \"key\": \"value\"\r\n}"), json);
}
TEST_F(ArduinoStringTests, JsonBuffer_GrowWhenAddingNewKey) {
JsonObject &object = _jsonBuffer.createObject();
String key1("hello"), key2("world");
object[key1] = 1;
size_t sizeBefore = _jsonBuffer.size();
object[key2] = 2;
size_t sizeAfter = _jsonBuffer.size();
ASSERT_GT(sizeAfter - sizeBefore, key2.size());
}
TEST_F(ArduinoStringTests, JsonBuffer_DontGrowWhenReusingKey) {
JsonObject &object = _jsonBuffer.createObject();
String key("hello");
object[key] = 1;
size_t sizeBefore = _jsonBuffer.size();
object[key] = 2;
size_t sizeAfter = _jsonBuffer.size();
ASSERT_EQ(sizeBefore, sizeAfter);
}

View File

@ -5,69 +5,31 @@
# https://github.com/bblanchon/ArduinoJson
# If you like this project, please add a star!
include(gtest.cmake)
set(GTEST_DIR ../third-party/gtest-1.7.0)
file(GLOB TESTS_FILES *.hpp *.cpp)
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
add_compile_options(
-fno-exceptions
-fno-rtti
-pedantic
-Wall
-Wcast-align
-Wcast-qual
-Wconversion
-Wctor-dtor-privacy
-Wdisabled-optimization
-Werror
-Wextra
-Wformat=2
-Winit-self
-Wmissing-include-dirs
-Wno-parentheses
-Wno-sign-conversion
-Wno-unused
-Wno-variadic-macros
-Wnon-virtual-dtor
-Wold-style-cast
-Woverloaded-virtual
-Wredundant-decls
-Wshadow
-Wsign-promo
-Wstrict-overflow=5
-Wundef
)
include_directories(
${GTEST_DIR}
${GTEST_DIR}/include)
add_definitions(-DGTEST_HAS_PTHREAD=0)
# Workaround for Visual Studio 2012
if (MSVC AND MSVC_VERSION EQUAL 1700)
add_definitions(-D_VARIADIC_MAX=10)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
add_compile_options(
-Wstrict-null-sentinel
)
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.5)
add_compile_options(-Wlogical-op) # the flag exists in 4.4 but is buggy
endif()
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.6)
add_compile_options(-Wnoexcept)
endif()
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(
-Wc++11-compat
-Wdeprecated-register
)
endif()
if(MSVC)
if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_compile_options(-W4)
endif()
add_executable(ArduinoJsonTests ${TESTS_FILES})
target_include_directories(ArduinoJsonTests PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../include)
target_link_libraries(ArduinoJsonTests gtest)
add_executable(ArduinoJsonTests
${TESTS_FILES}
${GTEST_DIR}/src/gtest-all.cc
${GTEST_DIR}/src/gtest_main.cc)
target_link_libraries(ArduinoJsonTests ArduinoJson)
add_test(ArduinoJsonTests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ArduinoJsonTests)

View File

@ -6,7 +6,11 @@
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#define protected public
#include <ArduinoJson/DynamicJsonBuffer.hpp>
using namespace ArduinoJson;
class DynamicJsonBuffer_Basic_Tests : public testing::Test {
protected:

48
test/Issue67.cpp Normal file
View File

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

View File

@ -14,11 +14,13 @@
#define SUITE Issue90
using namespace ArduinoJson::Internals;
static const char* superLong =
"12345678901234567890123456789012345678901234567890123456789012345678901234"
"5678901234567890123456789012345678901234567890123456789012345678901234567";
static const JsonVariant variant = RawJson(superLong);
static const JsonVariant variant = Unparsed(superLong);
TEST(SUITE, IsNotALong) { ASSERT_FALSE(variant.is<long>()); }

View File

@ -1,64 +0,0 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <ArduinoJson.h>
#include <gtest/gtest.h>
TEST(JsonArray_CopyFrom_Tests, OneDimension) {
DynamicJsonBuffer jsonBuffer;
JsonArray& array = jsonBuffer.createArray();
char json[32];
int source[] = {1, 2, 3};
bool ok = array.copyFrom(source);
ASSERT_TRUE(ok);
array.printTo(json, sizeof(json));
ASSERT_STREQ("[1,2,3]", json);
}
TEST(JsonArray_CopyFrom_Tests, OneDimension_JsonBufferTooSmall) {
const size_t SIZE = JSON_ARRAY_SIZE(2);
StaticJsonBuffer<SIZE> jsonBuffer;
JsonArray& array = jsonBuffer.createArray();
char json[32];
int source[] = {1, 2, 3};
bool ok = array.copyFrom(source);
ASSERT_FALSE(ok);
array.printTo(json, sizeof(json));
ASSERT_STREQ("[1,2]", json);
}
TEST(JsonArray_CopyFrom_Tests, TwoDimensions) {
DynamicJsonBuffer jsonBuffer;
JsonArray& array = jsonBuffer.createArray();
char json[32];
int source[][3] = {{1, 2, 3}, {4, 5, 6}};
bool ok = array.copyFrom(source);
ASSERT_TRUE(ok);
array.printTo(json, sizeof(json));
ASSERT_STREQ("[[1,2,3],[4,5,6]]", json);
}
TEST(JsonArray_CopyFrom_Tests, TwoDimensions_JsonBufferTooSmall) {
const size_t SIZE =
JSON_ARRAY_SIZE(2) + JSON_ARRAY_SIZE(3) + JSON_ARRAY_SIZE(2);
StaticJsonBuffer<SIZE> jsonBuffer;
JsonArray& array = jsonBuffer.createArray();
char json[32];
int source[][3] = {{1, 2, 3}, {4, 5, 6}};
bool ok = array.copyFrom(source);
ASSERT_FALSE(ok);
array.printTo(json, sizeof(json));
ASSERT_STREQ("[[1,2,3],[4,5]]", json);
}

View File

@ -1,56 +0,0 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <ArduinoJson.h>
#include <gtest/gtest.h>
TEST(JsonArray_CopyTo_Tests, BiggerOneDimensionIntegerArray) {
char json[] = "[1,2,3]";
DynamicJsonBuffer jsonBuffer;
JsonArray& array = jsonBuffer.parseArray(json);
int destination[4] = {0};
size_t result = array.copyTo(destination);
ASSERT_EQ(3, result);
ASSERT_EQ(1, destination[0]);
ASSERT_EQ(2, destination[1]);
ASSERT_EQ(3, destination[2]);
ASSERT_EQ(0, destination[3]);
}
TEST(JsonArray_CopyTo_Tests, SmallerOneDimensionIntegerArray) {
char json[] = "[1,2,3]";
DynamicJsonBuffer jsonBuffer;
JsonArray& array = jsonBuffer.parseArray(json);
int destination[2] = {0};
size_t result = array.copyTo(destination);
ASSERT_EQ(2, result);
ASSERT_EQ(1, destination[0]);
ASSERT_EQ(2, destination[1]);
}
TEST(JsonArray_CopyTo_Tests, TwoOneDimensionIntegerArray) {
char json[] = "[[1,2],[3],[4]]";
DynamicJsonBuffer jsonBuffer;
JsonArray& array = jsonBuffer.parseArray(json);
int destination[3][2] = {{0}};
array.copyTo(destination);
ASSERT_EQ(1, destination[0][0]);
ASSERT_EQ(2, destination[0][1]);
ASSERT_EQ(3, destination[1][0]);
ASSERT_EQ(0, destination[1][1]);
ASSERT_EQ(4, destination[2][0]);
ASSERT_EQ(0, destination[2][1]);
}

View File

@ -96,12 +96,6 @@ TEST_F(JsonArray_PrintTo_Tests, TwoIntegers) {
outputMustBe("[1,2]");
}
TEST_F(JsonArray_PrintTo_Tests, RawJson) {
array.add(RawJson("{\"key\":\"value\"}"));
outputMustBe("[{\"key\":\"value\"}]");
}
TEST_F(JsonArray_PrintTo_Tests, OneIntegerOverCapacity) {
array.add(1);
array.add(2);

View File

@ -5,8 +5,8 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <ArduinoJson.h>
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#include <stdint.h>
class JsonArray_Subscript_Tests : public ::testing::Test {
@ -33,14 +33,12 @@ TEST_(StoreInteger) {
EXPECT_FALSE(_array[0].is<double>());
}
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
TEST_(StoreLongLong) {
TEST_(StoreInt64) {
_array[0] = 9223372036854775807;
EXPECT_EQ(9223372036854775807, _array[0].as<long long>());
EXPECT_EQ(9223372036854775807, _array[0].as<int64_t>());
EXPECT_TRUE(_array[0].is<int>());
EXPECT_FALSE(_array[0].is<double>());
}
#endif
TEST_(StoreDouble) {
_array[0] = 123.45;
@ -59,7 +57,6 @@ TEST_(StoreBoolean) {
TEST_(StoreString) {
_array[0] = "hello";
EXPECT_STREQ("hello", _array[0].as<const char*>());
EXPECT_STREQ("hello", _array[0].as<char*>()); // <- short hand
EXPECT_TRUE(_array[0].is<const char*>());
EXPECT_FALSE(_array[0].is<int>());
}
@ -70,9 +67,6 @@ TEST_(StoreNestedArray) {
_array[0] = arr;
EXPECT_EQ(&arr, &_array[0].as<JsonArray&>());
EXPECT_EQ(&arr, &_array[0].as<JsonArray>()); // <- short hand
EXPECT_EQ(&arr, &_array[0].as<const JsonArray&>());
EXPECT_EQ(&arr, &_array[0].as<const JsonArray>()); // <- short hand
EXPECT_TRUE(_array[0].is<JsonArray&>());
EXPECT_FALSE(_array[0].is<int>());
}
@ -83,9 +77,6 @@ TEST_(StoreNestedObject) {
_array[0] = obj;
EXPECT_EQ(&obj, &_array[0].as<JsonObject&>());
EXPECT_EQ(&obj, &_array[0].as<JsonObject>()); // <- short hand
EXPECT_EQ(&obj, &_array[0].as<const JsonObject&>());
EXPECT_EQ(&obj, &_array[0].as<const JsonObject>()); // <- short hand
EXPECT_TRUE(_array[0].is<JsonObject&>());
EXPECT_FALSE(_array[0].is<int>());
}

View File

@ -8,6 +8,8 @@
#include <ArduinoJson.h>
#include <gtest/gtest.h>
using namespace ArduinoJson::Internals;
class JsonObject_PrintTo_Tests : public testing::Test {
public:
JsonObject_PrintTo_Tests() : _object(_jsonBuffer.createObject()) {}
@ -73,12 +75,6 @@ TEST_F(JsonObject_PrintTo_Tests, TwoIntegers) {
outputMustBe("{\"a\":1,\"b\":2}");
}
TEST_F(JsonObject_PrintTo_Tests, RawJson) {
_object["a"] = RawJson("[1,2]");
_object.set("b", RawJson("[4,5]"));
outputMustBe("{\"a\":[1,2],\"b\":[4,5]}");
}
TEST_F(JsonObject_PrintTo_Tests, TwoDoublesFourDigits) {
_object["a"] = double_with_n_digits(3.14159265358979323846, 4);
_object.set("b", 2.71828182845904523536, 4);

View File

@ -68,7 +68,6 @@ TEST_(StoreString) {
EXPECT_TRUE(_object["hello"].is<const char*>());
EXPECT_FALSE(_object["hello"].is<long>());
EXPECT_STREQ("h3110", _object["hello"].as<const char*>());
EXPECT_STREQ("h3110", _object["hello"].as<char*>()); // <- short hand
}
TEST_(StoreArray) {
@ -76,15 +75,8 @@ TEST_(StoreArray) {
_object["hello"] = arr;
EXPECT_EQ(&arr, &_object["hello"].asArray()); // <- DEPRECATED
EXPECT_EQ(&arr, &_object["hello"].as<JsonArray&>());
EXPECT_EQ(&arr, &_object["hello"].as<JsonArray>()); // <- short hand
EXPECT_EQ(&arr, &_object["hello"].as<const JsonArray&>());
EXPECT_EQ(&arr, &_object["hello"].as<const JsonArray>()); // <- short hand
EXPECT_EQ(&arr, &_object["hello"].asArray());
EXPECT_TRUE(_object["hello"].is<JsonArray&>());
EXPECT_TRUE(_object["hello"].is<JsonArray>());
EXPECT_TRUE(_object["hello"].is<const JsonArray&>());
EXPECT_TRUE(_object["hello"].is<const JsonArray>());
EXPECT_FALSE(_object["hello"].is<JsonObject&>());
}
@ -93,15 +85,8 @@ TEST_(StoreObject) {
_object["hello"] = obj;
EXPECT_EQ(&obj, &_object["hello"].asObject()); // DEPRECATED
EXPECT_EQ(&obj, &_object["hello"].as<JsonObject&>());
EXPECT_EQ(&obj, &_object["hello"].as<JsonObject>()); // <- short hand
EXPECT_EQ(&obj, &_object["hello"].as<const JsonObject&>());
EXPECT_EQ(&obj, &_object["hello"].as<const JsonObject>()); // <- short hand
EXPECT_EQ(&obj, &_object["hello"].asObject());
EXPECT_TRUE(_object["hello"].is<JsonObject&>());
EXPECT_TRUE(_object["hello"].is<JsonObject>());
EXPECT_TRUE(_object["hello"].is<const JsonObject&>());
EXPECT_TRUE(_object["hello"].is<const JsonObject>());
EXPECT_FALSE(_object["hello"].is<JsonArray&>());
}

View File

@ -125,14 +125,6 @@ TEST_F(JsonParser_Array_Tests, TwoDoubles) {
secondElementMustBe(1e2);
}
TEST_F(JsonParser_Array_Tests, UnsignedLong) {
whenInputIs("[4294967295]");
parseMustSucceed();
sizeMustBe(1);
firstElementMustBe(4294967295UL);
}
TEST_F(JsonParser_Array_Tests, TwoBooleans) {
whenInputIs("[true,false]");

View File

@ -1,91 +0,0 @@
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
class JsonParser_Variant_Test : public testing::Test {
protected:
void whenInputIs(const char* jsonString) {
strcpy(_jsonString, jsonString);
_result = _jsonBuffer.parse(_jsonString);
}
template <typename T>
void resultMustEqual(T expected) {
EXPECT_EQ(expected, _result.as<T>());
}
void resultMustEqual(const char* expected) {
EXPECT_STREQ(expected, _result.as<char*>());
}
template <typename T>
void resultTypeMustBe() {
EXPECT_TRUE(_result.is<T>());
}
void resultMustBeInvalid() { EXPECT_FALSE(_result.success()); }
void resultMustBeValid() { EXPECT_TRUE(_result.success()); }
private:
DynamicJsonBuffer _jsonBuffer;
JsonVariant _result;
char _jsonString[256];
};
TEST_F(JsonParser_Variant_Test, EmptyObject) {
whenInputIs("{}");
resultMustBeValid();
resultTypeMustBe<JsonObject>();
}
TEST_F(JsonParser_Variant_Test, EmptyArray) {
whenInputIs("[]");
resultMustBeValid();
resultTypeMustBe<JsonArray>();
}
TEST_F(JsonParser_Variant_Test, Integer) {
whenInputIs("42");
resultMustBeValid();
resultTypeMustBe<int>();
resultMustEqual(42);
}
TEST_F(JsonParser_Variant_Test, Double) {
whenInputIs("3.14");
resultMustBeValid();
resultTypeMustBe<double>();
resultMustEqual(3.14);
}
TEST_F(JsonParser_Variant_Test, String) {
whenInputIs("\"hello world\"");
resultMustBeValid();
resultTypeMustBe<char*>();
resultMustEqual("hello world");
}
TEST_F(JsonParser_Variant_Test, True) {
whenInputIs("true");
resultMustBeValid();
resultTypeMustBe<bool>();
resultMustEqual(true);
}
TEST_F(JsonParser_Variant_Test, False) {
whenInputIs("false");
resultMustBeValid();
resultTypeMustBe<bool>();
resultMustEqual(false);
}
TEST_F(JsonParser_Variant_Test, Invalid) {
whenInputIs("{");
resultMustBeInvalid();
}

View File

@ -5,9 +5,9 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#include <gtest/gtest.h>
#include <stdint.h>
static const char* null = 0;
@ -32,11 +32,6 @@ TEST(JsonVariant_As_Tests, DoubleAsLong) {
ASSERT_EQ(4L, variant.as<long>());
}
TEST(JsonVariant_As_Tests, DoubleAsUnsigned) {
JsonVariant variant = 4.2;
ASSERT_EQ(4U, variant.as<unsigned>());
}
TEST(JsonVariant_As_Tests, DoubleZeroAsBool) {
JsonVariant variant = 0.0;
ASSERT_FALSE(variant.as<bool>());
@ -97,16 +92,11 @@ TEST(JsonVariant_As_Tests, LongZeroAsBool) {
ASSERT_FALSE(variant.as<bool>());
}
TEST(JsonVariant_As_Tests, PositiveLongAsDouble) {
TEST(JsonVariant_As_Tests, LongAsDouble) {
JsonVariant variant = 42L;
ASSERT_EQ(42.0, variant.as<double>());
}
TEST(JsonVariant_As_Tests, NegativeLongAsDouble) {
JsonVariant variant = -42L;
ASSERT_EQ(-42.0, variant.as<double>());
}
TEST(JsonVariant_As_Tests, LongAsString) {
JsonVariant variant = 42L;
ASSERT_EQ(String("42"), variant.as<String>());
@ -147,17 +137,15 @@ TEST(JsonVariant_As_Tests, NumberStringAsLong) {
ASSERT_EQ(42L, variant.as<long>());
}
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
TEST(JsonVariant_As_Tests, NumberStringAsInt64Negative) {
JsonVariant variant = "-9223372036854775808";
ASSERT_EQ(-9223372036854775807 - 1, variant.as<long long>());
ASSERT_EQ(-9223372036854775807 - 1, variant.as<int64_t>());
}
TEST(JsonVariant_As_Tests, NumberStringAsInt64Positive) {
JsonVariant variant = "9223372036854775807";
ASSERT_EQ(9223372036854775807, variant.as<long long>());
ASSERT_EQ(9223372036854775807, variant.as<int64_t>());
}
#endif
TEST(JsonVariant_As_Tests, RandomStringAsBool) {
JsonVariant variant = "hello";
@ -169,16 +157,6 @@ TEST(JsonVariant_As_Tests, RandomStringAsLong) {
ASSERT_EQ(0L, variant.as<long>());
}
TEST(JsonVariant_As_Tests, RandomStringAsConstCharPtr) {
JsonVariant variant = "hello";
ASSERT_STREQ("hello", variant.as<const char*>());
}
TEST(JsonVariant_As_Tests, RandomStringAsCharPtr) {
JsonVariant variant = "hello";
ASSERT_STREQ("hello", variant.as<char*>());
}
TEST(JsonVariant_As_Tests, RandomStringAsString) {
JsonVariant variant = "hello";
ASSERT_EQ(String("hello"), variant.as<String>());
@ -214,21 +192,3 @@ TEST(JsonVariant_As_Tests, ArrayAsString) {
JsonVariant variant = arr;
ASSERT_EQ(String("[4,2]"), variant.as<String>());
}
TEST(JsonVariant_As_Tests, ArrayAsJsonArray) {
DynamicJsonBuffer buffer;
JsonArray& arr = buffer.createArray();
JsonVariant variant = arr;
ASSERT_EQ(&arr, &variant.as<JsonArray&>());
ASSERT_EQ(&arr, &variant.as<JsonArray>()); // <- shorthand
}
TEST(JsonVariant_As_Tests, ObjectAsJsonObject) {
DynamicJsonBuffer buffer;
JsonObject& arr = buffer.createObject();
JsonVariant variant = arr;
ASSERT_EQ(&arr, &variant.as<JsonObject&>());
ASSERT_EQ(&arr, &variant.as<JsonObject>()); // <- shorthand
}

View File

@ -6,7 +6,9 @@
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#include <ArduinoJson/JsonVariant.hpp>
using namespace ArduinoJson;
class JsonVariant_Comparison_Tests : public ::testing::Test {
protected:

View File

@ -10,6 +10,8 @@
#define SUITE JsonVariant_Is_Tests
using namespace ArduinoJson::Internals;
template <typename TTo, typename TFrom>
void assertIsNot(TFrom value) {
JsonVariant variant = value;
@ -74,35 +76,37 @@ TEST(SUITE, StringIsInt) { assertIsNot<int>("42"); }
TEST(SUITE, StringIsLong) { assertIsNot<long>("42"); }
TEST(SUITE, StringIsString) { assertIs<const char*>("42"); }
TEST(SUITE, UnparsedTrueIsArra) { assertIsNot<JsonArray&>(RawJson("true")); }
TEST(SUITE, UnparsedTrueIsBool) { assertIs<bool>(RawJson("true")); }
TEST(SUITE, UnparsedTrueIsDouble) { assertIsNot<double>(RawJson("true")); }
TEST(SUITE, UnparsedTrueIsFloat) { assertIsNot<float>(RawJson("true")); }
TEST(SUITE, UnparsedTrueIsInt) { assertIsNot<int>(RawJson("true")); }
TEST(SUITE, UnparsedTrueIsLong) { assertIsNot<long>(RawJson("true")); }
TEST(SUITE, UnparsedTrueIsString) { assertIsNot<const char*>(RawJson("true")); }
TEST(SUITE, UnparsedFalseIsArra) { assertIsNot<JsonArray&>(RawJson("false")); }
TEST(SUITE, UnparsedFalseIsBool) { assertIs<bool>(RawJson("false")); }
TEST(SUITE, UnparsedFalseIsDouble) { assertIsNot<double>(RawJson("false")); }
TEST(SUITE, UnparsedFalseIsFloat) { assertIsNot<float>(RawJson("false")); }
TEST(SUITE, UnparsedFalseIsInt) { assertIsNot<int>(RawJson("false")); }
TEST(SUITE, UnparsedFalseIsLong) { assertIsNot<long>(RawJson("false")); }
TEST(SUITE, UnparsedFalseIsString) {
assertIsNot<const char*>(RawJson("false"));
TEST(SUITE, UnparsedTrueIsArra) { assertIsNot<JsonArray&>(Unparsed("true")); }
TEST(SUITE, UnparsedTrueIsBool) { assertIs<bool>(Unparsed("true")); }
TEST(SUITE, UnparsedTrueIsDouble) { assertIsNot<double>(Unparsed("true")); }
TEST(SUITE, UnparsedTrueIsFloat) { assertIsNot<float>(Unparsed("true")); }
TEST(SUITE, UnparsedTrueIsInt) { assertIsNot<int>(Unparsed("true")); }
TEST(SUITE, UnparsedTrueIsLong) { assertIsNot<long>(Unparsed("true")); }
TEST(SUITE, UnparsedTrueIsString) {
assertIsNot<const char*>(Unparsed("true"));
}
TEST(SUITE, UnparsedIntIsArra) { assertIsNot<JsonArray&>(RawJson("42")); }
TEST(SUITE, UnparsedIntIsBool) { assertIsNot<bool>(RawJson("42")); }
TEST(SUITE, UnparsedIntIsDouble) { assertIsNot<double>(RawJson("42")); }
TEST(SUITE, UnparsedIntIsFloat) { assertIsNot<float>(RawJson("42")); }
TEST(SUITE, UnparsedIntIsInt) { assertIs<int>(RawJson("42")); }
TEST(SUITE, UnparsedIntIsLong) { assertIs<long>(RawJson("42")); }
TEST(SUITE, UnparsedIntIsString) { assertIsNot<const char*>(RawJson("42")); }
TEST(SUITE, UnparsedFalseIsArra) { assertIsNot<JsonArray&>(Unparsed("false")); }
TEST(SUITE, UnparsedFalseIsBool) { assertIs<bool>(Unparsed("false")); }
TEST(SUITE, UnparsedFalseIsDouble) { assertIsNot<double>(Unparsed("false")); }
TEST(SUITE, UnparsedFalseIsFloat) { assertIsNot<float>(Unparsed("false")); }
TEST(SUITE, UnparsedFalseIsInt) { assertIsNot<int>(Unparsed("false")); }
TEST(SUITE, UnparsedFalseIsLong) { assertIsNot<long>(Unparsed("false")); }
TEST(SUITE, UnparsedFalseIsString) {
assertIsNot<const char*>(Unparsed("false"));
}
TEST(SUITE, UnparsedFloatIsBool) { assertIsNot<bool>(RawJson("4.2e-10")); }
TEST(SUITE, UnparsedFloatIsDouble) { assertIs<double>(RawJson("4.2e-10")); }
TEST(SUITE, UnparsedFloatIsFloat) { assertIs<float>(RawJson("4.2e-10")); }
TEST(SUITE, UnparsedFloatIsInt) { assertIsNot<int>(RawJson("4.2e-10")); }
TEST(SUITE, UnparsedFloatIsLong) { assertIsNot<long>(RawJson("4.2e-10")); }
TEST(SUITE, UnparsedFloatIsStr) { assertIsNot<const char*>(RawJson("4.2")); }
TEST(SUITE, UnparsedIntIsArra) { assertIsNot<JsonArray&>(Unparsed("42")); }
TEST(SUITE, UnparsedIntIsBool) { assertIsNot<bool>(Unparsed("42")); }
TEST(SUITE, UnparsedIntIsDouble) { assertIsNot<double>(Unparsed("42")); }
TEST(SUITE, UnparsedIntIsFloat) { assertIsNot<float>(Unparsed("42")); }
TEST(SUITE, UnparsedIntIsInt) { assertIs<int>(Unparsed("42")); }
TEST(SUITE, UnparsedIntIsLong) { assertIs<long>(Unparsed("42")); }
TEST(SUITE, UnparsedIntIsString) { assertIsNot<const char*>(Unparsed("42")); }
TEST(SUITE, UnparsedFloatIsBool) { assertIsNot<bool>(Unparsed("4.2e-10")); }
TEST(SUITE, UnparsedFloatIsDouble) { assertIs<double>(Unparsed("4.2e-10")); }
TEST(SUITE, UnparsedFloatIsFloat) { assertIs<float>(Unparsed("4.2e-10")); }
TEST(SUITE, UnparsedFloatIsInt) { assertIsNot<int>(Unparsed("4.2e-10")); }
TEST(SUITE, UnparsedFloatIsLong) { assertIsNot<long>(Unparsed("4.2e-10")); }
TEST(SUITE, UnparsedFloatIsStr) { assertIsNot<const char*>(Unparsed("4.2")); }

View File

@ -7,7 +7,6 @@
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#include <limits>
class JsonVariant_PrintTo_Tests : public testing::Test {
protected:
@ -16,8 +15,8 @@ class JsonVariant_PrintTo_Tests : public testing::Test {
void outputMustBe(const char *expected) {
char buffer[256] = "";
size_t n = variant.printTo(buffer, sizeof(buffer));
ASSERT_STREQ(expected, buffer);
ASSERT_EQ(strlen(expected), n);
EXPECT_STREQ(expected, buffer);
EXPECT_EQ(strlen(expected), n);
}
};
@ -48,59 +47,19 @@ TEST_F(JsonVariant_PrintTo_Tests, DoubleFourDigits) {
outputMustBe("3.1416");
}
TEST_F(JsonVariant_PrintTo_Tests, Infinity) {
variant = std::numeric_limits<double>::infinity();
outputMustBe("Infinity");
}
TEST_F(JsonVariant_PrintTo_Tests, MinusInfinity) {
variant = -std::numeric_limits<double>::infinity();
outputMustBe("-Infinity");
}
TEST_F(JsonVariant_PrintTo_Tests, SignalingNaN) {
variant = std::numeric_limits<double>::signaling_NaN();
outputMustBe("NaN");
}
TEST_F(JsonVariant_PrintTo_Tests, QuietNaN) {
variant = std::numeric_limits<double>::quiet_NaN();
outputMustBe("NaN");
}
TEST_F(JsonVariant_PrintTo_Tests, VeryBigPositiveDouble) {
variant = JsonVariant(3.14159265358979323846e42, 4);
outputMustBe("3.1416e42");
}
TEST_F(JsonVariant_PrintTo_Tests, VeryBigNegativeDouble) {
variant = JsonVariant(-3.14159265358979323846e42, 4);
outputMustBe("-3.1416e42");
}
TEST_F(JsonVariant_PrintTo_Tests, VerySmallPositiveDouble) {
variant = JsonVariant(3.14159265358979323846e-42, 4);
outputMustBe("3.1416e-42");
}
TEST_F(JsonVariant_PrintTo_Tests, VerySmallNegativeDouble) {
variant = JsonVariant(-3.14159265358979323846e-42, 4);
outputMustBe("-3.1416e-42");
}
TEST_F(JsonVariant_PrintTo_Tests, Integer) {
variant = 42;
outputMustBe("42");
}
TEST_F(JsonVariant_PrintTo_Tests, NegativeLong) {
variant = -42;
outputMustBe("-42");
TEST_F(JsonVariant_PrintTo_Tests, Long) {
variant = 42L;
outputMustBe("42");
}
TEST_F(JsonVariant_PrintTo_Tests, UnsignedLong) {
variant = 4294967295UL;
outputMustBe("4294967295");
TEST_F(JsonVariant_PrintTo_Tests, Char) {
variant = '*';
outputMustBe("42");
}
TEST_F(JsonVariant_PrintTo_Tests, True) {
@ -113,7 +72,6 @@ TEST_F(JsonVariant_PrintTo_Tests, OneFalse) {
outputMustBe("false");
}
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
TEST_F(JsonVariant_PrintTo_Tests, NegativeInt64) {
variant = -9223372036854775807 - 1;
outputMustBe("-9223372036854775808");
@ -123,9 +81,3 @@ TEST_F(JsonVariant_PrintTo_Tests, PositiveInt64) {
variant = 9223372036854775807;
outputMustBe("9223372036854775807");
}
TEST_F(JsonVariant_PrintTo_Tests, UInt64) {
variant = 18446744073709551615;
outputMustBe("18446744073709551615");
}
#endif

View File

@ -5,9 +5,9 @@
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <stdint.h>
#include <limits>
#include <gtest/gtest.h>
#include <ArduinoJson.h>
class JsonVariant_Storage_Tests : public ::testing::Test {
@ -37,11 +37,9 @@ class JsonVariant_Storage_Tests : public ::testing::Test {
}
};
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
TEST_F(JsonVariant_Storage_Tests, SizeOfJsonInteger) {
ASSERT_EQ(8, sizeof(Internals::JsonInteger));
}
#endif
TEST_F(JsonVariant_Storage_Tests, Null) { testValue<const char *>(NULL); }
TEST_F(JsonVariant_Storage_Tests, String) { testValue<const char *>("hello"); }
@ -59,21 +57,15 @@ TEST_F(JsonVariant_Storage_Tests, UChar) { testNumericType<unsigned char>(); }
TEST_F(JsonVariant_Storage_Tests, UInt) { testNumericType<unsigned int>(); }
TEST_F(JsonVariant_Storage_Tests, ULong) { testNumericType<unsigned long>(); }
TEST_F(JsonVariant_Storage_Tests, UShort) { testNumericType<unsigned short>(); }
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
TEST_F(JsonVariant_Storage_Tests, LongLong) { testNumericType<unsigned long long>(); }
TEST_F(JsonVariant_Storage_Tests, ULongLong) { testNumericType<unsigned long long>(); }
#endif
TEST_F(JsonVariant_Storage_Tests, Int8) { testNumericType<int8_t>(); }
TEST_F(JsonVariant_Storage_Tests, Uint8) { testNumericType<uint8_t>(); }
TEST_F(JsonVariant_Storage_Tests, Int16) { testNumericType<int16_t>(); }
TEST_F(JsonVariant_Storage_Tests, Uint16) { testNumericType<uint16_t>(); }
TEST_F(JsonVariant_Storage_Tests, Int32) { testNumericType<int32_t>(); }
TEST_F(JsonVariant_Storage_Tests, Uint32) { testNumericType<uint32_t>(); }
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
TEST_F(JsonVariant_Storage_Tests, Int64) { testNumericType<int64_t>(); }
TEST_F(JsonVariant_Storage_Tests, Uint8) { testNumericType<uint8_t>(); }
TEST_F(JsonVariant_Storage_Tests, Uint16) { testNumericType<uint16_t>(); }
TEST_F(JsonVariant_Storage_Tests, Uint32) { testNumericType<uint32_t>(); }
TEST_F(JsonVariant_Storage_Tests, Uint64) { testNumericType<uint64_t>(); }
#endif
TEST_F(JsonVariant_Storage_Tests, CanStoreObject) {
DynamicJsonBuffer jsonBuffer;

View File

@ -17,10 +17,6 @@ TEST_F(JsonVariant_Undefined_Tests, AsLongReturns0) {
EXPECT_EQ(0, variant.as<long>());
}
TEST_F(JsonVariant_Undefined_Tests, AsUnsignedReturns0) {
EXPECT_EQ(0, variant.as<unsigned>());
}
TEST_F(JsonVariant_Undefined_Tests, AsStringReturnsNull) {
EXPECT_EQ(0, variant.asString());
}

View File

@ -6,7 +6,11 @@
// If you like this project, please add a star!
#include <gtest/gtest.h>
#include <ArduinoJson.h>
#define protected public
#include <ArduinoJson/StaticJsonBuffer.hpp>
using namespace ArduinoJson;
class StaticJsonBuffer_Basic_Tests : public testing::Test {
protected:

View File

@ -10,13 +10,9 @@
class StaticJsonBuffer_ParseArray_Tests : public testing::Test {
protected:
void with(JsonBuffer& jsonBuffer) {
_jsonBuffer = &jsonBuffer;
}
void with(JsonBuffer& jsonBuffer) { _jsonBuffer = &jsonBuffer; }
void whenInputIs(const char* json) {
strcpy(_jsonString, json);
}
void whenInputIs(const char* json) { strcpy(_jsonString, json); }
void parseMustSucceed() {
EXPECT_TRUE(_jsonBuffer->parseArray(_jsonString).success());
@ -77,12 +73,9 @@ TEST_F(StaticJsonBuffer_ParseArray_Tests,
}
TEST_F(StaticJsonBuffer_ParseArray_Tests, CharPtrNull) {
ASSERT_FALSE(
StaticJsonBuffer<100>().parseArray(static_cast<char*>(0)).success());
ASSERT_FALSE(StaticJsonBuffer<100>().parseArray((char*)0).success());
}
TEST_F(StaticJsonBuffer_ParseArray_Tests, ConstCharPtrNull) {
ASSERT_FALSE(StaticJsonBuffer<100>()
.parseArray(static_cast<const char*>(0))
.success());
ASSERT_FALSE(StaticJsonBuffer<100>().parseArray((const char*)0).success());
}

View File

@ -10,13 +10,9 @@
class StaticJsonBuffer_ParseObject_Tests : public testing::Test {
protected:
void with(JsonBuffer& jsonBuffer) {
_jsonBuffer = &jsonBuffer;
}
void with(JsonBuffer& jsonBuffer) { _jsonBuffer = &jsonBuffer; }
void whenInputIs(const char* json) {
strcpy(_jsonString, json);
}
void whenInputIs(const char* json) { strcpy(_jsonString, json); }
void parseMustSucceed() {
EXPECT_TRUE(_jsonBuffer->parseObject(_jsonString).success());
@ -78,12 +74,9 @@ TEST_F(StaticJsonBuffer_ParseObject_Tests,
}
TEST_F(StaticJsonBuffer_ParseObject_Tests, CharPtrNull) {
ASSERT_FALSE(
StaticJsonBuffer<100>().parseObject(static_cast<char*>(0)).success());
ASSERT_FALSE(StaticJsonBuffer<100>().parseObject((char*)0).success());
}
TEST_F(StaticJsonBuffer_ParseObject_Tests, ConstCharPtrNull) {
ASSERT_FALSE(StaticJsonBuffer<100>()
.parseObject(static_cast<const char*>(0))
.success());
ASSERT_FALSE(StaticJsonBuffer<100>().parseObject((const char*)0).success());
}

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