Minh Nguyen / ArduinoJson
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MsgPackSerializer.hpp Source File

MsgPackSerializer.hpp

00001 // ArduinoJson - arduinojson.org
00002 // Copyright Benoit Blanchon 2014-2021
00003 // MIT License
00004 
00005 #pragma once
00006 
00007 #include <ArduinoJson/MsgPack/endianess.hpp>
00008 #include <ArduinoJson/Polyfills/assert.hpp>
00009 #include <ArduinoJson/Polyfills/type_traits.hpp>
00010 #include <ArduinoJson/Serialization/CountingDecorator.hpp>
00011 #include <ArduinoJson/Serialization/measure.hpp>
00012 #include <ArduinoJson/Serialization/serialize.hpp>
00013 #include <ArduinoJson/Variant/VariantData.hpp>
00014 
00015 namespace ARDUINOJSON_NAMESPACE {
00016 
00017 template <typename TWriter>
00018 class MsgPackSerializer : public Visitor<size_t> {
00019  public:
00020   MsgPackSerializer(TWriter writer) : _writer(writer) {}
00021 
00022   template <typename T>
00023   typename enable_if<sizeof(T) == 4, size_t>::type visitFloat(T value32) {
00024     writeByte(0xCA);
00025     writeInteger(value32);
00026     return bytesWritten();
00027   }
00028 
00029   template <typename T>
00030   ARDUINOJSON_NO_SANITIZE("float-cast-overflow")
00031   typename enable_if<sizeof(T) == 8, size_t>::type visitFloat(T value64) {
00032     float value32 = float(value64);
00033     if (value32 == value64) {
00034       writeByte(0xCA);
00035       writeInteger(value32);
00036     } else {
00037       writeByte(0xCB);
00038       writeInteger(value64);
00039     }
00040     return bytesWritten();
00041   }
00042 
00043   size_t visitArray(const CollectionData& array) {
00044     size_t n = array.size();
00045     if (n < 0x10) {
00046       writeByte(uint8_t(0x90 + array.size()));
00047     } else if (n < 0x10000) {
00048       writeByte(0xDC);
00049       writeInteger(uint16_t(n));
00050     } else {
00051       writeByte(0xDD);
00052       writeInteger(uint32_t(n));
00053     }
00054     for (VariantSlot* slot = array.head(); slot; slot = slot->next()) {
00055       slot->data()->accept(*this);
00056     }
00057     return bytesWritten();
00058   }
00059 
00060   size_t visitObject(const CollectionData& object) {
00061     size_t n = object.size();
00062     if (n < 0x10) {
00063       writeByte(uint8_t(0x80 + n));
00064     } else if (n < 0x10000) {
00065       writeByte(0xDE);
00066       writeInteger(uint16_t(n));
00067     } else {
00068       writeByte(0xDF);
00069       writeInteger(uint32_t(n));
00070     }
00071     for (VariantSlot* slot = object.head(); slot; slot = slot->next()) {
00072       visitString(slot->key());
00073       slot->data()->accept(*this);
00074     }
00075     return bytesWritten();
00076   }
00077 
00078   size_t visitString(const char* value) {
00079     ARDUINOJSON_ASSERT(value != NULL);
00080 
00081     size_t n = strlen(value);
00082 
00083     if (n < 0x20) {
00084       writeByte(uint8_t(0xA0 + n));
00085     } else if (n < 0x100) {
00086       writeByte(0xD9);
00087       writeInteger(uint8_t(n));
00088     } else if (n < 0x10000) {
00089       writeByte(0xDA);
00090       writeInteger(uint16_t(n));
00091     } else {
00092       writeByte(0xDB);
00093       writeInteger(uint32_t(n));
00094     }
00095     writeBytes(reinterpret_cast<const uint8_t*>(value), n);
00096     return bytesWritten();
00097   }
00098 
00099   size_t visitRawJson(const char* data, size_t size) {
00100     writeBytes(reinterpret_cast<const uint8_t*>(data), size);
00101     return bytesWritten();
00102   }
00103 
00104   size_t visitNegativeInteger(UInt value) {
00105     UInt negated = UInt(~value + 1);
00106     if (value <= 0x20) {
00107       writeInteger(int8_t(negated));
00108     } else if (value <= 0x80) {
00109       writeByte(0xD0);
00110       writeInteger(int8_t(negated));
00111     } else if (value <= 0x8000) {
00112       writeByte(0xD1);
00113       writeInteger(int16_t(negated));
00114     } else if (value <= 0x80000000) {
00115       writeByte(0xD2);
00116       writeInteger(int32_t(negated));
00117     }
00118 #if ARDUINOJSON_USE_LONG_LONG
00119     else {
00120       writeByte(0xD3);
00121       writeInteger(int64_t(negated));
00122     }
00123 #endif
00124     return bytesWritten();
00125   }
00126 
00127   size_t visitPositiveInteger(UInt value) {
00128     if (value <= 0x7F) {
00129       writeInteger(uint8_t(value));
00130     } else if (value <= 0xFF) {
00131       writeByte(0xCC);
00132       writeInteger(uint8_t(value));
00133     } else if (value <= 0xFFFF) {
00134       writeByte(0xCD);
00135       writeInteger(uint16_t(value));
00136     }
00137 #if ARDUINOJSON_USE_LONG_LONG
00138     else if (value <= 0xFFFFFFFF)
00139 #else
00140     else
00141 #endif
00142     {
00143       writeByte(0xCE);
00144       writeInteger(uint32_t(value));
00145     }
00146 #if ARDUINOJSON_USE_LONG_LONG
00147     else {
00148       writeByte(0xCF);
00149       writeInteger(uint64_t(value));
00150     }
00151 #endif
00152     return bytesWritten();
00153   }
00154 
00155   size_t visitBoolean(bool value) {
00156     writeByte(value ? 0xC3 : 0xC2);
00157     return bytesWritten();
00158   }
00159 
00160   size_t visitNull() {
00161     writeByte(0xC0);
00162     return bytesWritten();
00163   }
00164 
00165  private:
00166   size_t bytesWritten() const {
00167     return _writer.count();
00168   }
00169 
00170   void writeByte(uint8_t c) {
00171     _writer.write(c);
00172   }
00173 
00174   void writeBytes(const uint8_t* p, size_t n) {
00175     _writer.write(p, n);
00176   }
00177 
00178   template <typename T>
00179   void writeInteger(T value) {
00180     fixEndianess(value);
00181     writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
00182   }
00183 
00184   CountingDecorator<TWriter> _writer;
00185 };
00186 
00187 template <typename TSource, typename TDestination>
00188 inline size_t serializeMsgPack(const TSource& source, TDestination& output) {
00189   return serialize<MsgPackSerializer>(source, output);
00190 }
00191 
00192 template <typename TSource>
00193 inline size_t serializeMsgPack(const TSource& source, void* output,
00194                                size_t size) {
00195   return serialize<MsgPackSerializer>(source, output, size);
00196 }
00197 
00198 template <typename TSource>
00199 inline size_t measureMsgPack(const TSource& source) {
00200   return measure<MsgPackSerializer>(source);
00201 }
00202 
00203 }  // namespace ARDUINOJSON_NAMESPACE