aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKitsune Ral <Kitsune-Ral@users.sf.net>2018-07-02 13:39:33 +0900
committerKitsune Ral <Kitsune-Ral@users.sf.net>2018-07-04 20:12:34 +0900
commited467d27b07781fdd2f7ddef043568954ce50b69 (patch)
treea0782b0d87de8cbd851c6a008764dd6ae07836db /lib
parentbd853f392aaf5b05e0a8023da85a38e91d90a6e0 (diff)
downloadlibquotient-ed467d27b07781fdd2f7ddef043568954ce50b69.tar.gz
libquotient-ed467d27b07781fdd2f7ddef043568954ce50b69.zip
Events: use a template structure instead of template variables; rearrange code into blocks
A template member variable in it seemed to cause internal compiler error in MSVC 2017, let alone MSVC 2015...
Diffstat (limited to 'lib')
-rw-r--r--lib/events/accountdataevents.h6
-rw-r--r--lib/events/directchatevent.h1
-rw-r--r--lib/events/event.cpp24
-rw-r--r--lib/events/event.h180
-rw-r--r--lib/events/receiptevent.h1
-rw-r--r--lib/events/redactionevent.h1
-rw-r--r--lib/events/roomavatarevent.h1
-rw-r--r--lib/events/roommemberevent.h1
-rw-r--r--lib/events/roommessageevent.h1
-rw-r--r--lib/events/simplestateevents.h4
-rw-r--r--lib/events/typingevent.h1
-rw-r--r--lib/room.cpp6
12 files changed, 121 insertions, 106 deletions
diff --git a/lib/events/accountdataevents.h b/lib/events/accountdataevents.h
index 6d53d2aa..ed4373cd 100644
--- a/lib/events/accountdataevents.h
+++ b/lib/events/accountdataevents.h
@@ -65,8 +65,10 @@ namespace QMatrixClient
toJson(std::move(content)) } }) \
{ } \
auto _ContentKey() const \
- { return fromJson<content_type>(contentJson()[#_ContentKey]); } \
- }; // End of macro
+ { return fromJson<content_type>(contentJson()[#_ContentKey##_ls]); } \
+ }; \
+ REGISTER_EVENT_TYPE(_Name) \
+ // End of macro
DEFINE_SIMPLE_EVENT(TagEvent, "m.tag", TagsMap, tags)
DEFINE_SIMPLE_EVENT(ReadMarkerEvent, "m.fully_read", QString, event_id)
diff --git a/lib/events/directchatevent.h b/lib/events/directchatevent.h
index 1d366721..7559796b 100644
--- a/lib/events/directchatevent.h
+++ b/lib/events/directchatevent.h
@@ -33,5 +33,6 @@ namespace QMatrixClient
QMultiHash<QString, QString> usersToDirectChats() const;
};
+ REGISTER_EVENT_TYPE(DirectChatEvent)
DEFINE_EVENTTYPE_ALIAS(DirectChat, DirectChatEvent)
}
diff --git a/lib/events/event.cpp b/lib/events/event.cpp
index 3f507347..447068af 100644
--- a/lib/events/event.cpp
+++ b/lib/events/event.cpp
@@ -18,14 +18,6 @@
#include "event.h"
-#include "roommessageevent.h"
-#include "simplestateevents.h"
-#include "roommemberevent.h"
-#include "roomavatarevent.h"
-#include "typingevent.h"
-#include "receiptevent.h"
-#include "accountdataevents.h"
-#include "directchatevent.h"
#include "redactionevent.h"
#include "logging.h"
@@ -33,12 +25,6 @@
using namespace QMatrixClient;
-event_type_t EventTypeRegistry::nextTypeId()
-{
- static event_type_t typeIndex = unknownTypeId();
- return ++typeIndex;
-}
-
Event::Event(Type type, const QJsonObject& json)
: _type(type), _json(json)
{
@@ -77,7 +63,7 @@ const QJsonObject Event::unsignedJson() const
}
[[gnu::unused]] static auto roomEventTypeInitialised =
- EventTypeRegistry::chainFactories<Event, RoomEvent>();
+ Event::factory_t::chainFactory<RoomEvent>();
RoomEvent::RoomEvent(Type type, event_mtype_t matrixType,
const QJsonObject& contentJson)
@@ -134,10 +120,16 @@ void RoomEvent::addId(const QString& newId)
}
[[gnu::unused]] static auto stateEventTypeInitialised =
- EventTypeRegistry::chainFactories<RoomEvent, StateEventBase>();
+ RoomEvent::factory_t::chainFactory<StateEventBase>();
bool StateEventBase::repeatsState() const
{
const auto prevContentJson = unsignedJson().value(PrevContentKeyL);
return fullJson().value(ContentKeyL) == prevContentJson;
}
+
+event_type_t QMatrixClient::nextTypeId()
+{
+ static event_type_t _id = EventTypeTraits<void>::id;
+ return ++_id;
+}
diff --git a/lib/events/event.h b/lib/events/event.h
index f8264baf..89ba94ac 100644
--- a/lib/events/event.h
+++ b/lib/events/event.h
@@ -21,6 +21,8 @@
#include "converters.h"
#include "util.h"
+#include <typeindex>
+
namespace QMatrixClient
{
// === event_ptr_tt<> and type casting facilities ===
@@ -46,10 +48,7 @@ namespace QMatrixClient
return unique_ptr_cast<TargetT>(ptr);
}
- // === Predefined types and JSON key names
-
- using event_type_t = uint;
- using event_mtype_t = const char*;
+ // === Standard Matrix key names and basicEventJson() ===
static const auto TypeKey = QStringLiteral("type");
static const auto ContentKey = QStringLiteral("content");
@@ -61,19 +60,57 @@ namespace QMatrixClient
static const auto RedactedCauseKeyL = "redacted_because"_ls;
static const auto PrevContentKeyL = "prev_content"_ls;
+ // Minimal correct Matrix event JSON
+ template <typename StrT>
+ inline QJsonObject basicEventJson(StrT matrixType,
+ const QJsonObject& content)
+ {
+ return { { TypeKey, std::forward<StrT>(matrixType) },
+ { ContentKey, content } };
+ }
+
// === Event factory ===
+ using event_type_t = size_t;
+ using event_mtype_t = const char*;
+
+ template <typename EventT>
+ struct EventTypeTraits
+ {
+ static const event_type_t id;
+ };
+
+ template <>
+ struct EventTypeTraits<void>
+ {
+ static constexpr event_type_t id = 0;
+ };
+
+ event_type_t nextTypeId();
+
+ template <typename EventT>
+ const event_type_t EventTypeTraits<EventT>::id = nextTypeId();
+
+ template <typename EventT>
+ inline event_type_t typeId() { return EventTypeTraits<std::decay_t<EventT>>::id; }
+
+ inline event_type_t unknownEventTypeId() { return typeId<void>(); }
+
template <typename EventT, typename... ArgTs>
inline event_ptr_tt<EventT> makeEvent(ArgTs&&... args)
{
return std::make_unique<EventT>(std::forward<ArgTs>(args)...);
}
- class EventTypeRegistry
+ template <typename BaseEventT>
+ class EventFactory
{
public:
- static constexpr event_type_t unknownTypeId() { return 0; }
- static event_type_t nextTypeId();
+ template <typename FnT>
+ static void addMethod(FnT&& method)
+ {
+ factories().emplace_back(std::forward<FnT>(method));
+ }
/** Chain two type factories
* Adds the factory class of EventT2 (EventT2::factory_t) to
@@ -83,53 +120,11 @@ namespace QMatrixClient
* to include RoomEvent types into the more general Event factory,
* and state event types into the RoomEvent factory.
*/
- template <typename EventT1, typename EventT2>
- static auto chainFactories()
- {
- EventT1::factory_t::addFactory(&EventT2::factory_t::make);
- return 0;
- }
-
- /** Add a type to its default factory
- * Adds a standard factory method (via makeEvent<>) for a given
- * type to EventT::factory_t factory class so that it can be
- * created dynamically from loadEvent<>().
- *
- * \tparam EventT the type to enable dynamic creation of
- * \return the registered type id
- * \sa loadEvent, Event::type
- */
template <typename EventT>
- static auto addType()
+ static auto chainFactory()
{
- EventT::factory_t::addFactory(
- [] (const QJsonObject& json, const QString& jsonMatrixType)
- {
- return EventT::matrixTypeId() == jsonMatrixType
- ? makeEvent<EventT>(json) : nullptr;
- });
- return nextTypeId();
- }
-
- template <typename EventT>
- static auto typeId() { return _typeId<std::decay_t<EventT>>; }
-
- private:
- template <typename EventT>
- static const event_type_t _typeId;
- };
-
- template <typename EventT>
- const event_type_t EventTypeRegistry::_typeId = addType<EventT>();
-
- template <typename BaseEventT>
- class EventFactory
- {
- public:
- template <typename FnT>
- static void addFactory(FnT&& factory)
- {
- factories().emplace_back(std::forward<FnT>(factory));
+ addMethod(&EventT::factory_t::make);
+ return 0;
}
static event_ptr_tt<BaseEventT> make(const QJsonObject& json,
@@ -138,8 +133,7 @@ namespace QMatrixClient
for (const auto& f: factories())
if (auto e = f(json, matrixType))
return e;
- return makeEvent<BaseEventT>(EventTypeRegistry::unknownTypeId(),
- json);
+ return makeEvent<BaseEventT>(unknownEventTypeId(), json);
}
private:
@@ -153,12 +147,24 @@ namespace QMatrixClient
}
};
- template <typename StrT>
- inline QJsonObject basicEventJson(StrT matrixType,
- const QJsonObject& content)
+ /** Add a type to its default factory
+ * Adds a standard factory method (via makeEvent<>) for a given
+ * type to EventT::factory_t factory class so that it can be
+ * created dynamically from loadEvent<>().
+ *
+ * \tparam EventT the type to enable dynamic creation of
+ * \return the registered type id
+ * \sa loadEvent, Event::type
+ */
+ template <typename EventT>
+ inline void setupFactory()
{
- return { { TypeKey, std::forward<StrT>(matrixType) },
- { ContentKey, content } };
+ EventT::factory_t::addMethod(
+ [] (const QJsonObject& json, const QString& jsonMatrixType)
+ {
+ return EventT::matrixTypeId() == jsonMatrixType
+ ? makeEvent<EventT>(json) : nullptr;
+ });
}
/** Create an event with proper type from a JSON object
@@ -199,6 +205,8 @@ namespace QMatrixClient
class Event
{
Q_GADGET
+ Q_PROPERTY(Type type READ type CONSTANT)
+ Q_PROPERTY(QJsonObject contentJson READ contentJson CONSTANT)
public:
using Type = event_type_t;
using factory_t = EventFactory<Event>;
@@ -228,22 +236,12 @@ namespace QMatrixClient
virtual bool isStateEvent() const { return false; }
- template <typename EventT>
- bool is() const
- {
- const auto eventTypeId = EventTypeRegistry::typeId<EventT>();
- return _type == eventTypeId;
- }
-
protected:
QJsonObject& editJson() { return _json; }
private:
Type _type;
QJsonObject _json;
-
- Q_PROPERTY(Type type READ type CONSTANT)
- Q_PROPERTY(QJsonObject contentJson READ contentJson CONSTANT)
};
using EventPtr = event_ptr_tt<Event>;
@@ -251,33 +249,47 @@ namespace QMatrixClient
using EventsArray = std::vector<event_ptr_tt<EventT>>;
using Events = EventsArray<Event>;
+ // === Macros used with event class definitions ===
+
// This macro should be used in a public section of an event class to
// provide matrixTypeId() and typeId().
#define DEFINE_EVENT_TYPEID(_Id, _Type) \
static constexpr event_mtype_t matrixTypeId() { return _Id; } \
- static event_type_t typeId() { return EventTypeRegistry::typeId<_Type>(); }
-
- // This macro should be put after an event class definition to define an
- // additional constant that can be used for an event type id. The constant
- // will be inside EventType namespace. This is for back-compatibility,
- // to support clients checking for EventType::ShortName (previously
- // EventType was a typedef for an enumeration). New code should use
- // either typeId() for a specific event type, or (better) casting methods
- // defined in the very beginning of this file.
+ static auto typeId() { return QMatrixClient::typeId<_Type>(); } \
+ // End of macro
+
+ // This macro should be put after an event class definition (in .h or .cpp)
+ // to enable its deserialisation from a /sync and other
+ // polymorphic event arrays
+#define REGISTER_EVENT_TYPE(_Type) \
+ namespace { \
+ [[gnu::unused]] \
+ static const auto _factoryAdded##_Type = ( setupFactory<_Type>(), 0); \
+ } \
+ // End of macro
+
+ // This macro provides constants in EventType:: namespace for
+ // back-compatibility with libQMatrixClient 0.3 event type system.
#define DEFINE_EVENTTYPE_ALIAS(_Id, _Type) \
namespace EventType \
{ \
- [[deprecated("Use "#_Type"::typeId(), Event::is<>() or visit<>()")]] \
- static const auto _Id { _Type::typeId() }; \
- } // End of macro
+ [[deprecated("Use typeId<>(), is<>() or visit<>()")]] \
+ static const auto _Id = typeId<_Type>(); \
+ } \
+ // End of macro
+
+ // === is<>() and visit<>() ===
+
+ template <typename EventT>
+ inline bool is(const Event& e) { return e.type() == typeId<EventT>(); }
- // === visit<>() ===
+ inline bool isUnknown(const Event& e) { return e.type() == unknownEventTypeId(); }
template <typename FnT>
inline fn_return_t<FnT> visit(const Event& event, FnT visitor)
{
using event_type = fn_arg_t<FnT>;
- if (event.is<event_type>())
+ if (is<event_type>(event))
return visitor(static_cast<event_type>(event));
return fn_return_t<FnT>();
}
@@ -286,7 +298,7 @@ namespace QMatrixClient
inline auto visit(const Event& event, FnT visitor1, FnTs&&... visitors)
{
using event_type1 = fn_arg_t<FnT>;
- if (event.is<event_type1>())
+ if (is<event_type1>(event))
return visitor1(static_cast<event_type1&>(event));
return visit(event, std::forward<FnTs>(visitors)...);
diff --git a/lib/events/receiptevent.h b/lib/events/receiptevent.h
index 10b3f631..5237ba69 100644
--- a/lib/events/receiptevent.h
+++ b/lib/events/receiptevent.h
@@ -48,5 +48,6 @@ namespace QMatrixClient
private:
EventsWithReceipts _eventsWithReceipts;
};
+ REGISTER_EVENT_TYPE(ReceiptEvent)
DEFINE_EVENTTYPE_ALIAS(Receipt, ReceiptEvent)
} // namespace QMatrixClient
diff --git a/lib/events/redactionevent.h b/lib/events/redactionevent.h
index 8c6cbeff..64504d57 100644
--- a/lib/events/redactionevent.h
+++ b/lib/events/redactionevent.h
@@ -36,5 +36,6 @@ namespace QMatrixClient
QString reason() const
{ return contentJson()["reason"_ls].toString(); }
};
+ REGISTER_EVENT_TYPE(RedactionEvent)
DEFINE_EVENTTYPE_ALIAS(Redaction, RedactionEvent)
} // namespace QMatrixClient
diff --git a/lib/events/roomavatarevent.h b/lib/events/roomavatarevent.h
index fe11807c..491861b1 100644
--- a/lib/events/roomavatarevent.h
+++ b/lib/events/roomavatarevent.h
@@ -37,5 +37,6 @@ namespace QMatrixClient
{ }
QUrl url() const { return content().url; }
};
+ REGISTER_EVENT_TYPE(RoomAvatarEvent)
DEFINE_EVENTTYPE_ALIAS(RoomAvatar, RoomAvatarEvent)
} // namespace QMatrixClient
diff --git a/lib/events/roommemberevent.h b/lib/events/roommemberevent.h
index 943d5ac6..1ecd63d1 100644
--- a/lib/events/roommemberevent.h
+++ b/lib/events/roommemberevent.h
@@ -80,5 +80,6 @@ namespace QMatrixClient
private:
REGISTER_ENUM(MembershipType)
};
+ REGISTER_EVENT_TYPE(RoomMemberEvent)
DEFINE_EVENTTYPE_ALIAS(RoomMember, RoomMemberEvent)
} // namespace QMatrixClient
diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h
index 3f3832d4..ccf30f96 100644
--- a/lib/events/roommessageevent.h
+++ b/lib/events/roommessageevent.h
@@ -67,6 +67,7 @@ namespace QMatrixClient
REGISTER_ENUM(MsgType)
};
+ REGISTER_EVENT_TYPE(RoomMessageEvent)
DEFINE_EVENTTYPE_ALIAS(RoomMessage, RoomMessageEvent)
using MessageEventType = RoomMessageEvent::MsgType;
diff --git a/lib/events/simplestateevents.h b/lib/events/simplestateevents.h
index a117efb1..afd59478 100644
--- a/lib/events/simplestateevents.h
+++ b/lib/events/simplestateevents.h
@@ -73,7 +73,9 @@ namespace QMatrixClient
std::forward<T>(value)) \
{ } \
auto _ContentKey() const { return content().value; } \
- }; // End of macro
+ }; \
+ REGISTER_EVENT_TYPE(_Name) \
+ // End of macro
DEFINE_SIMPLE_STATE_EVENT(RoomNameEvent, "m.room.name", QString, name)
DEFINE_EVENTTYPE_ALIAS(RoomName, RoomNameEvent)
diff --git a/lib/events/typingevent.h b/lib/events/typingevent.h
index 0c4b350d..27b668b4 100644
--- a/lib/events/typingevent.h
+++ b/lib/events/typingevent.h
@@ -34,5 +34,6 @@ namespace QMatrixClient
private:
QStringList _users;
};
+ REGISTER_EVENT_TYPE(TypingEvent)
DEFINE_EVENTTYPE_ALIAS(Typing, TypingEvent)
} // namespace QMatrixClient
diff --git a/lib/room.cpp b/lib/room.cpp
index 9f4b5a0e..080ad30d 100644
--- a/lib/room.cpp
+++ b/lib/room.cpp
@@ -168,7 +168,7 @@ class Room::Private
{
return !ti->isRedacted() &&
ti->senderId() != connection->userId() &&
- ti->is<RoomMessageEvent>();
+ is<RoomMessageEvent>(*ti);
}
void addNewMessageEvents(RoomEvents&& events);
@@ -725,7 +725,7 @@ const RoomMessageEvent*
Room::Private::getEventWithFile(const QString& eventId) const
{
auto evtIt = q->findInTimeline(eventId);
- if (evtIt != timeline.rend() && evtIt->event()->is<RoomMessageEvent>())
+ if (evtIt != timeline.rend() && is<RoomMessageEvent>(**evtIt))
{
auto* event = evtIt->viewAs<RoomMessageEvent>();
if (event->hasFileContent())
@@ -1275,7 +1275,7 @@ void Room::Private::dropDuplicateEvents(RoomEvents& events) const
inline bool isRedaction(const RoomEventPtr& e)
{
- return e && e->is<RedactionEvent>();
+ return e && is<RedactionEvent>(*e);
}
void Room::Private::processRedaction(event_ptr_tt<RedactionEvent>&& redaction)