From 4a9eeb850b25ab771a257f16294ec656a919da51 Mon Sep 17 00:00:00 2001 From: Mikko Ahlroth Date: Mon, 30 Jun 2014 22:33:24 +0300 Subject: [PATCH] Implement more datatypes and Type enum, create stub file for Hdata We'll use QVariant for dynamic typing, it offers easy storage of even complex QObjects in a dynamic type. --- harbour-weechatrelay.pro | 8 +- src/weechat/dynamictypeexception.cpp | 6 ++ src/weechat/dynamictypeexception.h | 13 +++ src/weechat/hdata.cpp | 6 ++ src/weechat/hdata.h | 18 ++++ src/weechatprotocolhandler.cpp | 134 ++++++++++++++++++++++++--- src/weechatprotocolhandler.h | 27 +++++- 7 files changed, 192 insertions(+), 20 deletions(-) create mode 100644 src/weechat/dynamictypeexception.cpp create mode 100644 src/weechat/dynamictypeexception.h create mode 100644 src/weechat/hdata.cpp create mode 100644 src/weechat/hdata.h diff --git a/harbour-weechatrelay.pro b/harbour-weechatrelay.pro index c96e943..25dc45f 100644 --- a/harbour-weechatrelay.pro +++ b/harbour-weechatrelay.pro @@ -16,7 +16,9 @@ SOURCES += src/harbour-weechatrelay.cpp \ src/connectionhandler.cpp \ src/weechatprotocolhandler.cpp \ src/protocolhandler.cpp \ - src/qsslcertificateinfo.cpp + src/qsslcertificateinfo.cpp \ + src/weechat/hdata.cpp \ + src/weechat/dynamictypeexception.cpp OTHER_FILES += qml/harbour-weechatrelay.qml \ rpm/harbour-weechatrelay.spec \ @@ -41,7 +43,9 @@ HEADERS += \ src/protocolhandler.h \ src/weechatprotocolhandler.h \ src/connectresolver.h \ - src/qsslcertificateinfo.h + src/qsslcertificateinfo.h \ + src/weechat/hdata.h \ + src/weechat/dynamictypeexception.h QT += network diff --git a/src/weechat/dynamictypeexception.cpp b/src/weechat/dynamictypeexception.cpp new file mode 100644 index 0000000..353312e --- /dev/null +++ b/src/weechat/dynamictypeexception.cpp @@ -0,0 +1,6 @@ +#include "dynamictypeexception.h" + +DynamicTypeException::DynamicTypeException(const std::string &__arg): + std::runtime_error(__arg) +{ +} diff --git a/src/weechat/dynamictypeexception.h b/src/weechat/dynamictypeexception.h new file mode 100644 index 0000000..44eb8cc --- /dev/null +++ b/src/weechat/dynamictypeexception.h @@ -0,0 +1,13 @@ +#ifndef DYNAMICTYPEEXCEPTION_H +#define DYNAMICTYPEEXCEPTION_H + +#include +#include + +class DynamicTypeException : public std::runtime_error +{ +public: + explicit DynamicTypeException(const std::string& __arg); +}; + +#endif // DYNAMICTYPEEXCEPTION_H diff --git a/src/weechat/hdata.cpp b/src/weechat/hdata.cpp new file mode 100644 index 0000000..65d883b --- /dev/null +++ b/src/weechat/hdata.cpp @@ -0,0 +1,6 @@ +#include "hdata.h" + +Hdata::Hdata(QObject *parent) : + QObject(parent) +{ +} diff --git a/src/weechat/hdata.h b/src/weechat/hdata.h new file mode 100644 index 0000000..e2cbd35 --- /dev/null +++ b/src/weechat/hdata.h @@ -0,0 +1,18 @@ +#ifndef HDATA_H +#define HDATA_H + +#include + +class Hdata : public QObject +{ + Q_OBJECT +public: + explicit Hdata(QObject *parent = 0); + +signals: + +public slots: + +}; + +#endif // HDATA_H diff --git a/src/weechatprotocolhandler.cpp b/src/weechatprotocolhandler.cpp index 88f6369..1cc5dc1 100644 --- a/src/weechatprotocolhandler.cpp +++ b/src/weechatprotocolhandler.cpp @@ -8,6 +8,7 @@ #include #include "weechatprotocolhandler.h" +#include "weechat/dynamictypeexception.h" WeeChatProtocolHandler::WeeChatProtocolHandler(QObject* parent) : ProtocolHandler(parent), @@ -101,7 +102,7 @@ void WeeChatProtocolHandler::handleBufferLineAdded(QDataStream* data) } -void WeeChatProtocolHandler::handleUnknown(QDataStream *data) +void WeeChatProtocolHandler::handleUnknown(QDataStream* data) { } @@ -109,6 +110,50 @@ void WeeChatProtocolHandler::handleUnknown(QDataStream *data) // TYPES +QVariant WeeChatProtocolHandler::handleDynamicType(Type type, QDataStream* data) +{ + if (type == CHAR) + { + return QVariant(handleChar(data)); + } + else if (type == INTEGER) + { + return QVariant(handleInt(data)); + } + else if (type == LONG) + { + return QVariant(handleLong(data)); + } + else if (type == STRING) + { + return QVariant(handleString(data)); + } + else if (type == BUFFER) + { + return QVariant(handleBuffer(data)); + } + else if (type == POINTER) + { + return QVariant(handlePointer(data)); + } + else if (type == TIME) + { + return QVariant(handleTime(data)); + } + else if (type == HASHTABLE) + { + return QVariant(handleHashTable(data)); + } + else if (type == ARRAY) + { + return QVariant(handleArray(data)); + } + else + { + throw new DynamicTypeException("Cannot read hdata as QVariant."); + } +} + char WeeChatProtocolHandler::handleChar(QDataStream* data) { quint8 c; @@ -214,17 +259,16 @@ QDateTime WeeChatProtocolHandler::handleTime(QDataStream* data) return ret.fromMSecsSinceEpoch(timestamp); } -QHash WeeChatProtocolHandler::handleHashTable(QDataStream* data) +QHash WeeChatProtocolHandler::handleHashTable(QDataStream* data) { - QHash ret; + QHash ret; - // The hashtable first contains the types for the key and value, these - // are currently always 'str' - QString keyType = handleString(data); - QString valueType = handleString(data); + // The hashtable first contains the types for the key and value + Type keyType = readType(data); + Type valueType = readType(data); - Q_ASSERT_X(keyType == "str" && valueType == "str", - "HashTable::readFrom", "HashTable uses type that isn't string."); + Q_ASSERT_X(keyType == STRING, + "HashTable::readFrom", "HashTable uses non-string keys."); // Next is the length of the table as a 4-byte int qint32 length = 0; @@ -233,7 +277,7 @@ QHash WeeChatProtocolHandler::handleHashTable(QDataStream* dat for (qint32 i = 0; i < length; ++i) { QString key = handleString(data); - QString value = handleString(data); + QVariant value = handleDynamicType(valueType, data); ret.insert(key, value); } @@ -241,16 +285,78 @@ QHash WeeChatProtocolHandler::handleHashTable(QDataStream* dat return ret; } -QList WeeChatProtocolHandler::handleStringArray(QDataStream* data) +std::pair WeeChatProtocolHandler::handleInfo(QDataStream* data) { - QList ret; + // Info consists of a string key and a string value + QString key = handleString(data); + QString value = handleString(data); + return std::pair(key, value); +} + +std::pair > WeeChatProtocolHandler::handleInfoList(QDataStream* data) +{ + // Infolist consists of name, count and then name, type and value for each element + QString name = handleString(data); + qint32 length = handleInt(data); + + QHash values; + for (qint32 i = 0; i < length; ++i) + { + QString key = handleString(data); + Type type = readType(data); + QVariant value = handleDynamicType(type, data); + values.insert(key, value); + } + + return std::pair >(name, values); +} + +QList WeeChatProtocolHandler::handleArray(QDataStream* data) +{ + QList ret; // Array consists of type (string), number of elements (int 4 bytes) and data - QString type = handleString(data); + Type type = readType(data); qint32 length = handleInt(data); + + for (qint32 i = 0; i < length; ++i) + { + ret.append(handleDynamicType(type, data)); + } + + return ret; } -QList WeeChatProtocolHandler::handleIntegerArray(QDataStream* data) +WeeChatProtocolHandler::Type WeeChatProtocolHandler::readType(QDataStream* data) { + // Type is stored as three chars + QString type = ""; + type.append(handleChar(data)); + type.append(handleChar(data)); + type.append(handleChar(data)); + if (type == "chr") + return CHAR; + else if (type == "int") + return INTEGER; + else if (type == "lon") + return LONG; + else if (type == "str") + return STRING; + else if (type == "buf") + return BUFFER; + else if (type == "ptr") + return POINTER; + else if (type == "tim") + return TIME; + else if (type == "htb") + return HASHTABLE; + else if (type == "hda") + return HDATA; + else if (type == "inf") + return INFO; + else if (type == "inl") + return INFOLIST; + else //if (type == "arr") + return ARRAY; } diff --git a/src/weechatprotocolhandler.h b/src/weechatprotocolhandler.h index af6aadd..9b8e2d9 100644 --- a/src/weechatprotocolhandler.h +++ b/src/weechatprotocolhandler.h @@ -7,6 +7,7 @@ #ifndef WEECHATPROTOCOLHANDLER_H #define WEECHATPROTOCOLHANDLER_H +#include #include #include #include @@ -16,6 +17,21 @@ class WeeChatProtocolHandler : public ProtocolHandler { Q_OBJECT public: + enum Type { + CHAR, + INTEGER, + LONG, + STRING, + BUFFER, + POINTER, + TIME, + HASHTABLE, + HDATA, + INFO, + INFOLIST, + ARRAY + }; + explicit WeeChatProtocolHandler(QObject* parent = 0); void initialize(QString password); @@ -38,6 +54,7 @@ protected: void handleUnknown(QDataStream* data); // Individual object types + QVariant handleDynamicType(Type type, QDataStream* data); char handleChar(QDataStream* data); qint32 handleInt(QDataStream* data); qint64 handleLong(QDataStream* data); @@ -45,11 +62,13 @@ protected: QByteArray handleBuffer(QDataStream* data); QString handlePointer(QDataStream* data); QDateTime handleTime(QDataStream* data); - QHash handleHashTable(QDataStream* data); - // TODO: Hdata, Info, Infolist - QList handleStringArray(QDataStream* data); - QList handleIntegerArray(QDataStream* data); + QHash handleHashTable(QDataStream* data); + // TODO: Hdata + std::pair handleInfo(QDataStream* data); + std::pair> handleInfoList(QDataStream* data); + QList handleArray(QDataStream* data); + Type readType(QDataStream* data); bool readingBody;