From fd5804719237b5d9731facfd6cbb3afb740f74ae Mon Sep 17 00:00:00 2001 From: romixlab Date: Mon, 22 Sep 2014 20:03:00 +0400 Subject: [PATCH] cmake files added, folder tree reorganized, pack test partially written --- .gitignore | 5 +- CMakeLists.txt | 74 ++++++ cmake_uninstall.cmake.in | 17 ++ src/CMakeLists.txt | 25 ++ src/main.cpp | 47 ++++ src/msgpack-qt.pro | 32 +++ src/msgpack.cpp | 40 +++ src/msgpack.h | 17 ++ src/msgpack_common.h | 18 ++ src/msgpack_export.h | 12 + src/private/pack_p.cpp | 307 +++++++++++++++++++++++ src/private/pack_p.h | 36 +++ src/private/sysdep.h | 152 ++++++++++++ src/private/unpack_p.cpp | 388 ++++++++++++++++++++++++++++++ src/private/unpack_p.h | 75 ++++++ test/pack/pack-test/pack-test.pro | 19 ++ test/pack/pack-test/tst_d.cpp | 26 ++ tests/CMakeLists.txt | 11 + tests/pack/CMakeLists.txt | 24 ++ tests/pack/pack-test.pro | 22 ++ tests/pack/pack_test.cpp | 198 +++++++++++++++ tests/pack/pack_test.cpp.autosave | 215 +++++++++++++++++ 22 files changed, 1759 insertions(+), 1 deletion(-) create mode 100644 CMakeLists.txt create mode 100644 cmake_uninstall.cmake.in create mode 100644 src/CMakeLists.txt create mode 100644 src/main.cpp create mode 100644 src/msgpack-qt.pro create mode 100644 src/msgpack.cpp create mode 100644 src/msgpack.h create mode 100644 src/msgpack_common.h create mode 100644 src/msgpack_export.h create mode 100644 src/private/pack_p.cpp create mode 100644 src/private/pack_p.h create mode 100644 src/private/sysdep.h create mode 100644 src/private/unpack_p.cpp create mode 100644 src/private/unpack_p.h create mode 100644 test/pack/pack-test/pack-test.pro create mode 100644 test/pack/pack-test/tst_d.cpp create mode 100644 tests/CMakeLists.txt create mode 100644 tests/pack/CMakeLists.txt create mode 100644 tests/pack/pack-test.pro create mode 100644 tests/pack/pack_test.cpp create mode 100644 tests/pack/pack_test.cpp.autosave diff --git a/.gitignore b/.gitignore index 86a9657..a2f6c2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -*.pro.user \ No newline at end of file +*.pro.user +build +lib +Makefile diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b439d94 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,74 @@ +project(qmsgpack) + +cmake_minimum_required(VERSION 2.8.8) + +set(CMAKE_INSTALL_NAME_DIR ${LIB_INSTALL_DIR}) + +# build type +if ("${CMAKE_BUILD_TYPE}" MATCHES "^Rel.*") + add_definitions("-DQT_NO_DEBUG_OUTPUT") +endif ("${CMAKE_BUILD_TYPE}" MATCHES "^Rel.*") + +# 'd' postfix on windows if debug +if (WIN32) + set(CMAKE_DEBUG_POSTFIX "d") +endif (WIN32) + + + +option (QT4_BUILD "BUild with Qt4") +if (NOT QT4_BUILD) + find_package(Qt5Core QUIET) +endif () + +if (Qt5Core_FOUND) + message("Qt5 found") + include_directories(${Qt5Core_INCLUDE_DIRS}) + add_definitions(${Qt5Core_DEFINITIONS}) + # Find includes in corresponding build directories + set(CMAKE_INCLUDE_CURRENT_DIR ON) + # Instruct CMake to run moc automatically when needed. + set(CMAKE_AUTOMOC ON) + set(PC_Requires "Qt5Core") +else () + message("Qt5 not found, searching for Qt4") + find_package(Qt4 REQUIRED) + include(${QT_USE_FILE}) + set(PC_Requires "QtCore") +endif () + +if (NOT WIN32) + set(QT_DONT_USE_QTGUI TRUE) +endif () + +#add extra search paths for libraries and includes +set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) +set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE STRING "Directory where lib will install") +set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "The directory the headers are installed in") +set(CMAKECONFIG_INSTALL_DIR "${LIB_INSTALL_DIR}/cmake/${CMAKE_PROJECT_NAME}" CACHE PATH "Directory where to install qmsgpack.cmake") + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + +set(QMSGPACK_MAJOR "0") +set(QMSGPACK_MINOR "0") +set(QMSGPACK_VERSION "0") + +set(MSGPACK_QT_LIB_VERSION_STRING "${QMSGPACK_MAJOR}.${QMSGPACK_MINOR}.${QMSGPACK_VERSION}") + +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") + +add_subdirectory(src) +#if (MSGPACK_BUILD_TESTS) + enable_testing() + add_subdirectory(tests) +#endif () + +install(EXPORT qmsgpack-export DESTINATION ${CMAKECONFIG_INSTALL_DIR} FILE MsgPackQtTargets.cmake) + +file(RELATIVE_PATH relInstallDir ${CMAKE_INSTALL_PREFIX}/$CMAKECONFIG_INSTALL_DIR} ${CMAKE_INSTALL_PREFIX}) + +add_custom_target(uninstall + "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") \ No newline at end of file diff --git a/cmake_uninstall.cmake.in b/cmake_uninstall.cmake.in new file mode 100644 index 0000000..13d8b8a --- /dev/null +++ b/cmake_uninstall.cmake.in @@ -0,0 +1,17 @@ +IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") +ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + +FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +STRING(REGEX REPLACE "\n" ";" files "${files}") +FOREACH(file ${files}) + MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") + EXEC_PROGRAM( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + IF(NOT "${rm_retval}" STREQUAL 0) + MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") + ENDIF(NOT "${rm_retval}" STREQUAL 0) +ENDFOREACH(file) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..2e83feb --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,25 @@ +set(qmsgpack_srcs msgpack.cpp private/pack_p.cpp private/unpack_p.cpp) +set(qmsgpack_headers msgpack.h msgpack_common.h msgpack_export.h) + +add_library(qmsgpack SHARED ${qmsgpack_srcs} ${qmsgpack_headers}) + +if (Qt5Core_FOUND) + target_link_libraries(qmsgpack Qt5::Core) +else () + target_link_libraries(qmsgpack ${QT_LIBRARIES}) +endif () + +if (NOT android) + set_target_properties(qmsgpack PROPERTIES + VERSION ${QMSGPACK_MAJOR}.${QMSGPACK_MINOR}.${QMSGPACK_VERSION} + SOVERSION ${QMSGPACK_MAJOR}) +endif () +set_target_properties(qmsgpack PROPERTIES + DEFINE_SYMBOL MSGPACK_MAKE_LIB + PUBLIC_HEADER "${qmsgpack_headers}") + +install(TARGETS qmsgpack EXPORT qmsgpack-export + LIBRARY DESTINATION ${LIB_INSTALL_DIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin + ARCHIVE DESTINATION ${LIB_INSTALL_DIR} + PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR}/qmsgpack) \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..32e49b2 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include + +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; +} + +QVariant unpackQPoint(QByteArray &data) +{ + QDataStream in(&data, QIODevice::ReadOnly); + in.setVersion(QDataStream::Qt_5_3); + QPoint p; + in >> p; + return p; +} + +int main(int argc, char *argv[]) +{ + Q_UNUSED(argc) + Q_UNUSED(argv) + //QCoreApplication a(argc, argv); + + MsgPack::registerPacker(QMetaType::QPoint, 7, packQPoint); + MsgPack::registerUnpacker(7, unpackQPoint); + + QVariantList l; + + l << QPoint(12, 13); + QByteArray arr = MsgPack::pack(l); + qDebug() << arr.toBase64(); + + qDebug() << MsgPack::unpack(arr); + + + return 0; + //return a.exec(); +} diff --git a/src/msgpack-qt.pro b/src/msgpack-qt.pro new file mode 100644 index 0000000..7774d33 --- /dev/null +++ b/src/msgpack-qt.pro @@ -0,0 +1,32 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-09-07T17:43:05 +# +#------------------------------------------------- + +QT += core + +QT -= gui + +TARGET = qmsgpack +CONFIG -= app_bundle + +TEMPLATE = lib +DEFINES += MSGPACK_MAKE_LIB +target.path = ../build +INSTALLS += target +QMAKE_CXXFLAGS += -fPIC + + +SOURCES += main.cpp \ + msgpack.cpp \ + private/pack_p.cpp \ + private/unpack_p.cpp + +HEADERS += \ + msgpack.h \ + private/pack_p.h \ + private/unpack_p.h \ + private/sysdep.h \ + msgpack_common.h \ + msgpack_export.h diff --git a/src/msgpack.cpp b/src/msgpack.cpp new file mode 100644 index 0000000..278ab50 --- /dev/null +++ b/src/msgpack.cpp @@ -0,0 +1,40 @@ +#include "msgpack.h" +#include +#include "private/unpack_p.h" +#include "private/pack_p.h" +#include + +QVariant MsgPack::unpack(const QByteArray &data) +{ + quint8 *p = (quint8 *)data.data(); + quint8 *end = p + data.size() - 1; + + return MsgPackPrivate::unpack(p, end); +} + + +QByteArray MsgPack::pack(const QVariant &variant) +{ + quint8 *p = 0; + quint8 *end = MsgPackPrivate::pack(variant, p, false); + quint32 size = end - p; + //qDebug() << "size probe:" << size; + + QByteArray arr; + arr.resize(size); + end = MsgPackPrivate::pack(variant, (quint8 *)arr.data(), true); + + return arr; +} + + +bool MsgPack::registerPacker(QMetaType::Type qType, qint8 msgpackType, MsgPack::pack_user_f packer) +{ + return MsgPackPrivate::register_packer(qType, msgpackType, packer); +} + + +bool MsgPack::registerUnpacker(qint8 msgpackType, MsgPack::unpack_user_f unpacker) +{ + return MsgPackPrivate::register_unpacker(msgpackType, unpacker); +} diff --git a/src/msgpack.h b/src/msgpack.h new file mode 100644 index 0000000..2592e34 --- /dev/null +++ b/src/msgpack.h @@ -0,0 +1,17 @@ +#ifndef MSGPACK_H +#define MSGPACK_H +#include +#include +#include "msgpack_common.h" +#include "msgpack_export.h" + +namespace MsgPack +{ + MSGPACK_EXPORT QVariant unpack(const QByteArray &data); + MSGPACK_EXPORT bool registerUnpacker(qint8 msgpackType, unpack_user_f unpacker); + + MSGPACK_EXPORT QByteArray pack(const QVariant &variant); + MSGPACK_EXPORT bool registerPacker(QMetaType::Type qType, qint8 msgpackType, pack_user_f packer); +} + +#endif // MSGPACK_H diff --git a/src/msgpack_common.h b/src/msgpack_common.h new file mode 100644 index 0000000..935f5ba --- /dev/null +++ b/src/msgpack_common.h @@ -0,0 +1,18 @@ +#ifndef COMMON_H +#define COMMON_H + +#include + +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 + */ +typedef quint32 (*pack_user_f)(const QVariant &variant, QByteArray &data, bool write); + +typedef QVariant (*unpack_user_f)(QByteArray &data); +} + +#endif // COMMON_H diff --git a/src/msgpack_export.h b/src/msgpack_export.h new file mode 100644 index 0000000..bc4ece0 --- /dev/null +++ b/src/msgpack_export.h @@ -0,0 +1,12 @@ +#ifndef MSGPACK_EXPORT_H +#define MSGPACK_EXPORT_H + +#include + +#if defined(MSGPACK_MAKE_LIB) // building lib +#define MSGPACK_EXPORT Q_DECL_EXPORT +#else // using lib +#define MSGPACK_EXPORT Q_DECL_IMPORT +#endif + +#endif // MSGPACK_EXPORT_H diff --git a/src/private/pack_p.cpp b/src/private/pack_p.cpp new file mode 100644 index 0000000..b81e7ca --- /dev/null +++ b/src/private/pack_p.cpp @@ -0,0 +1,307 @@ +#include "pack_p.h" +#include "private/sysdep.h" +#include + +QHash MsgPackPrivate::user_packers; + +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.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, wr); + else if (t == QMetaType::QString) + p = pack_string(v.toString(), p, wr); + else if (t == QMetaType::QVariantList) + 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); + else { + if (user_packers.contains(t)) + p = pack_user(v, p, wr); + else + qWarning() << "MsgPack::pack can't pack type:" << t; + } + + return p; +} + +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_uint(quint32 i, quint8 *p, bool wr) +{ + 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 QVariantList &list, quint8 *p, bool wr) +{ + 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; +} + + +bool MsgPackPrivate::register_packer(QMetaType::Type q_type, qint8 msgpack_type, MsgPack::pack_user_f packer) +{ + if (user_packers.contains(q_type)) { + qWarning() << "MsgPack::packer for qtype" << q_type << "already exist"; + return false; + } + if (packer == 0) { + qWarning() << "MsgPack::packer for qtype" << q_type << "is invalid"; + 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/src/private/pack_p.h b/src/private/pack_p.h new file mode 100644 index 0000000..bac2330 --- /dev/null +++ b/src/private/pack_p.h @@ -0,0 +1,36 @@ +#ifndef PACK_P_H +#define PACK_P_H +#include +#include "../msgpack_common.h" + +namespace MsgPackPrivate { +/* if wr (write) == false, packer just moves pointer forward + * + */ +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); + +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_user(const QVariant &v, quint8 *p, bool wr); + + + +} + +#endif // PACK_P_H diff --git a/src/private/sysdep.h b/src/private/sysdep.h new file mode 100644 index 0000000..25704f1 --- /dev/null +++ b/src/private/sysdep.h @@ -0,0 +1,152 @@ +/* + * MessagePack system dependencies + * + * Copyright (C) 2008-2010 FURUHASHI Sadayuki + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MSGPACK_SYSDEP_H__ +#define MSGPACK_SYSDEP_H__ +#include + +#ifndef _WIN32 +#include /* __BYTE_ORDER */ +#endif + +#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define __LITTLE_ENDIAN__ +#elif __BYTE_ORDER == __BIG_ENDIAN +#define __BIG_ENDIAN__ +#elif _WIN32 +#define __LITTLE_ENDIAN__ +#endif +#endif + + +#ifdef __LITTLE_ENDIAN__ + +#ifdef _WIN32 +# if defined(ntohs) +# define _msgpack_be16(x) ntohs(x) +# elif defined(_byteswap_ushort) || (defined(_MSC_VER) && _MSC_VER >= 1400) +# define _msgpack_be16(x) ((uint16_t)_byteswap_ushort((unsigned short)x)) +# else +# define _msgpack_be16(x) ( \ + ((((quint16)x) << 8) ) | \ + ((((quint16)x) >> 8) ) ) +# endif +#else +# define _msgpack_be16(x) ntohs(x) +#endif + +#ifdef _WIN32 +# if defined(ntohl) +# define _msgpack_be32(x) ntohl(x) +# elif defined(_byteswap_ulong) || (defined(_MSC_VER) && _MSC_VER >= 1400) +# define _msgpack_be32(x) ((uint32_t)_byteswap_ulong((unsigned long)x)) +# else +# define _msgpack_be32(x) \ + ( ((((quint32)x) << 24) ) | \ + ((((quint32)x) << 8) & 0x00ff0000U ) | \ + ((((quint32)x) >> 8) & 0x0000ff00U ) | \ + ((((quint32)x) >> 24) ) ) +# endif +#else +# define _msgpack_be32(x) ntohl(x) +#endif + +#if defined(_byteswap_uint64) || (defined(_MSC_VER) && _MSC_VER >= 1400) +# define _msgpack_be64(x) (_byteswap_uint64(x)) +#elif defined(bswap_64) +# define _msgpack_be64(x) bswap_64(x) +#elif defined(__DARWIN_OSSwapInt64) +# define _msgpack_be64(x) __DARWIN_OSSwapInt64(x) +#else +#define _msgpack_be64(x) \ + ( ((((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)( \ + (((quint16)((quint8*)(from))[0]) << 8) | \ + (((quint16)((quint8*)(from))[1]) ) )) + +#define _msgpack_load32(cast, from) ((cast)( \ + (((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)( \ + (((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 + +#define _msgpack_be16(x) (x) +#define _msgpack_be32(x) (x) +#define _msgpack_be64(x) (x) + +#define _msgpack_load16(cast, from) ((cast)( \ + (((quint16)((quint8*)from)[0]) << 8) | \ + (((quint16)((quint8*)from)[1]) ) )) + +#define _msgpack_load32(cast, from) ((cast)( \ + (((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)( \ + (((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 { quint16 val = _msgpack_be16(num); memcpy(to, &val, 2); } while(0) +#define _msgpack_store32(to, num) \ + do { quint32 val = _msgpack_be32(num); memcpy(to, &val, 4); } while(0) +#define _msgpack_store64(to, num) \ + do { quint64 val = _msgpack_be64(num); memcpy(to, &val, 8); } while(0) + +/* +#define _msgpack_load16(cast, from) \ + ({ cast val; memcpy(&val, (char*)from, 2); _msgpack_be16(val); }) +#define _msgpack_load32(cast, from) \ + ({ cast val; memcpy(&val, (char*)from, 4); _msgpack_be32(val); }) +#define _msgpack_load64(cast, from) \ + ({ cast val; memcpy(&val, (char*)from, 8); _msgpack_be64(val); }) +*/ + +#endif /* msgpack/sysdep.h */ + diff --git a/src/private/unpack_p.cpp b/src/private/unpack_p.cpp new file mode 100644 index 0000000..4502f98 --- /dev/null +++ b/src/private/unpack_p.cpp @@ -0,0 +1,388 @@ +#include "unpack_p.h" +#include "sysdep.h" +#include + +MsgPackPrivate::type_parser_f MsgPackPrivate::unpackers[32] = { + unpack_nil, + unpack_never_used, + unpack_false, unpack_true, + unpack_bin8, unpack_bin16, unpack_bin32, + unpack_ext8, unpack_ext16, unpack_ext32, + unpack_float32, unpack_float64, + unpack_uint8, unpack_uint16, unpack_uint32, unpack_uint64, + unpack_int8, unpack_int16, unpack_int32, unpack_int64, + unpack_fixext1, unpack_fixext2, unpack_fixext4, unpack_fixext8, unpack_fixext16, + unpack_str8, unpack_str16, unpack_str32, + unpack_array16, unpack_array32, + unpack_map16, unpack_map32 +}; + +QHash MsgPackPrivate::user_unpackers; + +QVariant MsgPackPrivate::unpack(quint8 *p, quint8 *end) +{ + QVariantList d; + + QVariant v; + while (p <= end) { + p = unpack_type(v, p); + d.append(v); + } + + if (p - end > 1) + return QVariant(); + + if (d.length() == 1) + return d[0]; + return d; +} + +quint8 *MsgPackPrivate::unpack_type(QVariant &v, quint8 *p) +{ + if (*p <= 127) { // positive fixint 0x00 - 0x7f + p = unpack_positive_fixint(v, p); + } else if (*p >= 0xe0) { // negative fixint 0xe0 - 0xff + p = unpack_negative_fixint(v, p); + } else if (*p >= 0x80 && *p <= 0x8f) { // fixmap 1000xxxx 0x80 - 0x8f + p = unpack_fixmap(v, p); + } else if (*p >= 0x90 && *p <= 0x9f) { // fixarray 1001xxxx 0x90 - 0x9f + p = unpack_fixarray(v, p); + } else if (*p >= 0xa0 && *p <= 0xbf) { // fixstr 101xxxxx 0xa0 - 0xbf + p = unpack_fixstr(v, p); + } else { // all other types + p = (unpackers[*p - 0xc0])(v, p); + } + + //qDebug() << "unpack type res:" << d << sz; + return p; +} + +quint8 * MsgPackPrivate::unpack_nil(QVariant &v, quint8 *p) +{ + Q_UNUSED(p) + Q_UNUSED(v) + return p + 1; +} + +quint8 * MsgPackPrivate::unpack_never_used(QVariant &v, quint8 *p) +{ + Q_UNUSED(p) + Q_UNUSED(v) + return p + 1; +} + +quint8 * MsgPackPrivate::unpack_false(QVariant &v, quint8 *p) +{ + Q_UNUSED(p) + v = false; + return p + 1; +} + +quint8 * MsgPackPrivate::unpack_true(QVariant &v, quint8 *p) +{ + Q_UNUSED(p) + v = true; + return p + 1; +} + +quint8 * MsgPackPrivate::unpack_positive_fixint(QVariant &v, quint8 *p) +{ + v = (quint32)*p; + return p + 1; +} + +quint8 * MsgPackPrivate::unpack_negative_fixint(QVariant &v, quint8 *p) +{ + v = (qint8)*p; + return p + 1; +} + +quint8 * MsgPackPrivate::unpack_uint8(QVariant &v, quint8 *p) +{ + v = (quint8)*(++p); + return p++; +} + +quint8 * MsgPackPrivate::unpack_uint16(QVariant &v, quint8 *p) +{ + p++; + v = _msgpack_load16(quint16, p); + return p + 2; +} + +quint8 * MsgPackPrivate::unpack_uint32(QVariant &v, quint8 *p) +{ + p++; + v = _msgpack_load32(quint32, p); + return p + 4; +} + +quint8 * MsgPackPrivate::unpack_uint64(QVariant &v, quint8 *p) +{ + p++; + v = _msgpack_load64(quint64, p); + return p + 8; +} + +quint8 * MsgPackPrivate::unpack_int8(QVariant &v, quint8 *p) +{ + v = (qint8)*(++p); + return p + 1; +} + +quint8 * MsgPackPrivate::unpack_int16(QVariant &v, quint8 *p) +{ + p++; + v = _msgpack_load16(qint16, p); + return p + 2; +} + +quint8 * MsgPackPrivate::unpack_int32(QVariant &v, quint8 *p) +{ + p++; + v = _msgpack_load32(quint32, p); + return p + 4; +} + +quint8 * MsgPackPrivate::unpack_int64(QVariant &v, quint8 *p) +{ + p++; + v = _msgpack_load64(qint64, p); + return p + 8; +} + +quint8 * MsgPackPrivate::unpack_float32(QVariant &v, quint8 *p) +{ + float f; + quint8 *fp = (quint8 *)&f; + p++; +#ifdef __LITTLE_ENDIAN__ + for (int i = 0; i < 4; ++i) + *(fp + 3 - i) = *(p + i); +#else + for (int i = 0; i < 4; ++i) + *(fp + i) = *(p + i); +#endif + v = f; + return p + 4; +} + +quint8 * MsgPackPrivate::unpack_float64(QVariant &v, quint8 *p) +{ + double d; + quint8 *fd = (quint8 *)&d; + p++; +#ifdef __LITTLE_ENDIAN__ + for (int i = 0; i < 8; ++i) + *(fd + 7 - i) = *(p + i); +#else + for (int i = 0; i < 4; ++i) + *(fp + i) = *(p + i); +#endif + v = d; + return p + 8; +} + +quint8 * MsgPackPrivate::unpack_fixstr(QVariant &v, quint8 *p) +{ + int len = (*p) & 0x1f; // 0b00011111 + p++; + v = QString::fromUtf8((char*)p, len); + return p + len; +} + +quint8 * MsgPackPrivate::unpack_str8(QVariant &v, quint8 *p) +{ + int len = *(++p); + v = QString::fromUtf8((char*)(++p), len); + return p + len; +} + +quint8 * MsgPackPrivate::unpack_str16(QVariant &v, quint8 *p) +{ + p++; + int len = _msgpack_load16(int, p); + p += 2; + v = QString::fromUtf8((char*)p, len); + return p + len; +} + +quint8 * MsgPackPrivate::unpack_str32(QVariant &v, quint8 *p) +{ + p++; + int len = _msgpack_load32(int, p); + p += 4; + v = QString::fromUtf8((char*)p, len); + return p + len; +} + +quint8 * MsgPackPrivate::unpack_bin8(QVariant &v, quint8 *p) +{ + int len = *(++p); + v = QByteArray((char*)(++p), len); + return p + len; +} + +quint8 * MsgPackPrivate::unpack_bin16(QVariant &v, quint8 *p) +{ + p++; + int len = _msgpack_load16(int, p); + p += 2; + v = QByteArray((char*)p, len); + return p + len; +} + +quint8 * MsgPackPrivate::unpack_bin32(QVariant &v, quint8 *p) +{ + p++; + int len = _msgpack_load32(int, p); + p += 4; + v = QByteArray((char*)p, len); + return p + len; +} + +quint8 * MsgPackPrivate::unpack_array_len(QVariant &v, quint8 *p, quint32 len) +{ + QVariantList arr; + + QVariant vu; + for (quint32 i = 0; i < len; ++i) { + p = unpack_type(vu, p); + arr.append(vu); + } + v = arr; + return p; +} + +quint8 * MsgPackPrivate::unpack_fixarray(QVariant &v, quint8 *p) +{ + quint32 len = (*p++) & 0x0f; // 0b00001111 + return unpack_array_len(v, p, len); +} + +quint8 * MsgPackPrivate::unpack_array16(QVariant &v, quint8 *p) +{ + p++; + quint32 len = _msgpack_load16(quint32, p); + return unpack_array_len(v, p += 2, len); +} + +quint8 * MsgPackPrivate::unpack_array32(QVariant &v, quint8 *p) +{ + p++; + quint32 len = _msgpack_load32(quint32, p); + return unpack_array_len(v, p += 4, len); +} + +quint8 * MsgPackPrivate::unpack_map_len(QVariant &v, quint8 *p, quint32 len) +{ + QMap map; + QVariant key, val; + + for (quint32 i = 0; i < len; ++i) { + p = unpack_type(key, p); + p = unpack_true(val, p); + + map.insert(key.toString(), val); + } + v = map; + return p; +} + +quint8 * MsgPackPrivate::unpack_fixmap(QVariant &v, quint8 *p) +{ + quint32 len = (*p++) & 0x0f; // 0b00001111 + return unpack_map_len(v, p ,len); +} + +quint8 * MsgPackPrivate::unpack_map16(QVariant &v, quint8 *p) +{ + p++; + quint32 len = _msgpack_load16(quint32, p); + return unpack_map_len(v, p += 2, len); +} + +quint8 * MsgPackPrivate::unpack_map32(QVariant &v, quint8 *p) +{ + p++; + quint32 len = _msgpack_load32(quint32, p); + return unpack_map_len(v, p + 4, len); +} + +quint8 *MsgPackPrivate::unpack_ext(QVariant &v, quint8 *p, qint8 type, quint32 len) +{ + if (!user_unpackers.contains(type)) { + qWarning() << "MsgPack::unpack() unpacker for type" << type << "doesn't exist"; + return p + len; + } + QByteArray data((char *)p, len); + v = user_unpackers[type](data); + return p + len; +} + +quint8 * MsgPackPrivate::unpack_fixext1(QVariant &v, quint8 *p) +{ + qint8 type = *(++p); + return unpack_ext(v, p + 1, type, 1); +} + +quint8 * MsgPackPrivate::unpack_fixext2(QVariant &v, quint8 *p) +{ + qint8 type = *(++p); + return unpack_ext(v, p + 1, type, 2); +} + +quint8 * MsgPackPrivate::unpack_fixext4(QVariant &v, quint8 *p) +{ + qint8 type = *(++p); + return unpack_ext(v, p + 1, type, 4); +} + +quint8 * MsgPackPrivate::unpack_fixext8(QVariant &v, quint8 *p) +{ + qint8 type = *(++p); + return unpack_ext(v, p + 1, type, 8); +} + +quint8 * MsgPackPrivate::unpack_fixext16(QVariant &v, quint8 *p) +{ + qint8 type = *(++p); + return unpack_ext(v, p + 1, type, 16); +} + +quint8 * MsgPackPrivate::unpack_ext8(QVariant &v, quint8 *p) +{ + qint8 type = *(++p); + quint32 len = *(p++); + return unpack_ext(v, p + 1, type, len); +} + +quint8 * MsgPackPrivate::unpack_ext16(QVariant &v, quint8 *p) +{ + qint8 type = *(++p); + quint32 len = _msgpack_load16(quint32, p); + p += 2; + return unpack_ext(v, p + 1, type, len); +} + +quint8 * MsgPackPrivate::unpack_ext32(QVariant &v, quint8 *p) +{ + qint8 type = *(++p); + quint32 len = _msgpack_load32(quint32, p); + p += 4; + return unpack_ext(v, p + 1, type, len); +} + +bool MsgPackPrivate::register_unpacker(qint8 msgpack_type, MsgPack::unpack_user_f unpacker) +{ + if (user_unpackers.contains(msgpack_type)) { + qWarning() << "MsgPack::unpacker for type" << msgpack_type << "already exists"; + return false; + } + if (unpacker == 0) { + qWarning() << "MsgPack::unpacker for type" << msgpack_type << "is invalid"; + return false; + } + user_unpackers.insert(msgpack_type, unpacker); + return true; +} diff --git a/src/private/unpack_p.h b/src/private/unpack_p.h new file mode 100644 index 0000000..e9cda80 --- /dev/null +++ b/src/private/unpack_p.h @@ -0,0 +1,75 @@ +#ifndef MSGPACK_P_H +#define MSGPACK_P_H +#include +#include "../msgpack_common.h" + +namespace MsgPackPrivate +{ +/* unpack functions: + * quint8 * _type_(QVariant &v, quint8 *p); + * parses some type, which data is stored at p + * type data goes to v + * return pointer to last byte + 1 + */ +typedef quint8 * (* type_parser_f)(QVariant &v, quint8 *p); +extern type_parser_f unpackers[32]; + +bool register_unpacker(qint8 msgpack_type, MsgPack::unpack_user_f unpacker); +extern QHash user_unpackers; + +// goes from p to end unpacking types with unpack_type function below +QVariant unpack(quint8 *p, quint8 *end); +// unpack some type, can be called recursively from other unpack functions +quint8 * unpack_type(QVariant &v, quint8 *p); + +quint8 * unpack_nil(QVariant &v, quint8 *p); +quint8 * unpack_never_used(QVariant &v, quint8 *p); +quint8 * unpack_false(QVariant &v, quint8 *p); +quint8 * unpack_true(QVariant &v, quint8 *p); + +quint8 * unpack_positive_fixint(QVariant &v, quint8 *p); +quint8 * unpack_negative_fixint(QVariant &v, quint8 *p); +quint8 * unpack_uint8(QVariant &v, quint8 *p); +quint8 * unpack_uint16(QVariant &v, quint8 *p); +quint8 * unpack_uint32(QVariant &v, quint8 *p); +quint8 * unpack_uint64(QVariant &v, quint8 *p); +quint8 * unpack_int8(QVariant &v, quint8 *p); +quint8 * unpack_int16(QVariant &v, quint8 *p); +quint8 * unpack_int32(QVariant &v, quint8 *p); +quint8 * unpack_int64(QVariant &v, quint8 *p); + +quint8 * unpack_float32(QVariant &v, quint8 *p); +quint8 * unpack_float64(QVariant &v, quint8 *p); + +quint8 * unpack_fixstr(QVariant &v, quint8 *p); +quint8 * unpack_str8(QVariant &v, quint8 *p); +quint8 * unpack_str16(QVariant &v, quint8 *p); +quint8 * unpack_str32(QVariant &v, quint8 *p); + +quint8 * unpack_bin8(QVariant &v, quint8 *p); +quint8 * unpack_bin16(QVariant &v, quint8 *p); +quint8 * unpack_bin32(QVariant &v, quint8 *p); + +quint8 * unpack_array_len(QVariant &v, quint8 *p, quint32 len); +quint8 * unpack_fixarray(QVariant &v, quint8 *p); +quint8 * unpack_array16(QVariant &v, quint8 *p); +quint8 * unpack_array32(QVariant &v, quint8 *p); + +quint8 * unpack_map_len(QVariant &v, quint8 *p, quint32 len); +quint8 * unpack_fixmap(QVariant &v, quint8 *p); +quint8 * unpack_map16(QVariant &v, quint8 *p); +quint8 * unpack_map32(QVariant &v, quint8 *p); + +quint8 * unpack_ext(QVariant &v, quint8 *p, qint8 type, quint32 len); +quint8 * unpack_fixext1(QVariant &v, quint8 *p); +quint8 * unpack_fixext2(QVariant &v, quint8 *p); +quint8 * unpack_fixext4(QVariant &v, quint8 *p); +quint8 * unpack_fixext8(QVariant &v, quint8 *p); +quint8 * unpack_fixext16(QVariant &v, quint8 *p); + +quint8 * unpack_ext8(QVariant &v, quint8 *p); +quint8 * unpack_ext16(QVariant &v, quint8 *p); +quint8 * unpack_ext32(QVariant &v, quint8 *p); +} + +#endif // MSGPACK_P_H diff --git a/test/pack/pack-test/pack-test.pro b/test/pack/pack-test/pack-test.pro new file mode 100644 index 0000000..925c788 --- /dev/null +++ b/test/pack/pack-test/pack-test.pro @@ -0,0 +1,19 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-09-20T15:17:37 +# +#------------------------------------------------- + +QT += testlib + +QT -= gui + +TARGET = tst_d +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + + +SOURCES += tst_d.cpp +DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/test/pack/pack-test/tst_d.cpp b/test/pack/pack-test/tst_d.cpp new file mode 100644 index 0000000..90df31a --- /dev/null +++ b/test/pack/pack-test/tst_d.cpp @@ -0,0 +1,26 @@ +#include +#include + +class d : public QObject +{ + Q_OBJECT + +public: + d(); + +private Q_SLOTS: + void testCase1(); +}; + +d::d() +{ +} + +void d::testCase1() +{ + QVERIFY2(true, "Failure"); +} + +QTEST_APPLESS_MAIN(d) + +#include "tst_d.moc" diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..09112b4 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,11 @@ +if (Qt5Core_FOUND) + find_package(Qt5Test REQUIRED) + + include_directories(${Qt5Test_INCLUDE_DIRS}) + add_definitions(${Qt5Test_DEFINITIONS}) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Test_EXECUTABLE_COMPILE_FLAGS}") + + set(TEST_LIBRARIES ${Qt5Test_LIBRARIES}) +endif () + +add_subdirectory(pack) \ No newline at end of file diff --git a/tests/pack/CMakeLists.txt b/tests/pack/CMakeLists.txt new file mode 100644 index 0000000..aa11400 --- /dev/null +++ b/tests/pack/CMakeLists.txt @@ -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 pack_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() \ No newline at end of file diff --git a/tests/pack/pack-test.pro b/tests/pack/pack-test.pro new file mode 100644 index 0000000..8aa092e --- /dev/null +++ b/tests/pack/pack-test.pro @@ -0,0 +1,22 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-09-20T15:17:37 +# +#------------------------------------------------- + +QT += testlib + +QT -= gui + +TARGET = pack_test +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + +LIBS += -lqmsgpack +INCLUDEPATH += ../../src + + +SOURCES += pack_test.cpp +DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/tests/pack/pack_test.cpp b/tests/pack/pack_test.cpp new file mode 100644 index 0000000..6883b24 --- /dev/null +++ b/tests/pack/pack_test.cpp @@ -0,0 +1,198 @@ +#include +#include +#include +#include "msgpack.h" + +class PackTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void test_bool(); + void test_fixint(); + void test_integer8(); + void test_integer16(); + void test_integer32(); + void test_integer64(); +}; + +void PackTest::test_bool() +{ + QByteArray arr = MsgPack::pack(false); + quint8 *p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 1); + QVERIFY(p[0] == 0xc2); + + arr = MsgPack::pack(true); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 1); + QVERIFY(p[0] == 0xc3); +} + +void PackTest::test_fixint() +{ + QByteArray arr = MsgPack::pack(0); + quint8 *p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 1); + QVERIFY(p[0] == 0x00); + + arr = MsgPack::pack(127); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 1); + QVERIFY(p[0] == 0x7f); + + arr = MsgPack::pack(-1); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 1); + QVERIFY(p[0] == 0xff); + + arr = MsgPack::pack(-32); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 1); + QVERIFY(p[0] == 0xe0); +} + +void PackTest::test_integer8() +{ + QByteArray arr = MsgPack::pack(128); + quint8 *p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 2); + QVERIFY(p[0] == 0xcc); + QVERIFY(p[1] == 0x80); + + arr = MsgPack::pack(255); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 2); + QVERIFY(p[0] == 0xcc); + QVERIFY(p[1] == 0xff); + + arr = MsgPack::pack(-33); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 2); + QVERIFY(p[0] == 0xd0); + QVERIFY(p[1] == 0xdf); + + arr = MsgPack::pack(-128); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 2); + QVERIFY(p[0] == 0xd0); + QVERIFY(p[1] == 0x80); +} + +void PackTest::test_integer16() +{ + QByteArray arr = MsgPack::pack(256); + quint8 *p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 3); + QVERIFY(p[0] == 0xcd); + QVERIFY(p[1] == 0x01); + QVERIFY(p[2] == 0x00); + + arr = MsgPack::pack(65535); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 3); + QVERIFY(p[0] == 0xcd); + QVERIFY(p[1] == 0xff); + QVERIFY(p[2] == 0xff); + + arr = MsgPack::pack(-129); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 3); + QVERIFY(p[0] == 0xd1); + QVERIFY(p[1] == 0xff); + QVERIFY(p[2] == 0x7f); + + arr = MsgPack::pack(-32768); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 3); + QVERIFY(p[0] == 0xd1); + QVERIFY(p[1] == 0x80); + QVERIFY(p[2] == 0x00); +} + +void PackTest::test_integer32() +{ + QByteArray arr = MsgPack::pack(65536); + quint8 *p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 5); + QVERIFY(p[0] == 0xce); + QVERIFY(p[1] == 0x00); + QVERIFY(p[2] == 0x01); + QVERIFY(p[3] == 0x00); + QVERIFY(p[4] == 0x00); + + arr = MsgPack::pack((quint32)4294967295); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 5); + QVERIFY(p[0] == 0xce); + QVERIFY(p[1] == 0xff); + QVERIFY(p[2] == 0xff); + QVERIFY(p[3] == 0xff); + QVERIFY(p[4] == 0xff); + + arr = MsgPack::pack(-32769); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 5); + QVERIFY(p[0] == 0xd2); + QVERIFY(p[1] == 0xff); + QVERIFY(p[2] == 0xff); + QVERIFY(p[3] == 0x7f); + QVERIFY(p[4] == 0xff); + + arr = MsgPack::pack((qint32)-2147483648); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 5); + QVERIFY(p[0] == 0xd2); + QVERIFY(p[1] == 0x80); + QVERIFY(p[2] == 0x00); + QVERIFY(p[3] == 0x00); + QVERIFY(p[4] == 0x00); +} + +void PackTest::test_integer64() +{ + QByteArray arr = MsgPack::pack((quint64)4294967296); + quint8 *p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 9); + QVERIFY(p[0] == 0xcf); + QVERIFY(p[1] == 0x00); + QVERIFY(p[2] == 0x00); + QVERIFY(p[3] == 0x00); + QVERIFY(p[4] == 0x01); + QVERIFY(p[5] == 0x00); + QVERIFY(p[6] == 0x00); + QVERIFY(p[7] == 0x00); + QVERIFY(p[8] == 0x00); + + arr = MsgPack::pack((quint64)18446744073709551615U); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 9); + QVERIFY(p[0] == 0xcf); + for (int i = 1; i < 9; ++i) + QVERIFY(p[i] == 0xff); + + arr = MsgPack::pack((qint64)-2147483649); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 9); + QVERIFY(p[0] == 0xd3); + QVERIFY(p[1] == 0xff); + QVERIFY(p[2] == 0xff); + QVERIFY(p[3] == 0xff); + QVERIFY(p[4] == 0xff); + QVERIFY(p[5] == 0x7f); + QVERIFY(p[6] == 0xff); + QVERIFY(p[7] == 0xff); + QVERIFY(p[8] == 0xff); + + arr = MsgPack::pack((qint64)-9223372036854775808); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 9); + QVERIFY(p[0] == 0xd3); + QVERIFY(p[1] == 0x80); + for (int i = 2; i < 9; ++i) + QVERIFY(p[i] == 0x00); +} + +QTEST_APPLESS_MAIN(PackTest) + +#include "pack_test.moc" diff --git a/tests/pack/pack_test.cpp.autosave b/tests/pack/pack_test.cpp.autosave new file mode 100644 index 0000000..9bfe173 --- /dev/null +++ b/tests/pack/pack_test.cpp.autosave @@ -0,0 +1,215 @@ +#include +#include +#include +#include "msgpack.h" + +class PackTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void test_bool(); + void test_fixint(); + void test_integer8(); + void test_integer16(); + void test_integer32(); + void test_integer64(); + void test_float(); +}; + +void PackTest::test_bool() +{ + QByteArray arr = MsgPack::pack(false); + quint8 *p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 1); + QVERIFY(p[0] == 0xc2); + + arr = MsgPack::pack(true); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 1); + QVERIFY(p[0] == 0xc3); +} + +void PackTest::test_fixint() +{ + QByteArray arr = MsgPack::pack(0); + quint8 *p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 1); + QVERIFY(p[0] == 0x00); + + arr = MsgPack::pack(127); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 1); + QVERIFY(p[0] == 0x7f); + + arr = MsgPack::pack(-1); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 1); + QVERIFY(p[0] == 0xff); + + arr = MsgPack::pack(-32); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 1); + QVERIFY(p[0] == 0xe0); +} + +void PackTest::test_integer8() +{ + QByteArray arr = MsgPack::pack(128); + quint8 *p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 2); + QVERIFY(p[0] == 0xcc); + QVERIFY(p[1] == 0x80); + + arr = MsgPack::pack(255); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 2); + QVERIFY(p[0] == 0xcc); + QVERIFY(p[1] == 0xff); + + arr = MsgPack::pack(-33); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 2); + QVERIFY(p[0] == 0xd0); + QVERIFY(p[1] == 0xdf); + + arr = MsgPack::pack(-128); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 2); + QVERIFY(p[0] == 0xd0); + QVERIFY(p[1] == 0x80); +} + +void PackTest::test_integer16() +{ + QByteArray arr = MsgPack::pack(256); + quint8 *p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 3); + QVERIFY(p[0] == 0xcd); + QVERIFY(p[1] == 0x01); + QVERIFY(p[2] == 0x00); + + arr = MsgPack::pack(65535); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 3); + QVERIFY(p[0] == 0xcd); + QVERIFY(p[1] == 0xff); + QVERIFY(p[2] == 0xff); + + arr = MsgPack::pack(-129); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 3); + QVERIFY(p[0] == 0xd1); + QVERIFY(p[1] == 0xff); + QVERIFY(p[2] == 0x7f); + + arr = MsgPack::pack(-32768); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 3); + QVERIFY(p[0] == 0xd1); + QVERIFY(p[1] == 0x80); + QVERIFY(p[2] == 0x00); +} + +void PackTest::test_integer32() +{ + QByteArray arr = MsgPack::pack(65536); + quint8 *p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 5); + QVERIFY(p[0] == 0xce); + QVERIFY(p[1] == 0x00); + QVERIFY(p[2] == 0x01); + QVERIFY(p[3] == 0x00); + QVERIFY(p[4] == 0x00); + + arr = MsgPack::pack((quint32)4294967295); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 5); + QVERIFY(p[0] == 0xce); + QVERIFY(p[1] == 0xff); + QVERIFY(p[2] == 0xff); + QVERIFY(p[3] == 0xff); + QVERIFY(p[4] == 0xff); + + arr = MsgPack::pack(-32769); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 5); + QVERIFY(p[0] == 0xd2); + QVERIFY(p[1] == 0xff); + QVERIFY(p[2] == 0xff); + QVERIFY(p[3] == 0x7f); + QVERIFY(p[4] == 0xff); + + arr = MsgPack::pack((qint32)-2147483648); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 5); + QVERIFY(p[0] == 0xd2); + QVERIFY(p[1] == 0x80); + QVERIFY(p[2] == 0x00); + QVERIFY(p[3] == 0x00); + QVERIFY(p[4] == 0x00); +} + +void PackTest::test_integer64() +{ + QByteArray arr = MsgPack::pack((quint64)4294967296); + quint8 *p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 9); + QVERIFY(p[0] == 0xcf); + QVERIFY(p[1] == 0x00); + QVERIFY(p[2] == 0x00); + QVERIFY(p[3] == 0x00); + QVERIFY(p[4] == 0x01); + QVERIFY(p[5] == 0x00); + QVERIFY(p[6] == 0x00); + QVERIFY(p[7] == 0x00); + QVERIFY(p[8] == 0x00); + + arr = MsgPack::pack((quint64)18446744073709551615U); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 9); + QVERIFY(p[0] == 0xcf); + for (int i = 1; i < 9; ++i) + QVERIFY(p[i] == 0xff); + + arr = MsgPack::pack((qint64)-2147483649); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 9); + QVERIFY(p[0] == 0xd3); + QVERIFY(p[1] == 0xff); + QVERIFY(p[2] == 0xff); + QVERIFY(p[3] == 0xff); + QVERIFY(p[4] == 0xff); + QVERIFY(p[5] == 0x7f); + QVERIFY(p[6] == 0xff); + QVERIFY(p[7] == 0xff); + QVERIFY(p[8] == 0xff); + + arr = MsgPack::pack((qint64)-9223372036854775808); + p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 9); + QVERIFY(p[0] == 0xd3); + QVERIFY(p[1] == 0x80); + for (int i = 2; i < 9; ++i) + QVERIFY(p[i] == 0x00); +} + +void PackTest::test_float() +{ + QByteArray arr = MsgPack::pack(1.234567); + quint8 *p = (quint8 *)arr.data(); + QVERIFY(arr.size() == 9); + QVERIFY(p[0] == 0xcf); + QVERIFY(p[1] == 0x00); + QVERIFY(p[2] == 0x00); + QVERIFY(p[3] == 0x00); + QVERIFY(p[4] == 0x01); + QVERIFY(p[5] == 0x00); + QVERIFY(p[6] == 0x00); + QVERIFY(p[7] == 0x00); + QVERIFY(p[8] == 0x00); +} + +QTEST_APPLESS_MAIN(PackTest) + +#include "pack_test.moc"