From 98cf9ff8ee511679cf6d63b07c2b9a4509c4776f Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 18 Sep 2014 23:47:58 +0400 Subject: [PATCH] user type packing implemented --- .gitignore | 1 + main.cpp | 38 +++++++++++--------------- msgpack.cpp | 6 +++++ msgpack_common.h | 2 +- private/pack_p.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++++ private/pack_p.h | 10 ++++--- private/unpack_p.h | 3 --- 7 files changed, 97 insertions(+), 29 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..86a9657 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pro.user \ No newline at end of file diff --git a/main.cpp b/main.cpp index 848873e..c16c6b0 100644 --- a/main.cpp +++ b/main.cpp @@ -1,18 +1,19 @@ #include #include #include +#include +#include -#include - -//int is_big_endian(void) -//{ -// union { -// quint32 i; -// char c[4]; -// } bint = {0x01020304}; - -// return bint.c[0] == 1; -//} +quint32 packQPoint(const QVariant &variant, QByteArray &data, bool write) +{ + if (write) { + data.resize(8); + QDataStream out(&data, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_5_3); + out << variant.toPoint(); + } + return 8; +} int main(int argc, char *argv[]) { @@ -20,19 +21,12 @@ int main(int argc, char *argv[]) Q_UNUSED(argv) //QCoreApplication a(argc, argv); -// qDebug() << "MsgPack"; -// qDebug() << MsgPack::deserialize(QByteArray::fromHex("dc 00 33 c2 c3 c0 00 00 00 00 00 00 00 00 00 ff ff ff ff ff 7f 7f cc ff cd ff ff ce ff ff ff ff e0 e0 d1 ff 80 d2 ff ff 80 00 d3 ff ff ff ff 80 00 00 00 00 00 01 ff a1 61 a1 61 a1 61 a0 a0 a0 91 00 91 00 91 00 90 90 90 80 80 80 81 a1 61 61 81 a1 61 61 81 a1 61 61 91 90 91 91 a1 61")); - - + MsgPack::registerPacker(QMetaType::QPoint, 7, packQPoint); QVariantList l; - QVariantMap map; - map["key"] = "val"; - map["key2"] = 123; - map["key3"] = 1.2; - l << map; - qDebug() << l[0].type(); - QByteArray arr = MsgPack::pack(map); + + l << QPoint(1, 2); + QByteArray arr = MsgPack::pack(l); qDebug() << arr.toBase64(); diff --git a/msgpack.cpp b/msgpack.cpp index b1def6b..3dd0da1 100644 --- a/msgpack.cpp +++ b/msgpack.cpp @@ -26,3 +26,9 @@ QByteArray MsgPack::pack(const QVariant &variant) return arr; } + + +bool MsgPack::registerPacker(QMetaType::Type qType, qint8 msgpackType, MsgPack::pack_user_f packer) +{ + return MsgPackPrivate::register_packer(qType, msgpackType, packer); +} diff --git a/msgpack_common.h b/msgpack_common.h index a390b05..9e04189 100644 --- a/msgpack_common.h +++ b/msgpack_common.h @@ -4,7 +4,7 @@ #include namespace MsgPack { -typedef quint8 * (pack_user_f)(const QVariant &t, quint8 *p, bool wr); +typedef quint32 (*pack_user_f)(const QVariant &variant, QByteArray &data, bool write); } #endif // COMMON_H diff --git a/private/pack_p.cpp b/private/pack_p.cpp index c5eb91d..dc7d045 100644 --- a/private/pack_p.cpp +++ b/private/pack_p.cpp @@ -1,5 +1,8 @@ #include "pack_p.h" #include "private/sysdep.h" +#include + +QHash MsgPackPrivate::user_packers; quint8 *MsgPackPrivate::pack(const QVariant &v, quint8 *p, bool wr) { @@ -24,6 +27,12 @@ quint8 *MsgPackPrivate::pack(const QVariant &v, quint8 *p, bool wr) p = pack_array(v.toByteArray(), p, wr); else if (t == QMetaType::QVariantMap) p = pack_map(v.toMap(), p, wr); + else { + if (user_packers.contains(t)) + p = pack_user(v, p, wr); + else + qWarning() << "MsgPack::pack can't pack type:" << t; + } return p; } @@ -233,3 +242,60 @@ quint8 *MsgPackPrivate::pack_map(const QVariantMap &map, quint8 *p, bool wr) } return p; } + + +bool MsgPackPrivate::register_packer(QMetaType::Type q_type, qint8 msgpack_type, MsgPack::pack_user_f packer) +{ + if (user_packers.contains(q_type)) + return false; + packer_t p; + p.packer = packer; + p.type = msgpack_type; + user_packers.insert(q_type, p); + return true; +} + +quint8 *MsgPackPrivate::pack_user(const QVariant &v, quint8 *p, bool wr) +{ + QMetaType::Type t = (QMetaType::Type)v.type() == QMetaType::User ? + (QMetaType::Type)v.userType() : (QMetaType::Type)v.type(); + QByteArray data; + packer_t pt = user_packers[t]; + quint32 len = pt.packer(v, data, wr); + if (len == 1) { + if (wr) *p = 0xd4; + p++; + } else if (len == 2) { + if (wr) *p = 0xd5; + p++; + } else if (len == 4) { + if (wr) *p = 0xd6; + p++; + } else if (len == 8) { + if (wr) *p = 0xd7; + p++; + } else if (len == 16) { + if (wr) *p = 0xd8; + p++; + } else if (len <= 255) { + if (wr) *p = 0xc7; + p++; + if (wr) *p = len; + p++; + } else if (len <= 65535) { + if (wr) *p = 0xc8; + p++; + if (wr) _msgpack_store16(p, len); + p += 2; + } else { + if (wr) *p = 0xc9; + p++; + if (wr) _msgpack_store32(p, len); + p += 4; + } + if (wr) *p = pt.type; + p++; + if (wr) + memcpy(p, data.data(), len); + return p += len; +} diff --git a/private/pack_p.h b/private/pack_p.h index 9330ef6..bac2330 100644 --- a/private/pack_p.h +++ b/private/pack_p.h @@ -7,9 +7,12 @@ namespace MsgPackPrivate { /* if wr (write) == false, packer just moves pointer forward * */ - -QHash user_packers; - +typedef struct { + MsgPack::pack_user_f packer; + qint8 type; +} packer_t; +bool register_packer(QMetaType::Type q_type, qint8 msgpack_type, MsgPack::pack_user_f packer); +extern QHash user_packers; quint8 * pack(const QVariant &v, quint8 *p, bool wr); @@ -24,6 +27,7 @@ quint8 * pack_string(const QString &str, quint8 *p, bool wr); quint8 * pack_double(double i, quint8 *p, bool wr); quint8 * pack_array(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); diff --git a/private/unpack_p.h b/private/unpack_p.h index 6f58d18..5fb10c1 100644 --- a/private/unpack_p.h +++ b/private/unpack_p.h @@ -2,8 +2,6 @@ #define MSGPACK_P_H #include - - namespace MsgPackPrivate { /* unpack functions: @@ -26,7 +24,6 @@ quint32 unpack_uint8(quint8 *p); quint32 unpack_uint16(quint8 *p); quint32 unpack_uint32(quint8 *p); - QVariant unpack_positive_fixint(quint8 *p, quint32 &sz); QVariant unpack_negative_fixint(quint8 *p, quint32 &sz); QVariant unpack_fixmap(quint8 *p, quint32 &sz);