mirror of
https://github.com/romixlab/qmsgpack.git
synced 2025-06-25 01:21:33 +02:00
Add peek(), readArrayHeader(), add length return to readExtHeader().
This commit is contained in:
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
Reference in New Issue
Block a user