1 Commits

4 changed files with 244 additions and 56 deletions

View File

@ -37,41 +37,51 @@ MSGPACK_EXPORT QString version();
*/
namespace FirstByte {
const quint8 POSITIVE_FIXINT = 0x7f;
const quint8 FIXMAP = 0x80;
const quint8 FIXARRAY = 0x90;
const quint8 FIXSTR = 0xa0;
const quint8 NIL = 0xc0;
const quint8 NEVER_USED = 0xc1;
const quint8 MFALSE = 0xc2;
const quint8 MTRUE = 0xc3;
const quint8 BIN8 = 0xc4;
const quint8 BIN16 = 0xc5;
const quint8 BIN32 = 0xc6;
const quint8 EXT8 = 0xc7;
const quint8 EXT16 = 0xc8;
const quint8 EXT32 = 0xc9;
const quint8 FLOAT32 = 0xca;
const quint8 FLOAT64 = 0xcb;
const quint8 UINT8 = 0xcc;
const quint8 UINT16 = 0xcd;
const quint8 UINT32 = 0xce;
const quint8 UINT64 = 0xcf;
const quint8 INT8 = 0xd0;
const quint8 INT16 = 0xd1;
const quint8 INT32 = 0xd2;
const quint8 INT64 = 0xd3;
const quint8 FIXEXT1 = 0xd4;
const quint8 FIXEXT2 = 0xd5;
const quint8 FIXEXT4 = 0xd6;
const quint8 FIXEXT8 = 0xd7;
const quint8 FIXEX16 = 0xd8;
const quint8 STR8 = 0xd9;
const quint8 STR16 = 0xda;
const quint8 STR32 = 0xdb;
const quint8 ARRAY16 = 0xdc;
const quint8 ARRAY32 = 0xdd;
const quint8 MAP16 = 0xde;
const quint8 MAP32 = 0xdf;
const quint8 FIXMAP = 0x80;
const quint8 FIXMAP_MASK = 0xf;
const quint8 FIXMAP_LAST = 0x8f;
const quint8 FIXARRAY = 0x90;
const quint8 FIXARRAY_MASK = 0xf;
const quint8 FIXARRAY_LAST = 0x9f;
const quint8 FIXSTR = 0xa0;
const quint8 FIXSTR_MASK = 0x1f;
const quint8 FIXSTR_LAST = 0xbf;
const quint8 NIL = 0xc0;
const quint8 NEVER_USED = 0xc1;
const quint8 MFALSE = 0xc2;
const quint8 MTRUE = 0xc3;
const quint8 BIN8 = 0xc4;
const quint8 BIN16 = 0xc5;
const quint8 BIN32 = 0xc6;
const quint8 EXT8 = 0xc7;
const quint8 EXT16 = 0xc8;
const quint8 EXT32 = 0xc9;
const quint8 FLOAT32 = 0xca;
const quint8 FLOAT64 = 0xcb;
const quint8 UINT8 = 0xcc;
const quint8 UINT16 = 0xcd;
const quint8 UINT32 = 0xce;
const quint8 UINT64 = 0xcf;
const quint8 INT8 = 0xd0;
const quint8 INT16 = 0xd1;
const quint8 INT32 = 0xd2;
const quint8 INT64 = 0xd3;
const quint8 FIXEXT1 = 0xd4;
const quint8 FIXEXT2 = 0xd5;
const quint8 FIXEXT4 = 0xd6;
const quint8 FIXEXT8 = 0xd7;
const quint8 FIXEX16 = 0xd8;
const quint8 STR8 = 0xd9;
const quint8 STR16 = 0xda;
const quint8 STR32 = 0xdb;
const quint8 ARRAY16 = 0xdc;
const quint8 ARRAY32 = 0xdd;
const quint8 MAP16 = 0xde;
const quint8 MAP32 = 0xdf;
const quint8 NEGATIVE_FIXINT = 0xe0;
}
}

View File

