diff --git a/main.cpp b/main.cpp index 34a22ed..848873e 100644 --- a/main.cpp +++ b/main.cpp @@ -16,6 +16,8 @@ int main(int argc, char *argv[]) { + Q_UNUSED(argc) + Q_UNUSED(argv) //QCoreApplication a(argc, argv); // qDebug() << "MsgPack"; @@ -24,10 +26,16 @@ int main(int argc, char *argv[]) QVariantList l; - l << "abcdefhijkabcdefhijkabcdefhijk12"; - QByteArray arr = MsgPack::pack(l); + QVariantMap map; + map["key"] = "val"; + map["key2"] = 123; + map["key3"] = 1.2; + l << map; + qDebug() << l[0].type(); + QByteArray arr = MsgPack::pack(map); qDebug() << arr.toBase64(); + return 0; //return a.exec(); } diff --git a/msgpack-qt.pro b/msgpack-qt.pro index 80b729c..c35a340 100644 --- a/msgpack-qt.pro +++ b/msgpack-qt.pro @@ -24,4 +24,5 @@ HEADERS += \ msgpack.h \ private/pack_p.h \ private/unpack_p.h \ - private/sysdep.h + private/sysdep.h \ + msgpack_common.h diff --git a/msgpack.h b/msgpack.h index bfa7cc2..ee86f8a 100644 --- a/msgpack.h +++ b/msgpack.h @@ -2,11 +2,14 @@ #define MSGPACK_H #include #include +#include "msgpack_common.h" namespace MsgPack { QVariant unpack(const QByteArray &data); + QByteArray pack(const QVariant &variant); + bool registerPacker(QMetaType::Type qType, qint8 msgpackType, pack_user_f packer); } #endif // MSGPACK_H diff --git a/msgpack_common.h b/msgpack_common.h new file mode 100644 index 0000000..a390b05 --- /dev/null +++ b/msgpack_common.h @@ -0,0 +1,10 @@ +#ifndef COMMON_H +#define COMMON_H + +#include + +namespace MsgPack { +typedef quint8 * (pack_user_f)(const QVariant &t, quint8 *p, bool wr); +} + +#endif // COMMON_H diff --git a/private/pack_p.cpp b/private/pack_p.cpp index 953da9c..c5eb91d 100644 --- a/private/pack_p.cpp +++ b/private/pack_p.cpp @@ -1,41 +1,235 @@ #include "pack_p.h" +#include "private/sysdep.h" - - -quint8 *MsgPackPrivate::pack(const QVariant &v, quint8 *p, bool sp) +quint8 *MsgPackPrivate::pack(const QVariant &v, quint8 *p, bool wr) { QMetaType::Type t = (QMetaType::Type)v.type(); if (t == QMetaType::Int) - p = pack_int(v, p, sp); + p = pack_int(v.toInt(), p, wr); + else if (t == QMetaType::UInt) + p = pack_uint(v.toInt(), p, wr); else if (t == QMetaType::Bool) - p = pack_bool(v, p, sp); + p = pack_bool(v, p, wr); + else if (t == QMetaType::QString) + p = pack_string(v.toString(), p, wr); else if (t == QMetaType::QVariantList) - p = pack_list(v, p, sp); + p = pack_list(v.toList(), p, wr); + else if (t == QMetaType::LongLong) + p = pack_longlong(v.toLongLong(), p, wr); + else if (t == QMetaType::ULongLong) + p = pack_ulonglong(v.toULongLong(), p, wr); + else if (t == QMetaType::Double) + p = pack_double(v.toDouble(), p, wr); + else if (t == QMetaType::QByteArray) + p = pack_array(v.toByteArray(), p, wr); + else if (t == QMetaType::QVariantMap) + p = pack_map(v.toMap(), p, wr); + return p; } -quint8 *MsgPackPrivate::pack_int(const QVariant &v, quint8 *p, bool sp) +quint8 *MsgPackPrivate::pack_int(qint32 i, quint8 *p, bool wr) { + if (i >= -32 && i <= 127) { + qint32 val = _msgpack_be32(i); + if (wr) *p = *( (quint8 *)&val + 3 ); + p++; + } else if (i >= -128 && i <= 255) { + if (wr) *p = i > 0 ? 0xcc : 0xd0; + p++; + if (wr) *p = i; + p++; + } else if (i >= -32768 && i <= 65535) { + if (wr) *p = i > 0 ? 0xcd : 0xd1; + p++; + if (wr) _msgpack_store16(p, i); + p += 2; + } else { + if (wr) *p = i > 0 ? 0xce : 0xd2; + p++; + if (wr) _msgpack_store32(p, i); + p += 4; + } + return p; } - -quint8 *MsgPackPrivate::pack_bool(const QVariant &v, quint8 *p, bool sp) +quint8 *MsgPackPrivate::pack_uint(quint32 i, quint8 *p, bool wr) { - if (!sp) + if (i <= 127) { + qint32 val = _msgpack_be32(i); + if (wr) *p = *( (quint8 *)&val + 3 ); + p++; + } else if (i <= 255) { + if (wr) *p = 0xcc; + p++; + if (wr) *p = i; + p++; + } else if (i <= 65535) { + if (wr) *p = 0xcd; + p++; + if (wr) _msgpack_store16(p, i); + p += 2; + } else { + if (wr) *p = 0xce; + p++; + if (wr) _msgpack_store32(p, i); + p += 4; + } + + return p; +} + +quint8 *MsgPackPrivate::pack_longlong(qint64 i, quint8 *p, bool wr) +{ + if (i >= -2147483648 && i <= 2147483647) + return p = pack_int(i, p, wr); + if (wr) *p = 0xd3; + p++; + if (wr) _msgpack_store64(p, i); + return p += 8; +} + +quint8 *MsgPackPrivate::pack_ulonglong(quint64 i, quint8 *p, bool wr) +{ + if (i <= 4294967295) + return pack_uint(i, p, wr); + if (wr) *p = 0xcf; + p++; + if (wr) _msgpack_store64(p, i); + return p += 8; +} + +quint8 *MsgPackPrivate::pack_bool(const QVariant &v, quint8 *p, bool wr) +{ + if (wr) *p = v.toBool() ? 0xc3 : 0xc2; return p + 1; } - -quint8 *MsgPackPrivate::pack_list(const QVariant &v, quint8 *p, bool sp) +quint8 *MsgPackPrivate::pack_list(const QVariantList &list, quint8 *p, bool wr) { - QVariantList list = v.toList(); - //pack_int(...) - if (!sp) - *p = 0x92; // 2el - p++; - foreach (QVariant item, v.toList()) - p = pack(item, p, sp); + int len = list.length(); + if (len <= 15) { + if (wr) *p = 0x90 | len; + p++; + } else { + if (len <= 65535) { + if (wr) *p = 0xdc; + p++; + _msgpack_store16(p, len); + p += 2; + } else { + if (wr) *p = 0xdd; + p++; + _msgpack_store32(p, len); + p += 4; + } + } + foreach (QVariant item, list) + p = pack(item, p, wr); + return p; +} + +quint8 *MsgPackPrivate::pack_string(const QString &str, quint8 *p, bool wr) +{ + int len = str.length(); + if (len <= 31) { + if (wr) *p = 0xa0 | len; + p++; + } else if (len <= 255) { + if (wr) *p = 0xd9; + p++; + if (wr) *p = len; + p++; + } else if (len <= 65535) { + if (wr) *p = 0xda; + p++; + if (wr) _msgpack_store16(p, len); + p += 2; + } else { + if (wr) *p = 0xdb; + p++; + if (wr) _msgpack_store32(p, len); + p += 4; + } + if (wr) memcpy(p, str.toUtf8().data(), len); + p += len; + + return p; +} + +quint8 *MsgPackPrivate::pack_double(double i, quint8 *p, bool wr) +{ + if (wr) *p = 0xcb; + p++; + if (wr) { + quint8 *d = (quint8 *)&i; +#ifdef __LITTLE_ENDIAN__ + for (int i = 0; i < 8; ++i) + *(p + 7 - i) = *(d + i); +#else + for (int i = 0; i < 8; ++i) + *(p + i) = *(d + i); +#endif + } + return p += 8; +} + +quint8 *MsgPackPrivate::pack_array(const QByteArray &arr, quint8 *p, bool wr) +{ + int len = arr.length(); + if (len <= 255) { + if (wr) *p = 0xc4; + p++; + if (wr) *p = len; + p++; + } else if (len <= 65535) { + if (wr) *p = 0xc5; + p++; + if (wr) _msgpack_store16(p, len); + p += 2; + } else { + if (wr) *p = 0xc6; + p++; + if (wr) _msgpack_store32(p, len); + p += 4; + } + if (wr) memcpy(p, arr.data(), len); + p += len; + + return p; +} + + +quint8 *MsgPackPrivate::pack_map(const QVariantMap &map, quint8 *p, bool wr) +{ + QMapIterator it(map); + int len = 0; + while (it.hasNext()) { + it.next(); + len++; + } + if (len <= 15) { + if (wr) *p = 0x80 | len; + p++; + } else if (len <= 65535) { + if (wr) *p = 0xde; + p++; + if (wr) _msgpack_store16(p, len); + p += 2; + } else { + if (wr) *p = 0xdf; + p++; + if (wr) _msgpack_store32(p, len); + p += 4; + } + + it.toFront(); + while (it.hasNext()) { + it.next(); + p = pack(it.key(), p, wr); + p = pack(it.value(), p, wr); + } return p; } diff --git a/private/pack_p.h b/private/pack_p.h index 392d4b3..9330ef6 100644 --- a/private/pack_p.h +++ b/private/pack_p.h @@ -1,18 +1,31 @@ #ifndef PACK_P_H #define PACK_P_H #include +#include "../msgpack_common.h" namespace MsgPackPrivate { -/* if sp (size probe) == true, packer just moves pointer forward +/* if wr (write) == false, packer just moves pointer forward * */ +QHash user_packers; + + +quint8 * pack(const QVariant &v, quint8 *p, bool wr); + +quint8 * pack_int(qint32 i, quint8 *p, bool wr); +quint8 * pack_uint(quint32 i, quint8 *p, bool wr); +quint8 * pack_longlong(qint64 i, quint8 *p, bool wr); +quint8 * pack_ulonglong(quint64 i, quint8 *p, bool wr); + +quint8 * pack_bool(const QVariant &v, quint8 *p, bool wr); +quint8 * pack_list(const QVariantList &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_array(const QByteArray &arr, quint8 *p, bool wr); +quint8 * pack_map(const QVariantMap &map, quint8 *p, bool wr); -quint8 * pack(const QVariant &v, quint8 *p, bool sp); -quint8 * pack_int(const QVariant &v, quint8 *p, bool sp); -quint8 * pack_bool(const QVariant &v, quint8 *p, bool sp); -quint8 * pack_list(const QVariant &v, quint8 *p, bool sp); } diff --git a/private/sysdep.h b/private/sysdep.h index 8f08216..25704f1 100644 --- a/private/sysdep.h +++ b/private/sysdep.h @@ -17,51 +17,9 @@ */ #ifndef MSGPACK_SYSDEP_H__ #define MSGPACK_SYSDEP_H__ +#include -#include -#include -#if defined(_MSC_VER) && _MSC_VER < 1600 -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -#elif defined(_MSC_VER) // && _MSC_VER >= 1600 -#include -#else -#include -#include -#endif - -#ifdef _WIN32 -#define _msgpack_atomic_counter_header -typedef long _msgpack_atomic_counter_t; -#define _msgpack_sync_decr_and_fetch(ptr) InterlockedDecrement(ptr) -#define _msgpack_sync_incr_and_fetch(ptr) InterlockedIncrement(ptr) -#elif defined(__GNUC__) && ((__GNUC__*10 + __GNUC_MINOR__) < 41) -#define _msgpack_atomic_counter_header "gcc_atomic.h" -#else -typedef unsigned int _msgpack_atomic_counter_t; -#define _msgpack_sync_decr_and_fetch(ptr) __sync_sub_and_fetch(ptr, 1) -#define _msgpack_sync_incr_and_fetch(ptr) __sync_add_and_fetch(ptr, 1) -#endif - -#ifdef _WIN32 - -#ifdef __cplusplus -/* numeric_limits::min,max */ -#ifdef max -#undef max -#endif -#ifdef min -#undef min -#endif -#endif - -#else +#ifndef _WIN32 #include /* __BYTE_ORDER */ #endif @@ -85,8 +43,8 @@ typedef unsigned int _msgpack_atomic_counter_t; # define _msgpack_be16(x) ((uint16_t)_byteswap_ushort((unsigned short)x)) # else # define _msgpack_be16(x) ( \ - ((((uint16_t)x) << 8) ) | \ - ((((uint16_t)x) >> 8) ) ) + ((((quint16)x) << 8) ) | \ + ((((quint16)x) >> 8) ) ) # endif #else # define _msgpack_be16(x) ntohs(x) @@ -99,10 +57,10 @@ typedef unsigned int _msgpack_atomic_counter_t; # define _msgpack_be32(x) ((uint32_t)_byteswap_ulong((unsigned long)x)) # else # define _msgpack_be32(x) \ - ( ((((uint32_t)x) << 24) ) | \ - ((((uint32_t)x) << 8) & 0x00ff0000U ) | \ - ((((uint32_t)x) >> 8) & 0x0000ff00U ) | \ - ((((uint32_t)x) >> 24) ) ) + ( ((((quint32)x) << 24) ) | \ + ((((quint32)x) << 8) & 0x00ff0000U ) | \ + ((((quint32)x) >> 8) & 0x0000ff00U ) | \ + ((((quint32)x) >> 24) ) ) # endif #else # define _msgpack_be32(x) ntohl(x) @@ -116,35 +74,35 @@ typedef unsigned int _msgpack_atomic_counter_t; # define _msgpack_be64(x) __DARWIN_OSSwapInt64(x) #else #define _msgpack_be64(x) \ - ( ((((uint64_t)x) << 56) ) | \ - ((((uint64_t)x) << 40) & 0x00ff000000000000ULL ) | \ - ((((uint64_t)x) << 24) & 0x0000ff0000000000ULL ) | \ - ((((uint64_t)x) << 8) & 0x000000ff00000000ULL ) | \ - ((((uint64_t)x) >> 8) & 0x00000000ff000000ULL ) | \ - ((((uint64_t)x) >> 24) & 0x0000000000ff0000ULL ) | \ - ((((uint64_t)x) >> 40) & 0x000000000000ff00ULL ) | \ - ((((uint64_t)x) >> 56) ) ) + ( ((((quint64)x) << 56) ) | \ + ((((quint64)x) << 40) & 0x00ff000000000000ULL ) | \ + ((((quint64)x) << 24) & 0x0000ff0000000000ULL ) | \ + ((((quint64)x) << 8) & 0x000000ff00000000ULL ) | \ + ((((quint64)x) >> 8) & 0x00000000ff000000ULL ) | \ + ((((quint64)x) >> 24) & 0x0000000000ff0000ULL ) | \ + ((((quint64)x) >> 40) & 0x000000000000ff00ULL ) | \ + ((((quint64)x) >> 56) ) ) #endif #define _msgpack_load16(cast, from) ((cast)( \ - (((uint16_t)((uint8_t*)(from))[0]) << 8) | \ - (((uint16_t)((uint8_t*)(from))[1]) ) )) + (((quint16)((quint8*)(from))[0]) << 8) | \ + (((quint16)((quint8*)(from))[1]) ) )) #define _msgpack_load32(cast, from) ((cast)( \ - (((uint32_t)((uint8_t*)(from))[0]) << 24) | \ - (((uint32_t)((uint8_t*)(from))[1]) << 16) | \ - (((uint32_t)((uint8_t*)(from))[2]) << 8) | \ - (((uint32_t)((uint8_t*)(from))[3]) ) )) + (((quint32)((quint8*)(from))[0]) << 24) | \ + (((quint32)((quint8*)(from))[1]) << 16) | \ + (((quint32)((quint8*)(from))[2]) << 8) | \ + (((quint32)((quint8*)(from))[3]) ) )) #define _msgpack_load64(cast, from) ((cast)( \ - (((uint64_t)((uint8_t*)(from))[0]) << 56) | \ - (((uint64_t)((uint8_t*)(from))[1]) << 48) | \ - (((uint64_t)((uint8_t*)(from))[2]) << 40) | \ - (((uint64_t)((uint8_t*)(from))[3]) << 32) | \ - (((uint64_t)((uint8_t*)(from))[4]) << 24) | \ - (((uint64_t)((uint8_t*)(from))[5]) << 16) | \ - (((uint64_t)((uint8_t*)(from))[6]) << 8) | \ - (((uint64_t)((uint8_t*)(from))[7]) ) )) + (((quint64)((quint8*)(from))[0]) << 56) | \ + (((quint64)((quint8*)(from))[1]) << 48) | \ + (((quint64)((quint8*)(from))[2]) << 40) | \ + (((quint64)((quint8*)(from))[3]) << 32) | \ + (((quint64)((quint8*)(from))[4]) << 24) | \ + (((quint64)((quint8*)(from))[5]) << 16) | \ + (((quint64)((quint8*)(from))[6]) << 8) | \ + (((quint64)((quint8*)(from))[7]) ) )) #else @@ -153,33 +111,33 @@ typedef unsigned int _msgpack_atomic_counter_t; #define _msgpack_be64(x) (x) #define _msgpack_load16(cast, from) ((cast)( \ - (((uint16_t)((uint8_t*)from)[0]) << 8) | \ - (((uint16_t)((uint8_t*)from)[1]) ) )) + (((quint16)((quint8*)from)[0]) << 8) | \ + (((quint16)((quint8*)from)[1]) ) )) #define _msgpack_load32(cast, from) ((cast)( \ - (((uint32_t)((uint8_t*)from)[0]) << 24) | \ - (((uint32_t)((uint8_t*)from)[1]) << 16) | \ - (((uint32_t)((uint8_t*)from)[2]) << 8) | \ - (((uint32_t)((uint8_t*)from)[3]) ) )) + (((quint32)((quint8*)from)[0]) << 24) | \ + (((quint32)((quint8*)from)[1]) << 16) | \ + (((quint32)((quint8*)from)[2]) << 8) | \ + (((quint32)((quint8*)from)[3]) ) )) #define _msgpack_load64(cast, from) ((cast)( \ - (((uint64_t)((uint8_t*)from)[0]) << 56) | \ - (((uint64_t)((uint8_t*)from)[1]) << 48) | \ - (((uint64_t)((uint8_t*)from)[2]) << 40) | \ - (((uint64_t)((uint8_t*)from)[3]) << 32) | \ - (((uint64_t)((uint8_t*)from)[4]) << 24) | \ - (((uint64_t)((uint8_t*)from)[5]) << 16) | \ - (((uint64_t)((uint8_t*)from)[6]) << 8) | \ - (((uint64_t)((uint8_t*)from)[7]) ) )) + (((quint64)((quint8*)from)[0]) << 56) | \ + (((quint64)((quint8*)from)[1]) << 48) | \ + (((quint64)((quint8*)from)[2]) << 40) | \ + (((quint64)((quint8*)from)[3]) << 32) | \ + (((quint64)((quint8*)from)[4]) << 24) | \ + (((quint64)((quint8*)from)[5]) << 16) | \ + (((quint64)((quint8*)from)[6]) << 8) | \ + (((quint64)((quint8*)from)[7]) ) )) #endif #define _msgpack_store16(to, num) \ - do { uint16_t val = _msgpack_be16(num); memcpy(to, &val, 2); } while(0) + do { quint16 val = _msgpack_be16(num); memcpy(to, &val, 2); } while(0) #define _msgpack_store32(to, num) \ - do { uint32_t val = _msgpack_be32(num); memcpy(to, &val, 4); } while(0) + do { quint32 val = _msgpack_be32(num); memcpy(to, &val, 4); } while(0) #define _msgpack_store64(to, num) \ - do { uint64_t val = _msgpack_be64(num); memcpy(to, &val, 8); } while(0) + do { quint64 val = _msgpack_be64(num); memcpy(to, &val, 8); } while(0) /* #define _msgpack_load16(cast, from) \ @@ -190,19 +148,5 @@ typedef unsigned int _msgpack_atomic_counter_t; ({ cast val; memcpy(&val, (char*)from, 8); _msgpack_be64(val); }) */ - -#if !defined(__cplusplus) && defined(_MSC_VER) -#if !defined(FALSE) -#define FALSE (0) -#endif -#if !defined(TRUE) -#define TRUE (!FALSE) -#endif -#define bool int -#define true TRUE -#define false FALSE -#define inline __inline -#endif - #endif /* msgpack/sysdep.h */ diff --git a/qmsgpack.pro.user b/qmsgpack.pro.user new file mode 100644 index 0000000..ec1a0c9 --- /dev/null +++ b/qmsgpack.pro.user @@ -0,0 +1,263 @@ + + + + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.3 GCC 64bit + Desktop Qt 5.3 GCC 64bit + qt.53.gcc_64_kit + 0 + 0 + 0 + + /home/roman/build/build-qmsgpack-Desktop_Qt_5_3_GCC_64bit-Debug + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + true + Сборка + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Сборка + + ProjectExplorer.BuildSteps.Build + + + + true + Сборка + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Очистка + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Отладка + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + /home/roman/build/build-qmsgpack-Desktop_Qt_5_3_GCC_64bit-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + true + Сборка + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Сборка + + ProjectExplorer.BuildSteps.Build + + + + true + Сборка + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Очистка + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Выпуск + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 2 + + + 0 + Установка + + ProjectExplorer.BuildSteps.Deploy + + 1 + Локальная установка + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + qmsgpack + + Qt4ProjectManager.Qt4RunConfiguration:/home/roman/git/msgpack-qt/qmsgpack.pro + + qmsgpack.pro + false + false + + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.EnvironmentId + {478d7604-9791-49cc-a5a5-2eb4eeaa05bd} + + + ProjectExplorer.Project.Updater.FileVersion + 15 + +