summaryrefslogtreecommitdiff
path: root/include/lib/ArduinoJson/Deserialization
diff options
context:
space:
mode:
Diffstat (limited to 'include/lib/ArduinoJson/Deserialization')
-rw-r--r--include/lib/ArduinoJson/Deserialization/Comments.hpp61
-rw-r--r--include/lib/ArduinoJson/Deserialization/JsonParser.hpp102
-rw-r--r--include/lib/ArduinoJson/Deserialization/JsonParserImpl.hpp189
-rw-r--r--include/lib/ArduinoJson/Deserialization/StringWriter.hpp41
4 files changed, 393 insertions, 0 deletions
diff --git a/include/lib/ArduinoJson/Deserialization/Comments.hpp b/include/lib/ArduinoJson/Deserialization/Comments.hpp
new file mode 100644
index 0000000..c2c48eb
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/Comments.hpp
@@ -0,0 +1,61 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2018
+// MIT License
+
+#pragma once
+
+namespace ArduinoJson {
+namespace Internals {
+template <typename TInput>
+void skipSpacesAndComments(TInput& input) {
+ for (;;) {
+ switch (input.current()) {
+ // spaces
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ input.move();
+ continue;
+
+ // comments
+ case '/':
+ switch (input.next()) {
+ // C-style block comment
+ case '*':
+ input.move(); // skip '/'
+ // no need to skip '*'
+ for (;;) {
+ input.move();
+ if (input.current() == '\0') return;
+ if (input.current() == '*' && input.next() == '/') {
+ input.move(); // skip '*'
+ input.move(); // skip '/'
+ break;
+ }
+ }
+ break;
+
+ // C++-style line comment
+ case '/':
+ // not need to skip "//"
+ for (;;) {
+ input.move();
+ if (input.current() == '\0') return;
+ if (input.current() == '\n') break;
+ }
+ break;
+
+ // not a comment, just a '/'
+ default:
+ return;
+ }
+ break;
+
+ default:
+ return;
+ }
+ }
+}
+}
+}
diff --git a/include/lib/ArduinoJson/Deserialization/JsonParser.hpp b/include/lib/ArduinoJson/Deserialization/JsonParser.hpp
new file mode 100644
index 0000000..4cbaf45
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/JsonParser.hpp
@@ -0,0 +1,102 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2018
+// MIT License
+
+#pragma once
+
+#include "../JsonBuffer.hpp"
+#include "../JsonVariant.hpp"
+#include "../TypeTraits/IsConst.hpp"
+#include "StringWriter.hpp"
+
+namespace ArduinoJson {
+namespace Internals {
+
+// Parse JSON string to create JsonArrays and JsonObjects
+// This internal class is not indended to be used directly.
+// Instead, use JsonBuffer.parseArray() or .parseObject()
+template <typename TReader, typename TWriter>
+class JsonParser {
+ public:
+ JsonParser(JsonBuffer *buffer, TReader reader, TWriter writer,
+ uint8_t nestingLimit)
+ : _buffer(buffer),
+ _reader(reader),
+ _writer(writer),
+ _nestingLimit(nestingLimit) {}
+
+ JsonArray &parseArray();
+ JsonObject &parseObject();
+
+ JsonVariant parseVariant() {
+ JsonVariant result;
+ parseAnythingTo(&result);
+ return result;
+ }
+
+ private:
+ JsonParser &operator=(const JsonParser &); // non-copiable
+
+ static bool eat(TReader &, char charToSkip);
+ FORCE_INLINE bool eat(char charToSkip) {
+ return eat(_reader, charToSkip);
+ }
+
+ const char *parseString();
+ bool parseAnythingTo(JsonVariant *destination);
+
+ inline bool parseArrayTo(JsonVariant *destination);
+ inline bool parseObjectTo(JsonVariant *destination);
+ inline bool parseStringTo(JsonVariant *destination);
+
+ static inline bool isBetween(char c, char min, char max) {
+ return min <= c && c <= max;
+ }
+
+ static inline bool canBeInNonQuotedString(char c) {
+ return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
+ isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
+ }
+
+ static inline bool isQuote(char c) {
+ return c == '\'' || c == '\"';
+ }
+
+ JsonBuffer *_buffer;
+ TReader _reader;
+ TWriter _writer;
+ uint8_t _nestingLimit;
+};
+
+template <typename TJsonBuffer, typename TString, typename Enable = void>
+struct JsonParserBuilder {
+ typedef typename StringTraits<TString>::Reader InputReader;
+ typedef JsonParser<InputReader, TJsonBuffer &> TParser;
+
+ static TParser makeParser(TJsonBuffer *buffer, TString &json,
+ uint8_t nestingLimit) {
+ return TParser(buffer, InputReader(json), *buffer, nestingLimit);
+ }
+};
+
+template <typename TJsonBuffer, typename TChar>
+struct JsonParserBuilder<TJsonBuffer, TChar *,
+ typename EnableIf<!IsConst<TChar>::value>::type> {
+ typedef typename StringTraits<TChar *>::Reader TReader;
+ typedef StringWriter<TChar> TWriter;
+ typedef JsonParser<TReader, TWriter> TParser;
+
+ static TParser makeParser(TJsonBuffer *buffer, TChar *json,
+ uint8_t nestingLimit) {
+ return TParser(buffer, TReader(json), TWriter(json), nestingLimit);
+ }
+};
+
+template <typename TJsonBuffer, typename TString>
+inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser(
+ TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) {
+ return JsonParserBuilder<TJsonBuffer, TString>::makeParser(buffer, json,
+ nestingLimit);
+}
+} // namespace Internals
+} // namespace ArduinoJson
diff --git a/include/lib/ArduinoJson/Deserialization/JsonParserImpl.hpp b/include/lib/ArduinoJson/Deserialization/JsonParserImpl.hpp
new file mode 100644
index 0000000..5042673
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/JsonParserImpl.hpp
@@ -0,0 +1,189 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2018
+// MIT License
+
+#pragma once
+
+#include "Comments.hpp"
+#include "JsonParser.hpp"
+
+template <typename TReader, typename TWriter>
+inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::eat(
+ TReader &reader, char charToSkip) {
+ skipSpacesAndComments(reader);
+ if (reader.current() != charToSkip) return false;
+ reader.move();
+ return true;
+}
+
+template <typename TReader, typename TWriter>
+inline bool
+ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseAnythingTo(
+ JsonVariant *destination) {
+ skipSpacesAndComments(_reader);
+
+ switch (_reader.current()) {
+ case '[':
+ return parseArrayTo(destination);
+
+ case '{':
+ return parseObjectTo(destination);
+
+ default:
+ return parseStringTo(destination);
+ }
+}
+
+template <typename TReader, typename TWriter>
+inline ArduinoJson::JsonArray &
+ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArray() {
+ if (_nestingLimit == 0) return JsonArray::invalid();
+ _nestingLimit--;
+
+ // Create an empty array
+ JsonArray &array = _buffer->createArray();
+
+ // Check opening braket
+ if (!eat('[')) goto ERROR_MISSING_BRACKET;
+ if (eat(']')) goto SUCCESS_EMPTY_ARRAY;
+
+ // Read each value
+ for (;;) {
+ // 1 - Parse value
+ JsonVariant value;
+ if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE;
+ if (!array.add(value)) goto ERROR_NO_MEMORY;
+
+ // 2 - More values?
+ if (eat(']')) goto SUCCES_NON_EMPTY_ARRAY;
+ if (!eat(',')) goto ERROR_MISSING_COMMA;
+ }
+
+SUCCESS_EMPTY_ARRAY:
+SUCCES_NON_EMPTY_ARRAY:
+ _nestingLimit++;
+ return array;
+
+ERROR_INVALID_VALUE:
+ERROR_MISSING_BRACKET:
+ERROR_MISSING_COMMA:
+ERROR_NO_MEMORY:
+ return JsonArray::invalid();
+}
+
+template <typename TReader, typename TWriter>
+inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArrayTo(
+ JsonVariant *destination) {
+ JsonArray &array = parseArray();
+ if (!array.success()) return false;
+
+ *destination = array;
+ return true;
+}
+
+template <typename TReader, typename TWriter>
+inline ArduinoJson::JsonObject &
+ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObject() {
+ if (_nestingLimit == 0) return JsonObject::invalid();
+ _nestingLimit--;
+
+ // Create an empty object
+ JsonObject &object = _buffer->createObject();
+
+ // Check opening brace
+ if (!eat('{')) goto ERROR_MISSING_BRACE;
+ if (eat('}')) goto SUCCESS_EMPTY_OBJECT;
+
+ // Read each key value pair
+ for (;;) {
+ // 1 - Parse key
+ const char *key = parseString();
+ if (!key) goto ERROR_INVALID_KEY;
+ if (!eat(':')) goto ERROR_MISSING_COLON;
+
+ // 2 - Parse value
+ JsonVariant value;
+ if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE;
+ if (!object.set(key, value)) goto ERROR_NO_MEMORY;
+
+ // 3 - More keys/values?
+ if (eat('}')) goto SUCCESS_NON_EMPTY_OBJECT;
+ if (!eat(',')) goto ERROR_MISSING_COMMA;
+ }
+
+SUCCESS_EMPTY_OBJECT:
+SUCCESS_NON_EMPTY_OBJECT:
+ _nestingLimit++;
+ return object;
+
+ERROR_INVALID_KEY:
+ERROR_INVALID_VALUE:
+ERROR_MISSING_BRACE:
+ERROR_MISSING_COLON:
+ERROR_MISSING_COMMA:
+ERROR_NO_MEMORY:
+ return JsonObject::invalid();
+}
+
+template <typename TReader, typename TWriter>
+inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObjectTo(
+ JsonVariant *destination) {
+ JsonObject &object = parseObject();
+ if (!object.success()) return false;
+
+ *destination = object;
+ return true;
+}
+
+template <typename TReader, typename TWriter>
+inline const char *
+ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseString() {
+ typename RemoveReference<TWriter>::type::String str = _writer.startString();
+
+ skipSpacesAndComments(_reader);
+ char c = _reader.current();
+
+ if (isQuote(c)) { // quotes
+ _reader.move();
+ char stopChar = c;
+ for (;;) {
+ c = _reader.current();
+ if (c == '\0') break;
+ _reader.move();
+
+ if (c == stopChar) break;
+
+ if (c == '\\') {
+ // replace char
+ c = Encoding::unescapeChar(_reader.current());
+ if (c == '\0') break;
+ _reader.move();
+ }
+
+ str.append(c);
+ }
+ } else { // no quotes
+ for (;;) {
+ if (!canBeInNonQuotedString(c)) break;
+ _reader.move();
+ str.append(c);
+ c = _reader.current();
+ }
+ }
+
+ return str.c_str();
+}
+
+template <typename TReader, typename TWriter>
+inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseStringTo(
+ JsonVariant *destination) {
+ bool hasQuotes = isQuote(_reader.current());
+ const char *value = parseString();
+ if (value == NULL) return false;
+ if (hasQuotes) {
+ *destination = value;
+ } else {
+ *destination = RawJson(value);
+ }
+ return true;
+}
diff --git a/include/lib/ArduinoJson/Deserialization/StringWriter.hpp b/include/lib/ArduinoJson/Deserialization/StringWriter.hpp
new file mode 100644
index 0000000..fd5507e
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/StringWriter.hpp
@@ -0,0 +1,41 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2018
+// MIT License
+
+#pragma once
+
+namespace ArduinoJson {
+namespace Internals {
+
+template <typename TChar>
+class StringWriter {
+ public:
+ class String {
+ public:
+ String(TChar** ptr) : _writePtr(ptr), _startPtr(*ptr) {}
+
+ void append(char c) {
+ *(*_writePtr)++ = TChar(c);
+ }
+
+ const char* c_str() const {
+ *(*_writePtr)++ = 0;
+ return reinterpret_cast<const char*>(_startPtr);
+ }
+
+ private:
+ TChar** _writePtr;
+ TChar* _startPtr;
+ };
+
+ StringWriter(TChar* buffer) : _ptr(buffer) {}
+
+ String startString() {
+ return String(&_ptr);
+ }
+
+ private:
+ TChar* _ptr;
+};
+}
+}