diff --git a/.gitignore b/.gitignore index ab6317a..c5ec2ea 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ build lib Makefile *.autosave +bin/ diff --git a/src/private/pack_p.cpp b/src/private/pack_p.cpp index 757327c..268fc06 100644 --- a/src/private/pack_p.cpp +++ b/src/private/pack_p.cpp @@ -216,7 +216,7 @@ quint8 *MsgPackPrivate::pack_float(float f, quint8 *p, bool wr) if (wr) *p = 0xca; p++; if (wr) { - quint8 *d = (quint8 *)&i; + quint8 *d = (quint8 *)&f; #ifdef __LITTLE_ENDIAN__ for (int i = 0; i < 4; ++i) *(p + 3 - i) = *(d + i); @@ -225,10 +225,9 @@ quint8 *MsgPackPrivate::pack_float(float f, quint8 *p, bool wr) *(p + i) = *(d + i); #endif } - return p + 8; + return p + 4; } - quint8 *MsgPackPrivate::pack_double(double i, quint8 *p, bool wr) { if (wr) *p = 0xcb; @@ -246,9 +245,8 @@ quint8 *MsgPackPrivate::pack_double(double i, quint8 *p, bool wr) return p + 8; } -quint8 *MsgPackPrivate::pack_bin(const QByteArray &arr, quint8 *p, bool wr) +quint8 *MsgPackPrivate::pack_bin_header(quint32 len, quint8 *p, bool wr) { - int len = arr.length(); if (len <= std::numeric_limits::max()) { if (wr) *p = compatibilityMode ? 0xd9 : 0xc4; p++; @@ -265,9 +263,15 @@ quint8 *MsgPackPrivate::pack_bin(const QByteArray &arr, quint8 *p, bool wr) if (wr) _msgpack_store32(p, len); p += 4; } + return p; +} + +quint8 *MsgPackPrivate::pack_bin(const QByteArray &arr, quint8 *p, bool wr) +{ + quint32 len = arr.length(); + p = pack_bin_header(len, p, wr); if (wr) memcpy(p, arr.data(), len); p += len; - return p; } diff --git a/src/private/pack_p.h b/src/private/pack_p.h index e8a55bf..db29911 100644 --- a/src/private/pack_p.h +++ b/src/private/pack_p.h @@ -40,6 +40,7 @@ quint8 * pack_string_raw(const char *str, quint32 len, quint8 *p, bool wr); quint8 * pack_string(const QString &str, quint8 *p, bool wr); quint8 * pack_float(float f, quint8 *p, bool wr); quint8 * pack_double(double i, quint8 *p, bool wr); +quint8 * pack_bin_header(quint32 len, quint8 *p, bool wr); quint8 * pack_bin(const QByteArray &arr, quint8 *p, bool wr); quint8 * pack_map(const QVariantMap &map, quint8 *p, bool wr, QVector &user_data); quint8 * pack_user(const QVariant &v, quint8 *p, bool wr, QVector &user_data); diff --git a/src/stream.cpp b/src/stream.cpp index 42baf83..81a683d 100644 --- a/src/stream.cpp +++ b/src/stream.cpp @@ -209,7 +209,7 @@ MsgPackStream &MsgPackStream::operator>>(float &f) CHECK_STREAM_PRECOND(*this); quint8 *fp = (quint8 *)&f; quint8 p[5]; - if (dev->read((char *)&p, 1) != 1) { + if (dev->read((char *)p, 1) != 1) { setStatus(ReadPastEnd); return *this; } @@ -217,6 +217,10 @@ MsgPackStream &MsgPackStream::operator>>(float &f) setStatus(ReadCorruptData); return *this; } + if (dev->read((char *)p + 1, 4) != 4) { + setStatus(ReadPastEnd); + return *this; + } #ifdef __LITTLE_ENDIAN__ for (int i = 0; i < 4; ++i) *(fp + 3 - i) = *(p + i + 1); @@ -230,9 +234,9 @@ MsgPackStream &MsgPackStream::operator>>(float &f) MsgPackStream &MsgPackStream::operator>>(double &d) { CHECK_STREAM_PRECOND(*this); - quint8 *fp = (quint8 *)&f; + quint8 *fp = (quint8 *)&d; quint8 p[9]; - if (dev->read((char *)&p, 1) != 1) { + if (dev->read((char *)p, 1) != 1) { setStatus(ReadPastEnd); return *this; } @@ -240,6 +244,10 @@ MsgPackStream &MsgPackStream::operator>>(double &d) setStatus(ReadCorruptData); return *this; } + if (dev->read((char *)p + 1, 8) != 8) { + setStatus(ReadPastEnd); + return *this; + } #ifdef __LITTLE_ENDIAN__ for (int i = 0; i < 8; ++i) *(fp + 7 - i) = *(p + i + 1); @@ -287,17 +295,39 @@ MsgPackStream &MsgPackStream::operator>>(QString &str) MsgPackStream &MsgPackStream::operator>>(QByteArray &array) { - -} - -MsgPackStream &MsgPackStream::operator>>(QVariantList &list) -{ - -} - -MsgPackStream &MsgPackStream::operator>>(QVariantMap &map) -{ - + 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; } MsgPackStream &MsgPackStream::operator<<(bool b) @@ -364,7 +394,7 @@ MsgPackStream &MsgPackStream::operator<<(double d) { CHECK_STREAM_WRITE_PRECOND(*this); quint8 p[9]; - quint8 sz = MsgPackPrivate::pack_float(d, p, true) - p; + quint8 sz = MsgPackPrivate::pack_double(d, p, true) - p; if (dev->write((char *)p, sz) != sz) setStatus(WriteFailed); return *this; @@ -399,17 +429,17 @@ MsgPackStream &MsgPackStream::operator<<(const char *str) MsgPackStream &MsgPackStream::operator<<(QByteArray array) { - -} - -MsgPackStream &MsgPackStream::operator<<(QVariantList list) -{ - -} - -MsgPackStream &MsgPackStream::operator<<(QVariantMap map) -{ - + 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; } bool MsgPackStream::unpack_upto_quint8(quint8 &u8, quint8 *p) diff --git a/src/stream.h b/src/stream.h index 545973d..d84f874 100644 --- a/src/stream.h +++ b/src/stream.h @@ -33,8 +33,6 @@ public: MsgPackStream &operator>>(double &d); MsgPackStream &operator>>(QString &str); MsgPackStream &operator>>(QByteArray &array); - MsgPackStream &operator>>(QVariantList &list); - MsgPackStream &operator>>(QVariantMap &map); MsgPackStream &operator<<(bool b); MsgPackStream &operator<<(quint32 u32); @@ -46,8 +44,6 @@ public: MsgPackStream &operator<<(QString str); MsgPackStream &operator<<(const char *str); MsgPackStream &operator<<(QByteArray array); - MsgPackStream &operator<<(QVariantList list); - MsgPackStream &operator<<(QVariantMap map); private: QIODevice *dev; @@ -64,4 +60,29 @@ private: bool unpack_upto_qint64(qint64 &i64, quint8 *p); }; +template +MsgPackStream& operator<<(MsgPackStream& s, const QList &list) +{ + s << (quint32)list.size(); + for (int i = 0; i < list.size(); ++i) + s << list[i]; + return s; +} + +template +MsgPackStream& operator>>(MsgPackStream& s, QList &list) +{ + list.clear(); + quint32 size; + s >> size; + for (quint32 i = 0; i < size; ++i) { + T t; + s >> t; + list.append(t); + if (s.atEnd()) + break; + } + return s; +} + #endif // STREAM_H diff --git a/tests/mixed/mixed_test.cpp b/tests/mixed/mixed_test.cpp index 2f9ea1b..0f17b8d 100644 --- a/tests/mixed/mixed_test.cpp +++ b/tests/mixed/mixed_test.cpp @@ -8,11 +8,85 @@ class MixedTest : public QObject Q_OBJECT private Q_SLOTS: + void test_float(); + void test_double(); void test_map(); void test_ext(); void test_mixed(); }; +void MixedTest::test_float() +{ + float f; + QByteArray packed; + + packed = MsgPack::pack(0.0f); + f = MsgPack::unpack(packed).toFloat(); + QVERIFY(f == 0.0f); + QVERIFY(packed.size() == 5); + + packed = MsgPack::pack(-0.0f); + f = MsgPack::unpack(packed).toFloat(); + QVERIFY(f == -0.0f); + QVERIFY(packed.size() == 5); + + packed = MsgPack::pack(1.0f); + f = MsgPack::unpack(packed).toFloat(); + QVERIFY(f == 1.0f); + QVERIFY(packed.size() == 5); + + packed = MsgPack::pack(-1.0f); + f = MsgPack::unpack(packed).toFloat(); + QVERIFY(f == -1.0f); + QVERIFY(packed.size() == 5); + + packed = MsgPack::pack(32767.0f); + f = MsgPack::unpack(packed).toFloat(); + QVERIFY(f == 32767.0f); + QVERIFY(packed.size() == 5); + + packed = MsgPack::pack(-32767.0f); + f = MsgPack::unpack(packed).toFloat(); + QVERIFY(f == -32767.0f); + QVERIFY(packed.size() == 5); +} + +void MixedTest::test_double() +{ + double d; + QByteArray packed; + + packed = MsgPack::pack(0.0); + d = MsgPack::unpack(packed).toDouble(); + QVERIFY(d == 0.0); + QVERIFY(packed.size() == 9); + + packed = MsgPack::pack(-0.0); + d = MsgPack::unpack(packed).toDouble(); + QVERIFY(d == -0.0); + QVERIFY(packed.size() == 9); + + packed = MsgPack::pack(1.0); + d = MsgPack::unpack(packed).toDouble(); + QVERIFY(d == 1.0); + QVERIFY(packed.size() == 9); + + packed = MsgPack::pack(-1.0); + d = MsgPack::unpack(packed).toDouble(); + QVERIFY(d == -1.0); + QVERIFY(packed.size() == 9); + + packed = MsgPack::pack(32767.0); + d = MsgPack::unpack(packed).toDouble(); + QVERIFY(d == 32767.0); + QVERIFY(packed.size() == 9); + + packed = MsgPack::pack(-32767.0); + d = MsgPack::unpack(packed).toDouble(); + QVERIFY(d == -32767.0); + QVERIFY(packed.size() == 9); +} + void MixedTest::test_map() { QVariantMap map; diff --git a/tests/pack/pack_test.cpp b/tests/pack/pack_test.cpp index 8d01fc2..2bd6aea 100644 --- a/tests/pack/pack_test.cpp +++ b/tests/pack/pack_test.cpp @@ -271,7 +271,7 @@ void PackTest::test_bin() QVERIFY(p[2] == 0x00); QVERIFY(memcmp(p + 3, ba.data(), ba.size()) == 0); - ba = QByteArray(65536, 'r'); + ba = QByteArray(65536, 'x'); arr = MsgPack::pack(ba); QVERIFY(arr.size() == ba.size() + 5); p = (quint8 *)arr.data(); diff --git a/tests/stream/stream_test.cpp b/tests/stream/stream_test.cpp index 29662b3..f055a95 100644 --- a/tests/stream/stream_test.cpp +++ b/tests/stream/stream_test.cpp @@ -14,7 +14,9 @@ private Q_SLOTS: void test_pack_integers(); void test_unpack_string(); void test_pack_string(); - + void test_float(); + void test_double(); + void test_bin(); }; void StreamTest::test_unpack_integers() @@ -203,7 +205,107 @@ void StreamTest::test_pack_string() QVERIFY(l[4].isEmpty()); } +void StreamTest::test_float() +{ + QByteArray packed; + { + MsgPackStream stream(&packed, QIODevice::WriteOnly); + stream << -0.0f << 0.0f << -1.0f << 1.0f << -32767.0f << 32767.0f; + QVERIFY(packed.size() == 6 * 5); + QVERIFY(stream.status() == MsgPackStream::Ok); + } + + MsgPackStream stream(packed); + float f; + + stream >> f; + QVERIFY(f == -0.0f); + QVERIFY(stream.status() == MsgPackStream::Ok); + + stream >> f; + QVERIFY(f == 0.0f); + QVERIFY(stream.status() == MsgPackStream::Ok); + + stream >> f; + QVERIFY(f == -1.0f); + QVERIFY(stream.status() == MsgPackStream::Ok); + + stream >> f; + QVERIFY(f == 1.0f); + QVERIFY(stream.status() == MsgPackStream::Ok); + + stream >> f; + QVERIFY(f == -32767.0f); + QVERIFY(stream.status() == MsgPackStream::Ok); + + stream >> f; + QVERIFY(f == 32767.0f); + QVERIFY(stream.status() == MsgPackStream::Ok); +} + +void StreamTest::test_double() +{ + QByteArray packed; + { + MsgPackStream stream(&packed, QIODevice::WriteOnly); + stream << -0.0 << 0.0 << -1.0 << 1.0 << -32767.0 << 32767.0; + QVERIFY(packed.size() == 6 * 9); + QVERIFY(stream.status() == MsgPackStream::Ok); + } + + MsgPackStream stream(packed); + double d; + + stream >> d; + QVERIFY(d == -0.0); + QVERIFY(stream.status() == MsgPackStream::Ok); + + stream >> d; + QVERIFY(d == 0.0); + QVERIFY(stream.status() == MsgPackStream::Ok); + + stream >> d; + QVERIFY(d == -1.0); + QVERIFY(stream.status() == MsgPackStream::Ok); + + stream >> d; + QVERIFY(d == 1.0); + QVERIFY(stream.status() == MsgPackStream::Ok); + + stream >> d; + QVERIFY(d == -32767.0); + QVERIFY(stream.status() == MsgPackStream::Ok); + + stream >> d; + QVERIFY(d == 32767.0); + QVERIFY(stream.status() == MsgPackStream::Ok); +} + +void StreamTest::test_bin() +{ + QByteArray ba1("msgpack"), ba2(256, 'r'), ba3(65536, 'x'); + QByteArray packed; + { + MsgPackStream stream(&packed, QIODevice::WriteOnly); + stream << ba1 << ba2 << ba3; + } + QVERIFY(packed.size() == 7+2 + 256+3 + 65536+5); + + MsgPackStream stream(packed); + QByteArray ba; + + stream >> ba; + QVERIFY(ba == ba1); + QVERIFY(stream.status() == MsgPackStream::Ok); + + stream >> ba; + QVERIFY(ba == ba2); + QVERIFY(stream.status() == MsgPackStream::Ok); + + stream >> ba; + QVERIFY(ba == ba3); + QVERIFY(stream.status() == MsgPackStream::Ok); +} QTEST_APPLESS_MAIN(StreamTest) - #include "stream_test.moc"