// ArduinoJson - arduinojson.org // Copyright Benoit Blanchon 2014-2018 // MIT License #pragma once #include "Comments.hpp" #include "JsonParser.hpp" template inline bool ArduinoJson::Internals::JsonParser::eat( TReader &reader, char charToSkip) { skipSpacesAndComments(reader); if (reader.current() != charToSkip) return false; reader.move(); return true; } template inline bool ArduinoJson::Internals::JsonParser::parseAnythingTo( JsonVariant *destination) { skipSpacesAndComments(_reader); switch (_reader.current()) { case '[': return parseArrayTo(destination); case '{': return parseObjectTo(destination); default: return parseStringTo(destination); } } template inline ArduinoJson::JsonArray & ArduinoJson::Internals::JsonParser::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 inline bool ArduinoJson::Internals::JsonParser::parseArrayTo( JsonVariant *destination) { JsonArray &array = parseArray(); if (!array.success()) return false; *destination = array; return true; } template inline ArduinoJson::JsonObject & ArduinoJson::Internals::JsonParser::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 inline bool ArduinoJson::Internals::JsonParser::parseObjectTo( JsonVariant *destination) { JsonObject &object = parseObject(); if (!object.success()) return false; *destination = object; return true; } template inline const char * ArduinoJson::Internals::JsonParser::parseString() { typename RemoveReference::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 inline bool ArduinoJson::Internals::JsonParser::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; }