2015-06-29 14:32:35 +03:00
|
|
|
#include "msgpackstream.h"
|
2015-05-16 12:07:10 +03:00
|
|
|
#include "private/pack_p.h"
|
2015-08-28 21:12:09 +03:00
|
|
|
|
2015-06-29 14:32:35 +03:00
|
|
|
#include <QBuffer>
|
2015-05-15 22:49:39 +03:00
|
|
|
#include <QDebug>
|
2015-05-02 00:06:35 +03:00
|
|
|
|
|
|
|
|
#undef CHECK_STREAM_PRECOND
|
|
|
|
|
#ifndef QT_NO_DEBUG
|
|
|
|
|
#define CHECK_STREAM_PRECOND(retVal) \
|
|
|
|
|
if (!dev) { \
|
|
|
|
|
qWarning("msgpack::Stream: No device"); \
|
|
|
|
|
return retVal; \
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
#define CHECK_STREAM_PRECOND(retVal) \
|
|
|
|
|
if (!dev) { \
|
|
|
|
|
return retVal; \
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define CHECK_STREAM_WRITE_PRECOND(retVal) \
|
|
|
|
|
CHECK_STREAM_PRECOND(retVal) \
|
|
|
|
|
if (q_status != Ok) \
|
|
|
|
|
return retVal;
|
|
|
|
|
|
|
|
|
|
MsgPackStream::MsgPackStream() :
|
2015-05-19 22:41:22 +03:00
|
|
|
dev(0), owndev(false), q_status(Ok)
|
2015-05-02 00:06:35 +03:00
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
MsgPackStream::MsgPackStream(QIODevice *d) :
|
2015-08-28 21:12:09 +03:00
|
|
|
dev(d), owndev(false)
|
2015-05-02 00:06:35 +03:00
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
MsgPackStream::MsgPackStream(QByteArray *a, QIODevice::OpenMode mode) :
|
2015-05-19 22:41:22 +03:00
|
|
|
owndev(true), q_status(Ok)
|
2015-05-02 00:06:35 +03:00
|
|
|
{
|
|
|
|
|
QBuffer *buf = new QBuffer(a);
|
|
|
|
|
buf->open(mode);
|
|
|
|
|
dev = buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream::MsgPackStream(const QByteArray &a) :
|
2015-05-19 22:41:22 +03:00
|
|
|
owndev(true), q_status(Ok)
|
2015-05-02 00:06:35 +03:00
|
|
|
{
|
|
|
|
|
QBuffer *buf = new QBuffer();
|
|
|
|
|
buf->setData(a);
|
|
|
|
|
buf->open(QIODevice::ReadOnly);
|
|
|
|
|
dev = buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream::~MsgPackStream()
|
|
|
|
|
{
|
|
|
|
|
if (owndev)
|
|
|
|
|
delete dev;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MsgPackStream::setDevice(QIODevice *d)
|
|
|
|
|
{
|
|
|
|
|
if (owndev)
|
|
|
|
|
delete dev;
|
|
|
|
|
dev = d;
|
|
|
|
|
owndev = false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-28 21:12:09 +03:00
|
|
|
QIODevice *MsgPackStream::device() const
|
|
|
|
|
{
|
|
|
|
|
return dev;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-02 00:06:35 +03:00
|
|
|
bool MsgPackStream::atEnd() const
|
|
|
|
|
{
|
|
|
|
|
return dev ? dev->atEnd() : true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream::Status MsgPackStream::status() const
|
|
|
|
|
{
|
|
|
|
|
return q_status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MsgPackStream::resetStatus()
|
|
|
|
|
{
|
|
|
|
|
q_status = Ok;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MsgPackStream::setStatus(Status status)
|
|
|
|
|
{
|
|
|
|
|
q_status = status;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-15 22:49:39 +03:00
|
|
|
MsgPackStream &MsgPackStream::operator>>(bool &b)
|
2015-05-02 00:06:35 +03:00
|
|
|
{
|
|
|
|
|
CHECK_STREAM_PRECOND(*this)
|
2015-05-15 22:49:39 +03:00
|
|
|
quint8 p[1];
|
|
|
|
|
if (!dev->getChar((char *)p)) {
|
|
|
|
|
b = false;
|
2015-05-02 00:06:35 +03:00
|
|
|
setStatus(ReadPastEnd);
|
2015-05-15 22:49:39 +03:00
|
|
|
} else {
|
2015-09-12 16:59:01 +03:00
|
|
|
if (p[0] != MsgPack::FirstByte::MTRUE ||
|
|
|
|
|
p[0] != MsgPack::FirstByte::MFALSE)
|
2015-05-15 22:49:39 +03:00
|
|
|
setStatus(ReadCorruptData);
|
2015-09-12 16:59:01 +03:00
|
|
|
b = (p[0] == MsgPack::FirstByte::MTRUE);
|
2015-05-15 22:49:39 +03:00
|
|
|
}
|
2015-05-02 00:06:35 +03:00
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-15 22:49:39 +03:00
|
|
|
MsgPackStream &MsgPackStream::operator >>(quint8 &u8)
|
|
|
|
|
{
|
2015-05-16 21:45:33 +03:00
|
|
|
CHECK_STREAM_PRECOND(*this);
|
2015-06-10 17:42:06 +03:00
|
|
|
quint64 u64;
|
|
|
|
|
if (unpack_ulonglong(u64) && u64 <= std::numeric_limits<quint8>::max())
|
|
|
|
|
u8 = u64;
|
|
|
|
|
else
|
2015-05-19 22:41:22 +03:00
|
|
|
setStatus(ReadCorruptData);
|
2015-05-15 22:49:39 +03:00
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream &MsgPackStream::operator>>(quint16 &u16)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_PRECOND(*this);
|
2015-06-10 17:42:06 +03:00
|
|
|
quint64 u64;
|
|
|
|
|
if (unpack_ulonglong(u64) && u64 <= std::numeric_limits<quint16>::max())
|
|
|
|
|
u16 = u64;
|
|
|
|
|
else
|
2015-05-19 22:41:22 +03:00
|
|
|
setStatus(ReadCorruptData);
|
2015-05-15 22:49:39 +03:00
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream &MsgPackStream::operator>>(quint32 &u32)
|
|
|
|
|
{
|
2015-05-16 21:45:33 +03:00
|
|
|
CHECK_STREAM_PRECOND(*this);
|
2015-06-10 17:42:06 +03:00
|
|
|
quint64 u64;
|
|
|
|
|
if (unpack_ulonglong(u64) && u64 <= std::numeric_limits<quint32>::max())
|
|
|
|
|
u32 = u64;
|
|
|
|
|
else
|
2015-05-19 22:41:22 +03:00
|
|
|
setStatus(ReadCorruptData);
|
2015-05-16 21:45:33 +03:00
|
|
|
return *this;
|
|
|
|
|
}
|
2015-05-15 22:49:39 +03:00
|
|
|
|
2015-05-16 21:45:33 +03:00
|
|
|
MsgPackStream &MsgPackStream::operator>>(quint64 &u64)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_PRECOND(*this);
|
2015-06-10 17:42:06 +03:00
|
|
|
unpack_ulonglong(u64);
|
2015-05-16 21:45:33 +03:00
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream &MsgPackStream::operator>>(qint8 &i8)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_PRECOND(*this);
|
2015-06-10 17:42:06 +03:00
|
|
|
qint64 i64;
|
|
|
|
|
if (!unpack_longlong(i64))
|
2015-05-16 21:45:33 +03:00
|
|
|
return *this;
|
2015-06-10 17:42:06 +03:00
|
|
|
if (i64 >= std::numeric_limits<qint8>::min() &&
|
|
|
|
|
i64 <= std::numeric_limits<qint8>::max())
|
|
|
|
|
i8 = i64;
|
|
|
|
|
else
|
2015-05-19 23:02:13 +03:00
|
|
|
setStatus(ReadCorruptData);
|
2015-05-16 21:45:33 +03:00
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream &MsgPackStream::operator>>(qint16 &i16)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_PRECOND(*this);
|
2015-06-10 17:42:06 +03:00
|
|
|
qint64 i64;
|
|
|
|
|
if (!unpack_longlong(i64))
|
2015-05-16 21:45:33 +03:00
|
|
|
return *this;
|
2015-06-10 17:42:06 +03:00
|
|
|
if (i64 >= std::numeric_limits<qint16>::min() &&
|
|
|
|
|
i64 <= std::numeric_limits<qint16>::max())
|
|
|
|
|
i16 = i64;
|
|
|
|
|
else
|
2015-05-19 22:41:22 +03:00
|
|
|
setStatus(ReadCorruptData);
|
2015-05-16 21:45:33 +03:00
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream &MsgPackStream::operator>>(qint32 &i32)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_PRECOND(*this);
|
2015-06-10 17:42:06 +03:00
|
|
|
qint64 i64;
|
|
|
|
|
if (!unpack_longlong(i64))
|
2015-05-16 21:45:33 +03:00
|
|
|
return *this;
|
2015-06-10 17:42:06 +03:00
|
|
|
if (i64 >= std::numeric_limits<qint32>::min() &&
|
|
|
|
|
i64 <= std::numeric_limits<qint32>::max())
|
|
|
|
|
i32 = i64;
|
|
|
|
|
else
|
2015-05-19 22:41:22 +03:00
|
|
|
setStatus(ReadCorruptData);
|
2015-05-16 21:45:33 +03:00
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream &MsgPackStream::operator>>(qint64 &i64)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_PRECOND(*this);
|
2015-06-10 17:42:06 +03:00
|
|
|
unpack_longlong(i64);
|
2015-05-16 21:45:33 +03:00
|
|
|
return *this;
|
2015-05-15 22:49:39 +03:00
|
|
|
}
|
|
|
|
|
|
2015-05-23 20:00:40 +03:00
|
|
|
MsgPackStream &MsgPackStream::operator>>(float &f)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_PRECOND(*this);
|
|
|
|
|
quint8 *fp = (quint8 *)&f;
|
|
|
|
|
quint8 p[5];
|
2015-05-24 22:31:35 +03:00
|
|
|
if (dev->read((char *)p, 1) != 1) {
|
2015-05-23 20:00:40 +03:00
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
if (p[0] != MsgPack::FirstByte::FLOAT32) {
|
|
|
|
|
setStatus(ReadCorruptData);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
2015-05-24 22:31:35 +03:00
|
|
|
if (dev->read((char *)p + 1, 4) != 4) {
|
|
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
2015-05-23 20:00:40 +03:00
|
|
|
#ifdef __LITTLE_ENDIAN__
|
|
|
|
|
for (int i = 0; i < 4; ++i)
|
|
|
|
|
*(fp + 3 - i) = *(p + i + 1);
|
|
|
|
|
#else
|
|
|
|
|
for (int i = 0; i < 4; ++i)
|
|
|
|
|
*(fp + i) = *(p + i + 1);
|
|
|
|
|
#endif
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream &MsgPackStream::operator>>(double &d)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_PRECOND(*this);
|
2015-05-24 22:31:35 +03:00
|
|
|
quint8 *fp = (quint8 *)&d;
|
2015-05-23 20:00:40 +03:00
|
|
|
quint8 p[9];
|
2015-05-24 22:31:35 +03:00
|
|
|
if (dev->read((char *)p, 1) != 1) {
|
2015-05-23 20:00:40 +03:00
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
if (p[0] != MsgPack::FirstByte::FLOAT64) {
|
|
|
|
|
setStatus(ReadCorruptData);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
2015-05-24 22:31:35 +03:00
|
|
|
if (dev->read((char *)p + 1, 8) != 8) {
|
|
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
2015-05-23 20:00:40 +03:00
|
|
|
#ifdef __LITTLE_ENDIAN__
|
|
|
|
|
for (int i = 0; i < 8; ++i)
|
|
|
|
|
*(fp + 7 - i) = *(p + i + 1);
|
|
|
|
|
#else
|
|
|
|
|
for (int i = 0; i < 8; ++i)
|
|
|
|
|
*(fp + i) = *(p + i + 1);
|
|
|
|
|
#endif
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-16 12:07:10 +03:00
|
|
|
MsgPackStream &MsgPackStream::operator>>(QString &str)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_PRECOND(*this);
|
|
|
|
|
quint8 p[5];
|
|
|
|
|
if (dev->read((char *)p, 1) != 1) {
|
|
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int len = 0;
|
|
|
|
|
if (*p >= 0xa0 && *p <= 0xbf) { // fixstr
|
|
|
|
|
len = (*p) & 0x1f; // 0b00011111
|
|
|
|
|
} else if (*p == MsgPack::FirstByte::STR8) {
|
|
|
|
|
if (dev->read((char *)p + 1, 1) == 1)
|
|
|
|
|
len = p[1];
|
|
|
|
|
} else if (*p == MsgPack::FirstByte::STR16) {
|
|
|
|
|
if (dev->read((char *)p + 1, 2) == 2)
|
|
|
|
|
len = _msgpack_load16(int, &p[1]);
|
|
|
|
|
} else if (*p == MsgPack::FirstByte::STR32) {
|
|
|
|
|
if (dev->read((char *)p + 1, 4) == 4)
|
|
|
|
|
len = _msgpack_load32(int, &p[1]);
|
|
|
|
|
} else {
|
|
|
|
|
setStatus(ReadCorruptData);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
2015-05-19 22:41:22 +03:00
|
|
|
quint8 *data = new quint8[len];
|
|
|
|
|
if (dev->read((char *)data, len) != len) {
|
|
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
delete[] data;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
str = QString::fromUtf8((const char*) data, len);
|
|
|
|
|
delete[] data;
|
2015-06-29 14:32:35 +03:00
|
|
|
return *this;
|
2015-05-16 12:07:10 +03:00
|
|
|
}
|
|
|
|
|
|
2015-05-23 20:00:40 +03:00
|
|
|
MsgPackStream &MsgPackStream::operator>>(QByteArray &array)
|
|
|
|
|
{
|
2015-05-24 22:31:35 +03:00
|
|
|
CHECK_STREAM_PRECOND(*this);
|
|
|
|
|
quint8 p[5];
|
|
|
|
|
if (dev->read((char *)p, 1) != 1) {
|
|
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
quint32 len;
|
|
|
|
|
if (p[0] == MsgPack::FirstByte::BIN8) {
|
|
|
|
|
if (dev->read((char *)p + 1, 1) != 1) {
|
|
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
len = p[1];
|
|
|
|
|
} else if (p[0] == MsgPack::FirstByte::BIN16) {
|
|
|
|
|
if (dev->read((char *)p + 1, 2) != 2) {
|
|
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
len = _msgpack_load16(quint16, &p[1]);
|
|
|
|
|
} else if (p[0] == MsgPack::FirstByte::BIN32) {
|
|
|
|
|
if (dev->read((char *)p + 1, 4) != 4) {
|
|
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
len = _msgpack_load32(quint32, &p[1]);
|
|
|
|
|
} else {
|
|
|
|
|
setStatus(ReadCorruptData);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
array.resize(len);
|
|
|
|
|
if (dev->read(array.data(), len) != len)
|
|
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return *this;
|
2015-05-23 20:00:40 +03:00
|
|
|
}
|
|
|
|
|
|
2015-06-10 17:42:06 +03:00
|
|
|
bool MsgPackStream::readBytes(char *data, uint len)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_PRECOND(false);
|
2015-09-12 16:48:21 +03:00
|
|
|
uint readed = dev->read(data, len);
|
|
|
|
|
if (readed != len) {
|
|
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MsgPackStream::readExtHeader(quint32 &len)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_PRECOND(false);
|
|
|
|
|
quint8 d[6];
|
|
|
|
|
if (dev->read((char*)d, 2) != 2) {
|
|
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (d[0] >= MsgPack::FirstByte::FIXEXT1 &&
|
|
|
|
|
d[0] <= MsgPack::FirstByte::FIXEX16) {
|
|
|
|
|
len = 1;
|
|
|
|
|
len <<= d[0] - MsgPack::FirstByte::FIXEXT1;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
quint8 toRead = 1;
|
|
|
|
|
toRead <<= d[0] - MsgPack::FirstByte::EXT8;
|
|
|
|
|
if (dev->read((char*)&d[2], toRead) != toRead) {
|
|
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (d[0] == MsgPack::FirstByte::EXT8) {
|
|
|
|
|
len = d[1];
|
|
|
|
|
} else if (d[0] == MsgPack::FirstByte::EXT16) {
|
|
|
|
|
len = _msgpack_load16(quint32, &d[1]);
|
|
|
|
|
} else if (d[0] == MsgPack::FirstByte::EXT32) {
|
|
|
|
|
len = _msgpack_load32(quint32, &d[1]);
|
|
|
|
|
} else {
|
|
|
|
|
setStatus(ReadCorruptData);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
2015-06-10 17:42:06 +03:00
|
|
|
}
|
|
|
|
|
|
2015-05-16 12:07:10 +03:00
|
|
|
MsgPackStream &MsgPackStream::operator<<(bool b)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_WRITE_PRECOND(*this);
|
|
|
|
|
quint8 m = b == true ?
|
2015-09-12 16:59:01 +03:00
|
|
|
MsgPack::FirstByte::MTRUE : MsgPack::FirstByte::MFALSE;
|
2015-05-16 12:07:10 +03:00
|
|
|
if (dev->write((char *)&m, 1) != 1)
|
|
|
|
|
setStatus(WriteFailed);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream &MsgPackStream::operator<<(quint32 u32)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_WRITE_PRECOND(*this);
|
|
|
|
|
quint8 p[5];
|
|
|
|
|
quint8 sz = MsgPackPrivate::pack_uint(u32, p, true) - p;
|
2015-05-16 21:45:33 +03:00
|
|
|
if (dev->write((char *)p, sz) != sz)
|
|
|
|
|
setStatus(WriteFailed);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream &MsgPackStream::operator<<(quint64 u64)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_WRITE_PRECOND(*this);
|
|
|
|
|
quint8 p[9];
|
|
|
|
|
quint8 sz = MsgPackPrivate::pack_ulonglong(u64, p, true) - p;
|
|
|
|
|
if (dev->write((char *)p, sz) != sz)
|
2015-05-16 12:07:10 +03:00
|
|
|
setStatus(WriteFailed);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream &MsgPackStream::operator<<(qint32 i32)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_WRITE_PRECOND(*this);
|
|
|
|
|
quint8 p[5];
|
2015-05-16 21:45:33 +03:00
|
|
|
quint8 sz = MsgPackPrivate::pack_int(i32, p, true) - p;
|
|
|
|
|
if (dev->write((char *)p, sz) != sz)
|
|
|
|
|
setStatus(WriteFailed);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream &MsgPackStream::operator<<(qint64 i64)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_WRITE_PRECOND(*this);
|
|
|
|
|
quint8 p[9];
|
|
|
|
|
quint8 sz = MsgPackPrivate::pack_longlong(i64, p, true) - p;
|
|
|
|
|
if (dev->write((char *)p, sz) != sz)
|
2015-05-16 12:07:10 +03:00
|
|
|
setStatus(WriteFailed);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-23 20:00:40 +03:00
|
|
|
MsgPackStream &MsgPackStream::operator<<(float f)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_WRITE_PRECOND(*this);
|
|
|
|
|
quint8 p[5];
|
|
|
|
|
quint8 sz = MsgPackPrivate::pack_float(f, p, true) - p;
|
|
|
|
|
if (dev->write((char *)p, sz) != sz)
|
|
|
|
|
setStatus(WriteFailed);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream &MsgPackStream::operator<<(double d)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_WRITE_PRECOND(*this);
|
|
|
|
|
quint8 p[9];
|
2015-05-24 22:31:35 +03:00
|
|
|
quint8 sz = MsgPackPrivate::pack_double(d, p, true) - p;
|
2015-05-23 20:00:40 +03:00
|
|
|
if (dev->write((char *)p, sz) != sz)
|
|
|
|
|
setStatus(WriteFailed);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-16 12:07:10 +03:00
|
|
|
MsgPackStream &MsgPackStream::operator<<(QString str)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_WRITE_PRECOND(*this);
|
|
|
|
|
quint8 *p = (quint8 *)0;
|
|
|
|
|
quint32 sz = MsgPackPrivate::pack_string(str, p, false) - p;
|
|
|
|
|
quint8 *data = new quint8[sz];
|
2015-05-19 22:41:22 +03:00
|
|
|
MsgPackPrivate::pack_string(str, data, true);
|
2015-05-16 12:07:10 +03:00
|
|
|
if (dev->write((char *)data, sz) != sz)
|
|
|
|
|
setStatus(WriteFailed);
|
|
|
|
|
delete[] data;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgPackStream &MsgPackStream::operator<<(const char *str)
|
|
|
|
|
{
|
2015-05-19 22:41:22 +03:00
|
|
|
CHECK_STREAM_WRITE_PRECOND(*this);
|
|
|
|
|
quint8 *p = (quint8 *)0;
|
|
|
|
|
quint32 str_len = strlen(str);
|
|
|
|
|
quint32 sz = MsgPackPrivate::pack_string_raw(str, str_len, p, false) - p;
|
|
|
|
|
quint8 *data = new quint8[sz];
|
|
|
|
|
MsgPackPrivate::pack_string_raw(str, str_len, data, true);
|
|
|
|
|
if (dev->write((char *)data, sz) != sz)
|
|
|
|
|
setStatus(WriteFailed);
|
|
|
|
|
delete[] data;
|
|
|
|
|
return *this;
|
2015-05-16 12:07:10 +03:00
|
|
|
}
|
2015-05-16 21:45:33 +03:00
|
|
|
|
2015-05-23 20:00:40 +03:00
|
|
|
MsgPackStream &MsgPackStream::operator<<(QByteArray array)
|
|
|
|
|
{
|
2015-05-24 22:31:35 +03:00
|
|
|
CHECK_STREAM_WRITE_PRECOND(*this);
|
|
|
|
|
quint8 p[5];
|
|
|
|
|
quint32 len = array.length();
|
|
|
|
|
quint8 header_len = MsgPackPrivate::pack_bin_header(len, p, true) - p;
|
|
|
|
|
if (dev->write((char *)p, header_len) != header_len) {
|
|
|
|
|
setStatus(WriteFailed);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
if (dev->write(array.data(), len) != len)
|
|
|
|
|
setStatus(WriteFailed);
|
|
|
|
|
return *this;
|
2015-05-23 20:00:40 +03:00
|
|
|
}
|
|
|
|
|
|
2015-05-29 20:15:26 +03:00
|
|
|
bool MsgPackStream::writeBytes(const char *data, uint len)
|
|
|
|
|
{
|
2015-06-10 17:42:06 +03:00
|
|
|
CHECK_STREAM_WRITE_PRECOND(false);
|
2015-09-12 16:48:21 +03:00
|
|
|
if (dev->write(data, len) != len) {
|
2015-05-29 20:15:26 +03:00
|
|
|
setStatus(WriteFailed);
|
2015-09-12 16:48:21 +03:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MsgPackStream::writeExtHeader(quint32 len, qint8 msgpackType)
|
|
|
|
|
{
|
|
|
|
|
CHECK_STREAM_WRITE_PRECOND(false);
|
|
|
|
|
quint8 d[6];
|
|
|
|
|
d[1] = msgpackType;
|
|
|
|
|
quint8 sz = 2;
|
|
|
|
|
if (len == 1) {
|
|
|
|
|
d[0] = 0xd4;
|
|
|
|
|
} else if (len == 2) {
|
|
|
|
|
d[0] = 0xd5;
|
|
|
|
|
} else if (len == 4) {
|
|
|
|
|
d[0] = 0xd6;
|
|
|
|
|
} else if (len == 8) {
|
|
|
|
|
d[0] = 0xd7;
|
|
|
|
|
} else if (len == 16) {
|
|
|
|
|
d[0] = 0xd8;
|
|
|
|
|
} else if (len <= std::numeric_limits<quint8>::max()) {
|
|
|
|
|
d[0] = 0xc7;
|
|
|
|
|
d[1] = (quint8)len;
|
|
|
|
|
d[2] = msgpackType;
|
|
|
|
|
sz = 3;
|
|
|
|
|
} else if (len <= std::numeric_limits<quint16>::max()) {
|
|
|
|
|
d[0] = 0xc8;
|
|
|
|
|
_msgpack_store16(&d[1], len);
|
|
|
|
|
d[3] = msgpackType;
|
|
|
|
|
sz = 4;
|
|
|
|
|
} else {
|
|
|
|
|
d[0] = 0xc9;
|
|
|
|
|
_msgpack_store32(&d[1], len);
|
|
|
|
|
d[5] = msgpackType;
|
|
|
|
|
sz = 6;
|
|
|
|
|
}
|
|
|
|
|
if (dev->write((const char *)d, sz) != sz) {
|
|
|
|
|
setStatus(WriteFailed);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2015-06-10 17:42:06 +03:00
|
|
|
return true;
|
2015-05-29 20:15:26 +03:00
|
|
|
}
|
|
|
|
|
|
2015-06-10 17:42:06 +03:00
|
|
|
bool MsgPackStream::unpack_longlong(qint64 &i64)
|
2015-05-16 21:45:33 +03:00
|
|
|
{
|
2015-06-10 17:42:06 +03:00
|
|
|
quint8 p[9];
|
|
|
|
|
if (dev->read((char *)p, 1) != 1) {
|
|
|
|
|
setStatus(ReadPastEnd);
|
2015-05-16 21:45:33 +03:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-10 17:42:06 +03:00
|
|
|
if (p[0] <= 127) {// positive fixint 0x00 - 0x7f
|
|
|
|
|
i64 = p[0];
|
2015-05-16 21:45:33 +03:00
|
|
|
return true;
|
2015-06-10 17:42:06 +03:00
|
|
|
} else if (*p >= 0xe0) { // negative fixint 0xe0 - 0xff
|
|
|
|
|
i64 = (qint8)p[0];
|
2015-05-16 21:45:33 +03:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-10 17:42:06 +03:00
|
|
|
static int typeLengths[] = {1, 2, 4, 8, 1, 2, 4, 8};
|
|
|
|
|
int typeLength = typeLengths[p[0] - MsgPack::FirstByte::UINT8];
|
|
|
|
|
if (dev->read((char *)p + 1, typeLength) != typeLength) {
|
|
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (p[0] == MsgPack::FirstByte::UINT8) {
|
|
|
|
|
i64 = p[1];
|
|
|
|
|
} else if (p[0] == MsgPack::FirstByte::INT8) {
|
|
|
|
|
i64 = (qint8)p[1];
|
|
|
|
|
} else if (p[0] == MsgPack::FirstByte::UINT16) {
|
|
|
|
|
i64 = _msgpack_load16(quint16, p + 1);
|
|
|
|
|
} else if (p[0] == MsgPack::FirstByte::INT16) {
|
|
|
|
|
i64 = _msgpack_load16(qint16, p + 1);
|
|
|
|
|
} else if (p[0] == MsgPack::FirstByte::UINT32) {
|
|
|
|
|
i64 = _msgpack_load32(quint32, p + 1);
|
|
|
|
|
} else if (p[0] == MsgPack::FirstByte::INT32) {
|
|
|
|
|
i64 = _msgpack_load32(qint32, p + 1);
|
|
|
|
|
} else if (p[0] == MsgPack::FirstByte::UINT64) {
|
|
|
|
|
quint64 u64;
|
|
|
|
|
u64 = _msgpack_load64(quint64, p + 1);
|
2015-08-28 21:12:09 +03:00
|
|
|
if (u64 > (quint64)std::numeric_limits<qint64>::max()) {
|
2015-06-10 17:42:06 +03:00
|
|
|
setStatus(ReadCorruptData);
|
2015-05-16 21:45:33 +03:00
|
|
|
return false;
|
|
|
|
|
}
|
2015-06-10 17:42:06 +03:00
|
|
|
i64 = u64;
|
|
|
|
|
} else if (p[0] == MsgPack::FirstByte::INT64) {
|
|
|
|
|
i64 = _msgpack_load64(qint64, p + 1);
|
2015-05-16 21:45:33 +03:00
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-10 17:42:06 +03:00
|
|
|
bool MsgPackStream::unpack_ulonglong(quint64 &u64)
|
2015-05-16 21:45:33 +03:00
|
|
|
{
|
2015-06-10 17:42:06 +03:00
|
|
|
quint8 p[9];
|
|
|
|
|
if (dev->read((char *)p, 1) != 1) {
|
|
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return false;
|
2015-05-16 21:45:33 +03:00
|
|
|
}
|
|
|
|
|
|
2015-06-10 17:42:06 +03:00
|
|
|
if (p[0] <= 127) {// positive fixint 0x00 - 0x7f
|
|
|
|
|
u64 = p[0];
|
2015-05-16 21:45:33 +03:00
|
|
|
return true;
|
2015-06-10 17:42:06 +03:00
|
|
|
} else if (*p >= 0xe0) { // negative fixint 0xe0 - 0xff
|
|
|
|
|
return false;
|
2015-05-16 21:45:33 +03:00
|
|
|
}
|
2015-06-10 17:42:06 +03:00
|
|
|
|
|
|
|
|
static int typeLengths[] = {1, 2, 4, 8, 1, 2, 4, 8};
|
|
|
|
|
int typeLength = typeLengths[p[0] - MsgPack::FirstByte::UINT8];
|
|
|
|
|
if (dev->read((char *)p + 1, typeLength) != typeLength) {
|
|
|
|
|
setStatus(ReadPastEnd);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (p[0] == MsgPack::FirstByte::UINT8) {
|
|
|
|
|
u64 = p[1];
|
|
|
|
|
return true;
|
|
|
|
|
} else if (p[0] == MsgPack::FirstByte::UINT16) {
|
|
|
|
|
u64 = _msgpack_load16(quint64, p + 1);
|
|
|
|
|
return true;
|
|
|
|
|
} else if (p[0] == MsgPack::FirstByte::UINT32) {
|
|
|
|
|
u64 = _msgpack_load32(quint64, p + 1);
|
|
|
|
|
return true;
|
|
|
|
|
} else if (p[0] == MsgPack::FirstByte::UINT64) {
|
|
|
|
|
u64 = _msgpack_load64(quint64, p + 1);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
setStatus(ReadCorruptData);
|
|
|
|
|
return false;
|
2015-05-16 21:45:33 +03:00
|
|
|
}
|