Rewrite type handling to be simpler, get rid of OO hierarchy

This commit is contained in:
Mikko Ahlroth 2014-06-30 09:41:17 +03:00
parent 840a50e54b
commit 4a8945d38d
34 changed files with 173 additions and 519 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
harbour-weechatrelay.pro.user harbour-weechatrelay.pro.user
*pro.user*

View file

@ -16,21 +16,7 @@ SOURCES += src/harbour-weechatrelay.cpp \
src/connectionhandler.cpp \ src/connectionhandler.cpp \
src/weechatprotocolhandler.cpp \ src/weechatprotocolhandler.cpp \
src/protocolhandler.cpp \ src/protocolhandler.cpp \
src/qsslcertificateinfo.cpp \ src/qsslcertificateinfo.cpp
src/weechatproto/protocoltype.cpp \
src/weechatproto/hashtable.cpp \
src/weechatproto/hdata.cpp \
src/weechatproto/info.cpp \
src/weechatproto/infolist.cpp \
src/weechatproto/array.cpp \
src/weechatproto/time.cpp \
src/weechatproto/pointer.cpp \
src/weechatproto/buffer.cpp \
src/weechatproto/string.cpp \
src/weechatproto/long.cpp \
src/weechatproto/integer.cpp \
src/weechatproto/char.cpp \
src/weechatproto/protocoltypeoverwriteexception.cpp
OTHER_FILES += qml/harbour-weechatrelay.qml \ OTHER_FILES += qml/harbour-weechatrelay.qml \
rpm/harbour-weechatrelay.spec \ rpm/harbour-weechatrelay.spec \
@ -55,21 +41,7 @@ HEADERS += \
src/protocolhandler.h \ src/protocolhandler.h \
src/weechatprotocolhandler.h \ src/weechatprotocolhandler.h \
src/connectresolver.h \ src/connectresolver.h \
src/qsslcertificateinfo.h \ src/qsslcertificateinfo.h
src/weechatproto/protocoltype.h \
src/weechatproto/hashtable.h \
src/weechatproto/hdata.h \
src/weechatproto/info.h \
src/weechatproto/infolist.h \
src/weechatproto/array.h \
src/weechatproto/time.h \
src/weechatproto/pointer.h \
src/weechatproto/buffer.h \
src/weechatproto/string.h \
src/weechatproto/long.h \
src/weechatproto/integer.h \
src/weechatproto/char.h \
src/weechatproto/protocoltypeoverwriteexception.h
QT += network QT += network

View file

@ -17,7 +17,7 @@ Version: 0.1
Release: 1 Release: 1
Group: Qt/Qt Group: Qt/Qt
License: MIT Expat licence License: MIT Expat licence
URL: http://example.org/ URL: https://bitbucket.org/vincit/harbour-weechatrelay
Source0: %{name}-%{version}.tar.bz2 Source0: %{name}-%{version}.tar.bz2
Source100: harbour-weechatrelay.yaml Source100: harbour-weechatrelay.yaml
Requires: sailfishsilica-qt5 >= 0.10.9 Requires: sailfishsilica-qt5 >= 0.10.9
@ -28,7 +28,7 @@ BuildRequires: pkgconfig(sailfishapp) >= 0.0.10
BuildRequires: desktop-file-utils BuildRequires: desktop-file-utils
%description %description
WeeCRApp (WeeChat Relay App) is a WeeChat relay client app for Sailfish OS. WeeCRApp (WeeChat Relay App) is a WeeChat relay client for Sailfish OS.
%prep %prep
%setup -q -n %{name}-%{version} %setup -q -n %{name}-%{version}

View file

@ -3,11 +3,11 @@ Summary: WeeCRApp
Version: 0.1 Version: 0.1
Release: 1 Release: 1
Group: Qt/Qt Group: Qt/Qt
URL: http://example.org/ URL: https://bitbucket.org/vincit/harbour-weechatrelay
License: MIT Expat licence License: MIT Expat licence
Sources: Sources:
- '%{name}-%{version}.tar.bz2' - '%{name}-%{version}.tar.bz2'
Description: "WeeCRApp (WeeChat Relay App) is a WeeChat relay client app for Sailfish Description: "WeeCRApp (WeeChat Relay App) is a WeeChat relay client for Sailfish
OS." OS."
Configure: none Configure: none
Builder: qtc5 Builder: qtc5

View file

@ -1,5 +0,0 @@
#include "array.h"
Array::Array()
{
}

View file

@ -1,12 +0,0 @@
#ifndef ARRAY_H
#define ARRAY_H
#include "protocoltype.h"
class Array : public ProtocolType
{
public:
Array();
};
#endif // ARRAY_H

