Minh Nguyen / ArduinoJson
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MsgPackDeserializer.hpp Source File

MsgPackDeserializer.hpp

00001 // ArduinoJson - arduinojson.org
00002 // Copyright Benoit Blanchon 2014-2021
00003 // MIT License
00004 
00005 #pragma once
00006 
00007 #include <ArduinoJson/Deserialization/deserialize.hpp>
00008 #include <ArduinoJson/Memory/MemoryPool.hpp>
00009 #include <ArduinoJson/MsgPack/endianess.hpp>
00010 #include <ArduinoJson/MsgPack/ieee754.hpp>
00011 #include <ArduinoJson/Polyfills/type_traits.hpp>
00012 #include <ArduinoJson/Variant/VariantData.hpp>
00013 
00014 namespace ARDUINOJSON_NAMESPACE {
00015 
00016 template <typename TReader, typename TStringStorage>
00017 class MsgPackDeserializer {
00018  public:
00019   MsgPackDeserializer(MemoryPool &pool, TReader reader,
00020                       TStringStorage stringStorage)
00021       : _pool(&pool),
00022         _reader(reader),
00023         _stringStorage(stringStorage),
00024         _error(DeserializationError::Ok),
00025         _foundSomething(false) {}
00026 
00027   template <typename TFilter>
00028   DeserializationError parse(VariantData &variant, TFilter filter,
00029                              NestingLimit nestingLimit) {
00030     parseVariant(variant, filter, nestingLimit);
00031     return _foundSomething ? _error : DeserializationError::EmptyInput;
00032   }
00033 
00034  private:
00035   // Prevent VS warning "assignment operator could not be generated"
00036   MsgPackDeserializer &operator=(const MsgPackDeserializer &);
00037 
00038   bool invalidInput() {
00039     _error = DeserializationError::InvalidInput;
00040     return false;
00041   }
00042 
00043   bool notSupported() {
00044     _error = DeserializationError::NotSupported;
00045     return false;
00046   }
00047 
00048   template <typename TFilter>
00049   bool parseVariant(VariantData &variant, TFilter filter,
00050                     NestingLimit nestingLimit) {
00051     uint8_t code = 0;  // TODO: why do we need to initialize this variable?
00052     if (!readByte(code))
00053       return false;
00054 
00055     _foundSomething = true;
00056 
00057     bool allowValue = filter.allowValue();
00058 
00059     switch (code) {
00060       case 0xc0:
00061         // already null
00062         return true;
00063 
00064       case 0xc1:
00065         return invalidInput();
00066 
00067       case 0xc2:
00068         if (allowValue)
00069           variant.setBoolean(false);
00070         return true;
00071 
00072       case 0xc3:
00073         if (allowValue)
00074           variant.setBoolean(true);
00075         return true;
00076 
00077       case 0xc4:  // bin 8
00078         if (allowValue)
00079           return notSupported();
00080         else
00081           return skipString<uint8_t>();
00082 
00083       case 0xc5:  // bin 16
00084         if (allowValue)
00085           return notSupported();
00086         else
00087           return skipString<uint16_t>();
00088 
00089       case 0xc6:  // bin 32
00090         if (allowValue)
00091           return notSupported();
00092         else
00093           return skipString<uint32_t>();
00094 
00095       case 0xc7:  // ext 8
00096         if (allowValue)
00097           return notSupported();
00098         else
00099           return skipExt<uint8_t>();
00100 
00101       case 0xc8:  // ext 16
00102         if (allowValue)
00103           return notSupported();
00104         else
00105           return skipExt<uint16_t>();
00106 
00107       case 0xc9:  // ext 32
00108         if (allowValue)
00109           return notSupported();
00110         else
00111           return skipExt<uint32_t>();
00112 
00113       case 0xca:
00114         if (allowValue)
00115           return readFloat<float>(variant);
00116         else
00117           return skipBytes(4);
00118 
00119       case 0xcb:
00120         if (allowValue)
00121           return readDouble<double>(variant);
00122         else
00123           return skipBytes(8);
00124 
00125       case 0xcc:
00126         if (allowValue)
00127           return readInteger<uint8_t>(variant);
00128         else
00129           return skipBytes(1);
00130 
00131       case 0xcd:
00132         if (allowValue)
00133           return readInteger<uint16_t>(variant);
00134         else
00135           return skipBytes(2);
00136 
00137       case 0xce:
00138         if (allowValue)
00139           return readInteger<uint32_t>(variant);
00140         else
00141           return skipBytes(4);
00142 
00143       case 0xcf:
00144         if (allowValue)
00145 #if ARDUINOJSON_USE_LONG_LONG
00146           return readInteger<uint64_t>(variant);
00147 #else
00148           return notSupported();
00149 #endif
00150         else
00151           return skipBytes(8);
00152 
00153       case 0xd0:
00154         if (allowValue)
00155           return readInteger<int8_t>(variant);
00156         else
00157           return skipBytes(1);
00158 
00159       case 0xd1:
00160         if (allowValue)
00161           return readInteger<int16_t>(variant);
00162         else
00163           return skipBytes(2);
00164 
00165       case 0xd2:
00166         if (allowValue)
00167           return readInteger<int32_t>(variant);
00168         else
00169           return skipBytes(4);
00170 
00171       case 0xd3:
00172         if (allowValue)
00173 #if ARDUINOJSON_USE_LONG_LONG
00174           return readInteger<int64_t>(variant);
00175 #else
00176           return notSupported();
00177 #endif
00178         else
00179           return skipBytes(8);
00180 
00181       case 0xd4:  // fixext 1
00182         if (allowValue)
00183           return notSupported();
00184         else
00185           return skipBytes(2);
00186 
00187       case 0xd5:  // fixext 2
00188         if (allowValue)
00189           return notSupported();
00190         else
00191           return skipBytes(3);
00192 
00193       case 0xd6:  // fixext 4
00194         if (allowValue)
00195           return notSupported();
00196         else
00197           return skipBytes(5);
00198 
00199       case 0xd7:  // fixext 8
00200         if (allowValue)
00201           return notSupported();
00202         else
00203           return skipBytes(9);
00204 
00205       case 0xd8:  // fixext 16
00206         if (allowValue)
00207           return notSupported();
00208         else
00209           return skipBytes(17);
00210 
00211       case 0xd9:
00212         if (allowValue)
00213           return readString<uint8_t>(variant);
00214         else
00215           return skipString<uint8_t>();
00216 
00217       case 0xda:
00218         if (allowValue)
00219           return readString<uint16_t>(variant);
00220         else
00221           return skipString<uint16_t>();
00222 
00223       case 0xdb:
00224         if (allowValue)
00225           return readString<uint32_t>(variant);
00226         else
00227           return skipString<uint32_t>();
00228 
00229       case 0xdc:
00230         return readArray<uint16_t>(variant, filter, nestingLimit);
00231 
00232       case 0xdd:
00233         return readArray<uint32_t>(variant, filter, nestingLimit);
00234 
00235       case 0xde:
00236         return readObject<uint16_t>(variant, filter, nestingLimit);
00237 
00238       case 0xdf:
00239         return readObject<uint32_t>(variant, filter, nestingLimit);
00240     }
00241 
00242     switch (code & 0xf0) {
00243       case 0x80:
00244         return readObject(variant, code & 0x0F, filter, nestingLimit);
00245 
00246       case 0x90:
00247         return readArray(variant, code & 0x0F, filter, nestingLimit);
00248     }
00249 
00250     if ((code & 0xe0) == 0xa0) {
00251       if (allowValue)
00252         return readString(variant, code & 0x1f);
00253       else
00254         return skipBytes(code & 0x1f);
00255     }
00256 
00257     if (allowValue)
00258       variant.setInteger(static_cast<int8_t>(code));
00259 
00260     return true;
00261   }
00262 
00263   bool readByte(uint8_t &value) {
00264     int c = _reader.read();
00265     if (c < 0) {
00266       _error = DeserializationError::IncompleteInput;
00267       return false;
00268     }
00269     value = static_cast<uint8_t>(c);
00270     return true;
00271   }
00272 
00273   bool readBytes(uint8_t *p, size_t n) {
00274     if (_reader.readBytes(reinterpret_cast<char *>(p), n) == n)
00275       return true;
00276     _error = DeserializationError::IncompleteInput;
00277     return false;
00278   }
00279 
00280   template <typename T>
00281   bool readBytes(T &value) {
00282     return readBytes(reinterpret_cast<uint8_t *>(&value), sizeof(value));
00283   }
00284 
00285   bool skipBytes(size_t n) {
00286     for (; n; --n) {
00287       if (_reader.read() < 0) {
00288         _error = DeserializationError::IncompleteInput;
00289         return false;
00290       }
00291     }
00292     return true;
00293   }
00294 
00295   template <typename T>
00296   bool readInteger(T &value) {
00297     if (!readBytes(value))
00298       return false;
00299     fixEndianess(value);
00300     return true;
00301   }
00302 
00303   template <typename T>
00304   bool readInteger(VariantData &variant) {
00305     T value;
00306     if (!readInteger(value))
00307       return false;
00308     variant.setInteger(value);
00309     return true;
00310   }
00311 
00312   template <typename T>
00313   typename enable_if<sizeof(T) == 4, bool>::type readFloat(
00314       VariantData &variant) {
00315     T value;
00316     if (!readBytes(value))
00317       return false;
00318     fixEndianess(value);
00319     variant.setFloat(value);
00320     return true;
00321   }
00322 
00323   template <typename T>
00324   typename enable_if<sizeof(T) == 8, bool>::type readDouble(
00325       VariantData &variant) {
00326     T value;
00327     if (!readBytes(value))
00328       return false;
00329     fixEndianess(value);
00330     variant.setFloat(value);
00331     return true;
00332   }
00333 
00334   template <typename T>
00335   typename enable_if<sizeof(T) == 4, bool>::type readDouble(
00336       VariantData &variant) {
00337     uint8_t i[8];  // input is 8 bytes
00338     T value;       // output is 4 bytes
00339     uint8_t *o = reinterpret_cast<uint8_t *>(&value);
00340     if (!readBytes(i, 8))
00341       return false;
00342     doubleToFloat(i, o);
00343     fixEndianess(value);
00344     variant.setFloat(value);
00345     return true;
00346   }
00347 
00348   template <typename T>
00349   bool readString(VariantData &variant) {
00350     T size;
00351     if (!readInteger(size))
00352       return false;
00353     return readString(variant, size);
00354   }
00355 
00356   template <typename T>
00357   bool readString() {
00358     T size;
00359     if (!readInteger(size))
00360       return false;
00361     return readString(size);
00362   }
00363 
00364   template <typename T>
00365   bool skipString() {
00366     T size;
00367     if (!readInteger(size))
00368       return false;
00369     return skipBytes(size);
00370   }
00371 
00372   bool readString(VariantData &variant, size_t n) {
00373     if (!readString(n))
00374       return false;
00375     variant.setStringPointer(_stringStorage.save(),
00376                              typename TStringStorage::storage_policy());
00377     return true;
00378   }
00379 
00380   bool readString(size_t n) {
00381     _stringStorage.startString();
00382     for (; n; --n) {
00383       uint8_t c;
00384       if (!readBytes(c))
00385         return false;
00386       _stringStorage.append(static_cast<char>(c));
00387     }
00388     _stringStorage.append('\0');
00389     if (!_stringStorage.isValid()) {
00390       _error = DeserializationError::NoMemory;
00391       return false;
00392     }
00393 
00394     return true;
00395   }
00396 
00397   template <typename TSize, typename TFilter>
00398   bool readArray(VariantData &variant, TFilter filter,
00399                  NestingLimit nestingLimit) {
00400     TSize size;
00401     if (!readInteger(size))
00402       return false;
00403     return readArray(variant, size, filter, nestingLimit);
00404   }
00405 
00406   template <typename TFilter>
00407   bool readArray(VariantData &variant, size_t n, TFilter filter,
00408                  NestingLimit nestingLimit) {
00409     if (nestingLimit.reached()) {
00410       _error = DeserializationError::TooDeep;
00411       return false;
00412     }
00413 
00414     bool allowArray = filter.allowArray();
00415 
00416     CollectionData *array = allowArray ? &variant.toArray() : 0;
00417 
00418     TFilter memberFilter = filter[0U];
00419 
00420     for (; n; --n) {
00421       VariantData *value;
00422 
00423       if (memberFilter.allow()) {
00424         value = array->addElement(_pool);
00425         if (!value) {
00426           _error = DeserializationError::NoMemory;
00427           return false;
00428         }
00429       } else {
00430         value = 0;
00431       }
00432 
00433       if (!parseVariant(*value, memberFilter, nestingLimit.decrement()))
00434         return false;
00435     }
00436 
00437     return true;
00438   }
00439 
00440   template <typename TSize, typename TFilter>
00441   bool readObject(VariantData &variant, TFilter filter,
00442                   NestingLimit nestingLimit) {
00443     TSize size;
00444     if (!readInteger(size))
00445       return false;
00446     return readObject(variant, size, filter, nestingLimit);
00447   }
00448 
00449   template <typename TFilter>
00450   bool readObject(VariantData &variant, size_t n, TFilter filter,
00451                   NestingLimit nestingLimit) {
00452     if (nestingLimit.reached()) {
00453       _error = DeserializationError::TooDeep;
00454       return false;
00455     }
00456 
00457     CollectionData *object = filter.allowObject() ? &variant.toObject() : 0;
00458 
00459     for (; n; --n) {
00460       if (!readKey())
00461         return false;
00462 
00463       const char *key = _stringStorage.c_str();
00464       TFilter memberFilter = filter[key];
00465       VariantData *member;
00466 
00467       if (memberFilter.allow()) {
00468         // Save key in memory pool.
00469         // This MUST be done before adding the slot.
00470         key = _stringStorage.save();
00471 
00472         VariantSlot *slot = object->addSlot(_pool);
00473         if (!slot) {
00474           _error = DeserializationError::NoMemory;
00475           return false;
00476         }
00477 
00478         slot->setKey(key, typename TStringStorage::storage_policy());
00479 
00480         member = slot->data();
00481       } else {
00482         member = 0;
00483       }
00484 
00485       if (!parseVariant(*member, memberFilter, nestingLimit.decrement()))
00486         return false;
00487     }
00488 
00489     return true;
00490   }
00491 
00492   bool readKey() {
00493     uint8_t code;
00494     if (!readByte(code))
00495       return false;
00496 
00497     if ((code & 0xe0) == 0xa0)
00498       return readString(code & 0x1f);
00499 
00500     switch (code) {
00501       case 0xd9:
00502         return readString<uint8_t>();
00503 
00504       case 0xda:
00505         return readString<uint16_t>();
00506 
00507       case 0xdb:
00508         return readString<uint32_t>();
00509 
00510       default:
00511         return notSupported();
00512     }
00513   }
00514 
00515   template <typename T>
00516   bool skipExt() {
00517     T size;
00518     if (!readInteger(size))
00519       return false;
00520     return skipBytes(size + 1);
00521   }
00522 
00523   MemoryPool *_pool;
00524   TReader _reader;
00525   TStringStorage _stringStorage;
00526   DeserializationError _error;
00527   bool _foundSomething;
00528 };
00529 
00530 //
00531 // deserializeMsgPack(JsonDocument&, const std::string&, ...)
00532 //
00533 // ... = NestingLimit
00534 template <typename TString>
00535 DeserializationError deserializeMsgPack(
00536     JsonDocument &doc, const TString &input,
00537     NestingLimit nestingLimit = NestingLimit()) {
00538   return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
00539                                           AllowAllFilter());
00540 }
00541 // ... = Filter, NestingLimit
00542 template <typename TString>
00543 DeserializationError deserializeMsgPack(
00544     JsonDocument &doc, const TString &input, Filter filter,
00545     NestingLimit nestingLimit = NestingLimit()) {
00546   return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
00547 }
00548 // ... = NestingLimit, Filter
00549 template <typename TString>
00550 DeserializationError deserializeMsgPack(JsonDocument &doc, const TString &input,
00551                                         NestingLimit nestingLimit,
00552                                         Filter filter) {
00553   return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
00554 }
00555 
00556 //
00557 // deserializeMsgPack(JsonDocument&, std::istream&, ...)
00558 //
00559 // ... = NestingLimit
00560 template <typename TStream>
00561 DeserializationError deserializeMsgPack(
00562     JsonDocument &doc, TStream &input,
00563     NestingLimit nestingLimit = NestingLimit()) {
00564   return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
00565                                           AllowAllFilter());
00566 }
00567 // ... = Filter, NestingLimit
00568 template <typename TStream>
00569 DeserializationError deserializeMsgPack(
00570     JsonDocument &doc, TStream &input, Filter filter,
00571     NestingLimit nestingLimit = NestingLimit()) {
00572   return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
00573 }
00574 // ... = NestingLimit, Filter
00575 template <typename TStream>
00576 DeserializationError deserializeMsgPack(JsonDocument &doc, TStream &input,
00577                                         NestingLimit nestingLimit,
00578                                         Filter filter) {
00579   return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
00580 }
00581 
00582 //
00583 // deserializeMsgPack(JsonDocument&, char*, ...)
00584 //
00585 // ... = NestingLimit
00586 template <typename TChar>
00587 DeserializationError deserializeMsgPack(
00588     JsonDocument &doc, TChar *input,
00589     NestingLimit nestingLimit = NestingLimit()) {
00590   return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
00591                                           AllowAllFilter());
00592 }
00593 // ... = Filter, NestingLimit
00594 template <typename TChar>
00595 DeserializationError deserializeMsgPack(
00596     JsonDocument &doc, TChar *input, Filter filter,
00597     NestingLimit nestingLimit = NestingLimit()) {
00598   return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
00599 }
00600 // ... = NestingLimit, Filter
00601 template <typename TChar>
00602 DeserializationError deserializeMsgPack(JsonDocument &doc, TChar *input,
00603                                         NestingLimit nestingLimit,
00604                                         Filter filter) {
00605   return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
00606 }
00607 
00608 //
00609 // deserializeMsgPack(JsonDocument&, char*, size_t, ...)
00610 //
00611 // ... = NestingLimit
00612 template <typename TChar>
00613 DeserializationError deserializeMsgPack(
00614     JsonDocument &doc, TChar *input, size_t inputSize,
00615     NestingLimit nestingLimit = NestingLimit()) {
00616   return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
00617                                           AllowAllFilter());
00618 }
00619 // ... = Filter, NestingLimit
00620 template <typename TChar>
00621 DeserializationError deserializeMsgPack(
00622     JsonDocument &doc, TChar *input, size_t inputSize, Filter filter,
00623     NestingLimit nestingLimit = NestingLimit()) {
00624   return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
00625                                           filter);
00626 }
00627 // ... = NestingLimit, Filter
00628 template <typename TChar>
00629 DeserializationError deserializeMsgPack(JsonDocument &doc, TChar *input,
00630                                         size_t inputSize,
00631                                         NestingLimit nestingLimit,
00632                                         Filter filter) {
00633   return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
00634                                           filter);
00635 }
00636 
00637 }  // namespace ARDUINOJSON_NAMESPACE