swimtracker-firmware/session/StreamingMsgPackEncoder.h

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;
};