View file

@ -1,28 +0,0 @@
#include "buffer.h"
Buffer::Buffer(): data(0)
{
}
void Buffer::readFrom(QDataStream* data)
{
ProtocolType::markRead();
// Buffer is the same as string, but just bytes
quint32 length;
*data >> length;
this->data = new QByteArray();
quint8 current;
for (quint32 i = 0; i < length; ++i)
{
*data >> current;
this->data->append(static_cast<char>(current));
}
}
const QByteArray* Buffer::getBytes() const
{
return this->data;
}

View file

@ -1,17 +0,0 @@
#ifndef BUFFER_H
#define BUFFER_H
#include "protocoltype.h"
class Buffer : public ProtocolType
{
public:
Buffer();
void readFrom(QDataStream* data);
const QByteArray* getBytes() const;
private:
QByteArray* data;
};
#endif // BUFFER_H

View file

@ -1,24 +0,0 @@
#include "char.h"
Char::Char(): data(' ')
{
}
void Char::readFrom(QDataStream* data)
{
ProtocolType::markRead();
quint8 c;
*data >> c;
this->data = static_cast<char>(c);
}
char Char::getChar() const
{
return this->data;
}
std::size_t Char::hash() const
{
return data * 2654435761 % 2^32;
}

View file

@ -1,20 +0,0 @@
#ifndef CHAR_H
#define CHAR_H
#include "protocoltype.h"
class Char : public ProtocolType
{
public:
Char();
void readFrom(QDataStream* data);
char getChar() const;
std::size_t hash() const;
private:
char data;
};
#endif // CHAR_H

View file

@ -1,10 +0,0 @@
#include "hashtable.h"
HashTable::HashTable()
{
}
void HashTable::readFrom(QDataStream* data)
{
ProtocolType::markRead();
}

View file

@ -1,17 +0,0 @@
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include "protocoltype.h"
#include <unordered_map>
class HashTable : public ProtocolType
{
public:
HashTable();
void readFrom(QDataStream* data);
private:
};
#endif // HASHTABLE_H

View file

@ -1,5 +0,0 @@
#include "hdata.h"
HData::HData()
{
}

View file

@ -1,12 +0,0 @@
#ifndef HDATA_H
#define HDATA_H
#include "protocoltype.h"
class HData : public ProtocolType
{
public:
HData();
};
#endif // HDATA_H

View file

@ -1,5 +0,0 @@
#include "info.h"
Info::Info()
{
}

View file

@ -1,12 +0,0 @@
#ifndef INFO_H
#define INFO_H
#include "protocoltype.h"
class Info : public ProtocolType
{
public:
Info();
};
#endif // INFO_H

View file

@ -1,5 +0,0 @@
#include "infolist.h"
InfoList::InfoList()
{
}

View file

@ -1,12 +0,0 @@
#ifndef INFOLIST_H
#define INFOLIST_H
#include "protocoltype.h"
class InfoList : public ProtocolType
{
public:
InfoList();
};
#endif // INFOLIST_H

View file

@ -1,17 +0,0 @@
#include "integer.h"
Integer::Integer(): data(0)
{
}
void Integer::readFrom(QDataStream* data)
{
ProtocolType::markRead();
*data >> this->data;
}
qint32 Integer::getInt() const
{
return this->data;
}

View file

@ -1,17 +0,0 @@
#ifndef INTEGER_H
#define INTEGER_H
#include "protocoltype.h"
class Integer : public ProtocolType
{
public:
Integer();
void readFrom(QDataStream* data);
qint32 getInt() const;
private:
qint32 data;
};
#endif // INTEGER_H

View file

@ -1,50 +0,0 @@
#include "long.h"
Long::Long(): data(0)
{
}
void Long::readFrom(QDataStream* data)
{
ProtocolType::markRead();
// Long is stored as a string, with one byte showing the length
quint8 length;
*data >> length;
quint8 current;
qint8 magnitude = 1;
for (quint8 i = 0; i < length; ++i)
{
*data >> current;
if (i == 0)
{
if (current == 45) // ASCII '-'
{
magnitude = -1;
}
}
else
{
this->data *= 10;
}
this->data += magnitude * static_cast<qint64>(current - '0');
}
}
qint64 Long::getLong() const
{
return this->data;
}
std::size_t Long::hash() const
{
return data * 2654435761 % 2^32;
}
bool Long::operator==(const Long& other) const
{
return (other.getLong() == this->data);
}

View file