@ -26,15 +26,15 @@
return retVal;
MsgPackStream::MsgPackStream() :
dev(0), owndev(false), q_status(Ok), flushWrites(false)
dev(0), owndev(false), q_status(Ok), flushWrites(false), blocking(false), m_rawMode(false)
{ }
MsgPackStream::MsgPackStream(QIODevice *d) :
dev(d), owndev(false), q_status(Ok), flushWrites(false)
dev(d), owndev(false), q_status(Ok), flushWrites(false), blocking(false), m_rawMode(false)
{ }
MsgPackStream::MsgPackStream(QByteArray *a, QIODevice::OpenMode mode) :
owndev(true), q_status(Ok), flushWrites(false)
owndev(true), q_status(Ok), flushWrites(false), blocking(false), m_rawMode(false)
{
QBuffer *buf = new QBuffer(a);
buf->open(mode);
@ -42,7 +42,7 @@ MsgPackStream::MsgPackStream(QByteArray *a, QIODevice::OpenMode mode) :
}
MsgPackStream::MsgPackStream(const QByteArray &a) :
owndev(true), q_status(Ok), flushWrites(false)
owndev(true), q_status(Ok), flushWrites(false), blocking(false), m_rawMode(false)
{
QBuffer *buf = new QBuffer();
buf->setData(a);
@ -336,20 +336,25 @@ bool MsgPackStream::readBytes(char *data, qint64 len)
CHECK_STREAM_PRECOND(false);
qint64 readed = 0;
qint64 thisRead = 0;
while (readed < len)
{
thisRead = dev->read(data, (len - readed));
if (thisRead < 0)
break;
/* Advance the read pointer */
data += thisRead;
readed += thisRead;
/* Data might not be available for a bit, so wait before reading again. */
if (readed < len) {
dev->waitForReadyRead(-1);
if (blocking) {
while (readed < len)
{
thisRead = dev->read(data, (len - readed));
if (thisRead < 0)
break;
/* Advance the read pointer */
data += thisRead;
readed += thisRead;
/* Data might not be available for a bit, so wait before reading again. */
if (readed < len) {
dev->waitForReadyRead(-1);
}
}
} else {
thisRead = dev->read(data, len);
}
if (thisRead < 0) {
if (thisRead < 0 || thisRead < len) {
/* FIXME: There are actual errors that can happen here. */
setStatus(ReadPastEnd);
return false;
@ -357,7 +362,7 @@ bool MsgPackStream::readBytes(char *data, qint64 len)
return true;
}
bool MsgPackStream::readExtHeader(quint32 &len)
bool MsgPackStream::readExtHeader(quint32 &len, qint8 &type)
{
CHECK_STREAM_PRECOND(false);
quint8 d[6];
@ -369,6 +374,7 @@ bool MsgPackStream::readExtHeader(quint32 &len)
d[0] <= MsgPack::FirstByte::FIXEX16) {
len = 1;
len <<= d[0] - MsgPack::FirstByte::FIXEXT1;
type = d[1];
return true;
}
@ -381,10 +387,13 @@ bool MsgPackStream::readExtHeader(quint32 &len)
if (d[0] == MsgPack::FirstByte::EXT8) {
len = d[1];
type = d[2];
} else if (d[0] == MsgPack::FirstByte::EXT16) {
len = _msgpack_load16(quint32, &d[1]);
type = d[3];
} else if (d[0] == MsgPack::FirstByte::EXT32) {
len = _msgpack_load32(quint32, &d[1]);
type = d[5];
} else {
setStatus(ReadCorruptData);
return false;
@ -392,6 +401,38 @@ bool MsgPackStream::readExtHeader(quint32 &len)
return true;
}
bool MsgPackStream::readArrayHeader(quint32 &len)
{
CHECK_STREAM_PRECOND(false);
quint8 d[5];
if (!readBytes((char*)d, 1)) {
setStatus(ReadPastEnd);
return false;
}
if (d[0] >= MsgPack::FirstByte::FIXARRAY && d[0] <= MsgPack::FirstByte::FIXARRAY_LAST) {
len = d[0] & MsgPack::FirstByte::FIXARRAY_MASK;
return true;
}
if (d[0] == MsgPack::FirstByte::ARRAY16 || d[0] == MsgPack::FirstByte::ARRAY32) {
quint8 lengthSectionSize = 2;
lengthSectionSize <<= d[0] - MsgPack::FirstByte::ARRAY16; // 2 or 4
if (!readBytes((char *)d + 1, lengthSectionSize)) {
setStatus(ReadPastEnd);
return false;
}
if (d[0] == MsgPack::FirstByte::ARRAY16) {
len = _msgpack_load16(quint16, d + 1);
} else {
len = _msgpack_load32(quint32, d + 1);
}
return true;
}
setStatus(ReadCorruptData);
return false;
}
MsgPackStream &MsgPackStream::operator<<(bool b)
{
CHECK_STREAM_WRITE_PRECOND(*this);
@ -572,6 +613,118 @@ bool MsgPackStream::writeExtHeader(quint32 len, qint8 msgpackType)
return true;
}
void MsgPackStream::setBlocking(bool enabled)
{
blocking = enabled;
}
void MsgPackStream::setRawMode(bool enabled)
{
m_rawMode = enabled;
}
PeekResult MsgPackStream::peek() const
{
if (!dev)
return PeekResult();
quint8 buf[6];
if (dev->peek((char *)buf, 1) != 1)
return PeekResult();
PeekResult p;
if (buf[0] >= MsgPack::FirstByte::FIXEXT1 && buf[0] <= MsgPack::FirstByte::FIXEX16 ) {
if (dev->peek((char *)buf, 2) != 2)
return PeekResult();
p.status = PeekResult::PeekOk;
p.msgpackType = MsgPack::FirstByte::FIXEXT1;
p.userType = buf[1];
return p;
}
if (buf[0] >= MsgPack::FirstByte::EXT8 && buf[0] <= MsgPack::FirstByte::EXT32) {
quint8 lengthSectionSize = 1;
lengthSectionSize <<= buf[0] - MsgPack::FirstByte::EXT8; // 1 or 2 or 4
if (dev->peek((char*)buf, lengthSectionSize + 2) != lengthSectionSize + 2)
return PeekResult();
p.status = PeekResult::PeekOk;
p.msgpackType = MsgPack::FirstByte::FIXEXT1;
p.userType = buf[lengthSectionSize + 1];
return p;
}
if (buf[0] >= MsgPack::FirstByte::FIXARRAY && buf[0] <= MsgPack::FirstByte::FIXARRAY_LAST) {
p.status = PeekResult::PeekOk;
p.msgpackType = buf[0] & ~MsgPack::FirstByte::FIXARRAY_MASK;
p.length = buf[0] & MsgPack::FirstByte::FIXARRAY_MASK;
return p;
}
if (buf[0] == MsgPack::FirstByte::ARRAY16 || buf[0] == MsgPack::FirstByte::ARRAY32) {
quint8 lengthSectionSize = 2;
lengthSectionSize <<= buf[0] - MsgPack::FirstByte::ARRAY16; // 2 or 4
if (dev->peek((char*)buf, lengthSectionSize + 1) != lengthSectionSize + 1)
return PeekResult();
p.status = PeekResult::PeekOk;
p.msgpackType = buf[0];
if (buf[0] == MsgPack::FirstByte::ARRAY16) {
p.length = _msgpack_load16(quint16, buf + 1);
} else {
p.length = _msgpack_load32(quint32, buf + 1);
}
return p;
}
return PeekResult();
}
// PeekResult p;
// p.status = PeekResult::Status::PeekOk; // all values is covered below
// if ( buf[0] >= MsgPack::FirstByte::FIXMAP && buf[0] <= MsgPack::FirstByte::FIXMAP_LAST) {
// p.msgpackType = buf[0] & ~MsgPack::FirstByte::FIXMAP_MASK;
// p.length = buf[0] & MsgPack::FirstByte::FIXMAP_MASK;
// return p;
// }
// if (buf[0] >= MsgPack::FirstByte::FIXSTR && buf[0] <= MsgPack::FirstByte::FIXSTR_LAST) {
// p.msgpackType = buf[0] & ~MsgPack::FirstByte::FIXSTR_MASK;
// p.length = buf[0] & MsgPack::FirstByte::FIXSTR_MASK;
// return p;
// }
// if (buf[0] == MsgPack::FirstByte::BIN8 || buf[0] == MsgPack::FirstByte::STR8) {
// }
// if ( buf[0] == MsgPack::FirstByte::NIL ||
// buf[0] == MsgPack::FirstByte::NEVER_USED ||
// buf[0] == MsgPack::FirstByte::MFALSE ||
// buf[0] == MsgPack::FirstByte::MTRUE ||
// buf[0] <= MsgPack::FirstByte::POSITIVE_FIXINT ||
// buf[0] >= MsgPack::FirstByte::NEGATIVE_FIXINT ) {
// p.msgpackType = buf[0];
// return p;
// }
// if ( buf[0] == MsgPack::FirstByte::UINT8 ||
// buf[0] == MsgPack::FirstByte::INT8 ) {
// p.msgpackType = buf[0];
// p.length = 1;
// return p;
// }
// if ( buf[0] == MsgPack::FirstByte::UINT16 ||
// buf[0] == MsgPack::FirstByte::INT16 ) {
// p.msgpackType = buf[0];
// p.length = 2;
// return p;
// }
// if ( buf[0] == MsgPack::FirstByte::UINT32 ||
// buf[0] == MsgPack::FirstByte::INT32 ||
// MsgPack::FirstByte::FLOAT32 ) {
// p.msgpackType = buf[0];
// p.length = 4;
// return p;
// }
// if ( buf[0] == MsgPack::FirstByte::UINT64 ||
// buf[0] == MsgPack::FirstByte::INT64 ||
// MsgPack::FirstByte::FLOAT64 ) {
// p.msgpackType = buf[0];
// p.length = 8;
// return p;
// }
//}
bool MsgPackStream::unpack_longlong(qint64 &i64)
{
quint8 p[9];

View File

@ -9,6 +9,21 @@
#include <QIODevice>
class PeekResult {
public:
PeekResult() : status(PeekFailed), msgpackType(0), userType(0), length(0) {}
quint8 msgpackType;
quint8 userType;
quint32 length;
enum Status {
PeekOk,
PeekFailed
};
Status status;
};
class MSGPACK_EXPORT MsgPackStream
{
public:
@ -43,7 +58,8 @@ public:
MsgPackStream &operator>>(QString &str);
MsgPackStream &operator>>(QByteArray &array);
bool readBytes(char *data, qint64 len);
bool readExtHeader(quint32 &len);
bool readExtHeader(quint32 &len, qint8 &type);
bool readArrayHeader(quint32 &len);
MsgPackStream &operator<<(bool b);
MsgPackStream &operator<<(quint32 u32);
@ -58,11 +74,17 @@ public:
bool writeBytes(const char *data, qint64 len);
bool writeExtHeader(quint32 len, qint8 msgpackType);
PeekResult peek() const;
void setBlocking(bool enabled);
void setRawMode(bool enabled);
private:
QIODevice *dev;
bool owndev;
Status q_status;
bool flushWrites;
bool blocking;
bool m_rawMode;
bool unpack_longlong(qint64 &i64);
bool unpack_ulonglong(quint64 &u64);

View File

@ -74,7 +74,8 @@ MsgPackStream &operator<<(MsgPackStream &s, const QTime &t)
MsgPackStream& operator>>(MsgPackStream& s, QTime &t)
{
quint32 len;
s.readExtHeader(len);
qint8 type;
s.readExtHeader(len, type);
if (len != 1 && len != 2 && len != 4) {
s.setStatus(MsgPackStream::ReadCorruptData);
t = QTime();
@ -109,7 +110,8 @@ MsgPackStream &operator<<(MsgPackStream &s, const QDate &date)
MsgPackStream& operator>>(MsgPackStream& s, QDate &date)
{
quint32 len;
s.readExtHeader(len);
qint8 type;
s.readExtHeader(len, type);
if (len != 1 && len != 3) {
s.setStatus(MsgPackStream::ReadCorruptData);
date = QDate();
@ -150,7 +152,8 @@ MsgPackStream &operator<<(MsgPackStream& s, const QDateTime &dt)
MsgPackStream& operator>>(MsgPackStream& s, QDateTime &dt)
{
quint32 len;
s.readExtHeader(len);
qint8 type;
s.readExtHeader(len, type);
if (len != 1 && len != 5 && len != 7) {
s.setStatus(MsgPackStream::ReadCorruptData);
dt = QDateTime();