THRIFT-922. cpp: Convert protocol classes to use non-virtual functions

Updated the thrift protocol classes to use non-virtual calls for most
functions.  The correct implementation is determined at compile time via
templates now.  Only the base TProtocol class falls back to using
virtual function calls.

git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@1005135 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am
index f36ac82..344e330 100644
--- a/lib/cpp/Makefile.am
+++ b/lib/cpp/Makefile.am
@@ -111,11 +111,11 @@
                          src/protocol/TCompactProtocol.h \
                          src/protocol/TDenseProtocol.h \
                          src/protocol/TDebugProtocol.h \
-                         src/protocol/TOneWayProtocol.h \
                          src/protocol/TBase64Utils.h \
                          src/protocol/TJSONProtocol.h \
                          src/protocol/TProtocolTap.h \
                          src/protocol/TProtocolException.h \
+                         src/protocol/TVirtualProtocol.h \
                          src/protocol/TProtocol.h
 
 include_transportdir = $(include_thriftdir)/transport
diff --git a/lib/cpp/src/protocol/TBinaryProtocol.h b/lib/cpp/src/protocol/TBinaryProtocol.h
index 7fd3de6..45c5842 100644
--- a/lib/cpp/src/protocol/TBinaryProtocol.h
+++ b/lib/cpp/src/protocol/TBinaryProtocol.h
@@ -21,6 +21,7 @@
 #define _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ 1
 
 #include "TProtocol.h"
+#include "TVirtualProtocol.h"
 
 #include <boost/shared_ptr.hpp>
 
@@ -31,7 +32,7 @@
  * binary format, essentially just spitting out the raw bytes.
  *
  */
-class TBinaryProtocol : public TProtocol {
+class TBinaryProtocol : public TVirtualProtocol<TBinaryProtocol> {
  protected:
   static const int32_t VERSION_MASK = 0xffff0000;
   static const int32_t VERSION_1 = 0x80010000;
@@ -39,7 +40,7 @@
 
  public:
   TBinaryProtocol(boost::shared_ptr<TTransport> trans) :
-    TProtocol(trans),
+    TVirtualProtocol<TBinaryProtocol>(trans),
     string_limit_(0),
     container_limit_(0),
     strict_read_(false),
@@ -52,7 +53,7 @@
                   int32_t container_limit,
                   bool strict_read,
                   bool strict_write) :
-    TProtocol(trans),
+    TVirtualProtocol<TBinaryProtocol>(trans),
     string_limit_(string_limit),
     container_limit_(container_limit),
     strict_read_(strict_read),
@@ -84,11 +85,11 @@
    * Writing functions.
    */
 
-  virtual uint32_t writeMessageBegin(const std::string& name,
-                                     const TMessageType messageType,
-                                     const int32_t seqid);
+  uint32_t writeMessageBegin(const std::string& name,
+                             const TMessageType messageType,
+                             const int32_t seqid);
 
-  virtual uint32_t writeMessageEnd();
+  uint32_t writeMessageEnd();
 
 
   uint32_t writeStructBegin(const char* name);
diff --git a/lib/cpp/src/protocol/TCompactProtocol.h b/lib/cpp/src/protocol/TCompactProtocol.h
index 1d940a2..77c4454 100644
--- a/lib/cpp/src/protocol/TCompactProtocol.h
+++ b/lib/cpp/src/protocol/TCompactProtocol.h
@@ -20,7 +20,7 @@
 #ifndef _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_H_
 #define _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_H_ 1
 
-#include "TProtocol.h"
+#include "TVirtualProtocol.h"
 
 #include <stack>
 #include <boost/shared_ptr.hpp>
@@ -30,7 +30,7 @@
 /**
  * C++ Implementation of the Compact Protocol as described in THRIFT-110
  */
-class TCompactProtocol : public TProtocol {
+class TCompactProtocol : public TVirtualProtocol<TCompactProtocol> {
 
  protected:
   static const int8_t  PROTOCOL_ID = 0x82;
@@ -86,7 +86,7 @@
 
  public:
   TCompactProtocol(boost::shared_ptr<TTransport> trans) :
-    TProtocol(trans),
+    TVirtualProtocol<TCompactProtocol>(trans),
     lastFieldId_(0),
     string_limit_(0),
     string_buf_(NULL),
@@ -99,7 +99,7 @@
   TCompactProtocol(boost::shared_ptr<TTransport> trans,
                    int32_t string_limit,
                    int32_t container_limit) :
-    TProtocol(trans),
+    TVirtualProtocol<TCompactProtocol>(trans),
     lastFieldId_(0),
     string_limit_(string_limit),
     string_buf_(NULL),
diff --git a/lib/cpp/src/protocol/TDebugProtocol.h b/lib/cpp/src/protocol/TDebugProtocol.h
index ab69e0c..1efcbd0 100644
--- a/lib/cpp/src/protocol/TDebugProtocol.h
+++ b/lib/cpp/src/protocol/TDebugProtocol.h
@@ -20,8 +20,7 @@
 #ifndef _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_
 #define _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ 1
 
-#include "TProtocol.h"
-#include "TOneWayProtocol.h"
+#include "TVirtualProtocol.h"
 
 #include <boost/shared_ptr.hpp>
 
@@ -46,7 +45,7 @@
  * Reading from this protocol is not supported.
  *
  */
-class TDebugProtocol : public TWriteOnlyProtocol {
+class TDebugProtocol : public TVirtualProtocol<TDebugProtocol> {
  private:
   enum write_state_t
   { UNINIT
@@ -59,7 +58,7 @@
 
  public:
   TDebugProtocol(boost::shared_ptr<TTransport> trans)
-    : TWriteOnlyProtocol(trans, "TDebugProtocol")
+    : TVirtualProtocol<TDebugProtocol>(trans)
     , string_limit_(DEFAULT_STRING_LIMIT)
     , string_prefix_size_(DEFAULT_STRING_PREFIX_SIZE)
   {
@@ -78,11 +77,11 @@
   }
 
 
-  virtual uint32_t writeMessageBegin(const std::string& name,
-                                     const TMessageType messageType,
-                                     const int32_t seqid);
+  uint32_t writeMessageBegin(const std::string& name,
+                             const TMessageType messageType,
+                             const int32_t seqid);
 
-  virtual uint32_t writeMessageEnd();
+  uint32_t writeMessageEnd();
 
 
   uint32_t writeStructBegin(const char* name);
diff --git a/lib/cpp/src/protocol/TDenseProtocol.h b/lib/cpp/src/protocol/TDenseProtocol.h
index 7655a47..ca2d427 100644
--- a/lib/cpp/src/protocol/TDenseProtocol.h
+++ b/lib/cpp/src/protocol/TDenseProtocol.h
@@ -56,7 +56,8 @@
  * methods within our versions.
  *
  */
-class TDenseProtocol : public TBinaryProtocol {
+class TDenseProtocol
+  : public TVirtualProtocol<TDenseProtocol, TBinaryProtocol> {
  protected:
   static const int32_t VERSION_MASK = 0xffff0000;
   // VERSION_1 (0x80010000)  is taken by TBinaryProtocol.
@@ -72,7 +73,7 @@
    */
   TDenseProtocol(boost::shared_ptr<TTransport> trans,
                  TypeSpec* type_spec = NULL) :
-    TBinaryProtocol(trans),
+    TVirtualProtocol<TDenseProtocol, TBinaryProtocol>(trans),
     type_spec_(type_spec),
     standalone_(true)
   {}
@@ -89,56 +90,54 @@
    * Writing functions.
    */
 
-  virtual uint32_t writeMessageBegin(const std::string& name,
-                                     const TMessageType messageType,
-                                     const int32_t seqid);
+  uint32_t writeMessageBegin(const std::string& name,
+                             const TMessageType messageType,
+                             const int32_t seqid);
 
-  virtual uint32_t writeMessageEnd();
+  uint32_t writeMessageEnd();
 
 
-  virtual uint32_t writeStructBegin(const char* name);
+  uint32_t writeStructBegin(const char* name);
 
-  virtual uint32_t writeStructEnd();
+  uint32_t writeStructEnd();
 
-  virtual uint32_t writeFieldBegin(const char* name,
-                                   const TType fieldType,
-                                   const int16_t fieldId);
+  uint32_t writeFieldBegin(const char* name,
+                           const TType fieldType,
+                           const int16_t fieldId);
 
-  virtual uint32_t writeFieldEnd();
+  uint32_t writeFieldEnd();
 
-  virtual uint32_t writeFieldStop();
+  uint32_t writeFieldStop();
 
-  virtual uint32_t writeMapBegin(const TType keyType,
-                                 const TType valType,
-                                 const uint32_t size);
+  uint32_t writeMapBegin(const TType keyType,
+                         const TType valType,
+                         const uint32_t size);
 
-  virtual uint32_t writeMapEnd();
+  uint32_t writeMapEnd();
 
-  virtual uint32_t writeListBegin(const TType elemType,
-                                  const uint32_t size);
+  uint32_t writeListBegin(const TType elemType, const uint32_t size);
 
-  virtual uint32_t writeListEnd();
+  uint32_t writeListEnd();
 
-  virtual uint32_t writeSetBegin(const TType elemType,
-                                 const uint32_t size);
+  uint32_t writeSetBegin(const TType elemType, const uint32_t size);
 
-  virtual uint32_t writeSetEnd();
+  uint32_t writeSetEnd();
 
-  virtual uint32_t writeBool(const bool value);
+  uint32_t writeBool(const bool value);
 
-  virtual uint32_t writeByte(const int8_t byte);
+  uint32_t writeByte(const int8_t byte);
 
-  virtual uint32_t writeI16(const int16_t i16);
+  uint32_t writeI16(const int16_t i16);
 
-  virtual uint32_t writeI32(const int32_t i32);
+  uint32_t writeI32(const int32_t i32);
 
-  virtual uint32_t writeI64(const int64_t i64);
+  uint32_t writeI64(const int64_t i64);
 
-  virtual uint32_t writeDouble(const double dub);
+  uint32_t writeDouble(const double dub);
 
-  virtual uint32_t writeString(const std::string& str);
+  uint32_t writeString(const std::string& str);
 
-  virtual uint32_t writeBinary(const std::string& str);
+  uint32_t writeBinary(const std::string& str);
 
 
   /*
diff --git a/lib/cpp/src/protocol/TJSONProtocol.cpp b/lib/cpp/src/protocol/TJSONProtocol.cpp
index 2a9c8f0..ed2f518 100644
--- a/lib/cpp/src/protocol/TJSONProtocol.cpp
+++ b/lib/cpp/src/protocol/TJSONProtocol.cpp
@@ -357,7 +357,7 @@
 
 
 TJSONProtocol::TJSONProtocol(boost::shared_ptr<TTransport> ptrans) :
-  TProtocol(ptrans),
+  TVirtualProtocol<TJSONProtocol>(ptrans),
   context_(new TJSONContext()),
   reader_(*ptrans) {
 }
diff --git a/lib/cpp/src/protocol/TJSONProtocol.h b/lib/cpp/src/protocol/TJSONProtocol.h
index 2df499a..cd42f5e 100644
--- a/lib/cpp/src/protocol/TJSONProtocol.h
+++ b/lib/cpp/src/protocol/TJSONProtocol.h
@@ -20,7 +20,7 @@
 #ifndef _THRIFT_PROTOCOL_TJSONPROTOCOL_H_
 #define _THRIFT_PROTOCOL_TJSONPROTOCOL_H_ 1
 
-#include "TProtocol.h"
+#include "TVirtualProtocol.h"
 
 #include <stack>
 
@@ -92,7 +92,7 @@
  * transmission. I don't know of any work-around for this issue.
  *
  */
-class TJSONProtocol : public TProtocol {
+class TJSONProtocol : public TVirtualProtocol<TJSONProtocol> {
  public:
 
   TJSONProtocol(boost::shared_ptr<TTransport> ptrans);
diff --git a/lib/cpp/src/protocol/TOneWayProtocol.h b/lib/cpp/src/protocol/TOneWayProtocol.h
deleted file mode 100644
index 6f08fe1..0000000
--- a/lib/cpp/src/protocol/TOneWayProtocol.h
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#ifndef _THRIFT_PROTOCOL_TONEWAYPROTOCOL_H_
-#define _THRIFT_PROTOCOL_TONEWAYPROTOCOL_H_ 1
-
-#include "TProtocol.h"
-
-namespace apache { namespace thrift { namespace protocol {
-
-/**
- * Abstract class for implementing a protocol that can only be written,
- * not read.
- *
- */
-class TWriteOnlyProtocol : public TProtocol {
- public:
-  /**
-   * @param subclass_name  The name of the concrete subclass.
-   */
-  TWriteOnlyProtocol(boost::shared_ptr<TTransport> trans,
-                     const std::string& subclass_name)
-    : TProtocol(trans)
-    , subclass_(subclass_name)
-  {}
-
-  // All writing functions remain abstract.
-
-  /**
-   * Reading functions all throw an exception.
-   */
-
-  uint32_t readMessageBegin(std::string& name,
-                            TMessageType& messageType,
-                            int32_t& seqid) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readMessageEnd() {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readStructBegin(std::string& name) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readStructEnd() {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readFieldBegin(std::string& name,
-                          TType& fieldType,
-                          int16_t& fieldId) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readFieldEnd() {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readMapBegin(TType& keyType,
-                        TType& valType,
-                        uint32_t& size) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readMapEnd() {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readListBegin(TType& elemType,
-                         uint32_t& size) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readListEnd() {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readSetBegin(TType& elemType,
-                        uint32_t& size) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readSetEnd() {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readBool(bool& value) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readByte(int8_t& byte) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readI16(int16_t& i16) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readI32(int32_t& i32) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readI64(int64_t& i64) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readDouble(double& dub) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readString(std::string& str) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
-  uint32_t readBinary(std::string& str) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support reading (yet).");
-  }
-
- private:
-  std::string subclass_;
-};
-
-
-/**
- * Abstract class for implementing a protocol that can only be read,
- * not written.
- *
- */
-class TReadOnlyProtocol : public TProtocol {
- public:
-  /**
-   * @param subclass_name  The name of the concrete subclass.
-   */
-  TReadOnlyProtocol(boost::shared_ptr<TTransport> trans,
-                    const std::string& subclass_name)
-    : TProtocol(trans)
-    , subclass_(subclass_name)
-  {}
-
-  // All reading functions remain abstract.
-
-  /**
-   * Writing functions all throw an exception.
-   */
-
-  uint32_t writeMessageBegin(const std::string& name,
-                             const TMessageType messageType,
-                             const int32_t seqid) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeMessageEnd() {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-
-  uint32_t writeStructBegin(const char* name) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeStructEnd() {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeFieldBegin(const char* name,
-                           const TType fieldType,
-                           const int16_t fieldId) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeFieldEnd() {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeFieldStop() {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeMapBegin(const TType keyType,
-                         const TType valType,
-                         const uint32_t size) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeMapEnd() {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeListBegin(const TType elemType,
-                          const uint32_t size) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeListEnd() {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeSetBegin(const TType elemType,
-                         const uint32_t size) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeSetEnd() {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeBool(const bool value) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeByte(const int8_t byte) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeI16(const int16_t i16) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeI32(const int32_t i32) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeI64(const int64_t i64) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeDouble(const double dub) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeString(const std::string& str) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
-  uint32_t writeBinary(const std::string& str) {
-    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
-        subclass_ + " does not support writing (yet).");
-  }
-
- private:
-  std::string subclass_;
-};
-
-}}} // apache::thrift::protocol
-
-#endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_
diff --git a/lib/cpp/src/protocol/TProtocol.h b/lib/cpp/src/protocol/TProtocol.h
index 2e24f75..6bf7e3b 100644
--- a/lib/cpp/src/protocol/TProtocol.h
+++ b/lib/cpp/src/protocol/TProtocol.h
@@ -165,6 +165,111 @@
   T_ONEWAY     = 4
 };
 
+
+/**
+ * Helper template for implementing TProtocol::skip().
+ *
+ * Templatized to avoid having to make virtual function calls.
+ */
+template <class Protocol_>
+uint32_t skip(Protocol_& prot, TType type) {
+  switch (type) {
+  case T_BOOL:
+    {
+      bool boolv;
+      return prot.readBool(boolv);
+    }
+  case T_BYTE:
+    {
+      int8_t bytev;
+      return prot.readByte(bytev);
+    }
+  case T_I16:
+    {
+      int16_t i16;
+      return prot.readI16(i16);
+    }
+  case T_I32:
+    {
+      int32_t i32;
+      return prot.readI32(i32);
+    }
+  case T_I64:
+    {
+      int64_t i64;
+      return prot.readI64(i64);
+    }
+  case T_DOUBLE:
+    {
+      double dub;
+      return prot.readDouble(dub);
+    }
+  case T_STRING:
+    {
+      std::string str;
+      return prot.readBinary(str);
+    }
+  case T_STRUCT:
+    {
+      uint32_t result = 0;
+      std::string name;
+      int16_t fid;
+      TType ftype;
+      result += prot.readStructBegin(name);
+      while (true) {
+        result += prot.readFieldBegin(name, ftype, fid);
+        if (ftype == T_STOP) {
+          break;
+        }
+        result += skip(prot, ftype);
+        result += prot.readFieldEnd();
+      }
+      result += prot.readStructEnd();
+      return result;
+    }
+  case T_MAP:
+    {
+      uint32_t result = 0;
+      TType keyType;
+      TType valType;
+      uint32_t i, size;
+      result += prot.readMapBegin(keyType, valType, size);
+      for (i = 0; i < size; i++) {
+        result += skip(prot, keyType);
+        result += skip(prot, valType);
+      }
+      result += prot.readMapEnd();
+      return result;
+    }
+  case T_SET:
+    {
+      uint32_t result = 0;
+      TType elemType;
+      uint32_t i, size;
+      result += prot.readSetBegin(elemType, size);
+      for (i = 0; i < size; i++) {
+        result += skip(prot, elemType);
+      }
+      result += prot.readSetEnd();
+      return result;
+    }
+  case T_LIST:
+    {
+      uint32_t result = 0;
+      TType elemType;
+      uint32_t i, size;
+      result += prot.readListBegin(elemType, size);
+      for (i = 0; i < size; i++) {
+        result += skip(prot, elemType);
+      }
+      result += prot.readListEnd();
+      return result;
+    }
+  default:
+    return 0;
+  }
+}
+
 /**
  * Abstract class for a thrift protocol driver. These are all the methods that
  * a protocol must implement. Essentially, there must be some way of reading
@@ -187,108 +292,324 @@
    * Writing functions.
    */
 
-  virtual uint32_t writeMessageBegin(const std::string& name,
-                                     const TMessageType messageType,
-                                     const int32_t seqid) = 0;
+  virtual uint32_t writeMessageBegin_virt(const std::string& name,
+                                          const TMessageType messageType,
+                                          const int32_t seqid) = 0;
 
-  virtual uint32_t writeMessageEnd() = 0;
+  virtual uint32_t writeMessageEnd_virt() = 0;
 
 
-  virtual uint32_t writeStructBegin(const char* name) = 0;
+  virtual uint32_t writeStructBegin_virt(const char* name) = 0;
 
-  virtual uint32_t writeStructEnd() = 0;
+  virtual uint32_t writeStructEnd_virt() = 0;
 
-  virtual uint32_t writeFieldBegin(const char* name,
-                                   const TType fieldType,
-                                   const int16_t fieldId) = 0;
+  virtual uint32_t writeFieldBegin_virt(const char* name,
+                                        const TType fieldType,
+                                        const int16_t fieldId) = 0;
 
-  virtual uint32_t writeFieldEnd() = 0;
+  virtual uint32_t writeFieldEnd_virt() = 0;
 
-  virtual uint32_t writeFieldStop() = 0;
+  virtual uint32_t writeFieldStop_virt() = 0;
 
-  virtual uint32_t writeMapBegin(const TType keyType,
-                                 const TType valType,
-                                 const uint32_t size) = 0;
+  virtual uint32_t writeMapBegin_virt(const TType keyType,
+                                      const TType valType,
+                                      const uint32_t size) = 0;
 
-  virtual uint32_t writeMapEnd() = 0;
+  virtual uint32_t writeMapEnd_virt() = 0;
 
-  virtual uint32_t writeListBegin(const TType elemType,
-                                  const uint32_t size) = 0;
+  virtual uint32_t writeListBegin_virt(const TType elemType,
+                                       const uint32_t size) = 0;
 
-  virtual uint32_t writeListEnd() = 0;
+  virtual uint32_t writeListEnd_virt() = 0;
 
-  virtual uint32_t writeSetBegin(const TType elemType,
-                                 const uint32_t size) = 0;
+  virtual uint32_t writeSetBegin_virt(const TType elemType,
+                                      const uint32_t size) = 0;
 
-  virtual uint32_t writeSetEnd() = 0;
+  virtual uint32_t writeSetEnd_virt() = 0;
 
-  virtual uint32_t writeBool(const bool value) = 0;
+  virtual uint32_t writeBool_virt(const bool value) = 0;
 
-  virtual uint32_t writeByte(const int8_t byte) = 0;
+  virtual uint32_t writeByte_virt(const int8_t byte) = 0;
 
-  virtual uint32_t writeI16(const int16_t i16) = 0;
+  virtual uint32_t writeI16_virt(const int16_t i16) = 0;
 
-  virtual uint32_t writeI32(const int32_t i32) = 0;
+  virtual uint32_t writeI32_virt(const int32_t i32) = 0;
 
-  virtual uint32_t writeI64(const int64_t i64) = 0;
+  virtual uint32_t writeI64_virt(const int64_t i64) = 0;
 
-  virtual uint32_t writeDouble(const double dub) = 0;
+  virtual uint32_t writeDouble_virt(const double dub) = 0;
 
-  virtual uint32_t writeString(const std::string& str) = 0;
+  virtual uint32_t writeString_virt(const std::string& str) = 0;
 
-  virtual uint32_t writeBinary(const std::string& str) = 0;
+  virtual uint32_t writeBinary_virt(const std::string& str) = 0;
+
+  uint32_t writeMessageBegin(const std::string& name,
+                             const TMessageType messageType,
+                             const int32_t seqid) {
+    T_VIRTUAL_CALL();
+    return writeMessageBegin_virt(name, messageType, seqid);
+  }
+
+  uint32_t writeMessageEnd() {
+    T_VIRTUAL_CALL();
+    return writeMessageEnd_virt();
+  }
+
+
+  uint32_t writeStructBegin(const char* name) {
+    T_VIRTUAL_CALL();
+    return writeStructBegin_virt(name);
+  }
+
+  uint32_t writeStructEnd() {
+    T_VIRTUAL_CALL();
+    return writeStructEnd_virt();
+  }
+
+  uint32_t writeFieldBegin(const char* name,
+                           const TType fieldType,
+                           const int16_t fieldId) {
+    T_VIRTUAL_CALL();
+    return writeFieldBegin_virt(name, fieldType, fieldId);
+  }
+
+  uint32_t writeFieldEnd() {
+    T_VIRTUAL_CALL();
+    return writeFieldEnd_virt();
+  }
+
+  uint32_t writeFieldStop() {
+    T_VIRTUAL_CALL();
+    return writeFieldStop_virt();
+  }
+
+  uint32_t writeMapBegin(const TType keyType,
+                         const TType valType,
+                         const uint32_t size) {
+    T_VIRTUAL_CALL();
+    return writeMapBegin_virt(keyType, valType, size);
+  }
+
+  uint32_t writeMapEnd() {
+    T_VIRTUAL_CALL();
+    return writeMapEnd_virt();
+  }
+
+  uint32_t writeListBegin(const TType elemType, const uint32_t size) {
+    T_VIRTUAL_CALL();
+    return writeListBegin_virt(elemType, size);
+  }
+
+  uint32_t writeListEnd() {
+    T_VIRTUAL_CALL();
+    return writeListEnd_virt();
+  }
+
+  uint32_t writeSetBegin(const TType elemType, const uint32_t size) {
+    T_VIRTUAL_CALL();
+    return writeSetBegin_virt(elemType, size);
+  }
+
+  uint32_t writeSetEnd() {
+    T_VIRTUAL_CALL();
+    return writeSetEnd_virt();
+  }
+
+  uint32_t writeBool(const bool value) {
+    T_VIRTUAL_CALL();
+    return writeBool_virt(value);
+  }
+
+  uint32_t writeByte(const int8_t byte) {
+    T_VIRTUAL_CALL();
+    return writeByte_virt(byte);
+  }
+
+  uint32_t writeI16(const int16_t i16) {
+    T_VIRTUAL_CALL();
+    return writeI16_virt(i16);
+  }
+
+  uint32_t writeI32(const int32_t i32) {
+    T_VIRTUAL_CALL();
+    return writeI32_virt(i32);
+  }
+
+  uint32_t writeI64(const int64_t i64) {
+    T_VIRTUAL_CALL();
+    return writeI64_virt(i64);
+  }
+
+  uint32_t writeDouble(const double dub) {
+    T_VIRTUAL_CALL();
+    return writeDouble_virt(dub);
+  }
+
+  uint32_t writeString(const std::string& str) {
+    T_VIRTUAL_CALL();
+    return writeString_virt(str);
+  }
+
+  uint32_t writeBinary(const std::string& str) {
+    T_VIRTUAL_CALL();
+    return writeBinary_virt(str);
+  }
 
   /**
    * Reading functions
    */
 
-  virtual uint32_t readMessageBegin(std::string& name,
-                                    TMessageType& messageType,
-                                    int32_t& seqid) = 0;
+  virtual uint32_t readMessageBegin_virt(std::string& name,
+                                         TMessageType& messageType,
+                                         int32_t& seqid) = 0;
 
-  virtual uint32_t readMessageEnd() = 0;
+  virtual uint32_t readMessageEnd_virt() = 0;
 
-  virtual uint32_t readStructBegin(std::string& name) = 0;
+  virtual uint32_t readStructBegin_virt(std::string& name) = 0;
 
-  virtual uint32_t readStructEnd() = 0;
+  virtual uint32_t readStructEnd_virt() = 0;
 
-  virtual uint32_t readFieldBegin(std::string& name,
-                                  TType& fieldType,
-                                  int16_t& fieldId) = 0;
+  virtual uint32_t readFieldBegin_virt(std::string& name,
+                                       TType& fieldType,
+                                       int16_t& fieldId) = 0;
 
-  virtual uint32_t readFieldEnd() = 0;
+  virtual uint32_t readFieldEnd_virt() = 0;
 
-  virtual uint32_t readMapBegin(TType& keyType,
-                                TType& valType,
-                                uint32_t& size) = 0;
+  virtual uint32_t readMapBegin_virt(TType& keyType,
+                                     TType& valType,
+                                     uint32_t& size) = 0;
 
-  virtual uint32_t readMapEnd() = 0;
+  virtual uint32_t readMapEnd_virt() = 0;
 
-  virtual uint32_t readListBegin(TType& elemType,
-                                 uint32_t& size) = 0;
+  virtual uint32_t readListBegin_virt(TType& elemType,
+                                      uint32_t& size) = 0;
 
-  virtual uint32_t readListEnd() = 0;
+  virtual uint32_t readListEnd_virt() = 0;
 
-  virtual uint32_t readSetBegin(TType& elemType,
-                                uint32_t& size) = 0;
+  virtual uint32_t readSetBegin_virt(TType& elemType,
+                                     uint32_t& size) = 0;
 
-  virtual uint32_t readSetEnd() = 0;
+  virtual uint32_t readSetEnd_virt() = 0;
 
-  virtual uint32_t readBool(bool& value) = 0;
+  virtual uint32_t readBool_virt(bool& value) = 0;
 
-  virtual uint32_t readByte(int8_t& byte) = 0;
+  virtual uint32_t readByte_virt(int8_t& byte) = 0;
 
-  virtual uint32_t readI16(int16_t& i16) = 0;
+  virtual uint32_t readI16_virt(int16_t& i16) = 0;
 
-  virtual uint32_t readI32(int32_t& i32) = 0;
+  virtual uint32_t readI32_virt(int32_t& i32) = 0;
 
-  virtual uint32_t readI64(int64_t& i64) = 0;
+  virtual uint32_t readI64_virt(int64_t& i64) = 0;
 
-  virtual uint32_t readDouble(double& dub) = 0;
+  virtual uint32_t readDouble_virt(double& dub) = 0;
 
-  virtual uint32_t readString(std::string& str) = 0;
+  virtual uint32_t readString_virt(std::string& str) = 0;
 
-  virtual uint32_t readBinary(std::string& str) = 0;
+  virtual uint32_t readBinary_virt(std::string& str) = 0;
+
+  uint32_t readMessageBegin(std::string& name,
+                            TMessageType& messageType,
+                            int32_t& seqid) {
+    T_VIRTUAL_CALL();
+    return readMessageBegin_virt(name, messageType, seqid);
+  }
+
+  uint32_t readMessageEnd() {
+    T_VIRTUAL_CALL();
+    return readMessageEnd_virt();
+  }
+
+  uint32_t readStructBegin(std::string& name) {
+    T_VIRTUAL_CALL();
+    return readStructBegin_virt(name);
+  }
+
+  uint32_t readStructEnd() {
+    T_VIRTUAL_CALL();
+    return readStructEnd_virt();
+  }
+
+  uint32_t readFieldBegin(std::string& name,
+                          TType& fieldType,
+                          int16_t& fieldId) {
+    T_VIRTUAL_CALL();
+    return readFieldBegin_virt(name, fieldType, fieldId);
+  }
+
+  uint32_t readFieldEnd() {
+    T_VIRTUAL_CALL();
+    return readFieldEnd_virt();
+  }
+
+  uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size) {
+    T_VIRTUAL_CALL();
+    return readMapBegin_virt(keyType, valType, size);
+  }
+
+  uint32_t readMapEnd() {
+    T_VIRTUAL_CALL();
+    return readMapEnd_virt();
+  }
+
+  uint32_t readListBegin(TType& elemType, uint32_t& size) {
+    T_VIRTUAL_CALL();
+    return readListBegin_virt(elemType, size);
+  }
+
+  uint32_t readListEnd() {
+    T_VIRTUAL_CALL();
+    return readListEnd_virt();
+  }
+
+  uint32_t readSetBegin(TType& elemType, uint32_t& size) {
+    T_VIRTUAL_CALL();
+    return readSetBegin_virt(elemType, size);
+  }
+
+  uint32_t readSetEnd() {
+    T_VIRTUAL_CALL();
+    return readSetEnd_virt();
+  }
+
+  uint32_t readBool(bool& value) {
+    T_VIRTUAL_CALL();
+    return readBool_virt(value);
+  }
+
+  uint32_t readByte(int8_t& byte) {
+    T_VIRTUAL_CALL();
+    return readByte_virt(byte);
+  }
+
+  uint32_t readI16(int16_t& i16) {
+    T_VIRTUAL_CALL();
+    return readI16_virt(i16);
+  }
+
+  uint32_t readI32(int32_t& i32) {
+    T_VIRTUAL_CALL();
+    return readI32_virt(i32);
+  }
+
+  uint32_t readI64(int64_t& i64) {
+    T_VIRTUAL_CALL();
+    return readI64_virt(i64);
+  }
+
+  uint32_t readDouble(double& dub) {
+    T_VIRTUAL_CALL();
+    return readDouble_virt(dub);
+  }
+
+  uint32_t readString(std::string& str) {
+    T_VIRTUAL_CALL();
+    return readString_virt(str);
+  }
+
+  uint32_t readBinary(std::string& str) {
+    T_VIRTUAL_CALL();
+    return readBinary_virt(str);
+  }
 
   uint32_t readBool(std::vector<bool>::reference ref) {
     bool value;
@@ -301,101 +622,11 @@
    * Method to arbitrarily skip over data.
    */
   uint32_t skip(TType type) {
-    switch (type) {
-    case T_BOOL:
-      {
-        bool boolv;
-        return readBool(boolv);
-      }
-    case T_BYTE:
-      {
-        int8_t bytev;
-        return readByte(bytev);
-      }
-    case T_I16:
-      {
-        int16_t i16;
-        return readI16(i16);
-      }
-    case T_I32:
-      {
-        int32_t i32;
-        return readI32(i32);
-      }
-    case T_I64:
-      {
-        int64_t i64;
-        return readI64(i64);
-      }
-    case T_DOUBLE:
-      {
-        double dub;
-        return readDouble(dub);
-      }
-    case T_STRING:
-      {
-        std::string str;
-        return readBinary(str);
-      }
-    case T_STRUCT:
-      {
-        uint32_t result = 0;
-        std::string name;
-        int16_t fid;
-        TType ftype;
-        result += readStructBegin(name);
-        while (true) {
-          result += readFieldBegin(name, ftype, fid);
-          if (ftype == T_STOP) {
-            break;
-          }
-          result += skip(ftype);
-          result += readFieldEnd();
-        }
-        result += readStructEnd();
-        return result;
-      }
-    case T_MAP:
-      {
-        uint32_t result = 0;
-        TType keyType;
-        TType valType;
-        uint32_t i, size;
-        result += readMapBegin(keyType, valType, size);
-        for (i = 0; i < size; i++) {
-          result += skip(keyType);
-          result += skip(valType);
-        }
-        result += readMapEnd();
-        return result;
-      }
-    case T_SET:
-      {
-        uint32_t result = 0;
-        TType elemType;
-        uint32_t i, size;
-        result += readSetBegin(elemType, size);
-        for (i = 0; i < size; i++) {
-          result += skip(elemType);
-        }
-        result += readSetEnd();
-        return result;
-      }
-    case T_LIST:
-      {
-        uint32_t result = 0;
-        TType elemType;
-        uint32_t i, size;
-        result += readListBegin(elemType, size);
-        for (i = 0; i < size; i++) {
-          result += skip(elemType);
-        }
-        result += readListEnd();
-        return result;
-      }
-    default:
-      return 0;
-    }
+    T_VIRTUAL_CALL();
+    return skip_virt(type);
+  }
+  virtual uint32_t skip_virt(TType type) {
+    return ::apache::thrift::protocol::skip(*this, type);
   }
 
   inline boost::shared_ptr<TTransport> getTransport() {
diff --git a/lib/cpp/src/protocol/TProtocolTap.h b/lib/cpp/src/protocol/TProtocolTap.h
index 5580216..26fbd3a 100644
--- a/lib/cpp/src/protocol/TProtocolTap.h
+++ b/lib/cpp/src/protocol/TProtocolTap.h
@@ -20,7 +20,7 @@
 #ifndef _THRIFT_PROTOCOL_TPROTOCOLTAP_H_
 #define _THRIFT_PROTOCOL_TPROTOCOLTAP_H_ 1
 
-#include <protocol/TOneWayProtocol.h>
+#include <protocol/TVirtualProtocol.h>
 
 namespace apache { namespace thrift { namespace protocol {
 
@@ -32,44 +32,44 @@
  * second protocol object.
  *
  */
-class TProtocolTap : public TReadOnlyProtocol {
+class TProtocolTap : public TVirtualProtocol<TProtocolTap> {
  public:
    TProtocolTap(boost::shared_ptr<TProtocol> source,
                 boost::shared_ptr<TProtocol> sink)
-     : TReadOnlyProtocol(source->getTransport(), "TProtocolTap")
+     : TVirtualProtocol<TProtocolTap>(source->getTransport())
      , source_(source)
      , sink_(sink)
   {}
 
-  virtual uint32_t readMessageBegin(std::string& name,
-                                    TMessageType& messageType,
-                                    int32_t& seqid) {
+  uint32_t readMessageBegin(std::string& name,
+                            TMessageType& messageType,
+                            int32_t& seqid) {
     uint32_t rv = source_->readMessageBegin(name, messageType, seqid);
     sink_->writeMessageBegin(name, messageType, seqid);
     return rv;
   }
 
-  virtual uint32_t readMessageEnd() {
+  uint32_t readMessageEnd() {
     uint32_t rv = source_->readMessageEnd();
     sink_->writeMessageEnd();
     return rv;
   }
 
-  virtual uint32_t readStructBegin(std::string& name) {
+  uint32_t readStructBegin(std::string& name) {
     uint32_t rv = source_->readStructBegin(name);
     sink_->writeStructBegin(name.c_str());
     return rv;
   }
 
-  virtual uint32_t readStructEnd() {
+  uint32_t readStructEnd() {
     uint32_t rv = source_->readStructEnd();
     sink_->writeStructEnd();
     return rv;
   }
 
-  virtual uint32_t readFieldBegin(std::string& name,
-                                  TType& fieldType,
-                                  int16_t& fieldId) {
+  uint32_t readFieldBegin(std::string& name,
+                          TType& fieldType,
+                          int16_t& fieldId) {
     uint32_t rv = source_->readFieldBegin(name, fieldType, fieldId);
     if (fieldType == T_STOP) {
       sink_->writeFieldStop();
@@ -80,98 +80,96 @@
   }
 
 
-  virtual uint32_t readFieldEnd() {
+  uint32_t readFieldEnd() {
     uint32_t rv = source_->readFieldEnd();
     sink_->writeFieldEnd();
     return rv;
   }
 
-  virtual uint32_t readMapBegin(TType& keyType,
-                                TType& valType,
-                                uint32_t& size) {
+  uint32_t readMapBegin(TType& keyType,
+                        TType& valType,
+                        uint32_t& size) {
     uint32_t rv = source_->readMapBegin(keyType, valType, size);
     sink_->writeMapBegin(keyType, valType, size);
     return rv;
   }
 
 
-  virtual uint32_t readMapEnd() {
+  uint32_t readMapEnd() {
     uint32_t rv = source_->readMapEnd();
     sink_->writeMapEnd();
     return rv;
   }
 
-  virtual uint32_t readListBegin(TType& elemType,
-                                 uint32_t& size) {
+  uint32_t readListBegin(TType& elemType, uint32_t& size) {
     uint32_t rv = source_->readListBegin(elemType, size);
     sink_->writeListBegin(elemType, size);
     return rv;
   }
 
 
-  virtual uint32_t readListEnd() {
+  uint32_t readListEnd() {
     uint32_t rv = source_->readListEnd();
     sink_->writeListEnd();
     return rv;
   }
 
-  virtual uint32_t readSetBegin(TType& elemType,
-                                uint32_t& size) {
+  uint32_t readSetBegin(TType& elemType, uint32_t& size) {
     uint32_t rv = source_->readSetBegin(elemType, size);
     sink_->writeSetBegin(elemType, size);
     return rv;
   }
 
 
-  virtual uint32_t readSetEnd() {
+  uint32_t readSetEnd() {
     uint32_t rv = source_->readSetEnd();
     sink_->writeSetEnd();
     return rv;
   }
 
-  virtual uint32_t readBool(bool& value) {
+  uint32_t readBool(bool& value) {
     uint32_t rv = source_->readBool(value);
     sink_->writeBool(value);
     return rv;
   }
 
-  virtual uint32_t readByte(int8_t& byte) {
+  uint32_t readByte(int8_t& byte) {
     uint32_t rv = source_->readByte(byte);
     sink_->writeByte(byte);
     return rv;
   }
 
-  virtual uint32_t readI16(int16_t& i16) {
+  uint32_t readI16(int16_t& i16) {
     uint32_t rv = source_->readI16(i16);
     sink_->writeI16(i16);
     return rv;
   }
 
-  virtual uint32_t readI32(int32_t& i32) {
+  uint32_t readI32(int32_t& i32) {
     uint32_t rv = source_->readI32(i32);
     sink_->writeI32(i32);
     return rv;
   }
 
-  virtual uint32_t readI64(int64_t& i64) {
+  uint32_t readI64(int64_t& i64) {
     uint32_t rv = source_->readI64(i64);
     sink_->writeI64(i64);
     return rv;
   }
 
-  virtual uint32_t readDouble(double& dub) {
+  uint32_t readDouble(double& dub) {
     uint32_t rv = source_->readDouble(dub);
     sink_->writeDouble(dub);
     return rv;
   }
 
-  virtual uint32_t readString(std::string& str) {
+  uint32_t readString(std::string& str) {
     uint32_t rv = source_->readString(str);
     sink_->writeString(str);
     return rv;
   }
 
-  virtual uint32_t readBinary(std::string& str) {
+  uint32_t readBinary(std::string& str) {
     uint32_t rv = source_->readBinary(str);
     sink_->writeBinary(str);
     return rv;
diff --git a/lib/cpp/src/protocol/TVirtualProtocol.h b/lib/cpp/src/protocol/TVirtualProtocol.h
new file mode 100644
index 0000000..7f01570
--- /dev/null
+++ b/lib/cpp/src/protocol/TVirtualProtocol.h
@@ -0,0 +1,495 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_
+#define _THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_ 1
+
+#include <protocol/TProtocol.h>
+
+namespace apache { namespace thrift { namespace protocol {
+
+using apache::thrift::transport::TTransport;
+
+/**
+ * Helper class that provides default implementations of TProtocol methods.
+ *
+ * This class provides default implementations of the non-virtual TProtocol
+ * methods.  It exists primarily so TVirtualProtocol can derive from it.  It
+ * prevents TVirtualProtocol methods from causing infinite recursion if the
+ * non-virtual methods are not overridden by the TVirtualProtocol subclass.
+ *
+ * You probably don't want to use this class directly.  Use TVirtualProtocol
+ * instead.
+ */
+class TProtocolDefaults : public TProtocol {
+ public:
+  uint32_t readMessageBegin(std::string& name,
+                            TMessageType& messageType,
+                            int32_t& seqid) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readMessageEnd() {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readStructBegin(std::string& name) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readStructEnd() {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readFieldBegin(std::string& name,
+                          TType& fieldType,
+                          int16_t& fieldId) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readFieldEnd() {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readMapEnd() {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readListBegin(TType& elemType, uint32_t& size) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readListEnd() {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readSetBegin(TType& elemType, uint32_t& size) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readSetEnd() {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readBool(bool& value) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readByte(int8_t& byte) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readI16(int16_t& i16) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readI32(int32_t& i32) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readI64(int64_t& i64) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readDouble(double& dub) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readString(std::string& str) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t readBinary(std::string& str) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support reading (yet).");
+  }
+
+  uint32_t writeMessageBegin(const std::string& name,
+                             const TMessageType messageType,
+                             const int32_t seqid) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeMessageEnd() {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+
+  uint32_t writeStructBegin(const char* name) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeStructEnd() {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeFieldBegin(const char* name,
+                           const TType fieldType,
+                           const int16_t fieldId) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeFieldEnd() {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeFieldStop() {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeMapBegin(const TType keyType,
+                         const TType valType,
+                         const uint32_t size) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeMapEnd() {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeListBegin(const TType elemType, const uint32_t size) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeListEnd() {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeSetBegin(const TType elemType, const uint32_t size) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeSetEnd() {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeBool(const bool value) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeByte(const int8_t byte) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeI16(const int16_t i16) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeI32(const int32_t i32) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeI64(const int64_t i64) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeDouble(const double dub) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeString(const std::string& str) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t writeBinary(const std::string& str) {
+    throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+                             "this protocol does not support writing (yet).");
+  }
+
+  uint32_t skip(TType type) {
+    return ::apache::thrift::protocol::skip(*this, type);
+  }
+
+ protected:
+  TProtocolDefaults(boost::shared_ptr<TTransport> ptrans)
+    : TProtocol(ptrans)
+  {}
+};
+
+/**
+ * Concrete TProtocol classes should inherit from TVirtualProtocol
+ * so they don't have to manually override virtual methods.
+ */
+template <class Protocol_, class Super_=TProtocolDefaults>
+class TVirtualProtocol : public Super_ {
+ public:
+  /**
+   * Writing functions.
+   */
+
+  virtual uint32_t writeMessageBegin_virt(const std::string& name,
+                                          const TMessageType messageType,
+                                          const int32_t seqid) {
+    return static_cast<Protocol_*>(this)->writeMessageBegin(name, messageType,
+                                                            seqid);
+  }
+
+  virtual uint32_t writeMessageEnd_virt() {
+    return static_cast<Protocol_*>(this)->writeMessageEnd();
+  }
+
+
+  virtual uint32_t writeStructBegin_virt(const char* name) {
+    return static_cast<Protocol_*>(this)->writeStructBegin(name);
+  }
+
+  virtual uint32_t writeStructEnd_virt() {
+    return static_cast<Protocol_*>(this)->writeStructEnd();
+  }
+
+  virtual uint32_t writeFieldBegin_virt(const char* name,
+                                        const TType fieldType,
+                                        const int16_t fieldId) {
+    return static_cast<Protocol_*>(this)->writeFieldBegin(name, fieldType,
+                                                          fieldId);
+  }
+
+  virtual uint32_t writeFieldEnd_virt() {
+    return static_cast<Protocol_*>(this)->writeFieldEnd();
+  }
+
+  virtual uint32_t writeFieldStop_virt() {
+    return static_cast<Protocol_*>(this)->writeFieldStop();
+  }
+
+  virtual uint32_t writeMapBegin_virt(const TType keyType,
+                                      const TType valType,
+                                      const uint32_t size) {
+    return static_cast<Protocol_*>(this)->writeMapBegin(keyType, valType, size);
+  }
+
+  virtual uint32_t writeMapEnd_virt() {
+    return static_cast<Protocol_*>(this)->writeMapEnd();
+  }
+
+  virtual uint32_t writeListBegin_virt(const TType elemType,
+                                       const uint32_t size) {
+    return static_cast<Protocol_*>(this)->writeListBegin(elemType, size);
+  }
+
+  virtual uint32_t writeListEnd_virt() {
+    return static_cast<Protocol_*>(this)->writeListEnd();
+  }
+
+  virtual uint32_t writeSetBegin_virt(const TType elemType,
+                                      const uint32_t size) {
+    return static_cast<Protocol_*>(this)->writeSetBegin(elemType, size);
+  }
+
+  virtual uint32_t writeSetEnd_virt() {
+    return static_cast<Protocol_*>(this)->writeSetEnd();
+  }
+
+  virtual uint32_t writeBool_virt(const bool value) {
+    return static_cast<Protocol_*>(this)->writeBool(value);
+  }
+
+  virtual uint32_t writeByte_virt(const int8_t byte) {
+    return static_cast<Protocol_*>(this)->writeByte(byte);
+  }
+
+  virtual uint32_t writeI16_virt(const int16_t i16) {
+    return static_cast<Protocol_*>(this)->writeI16(i16);
+  }
+
+  virtual uint32_t writeI32_virt(const int32_t i32) {
+    return static_cast<Protocol_*>(this)->writeI32(i32);
+  }
+
+  virtual uint32_t writeI64_virt(const int64_t i64) {
+    return static_cast<Protocol_*>(this)->writeI64(i64);
+  }
+
+  virtual uint32_t writeDouble_virt(const double dub) {
+    return static_cast<Protocol_*>(this)->writeDouble(dub);
+  }
+
+  virtual uint32_t writeString_virt(const std::string& str) {
+    return static_cast<Protocol_*>(this)->writeString(str);
+  }
+
+  virtual uint32_t writeBinary_virt(const std::string& str) {
+    return static_cast<Protocol_*>(this)->writeBinary(str);
+  }
+
+  /**
+   * Reading functions
+   */
+
+  virtual uint32_t readMessageBegin_virt(std::string& name,
+                                         TMessageType& messageType,
+                                         int32_t& seqid) {
+    return static_cast<Protocol_*>(this)->readMessageBegin(name, messageType,
+                                                           seqid);
+  }
+
+  virtual uint32_t readMessageEnd_virt() {
+    return static_cast<Protocol_*>(this)->readMessageEnd();
+  }
+
+  virtual uint32_t readStructBegin_virt(std::string& name) {
+    return static_cast<Protocol_*>(this)->readStructBegin(name);
+  }
+
+  virtual uint32_t readStructEnd_virt() {
+    return static_cast<Protocol_*>(this)->readStructEnd();
+  }
+
+  virtual uint32_t readFieldBegin_virt(std::string& name,
+                                       TType& fieldType,
+                                       int16_t& fieldId) {
+    return static_cast<Protocol_*>(this)->readFieldBegin(name, fieldType,
+                                                         fieldId);
+  }
+
+  virtual uint32_t readFieldEnd_virt() {
+    return static_cast<Protocol_*>(this)->readFieldEnd();
+  }
+
+  virtual uint32_t readMapBegin_virt(TType& keyType,
+                                     TType& valType,
+                                     uint32_t& size) {
+    return static_cast<Protocol_*>(this)->readMapBegin(keyType, valType, size);
+  }
+
+  virtual uint32_t readMapEnd_virt() {
+    return static_cast<Protocol_*>(this)->readMapEnd();
+  }
+
+  virtual uint32_t readListBegin_virt(TType& elemType,
+                                      uint32_t& size) {
+    return static_cast<Protocol_*>(this)->readListBegin(elemType, size);
+  }
+
+  virtual uint32_t readListEnd_virt() {
+    return static_cast<Protocol_*>(this)->readListEnd();
+  }
+
+  virtual uint32_t readSetBegin_virt(TType& elemType,
+                                     uint32_t& size) {
+    return static_cast<Protocol_*>(this)->readSetBegin(elemType, size);
+  }
+
+  virtual uint32_t readSetEnd_virt() {
+    return static_cast<Protocol_*>(this)->readSetEnd();
+  }
+
+  virtual uint32_t readBool_virt(bool& value) {
+    return static_cast<Protocol_*>(this)->readBool(value);
+  }
+
+  virtual uint32_t readByte_virt(int8_t& byte) {
+    return static_cast<Protocol_*>(this)->readByte(byte);
+  }
+
+  virtual uint32_t readI16_virt(int16_t& i16) {
+    return static_cast<Protocol_*>(this)->readI16(i16);
+  }
+
+  virtual uint32_t readI32_virt(int32_t& i32) {
+    return static_cast<Protocol_*>(this)->readI32(i32);
+  }
+
+  virtual uint32_t readI64_virt(int64_t& i64) {
+    return static_cast<Protocol_*>(this)->readI64(i64);
+  }
+
+  virtual uint32_t readDouble_virt(double& dub) {
+    return static_cast<Protocol_*>(this)->readDouble(dub);
+  }
+
+  virtual uint32_t readString_virt(std::string& str) {
+    return static_cast<Protocol_*>(this)->readString(str);
+  }
+
+  virtual uint32_t readBinary_virt(std::string& str) {
+    return static_cast<Protocol_*>(this)->readBinary(str);
+  }
+
+  virtual uint32_t skip_virt(TType type) {
+    return static_cast<Protocol_*>(this)->skip(type);
+  }
+
+  /*
+   * Provide a default skip() implementation that uses non-virtual read
+   * methods.
+   *
+   * Note: subclasses that use TVirtualProtocol to derive from another protocol
+   * implementation (i.e., not TProtocolDefaults) should beware that this may
+   * override any non-default skip() implementation provided by the parent
+   * transport class.  They may need to explicitly redefine skip() to call the
+   * correct parent implementation, if desired.
+   */
+  uint32_t skip(TType type) {
+    Protocol_* const prot = static_cast<Protocol_*>(this);
+    return ::apache::thrift::protocol::skip(*prot, type);
+  }
+
+ protected:
+  TVirtualProtocol(boost::shared_ptr<TTransport> ptrans)
+    : Super_(ptrans)
+  {}
+};
+
+}}} // apache::thrift::protocol
+
+#endif // #define _THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_ 1