Variadic templates for RPCs
[invirt/third/libt4.git] / rpc / marshall.h
index e0370d1..27cebbb 100644 (file)
@@ -11,7 +11,6 @@
 #include <cstddef>
 #include <inttypes.h>
 #include "lang/verify.h"
-#include "lang/algorithm.h"
 
 struct req_header {
        req_header(int x=0, int p=0, int c = 0, int s = 0, int xi = 0):
@@ -29,18 +28,14 @@ struct reply_header {
        int ret;
 };
 
-typedef uint64_t rpc_checksum_t;
 typedef int rpc_sz_t;
 
-enum {
-       //size of initial buffer allocation 
-       DEFAULT_RPC_SZ = 1024,
-#if RPC_CHECKSUMMING
-       //size of rpc_header includes a 4-byte int to be filled by tcpchan and uint64_t checksum
-       RPC_HEADER_SZ = static_max<sizeof(req_header), sizeof(reply_header)>::value + sizeof(rpc_sz_t) + sizeof(rpc_checksum_t)
-#else
-               RPC_HEADER_SZ = static_max<sizeof(req_header), sizeof(reply_header)>::value + sizeof(rpc_sz_t)
-#endif
+//size of initial buffer allocation 
+#define DEFAULT_RPC_SZ 1024
+#define RPC_HEADER_SZ (std::max(sizeof(req_header), sizeof(reply_header)) + sizeof(rpc_sz_t))
+
+struct pass {
+    template<typename... Args> inline pass(Args&&...) {}
 };
 
 class marshall {
@@ -57,6 +52,10 @@ class marshall {
                        _ind = RPC_HEADER_SZ;
                }
 
+        template <typename... Args> marshall(const Args&... args) : marshall() {
+            (void)pass{(*this << args)...};
+        }
+
                ~marshall() { 
                        if (_buf) 
                                free(_buf); 
@@ -84,9 +83,6 @@ class marshall {
                        int saved_sz = _ind;
                        //leave the first 4-byte empty for channel to fill size of pdu
                        _ind = sizeof(rpc_sz_t); 
-#if RPC_CHECKSUMMING
-                       _ind += sizeof(rpc_checksum_t);
-#endif
                        pack(h.xid);
                        pack(h.proc);
                        pack((int)h.clt_nonce);
@@ -99,9 +95,6 @@ class marshall {
                        int saved_sz = _ind;
                        //leave the first 4-byte empty for channel to fill size of pdu
                        _ind = sizeof(rpc_sz_t); 
-#if RPC_CHECKSUMMING
-                       _ind += sizeof(rpc_checksum_t);
-#endif
                        pack(h.xid);
                        pack(h.ret);
                        _ind = saved_sz;
@@ -115,6 +108,7 @@ class marshall {
                        return;
                }
 };
+
 marshall& operator<<(marshall &, bool);
 marshall& operator<<(marshall &, unsigned int);
 marshall& operator<<(marshall &, int);
@@ -125,6 +119,40 @@ marshall& operator<<(marshall &, short);
 marshall& operator<<(marshall &, unsigned long long);
 marshall& operator<<(marshall &, const std::string &);
 
+template <class C> marshall &
+operator<<(marshall &m, std::vector<C> v)
+{
+       m << (unsigned int) v.size();
+       for(unsigned i = 0; i < v.size(); i++)
+               m << v[i];
+       return m;
+}
+
+template <class A, class B> marshall &
+operator<<(marshall &m, const std::map<A,B> &d) {
+       typename std::map<A,B>::const_iterator i;
+
+       m << (unsigned int) d.size();
+
+       for (i = d.begin(); i != d.end(); i++) {
+               m << i->first << i->second;
+       }
+       return m;
+}
+
+template <class A> marshall &
+operator<<(marshall &m, const std::list<A> &d) {
+    m << std::vector<A>(d.begin(), d.end());
+    return m;
+}
+
+template <class A, class B> marshall &
+operator<<(marshall &m, const std::pair<A,B> &d) {
+    m << d.first;
+    m << d.second;
+    return m;
+}
+
 class unmarshall {
        private:
                char *_buf;
@@ -175,9 +203,6 @@ class unmarshall {
                void unpack_req_header(req_header *h) {
                        //the first 4-byte is for channel to fill size of pdu
                        _ind = sizeof(rpc_sz_t); 
-#if RPC_CHECKSUMMING
-                       _ind += sizeof(rpc_checksum_t);
-#endif
                        unpack(&h->xid);
                        unpack(&h->proc);
                        unpack((int *)&h->clt_nonce);
@@ -189,13 +214,19 @@ class unmarshall {
                void unpack_reply_header(reply_header *h) {
                        //the first 4-byte is for channel to fill size of pdu
                        _ind = sizeof(rpc_sz_t); 
-#if RPC_CHECKSUMMING
-                       _ind += sizeof(rpc_checksum_t);
-#endif
                        unpack(&h->xid);
                        unpack(&h->ret);
                        _ind = RPC_HEADER_SZ;
                }
+
+        template <class OutputIterator>
+        void iterate(OutputIterator i, int n) {
+            while (n--) {
+                typename OutputIterator::value_type t;
+                *this >> t;
+                *i++ = t;
+            }
+        }
 };
 
 unmarshall& operator>>(unmarshall &, bool &);
@@ -208,54 +239,50 @@ unmarshall& operator>>(unmarshall &, int &);
 unmarshall& operator>>(unmarshall &, unsigned long long &);
 unmarshall& operator>>(unmarshall &, std::string &);
 
-template <class C> marshall &
-operator<<(marshall &m, std::vector<C> v)
-{
-       m << (unsigned int) v.size();
-       for(unsigned i = 0; i < v.size(); i++)
-               m << v[i];
-       return m;
-}
-
 template <class C> unmarshall &
 operator>>(unmarshall &u, std::vector<C> &v)
 {
        unsigned n;
        u >> n;
-       for(unsigned i = 0; i < n; i++){
-               C z;
-               u >> z;
-               v.push_back(z);
-       }
+    v.clear();
+    while (n--) {
+        C c;
+        u >> c;
+        v.push_back(c);
+    }
        return u;
 }
 
-template <class A, class B> marshall &
-operator<<(marshall &m, const std::map<A,B> &d) {
-       typename std::map<A,B>::const_iterator i;
-
-       m << (unsigned int) d.size();
-
-       for (i = d.begin(); i != d.end(); i++) {
-               m << i->first << i->second;
-       }
-       return m;
-}
-
 template <class A, class B> unmarshall &
 operator>>(unmarshall &u, std::map<A,B> &d) {
-       unsigned int n;
+       unsigned n;
        u >> n;
-
        d.clear();
-
-       for (unsigned int lcv = 0; lcv < n; lcv++) {
-               A a;
-               B b;
-               u >> a >> b;
-               d[a] = b;
-       }
+    while (n--) {
+        A a;
+        B b;
+        u >> a >> b;
+        d[a] = b;
+    }
        return u;
 }
 
+template <class C> unmarshall &
+operator>>(unmarshall &u, std::list<C> &l) {
+    unsigned n;
+    u >> n;
+    l.clear();
+    while (n--) {
+        C c;
+        u >> c;
+        l.push_back(c);
+    }
+    return u;
+}
+
+template <class A, class B> unmarshall &
+operator>>(unmarshall &u, std::pair<A,B> &d) {
+    return u >> d.first >> d.second;
+}
+
 #endif