// ArduinoJson - arduinojson.org // Copyright Benoit Blanchon 2014-2018 // MIT License #pragma once #include "../JsonVariant.hpp" #include "../Memory/JsonBuffer.hpp" #include "../Strings/StringWriter.hpp" #include "../TypeTraits/IsConst.hpp" #include "./MsgPackError.hpp" #include "./endianess.hpp" #include "./ieee754.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 class MsgPackDeserializer { public: MsgPackDeserializer(JsonBuffer *buffer, TReader reader, TWriter writer, uint8_t nestingLimit) : _buffer(buffer), _reader(reader), _writer(writer), _nestingLimit(nestingLimit) {} MsgPackError parse(JsonArray &array) { uint8_t c = readOne(); size_t n; if ((c & 0xF0) == 0x90) { n = c & 0x0F; } else if (c == 0xdc) { n = readInteger(); } else if (c == 0xdd) { n = readInteger(); } else { return MsgPackError::NotAnArray; } return readArray(array, n); } MsgPackError parse(JsonObject &object) { uint8_t c = readOne(); size_t n; if ((c & 0xf0) == 0x80) { n = c & 0x0f; } else if (c == 0xde) { n = readInteger(); } else if (c == 0xdf) { n = readInteger(); } else { return MsgPackError::NotAnObject; } return readObject(object, n); } MsgPackError parse(JsonVariant &variant) { uint8_t c = readOne(); if ((c & 0x80) == 0) { variant = c; return MsgPackError::Ok; } if ((c & 0xe0) == 0xe0) { variant = static_cast(c); return MsgPackError::Ok; } if ((c & 0xe0) == 0xa0) { return readString(variant, c & 0x1f); } if ((c & 0xf0) == 0x90) return readArray(variant, c & 0x0F); if ((c & 0xf0) == 0x80) return readObject(variant, c & 0x0F); switch (c) { case 0xc0: variant = static_cast(0); return MsgPackError::Ok; case 0xc2: variant = false; return MsgPackError::Ok; case 0xc3: variant = true; return MsgPackError::Ok; case 0xcc: variant = readInteger(); return MsgPackError::Ok; case 0xcd: variant = readInteger(); return MsgPackError::Ok; case 0xce: variant = readInteger(); return MsgPackError::Ok; case 0xcf: #if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 variant = readInteger(); #else readInteger(); variant = readInteger(); #endif return MsgPackError::Ok; case 0xd0: variant = readInteger(); return MsgPackError::Ok; case 0xd1: variant = readInteger(); return MsgPackError::Ok; case 0xd2: variant = readInteger(); return MsgPackError::Ok; case 0xd3: #if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 variant = readInteger(); #else readInteger(); variant = readInteger(); #endif return MsgPackError::Ok; case 0xca: variant = readFloat(); return MsgPackError::Ok; case 0xcb: variant = readDouble(); return MsgPackError::Ok; case 0xd9: { uint8_t n = readInteger(); return readString(variant, n); } case 0xda: { uint16_t n = readInteger(); return readString(variant, n); } case 0xdb: { uint32_t n = readInteger(); return readString(variant, n); } case 0xdc: return readArray(variant, readInteger()); case 0xdd: return readArray(variant, readInteger()); case 0xde: return readObject(variant, readInteger()); case 0xdf: return readObject(variant, readInteger()); default: return MsgPackError::NotSupported; } } private: // Prevent VS warning "assignment operator could not be generated" MsgPackDeserializer &operator=(const MsgPackDeserializer &); uint8_t readOne() { char c = _reader.current(); _reader.move(); return static_cast(c); } void read(uint8_t *p, size_t n) { for (size_t i = 0; i < n; i++) p[i] = readOne(); } template void read(T &value) { read(reinterpret_cast(&value), sizeof(value)); } template T readInteger() { T value; read(value); fixEndianess(value); return value; } template typename EnableIf::type readFloat() { T value; read(value); fixEndianess(value); return value; } template typename EnableIf::type readDouble() { T value; read(value); fixEndianess(value); return value; } template typename EnableIf::type readDouble() { uint8_t i[8]; // input is 8 bytes T value; // output is 4 bytes uint8_t *o = reinterpret_cast(&value); read(i, 8); doubleToFloat(i, o); fixEndianess(value); return value; } MsgPackError readString(JsonVariant &variant, size_t n) { typename RemoveReference::type::String str = _writer.startString(); for (; n; --n) str.append(static_cast(readOne())); const char *s = str.c_str(); if (s == NULL) return MsgPackError::NoMemory; variant = s; return MsgPackError::Ok; } MsgPackError readArray(JsonVariant &variant, size_t n) { JsonArray *array = new (_buffer) JsonArray(_buffer); if (!array) return MsgPackError::NoMemory; variant = array; return readArray(*array, n); } MsgPackError readArray(JsonArray &array, size_t n) { if (_nestingLimit == 0) return MsgPackError::TooDeep; --_nestingLimit; for (; n; --n) { JsonVariant variant; MsgPackError err = parse(variant); if (err) return err; if (!array.add(variant)) return MsgPackError::NoMemory; } ++_nestingLimit; return MsgPackError::Ok; } MsgPackError readObject(JsonVariant &variant, size_t n) { JsonObject *object = new (_buffer) JsonObject(_buffer); if (!object) return MsgPackError::NoMemory; variant = object; return readObject(*object, n); } MsgPackError readObject(JsonObject &object, size_t n) { if (_nestingLimit == 0) return MsgPackError::TooDeep; --_nestingLimit; for (; n; --n) { MsgPackError err; JsonVariant variant; err = parse(variant); if (err) return err; const char *key = variant.as(); if (!key) return MsgPackError::NotSupported; err = parse(variant); if (err) return err; if (!object.set(key, variant)) return MsgPackError::NoMemory; } ++_nestingLimit; return MsgPackError::Ok; } JsonBuffer *_buffer; TReader _reader; TWriter _writer; uint8_t _nestingLimit; }; template struct MsgPackDeserializerBuilder { typedef typename StringTraits::Reader InputReader; typedef MsgPackDeserializer TParser; static TParser makeMsgPackDeserializer(TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) { return TParser(buffer, InputReader(json), *buffer, nestingLimit); } }; template struct MsgPackDeserializerBuilder< TJsonBuffer, TChar *, typename EnableIf::value>::type> { typedef typename StringTraits::Reader TReader; typedef StringWriter TWriter; typedef MsgPackDeserializer TParser; static TParser makeMsgPackDeserializer(TJsonBuffer *buffer, TChar *json, uint8_t nestingLimit) { return TParser(buffer, TReader(json), TWriter(json), nestingLimit); } }; template inline typename MsgPackDeserializerBuilder::TParser makeMsgPackDeserializer(TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) { return MsgPackDeserializerBuilder< TJsonBuffer, TString>::makeMsgPackDeserializer(buffer, json, nestingLimit); } } // namespace Internals } // namespace ArduinoJson