@ -1,19 +0,0 @@
#ifndef LONG_H
#define LONG_H
#include "protocoltype.h"
class Long : public ProtocolType
{
public:
Long();
void readFrom(QDataStream* data);
qint64 getLong() const;
std::size_t hash() const;
bool operator==(const Long& other) const;
private:
qint64 data;
};
#endif // LONG_H

View file

@ -1,28 +0,0 @@
#include "pointer.h"
Pointer::Pointer(): data(0)
{
}
void Pointer::readFrom(QDataStream* data)
{
ProtocolType::markRead();
// Pointers are stored as length (1 byte) + data as hex string
quint8 length;
*data >> length;
this->data = new QString();
quint8 current;
for (quint8 i = 0; i < length; ++i)
{
*data >> current;
this->data->append(static_cast<char>(current));
}
}
const QString* Pointer::getPointer() const
{
return this->data;
}

View file

@ -1,17 +0,0 @@
#ifndef POINTER_H
#define POINTER_H
#include "protocoltype.h"
class Pointer : public ProtocolType
{
public:
Pointer();
void readFrom(QDataStream* data);
const QString* getPointer() const;
private:
QString* data;
};
#endif // POINTER_H

View file

@ -1,19 +0,0 @@
#include "protocoltype.h"
#include "protocoltypeoverwriteexception.h"
ProtocolType::ProtocolType(): isRead(false)
{
}
// Mark this object as read, so that the values can't
// be overwritten. A second call to this method will throw
// an exception.
void ProtocolType::markRead()
{
if (isRead)
{
throw new ProtocolTypeOverWriteException("Cannot overwrite ProtocolType.");
}
isRead = true;
}

View file

@ -1,22 +0,0 @@
#ifndef PROTOCOLTYPE_H
#define PROTOCOLTYPE_H
#include <QDataStream>
#include <cstddef>
class ProtocolType
{
public:
ProtocolType();
virtual void readFrom(QDataStream* data) = 0;
void markRead();
// For hashtable
virtual std::size_t hash() const = 0;
private:
bool isRead;
};
#endif // PROTOCOLTYPE_H

View file

@ -1,6 +0,0 @@
#include "protocoltypeoverwriteexception.h"
ProtocolTypeOverWriteException::ProtocolTypeOverWriteException(const std::string& reason):
std::runtime_error(reason)
{
}

View file

@ -1,13 +0,0 @@
#ifndef PROTOCOLTYPEOVERWRITEEXCEPTION_H
#define PROTOCOLTYPEOVERWRITEEXCEPTION_H
#include <stdexcept>
#include <string>
class ProtocolTypeOverWriteException : public std::runtime_error
{
public:
explicit ProtocolTypeOverWriteException(const std::string& reason);
};
#endif // PROTOCOLTYPEOVERWRITEEXCEPTION_H

View file

@ -1,28 +0,0 @@
#include "string.h"
String::String(): data(0)
{
}
void String::readFrom(QDataStream* data)
{
ProtocolType::markRead();
// Strings are stored as length (4 bytes) + data (no \0)
quint32 length;
*data >> length;
this->data = new QString();
quint8 current;
for (quint32 i = 0; i < length; ++i)
{
*data >> current;
this->data->append(static_cast<char>(current));
}
}
const QString* String::getString() const
{
return this->data;
}

View file

@ -1,17 +0,0 @@
#ifndef STRING_H
#define STRING_H
#include "protocoltype.h"
class String : public ProtocolType
{
public:
String();
void readFrom(QDataStream* data);
const QString* getString() const;
private:
QString* data;
};
#endif // STRING_H

View file

@ -1,25 +0,0 @@
#include "time.h"
#include "long.h"
Time::Time(): data(0)
{
}
void Time::readFrom(QDataStream* data)
{
ProtocolType::markRead();
// Time is stored as length (1 byte) + data (unix time)
// It's the same format as a Long so we will read it that way
Long* timelong = new Long();
timelong->readFrom(data);
quint64 timestamp = timelong->getLong();
this->data = new QDateTime();
this->data->fromTime_t(timestamp);
}
const QDateTime* Time::getTime() const
{
return this->data;
}

View file

@ -1,19 +0,0 @@
#ifndef TIME_H
#define TIME_H
#include "protocoltype.h"
#include <QDateTime>
class Time : public ProtocolType
{
public:
Time();
void readFrom(QDataStream* data);
const QDateTime* getTime() const;
private:
QDateTime* data;
};
#endif // TIME_H

View file

@ -93,7 +93,164 @@ void WeeChatProtocolHandler::handleBody(QDataStream* data)
delete idData; delete idData;
} }
// EVENTS
void WeeChatProtocolHandler::handleBufferLineAdded(QDataStream* data) void WeeChatProtocolHandler::handleBufferLineAdded(QDataStream* data)
{ {
} }
void WeeChatProtocolHandler::handleUnknown(QDataStream *data)
{
}
// TYPES
char WeeChatProtocolHandler::handleChar(QDataStream* data)
{
quint8 c;
*data >> c;
return static_cast<char>(c);
}
qint32 WeeChatProtocolHandler::handleInt(QDataStream* data)
{
qint32 ret;
*data >> ret;
return ret;
}
qint64 WeeChatProtocolHandler::handleLong(QDataStream* data)
{
// Long is stored as a string, with one byte showing the length
qint64 ret = 0;
quint8 length;
*data >> length;
quint8 current;
qint8 magnitude = 1;
for (quint8 i = 0; i < length; ++i)
{
*data >> current;
if (i == 0)
{
if (current == 45) // ASCII '-'
{
magnitude = -1;
}
}
else
{
ret *= 10;
}
ret += magnitude * static_cast<qint64>(current - '0');
}
return ret;
}
QString WeeChatProtocolHandler::handleString(QDataStream* data)
{
// Strings are stored as length (4 bytes) + data (no \0)
QString ret;
quint32 length;
*data >> length;
quint8 current;
for (quint32 i = 0; i < length; ++i)
{
*data >> current;
ret.append(static_cast<char>(current));
}
return ret;
}
QByteArray WeeChatProtocolHandler::handleBuffer(QDataStream* data)
{
// Buffer is the same as string, but just bytes
QByteArray ret;
quint32 length;
*data >> length;
quint8 current;
for (quint32 i = 0; i < length; ++i)
{
*data >> current;
ret.append(static_cast<char>(current));
}
return ret;
}
QString WeeChatProtocolHandler::handlePointer(QDataStream* data)
{
// Pointers are stored as length (1 byte) + data as hex string
QString ret;
quint8 length;
*data >> length;
quint8 current;
for (quint8 i = 0; i < length; ++i)
{
*data >> current;
ret.append(static_cast<char>(current));
}
return ret;
}
QDateTime WeeChatProtocolHandler::handleTime(QDataStream* data)
{
// Time is stored as length (1 byte) + data (unix time)
// It's the same format as a Long so we will read it that way
QDateTime ret;
quint64 timestamp = static_cast<quint64>(handleLong(data));
return ret.fromMSecsSinceEpoch(timestamp);
}
QHash<QString, QString> WeeChatProtocolHandler::handleHashTable(QDataStream* data)
{
QHash<QString, QString> 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);
Q_ASSERT_X(keyType == "str" && valueType == "str",
"HashTable::readFrom", "HashTable uses type that isn't string.");
// Next is the length of the table as a 4-byte int
qint32 length = 0;
*data >> length;
for (qint32 i = 0; i < length; ++i)
{
QString key = handleString(data);
QString value = handleString(data);
ret.insert(key, value);
}
return ret;
}
QList<QString> WeeChatProtocolHandler::handleStringArray(QDataStream* data)
{
QList<QString> ret;
// Array consists of type (string), number of elements (int 4 bytes) and data
QString type = handleString(data);
qint32 length = handleInt(data);
}
QList<qint32> WeeChatProtocolHandler::handleIntegerArray(QDataStream* data)
{
}

View file

@ -9,6 +9,7 @@
#include <QObject> #include <QObject>
#include <QDateTime> #include <QDateTime>
#include <QHash>
#include "protocolhandler.h" #include "protocolhandler.h"
class WeeChatProtocolHandler : public ProtocolHandler class WeeChatProtocolHandler : public ProtocolHandler
@ -40,10 +41,14 @@ protected:
char handleChar(QDataStream* data); char handleChar(QDataStream* data);
qint32 handleInt(QDataStream* data); qint32 handleInt(QDataStream* data);
qint64 handleLong(QDataStream* data); qint64 handleLong(QDataStream* data);
QString* handleString(QDataStream* data); QString handleString(QDataStream* data);
QByteArray* handleBuffer(QDataStream* data); QByteArray handleBuffer(QDataStream* data);
QString* handlePointer(QDataStream* data); QString handlePointer(QDataStream* data);
QDateTime* handleTime(QDataStream* data); QDateTime handleTime(QDataStream* data);
QHash<QString, QString> handleHashTable(QDataStream* data);
// TODO: Hdata, Info, Infolist
QList<QString> handleStringArray(QDataStream* data);
QList<qint32> handleIntegerArray(QDataStream* data);
bool readingBody; bool readingBody;