very dirty metacompiler for protocol information code
This commit is contained in:
parent
dbd3af8265
commit
b0841dd6e8
7 changed files with 163 additions and 103 deletions
|
@ -8,7 +8,7 @@ DEPENDPATH += .
|
||||||
INCLUDEPATH += .
|
INCLUDEPATH += .
|
||||||
|
|
||||||
# Input
|
# Input
|
||||||
HEADERS += protocol.h widget.h
|
HEADERS += protocol.h widget.h protocol_commands.h
|
||||||
SOURCES += main.cpp protocol.cpp widget.cpp
|
SOURCES += main.cpp protocol.cpp widget.cpp protocol_commands.cpp
|
||||||
|
|
||||||
CONFIG += qt debug
|
CONFIG += qt debug
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
#include "protocol.h"
|
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
#include <QXmlStreamWriter>
|
#include <QXmlStreamWriter>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include "protocol.h"
|
||||||
|
#include "protocol_commands.h"
|
||||||
|
|
||||||
|
QHash<QString, Command::NewCommandFunction> Command::commandHash;
|
||||||
|
|
||||||
Command::Command(const QString &_cmdName)
|
Command::Command(const QString &_cmdName)
|
||||||
: cmdName(_cmdName)
|
: cmdName(_cmdName)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Command::validateParameters()
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Command::read(QXmlStreamReader &xml)
|
bool Command::read(QXmlStreamReader &xml)
|
||||||
|
@ -22,7 +20,7 @@ bool Command::read(QXmlStreamReader &xml)
|
||||||
} else if (xml.isEndElement()) {
|
} else if (xml.isEndElement()) {
|
||||||
qDebug() << "endElement: " << xml.name().toString();
|
qDebug() << "endElement: " << xml.name().toString();
|
||||||
if (xml.name() == cmdName) {
|
if (xml.name() == cmdName) {
|
||||||
validateParameters();
|
extractParameters();
|
||||||
qDebug() << "FERTIG";
|
qDebug() << "FERTIG";
|
||||||
deleteLater();
|
deleteLater();
|
||||||
return true;
|
return true;
|
||||||
|
@ -53,3 +51,10 @@ void Command::write(QXmlStreamWriter &xml)
|
||||||
|
|
||||||
xml.writeEndElement();
|
xml.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Command *Command::getNewCommand(const QString &name)
|
||||||
|
{
|
||||||
|
if (!commandHash.contains(name))
|
||||||
|
return 0;
|
||||||
|
return commandHash.value(name)();
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
#include <QHash>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
class QXmlStreamReader;
|
class QXmlStreamReader;
|
||||||
class QXmlStreamWriter;
|
class QXmlStreamWriter;
|
||||||
|
@ -11,54 +13,58 @@ class QXmlStreamWriter;
|
||||||
class Command : public QObject {
|
class Command : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
protected:
|
protected:
|
||||||
|
typedef Command *(*NewCommandFunction)();
|
||||||
|
static QHash<QString, NewCommandFunction> commandHash;
|
||||||
|
|
||||||
QString cmdName;
|
QString cmdName;
|
||||||
QMap<QString, QString> parameters;
|
QMap<QString, QString> parameters;
|
||||||
QString currentElementText;
|
QString currentElementText;
|
||||||
|
void setParameter(const QString &name, const QString &value) { parameters[name] = value; }
|
||||||
|
void setParameter(const QString &name, bool value) { parameters[name] = (value ? "1" : "0"); }
|
||||||
|
void setParameter(const QString &name, int value) { parameters[name] = QString::number(value); }
|
||||||
|
virtual void extractParameters() { };
|
||||||
public:
|
public:
|
||||||
Command(const QString &_cmdName);
|
Command(const QString &_cmdName);
|
||||||
|
static void initializeHash();
|
||||||
|
static Command *getNewCommand(const QString &name);
|
||||||
virtual bool read(QXmlStreamReader &xml);
|
virtual bool read(QXmlStreamReader &xml);
|
||||||
virtual void write(QXmlStreamWriter &xml);
|
virtual void write(QXmlStreamWriter &xml);
|
||||||
void validateParameters();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Command_Ping : public Command {
|
class ChatCommand : public Command {
|
||||||
public:
|
Q_OBJECT
|
||||||
Command_Ping() : Command("ping") { }
|
|
||||||
};
|
|
||||||
class Command_ChatListChannels : public Command {
|
|
||||||
public:
|
|
||||||
Command_ChatListChannels() : Command("chat_list_channels") { }
|
|
||||||
};
|
|
||||||
class Command_ChatJoinChannel : public Command {
|
|
||||||
private:
|
private:
|
||||||
QString channel;
|
QString channel;
|
||||||
public:
|
protected:
|
||||||
Command_ChatJoinChannel(const QString &_channel = QString()) : Command("chat_join_channel"), channel(_channel)
|
void extractParameters()
|
||||||
{
|
{
|
||||||
parameters.insert("channel", channel);
|
channel = parameters["channel"];
|
||||||
}
|
}
|
||||||
};
|
|
||||||
class Command_ChatLeaveChannel : public Command {
|
|
||||||
private:
|
|
||||||
QString channel;
|
|
||||||
public:
|
public:
|
||||||
Command_ChatLeaveChannel(const QString &_channel = QString()) : Command("chat_leave_channel"), channel(_channel)
|
ChatCommand(const QString &_cmdName, const QString &_channel)
|
||||||
|
: Command(_cmdName), channel(_channel)
|
||||||
{
|
{
|
||||||
parameters.insert("channel", channel);
|
setParameter("channel", channel);
|
||||||
}
|
|
||||||
};
|
|
||||||
class Command_ChatSay : public Command {
|
|
||||||
private:
|
|
||||||
QString channel;
|
|
||||||
QString message;
|
|
||||||
public:
|
|
||||||
Command_ChatSay(const QString &_channel = QString(), const QString &_message = QString()) : Command("chat_say"), channel(_channel), message(_message)
|
|
||||||
{
|
|
||||||
parameters.insert("channel", channel);
|
|
||||||
parameters.insert("message", message);
|
|
||||||
}
|
}
|
||||||
|
QString getChannel() const { return channel; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GameCommand : public Command {
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
int gameId;
|
||||||
|
protected:
|
||||||
|
void extractParameters()
|
||||||
|
{
|
||||||
|
gameId = parameters["game_id"].toInt();
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
GameCommand(const QString &_cmdName, int _gameId)
|
||||||
|
: Command(_cmdName), gameId(_gameId)
|
||||||
|
{
|
||||||
|
setParameter("game_id", gameId);
|
||||||
|
}
|
||||||
|
int getGameId() const { return gameId; }
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
0:ping:Ping
|
||||||
0:login:Login:s,username:s,password
|
0:login:Login:s,username:s,password
|
||||||
0:chat_list_channels:ChatListChannels
|
0:chat_list_channels:ChatListChannels
|
||||||
0:chat_join_channel:ChatJoinChannel:s,channel
|
0:chat_join_channel:ChatJoinChannel:s,channel
|
|
@ -1,56 +0,0 @@
|
||||||
#!/usr/bin/perl
|
|
||||||
|
|
||||||
open(file, "protocol_info.dat");
|
|
||||||
while (<file>) {
|
|
||||||
s/\s+$//;
|
|
||||||
@line = split(/:/);
|
|
||||||
$type = shift(@line);
|
|
||||||
if ($type == 0) {
|
|
||||||
$baseClass = 'Command';
|
|
||||||
} elsif ($type == 1) {
|
|
||||||
$baseClass = 'ChatCommand';
|
|
||||||
} else {
|
|
||||||
$baseClass = 'GameCommand';
|
|
||||||
}
|
|
||||||
|
|
||||||
$name1 = shift(@line);
|
|
||||||
$className = 'Command_' . shift(@line);
|
|
||||||
print "class $className : public $baseClass {\n"
|
|
||||||
. "private:\n";
|
|
||||||
$paramStr1 = '';
|
|
||||||
$paramStr2 = '';
|
|
||||||
$paramStr3 = '';
|
|
||||||
$paramStr4 = '';
|
|
||||||
while ($param = shift(@line)) {
|
|
||||||
($key, $value) = split(/,/, $param);
|
|
||||||
$prettyVarName = $value;
|
|
||||||
if (!($paramStr1 eq '')) {
|
|
||||||
$paramStr1 .= ', ';
|
|
||||||
}
|
|
||||||
$paramStr2 .= ", $prettyVarName(_$prettyVarName)";
|
|
||||||
$paramStr3 .= "\t\tparameters.insert(\"$value\", $prettyVarName);\n";
|
|
||||||
if ($key == 'b') {
|
|
||||||
$dataType = 'bool';
|
|
||||||
$paramStr1 .= "bool _$prettyVarName = false";
|
|
||||||
} elsif ($key == 's') {
|
|
||||||
$dataType = 'QString';
|
|
||||||
$paramStr1 .= "const QString &_$prettyVarName = QString()";
|
|
||||||
} elsif ($key == 'i') {
|
|
||||||
$dataType = 'int';
|
|
||||||
$paramStr1 .= "int _$prettyVarName = -1";
|
|
||||||
}
|
|
||||||
$first = substr($prettyVarName, 0, 1);
|
|
||||||
$first =~ tr/a-z/A-Z/;
|
|
||||||
$prettyVarName2 = $first . substr($prettyVarName, 1, length($prettyVarName));
|
|
||||||
$paramStr4 .= "\t$dataType get$prettyVarName2() const { return $prettyVarName; }\n";
|
|
||||||
print "\t$dataType $value;\n";
|
|
||||||
}
|
|
||||||
print "public:\n";
|
|
||||||
print "\t$className($paramStr1)\n\t\t: $baseClass(\"$name1\")$paramStr2\n"
|
|
||||||
. "\t{\n";
|
|
||||||
print $paramStr3;
|
|
||||||
print "\t}\n";
|
|
||||||
print $paramStr4;
|
|
||||||
print "};\n";
|
|
||||||
}
|
|
||||||
close(file);
|
|
105
common/protocol_mc.pl
Executable file
105
common/protocol_mc.pl
Executable file
|
@ -0,0 +1,105 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
$initializeHash = '';
|
||||||
|
|
||||||
|
open(headerfile, ">protocol_commands.h");
|
||||||
|
print headerfile "#ifndef PROTOCOL_COMMANDS_H\n"
|
||||||
|
. "#define PROTOCOL_COMMANDS_H\n\n"
|
||||||
|
. "#include \"protocol.h\"\n\n";
|
||||||
|
|
||||||
|
open(cppfile, ">protocol_commands.cpp");
|
||||||
|
print cppfile "#include \"protocol.h\"\n"
|
||||||
|
. "#include \"protocol_commands.h\"\n\n";
|
||||||
|
|
||||||
|
open(file, "protocol_commands.dat");
|
||||||
|
while (<file>) {
|
||||||
|
s/\s+$//;
|
||||||
|
@line = split(/:/);
|
||||||
|
$type = shift(@line);
|
||||||
|
$name1 = shift(@line);
|
||||||
|
if ($type == 0) {
|
||||||
|
$baseClass = 'Command';
|
||||||
|
$parentConstructorCall = "$baseClass(\"$name1\")";
|
||||||
|
$constructorParamsH = "";
|
||||||
|
$constructorParamsCpp = "";
|
||||||
|
} elsif ($type == 1) {
|
||||||
|
$baseClass = 'ChatCommand';
|
||||||
|
$parentConstructorCall = "$baseClass(\"$name1\", _channel)";
|
||||||
|
$constructorParamsH = "const QString &_channel = QString()";
|
||||||
|
$constructorParamsCpp = "const QString &_channel";
|
||||||
|
} else {
|
||||||
|
$baseClass = 'GameCommand';
|
||||||
|
$parentConstructorCall = "$baseClass(\"$name1\", _gameId)";
|
||||||
|
$constructorParamsH = "int _gameId = -1";
|
||||||
|
$constructorParamsCpp = "int _gameId";
|
||||||
|
}
|
||||||
|
|
||||||
|
$className = 'Command_' . shift(@line);
|
||||||
|
print headerfile "class $className : public $baseClass {\n"
|
||||||
|
. "\tQ_OBJECT\n"
|
||||||
|
. "private:\n";
|
||||||
|
$paramStr2 = '';
|
||||||
|
$paramStr3 = '';
|
||||||
|
$paramStr4 = '';
|
||||||
|
$paramStr5 = '';
|
||||||
|
while ($param = shift(@line)) {
|
||||||
|
($key, $value) = split(/,/, $param);
|
||||||
|
($prettyVarName = $value) =~ s/_(.)/\U$1\E/g;
|
||||||
|
if (!($constructorParamsH eq '')) {
|
||||||
|
$constructorParamsH .= ', ';
|
||||||
|
}
|
||||||
|
if (!($constructorParamsCpp eq '')) {
|
||||||
|
$constructorParamsCpp .= ', ';
|
||||||
|
}
|
||||||
|
$paramStr2 .= ", $prettyVarName(_$prettyVarName)";
|
||||||
|
$paramStr3 .= "\tsetParameter(\"$value\", $prettyVarName);\n";
|
||||||
|
if ($key eq 'b') {
|
||||||
|
$dataType = 'bool';
|
||||||
|
$constructorParamsH .= "bool _$prettyVarName = false";
|
||||||
|
$constructorParamsCpp .= "bool _$prettyVarName";
|
||||||
|
$paramStr5 .= "\t$prettyVarName = (parameters[\"$value\"] == \"1\");\n";
|
||||||
|
} elsif ($key eq 's') {
|
||||||
|
$dataType = 'QString';
|
||||||
|
$constructorParamsH .= "const QString &_$prettyVarName = QString()";
|
||||||
|
$constructorParamsCpp .= "const QString &_$prettyVarName";
|
||||||
|
$paramStr5 .= "\t$prettyVarName = parameters[\"$value\"];\n";
|
||||||
|
} elsif ($key eq 'i') {
|
||||||
|
$dataType = 'int';
|
||||||
|
$constructorParamsH .= "int _$prettyVarName = -1";
|
||||||
|
$constructorParamsCpp .= "int _$prettyVarName";
|
||||||
|
$paramStr5 .= "\t$prettyVarName = parameters[\"$value\"].toInt();\n";
|
||||||
|
}
|
||||||
|
($prettyVarName2 = $prettyVarName) =~ s/^(.)/\U$1\E/;
|
||||||
|
$paramStr4 .= "\t$dataType get$prettyVarName2() const { return $prettyVarName; }\n";
|
||||||
|
print headerfile "\t$dataType $prettyVarName;\n";
|
||||||
|
}
|
||||||
|
print headerfile "public:\n"
|
||||||
|
. "\t$className($constructorParamsH);\n"
|
||||||
|
. $paramStr4
|
||||||
|
. "\tstatic Command *newCommand() { return new $className; }\n"
|
||||||
|
. ($paramStr5 eq '' ? '' : "protected:\n\tvoid extractParameters();\n")
|
||||||
|
. "};\n";
|
||||||
|
print cppfile $className . "::$className($constructorParamsCpp)\n"
|
||||||
|
. "\t: $parentConstructorCall$paramStr2\n"
|
||||||
|
. "{\n"
|
||||||
|
. $paramStr3
|
||||||
|
. "}\n";
|
||||||
|
if (!($paramStr5 eq '')) {
|
||||||
|
print cppfile "void $className" . "::extractParameters()\n"
|
||||||
|
. "{\n"
|
||||||
|
. "\t$baseClass" . "::extractParameters();\n"
|
||||||
|
. $paramStr5
|
||||||
|
. "}\n";
|
||||||
|
}
|
||||||
|
$initializeHash .= "\tcommandHash.insert(\"$name1\", $className" . "::newCommand);\n";
|
||||||
|
}
|
||||||
|
close(file);
|
||||||
|
|
||||||
|
print headerfile "\n#endif\n";
|
||||||
|
close(headerfile);
|
||||||
|
|
||||||
|
print cppfile "void Command::initializeHash()\n"
|
||||||
|
. "{\n"
|
||||||
|
. $initializeHash
|
||||||
|
. "}\n";
|
||||||
|
close(cppfile);
|
|
@ -2,6 +2,7 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "widget.h"
|
#include "widget.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
|
#include "protocol_commands.h"
|
||||||
|
|
||||||
Widget::Widget()
|
Widget::Widget()
|
||||||
: QMainWindow(), currentCommand(0)
|
: QMainWindow(), currentCommand(0)
|
||||||
|
@ -24,6 +25,8 @@ Widget::Widget()
|
||||||
QWidget *central = new QWidget;
|
QWidget *central = new QWidget;
|
||||||
central->setLayout(vbox);
|
central->setLayout(vbox);
|
||||||
setCentralWidget(central);
|
setCentralWidget(central);
|
||||||
|
|
||||||
|
Command::initializeHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::startClicked()
|
void Widget::startClicked()
|
||||||
|
@ -31,6 +34,7 @@ void Widget::startClicked()
|
||||||
currentCommand = 0;
|
currentCommand = 0;
|
||||||
xmlWriter.writeStartDocument();
|
xmlWriter.writeStartDocument();
|
||||||
xmlWriter.writeStartElement("cockatrice_communication");
|
xmlWriter.writeStartElement("cockatrice_communication");
|
||||||
|
xmlWriter.writeAttribute("version", "4");
|
||||||
|
|
||||||
Command *test = new Command_Ping;
|
Command *test = new Command_Ping;
|
||||||
test->write(xmlWriter);
|
test->write(xmlWriter);
|
||||||
|
@ -63,13 +67,8 @@ void Widget::parseXml()
|
||||||
if (xmlReader.isStartElement()) {
|
if (xmlReader.isStartElement()) {
|
||||||
QString cmdStr = xmlReader.name().toString();
|
QString cmdStr = xmlReader.name().toString();
|
||||||
qDebug() << "parseXml: startElement: " << cmdStr;
|
qDebug() << "parseXml: startElement: " << cmdStr;
|
||||||
if (cmdStr == "ping")
|
currentCommand = Command::getNewCommand(cmdStr);
|
||||||
currentCommand = new Command_Ping;
|
if (!currentCommand)
|
||||||
else if (cmdStr == "chat_leave_channel")
|
|
||||||
currentCommand = new Command_ChatLeaveChannel;
|
|
||||||
else if (cmdStr == "chat_say")
|
|
||||||
currentCommand = new Command_ChatSay;
|
|
||||||
else
|
|
||||||
qDebug() << "unrecognized command";
|
qDebug() << "unrecognized command";
|
||||||
readCurrentCommand();
|
readCurrentCommand();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue