diff --git a/.clang-format b/.clang-format index b5681465..36809363 100644 --- a/.clang-format +++ b/.clang-format @@ -1,4 +1,5 @@ # http://clang.llvm.org/docs/ClangFormatStyleOptions.html BasedOnStyle: Google -Standard: Cpp03 \ No newline at end of file +Standard: Cpp03 +AllowShortFunctionsOnASingleLine: Empty diff --git a/ArduinoJson.h b/ArduinoJson.h index ba9d3c72..6dc6b0ca 100644 --- a/ArduinoJson.h +++ b/ArduinoJson.h @@ -5,10 +5,4 @@ // 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" diff --git a/CHANGELOG.md b/CHANGELOG.md index f5b4f54e..732fc25d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ ArduinoJson: change log ======================= +HEAD +---- + +* ArduinoJson is now a header-only library (issue #199) + v5.5.1 ------ diff --git a/CMakeLists.txt b/CMakeLists.txt index 3dcfa7ea..b8328b92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ # https://github.com/bblanchon/ArduinoJson # If you like this project, please add a star! -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.0) project(ArduinoJson) enable_testing() @@ -18,5 +18,4 @@ if(${COVERAGE}) set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") endif() -add_subdirectory(src) add_subdirectory(test) diff --git a/include/ArduinoJson.h b/include/ArduinoJson.h index 1fd70a79..ec279cc2 100644 --- a/include/ArduinoJson.h +++ b/include/ArduinoJson.h @@ -5,9 +5,5 @@ // https://github.com/bblanchon/ArduinoJson // If you like this project, please add a star! -#include "ArduinoJson/DynamicJsonBuffer.hpp" -#include "ArduinoJson/JsonArray.hpp" -#include "ArduinoJson/JsonObject.hpp" -#include "ArduinoJson/StaticJsonBuffer.hpp" - +#include "ArduinoJson.hpp" using namespace ArduinoJson; diff --git a/include/ArduinoJson.hpp b/include/ArduinoJson.hpp new file mode 100644 index 00000000..7c38e641 --- /dev/null +++ b/include/ArduinoJson.hpp @@ -0,0 +1,19 @@ +// Copyright Benoit Blanchon 2014-2016 +// MIT License +// +// Arduino JSON library +// https://github.com/bblanchon/ArduinoJson +// If you like this project, please add a star! + +#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; diff --git a/include/ArduinoJson/Internals/BlockJsonBuffer.hpp b/include/ArduinoJson/Internals/BlockJsonBuffer.hpp index 66f72219..3dff178f 100644 --- a/include/ArduinoJson/Internals/BlockJsonBuffer.hpp +++ b/include/ArduinoJson/Internals/BlockJsonBuffer.hpp @@ -11,12 +11,26 @@ #include +#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 @@ -51,7 +65,6 @@ class BlockJsonBuffer : public JsonBuffer { return total; } - protected: virtual void* alloc(size_t bytes) { return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes); } @@ -92,3 +105,11 @@ 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 diff --git a/include/ArduinoJson/Internals/Comments.hpp b/include/ArduinoJson/Internals/Comments.hpp index 5e065271..6e62066a 100644 --- a/include/ArduinoJson/Internals/Comments.hpp +++ b/include/ArduinoJson/Internals/Comments.hpp @@ -9,6 +9,48 @@ namespace ArduinoJson { namespace Internals { -const char *skipSpacesAndComments(const char *ptr); +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; + } + } +} } } diff --git a/include/ArduinoJson/Internals/Encoding.hpp b/include/ArduinoJson/Internals/Encoding.hpp index 571f6087..017894ad 100644 --- a/include/ArduinoJson/Internals/Encoding.hpp +++ b/include/ArduinoJson/Internals/Encoding.hpp @@ -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; + const char *p = escapeTable(false); 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 + 4; + const char *p = escapeTable(true); for (;;) { if (p[0] == '\0') return c; if (p[0] == c) return p[1]; @@ -34,7 +34,9 @@ class Encoding { } private: - static const char _escapeTable[]; + static const char *escapeTable(bool excludeIdenticals) { + return &"\"\"\\\\b\bf\fn\nr\rt\t"[excludeIdenticals ? 4 : 0]; + } }; } } diff --git a/include/ArduinoJson/Internals/IndentedPrint.hpp b/include/ArduinoJson/Internals/IndentedPrint.hpp index 6bc0009d..6984fab1 100644 --- a/include/ArduinoJson/Internals/IndentedPrint.hpp +++ b/include/ArduinoJson/Internals/IndentedPrint.hpp @@ -23,7 +23,13 @@ class IndentedPrint : public Print { isNewLine = true; } - virtual size_t write(uint8_t); + virtual size_t write(uint8_t c) { + size_t n = 0; + if (isNewLine) n += writeTabs(); + n += sink->write(c); + isNewLine = c == '\n'; + return n; + } // Adds one level of indentation void indent() { @@ -46,7 +52,11 @@ class IndentedPrint : public Print { uint8_t tabSize : 3; bool isNewLine : 1; - size_t writeTabs(); + size_t writeTabs() { + size_t n = 0; + for (int i = 0; i < level * tabSize; i++) n += sink->write(' '); + return n; + } 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 diff --git a/include/ArduinoJson/Internals/JsonParser.hpp b/include/ArduinoJson/Internals/JsonParser.hpp index 6f634c6c..88fe845e 100644 --- a/include/ArduinoJson/Internals/JsonParser.hpp +++ b/include/ArduinoJson/Internals/JsonParser.hpp @@ -44,6 +44,19 @@ 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; diff --git a/src/Internals/JsonParser.cpp b/include/ArduinoJson/Internals/JsonParser.ipp similarity index 74% rename from src/Internals/JsonParser.cpp rename to include/ArduinoJson/Internals/JsonParser.ipp index 0420d07d..088670d3 100644 --- a/src/Internals/JsonParser.cpp +++ b/include/ArduinoJson/Internals/JsonParser.ipp @@ -5,18 +5,10 @@ // https://github.com/bblanchon/ArduinoJson // If you like this project, please add a star! -#include "../../include/ArduinoJson/Internals/JsonParser.hpp" +#include "JsonParser.hpp" +#include "Comments.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" - -using namespace ArduinoJson; -using namespace ArduinoJson::Internals; - -bool JsonParser::skip(char charToSkip) { +inline bool ArduinoJson::Internals::JsonParser::skip(char charToSkip) { const char *ptr = skipSpacesAndComments(_readPtr); if (*ptr != charToSkip) return false; ptr++; @@ -24,7 +16,8 @@ bool JsonParser::skip(char charToSkip) { return true; } -bool JsonParser::parseAnythingTo(JsonVariant *destination) { +inline bool ArduinoJson::Internals::JsonParser::parseAnythingTo( + JsonVariant *destination) { if (_nestingLimit == 0) return false; _nestingLimit--; bool success = parseAnythingToUnsafe(destination); @@ -32,7 +25,8 @@ bool JsonParser::parseAnythingTo(JsonVariant *destination) { return success; } -inline bool JsonParser::parseAnythingToUnsafe(JsonVariant *destination) { +inline bool ArduinoJson::Internals::JsonParser::parseAnythingToUnsafe( + JsonVariant *destination) { _readPtr = skipSpacesAndComments(_readPtr); switch (*_readPtr) { @@ -47,7 +41,8 @@ inline bool JsonParser::parseAnythingToUnsafe(JsonVariant *destination) { } } -JsonArray &JsonParser::parseArray() { +inline ArduinoJson::JsonArray & +ArduinoJson::Internals::JsonParser::parseArray() { // Create an empty array JsonArray &array = _buffer->createArray(); @@ -78,7 +73,8 @@ ERROR_NO_MEMORY: return JsonArray::invalid(); } -bool JsonParser::parseArrayTo(JsonVariant *destination) { +inline bool ArduinoJson::Internals::JsonParser::parseArrayTo( + JsonVariant *destination) { JsonArray &array = parseArray(); if (!array.success()) return false; @@ -86,7 +82,8 @@ bool JsonParser::parseArrayTo(JsonVariant *destination) { return true; } -JsonObject &JsonParser::parseObject() { +inline ArduinoJson::JsonObject & +ArduinoJson::Internals::JsonParser::parseObject() { // Create an empty object JsonObject &object = _buffer->createObject(); @@ -124,7 +121,8 @@ ERROR_NO_MEMORY: return JsonObject::invalid(); } -bool JsonParser::parseObjectTo(JsonVariant *destination) { +inline bool ArduinoJson::Internals::JsonParser::parseObjectTo( + JsonVariant *destination) { JsonObject &object = parseObject(); if (!object.success()) return false; @@ -132,18 +130,7 @@ bool JsonParser::parseObjectTo(JsonVariant *destination) { return true; } -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() { +inline const char *ArduinoJson::Internals::JsonParser::parseString() { const char *readPtr = _readPtr; char *writePtr = _writePtr; @@ -188,7 +175,8 @@ const char *JsonParser::parseString() { return startPtr; } -bool JsonParser::parseStringTo(JsonVariant *destination) { +inline bool ArduinoJson::Internals::JsonParser::parseStringTo( + JsonVariant *destination) { bool hasQuotes = isQuote(_readPtr[0]); const char *value = parseString(); if (value == NULL) return false; diff --git a/include/ArduinoJson/Internals/JsonWriter.hpp b/include/ArduinoJson/Internals/JsonWriter.hpp index a73621be..ba6da82f 100644 --- a/include/ArduinoJson/Internals/JsonWriter.hpp +++ b/include/ArduinoJson/Internals/JsonWriter.hpp @@ -7,12 +7,12 @@ #pragma once +#include "../Polyfills/attributes.hpp" #include "../Polyfills/isInfinity.hpp" #include "../Polyfills/isNaN.hpp" #include "../Polyfills/normalize.hpp" #include "../Print.hpp" #include "Encoding.hpp" -#include "ForceInline.hpp" #include "JsonFloat.hpp" #include "JsonInteger.hpp" diff --git a/include/ArduinoJson/Internals/List.hpp b/include/ArduinoJson/Internals/List.hpp index 36e1af67..2c01bfbc 100644 --- a/include/ArduinoJson/Internals/List.hpp +++ b/include/ArduinoJson/Internals/List.hpp @@ -36,21 +36,56 @@ 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 size() const { + size_t nodeCount = 0; + for (node_type *node = _firstNode; node; node = node->next) nodeCount++; + return nodeCount; + } - 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(); - void removeNode(node_type *nodeToRemove); + 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; + } + } JsonBuffer *_buffer; node_type *_firstNode; diff --git a/include/ArduinoJson/Internals/Prettyfier.hpp b/include/ArduinoJson/Internals/Prettyfier.hpp index 3634f3ef..0136b1c0 100644 --- a/include/ArduinoJson/Internals/Prettyfier.hpp +++ b/include/ArduinoJson/Internals/Prettyfier.hpp @@ -20,24 +20,89 @@ class Prettyfier : public Print { _inString = false; } - virtual size_t write(uint8_t); + virtual size_t write(uint8_t c) { + size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c); + _previousChar = c; + return n; + } private: Prettyfier& operator=(const Prettyfier&); // cannot be assigned - bool inEmptyBlock() { return _previousChar == '{' || _previousChar == '['; } + bool inEmptyBlock() { + return _previousChar == '{' || _previousChar == '['; + } - size_t handleStringChar(uint8_t); - size_t handleMarkupChar(uint8_t); + size_t handleStringChar(uint8_t c) { + bool isQuote = c == '"' && _previousChar != '\\'; - 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(); + 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(); + } uint8_t _previousChar; IndentedPrint& _sink; diff --git a/include/ArduinoJson/Internals/StaticStringBuilder.hpp b/include/ArduinoJson/Internals/StaticStringBuilder.hpp index a44800fc..34bf00dd 100644 --- a/include/ArduinoJson/Internals/StaticStringBuilder.hpp +++ b/include/ArduinoJson/Internals/StaticStringBuilder.hpp @@ -20,7 +20,13 @@ class StaticStringBuilder : public Print { buffer[0] = '\0'; } - virtual size_t write(uint8_t c); + virtual size_t write(uint8_t c) { + if (length >= capacity) return 0; + + buffer[length++] = c; + buffer[length] = '\0'; + return 1; + } private: char *buffer; diff --git a/include/ArduinoJson/JsonArray.hpp b/include/ArduinoJson/JsonArray.hpp index 88e5f880..adfb3625 100644 --- a/include/ArduinoJson/JsonArray.hpp +++ b/include/ArduinoJson/JsonArray.hpp @@ -56,10 +56,12 @@ class JsonArray : public Internals::JsonPrintable, : Internals::List(buffer) {} // Gets the value at the specified index - FORCE_INLINE JsonVariant operator[](size_t index) const; + JsonVariant operator[](size_t index) const { + return get(index); + } // Gets or sets the value at specified index - FORCE_INLINE JsonArraySubscript operator[](size_t index); + JsonArraySubscript operator[](size_t index); // Adds the specified value at the end of the array. // @@ -72,7 +74,7 @@ class JsonArray : public Internals::JsonPrintable, // bool add(double value); // bool add(const char*); template - FORCE_INLINE bool add( + bool add( T value, typename TypeTraits::EnableIf< CanSet::value && !TypeTraits::IsReference::value>::type * = 0) { @@ -83,18 +85,16 @@ class JsonArray : public Internals::JsonPrintable, // bool add(JsonArray&); // bool add(JsonObject&); template - FORCE_INLINE bool add( - const T &value, - typename TypeTraits::EnableIf::value>::type * = 0) { + bool add(const T &value, + typename TypeTraits::EnableIf::value>::type * = 0) { return addNode(const_cast(value)); } // bool add(float value, uint8_t decimals); // bool add(double value, uint8_t decimals); template - FORCE_INLINE bool add( - T value, uint8_t decimals, - typename TypeTraits::EnableIf::value>::type - * = 0) { + bool add(T value, uint8_t decimals, + typename TypeTraits::EnableIf< + TypeTraits::IsFloatingPoint::value>::type * = 0) { return addNode(JsonVariant(value, decimals)); } @@ -105,7 +105,7 @@ class JsonArray : public Internals::JsonPrintable, // bool set(size_t index, int value); // bool set(size_t index, short value); template - FORCE_INLINE bool set( + bool set( size_t index, T value, typename TypeTraits::EnableIf< CanSet::value && !TypeTraits::IsReference::value>::type * = 0) { @@ -116,31 +116,38 @@ class JsonArray : public Internals::JsonPrintable, // bool set(size_t index, JsonArray&); // bool set(size_t index, JsonObject&); template - FORCE_INLINE bool set( - size_t index, const T &value, - typename TypeTraits::EnableIf::value>::type * = 0) { + bool set(size_t index, const T &value, + typename TypeTraits::EnableIf::value>::type * = 0) { return setNodeAt(index, const_cast(value)); } // bool set(size_t index, float value, uint8_t decimals = 2); // bool set(size_t index, double value, uint8_t decimals = 2); template - FORCE_INLINE bool set( - size_t index, T value, uint8_t decimals, - typename TypeTraits::EnableIf::value>::type - * = 0) { + bool set(size_t index, T value, uint8_t decimals, + typename TypeTraits::EnableIf< + TypeTraits::IsFloatingPoint::value>::type * = 0) { return setNodeAt(index, JsonVariant(value, decimals)); } // Gets the value at the specified index. - FORCE_INLINE JsonVariant get(size_t index) const; + JsonVariant get(size_t index) const { + node_type *node = getNodeAt(index); + return node ? node->content : JsonVariant(); + } // Gets the value at the specified index. template - FORCE_INLINE T get(size_t index) const; + T get(size_t index) const { + node_type *node = getNodeAt(index); + return node ? node->content.as() : JsonVariant::defaultValue(); + } // Check the type of the value at specified index. template - FORCE_INLINE bool is(size_t index) const; + bool is(size_t index) const { + node_type *node = getNodeAt(index); + return node ? node->content.is() : false; + } // Creates a JsonArray and adds a reference at the end of the array. // It's a shortcut for JsonBuffer::createArray() and JsonArray::add() @@ -151,15 +158,34 @@ class JsonArray : public Internals::JsonPrintable, JsonObject &createNestedObject(); // Removes element at specified index. - void removeAt(size_t index); + void removeAt(size_t index) { + removeNode(getNodeAt(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() { return _invalid; } + static JsonArray &invalid() { + static JsonArray instance(NULL); + return instance; + } // Serialize the array to the specified JsonWriter. - void writeTo(Internals::JsonWriter &writer) const; + 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 @@ -215,20 +241,28 @@ class JsonArray : public Internals::JsonPrintable, } private: - node_type *getNodeAt(size_t index) const; + node_type *getNodeAt(size_t index) const { + node_type *node = _firstNode; + while (node && index--) node = node->next; + return node; + } template - bool setNodeAt(size_t index, TValue value); + bool setNodeAt(size_t index, TValue value) { + node_type *node = getNodeAt(index); + return node != NULL && setNodeValue(node, value); + } template - bool addNode(TValue); + bool addNode(TValue value) { + node_type *node = addNewNode(); + return node != NULL && setNodeValue(node, value); + } template - FORCE_INLINE bool setNodeValue(node_type *, T value); - - // The instance returned by JsonArray::invalid() - static JsonArray _invalid; + bool setNodeValue(node_type *node, T value) { + node->content = value; + return true; + } }; } - -#include "JsonArray.ipp" diff --git a/include/ArduinoJson/JsonArray.ipp b/include/ArduinoJson/JsonArray.ipp index d46d7364..b5268476 100644 --- a/include/ArduinoJson/JsonArray.ipp +++ b/include/ArduinoJson/JsonArray.ipp @@ -13,32 +13,6 @@ 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 -inline bool JsonArray::addNode(TValue value) { - node_type *node = addNewNode(); - return node != NULL && setNodeValue(node, value); -} - -template -inline bool JsonArray::setNodeAt(size_t index, TValue value) { - node_type *node = getNodeAt(index); - return node != NULL && setNodeValue(node, value); -} - -template -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); @@ -47,29 +21,6 @@ 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 -inline T JsonArray::get(size_t index) const { - node_type *node = getNodeAt(index); - return node ? node->content.as() : JsonVariant::defaultValue(); -} - -template -inline bool JsonArray::is(size_t index) const { - node_type *node = getNodeAt(index); - return node ? node->content.is() : false; -} - -template -inline const JsonArraySubscript JsonVariantBase::operator[]( - int index) const { - return asArray()[index]; -} - template <> inline JsonArray &JsonVariant::defaultValue() { return JsonArray::invalid(); diff --git a/include/ArduinoJson/JsonArraySubscript.hpp b/include/ArduinoJson/JsonArraySubscript.hpp index 8c489680..6076476c 100644 --- a/include/ArduinoJson/JsonArraySubscript.hpp +++ b/include/ArduinoJson/JsonArraySubscript.hpp @@ -77,6 +77,16 @@ inline std::ostream& operator<<(std::ostream& os, } #endif +inline JsonArraySubscript JsonArray::operator[](size_t index) { + return JsonArraySubscript(*this, index); +} + +template +inline const JsonArraySubscript JsonVariantBase::operator[]( + int index) const { + return asArray()[index]; +} + } // namespace ArduinoJson #ifdef _MSC_VER diff --git a/include/ArduinoJson/JsonBuffer.ipp b/include/ArduinoJson/JsonBuffer.ipp new file mode 100644 index 00000000..3099861b --- /dev/null +++ b/include/ArduinoJson/JsonBuffer.ipp @@ -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 "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(alloc(size)); + if (dest != NULL) memcpy(dest, source, size); + return dest; +} diff --git a/include/ArduinoJson/JsonObject.hpp b/include/ArduinoJson/JsonObject.hpp index 8a26a3a6..0cef1292 100644 --- a/include/ArduinoJson/JsonObject.hpp +++ b/include/ArduinoJson/JsonObject.hpp @@ -52,15 +52,16 @@ class JsonObject : public Internals::JsonPrintable, // Create an empty JsonArray attached to the specified JsonBuffer. // You should not use this constructor directly. // Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject(). - FORCE_INLINE explicit JsonObject(JsonBuffer* buffer) - : Internals::List(buffer) {} + explicit JsonObject(JsonBuffer* buffer) : Internals::List(buffer) {} // Gets or sets the value associated with the specified key. - FORCE_INLINE JsonObjectSubscript operator[](const char* key); - FORCE_INLINE JsonObjectSubscript operator[](const String& key); + JsonObjectSubscript operator[](const char* key); + JsonObjectSubscript operator[](const String& key); // Gets the value associated with the specified key. - FORCE_INLINE JsonVariant operator[](JsonObjectKey key) const; + JsonVariant operator[](JsonObjectKey key) const { + return get(key); + } // Sets the specified key with the specified value. // bool set(TKey key, bool value); @@ -73,7 +74,7 @@ class JsonObject : public Internals::JsonPrintable, // bool set(TKey key, const char* value); // bool set(TKey key, RawJson value); template - FORCE_INLINE bool set( + bool set( JsonObjectKey key, T value, typename TypeTraits::EnableIf< CanSet::value && !TypeTraits::IsReference::value>::type* = 0) { @@ -84,71 +85,117 @@ class JsonObject : public Internals::JsonPrintable, // bool set(Key, JsonObject&); // bool set(Key, JsonVariant&); template - FORCE_INLINE bool set( - JsonObjectKey key, const T& value, - typename TypeTraits::EnableIf::value>::type* = 0) { + bool set(JsonObjectKey key, const T& value, + typename TypeTraits::EnableIf::value>::type* = 0) { return setNodeAt(key, const_cast(value)); } // bool set(Key, float value, uint8_t decimals); // bool set(Key, double value, uint8_t decimals); template - FORCE_INLINE bool set( - JsonObjectKey key, TValue value, uint8_t decimals, - typename TypeTraits::EnableIf< - TypeTraits::IsFloatingPoint::value>::type* = 0) { + bool set(JsonObjectKey key, TValue value, uint8_t decimals, + typename TypeTraits::EnableIf< + TypeTraits::IsFloatingPoint::value>::type* = 0) { return setNodeAt(key, JsonVariant(value, decimals)); } // Gets the value associated with the specified key. - FORCE_INLINE JsonVariant get(JsonObjectKey) const; + JsonVariant get(JsonObjectKey key) const { + node_type* node = getNodeAt(key.c_str()); + return node ? node->content.value : JsonVariant(); + } // Gets the value associated with the specified key. template - FORCE_INLINE T get(JsonObjectKey) const; + T get(JsonObjectKey key) const { + node_type* node = getNodeAt(key.c_str()); + return node ? node->content.value.as() : JsonVariant::defaultValue(); + } // Checks the type of the value associated with the specified key. template - FORCE_INLINE bool is(JsonObjectKey) const; + bool is(JsonObjectKey key) const { + node_type* node = getNodeAt(key.c_str()); + return node ? node->content.value.is() : false; + } // Creates and adds a JsonArray. // This is a shortcut for JsonBuffer::createArray() and JsonObject::add(). - FORCE_INLINE JsonArray& createNestedArray(JsonObjectKey key); + JsonArray& createNestedArray(JsonObjectKey key); // Creates and adds a JsonObject. // This is a shortcut for JsonBuffer::createObject() and JsonObject::add(). - FORCE_INLINE JsonObject& createNestedObject(JsonObjectKey key); + JsonObject& createNestedObject(JsonObjectKey key); // Tells weither the specified key is present and associated with a value. - FORCE_INLINE bool containsKey(JsonObjectKey key) const; + bool containsKey(JsonObjectKey key) const { + return getNodeAt(key.c_str()) != NULL; + } // Removes the specified key and the associated value. - void remove(JsonObjectKey key); + void remove(JsonObjectKey key) { + removeNode(getNodeAt(key.c_str())); + } // Returns a reference an invalid JsonObject. // This object is meant to replace a NULL pointer. // This is used when memory allocation or JSON parsing fail. - static JsonObject& invalid() { return _invalid; } + static JsonObject& invalid() { + static JsonObject instance(NULL); + return instance; + } // Serialize the object to the specified JsonWriter - void writeTo(Internals::JsonWriter& writer) const; + 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(); + } private: // Returns the list node that matches the specified key. - node_type* getNodeAt(const char* key) const; - - node_type* getOrCreateNodeAt(const char* 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; + } template - FORCE_INLINE bool setNodeAt(JsonObjectKey key, T value); + 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(node, value); + } - FORCE_INLINE bool setNodeKey(node_type*, JsonObjectKey key); + 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; + } template - FORCE_INLINE bool setNodeValue(node_type*, T value); - - // The instance returned by JsonObject::invalid() - static JsonObject _invalid; + bool setNodeValue(node_type* node, T value) { + node->content.value = value; + return true; + } }; } - -#include "JsonObject.ipp" diff --git a/include/ArduinoJson/JsonObject.ipp b/include/ArduinoJson/JsonObject.ipp index afe2c40f..05857b26 100644 --- a/include/ArduinoJson/JsonObject.ipp +++ b/include/ArduinoJson/JsonObject.ipp @@ -13,71 +13,6 @@ namespace ArduinoJson { -inline JsonVariant JsonObject::get(JsonObjectKey key) const { - node_type *node = getNodeAt(key.c_str()); - return node ? node->content.value : JsonVariant(); -} - -template -inline T JsonObject::get(JsonObjectKey key) const { - node_type *node = getNodeAt(key.c_str()); - return node ? node->content.value.as() : JsonVariant::defaultValue(); -} - -template -inline bool JsonObject::is(JsonObjectKey key) const { - node_type *node = getNodeAt(key.c_str()); - return node ? node->content.value.is() : false; -} - -inline JsonObjectSubscript JsonObject::operator[]( - const char *key) { - return JsonObjectSubscript(*this, key); -} - -inline JsonObjectSubscript JsonObject::operator[]( - const String &key) { - return JsonObjectSubscript(*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 -inline bool JsonObject::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(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 -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); @@ -90,18 +25,6 @@ inline bool JsonObject::setNodeValue(node_type *node, const String &value) { return node->content.value; } -template -inline const JsonObjectSubscript JsonVariantBase:: -operator[](const char *key) const { - return asObject()[key]; -} - -template -inline const JsonObjectSubscript JsonVariantBase:: -operator[](const String &key) const { - return asObject()[key]; -} - template <> inline JsonObject const &JsonVariant::defaultValue() { return JsonObject::invalid(); diff --git a/include/ArduinoJson/JsonObjectSubscript.hpp b/include/ArduinoJson/JsonObjectSubscript.hpp index 3916a917..0d05a594 100644 --- a/include/ArduinoJson/JsonObjectSubscript.hpp +++ b/include/ArduinoJson/JsonObjectSubscript.hpp @@ -45,9 +45,13 @@ class JsonObjectSubscript : public JsonVariantBase > { 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 FORCE_INLINE TValue as() const { @@ -69,7 +73,9 @@ class JsonObjectSubscript : public JsonVariantBase > { 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); @@ -92,6 +98,28 @@ inline std::ostream& operator<<( } #endif +inline JsonObjectSubscript JsonObject::operator[]( + const char* key) { + return JsonObjectSubscript(*this, key); +} + +inline JsonObjectSubscript JsonObject::operator[]( + const String& key) { + return JsonObjectSubscript(*this, key); +} + +template +inline const JsonObjectSubscript JsonVariantBase:: +operator[](const char* key) const { + return asObject()[key]; +} + +template +inline const JsonObjectSubscript JsonVariantBase:: +operator[](const String& key) const { + return asObject()[key]; +} + } // namespace ArduinoJson #ifdef _MSC_VER diff --git a/include/ArduinoJson/JsonVariant.hpp b/include/ArduinoJson/JsonVariant.hpp index c32ac90a..6aa6fa76 100644 --- a/include/ArduinoJson/JsonVariant.hpp +++ b/include/ArduinoJson/JsonVariant.hpp @@ -41,11 +41,15 @@ class JsonVariant : public JsonVariantBase { struct IsConstructibleFrom; // Creates an uninitialized JsonVariant - FORCE_INLINE JsonVariant() : _type(Internals::JSON_UNDEFINED) {} + JsonVariant() : _type(Internals::JSON_UNDEFINED) {} // Create a JsonVariant containing a boolean value. // It will be serialized as "true" or "false" in JSON. - FORCE_INLINE JsonVariant(bool value); + JsonVariant(bool value) { + using namespace Internals; + _type = JSON_BOOLEAN; + _content.asInteger = static_cast(value); + } // Create a JsonVariant containing a floating point value. // The second argument specifies the number of decimal digits to write in @@ -53,10 +57,9 @@ class JsonVariant : public JsonVariantBase { // JsonVariant(double value, uint8_t decimals); // JsonVariant(float value, uint8_t decimals); template - FORCE_INLINE JsonVariant( - T value, uint8_t decimals = 2, - typename TypeTraits::EnableIf::value>::type - * = 0) { + JsonVariant(T value, uint8_t decimals = 2, + typename TypeTraits::EnableIf< + TypeTraits::IsFloatingPoint::value>::type * = 0) { using namespace Internals; _type = static_cast(JSON_FLOAT_0_DECIMALS + decimals); _content.asFloat = static_cast(value); @@ -67,9 +70,9 @@ class JsonVariant : public JsonVariantBase { // JsonVariant(signed int) // JsonVariant(signed long) template - FORCE_INLINE JsonVariant( - T value, typename TypeTraits::EnableIf< - TypeTraits::IsSignedIntegral::value>::type * = 0) { + JsonVariant(T value, + typename TypeTraits::EnableIf< + TypeTraits::IsSignedIntegral::value>::type * = 0) { using namespace Internals; if (value >= 0) { _type = JSON_POSITIVE_INTEGER; @@ -83,25 +86,37 @@ class JsonVariant : public JsonVariantBase { // JsonVariant(unsigned int) // JsonVariant(unsigned long) template - FORCE_INLINE JsonVariant( - T value, typename TypeTraits::EnableIf< - TypeTraits::IsUnsignedIntegral::value>::type * = 0) { + JsonVariant(T value, + typename TypeTraits::EnableIf< + TypeTraits::IsUnsignedIntegral::value>::type * = 0) { using namespace Internals; _type = JSON_POSITIVE_INTEGER; _content.asInteger = static_cast(value); } // Create a JsonVariant containing a string. - FORCE_INLINE JsonVariant(const char *value); + JsonVariant(const char *value) { + _type = Internals::JSON_STRING; + _content.asString = value; + } // Create a JsonVariant containing an unparsed string - FORCE_INLINE JsonVariant(RawJson value); + JsonVariant(RawJson value) { + _type = Internals::JSON_UNPARSED; + _content.asString = value; + } // Create a JsonVariant containing a reference to an array. - FORCE_INLINE JsonVariant(JsonArray &array); + JsonVariant(JsonArray &array) { + _type = Internals::JSON_ARRAY; + _content.asArray = &array; + } // Create a JsonVariant containing a reference to an object. - FORCE_INLINE JsonVariant(JsonObject &object); + JsonVariant(JsonObject &object) { + _type = Internals::JSON_OBJECT; + _content.asObject = &object; + } // Get the variant as the specified type. // @@ -257,7 +272,9 @@ class JsonVariant : public JsonVariantBase { } // Returns true if the variant has a value - bool success() const { return _type != Internals::JSON_UNDEFINED; } + bool success() const { + return _type != Internals::JSON_UNDEFINED; + } // Serialize the variant to a JsonWriter void writeTo(Internals::JsonWriter &writer) const; @@ -275,9 +292,8 @@ class JsonVariant : public JsonVariantBase { private: // It's not allowed to store a char template - FORCE_INLINE JsonVariant(T value, - typename TypeTraits::EnableIf< - TypeTraits::IsSame::value>::type * = 0); + JsonVariant(T value, typename TypeTraits::EnableIf< + TypeTraits::IsSame::value>::type * = 0); String toString() const; Internals::JsonFloat asFloat() const; @@ -286,9 +302,15 @@ class JsonVariant : public JsonVariantBase { 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; } + 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; @@ -328,6 +350,3 @@ struct JsonVariant::IsConstructibleFrom { TypeTraits::IsSame::value; }; } - -// Include inline implementations -#include "JsonVariant.ipp" diff --git a/include/ArduinoJson/JsonVariant.ipp b/include/ArduinoJson/JsonVariant.ipp index d01bbfa6..bd0663f5 100644 --- a/include/ArduinoJson/JsonVariant.ipp +++ b/include/ArduinoJson/JsonVariant.ipp @@ -10,37 +10,15 @@ #include "Configuration.hpp" #include "JsonVariant.hpp" #include "Internals/Parse.hpp" +#include "JsonArray.hpp" +#include "JsonObject.hpp" -#include +#include // for strcmp +#include // for errno +#include // for strtol, strtod namespace ArduinoJson { -inline JsonVariant::JsonVariant(bool value) { - using namespace Internals; - _type = JSON_BOOLEAN; - _content.asInteger = static_cast(value); -} - -inline JsonVariant::JsonVariant(const char *value) { - _type = Internals::JSON_STRING; - _content.asString = value; -} - -inline JsonVariant::JsonVariant(RawJson 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; -} - inline Internals::JsonInteger JsonVariant::asInteger() const { using namespace Internals; switch (_type) { @@ -80,6 +58,119 @@ inline Internals::JsonUInt JsonVariant::asUnsignedInteger() const { } } +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(_content.asInteger); + case JSON_NEGATIVE_INTEGER: + return -static_cast(_content.asInteger); + case JSON_STRING: + case JSON_UNPARSED: + return _content.asString ? parse(_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(); +} + +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(_type - JSON_FLOAT_0_DECIMALS); + writer.writeFloat(_content.asFloat, decimals); + } +} + #if ARDUINOJSON_ENABLE_STD_STREAM inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) { return source.printTo(os); diff --git a/include/ArduinoJson/JsonVariantBase.hpp b/include/ArduinoJson/JsonVariantBase.hpp index b8b6c393..bd4fb8da 100644 --- a/include/ArduinoJson/JsonVariantBase.hpp +++ b/include/ArduinoJson/JsonVariantBase.hpp @@ -7,7 +7,7 @@ #pragma once -#include "Internals/ForceInline.hpp" +#include "Polyfills/attributes.hpp" #include "JsonObjectKey.hpp" namespace ArduinoJson { diff --git a/include/ArduinoJson/Internals/ForceInline.hpp b/include/ArduinoJson/Polyfills/attributes.hpp similarity index 78% rename from include/ArduinoJson/Internals/ForceInline.hpp rename to include/ArduinoJson/Polyfills/attributes.hpp index 2a189861..ac215f4d 100644 --- a/include/ArduinoJson/Internals/ForceInline.hpp +++ b/include/ArduinoJson/Polyfills/attributes.hpp @@ -9,6 +9,8 @@ #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 diff --git a/include/ArduinoJson/StaticJsonBuffer.hpp b/include/ArduinoJson/StaticJsonBuffer.hpp index ce4172fd..2ae9a3ab 100644 --- a/include/ArduinoJson/StaticJsonBuffer.hpp +++ b/include/ArduinoJson/StaticJsonBuffer.hpp @@ -9,6 +9,16 @@ #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. @@ -19,8 +29,12 @@ 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; @@ -34,3 +48,11 @@ 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 diff --git a/src/ArduinoJson.h b/src/ArduinoJson.h deleted file mode 100644 index 2418aa7f..00000000 --- a/src/ArduinoJson.h +++ /dev/null @@ -1,14 +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! - -// 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" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index a6de0385..00000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,71 +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! - -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_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 - ) -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) - add_definitions(-D_CRT_SECURE_NO_WARNINGS) - add_compile_options(-W4) -endif() - -add_library(ArduinoJson ${CPP_FILES} ${HPP_FILES} ${IPP_FILES}) - -target_include_directories(ArduinoJson INTERFACE ${CMAKE_CURRENT_LIST_DIR}/../include) diff --git a/src/Internals/Comments.cpp b/src/Internals/Comments.cpp deleted file mode 100644 index b16d1903..00000000 --- a/src/Internals/Comments.cpp +++ /dev/null @@ -1,52 +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 "../../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; - } - } -} diff --git a/src/Internals/Encoding.cpp b/src/Internals/Encoding.cpp deleted file mode 100644 index afc2c862..00000000 --- a/src/Internals/Encoding.cpp +++ /dev/null @@ -1,14 +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 "../../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"; diff --git a/src/Internals/IndentedPrint.cpp b/src/Internals/IndentedPrint.cpp deleted file mode 100644 index e0c13736..00000000 --- a/src/Internals/IndentedPrint.cpp +++ /dev/null @@ -1,30 +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 "../../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; -} diff --git a/src/Internals/List.cpp b/src/Internals/List.cpp deleted file mode 100644 index 4409fbc5..00000000 --- a/src/Internals/List.cpp +++ /dev/null @@ -1,50 +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 "../../include/ArduinoJson/Internals/List.hpp" - -#include "../../include/ArduinoJson/JsonPair.hpp" -#include "../../include/ArduinoJson/JsonVariant.hpp" - -using namespace ArduinoJson; -using namespace ArduinoJson::Internals; - -template -size_t List::size() const { - size_t nodeCount = 0; - for (node_type *node = _firstNode; node; node = node->next) nodeCount++; - return nodeCount; -} - -template -typename List::node_type *List::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 -void List::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; -template class ArduinoJson::Internals::List; diff --git a/src/Internals/Prettyfier.cpp b/src/Internals/Prettyfier.cpp deleted file mode 100644 index 18d5b19d..00000000 --- a/src/Internals/Prettyfier.cpp +++ /dev/null @@ -1,87 +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 "../../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(); -} diff --git a/src/Internals/StaticStringBuilder.cpp b/src/Internals/StaticStringBuilder.cpp deleted file mode 100644 index e032bce7..00000000 --- a/src/Internals/StaticStringBuilder.cpp +++ /dev/null @@ -1,18 +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 "../../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; -} diff --git a/src/JsonArray.cpp b/src/JsonArray.cpp deleted file mode 100644 index 751619c9..00000000 --- a/src/JsonArray.cpp +++ /dev/null @@ -1,40 +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 "../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(); -} diff --git a/src/JsonBuffer.cpp b/src/JsonBuffer.cpp deleted file mode 100644 index ba8a6953..00000000 --- a/src/JsonBuffer.cpp +++ /dev/null @@ -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! - -#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(); -} - -JsonVariant JsonBuffer::parse(char *json, uint8_t nestingLimit) { - JsonParser parser(this, json, nestingLimit); - return parser.parseVariant(); -} - -char *JsonBuffer::strdup(const char *source, size_t length) { - size_t size = length + 1; - char *dest = static_cast(alloc(size)); - if (dest != NULL) memcpy(dest, source, size); - return dest; -} diff --git a/src/JsonObject.cpp b/src/JsonObject.cpp deleted file mode 100644 index afa939c8..00000000 --- a/src/JsonObject.cpp +++ /dev/null @@ -1,44 +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 "../include/ArduinoJson/JsonObject.hpp" - -#include // 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(); -} diff --git a/src/JsonVariant.cpp b/src/JsonVariant.cpp deleted file mode 100644 index 2f9e5f71..00000000 --- a/src/JsonVariant.cpp +++ /dev/null @@ -1,125 +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 "../include/ArduinoJson/JsonVariant.hpp" - -#include "../include/ArduinoJson/JsonArray.hpp" -#include "../include/ArduinoJson/JsonObject.hpp" - -#include // for errno -#include // 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 { - switch (_type) { - case JSON_UNDEFINED: - return 0; - case JSON_POSITIVE_INTEGER: - case JSON_BOOLEAN: - return static_cast(_content.asInteger); - case JSON_NEGATIVE_INTEGER: - return -static_cast(_content.asInteger); - case JSON_STRING: - case JSON_UNPARSED: - return _content.asString ? parse(_content.asString) : 0; - default: - return _content.asFloat; - } -} - -String JsonVariant::toString() const { - String s; - if ((_type == JSON_STRING || _type == JSON_UNPARSED) && - _content.asString != NULL) - s = _content.asString; - else - printTo(s); - return s; -} - -bool JsonVariant::isBoolean() 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"); -} - -bool JsonVariant::isInteger() const { - 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; -} - -bool JsonVariant::isFloat() 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(); -} - -void JsonVariant::writeTo(JsonWriter &writer) const { - 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(_type - JSON_FLOAT_0_DECIMALS); - writer.writeFloat(_content.asFloat, decimals); - } -} -} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5606dae7..ea8074a8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,31 +5,69 @@ # https://github.com/bblanchon/ArduinoJson # If you like this project, please add a star! -set(GTEST_DIR ../third-party/gtest-1.7.0) +include(gtest.cmake) file(GLOB TESTS_FILES *.hpp *.cpp) -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) +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 + ) endif() -if (MSVC) +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) add_definitions(-D_CRT_SECURE_NO_WARNINGS) + add_compile_options(-W4) endif() -add_executable(ArduinoJsonTests - ${TESTS_FILES} - ${GTEST_DIR}/src/gtest-all.cc - ${GTEST_DIR}/src/gtest_main.cc) - - -target_link_libraries(ArduinoJsonTests ArduinoJson) +add_executable(ArduinoJsonTests ${TESTS_FILES}) +target_include_directories(ArduinoJsonTests PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../include) +target_link_libraries(ArduinoJsonTests gtest) add_test(ArduinoJsonTests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ArduinoJsonTests) diff --git a/test/DynamicJsonBuffer_Basic_Tests.cpp b/test/DynamicJsonBuffer_Basic_Tests.cpp index 798f9629..db52d886 100644 --- a/test/DynamicJsonBuffer_Basic_Tests.cpp +++ b/test/DynamicJsonBuffer_Basic_Tests.cpp @@ -6,11 +6,7 @@ // If you like this project, please add a star! #include - -#define protected public -#include - -using namespace ArduinoJson; +#include class DynamicJsonBuffer_Basic_Tests : public testing::Test { protected: diff --git a/test/JsonArray_CopyTo_Tests.cpp b/test/JsonArray_CopyTo_Tests.cpp index 41488ef4..8a8279cc 100644 --- a/test/JsonArray_CopyTo_Tests.cpp +++ b/test/JsonArray_CopyTo_Tests.cpp @@ -44,7 +44,7 @@ TEST(JsonArray_CopyTo_Tests, TwoOneDimensionIntegerArray) { DynamicJsonBuffer jsonBuffer; JsonArray& array = jsonBuffer.parseArray(json); - int destination[3][2] = {0}; + int destination[3][2] = {{0}}; array.copyTo(destination); ASSERT_EQ(1, destination[0][0]); diff --git a/test/JsonVariant_Comparison_Tests.cpp b/test/JsonVariant_Comparison_Tests.cpp index 3f0cef45..bf66ad1e 100644 --- a/test/JsonVariant_Comparison_Tests.cpp +++ b/test/JsonVariant_Comparison_Tests.cpp @@ -6,9 +6,7 @@ // If you like this project, please add a star! #include -#include - -using namespace ArduinoJson; +#include class JsonVariant_Comparison_Tests : public ::testing::Test { protected: diff --git a/test/StaticJsonBuffer_Basic_Tests.cpp b/test/StaticJsonBuffer_Basic_Tests.cpp index 08f10a6e..116784f8 100644 --- a/test/StaticJsonBuffer_Basic_Tests.cpp +++ b/test/StaticJsonBuffer_Basic_Tests.cpp @@ -6,11 +6,7 @@ // If you like this project, please add a star! #include - -#define protected public -#include - -using namespace ArduinoJson; +#include class StaticJsonBuffer_Basic_Tests : public testing::Test { protected: diff --git a/test/StaticJsonBuffer_ParseArray_Tests.cpp b/test/StaticJsonBuffer_ParseArray_Tests.cpp index 8cb253f7..c1139768 100644 --- a/test/StaticJsonBuffer_ParseArray_Tests.cpp +++ b/test/StaticJsonBuffer_ParseArray_Tests.cpp @@ -10,9 +10,13 @@ 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()); @@ -73,9 +77,12 @@ TEST_F(StaticJsonBuffer_ParseArray_Tests, } TEST_F(StaticJsonBuffer_ParseArray_Tests, CharPtrNull) { - ASSERT_FALSE(StaticJsonBuffer<100>().parseArray((char*)0).success()); + ASSERT_FALSE( + StaticJsonBuffer<100>().parseArray(static_cast(0)).success()); } TEST_F(StaticJsonBuffer_ParseArray_Tests, ConstCharPtrNull) { - ASSERT_FALSE(StaticJsonBuffer<100>().parseArray((const char*)0).success()); + ASSERT_FALSE(StaticJsonBuffer<100>() + .parseArray(static_cast(0)) + .success()); } diff --git a/test/StaticJsonBuffer_ParseObject_Tests.cpp b/test/StaticJsonBuffer_ParseObject_Tests.cpp index 532fbc30..0043b7bf 100644 --- a/test/StaticJsonBuffer_ParseObject_Tests.cpp +++ b/test/StaticJsonBuffer_ParseObject_Tests.cpp @@ -10,9 +10,13 @@ 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()); @@ -74,9 +78,12 @@ TEST_F(StaticJsonBuffer_ParseObject_Tests, } TEST_F(StaticJsonBuffer_ParseObject_Tests, CharPtrNull) { - ASSERT_FALSE(StaticJsonBuffer<100>().parseObject((char*)0).success()); + ASSERT_FALSE( + StaticJsonBuffer<100>().parseObject(static_cast(0)).success()); } TEST_F(StaticJsonBuffer_ParseObject_Tests, ConstCharPtrNull) { - ASSERT_FALSE(StaticJsonBuffer<100>().parseObject((const char*)0).success()); + ASSERT_FALSE(StaticJsonBuffer<100>() + .parseObject(static_cast(0)) + .success()); } diff --git a/test/gtest.cmake b/test/gtest.cmake new file mode 100644 index 00000000..e5a3ca41 --- /dev/null +++ b/test/gtest.cmake @@ -0,0 +1,24 @@ +set(GTEST_DIR ../third-party/gtest-1.7.0) + +add_library(gtest + ${GTEST_DIR}/src/gtest-all.cc + ${GTEST_DIR}/src/gtest_main.cc +) + +target_include_directories(gtest + PUBLIC + ${GTEST_DIR} + ${GTEST_DIR}/include +) + + +target_compile_definitions(gtest PUBLIC -DGTEST_HAS_PTHREAD=0) + +if (MSVC) + if (MSVC_VERSION EQUAL 1700) + # Workaround for Visual Studio 2012 + target_compile_definitions(gtest PUBLIC -D_VARIADIC_MAX=10) + endif() + + target_compile_definitions(gtest PUBLIC -D_CRT_SECURE_NO_WARNINGS) +endif() diff --git a/third-party/gtest-1.7.0/include/gtest/gtest-param-test.h b/third-party/gtest-1.7.0/include/gtest/gtest-param-test.h index d6702c8f..a25e705e 100644 --- a/third-party/gtest-1.7.0/include/gtest/gtest-param-test.h +++ b/third-party/gtest-1.7.0/include/gtest/gtest-param-test.h @@ -1,3 +1,8 @@ +// clang-format off +#ifdef __GNUC__ +#pragma GCC system_header +#endif + // This file was GENERATED by command: // pump.py gtest-param-test.h.pump // DO NOT EDIT BY HAND!!! diff --git a/third-party/gtest-1.7.0/include/gtest/gtest.h b/third-party/gtest-1.7.0/include/gtest/gtest.h index 6fa0a392..26e30d6a 100644 --- a/third-party/gtest-1.7.0/include/gtest/gtest.h +++ b/third-party/gtest-1.7.0/include/gtest/gtest.h @@ -1,3 +1,8 @@ +// clang-format off +#ifdef __GNUC__ +#pragma GCC system_header +#endif + // Copyright 2005, Google Inc. // All rights reserved. // diff --git a/third-party/gtest-1.7.0/include/gtest/internal/gtest-internal.h b/third-party/gtest-1.7.0/include/gtest/internal/gtest-internal.h index 0dcc3a31..09ac063a 100644 --- a/third-party/gtest-1.7.0/include/gtest/internal/gtest-internal.h +++ b/third-party/gtest-1.7.0/include/gtest/internal/gtest-internal.h @@ -1,3 +1,8 @@ +// clang-format off +#ifdef __GNUC__ +#pragma GCC system_header +#endif + // Copyright 2005, Google Inc. // All rights reserved. // diff --git a/third-party/gtest-1.7.0/include/gtest/internal/gtest-port.h b/third-party/gtest-1.7.0/include/gtest/internal/gtest-port.h index dc4fe0cb..77f00233 100644 --- a/third-party/gtest-1.7.0/include/gtest/internal/gtest-port.h +++ b/third-party/gtest-1.7.0/include/gtest/internal/gtest-port.h @@ -1,3 +1,8 @@ +// clang-format off +#ifdef __GNUC__ +#pragma GCC system_header +#endif + // Copyright 2005, Google Inc. // All rights reserved. //