From 8bb8d7e5b7433ada8eef068016054d4eb2c645b8 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 30 May 2019 16:28:45 -0400
Subject: [PATCH] SL-11216: Introduce generic LLStoreListener<T> to capture
 event data.

LLStoreListener is an adapter initialized with a reference to an LLEventPump
on which to listen, a reference to a variable into which to store received
data, and an optional llsd::drill() path to extract desired data from each
event received on the subject LLEventPump.

In effect, LLStoreListener is like a miniature LLEventAPI whose only operation
is to store to its destination variable.
---
 indra/llcommon/lleventfilter.h | 51 ++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/indra/llcommon/lleventfilter.h b/indra/llcommon/lleventfilter.h
index ff8fc9bc7fc..8e7c0755815 100644
--- a/indra/llcommon/lleventfilter.h
+++ b/indra/llcommon/lleventfilter.h
@@ -32,6 +32,7 @@
 #include "llevents.h"
 #include "stdtypes.h"
 #include "lltimer.h"
+#include "llsdutil.h"
 #include <boost/function.hpp>
 
 /**
@@ -376,4 +377,54 @@ class LLEventBatchThrottle: public LLEventThrottle
     std::size_t mBatchSize;
 };
 
+/**
+ * LLStoreListener self-registers on the LLEventPump of interest, and
+ * unregisters on destruction. As long as it exists, a particular element is
+ * extracted from every event that comes through the upstream LLEventPump and
+ * stored into the target variable.
+ *
+ * This is implemented as a subclass of LLEventFilter, though strictly
+ * speaking it isn't really a "filter" at all: it never passes incoming events
+ * to its own listeners, if any.
+ *
+ * TBD: A variant based on output iterators that stores and then increments
+ * the iterator. Useful with boost::coroutine2!
+ */
+template <typename T>
+class LLStoreListener: public LLEventFilter
+{
+public:
+    // pass target and optional path to element
+    LLStoreListener(T& target, const LLSD& path=LLSD(), bool consume=false):
+        LLEventFilter("store"),
+        mTarget(target),
+        mPath(path),
+        mConsume(consume)
+    {}
+    // construct and connect
+    LLStoreListener(LLEventPump& source, T& target, const LLSD& path=LLSD(), bool consume=false):
+        LLEventFilter(source, "store"),
+        mTarget(target),
+        mPath(path),
+        mConsume(consume)
+    {}
+
+    // Calling post() with an LLSD event extracts the element indicated by
+    // path, then stores it to mTarget.
+    virtual bool post(const LLSD& event)
+    {
+        // Extract the element specified by 'mPath' from 'event'. To perform a
+        // generic type-appropriate store through mTarget, construct an
+        // LLSDParam<T> and store that, thus engaging LLSDParam's custom
+        // conversions.
+        mTarget = LLSDParam<T>(llsd::drill(event, mPath));
+        return mConsume;
+    }
+
+private:
+    T& mTarget;
+    const LLSD mPath;
+    const bool mConsume;
+};
+
 #endif /* ! defined(LL_LLEVENTFILTER_H) */
-- 
GitLab