Simplify XmlReplayEvent retrieval and add support for matching id.

This commit is contained in:
sawinglogz 2020-06-16 16:43:16 -04:00
parent d350e47382
commit 8fbf665b89

View File

@ -38,24 +38,24 @@ protected:
void epilogue(); void epilogue();
}; };
class XmlReplayEvent;
class XmlReplay class XmlReplay
{ {
public: public:
XmlReplay(class QFile * file); XmlReplay(class QFile * file);
XmlReplay(QXmlStreamReader & xml); XmlReplay(QXmlStreamReader & xml);
~XmlReplay(); ~XmlReplay();
template<class T> inline T* getNextEvent(); template<class T> inline T* getNextEvent(const QString & id = "");
protected: protected:
void deserialize(QXmlStreamReader & xml); void deserialize(QXmlStreamReader & xml);
void deserializeEvents(QXmlStreamReader & xml); void deserializeEvents(QXmlStreamReader & xml);
// TODO: maybe the QList should be a QHash on the timestamp? QHash<QString,QHash<QString,QList<XmlReplayEvent*>>> m_eventIndex;
// Then indices would be iterators over a sorted list of keys. QList<XmlReplayEvent*> m_events;
QHash<QString,QList<class XmlReplayEvent*>> m_events;
QHash<QString,int> m_indices;
class XmlReplayEvent* getNextEvent(const QString & type); XmlReplayEvent* getNextEvent(const QString & type, const QString & id = "");
}; };
class XmlReplayEvent class XmlReplayEvent
@ -64,6 +64,7 @@ public:
XmlReplayEvent(); XmlReplayEvent();
virtual ~XmlReplayEvent() = default; virtual ~XmlReplayEvent() = default;
virtual const QString & tag() const = 0; virtual const QString & tag() const = 0;
virtual const QString & id() const { static const QString none(""); return none; };
void record(XmlRecorder* xml); void record(XmlRecorder* xml);
friend QXmlStreamWriter & operator<<(QXmlStreamWriter & xml, const XmlReplayEvent & event); friend QXmlStreamWriter & operator<<(QXmlStreamWriter & xml, const XmlReplayEvent & event);
@ -77,9 +78,12 @@ protected:
static QHash<QString,FactoryMethod> s_factories; static QHash<QString,FactoryMethod> s_factories;
QDateTime m_time; QDateTime m_time;
XmlReplayEvent* m_next;
virtual void write(QXmlStreamWriter & /*xml*/) const {} virtual void write(QXmlStreamWriter & /*xml*/) const {}
virtual void read(QXmlStreamReader & /*xml*/) {} virtual void read(QXmlStreamReader & /*xml*/) {}
friend class XmlReplay;
}; };
QHash<QString,XmlReplayEvent::FactoryMethod> XmlReplayEvent::s_factories; QHash<QString,XmlReplayEvent::FactoryMethod> XmlReplayEvent::s_factories;
@ -133,10 +137,8 @@ XmlReplay::XmlReplay(QXmlStreamReader & xml)
XmlReplay::~XmlReplay() XmlReplay::~XmlReplay()
{ {
for (auto list : m_events.values()) { for (auto event : m_events) {
for (auto event : list) { delete event;
delete event;
}
} }
} }
@ -160,11 +162,20 @@ void XmlReplay::deserialize(QXmlStreamReader & xml)
void XmlReplay::deserializeEvents(QXmlStreamReader & xml) void XmlReplay::deserializeEvents(QXmlStreamReader & xml)
{ {
while (xml.readNextStartElement()) { while (xml.readNextStartElement()) {
QString name = xml.name().toString(); QString type = xml.name().toString();
XmlReplayEvent* event = XmlReplayEvent::createInstance(name); XmlReplayEvent* event = XmlReplayEvent::createInstance(type);
if (event) { if (event) {
xml >> *event; xml >> *event;
auto & events = m_events[name];
// Add to list
if (m_events.isEmpty() == false) {
m_events.last()->m_next = event;
}
m_events.append(event);
// Add to index
const QString & id = event->id();
auto & events = m_eventIndex[type][id];
events.append(event); events.append(event);
} else { } else {
xml.skipCurrentElement(); xml.skipCurrentElement();
@ -172,27 +183,29 @@ void XmlReplay::deserializeEvents(QXmlStreamReader & xml)
} }
} }
XmlReplayEvent* XmlReplay::getNextEvent(const QString & type) XmlReplayEvent* XmlReplay::getNextEvent(const QString & type, const QString & id)
{ {
XmlReplayEvent* event = nullptr; XmlReplayEvent* event = nullptr;
if (m_events.contains(type)) { if (m_eventIndex.contains(type)) {
auto & events = m_events[type]; auto & ids = m_eventIndex[type];
int i = m_indices[type]; if (ids.contains(id)) {
if (i < events.size()) { auto & events = ids[id];
event = events[i]; if (events.isEmpty() == false) {
// TODO: if we're simulating the original timing, return nullptr if we haven't reached this event's time yet; event = events.first();
// otherwise: // TODO: if we're simulating the original timing, return nullptr if we haven't reached this event's time yet;
m_indices[type] = i + 1; // otherwise:
events.removeFirst();
}
} }
} }
return event; return event;
} }
template<class T> template<class T>
T* XmlReplay::getNextEvent() T* XmlReplay::getNextEvent(const QString & id)
{ {
T* event = dynamic_cast<T*>(getNextEvent(T::TAG)); T* event = dynamic_cast<T*>(getNextEvent(T::TAG, id));
return event; return event;
} }
@ -201,7 +214,7 @@ T* XmlReplay::getNextEvent()
// MARK: XML record/playback event base class // MARK: XML record/playback event base class
XmlReplayEvent::XmlReplayEvent() XmlReplayEvent::XmlReplayEvent()
: m_time(QDateTime::currentDateTime()) : m_time(QDateTime::currentDateTime()), m_next(nullptr)
{ {
} }