127 lines
3.4 KiB
C++
127 lines
3.4 KiB
C++
|
|
template<typename T> struct TypeToMsgPackCode{};
|
|
template<> struct TypeToMsgPackCode<uint8_t> { static const char CODE; };
|
|
template<> struct TypeToMsgPackCode<uint16_t>{ static const char CODE; };
|
|
template<> struct TypeToMsgPackCode<uint32_t>{ static const char CODE; };
|
|
template<> struct TypeToMsgPackCode<int8_t> { static const char CODE; };
|
|
template<> struct TypeToMsgPackCode<int16_t> { static const char CODE; };
|
|
template<> struct TypeToMsgPackCode<int32_t> { static const char CODE; };
|
|
|
|
const char TypeToMsgPackCode<uint8_t>::CODE = '\xcc';
|
|
const char TypeToMsgPackCode<uint16_t>::CODE = '\xcd';
|
|
const char TypeToMsgPackCode<uint32_t>::CODE = '\xce';
|
|
const char TypeToMsgPackCode<int8_t>::CODE = '\xd0';
|
|
const char TypeToMsgPackCode<int16_t>::CODE = '\xd1';
|
|
const char TypeToMsgPackCode<int32_t>::CODE = '\xd2';
|
|
|
|
|
|
template<typename Writer>
|
|
class StreamingMsgPackEncoder
|
|
{
|
|
public:
|
|
StreamingMsgPackEncoder(Writer * writer_)
|
|
: writer(writer_), contentLength(0), sizeCountMode(false)
|
|
{}
|
|
|
|
void sendMap16(byte size)
|
|
{
|
|
if( sizeCountMode )
|
|
{
|
|
contentLength += 1;
|
|
}
|
|
else
|
|
{
|
|
size |= 0b10000000;
|
|
writer->write((const char*)(&size), 1);
|
|
}
|
|
}
|
|
|
|
void sendString255(PGM_P s)
|
|
{
|
|
auto len = strlen_P(s);
|
|
if( len >= 255 ) {
|
|
Serial.println(F("ERROR: StreamingMsgPackEncoder::string255 - string too long"));
|
|
return;
|
|
}
|
|
byte castedLen = (byte)(len);
|
|
|
|
if( sizeCountMode )
|
|
{
|
|
contentLength += 2 + castedLen;
|
|
}
|
|
else
|
|
{
|
|
writer->write("\xd9", 1);
|
|
writer->write((const char*)&castedLen, 1);
|
|
writer->write(s, len);
|
|
}
|
|
}
|
|
|
|
template<typename T>
|
|
void sendInt(T value)
|
|
{
|
|
if( sizeCountMode )
|
|
{
|
|
contentLength += 1 + sizeof(T);
|
|
}
|
|
else
|
|
{
|
|
if( sizeof(T) == 4 )
|
|
value = htonl(value);
|
|
else if( sizeof(T) == 2)
|
|
value = htons(value);
|
|
writer->write(&TypeToMsgPackCode<T>::CODE, 1);
|
|
writer->write((const char*)&value, sizeof(T));
|
|
}
|
|
}
|
|
|
|
template<typename T>
|
|
void sendArray(const T * data, uint32_t length)
|
|
{
|
|
sendArrayHeader<T>(length);
|
|
sendArrayPartialContents(data, length);
|
|
}
|
|
|
|
template<typename T>
|
|
void sendArrayHeader(uint32_t length)
|
|
{
|
|
if( sizeCountMode )
|
|
{
|
|
contentLength += 1 + sizeof(uint32_t) + 1 + length * sizeof(T);
|
|
}
|
|
else
|
|
{
|
|
uint32_t nlength = htonl(length * sizeof(T));
|
|
writer->write("\xc9", 1); // ext dtype since typed arrays are not supported by msgpack
|
|
writer->write((char*)(&nlength), sizeof(uint32_t) );
|
|
writer->write(&TypeToMsgPackCode<T>::CODE, 1); // put code for type here, this is not part of msgpack but custom
|
|
}
|
|
}
|
|
|
|
template<typename T>
|
|
void sendArrayPartialContents(T * data, uint32_t length)
|
|
{
|
|
if( !sizeCountMode ) {
|
|
writer->write((char*)(data), length * sizeof(T));
|
|
}
|
|
}
|
|
|
|
void setSizeCountMode(bool sizeCountMode_=true)
|
|
{
|
|
sizeCountMode = sizeCountMode_;
|
|
}
|
|
|
|
bool getSizeCountMode() const {
|
|
return sizeCountMode;
|
|
}
|
|
|
|
uint32_t getContentLength() const {
|
|
return contentLength;
|
|
}
|
|
|
|
private:
|
|
Writer * writer;
|
|
uint32_t contentLength;
|
|
bool sizeCountMode;
|
|
};
|