From 6f73e88b27b8b046fb3f135406eb365ef1ad8f5b Mon Sep 17 00:00:00 2001
From: Riccardo Musso <riccardo.musso@skywarder.eu>
Date: Wed, 27 Apr 2022 17:48:42 +0200
Subject: [PATCH] Implemented MessageField and Topic
---
Core/Messages/messagefield.cpp | 95 ++++++++++++++++++++++++++++++++++
Core/Messages/messagefield.h | 52 +++++++++++++++++++
Core/Messages/topic.cpp | 40 ++++++++++++++
Core/Messages/topic.h | 40 ++++++++++++++
Core/modulemessage.h | 34 ++++++------
SkywardHub.pro | 4 ++
6 files changed, 248 insertions(+), 17 deletions(-)
create mode 100644 Core/Messages/messagefield.cpp
create mode 100644 Core/Messages/messagefield.h
create mode 100644 Core/Messages/topic.cpp
create mode 100644 Core/Messages/topic.h
diff --git a/Core/Messages/messagefield.cpp b/Core/Messages/messagefield.cpp
new file mode 100644
index 00000000..0fab7dfa
--- /dev/null
+++ b/Core/Messages/messagefield.cpp
@@ -0,0 +1,95 @@
+#include "messagefield.h"
+
+MessageField::MessageField() : type(Type::EMPTY) { }
+
+MessageField::MessageField(int64_t _i64) : type(Type::INTEGER), i64(_i64) {}
+MessageField::MessageField(uint64_t _u64) : type(Type::UINTEGER), u64(_u64) {}
+MessageField::MessageField(double _d) : type(Type::DOUBLE), d(_d) {}
+MessageField::MessageField(char _c) : type(Type::CHAR), c(_c) {}
+MessageField::MessageField(QString _s) : type(Type::STRING), s(_s) {}
+
+int64_t MessageField::getInteger(int64_t defaultValue) const {
+ if(type == Type::INTEGER) {
+ return i64;
+ } else {
+ return defaultValue;
+ }
+}
+
+uint64_t MessageField::getUInteger(uint64_t defaultValue) const {
+ if(type == Type::UINTEGER) {
+ return u64;
+ } else {
+ return defaultValue;
+ }
+}
+
+double MessageField::getDouble(double defaultValue) const {
+ if(type == Type::DOUBLE) {
+ return d;
+ } else {
+ return defaultValue;
+ }
+}
+
+char MessageField::getChar(char defaultValue) const {
+ if(type == Type::CHAR) {
+ return c;
+ } else {
+ return defaultValue;
+ }
+}
+
+QString MessageField::getString() const {
+ switch(type) {
+ case Type::EMPTY:
+ return QString();
+ case Type::INTEGER:
+ return QString::number(i64);
+ case Type::UINTEGER:
+ return QString::number(u64);
+ case Type::DOUBLE:
+ return QString::number(d);
+ case Type::CHAR:
+ return QString(c);
+ case Type::STRING:
+ return s;
+ }
+}
+
+void MessageField::set(int64_t value) {
+ type = Type::INTEGER;
+ i64 = value;
+}
+
+void MessageField::set(uint64_t value) {
+ type = Type::UINTEGER;
+ u64 = value;
+}
+
+void MessageField::set(double value) {
+ type = Type::DOUBLE;
+ d = value;
+}
+
+void MessageField::set(char value) {
+ type = Type::CHAR;
+ c = value;
+}
+
+void MessageField::set(QString value) {
+ type = Type::STRING;
+ s = value;
+}
+
+void MessageField::set() {
+ if(type == Type::STRING) {
+ s.clear();
+ }
+
+ type = Type::EMPTY;
+}
+
+MessageField::Type MessageField::getType() const {
+ return type;
+}
diff --git a/Core/Messages/messagefield.h b/Core/Messages/messagefield.h
new file mode 100644
index 00000000..c00dd650
--- /dev/null
+++ b/Core/Messages/messagefield.h
@@ -0,0 +1,52 @@
+#ifndef MESSAGEFIELD_H
+#define MESSAGEFIELD_H
+
+#include <QString>
+#include <cstdint>
+
+class MessageField {
+ public:
+ enum class Type {
+ EMPTY,
+ INTEGER,
+ UINTEGER,
+ DOUBLE,
+ CHAR,
+ STRING
+ };
+
+ MessageField();
+ MessageField(int64_t _i64);
+ MessageField(uint64_t _u64);
+ MessageField(double _d);
+ MessageField(char _c);
+ MessageField(QString _s);
+
+ int64_t getInteger(int64_t defaultValue) const;
+ uint64_t getUInteger(uint64_t defaultValue) const;
+ double getDouble(double defaultValue) const;
+ char getChar(char defaultValue) const;
+ QString getString() const;
+
+ void set(int64_t value);
+ void set(uint64_t value);
+ void set(double value);
+ void set(char value);
+ void set(QString value);
+ void set();
+
+ Type getType() const;
+
+ private:
+ Type type;
+ QString s;
+
+ union {
+ int64_t i64;
+ uint64_t u64;
+ double d;
+ char c;
+ };
+};
+
+#endif // MESSAGEFIELD_H
diff --git a/Core/Messages/topic.cpp b/Core/Messages/topic.cpp
new file mode 100644
index 00000000..7fee1b57
--- /dev/null
+++ b/Core/Messages/topic.cpp
@@ -0,0 +1,40 @@
+#include "topic.h"
+
+#include <QRegExp>
+
+Topic::Topic(QString str) {
+ if(str == "*" || str.contains(QRegExp("^[A-Za-z0-9$_]+(/[A-Za-z0-9$_]+)*(/*)?$"))) {
+ repr = str;
+ } else {
+ str = "Invalid";
+ }
+}
+
+bool Topic::match(Topic prefix) const {
+ if(prefix.repr.endsWith("*")) {
+ int prefixSize = prefix.repr.size() - 2;
+ return repr.size() >= prefixSize && repr.at(prefixSize - 1) == '/' && repr.startsWith(prefix.repr.leftRef(prefixSize));
+ } else {
+ return repr == prefix.repr;
+ }
+}
+
+Topic Topic::getParent() const {
+ int idx = repr.lastIndexOf('/');
+ return idx == -1 ? Topic(repr) : Topic(repr.left(idx));
+}
+
+Topic Topic::getRoot() const {
+ int idx = repr.indexOf('/');
+ return idx == -1 ? Topic(repr) : Topic(repr.left(idx));
+}
+
+QString Topic::toString() const {
+ return repr;
+}
+
+bool Topic::isWildcard() const {
+ return repr.contains('*');
+}
+
+static const Topic Any("*");
diff --git a/Core/Messages/topic.h b/Core/Messages/topic.h
new file mode 100644
index 00000000..efd65851
--- /dev/null
+++ b/Core/Messages/topic.h
@@ -0,0 +1,40 @@
+#ifndef TOPIC_H
+#define TOPIC_H
+
+#include <QString>
+
+/*
+ * This class defines topics for GS messages.
+ *
+ * Topics are strings made of alphanumerical characters and slashes '/'. For example,
+ * "Prefix/Section2/Message" and "SomeMessage" are valid topics. I'll call the parts
+ * between slashes tokens.
+ *
+ * When a Module subscribes to a topic, it is allowed to specify a wildcard topic, which
+ * uses as last token a *, so that it will match against all topics with the same prefix.
+ *
+ * For example: "Prefix/*" is a valid topic that matches against "Prefix", "Prefix/AMessage" and
+ * "Prefix/Section2/Message". Similarly, "*" will match against anything.
+ *
+*/
+
+class Topic {
+ private:
+ QString repr;
+
+ public:
+ Topic(QString str);
+
+ bool match(Topic prefix) const;
+ bool match(QString prefix) const;
+
+ Topic getParent() const;
+ Topic getRoot() const;
+
+ QString toString() const;
+ bool isWildcard() const;
+
+ static const Topic Any;
+};
+
+#endif // TOPIC_H
diff --git a/Core/modulemessage.h b/Core/modulemessage.h
index ef0d9232..a5f5f14d 100644
--- a/Core/modulemessage.h
+++ b/Core/modulemessage.h
@@ -9,49 +9,49 @@
class ModuleMessage {
public:
ModuleMessage();
- ModuleMessage(const QString &topic);
- ModuleMessage(const QString &_topic, const QString &payload);
- ModuleMessage(const QString &_topic, const QString &payload, const QTime &time);
- ModuleMessage(const ModuleMessage &other);
+ ModuleMessage(const QString& topic);
+ ModuleMessage(const QString& _topic, const QString& payload);
+ ModuleMessage(const QString& _topic, const QString& payload, const QTime& time);
+ ModuleMessage(const ModuleMessage& other);
- ModuleMessage operator=(const ModuleMessage &other);
+ ModuleMessage operator=(const ModuleMessage& other);
QString payload() const;
- void setPayload(const QString &value);
+ void setPayload(const QString& value);
void setPayload(int value);
QString topic() const;
- void setTopic(const QString &value);
+ void setTopic(const QString& value);
QTime timestamp() const;
- void setTimestamp(const QTime ×tamp);
+ void setTimestamp(const QTime& timestamp);
QString getHigherHierarchyTopic() const;
QString originalTopic() const;
- void setOriginalTopic(const QString &originalTopic);
+ void setOriginalTopic(const QString& originalTopic);
/*
* Returns an XmlObject containing some options
*/
XmlObject getOptions() const;
- QString getOption(const QString &optionName) const;
- bool getIntOption(const QString &optionName, int &val) const;
- void setOptions(const XmlObject &value);
- void addOption(const QString &optionName, const QString &value);
- void addOption(const QString &optionName, int value);
+ QString getOption(const QString& optionName) const;
+ bool getIntOption(const QString& optionName, int& val) const;
+ void setOptions(const XmlObject& value);
+ void addOption(const QString& optionName, const QString& value);
+ void addOption(const QString& optionName, int value);
/*
* Get the value of "value" if the payload exist and is an integer
*/
- bool getIntPayload(int &value) const;
+ bool getIntPayload(int& value) const;
- bool getFloatPayload(float &value) const;
+ bool getFloatPayload(float& value) const;
QString toString() const;
private:
- void copy(const ModuleMessage &msg);
+ void copy(const ModuleMessage& msg);
QString _payload;
QString _topic;
diff --git a/SkywardHub.pro b/SkywardHub.pro
index b6275d74..38fe5829 100644
--- a/SkywardHub.pro
+++ b/SkywardHub.pro
@@ -17,6 +17,8 @@ SOURCES += \
Components/ToggleButton/togglebutton.cpp \
Components/ErrorDisplayer/error.cpp \
Components/ErrorDisplayer/errordisplayer.cpp \
+ Core/Messages/messagefield.cpp \
+ Core/Messages/topic.cpp \
Core/module.cpp \
Core/moduleeventshandler.cpp \
Core/modulemessage.cpp \
@@ -73,6 +75,8 @@ HEADERS += \
Components/ToggleButton/togglebutton.h \
Components/ErrorDisplayer/error.h \
Components/ErrorDisplayer/errordisplayer.h \
+ Core/Messages/messagefield.h \
+ Core/Messages/topic.h \
Core/module.h \
Core/moduleeventshandler.h \
Core/modulemessage.h \
--
GitLab