mirror of
https://github.com/romixlab/qmsgpack.git
synced 2025-07-31 19:04:26 +02:00
MsgPackStream integers pack and unpack
User types packers now called only once, and return QByteArray
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include "private/pack_p.h"
|
||||
#include "private/qt_types_p.h"
|
||||
#include "private/sysdep.h"
|
||||
#include <QVector>
|
||||
|
||||
QVariant MsgPack::unpack(const QByteArray &data)
|
||||
{
|
||||
@@ -16,13 +17,14 @@ QVariant MsgPack::unpack(const QByteArray &data)
|
||||
QByteArray MsgPack::pack(const QVariant &variant)
|
||||
{
|
||||
quint8 *p = 0;
|
||||
quint8 *end = MsgPackPrivate::pack(variant, p, false);
|
||||
QVector<QByteArray> user_data;
|
||||
quint8 *end = MsgPackPrivate::pack(variant, p, false, user_data);
|
||||
quint32 size = end - p;
|
||||
//qDebug() << "size probe:" << size;
|
||||
|
||||
QByteArray arr;
|
||||
arr.resize(size);
|
||||
end = MsgPackPrivate::pack(variant, (quint8 *)arr.data(), true);
|
||||
end = MsgPackPrivate::pack(variant, (quint8 *)arr.data(), true, user_data);
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
@@ -10,14 +10,14 @@
|
||||
|
||||
namespace MsgPack {
|
||||
/**
|
||||
* pack some variant to byte array data
|
||||
* when write == false only calculates and returns size
|
||||
* when write == true writes bytes to data, and returns the same size
|
||||
* return type size
|
||||
* @brief pack user type to byte array data
|
||||
* @arg variant user type, must be registered first
|
||||
* @return array with user data only, all other fields will be added automatically
|
||||
*/
|
||||
typedef quint32 (*pack_user_f)(const QVariant &variant, QByteArray &data, bool write);
|
||||
typedef QByteArray (*pack_user_f)(const QVariant &variant);
|
||||
/**
|
||||
* unpack user type to QVariant
|
||||
* @brief unpack user type to QVariant
|
||||
* @arg data only user data, without size and messagepack type
|
||||
*/
|
||||
typedef QVariant (*unpack_user_f)(const QByteArray &data);
|
||||
/**
|
||||
|
@@ -16,7 +16,7 @@ QHash<QMetaType::Type, MsgPackPrivate::packer_t> MsgPackPrivate::user_packers;
|
||||
bool MsgPackPrivate::compatibilityMode = false;
|
||||
QReadWriteLock MsgPackPrivate::packers_lock;
|
||||
|
||||
quint8 *MsgPackPrivate::pack(const QVariant &v, quint8 *p, bool wr)
|
||||
quint8 *MsgPackPrivate::pack(const QVariant &v, quint8 *p, bool wr, QVector<QByteArray> &user_data)
|
||||
{
|
||||
QMetaType::Type t = (QMetaType::Type)v.type();
|
||||
if (t == QMetaType::Int)
|
||||
@@ -28,7 +28,7 @@ quint8 *MsgPackPrivate::pack(const QVariant &v, quint8 *p, bool wr)
|
||||
else if (t == QMetaType::QString)
|
||||
p = pack_string(v.toString(), p, wr);
|
||||
else if (t == QMetaType::QVariantList)
|
||||
p = pack_array(v.toList(), p, wr);
|
||||
p = pack_array(v.toList(), p, wr, user_data);
|
||||
else if (t == QMetaType::QStringList)
|
||||
p = pack_stringlist(v.toStringList(), p, wr);
|
||||
else if (t == QMetaType::LongLong)
|
||||
@@ -40,7 +40,7 @@ quint8 *MsgPackPrivate::pack(const QVariant &v, quint8 *p, bool wr)
|
||||
else if (t == QMetaType::QByteArray)
|
||||
p = pack_bin(v.toByteArray(), p, wr);
|
||||
else if (t == QMetaType::QVariantMap)
|
||||
p = pack_map(v.toMap(), p, wr);
|
||||
p = pack_map(v.toMap(), p, wr, user_data);
|
||||
else {
|
||||
if (t == QMetaType::User)
|
||||
t = (QMetaType::Type)v.userType();
|
||||
@@ -48,7 +48,7 @@ quint8 *MsgPackPrivate::pack(const QVariant &v, quint8 *p, bool wr)
|
||||
bool has_packer = user_packers.contains(t);
|
||||
locker.unlock();
|
||||
if (has_packer)
|
||||
p = pack_user(v, p, wr);
|
||||
p = pack_user(v, p, wr, user_data);
|
||||
else
|
||||
qWarning() << "MsgPack::pack can't pack type:" << t;
|
||||
}
|
||||
@@ -157,12 +157,12 @@ quint8 *MsgPackPrivate::pack_arraylen(quint32 len, quint8 *p, bool wr)
|
||||
return p;
|
||||
}
|
||||
|
||||
quint8 *MsgPackPrivate::pack_array(const QVariantList &list, quint8 *p, bool wr)
|
||||
quint8 *MsgPackPrivate::pack_array(const QVariantList &list, quint8 *p, bool wr, QVector<QByteArray> &user_data)
|
||||
{
|
||||
int len = list.length();
|
||||
p = pack_arraylen(len, p, wr);
|
||||
foreach (QVariant item, list)
|
||||
p = pack(item, p, wr);
|
||||
p = pack(item, p, wr, user_data);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ quint8 *MsgPackPrivate::pack_bin(const QByteArray &arr, quint8 *p, bool wr)
|
||||
}
|
||||
|
||||
|
||||
quint8 *MsgPackPrivate::pack_map(const QVariantMap &map, quint8 *p, bool wr)
|
||||
quint8 *MsgPackPrivate::pack_map(const QVariantMap &map, quint8 *p, bool wr, QVector<QByteArray> &user_data)
|
||||
{
|
||||
QMapIterator<QString, QVariant> it(map);
|
||||
int len = 0;
|
||||
@@ -272,8 +272,8 @@ quint8 *MsgPackPrivate::pack_map(const QVariantMap &map, quint8 *p, bool wr)
|
||||
it.toFront();
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
p = pack(it.key(), p, wr);
|
||||
p = pack(it.value(), p, wr);
|
||||
p = pack(it.key(), p, wr, user_data);
|
||||
p = pack(it.value(), p, wr, user_data);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
@@ -296,15 +296,25 @@ bool MsgPackPrivate::register_packer(QMetaType::Type q_type, qint8 msgpack_type,
|
||||
return true;
|
||||
}
|
||||
|
||||
quint8 *MsgPackPrivate::pack_user(const QVariant &v, quint8 *p, bool wr)
|
||||
quint8 *MsgPackPrivate::pack_user(const QVariant &v, quint8 *p, bool wr, QVector<QByteArray> &user_data)
|
||||
{
|
||||
QMetaType::Type t = (QMetaType::Type)v.type() == QMetaType::User ?
|
||||
(QMetaType::Type)v.userType() : (QMetaType::Type)v.type();
|
||||
QByteArray data;
|
||||
QReadLocker locker(&packers_lock);
|
||||
packer_t pt = user_packers[t];
|
||||
locker.unlock();
|
||||
quint32 len = pt.packer(v, data, wr);
|
||||
|
||||
QByteArray data;
|
||||
if (wr) {
|
||||
data = user_data.front();
|
||||
user_data.pop_front();
|
||||
|
||||
} else {
|
||||
data = pt.packer(v);
|
||||
user_data.push_back(data);
|
||||
}
|
||||
|
||||
quint32 len = data.size();
|
||||
if (len == 1) {
|
||||
if (wr) *p = 0xd4;
|
||||
p++;
|
||||
|
@@ -23,7 +23,7 @@ extern QHash<QMetaType::Type, packer_t> user_packers;
|
||||
extern QReadWriteLock packers_lock;
|
||||
extern bool compatibilityMode;
|
||||
|
||||
quint8 * pack(const QVariant &v, quint8 *p, bool wr);
|
||||
quint8 * pack(const QVariant &v, quint8 *p, bool wr, QVector<QByteArray> &user_data);
|
||||
|
||||
quint8 * pack_int(qint32 i, quint8 *p, bool wr);
|
||||
quint8 * pack_uint(quint32 i, quint8 *p, bool wr);
|
||||
@@ -33,14 +33,14 @@ quint8 * pack_ulonglong(quint64 i, quint8 *p, bool wr);
|
||||
quint8 * pack_bool(const QVariant &v, quint8 *p, bool wr);
|
||||
|
||||
quint8 * pack_arraylen(quint32 len, quint8 *p, bool wr);
|
||||
quint8 * pack_array(const QVariantList &list, quint8 *p, bool wr);
|
||||
quint8 * pack_array(const QVariantList &list, quint8 *p, bool wr, QVector<QByteArray> &user_data);
|
||||
quint8 * pack_stringlist(const QStringList &list, quint8 *p, bool wr);
|
||||
|
||||
quint8 * pack_string(const QString &str, quint8 *p, bool wr);
|
||||
quint8 * pack_double(double i, quint8 *p, bool wr);
|
||||
quint8 * pack_bin(const QByteArray &arr, quint8 *p, bool wr);
|
||||
quint8 * pack_map(const QVariantMap &map, quint8 *p, bool wr);
|
||||
quint8 * pack_user(const QVariant &v, quint8 *p, bool wr);
|
||||
quint8 * pack_map(const QVariantMap &map, quint8 *p, bool wr, QVector<QByteArray> &user_data);
|
||||
quint8 * pack_user(const QVariant &v, quint8 *p, bool wr, QVector<QByteArray> &user_data);
|
||||
}
|
||||
|
||||
#endif // PACK_P_H
|
||||
|
@@ -46,18 +46,17 @@ bool MsgPackPrivate::register_qtype(QMetaType::Type q_type, quint8 msgpack_type)
|
||||
}
|
||||
|
||||
#ifdef QT_GUI_LIB
|
||||
quint32 MsgPackPrivate::pack_qcolor(const QVariant &variant, QByteArray &data, bool write)
|
||||
QByteArray MsgPackPrivate::pack_qcolor(const QVariant &variant)
|
||||
{
|
||||
if (write) {
|
||||
QColor color = variant.value<QColor>();
|
||||
data.resize(4);
|
||||
quint8 *p = (quint8 *)data.data();
|
||||
p[0] = color.red();
|
||||
p[1] = color.green();
|
||||
p[2] = color.blue();
|
||||
p[3] = color.alpha();
|
||||
}
|
||||
return 4; // 4 bytes: r,g,b,a
|
||||
QByteArray data;
|
||||
data.resize(4);
|
||||
QColor color = variant.value<QColor>();
|
||||
quint8 *p = (quint8 *)data.data();
|
||||
p[0] = color.red();
|
||||
p[1] = color.green();
|
||||
p[2] = color.blue();
|
||||
p[3] = color.alpha();
|
||||
return data;
|
||||
}
|
||||
|
||||
QVariant MsgPackPrivate::unpack_qcolor(const QByteArray &data)
|
||||
@@ -96,15 +95,14 @@ QTime MsgPackPrivate::unpack_qtime_raw(quint8 *p, bool with_ms)
|
||||
return QTime(h, m, s, ms);
|
||||
}
|
||||
|
||||
quint32 MsgPackPrivate::pack_qtime(const QVariant &variant, QByteArray &data, bool write)
|
||||
QByteArray MsgPackPrivate::pack_qtime(const QVariant &variant)
|
||||
{
|
||||
QTime time = variant.toTime();
|
||||
quint8 size = time.msec() == 0 ? 2 : 4;
|
||||
if (write) {
|
||||
data.resize(size);
|
||||
pack_qtime_raw(time, (quint8 *)data.data());
|
||||
}
|
||||
return size;
|
||||
QByteArray data;
|
||||
data.resize(size);
|
||||
pack_qtime_raw(time, (quint8 *)data.data());
|
||||
return data;
|
||||
}
|
||||
|
||||
QVariant MsgPackPrivate::unpack_qtime(const QByteArray &data)
|
||||
@@ -134,13 +132,12 @@ QDate MsgPackPrivate::unpack_qdate_raw(quint8 *p)
|
||||
return QDate(year, month, day);
|
||||
}
|
||||
|
||||
quint32 MsgPackPrivate::pack_qdate(const QVariant &variant, QByteArray &data, bool write)
|
||||
QByteArray MsgPackPrivate::pack_qdate(const QVariant &variant)
|
||||
{
|
||||
if (write) {
|
||||
data.resize(3);
|
||||
pack_qdate_raw(variant.toDate(), (quint8 *)data.data());
|
||||
}
|
||||
return 3;
|
||||
QByteArray data;
|
||||
data.resize(3);
|
||||
pack_qdate_raw(variant.toDate(), (quint8 *)data.data());
|
||||
return data;
|
||||
}
|
||||
|
||||
QVariant MsgPackPrivate::unpack_qdate(const QByteArray &data)
|
||||
@@ -148,18 +145,17 @@ QVariant MsgPackPrivate::unpack_qdate(const QByteArray &data)
|
||||
return unpack_qdate_raw((quint8 *)data.data());
|
||||
}
|
||||
|
||||
quint32 MsgPackPrivate::pack_qdatetime(const QVariant &variant, QByteArray &data, bool write)
|
||||
QByteArray MsgPackPrivate::pack_qdatetime(const QVariant &variant)
|
||||
{
|
||||
QDateTime dt = variant.toDateTime();
|
||||
quint8 time_size = dt.time().msec() == 0 ? 2 : 4;
|
||||
if (write) {
|
||||
data.resize(3 + time_size);
|
||||
quint8 *p = (quint8 *)data.data();
|
||||
pack_qdate_raw(dt.date(), p);
|
||||
p += 3;
|
||||
pack_qtime_raw(dt.time(), p);
|
||||
}
|
||||
return 3 + time_size; // 3 for date, 4 for time
|
||||
QByteArray data;
|
||||
data.resize(3 + time_size);
|
||||
quint8 *p = (quint8 *)data.data();
|
||||
pack_qdate_raw(dt.date(), p);
|
||||
p += 3;
|
||||
pack_qtime_raw(dt.time(), p);
|
||||
return data;
|
||||
}
|
||||
|
||||
QVariant MsgPackPrivate::unpack_qdatetime(const QByteArray &data)
|
||||
@@ -171,20 +167,7 @@ QVariant MsgPackPrivate::unpack_qdatetime(const QByteArray &data)
|
||||
}
|
||||
|
||||
// Points and Vectors
|
||||
quint8 MsgPackPrivate::pack_two_integers(qint32 a, qint32 b, quint8 *to, bool write)
|
||||
{
|
||||
quint8 *p = 0;
|
||||
p = MsgPackPrivate::pack_int(a, p, false);
|
||||
p = MsgPackPrivate::pack_int(b, p, false);
|
||||
quint8 size = p - (quint8 *)0;
|
||||
if (write) {
|
||||
to = MsgPackPrivate::pack_int(a, to, true);
|
||||
MsgPackPrivate::pack_int(b, to, true);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
quint32 MsgPackPrivate::pack_qpoint(const QVariant &variant, QByteArray &data, bool write)
|
||||
QByteArray MsgPackPrivate::pack_qpoint(const QVariant &variant)
|
||||
{
|
||||
// QPoint pt = variant.toPoint();
|
||||
// quint8 size = pack_two_integers(pt.x(), pt.y(), 0, false);
|
||||
@@ -208,7 +191,7 @@ QVariant MsgPackPrivate::unpack_qpoint(const QByteArray &data)
|
||||
// return pt;
|
||||
}
|
||||
|
||||
quint32 MsgPackPrivate::pack_qsize(const QVariant &variant, QByteArray &data, bool write)
|
||||
QByteArray MsgPackPrivate::pack_qsize(const QVariant &variant)
|
||||
{
|
||||
// QSize sz = variant.toSize();
|
||||
// quint8 size = pack_two_integers(sz.width(), sz.height(), 0, false);
|
||||
@@ -232,7 +215,7 @@ QVariant MsgPackPrivate::unpack_qsize(const QByteArray &data)
|
||||
// return sz;
|
||||
}
|
||||
|
||||
quint32 MsgPackPrivate::pack_qrect(const QVariant &variant, QByteArray &data, bool write)
|
||||
QByteArray MsgPackPrivate::pack_qrect(const QVariant &variant)
|
||||
{
|
||||
// QRect rect = variant.toRect();
|
||||
// QPoint pt1 = rect.topLeft();
|
||||
|
@@ -9,7 +9,7 @@ namespace MsgPackPrivate
|
||||
bool register_qtype(QMetaType::Type q_type, quint8 msgpack_type);
|
||||
|
||||
#ifdef QT_GUI_LIB
|
||||
quint32 pack_qcolor(const QVariant &variant, QByteArray &data, bool write);
|
||||
QByteArray pack_qcolor(const QVariant &variant);
|
||||
QVariant unpack_qcolor(const QByteArray &data);
|
||||
#endif //QT_GUI_LIB
|
||||
|
||||
@@ -28,7 +28,7 @@ void pack_qtime_raw(const QTime &time, quint8 *p); // return 2 - without ms, 4 w
|
||||
* @return QTime
|
||||
*/
|
||||
QTime unpack_qtime_raw(quint8 *p, bool with_ms);
|
||||
quint32 pack_qtime(const QVariant &variant, QByteArray &data, bool write);
|
||||
QByteArray pack_qtime(const QVariant &variant);
|
||||
QVariant unpack_qtime(const QByteArray &data);
|
||||
|
||||
/**
|
||||
@@ -40,19 +40,18 @@ QVariant unpack_qtime(const QByteArray &data);
|
||||
void pack_qdate_raw(const QDate &date, quint8 *p);
|
||||
/// @brief internal: unpack bytes to QDate
|
||||
QDate unpack_qdate_raw(quint8 *p);
|
||||
quint32 pack_qdate(const QVariant &variant, QByteArray &data, bool write);
|
||||
QByteArray pack_qdate(const QVariant &variant);
|
||||
QVariant unpack_qdate(const QByteArray &data);
|
||||
|
||||
quint32 pack_qdatetime(const QVariant &variant, QByteArray &data, bool write);
|
||||
QByteArray pack_qdatetime(const QVariant &variant);
|
||||
QVariant unpack_qdatetime(const QByteArray &data);
|
||||
|
||||
// Points and Vectors
|
||||
quint8 pack_two_integers(qint32 a, qint32 b, quint8 *to, bool write);
|
||||
quint32 pack_qpoint(const QVariant &variant, QByteArray &data, bool write);
|
||||
QByteArray pack_qpoint(const QVariant &variant);
|
||||
QVariant unpack_qpoint(const QByteArray &data);
|
||||
quint32 pack_qsize(const QVariant &variant, QByteArray &data, bool write);
|
||||
QByteArray pack_qsize(const QVariant &variant);
|
||||
QVariant unpack_qsize(const QByteArray &data);
|
||||
quint32 pack_qrect(const QVariant &variant, QByteArray &data, bool write);
|
||||
QByteArray pack_qrect(const QVariant &variant);
|
||||
QVariant unpack_qrect(const QByteArray &data);
|
||||
|
||||
} // MsgPackPrivate
|
||||
|
291
src/stream.cpp
291
src/stream.cpp
@@ -3,6 +3,7 @@
|
||||
#include "private/sysdep.h"
|
||||
#include "private/pack_p.h"
|
||||
#include "msgpack_common.h"
|
||||
#include <limits>
|
||||
#include <QDebug>
|
||||
|
||||
#undef CHECK_STREAM_PRECOND
|
||||
@@ -106,35 +107,98 @@ MsgPackStream &MsgPackStream::operator>>(bool &b)
|
||||
|
||||
MsgPackStream &MsgPackStream::operator >>(quint8 &u8)
|
||||
{
|
||||
CHECK_STREAM_PRECOND(*this)
|
||||
char c;
|
||||
if (!dev->getChar(&c)) {
|
||||
u8 = 0;
|
||||
CHECK_STREAM_PRECOND(*this);
|
||||
quint8 p;
|
||||
if (dev->read((char *)&p, 1) != 1) {
|
||||
setStatus(ReadPastEnd);
|
||||
} else {
|
||||
u8 = quint8(c);
|
||||
return *this;
|
||||
}
|
||||
unpack_upto_quint8(u8, &p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MsgPackStream &MsgPackStream::operator>>(quint16 &u16)
|
||||
{
|
||||
CHECK_STREAM_PRECOND(*this);
|
||||
quint8 p[3];
|
||||
if (dev->read((char *)p, 3) != 3) {
|
||||
u16 = 0;
|
||||
quint8 p;
|
||||
if (dev->read((char *)&p, 1) != 1) {
|
||||
setStatus(ReadPastEnd);
|
||||
} else {
|
||||
if (p[0] != MsgPack::FirstByte::UINT16)
|
||||
setStatus(ReadCorruptData);
|
||||
u16 = _msgpack_load16(quint16, (p + 1));
|
||||
return *this;
|
||||
}
|
||||
unpack_upto_quint16(u16, &p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MsgPackStream &MsgPackStream::operator>>(quint32 &u32)
|
||||
{
|
||||
CHECK_STREAM_PRECOND(*this);
|
||||
quint8 p;
|
||||
if (dev->read((char *)&p, 1) != 1) {
|
||||
setStatus(ReadPastEnd);
|
||||
return *this;
|
||||
}
|
||||
unpack_upto_quint32(u32, &p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MsgPackStream &MsgPackStream::operator>>(quint64 &u64)
|
||||
{
|
||||
CHECK_STREAM_PRECOND(*this);
|
||||
quint8 p;
|
||||
if (dev->read((char *)&p, 1) != 1) {
|
||||
setStatus(ReadPastEnd);
|
||||
return *this;
|
||||
}
|
||||
unpack_upto_quint64(u64, &p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MsgPackStream &MsgPackStream::operator>>(qint8 &i8)
|
||||
{
|
||||
CHECK_STREAM_PRECOND(*this);
|
||||
quint8 p;
|
||||
if (dev->read((char *)&p, 1) != 1) {
|
||||
setStatus(ReadPastEnd);
|
||||
return *this;
|
||||
}
|
||||
unpack_upto_qint8(i8, &p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MsgPackStream &MsgPackStream::operator>>(qint16 &i16)
|
||||
{
|
||||
CHECK_STREAM_PRECOND(*this);
|
||||
quint8 p;
|
||||
if (dev->read((char *)&p, 1) != 1) {
|
||||
setStatus(ReadPastEnd);
|
||||
return *this;
|
||||
}
|
||||
unpack_upto_qint16(i16, &p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MsgPackStream &MsgPackStream::operator>>(qint32 &i32)
|
||||
{
|
||||
CHECK_STREAM_PRECOND(*this);
|
||||
quint8 p;
|
||||
if (dev->read((char *)&p, 1) != 1) {
|
||||
setStatus(ReadPastEnd);
|
||||
return *this;
|
||||
}
|
||||
unpack_upto_qint32(i32, &p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MsgPackStream &MsgPackStream::operator>>(qint64 &i64)
|
||||
{
|
||||
CHECK_STREAM_PRECOND(*this);
|
||||
quint8 p;
|
||||
if (dev->read((char *)&p, 1) != 1) {
|
||||
setStatus(ReadPastEnd);
|
||||
return *this;
|
||||
}
|
||||
unpack_upto_qint64(i64, &p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MsgPackStream &MsgPackStream::operator>>(QString &str)
|
||||
@@ -179,7 +243,17 @@ MsgPackStream &MsgPackStream::operator<<(quint32 u32)
|
||||
CHECK_STREAM_WRITE_PRECOND(*this);
|
||||
quint8 p[5];
|
||||
quint8 sz = MsgPackPrivate::pack_uint(u32, p, true) - p;
|
||||
if (!dev->write((char *)p, sz) != sz)
|
||||
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)
|
||||
setStatus(WriteFailed);
|
||||
return *this;
|
||||
}
|
||||
@@ -188,8 +262,18 @@ MsgPackStream &MsgPackStream::operator<<(qint32 i32)
|
||||
{
|
||||
CHECK_STREAM_WRITE_PRECOND(*this);
|
||||
quint8 p[5];
|
||||
quint8 sz = MsgPackPrivate::pack_uint(i32, p, true) - p;
|
||||
if (!dev->write((char *)p, sz) != sz)
|
||||
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)
|
||||
setStatus(WriteFailed);
|
||||
return *this;
|
||||
}
|
||||
@@ -200,7 +284,8 @@ MsgPackStream &MsgPackStream::operator<<(QString str)
|
||||
quint8 *p = (quint8 *)0;
|
||||
quint32 sz = MsgPackPrivate::pack_string(str, p, false) - p;
|
||||
quint8 *data = new quint8[sz];
|
||||
MsgPackPrivate::pack(str, data, true);
|
||||
QVector<QByteArray> user_data;
|
||||
MsgPackPrivate::pack(str, data, true, user_data);
|
||||
if (dev->write((char *)data, sz) != sz)
|
||||
setStatus(WriteFailed);
|
||||
delete[] data;
|
||||
@@ -211,3 +296,175 @@ MsgPackStream &MsgPackStream::operator<<(const char *str)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool MsgPackStream::unpack_upto_quint8(quint8 &u8, quint8 *p)
|
||||
{
|
||||
if (*p <= MsgPack::FirstByte::POSITIVE_FIXINT) {
|
||||
u8 = *p;
|
||||
} else if (*p == MsgPack::FirstByte::UINT8) {
|
||||
if (dev->read((char* )&u8, 1) != 1) {
|
||||
setStatus(ReadPastEnd);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
setStatus(ReadCorruptData);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MsgPackStream::unpack_upto_quint16(quint16 &u16, quint8 *p)
|
||||
{
|
||||
if (*p == MsgPack::FirstByte::UINT16) {
|
||||
quint8 d[2];
|
||||
if (dev->read((char *)d, 2) != 2) {
|
||||
setStatus(ReadPastEnd);
|
||||
return false;
|
||||
}
|
||||
u16 = _msgpack_load16(quint16, d);
|
||||
} else {
|
||||
quint8 u8;
|
||||
bool ok = unpack_upto_quint8(u8, p);
|
||||
u16 = u8;
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
bool MsgPackStream::unpack_upto_quint32(quint32 &u32, quint8 *p)
|
||||
{
|
||||
if (*p == MsgPack::FirstByte::UINT32) {
|
||||
quint8 d[4];
|
||||
if (dev->read((char *)d, 4) != 4) {
|
||||
setStatus(ReadPastEnd);
|
||||
return false;
|
||||
}
|
||||
u32 = _msgpack_load32(quint32, d);
|
||||
return true;
|
||||
} else {
|
||||
quint16 u16;
|
||||
bool ok = unpack_upto_quint16(u16, p);
|
||||
u32 = u16;
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
bool MsgPackStream::unpack_upto_quint64(quint64 &u64, quint8 *p)
|
||||
{
|
||||
if (*p == MsgPack::FirstByte::UINT64) {
|
||||
quint8 d[8];
|
||||
if (dev->read((char *)d, 8) != 8) {
|
||||
setStatus(ReadPastEnd);
|
||||
return false;
|
||||
}
|
||||
u64 = _msgpack_load64(quint64, d);
|
||||
return true;
|
||||
} else {
|
||||
quint32 u32;
|
||||
bool ok = unpack_upto_quint32(u32, p);
|
||||
u64 = u32;
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
bool MsgPackStream::unpack_upto_qint8(qint8 &i8, quint8 *p)
|
||||
{
|
||||
if (*p >= MsgPack::FirstByte::NEGATIVE_FIXINT) {
|
||||
i8 = *p;
|
||||
} else if (*p == MsgPack::FirstByte::INT8) {
|
||||
if (dev->read((char *)&i8, 1) != 1) {
|
||||
setStatus(ReadPastEnd);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
quint8 u8;
|
||||
bool ok = unpack_upto_quint8(u8, p);
|
||||
if (u8 > std::numeric_limits<qint8>::max())
|
||||
setStatus(ReadCorruptData);
|
||||
else
|
||||
i8 = u8;
|
||||
return ok;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MsgPackStream::unpack_upto_qint16(qint16 &i16, quint8 *p)
|
||||
{
|
||||
if (*p == MsgPack::FirstByte::INT16) {
|
||||
quint8 d[2];
|
||||
if (dev->read((char *)d, 2) != 2) {
|
||||
setStatus(ReadPastEnd);
|
||||
return false;
|
||||
}
|
||||
i16 = _msgpack_load16(qint16, d);
|
||||
return true;
|
||||
} else {
|
||||
qint8 i8;
|
||||
bool ok = unpack_upto_qint8(i8, p);
|
||||
if (ok) {
|
||||
i16 = i8;
|
||||
} else {
|
||||
quint16 u16;
|
||||
bool ok = unpack_upto_quint16(u16, p);
|
||||
if (u16 <= std::numeric_limits<qint16>::max())
|
||||
i16 = u16;
|
||||
else
|
||||
setStatus(ReadCorruptData);
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MsgPackStream::unpack_upto_qint32(qint32 &i32, quint8 *p)
|
||||
{
|
||||
if(*p == MsgPack::FirstByte::INT32) {
|
||||
quint8 d[4];
|
||||
if (dev->read((char *)d, 4) != 4) {
|
||||
setStatus(ReadPastEnd);
|
||||
return false;
|
||||
}
|
||||
i32 = _msgpack_load32(qint32, d);
|
||||
return true;
|
||||
} else {
|
||||
qint16 i16;
|
||||
bool ok = unpack_upto_qint16(i16, p);
|
||||
if (ok) {
|
||||
i32 = i16;
|
||||
} else {
|
||||
quint32 u32;
|
||||
bool ok = unpack_upto_quint32(u32, p);
|
||||
if (u32 <= std::numeric_limits<qint32>::max())
|
||||
i32 = u32;
|
||||
else
|
||||
setStatus(ReadCorruptData);
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MsgPackStream::unpack_upto_qint64(qint64 &i64, quint8 *p)
|
||||
{
|
||||
if(*p == MsgPack::FirstByte::INT64) {
|
||||
quint8 d[8];
|
||||
if (dev->read((char *)d, 8) != 8) {
|
||||
setStatus(ReadPastEnd);
|
||||
return false;
|
||||
}
|
||||
i64 = _msgpack_load64(qint64, d);
|
||||
return true;
|
||||
} else {
|
||||
qint32 i32;
|
||||
bool ok = unpack_upto_qint32(i32, p);
|
||||
if (ok) {
|
||||
i64 = i32;
|
||||
} else {
|
||||
quint64 u64;
|
||||
bool ok = unpack_upto_quint64(u64, p);
|
||||
if (u64 <= std::numeric_limits<qint64>::max())
|
||||
i64 = u64;
|
||||
else
|
||||
setStatus(ReadCorruptData);
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -58,6 +58,15 @@ private:
|
||||
Status q_status;
|
||||
|
||||
MsgPackStream &operator<<(const char *str); // use QStringLiteral instead
|
||||
|
||||
bool unpack_upto_quint8(quint8 &u8, quint8 *p);
|
||||
bool unpack_upto_quint16(quint16 &u16, quint8 *p);
|
||||
bool unpack_upto_quint32(quint32 &u32, quint8 *p);
|
||||
bool unpack_upto_quint64(quint64 &u64, quint8 *p);
|
||||
bool unpack_upto_qint8(qint8 &i8, quint8 *p);
|
||||
bool unpack_upto_qint16(qint16 &i16, quint8 *p);
|
||||
bool unpack_upto_qint32(qint32 &i32, quint8 *p);
|
||||
bool unpack_upto_qint64(qint64 &i64, quint8 *p);
|
||||
};
|
||||
|
||||
#endif // STREAM_H
|
||||
|
@@ -8,7 +8,7 @@ if (Qt5Core_FOUND)
|
||||
set(TEST_LIBRARIES ${Qt5Test_LIBRARIES})
|
||||
endif ()
|
||||
|
||||
set(TEST_SUBDIRS pack unpack mixed qttypes)
|
||||
set(TEST_SUBDIRS pack unpack mixed qttypes stream)
|
||||
|
||||
foreach(subdir ${TEST_SUBDIRS})
|
||||
add_subdirectory(${subdir})
|
||||
|
@@ -66,17 +66,15 @@ private:
|
||||
|
||||
Q_DECLARE_METATYPE(CustomType)
|
||||
|
||||
quint32 pack_custom_type(const QVariant &variant, QByteArray &data, bool write)
|
||||
QByteArray pack_custom_type(const QVariant &variant)
|
||||
{
|
||||
CustomType ct = variant.value<CustomType>();
|
||||
if (write) {
|
||||
data.resize(ct.size());
|
||||
quint8 *p = (quint8 *)data.data();
|
||||
for (int i = 0; i < ct.size(); ++i)
|
||||
p[i] = 7;
|
||||
}
|
||||
|
||||
return ct.size();
|
||||
QByteArray data;
|
||||
data.resize(ct.size());
|
||||
quint8 *p = (quint8 *)data.data();
|
||||
for (int i = 0; i < ct.size(); ++i)
|
||||
p[i] = 7;
|
||||
return data;
|
||||
}
|
||||
|
||||
QVariant unpack_custom_type(const QByteArray &data)
|
||||
|
24
tests/stream/CMakeLists.txt
Normal file
24
tests/stream/CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
set(QT_USE_QTTEST TRUE)
|
||||
|
||||
if (NOT Qt5Core_FOUND)
|
||||
include( ${QT_USE_FILE} )
|
||||
endif()
|
||||
|
||||
include(AddFileDependencies)
|
||||
|
||||
include_directories(../../src ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(UNIT_TESTS stream_test)
|
||||
|
||||
foreach(test ${UNIT_TESTS})
|
||||
message(status "Building ${test}")
|
||||
add_executable(${test} ${test}.cpp)
|
||||
|
||||
target_link_libraries(${test}
|
||||
${QT_LIBRARIES}
|
||||
${TEST_LIBRARIES}
|
||||
qmsgpack
|
||||
)
|
||||
|
||||
add_test(${test} ${test})
|
||||
endforeach()
|
141
tests/stream/stream_test.cpp
Normal file
141
tests/stream/stream_test.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
#include <QString>
|
||||
#include <QtTest>
|
||||
#include <QDebug>
|
||||
#include <stream.h>
|
||||
#include <msgpack.h>
|
||||
#include <limits>
|
||||
|
||||
class StreamTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void test_unpack_integers();
|
||||
void test_pack_integers();
|
||||
|
||||
};
|
||||
|
||||
void StreamTest::test_unpack_integers()
|
||||
{
|
||||
QByteArray ints = QByteArray::fromBase64("AH//4cyAzP/Q39CAzQEAzf//0f9/0YAAz"
|
||||
"gABAADO/////9L//3//0oAAAADPAAAAAQ"
|
||||
"AAAADP///////////T/////3/////TgAA"
|
||||
"AAAAAAAA=");
|
||||
MsgPackStream stream(ints);
|
||||
quint8 u8;
|
||||
quint16 u16;
|
||||
quint32 u32;
|
||||
quint64 u64;
|
||||
qint8 i8;
|
||||
qint16 i16;
|
||||
qint32 i32;
|
||||
qint64 i64;
|
||||
|
||||
stream >> u8;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(u8 == 0);
|
||||
stream >> u8;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(u8 == 127);
|
||||
stream >> i8;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(i8 == -1);
|
||||
stream >> i8;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(i8 == -31);
|
||||
stream >> u8;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(u8 == 128);
|
||||
stream >> u8;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(u8 == 255);
|
||||
stream >> i8;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(i8 == -33);
|
||||
stream >> i8;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(i8 == -128);
|
||||
stream >> u16;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(u16 == 256);
|
||||
stream >> u32;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(u32 == 65535);
|
||||
stream >> i16;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(i16 == -129);
|
||||
stream >> i16;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(i16 == -32768);
|
||||
stream >> u32;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(u32 == 65536);
|
||||
stream >> u32;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(u32 == 4294967295);
|
||||
stream >> i32;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(i32 == -32769);
|
||||
stream >> i32;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(i32 == -2147483648);
|
||||
stream >> u64;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(u64 == 4294967296);
|
||||
stream >> u64;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(u64 == std::numeric_limits<quint64>::max());
|
||||
stream >> i64;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(i64 == -2147483649);
|
||||
stream >> i64;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
QVERIFY(i64 == std::numeric_limits<qint64>::min());
|
||||
}
|
||||
|
||||
void StreamTest::test_pack_integers()
|
||||
{
|
||||
QByteArray packed;
|
||||
MsgPackStream stream(&packed, QIODevice::WriteOnly);
|
||||
stream << 0 << 127 << -1 << -31 << 128 << 255 << -33 << -128 << 256;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
stream << 65535 << -129 << -32768 << 65536;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
stream << (quint32)4294967295 << -32769 << (qint32)-2147483648;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
stream << (quint64)4294967296;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
stream << std::numeric_limits<quint64>::max();
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
stream << (qint64)-2147483649;
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
stream << std::numeric_limits<qint64>::min();
|
||||
QVERIFY(stream.status() == MsgPackStream::Ok);
|
||||
|
||||
QVariantList l = MsgPack::unpack(packed).toList();
|
||||
QVERIFY(l[0].toInt() == 0);
|
||||
QVERIFY(l[1].toInt() == 127);
|
||||
QVERIFY(l[2].toInt() == -1);
|
||||
QVERIFY(l[3].toInt() == -31);
|
||||
QVERIFY(l[4].toInt() == 128);
|
||||
QVERIFY(l[5].toInt() == 255);
|
||||
QVERIFY(l[6].toInt() == -33);
|
||||
QVERIFY(l[7].toInt() == -128);
|
||||
QVERIFY(l[8].toInt() == 256);
|
||||
QVERIFY(l[9].toInt() == 65535);
|
||||
QVERIFY(l[10].toInt() == -129);
|
||||
QVERIFY(l[11].toInt() == -32768);
|
||||
QVERIFY(l[12].toInt() == 65536);
|
||||
QVERIFY(l[13].toUInt() == 4294967295);
|
||||
QVERIFY(l[14].toInt() == -32769);
|
||||
QVERIFY(l[15].toInt() == -2147483648);
|
||||
QVERIFY(l[16].toLongLong() == 4294967296);
|
||||
QVERIFY(l[17].toULongLong() == std::numeric_limits<quint64>::max());
|
||||
QVERIFY(l[18].toLongLong() == -2147483649);
|
||||
QVERIFY(l[19].toLongLong() == std::numeric_limits<qint64>::min());
|
||||
}
|
||||
|
||||
|
||||
QTEST_APPLESS_MAIN(StreamTest)
|
||||
|
||||
#include "stream_test.moc"
|
Reference in New Issue
Block a user