]> git.tdb.fi Git - libs/net.git/blobdiff - source/net/receiver.h
Add a dynamic receiver class for more flexible packet handling
[libs/net.git] / source / net / receiver.h
index 9af1bb7154af65a226d96836c43fe48d9bc18fa3..a0a9f2913d0ed0e48fb6a47aa5793f04aa76ac99 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef MSP_NET_RECEIVER_H_
 #define MSP_NET_RECEIVER_H_
 
+#include <vector>
+#include <msp/core/algorithm.h>
+#include <msp/core/maputils.h>
+#include <msp/core/variant.h>
 #include "mspnet_api.h"
 
 namespace Msp {
@@ -14,6 +18,7 @@ public:
        virtual ~ReceiverBase() = default;
 };
 
+
 template<typename P>
 class PacketReceiver: public virtual ReceiverBase
 {
@@ -23,6 +28,54 @@ public:
        virtual void receive(const P &) = 0;
 };
 
+
+class MSPNET_API DynamicReceiver: public ReceiverBase
+{
+protected:
+       DynamicReceiver() = default;
+public:
+       virtual void receive(unsigned, const Variant &) = 0;
+};
+
+
+class MSPNET_API DynamicDispatcher: public DynamicReceiver
+{
+private:
+       using DispatchFunc = void(ReceiverBase &, const Variant &);
+
+       struct Target
+       {
+               unsigned packet_id;
+               ReceiverBase *receiver;
+               DispatchFunc *func;
+
+               Target(unsigned i, ReceiverBase &r, DispatchFunc *f): packet_id(i), receiver(&r), func(f) { }
+       };
+
+       std::vector<Target> targets;
+
+public:
+       template<typename P>
+       void add_receiver(unsigned, PacketReceiver<P> &);
+
+       void receive(unsigned, const Variant &) override;
+};
+
+
+template<typename P>
+void DynamicDispatcher::add_receiver(unsigned packet_id, PacketReceiver<P> &r)
+{
+       auto i = lower_bound_member(targets, packet_id, &Target::packet_id);
+       if(i!=targets.end() && i->packet_id==packet_id)
+               throw key_error(packet_id);
+
+       auto dispatch = [](ReceiverBase &receiver, const Variant &packet){
+               dynamic_cast<PacketReceiver<P> &>(receiver).receive(packet.value<P>());
+       };
+
+       targets.emplace(i, packet_id, r, +dispatch);
+}
+
 } // namespace Net
 } // namespace Msp