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 += .
|
||||
|
||||
# Input
|
||||
HEADERS += protocol.h widget.h
|
||||
SOURCES += main.cpp protocol.cpp widget.cpp
|
||||
HEADERS += protocol.h widget.h protocol_commands.h
|
||||
SOURCES += main.cpp protocol.cpp widget.cpp protocol_commands.cpp
|
||||
|
||||
CONFIG += qt debug
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
#include "protocol.h"
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QDebug>
|
||||
#include "protocol.h"
|
||||
#include "protocol_commands.h"
|
||||
|
||||
QHash<QString, Command::NewCommandFunction> Command::commandHash;
|
||||
|
||||
Command::Command(const QString &_cmdName)
|
||||
: cmdName(_cmdName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Command::validateParameters()
|
||||
{
|
||||
}
|
||||
|
||||
bool Command::read(QXmlStreamReader &xml)
|
||||
|
@ -22,7 +20,7 @@ bool Command::read(QXmlStreamReader &xml)
|
|||
} else if (xml.isEndElement()) {
|
||||
qDebug() << "endElement: " << xml.name().toString();
|
||||
if (xml.name() == cmdName) {
|
||||
validateParameters();
|
||||
extractParameters();
|
||||
qDebug() << "FERTIG";
|
||||
deleteLater();
|
||||
return true;
|
||||
|
@ -53,3 +51,10 @@ void Command::write(QXmlStreamWriter &xml)
|
|||
|
||||
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 <QMap>
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
|
||||
class QXmlStreamReader;
|
||||
class QXmlStreamWriter;
|
||||
|
@ -11,54 +13,58 @@ class QXmlStreamWriter;
|
|||
class Command : public QObject {
|
||||
Q_OBJECT
|
||||
protected:
|
||||
typedef Command *(*NewCommandFunction)();
|
||||
static QHash<QString, NewCommandFunction> commandHash;
|
||||
|
||||
QString cmdName;
|
||||
QMap<QString, QString> parameters;
|
||||
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:
|
||||
Command(const QString &_cmdName);
|
||||
static void initializeHash();
|
||||
static Command *getNewCommand(const QString &name);
|
||||
virtual bool read(QXmlStreamReader &xml);
|
||||
virtual void write(QXmlStreamWriter &xml);
|
||||
void validateParameters();
|
||||
};
|
||||
|
||||
class Command_Ping : public Command {
|
||||
public:
|
||||
Command_Ping() : Command("ping") { }
|
||||
};
|
||||
class Command_ChatListChannels : public Command {
|
||||
public:
|
||||
Command_ChatListChannels() : Command("chat_list_channels") { }
|
||||
};
|
||||
class Command_ChatJoinChannel : public Command {
|
||||
class ChatCommand : public Command {
|
||||
Q_OBJECT
|
||||
private:
|
||||
QString channel;
|
||||
public:
|
||||
Command_ChatJoinChannel(const QString &_channel = QString()) : Command("chat_join_channel"), channel(_channel)
|
||||
protected:
|
||||
void extractParameters()
|
||||
{
|
||||
parameters.insert("channel", channel);
|
||||
channel = parameters["channel"];
|
||||
}
|
||||
};
|
||||
class Command_ChatLeaveChannel : public Command {
|
||||
private:
|
||||
QString channel;
|
||||
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);
|
||||
}
|
||||
};
|
||||
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);
|
||||
setParameter("channel", channel);
|
||||
}
|
||||
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
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
0:ping:Ping
|
||||
0:login:Login:s,username:s,password
|
||||
0:chat_list_channels:ChatListChannels
|
||||
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 "widget.h"
|
||||
#include "protocol.h"
|
||||
#include "protocol_commands.h"
|
||||
|
||||
Widget::Widget()
|
||||
: QMainWindow(), currentCommand(0)
|
||||
|
@ -24,6 +25,8 @@ Widget::Widget()
|
|||
QWidget *central = new QWidget;
|
||||
central->setLayout(vbox);
|
||||
setCentralWidget(central);
|
||||
|
||||
Command::initializeHash();
|
||||
}
|
||||
|
||||
void Widget::startClicked()
|
||||
|
@ -31,6 +34,7 @@ void Widget::startClicked()
|
|||
currentCommand = 0;
|
||||
xmlWriter.writeStartDocument();
|
||||
xmlWriter.writeStartElement("cockatrice_communication");
|
||||
xmlWriter.writeAttribute("version", "4");
|
||||
|
||||
Command *test = new Command_Ping;
|
||||
test->write(xmlWriter);
|
||||
|
@ -63,13 +67,8 @@ void Widget::parseXml()
|
|||
if (xmlReader.isStartElement()) {
|
||||
QString cmdStr = xmlReader.name().toString();
|
||||
qDebug() << "parseXml: startElement: " << cmdStr;
|
||||
if (cmdStr == "ping")
|
||||
currentCommand = new Command_Ping;
|
||||
else if (cmdStr == "chat_leave_channel")
|
||||
currentCommand = new Command_ChatLeaveChannel;
|
||||
else if (cmdStr == "chat_say")
|
||||
currentCommand = new Command_ChatSay;
|
||||
else
|
||||
currentCommand = Command::getNewCommand(cmdStr);
|
||||
if (!currentCommand)
|
||||
qDebug() << "unrecognized command";
|
||||
readCurrentCommand();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue