Skip to content

Instantly share code, notes, and snippets.

@talhaHavadar
Created October 5, 2020 19:27
Show Gist options
  • Save talhaHavadar/15790c5de70f034b6d8cb3f677aa6d90 to your computer and use it in GitHub Desktop.
Save talhaHavadar/15790c5de70f034b6d8cb3f677aa6d90 to your computer and use it in GitHub Desktop.
QT Generic Binary Data Parser Implementation
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>
#include "packet.h"
#include "packetparser.h"
#include "packetprocessor.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
PacketProcessor pp;
TemperaturePacketParser tempParser;
pp.addParser(&tempParser);
QByteArray ba;
ba.append((char)0);
ba.append((char)0);
ba.append((char)0);
ba.append((char)1);
ba.append((char)0);
ba.append((char)0);
ba.append((char)0);
ba.append(100);
pp.processPackets(ba);
return app.exec();
}
#include "packet.h"
void TemperaturePacket::read(QDataStream &data)
{
quint32 val;
data >> val;
this->setValue(val);
}
void TemperaturePacket::write(QDataStream &data) const
{
data << this->value();
}
void VelocityPacket::read(QDataStream &data)
{
quint32 val;
data >> val;
this->setValue(val);
}
void VelocityPacket::write(QDataStream &data) const
{
data << this->value();
}
#ifndef PACKET_H
#define PACKET_H
#include <QtGlobal>
#include <QDataStream>
#include <QDebug>
enum class PacketType
{
TEMPERATURE = 0x1,
VELOCITY = 0x2
};
class Packet
{
public:
Packet(PacketType type): m_type{type} {}
virtual ~Packet() { qDebug() << "Packet Destructor\n"; }
virtual void read(QDataStream& data) = 0;
virtual void write(QDataStream& data) const = 0;
const PacketType& type() const { return m_type; }
private:
const PacketType m_type;
};
class TemperaturePacket: public Packet
{
public:
TemperaturePacket(): Packet(PacketType::TEMPERATURE) {}
virtual ~TemperaturePacket() { qDebug() << "TemperaturePacket Destructor\n"; }
void read(QDataStream &data) override;
void write(QDataStream &data) const override;
void setValue(const quint32& value) { m_value = value; }
const quint32& value() const { return m_value; }
private:
quint32 m_value;
};
class VelocityPacket: public Packet
{
public:
VelocityPacket(): Packet(PacketType::VELOCITY) {}
virtual ~VelocityPacket() { qDebug() << "VelocityPacket Destructor\n"; }
void read(QDataStream &data) override;
void write(QDataStream &data) const override;
void setValue(const quint32& value) { m_value = value; }
const quint32& value() const { return m_value; }
private:
quint32 m_value;
};
#endif // PACKET_H
#include "packetparser.h"
#include <QDebug>
std::unique_ptr<Packet> TemperaturePacketParser::parse(QDataStream &data)
{
std::unique_ptr<TemperaturePacket> tempPacket = std::make_unique<TemperaturePacket>();
tempPacket->read(data);
return tempPacket;
}
#ifndef PACKETPARSER_H
#define PACKETPARSER_H
#include "packet.h"
#include <memory>
#include <QDataStream>
class PacketParser
{
public:
PacketParser(const PacketType& type): m_type{type} {};
virtual ~PacketParser() {}
virtual std::unique_ptr<Packet> parse(QDataStream& data) = 0;
const PacketType& type() const { return m_type; }
private:
const PacketType m_type;
};
class TemperaturePacketParser: public PacketParser
{
public:
TemperaturePacketParser(): PacketParser(PacketType::TEMPERATURE) {}
virtual ~TemperaturePacketParser() {}
std::unique_ptr<Packet> parse(QDataStream &data) override;
};
#endif // PACKETPARSER_H
#include "packetprocessor.h"
#include <QDataStream>
#include <QDebug>
void PacketProcessor::processPackets(QByteArray &data)
{
QDataStream io (data);
while(!io.atEnd())
{
quint32 type = 0;
io >> type;
qDebug() << "type: " << type << "\n";
PacketParser* const parser = m_parsers->value((PacketType) type, nullptr);
if (parser != nullptr)
{
TemperaturePacket* tmpPkt;
std::unique_ptr<Packet> packet = parser->parse(io);
if ((tmpPkt = dynamic_cast<TemperaturePacket*>(packet.get())))
{
qDebug() << "tmpPkt.value: " << tmpPkt->value() << "\n";
}
qDebug() << "packet type: " << (int) packet->type() << "\n";
}
}
}
#ifndef PACKETPROCESSOR_H
#define PACKETPROCESSOR_H
#include <QMap>
#include "packetparser.h"
class PacketProcessor
{
public:
PacketProcessor() {
m_parsers = new QMap<PacketType, PacketParser*>();
};
virtual ~PacketProcessor() {
delete m_parsers;
}
void addParser(PacketParser* parser) { m_parsers->insert(parser->type(), parser); }
void processPackets(QByteArray& data);
private:
QMap<PacketType, PacketParser*>* m_parsers;
};
#endif // PACKETPROCESSOR_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment