#include "ArduinoJson/Internals/JsonParser.hpp" #include // for strtol, strtod #include #include "ArduinoJson/JsonBuffer.hpp" #include "ArduinoJson/Internals/QuotedString.hpp" using namespace ArduinoJson::Internals; void JsonParser::skipSpaces() { while (isspace(*_ptr)) _ptr++; } bool JsonParser::skip(char charToSkip) { skipSpaces(); if (*_ptr != charToSkip) return false; _ptr++; skipSpaces(); return true; } JsonNode *JsonParser::parseAnything() { skipSpaces(); switch (*_ptr) { case '[': return parseArray(); case 't': case 'f': return parseBoolean(); case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return parseNumber(); case 'n': return parseNull(); case '{': return parseObject(); case '\'': case '\"': return parseString(); default: return NULL; // invalid JSON } } JsonNode *JsonParser::parseArray() { JsonNode *node = _buffer->createArrayNode(); skip('['); if (isEnd()) return 0; if (skip(']')) return node; // empty array for (;;) { JsonNode *child = parseAnything(); if (!child) return 0; // child parsing failed node->addChild(child); if (skip(']')) return node; // end of the array if (!skip(',')) return 0; // comma is missing } } JsonNode *JsonParser::parseBoolean() { bool value = *_ptr == 't'; _ptr += value ? 4 : 5; // 4 = strlen("true") // 5 = strlen("false"); return _buffer->createBoolNode(value); } JsonNode *JsonParser::parseNumber() { char *endOfLong; long longValue = strtol(_ptr, &endOfLong, 10); if (*endOfLong == '.') // stopped on a decimal separator { double value = strtod(_ptr, &_ptr); int decimals = _ptr - endOfLong - 1; return _buffer->createDoubleNode(value, decimals); } else { _ptr = endOfLong; return _buffer->createLongNode(longValue); } } JsonNode *JsonParser::parseNull() { _ptr += 4; // strlen("null") return _buffer->createStringNode(0); } JsonNode *JsonParser::parseObject() { JsonNode *node = _buffer->createObjectNode(); skip('{'); if (isEnd()) return 0; // premature ending if (skip('}')) return node; // empty object for (;;) { JsonNode *child = parseObjectKeyValue(); if (!child) return 0; // child parsing failed node->addChild(child); if (skip('}')) return node; // end of the object if (!skip(',')) return 0; // comma is missing } } JsonNode *JsonParser::parseObjectKeyValue() { const char *key = QuotedString::extractFrom(_ptr, &_ptr); if (!key) return 0; // failed to extract key if (!skip(':')) return 0; // colon is missing JsonNode *value = parseAnything(); if (!value) return 0; // value parsing failed return _buffer->createObjectKeyValueNode(key, value); } JsonNode *JsonParser::parseString() { const char *s = QuotedString::extractFrom(_ptr, &_ptr); return _buffer->createStringNode(s); }