Skip to content

Commit

Permalink
Refactoring/reimplementation of MXP support (Mudlet#3625)
Browse files Browse the repository at this point in the history
    Refactoring/reimplementation of MXP protocol
        Extracts MXP support from TBuffer
        Separates input parsing from protocol processing: input is parsed into MxpTag objects by the MxpNodeBuilder and are passed to be handled by the MxpTagProcessor
        Class hierarchy of MxpTagHandler for implementing support for each tag: allows for a clear separation of the implementation of each tag and makes it easier for adding support for new tags
        Defines a clear interface (MxpClient) separating the MXP implementation from other parts of the code
        Solves some limitations of previous implementation such as supporting element definitions not only for<SEND> tags, interpolating named and positional attributes and interpolating &text; placeholder by tag content
        Includes support for COLOR tag
        Handles FONT, U, I, B, VAR and !ENTITY tags, but so far no defined behavior (can be implemented in MxpMudlet)
        Attributes that hold MXP state are now in the Host class to avoid needless copies when TBuffer is copied around
        Introduces QtTests for some of the classes
    Other refactorings intended to simplify TBuffer class, extracting responbilities that aren't directly related to the buffer mgmt
        Extracted TEncodingTable from TBuffer, this class is responsible for mapping encoding names to tables. It also removes some bloat from TBuffer.
        TLinkStore to manage links and associated hints to be displayed.
        TEntityResolver to map character entities, such as &gt; &Mudlet#32; &#x20; to their associated string values; supports interpolating strings replacing the entity placeholders by their values
  • Loading branch information
gcms authored May 3, 2020
1 parent 59ceff9 commit 102491a
Show file tree
Hide file tree
Showing 72 changed files with 5,491 additions and 1,293 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ add_subdirectory(3rdparty/edbee-lib/edbee-lib)
add_subdirectory(3rdparty/communi)
add_subdirectory(translations/translated)
add_subdirectory(src)
add_subdirectory(test)

if(USE_UPDATER)
add_subdirectory(3rdparty/dblsqd)
Expand Down
52 changes: 52 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,45 @@ set(mudlet_SRCS
TDebug.cpp
TDockWidget.cpp
TEasyButtonBar.cpp
TEncodingTable.cpp
TEntityHandler.cpp
TEntityResolver.cpp
TFlipButton.cpp
TForkedProcess.cpp
TimerUnit.cpp
TKey.cpp
TLabel.cpp
TLinkStore.cpp
TLuaInterpreter.cpp
TMap.cpp
TMedia.cpp
TMxpElementDefinitionHandler.cpp
TMxpElementRegistry.cpp
TMxpFormattingTagsHandler.cpp
TMxpBRTagHandler.cpp
TMxpColorTagHandler.cpp
TMxpCustomElementTagHandler.cpp
TMxpEntityTagHandler.cpp
TMxpFontTagHandler.cpp
TMxpLinkTagHandler.cpp
TMxpNodeBuilder.cpp
TMxpMudlet.cpp
TMxpProcessor.cpp
TMxpSendTagHandler.cpp
TMxpSupportTagHandler.cpp
MxpTag.cpp
TMxpTagHandler.cpp
TMxpTagParser.cpp
TMxpTagProcessor.cpp
TMxpVarTagHandler.cpp
TMxpVersionTagHandler.cpp
TriggerUnit.cpp
TRoom.cpp
TRoomDB.cpp
TScript.cpp
TSplitter.cpp
TSplitterHandle.cpp
TStringUtils.cpp
TTabBar.cpp
TTextCodec.cpp
TTextEdit.cpp
Expand Down Expand Up @@ -183,24 +208,51 @@ set(mudlet_HDRS
TDebug.h
TDockWidget.h
TEasyButtonBar.h
TEncodingTable.h
TEntityHandler.h
TEntityResolver.h
testdbg.h
TEvent.h
TForkedProcess.h
TFlipButton.h
TimerUnit.h
TKey.h
TLabel.h
TLinkStore.h
TLuaInterpreter.h
TMap.h
TMatchState.h
TMedia.h
TMxpBRTagHandler.h
TMxpClient.h
TMxpColorTagHandler.h
TMxpCustomElementTagHandler.h
TMxpEntityTagHandler.h
TMxpFontTagHandler.h
TMxpLinkTagHandler.h
TMxpElementDefinitionHandler.h
TMxpElementRegistry.h
TMxpContext.h
TMxpFormattingTagsHandler.h
TMxpMudlet.h
TMxpNodeBuilder.h
TMxpProcessor.h
TMxpSendTagHandler.h
MxpTag.h
TMxpTagHandler.h
TMxpTagParser.h
TMxpTagProcessor.h
TMxpSupportTagHandler.cpp
TMxpVarTagHandler.h
TMxpVersionTagHandler.h
Tree.h
TriggerUnit.h
TRoom.h
TRoomDB.h
TScript.h
TSplitter.h
TSplitterHandle.h
TStringUtils.h
TTabBar.h
TTextCodec.h
TTextEdit.h
Expand Down
3 changes: 3 additions & 0 deletions src/Host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "dlgMapper.h"
#include "mudlet.h"


#include "pre_guard.h"
#include <chrono>
#include <QtUiTools>
Expand Down Expand Up @@ -205,6 +206,8 @@ Host::Host(int port, const QString& hostname, const QString& login, const QStrin
, mEnableMSP(true)
, mEnableMSDP(false)
, mServerMXPenabled(true)
, mMxpClient(this)
, mMxpProcessor(&mMxpClient)
, mMediaLocationGMCP(QString())
, mMediaLocationMSP(QString())
, mFORCE_GA_OFF(false)
Expand Down
6 changes: 6 additions & 0 deletions src/Host.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
#include <QTextStream>
#include "post_guard.h"

#include "TMxpMudlet.h"
#include "TMxpProcessor.h"

class QDialog;
class QDockWidget;
class QPushButton;
Expand Down Expand Up @@ -356,6 +359,9 @@ class Host : public QObject
bool mEnableMSP;
bool mEnableMSDP;
bool mServerMXPenabled;

TMxpMudlet mMxpClient;
TMxpProcessor mMxpProcessor;
QString mMediaLocationGMCP;
QString mMediaLocationMSP;
QTextStream mErrorLogStream;
Expand Down
126 changes: 126 additions & 0 deletions src/MxpTag.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/***************************************************************************
* Copyright (C) 2020 by Gustavo Sousa - gustavocms@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#include "MxpTag.h"
#include "TMxpTagParser.h"

const MxpTagAttribute& MxpStartTag::getAttribute(int attrIndex) const
{
return getAttribute(mAttrsNames[attrIndex]);
}

const MxpTagAttribute& MxpStartTag::getAttribute(const QString& attrName) const
{
const auto ptr = mAttrsMap.find(attrName.toUpper());
return *ptr;
}

const QString& MxpStartTag::getAttributeValue(int attrIndex) const
{
return getAttribute(attrIndex).getValue();
}

const QString& MxpStartTag::getAttributeValue(const QString& attrName) const
{
return getAttribute(attrName).getValue();
}

bool MxpStartTag::hasAttribute(const QString& attrName) const
{
return mAttrsMap.contains(attrName.toUpper());
}

bool MxpStartTag::isAttributeAt(const char* attrName, int attrIndex)
{
return mAttrsNames[attrIndex].compare(attrName, Qt::CaseInsensitive) == 0;
}

bool MxpTag::isNamed(const QString& tagName) const
{
return name.compare(tagName, Qt::CaseInsensitive) == 0;
}

QString MxpEndTag::toString() const
{
QString result;
result.append("</");
result.append(name);
result.append(">");
return result;
}

QString MxpStartTag::toString() const
{
QString result;
result.append('<');
result.append(name);
for (const auto& attrName : mAttrsNames) {
result.append(' ');
if (attrName.contains(" ") || attrName.contains("<")) {
result.append('"');
result.append(attrName);
result.append('"');
} else {
result.append(attrName);
}

const auto& attr = getAttribute(attrName);
if (attr.hasValue()) {
result.append('=');

const auto& val = attr.getValue();
result.append('"');
result.append(val);
result.append('"');
}
}

if (mIsEmpty) {
result.append(" /");
}

result.append('>');

return result;
}

MxpStartTag MxpStartTag::transform(const MxpTagAttribute::Transformation& transformation) const
{
QList<MxpTagAttribute> newAttrs;
for (const auto& attr : mAttrsNames) {
newAttrs.append(transformation(mAttrsMap[attr.toUpper()]));
}

return MxpStartTag(name, newAttrs, mIsEmpty);
}

const QString& MxpStartTag::getAttributeByNameOrIndex(const QString& attrName, int attrIndex, const QString& defaultValue) const
{
if (hasAttribute(attrName))
return getAttributeValue(attrName);
if (getAttributesCount() > attrIndex && !getAttribute(attrIndex).hasValue())
return getAttribute(attrIndex).getName();

return defaultValue;
}

const QString& MxpStartTag::getAttrName(int attrIndex) const
{
return mAttrsNames[attrIndex];
}
Loading

0 comments on commit 102491a

Please sign in to comment.