diff --git a/common/common.pro b/common/common.pro index b4256651..1a29dd56 100644 --- a/common/common.pro +++ b/common/common.pro @@ -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 diff --git a/common/protocol.cpp b/common/protocol.cpp index 43186ef0..bef71c0f 100644 --- a/common/protocol.cpp +++ b/common/protocol.cpp @@ -1,16 +1,14 @@ -#include "protocol.h" #include #include #include +#include "protocol.h" +#include "protocol_commands.h" + +QHash 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)(); +} diff --git a/common/protocol.h b/common/protocol.h index 4c92c3ba..d4e17a38 100644 --- a/common/protocol.h +++ b/common/protocol.h @@ -3,7 +3,9 @@ #include #include +#include #include +#include class QXmlStreamReader; class QXmlStreamWriter; @@ -11,54 +13,58 @@ class QXmlStreamWriter; class Command : public QObject { Q_OBJECT protected: + typedef Command *(*NewCommandFunction)(); + static QHash commandHash; + QString cmdName; QMap 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 diff --git a/common/protocol_info.dat b/common/protocol_commands.dat similarity index 97% rename from common/protocol_info.dat rename to common/protocol_commands.dat index 7eb44b98..2b3314d1 100644 --- a/common/protocol_info.dat +++ b/common/protocol_commands.dat @@ -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 diff --git a/common/protocol_info.pl b/common/protocol_info.pl deleted file mode 100755 index fd022a0f..00000000 --- a/common/protocol_info.pl +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/perl - -open(file, "protocol_info.dat"); -while () { - 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); diff --git a/common/protocol_mc.pl b/common/protocol_mc.pl new file mode 100755 index 00000000..24230f1a --- /dev/null +++ b/common/protocol_mc.pl @@ -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 () { + 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); diff --git a/common/widget.cpp b/common/widget.cpp index 07c938b5..81fee7e3 100644 --- a/common/widget.cpp +++ b/common/widget.cpp @@ -2,6 +2,7 @@ #include #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(); }