You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by be...@apache.org on 2015/07/09 03:34:07 UTC

thrift git commit: THRIFT-3217 Provide a little endian variant of the binary protocol in C++ Client: C++ Patch: Ben Craig

Repository: thrift
Updated Branches:
  refs/heads/master 33f3f01ce -> 384f976a3


THRIFT-3217 Provide a little endian variant of the binary protocol in C++
Client: C++
Patch: Ben Craig <be...@apache.org>

This closes #537


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/384f976a
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/384f976a
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/384f976a

Branch: refs/heads/master
Commit: 384f976a3bb27371de4be5355193450c1f270019
Parents: 33f3f01
Author: Ben Craig <be...@apache.org>
Authored: Wed Jul 8 20:33:03 2015 -0500
Committer: Ben Craig <be...@apache.org>
Committed: Wed Jul 8 20:33:03 2015 -0500

----------------------------------------------------------------------
 lib/cpp/src/thrift/protocol/TBinaryProtocol.h   |  36 ++--
 lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc | 188 +++++++++----------
 lib/cpp/src/thrift/protocol/TProtocol.h         |  43 +++++
 lib/cpp/test/AllProtocolTests.cpp               |   4 +
 lib/cpp/test/Benchmark.cpp                      | 165 ++++++++++++++--
 test/DebugProtoTest.thrift                      |   6 +-
 6 files changed, 317 insertions(+), 125 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/384f976a/lib/cpp/src/thrift/protocol/TBinaryProtocol.h
----------------------------------------------------------------------
diff --git a/lib/cpp/src/thrift/protocol/TBinaryProtocol.h b/lib/cpp/src/thrift/protocol/TBinaryProtocol.h
index 25f0255..7291988 100644
--- a/lib/cpp/src/thrift/protocol/TBinaryProtocol.h
+++ b/lib/cpp/src/thrift/protocol/TBinaryProtocol.h
@@ -34,8 +34,8 @@ namespace protocol {
  * binary format, essentially just spitting out the raw bytes.
  *
  */
-template <class Transport_>
-class TBinaryProtocolT : public TVirtualProtocol<TBinaryProtocolT<Transport_> > {
+template <class Transport_, class ByteOrder_ = TNetworkBigEndian>
+class TBinaryProtocolT : public TVirtualProtocol<TBinaryProtocolT<Transport_, ByteOrder_> > {
 protected:
   static const int32_t VERSION_MASK = ((int32_t)0xffff0000);
   static const int32_t VERSION_1 = ((int32_t)0x80010000);
@@ -43,7 +43,7 @@ protected:
 
 public:
   TBinaryProtocolT(boost::shared_ptr<Transport_> trans)
-    : TVirtualProtocol<TBinaryProtocolT<Transport_> >(trans),
+    : TVirtualProtocol<TBinaryProtocolT<Transport_, ByteOrder_> >(trans),
       trans_(trans.get()),
       string_limit_(0),
       container_limit_(0),
@@ -55,7 +55,7 @@ public:
                    int32_t container_limit,
                    bool strict_read,
                    bool strict_write)
-    : TVirtualProtocol<TBinaryProtocolT<Transport_> >(trans),
+    : TVirtualProtocol<TBinaryProtocolT<Transport_, ByteOrder_> >(trans),
       trans_(trans.get()),
       string_limit_(string_limit),
       container_limit_(container_limit),
@@ -150,7 +150,7 @@ public:
 
   inline uint32_t readBool(bool& value);
   // Provide the default readBool() implementation for std::vector<bool>
-  using TVirtualProtocol<TBinaryProtocolT<Transport_> >::readBool;
+  using TVirtualProtocol<TBinaryProtocolT<Transport_, ByteOrder_> >::readBool;
 
   inline uint32_t readByte(int8_t& byte);
 
@@ -182,11 +182,12 @@ protected:
 };
 
 typedef TBinaryProtocolT<TTransport> TBinaryProtocol;
+typedef TBinaryProtocolT<TTransport, TNetworkLittleEndian> TLEBinaryProtocol;
 
 /**
  * Constructs binary protocol handlers
  */
-template <class Transport_>
+template <class Transport_, class ByteOrder_ = TNetworkBigEndian>
 class TBinaryProtocolFactoryT : public TProtocolFactory {
 public:
   TBinaryProtocolFactoryT()
@@ -216,17 +217,19 @@ public:
     boost::shared_ptr<Transport_> specific_trans = boost::dynamic_pointer_cast<Transport_>(trans);
     TProtocol* prot;
     if (specific_trans) {
-      prot = new TBinaryProtocolT<Transport_>(specific_trans,
-                                              string_limit_,
-                                              container_limit_,
-                                              strict_read_,
-                                              strict_write_);
+      prot = new TBinaryProtocolT<Transport_, ByteOrder_>(
+        specific_trans,
+        string_limit_,
+        container_limit_,
+        strict_read_,
+        strict_write_);
     } else {
-      prot = new TBinaryProtocol(trans,
-                                 string_limit_,
-                                 container_limit_,
-                                 strict_read_,
-                                 strict_write_);
+      prot = new TBinaryProtocolT<TTransport, ByteOrder_>(
+        trans,
+        string_limit_,
+        container_limit_,
+        strict_read_,
+        strict_write_);
     }
 
     return boost::shared_ptr<TProtocol>(prot);
@@ -240,6 +243,7 @@ private:
 };
 
 typedef TBinaryProtocolFactoryT<TTransport> TBinaryProtocolFactory;
+typedef TBinaryProtocolFactoryT<TTransport, TNetworkLittleEndian> TLEBinaryProtocolFactory;
 }
 }
 } // apache::thrift::protocol

http://git-wip-us.apache.org/repos/asf/thrift/blob/384f976a/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc
----------------------------------------------------------------------
diff --git a/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc b/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc
index 0d72d8a..ae350df 100644
--- a/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc
+++ b/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc
@@ -28,8 +28,8 @@ namespace apache {
 namespace thrift {
 namespace protocol {
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeMessageBegin(const std::string& name,
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeMessageBegin(const std::string& name,
                                                          const TMessageType messageType,
                                                          const int32_t seqid) {
   if (this->strict_write_) {
@@ -48,24 +48,24 @@ uint32_t TBinaryProtocolT<Transport_>::writeMessageBegin(const std::string& name
   }
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeMessageEnd() {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeMessageEnd() {
   return 0;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeStructBegin(const char* name) {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeStructBegin(const char* name) {
   (void)name;
   return 0;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeStructEnd() {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeStructEnd() {
   return 0;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeFieldBegin(const char* name,
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeFieldBegin(const char* name,
                                                        const TType fieldType,
                                                        const int16_t fieldId) {
   (void)name;
@@ -75,18 +75,18 @@ uint32_t TBinaryProtocolT<Transport_>::writeFieldBegin(const char* name,
   return wsize;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeFieldEnd() {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeFieldEnd() {
   return 0;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeFieldStop() {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeFieldStop() {
   return writeByte((int8_t)T_STOP);
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeMapBegin(const TType keyType,
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeMapBegin(const TType keyType,
                                                      const TType valType,
                                                      const uint32_t size) {
   uint32_t wsize = 0;
@@ -96,85 +96,85 @@ uint32_t TBinaryProtocolT<Transport_>::writeMapBegin(const TType keyType,
   return wsize;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeMapEnd() {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeMapEnd() {
   return 0;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeListBegin(const TType elemType, const uint32_t size) {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeListBegin(const TType elemType, const uint32_t size) {
   uint32_t wsize = 0;
   wsize += writeByte((int8_t)elemType);
   wsize += writeI32((int32_t)size);
   return wsize;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeListEnd() {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeListEnd() {
   return 0;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeSetBegin(const TType elemType, const uint32_t size) {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeSetBegin(const TType elemType, const uint32_t size) {
   uint32_t wsize = 0;
   wsize += writeByte((int8_t)elemType);
   wsize += writeI32((int32_t)size);
   return wsize;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeSetEnd() {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeSetEnd() {
   return 0;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeBool(const bool value) {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeBool(const bool value) {
   uint8_t tmp = value ? 1 : 0;
   this->trans_->write(&tmp, 1);
   return 1;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeByte(const int8_t byte) {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeByte(const int8_t byte) {
   this->trans_->write((uint8_t*)&byte, 1);
   return 1;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeI16(const int16_t i16) {
-  int16_t net = (int16_t)htons(i16);
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeI16(const int16_t i16) {
+  int16_t net = (int16_t)ByteOrder_::toWire16(i16);
   this->trans_->write((uint8_t*)&net, 2);
   return 2;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeI32(const int32_t i32) {
-  int32_t net = (int32_t)htonl(i32);
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeI32(const int32_t i32) {
+  int32_t net = (int32_t)ByteOrder_::toWire32(i32);
   this->trans_->write((uint8_t*)&net, 4);
   return 4;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeI64(const int64_t i64) {
-  int64_t net = (int64_t)htonll(i64);
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeI64(const int64_t i64) {
+  int64_t net = (int64_t)ByteOrder_::toWire64(i64);
   this->trans_->write((uint8_t*)&net, 8);
   return 8;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeDouble(const double dub) {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeDouble(const double dub) {
   BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
   BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
 
   uint64_t bits = bitwise_cast<uint64_t>(dub);
-  bits = htonll(bits);
+  bits = ByteOrder_::toWire64(bits);
   this->trans_->write((uint8_t*)&bits, 8);
   return 8;
 }
 
-template <class Transport_>
+template <class Transport_, class ByteOrder_>
 template <typename StrType>
-uint32_t TBinaryProtocolT<Transport_>::writeString(const StrType& str) {
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeString(const StrType& str) {
   if (str.size() > static_cast<size_t>((std::numeric_limits<int32_t>::max)()))
     throw TProtocolException(TProtocolException::SIZE_LIMIT);
   uint32_t size = static_cast<uint32_t>(str.size());
@@ -185,17 +185,17 @@ uint32_t TBinaryProtocolT<Transport_>::writeString(const StrType& str) {
   return result + size;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::writeBinary(const std::string& str) {
-  return TBinaryProtocolT<Transport_>::writeString(str);
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeBinary(const std::string& str) {
+  return TBinaryProtocolT<Transport_, ByteOrder_>::writeString(str);
 }
 
 /**
  * Reading functions
  */
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readMessageBegin(std::string& name,
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readMessageBegin(std::string& name,
                                                         TMessageType& messageType,
                                                         int32_t& seqid) {
   uint32_t result = 0;
@@ -227,24 +227,24 @@ uint32_t TBinaryProtocolT<Transport_>::readMessageBegin(std::string& name,
   return result;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readMessageEnd() {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readMessageEnd() {
   return 0;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readStructBegin(std::string& name) {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readStructBegin(std::string& name) {
   name = "";
   return 0;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readStructEnd() {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readStructEnd() {
   return 0;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readFieldBegin(std::string& name,
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readFieldBegin(std::string& name,
                                                       TType& fieldType,
                                                       int16_t& fieldId) {
   (void)name;
@@ -260,13 +260,13 @@ uint32_t TBinaryProtocolT<Transport_>::readFieldBegin(std::string& name,
   return result;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readFieldEnd() {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readFieldEnd() {
   return 0;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readMapBegin(TType& keyType,
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readMapBegin(TType& keyType,
                                                     TType& valType,
                                                     uint32_t& size) {
   int8_t k, v;
@@ -286,13 +286,13 @@ uint32_t TBinaryProtocolT<Transport_>::readMapBegin(TType& keyType,
   return result;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readMapEnd() {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readMapEnd() {
   return 0;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readListBegin(TType& elemType, uint32_t& size) {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readListBegin(TType& elemType, uint32_t& size) {
   int8_t e;
   uint32_t result = 0;
   int32_t sizei;
@@ -308,13 +308,13 @@ uint32_t TBinaryProtocolT<Transport_>::readListBegin(TType& elemType, uint32_t&
   return result;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readListEnd() {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readListEnd() {
   return 0;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readSetBegin(TType& elemType, uint32_t& size) {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readSetBegin(TType& elemType, uint32_t& size) {
   int8_t e;
   uint32_t result = 0;
   int32_t sizei;
@@ -330,62 +330,62 @@ uint32_t TBinaryProtocolT<Transport_>::readSetBegin(TType& elemType, uint32_t& s
   return result;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readSetEnd() {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readSetEnd() {
   return 0;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readBool(bool& value) {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readBool(bool& value) {
   uint8_t b[1];
   this->trans_->readAll(b, 1);
   value = *(int8_t*)b != 0;
   return 1;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readByte(int8_t& byte) {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readByte(int8_t& byte) {
   uint8_t b[1];
   this->trans_->readAll(b, 1);
   byte = *(int8_t*)b;
   return 1;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readI16(int16_t& i16) {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readI16(int16_t& i16) {
   union bytes {
     uint8_t b[2];
     int16_t all;
   } theBytes;
   this->trans_->readAll(theBytes.b, 2);
-  i16 = (int16_t)ntohs(theBytes.all);
+  i16 = (int16_t)ByteOrder_::fromWire16(theBytes.all);
   return 2;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readI32(int32_t& i32) {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readI32(int32_t& i32) {
   union bytes {
     uint8_t b[4];
     int32_t all;
   } theBytes;
   this->trans_->readAll(theBytes.b, 4);
-  i32 = (int32_t)ntohl(theBytes.all);
+  i32 = (int32_t)ByteOrder_::fromWire32(theBytes.all);
   return 4;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readI64(int64_t& i64) {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readI64(int64_t& i64) {
   union bytes {
     uint8_t b[8];
     int64_t all;
   } theBytes;
   this->trans_->readAll(theBytes.b, 8);
-  i64 = (int64_t)ntohll(theBytes.all);
+  i64 = (int64_t)ByteOrder_::fromWire64(theBytes.all);
   return 8;
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readDouble(double& dub) {
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readDouble(double& dub) {
   BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
   BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
 
@@ -394,28 +394,28 @@ uint32_t TBinaryProtocolT<Transport_>::readDouble(double& dub) {
     uint64_t all;
   } theBytes;
   this->trans_->readAll(theBytes.b, 8);
-  theBytes.all = ntohll(theBytes.all);
+  theBytes.all = ByteOrder_::fromWire64(theBytes.all);
   dub = bitwise_cast<double>(theBytes.all);
   return 8;
 }
 
-template <class Transport_>
+template <class Transport_, class ByteOrder_>
 template <typename StrType>
-uint32_t TBinaryProtocolT<Transport_>::readString(StrType& str) {
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readString(StrType& str) {
   uint32_t result;
   int32_t size;
   result = readI32(size);
   return result + readStringBody(str, size);
 }
 
-template <class Transport_>
-uint32_t TBinaryProtocolT<Transport_>::readBinary(std::string& str) {
-  return TBinaryProtocolT<Transport_>::readString(str);
+template <class Transport_, class ByteOrder_>
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readBinary(std::string& str) {
+  return TBinaryProtocolT<Transport_, ByteOrder_>::readString(str);
 }
 
-template <class Transport_>
+template <class Transport_, class ByteOrder_>
 template <typename StrType>
-uint32_t TBinaryProtocolT<Transport_>::readStringBody(StrType& str, int32_t size) {
+uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readStringBody(StrType& str, int32_t size) {
   uint32_t result = 0;
 
   // Catch error cases

http://git-wip-us.apache.org/repos/asf/thrift/blob/384f976a/lib/cpp/src/thrift/protocol/TProtocol.h
----------------------------------------------------------------------
diff --git a/lib/cpp/src/thrift/protocol/TProtocol.h b/lib/cpp/src/thrift/protocol/TProtocol.h
index f3b6048..9eec1ee 100644
--- a/lib/cpp/src/thrift/protocol/TProtocol.h
+++ b/lib/cpp/src/thrift/protocol/TProtocol.h
@@ -105,6 +105,10 @@ static inline To bitwise_cast(From from) {
 #  include <byteswap.h>
 #  define htolell(n) bswap_64(n)
 #  define letohll(n) bswap_64(n)
+#  define THRIFT_htolel(n) bswap_32(n)
+#  define THRIFT_letohl(n) bswap_32(n)
+#  define THRIFT_htoles(n) bswap_16(n)
+#  define THRIFT_letohs(n) bswap_16(n)
 # else /* GNUC & GLIBC */
 #  define bswap_64(n) \
       ( (((n) & 0xff00000000000000ull) >> 56) \
@@ -115,12 +119,28 @@ static inline To bitwise_cast(From from) {
       | (((n) & 0x0000000000ff0000ull) << 24) \
       | (((n) & 0x000000000000ff00ull) << 40) \
       | (((n) & 0x00000000000000ffull) << 56) )
+#  define bswap_32(n) \
+      ( (((n) & 0xff000000ul) >> 24) \
+      | (((n) & 0x00ff0000ul) >> 8)  \
+      | (((n) & 0x0000ff00ul) << 8)  \
+      | (((n) & 0x000000fful) << 24) )
+#  define bswap_16(n) \
+      ( (((n) & ((unsigned short)0xff00ul)) >> 8)  \
+      | (((n) & ((unsigned short)0x00fful)) << 8)  )
 #  define htolell(n) bswap_64(n)
 #  define letohll(n) bswap_64(n)
+#  define THRIFT_htolel(n) bswap_32(n)
+#  define THRIFT_letohl(n) bswap_32(n)
+#  define THRIFT_htoles(n) bswap_16(n)
+#  define THRIFT_letohs(n) bswap_16(n)
 # endif /* GNUC & GLIBC */
 #elif __THRIFT_BYTE_ORDER == __THRIFT_LITTLE_ENDIAN
 #  define htolell(n) (n)
 #  define letohll(n) (n)
+#  define THRIFT_htolel(n) (n)
+#  define THRIFT_letohl(n) (n)
+#  define THRIFT_htoles(n) (n)
+#  define THRIFT_letohs(n) (n)
 # if defined(__GNUC__) && defined(__GLIBC__)
 #  include <byteswap.h>
 #  define ntohll(n) bswap_64(n)
@@ -669,6 +689,29 @@ public:
  * It is used only by the generator code.
  */
 class TDummyProtocol : public TProtocol {};
+
+// This is the default / legacy choice
+struct TNetworkBigEndian
+{
+  static uint16_t toWire16(uint16_t x)   {return htons(x);}
+  static uint32_t toWire32(uint32_t x)   {return htonl(x);}
+  static uint64_t toWire64(uint64_t x)   {return htonll(x);}
+  static uint16_t fromWire16(uint16_t x) {return ntohs(x);}
+  static uint32_t fromWire32(uint32_t x) {return ntohl(x);}
+  static uint64_t fromWire64(uint64_t x) {return ntohll(x);}
+};
+
+// On most systems, this will be a bit faster than TNetworkBigEndian
+struct TNetworkLittleEndian
+{
+  static uint16_t toWire16(uint16_t x)   {return THRIFT_htoles(x);}
+  static uint32_t toWire32(uint32_t x)   {return THRIFT_htolel(x);}
+  static uint64_t toWire64(uint64_t x)   {return htolell(x);}
+  static uint16_t fromWire16(uint16_t x) {return THRIFT_letohs(x);}
+  static uint32_t fromWire32(uint32_t x) {return THRIFT_letohl(x);}
+  static uint64_t fromWire64(uint64_t x) {return letohll(x);}
+};
+
 }
 }
 } // apache::thrift::protocol

http://git-wip-us.apache.org/repos/asf/thrift/blob/384f976a/lib/cpp/test/AllProtocolTests.cpp
----------------------------------------------------------------------
diff --git a/lib/cpp/test/AllProtocolTests.cpp b/lib/cpp/test/AllProtocolTests.cpp
index a1bccb5..6b5c7c4 100644
--- a/lib/cpp/test/AllProtocolTests.cpp
+++ b/lib/cpp/test/AllProtocolTests.cpp
@@ -38,6 +38,10 @@ BOOST_AUTO_TEST_CASE(test_binary_protocol) {
   testProtocol<TBinaryProtocol>("TBinaryProtocol");
 }
 
+BOOST_AUTO_TEST_CASE(test_little_binary_protocol) {
+  testProtocol<TLEBinaryProtocol>("TLEBinaryProtocol");
+}
+
 BOOST_AUTO_TEST_CASE(test_compact_protocol) {
   testProtocol<TCompactProtocol>("TCompactProtocol");
 }

http://git-wip-us.apache.org/repos/asf/thrift/blob/384f976a/lib/cpp/test/Benchmark.cpp
----------------------------------------------------------------------
diff --git a/lib/cpp/test/Benchmark.cpp b/lib/cpp/test/Benchmark.cpp
index 9d96d08..69e6414 100644
--- a/lib/cpp/test/Benchmark.cpp
+++ b/lib/cpp/test/Benchmark.cpp
@@ -66,41 +66,178 @@ int main() {
   ooe.zomg_unicode = "\xd7\n\a\t";
   ooe.base64 = "\1\2\3\255";
 
-  boost::shared_ptr<TMemoryBuffer> buf(new TMemoryBuffer());
+  int num = 100000;
+  boost::shared_ptr<TMemoryBuffer> buf(new TMemoryBuffer(num*1000));
 
-  int num = 1000000;
+  uint8_t* data = NULL;
+  uint32_t datasize = 0;
 
   {
+    buf->resetBuffer();
+    TBinaryProtocolT<TMemoryBuffer> prot(buf);
+    double elapsed = 0.0;
     Timer timer;
 
     for (int i = 0; i < num; i++) {
-      buf->resetBuffer();
-      TBinaryProtocolT<TBufferBase> prot(buf);
       ooe.write(&prot);
     }
-    cout << "Write: " << num / (1000 * timer.frame()) << " kHz" << endl;
+    elapsed = timer.frame();
+    cout << "Write big endian: " << num / (1000 * elapsed) << " kHz" << endl;
   }
 
-  uint8_t* data;
-  uint32_t datasize;
-
   buf->getBuffer(&data, &datasize);
 
   {
+    boost::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
+    TBinaryProtocolT<TMemoryBuffer> prot(buf2);
+    OneOfEach ooe2;
+    double elapsed = 0.0;
+    Timer timer;
 
+    for (int i = 0; i < num; i++) {
+      ooe2.read(&prot);
+    }
+    elapsed = timer.frame();
+    cout << " Read big endian: " << num / (1000 * elapsed) << " kHz" << endl;
+  }
+
+  {
+    buf->resetBuffer();
+    TBinaryProtocolT<TMemoryBuffer, TNetworkLittleEndian> prot(buf);
+    double elapsed = 0.0;
+    Timer timer;
+
+    for (int i = 0; i < num; i++) {
+      ooe.write(&prot);
+    }
+    elapsed = timer.frame();
+    cout << "Write little endian: " << num / (1000 * elapsed) << " kHz" << endl;
+  }
+
+  {
+    OneOfEach ooe2;
+    boost::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
+    TBinaryProtocolT<TMemoryBuffer, TNetworkLittleEndian> prot(buf2);
+    double elapsed = 0.0;
     Timer timer;
 
     for (int i = 0; i < num; i++) {
-      OneOfEach ooe2;
-      boost::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
-      // buf2->resetBuffer(data, datasize);
-      TBinaryProtocolT<TBufferBase> prot(buf2);
       ooe2.read(&prot);
+    }
+    elapsed = timer.frame();
+    cout << " Read little endian: " << num / (1000 * elapsed) << " kHz" << endl;
+  }
 
-      // cout << apache::thrift::ThriftDebugString(ooe2) << endl << endl;
+  {
+    buf->resetBuffer();
+    TBinaryProtocolT<TMemoryBuffer> prot(buf);
+    double elapsed = 0.0;
+    Timer timer;
+
+    for (int i = 0; i < num; i++) {
+      ooe.write(&prot);
     }
-    cout << " Read: " << num / (1000 * timer.frame()) << " kHz" << endl;
+    elapsed = timer.frame();
+    cout << "Write big endian: " << num / (1000 * elapsed) << " kHz" << endl;
+  }
+
+  {
+    boost::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
+    TBinaryProtocolT<TMemoryBuffer> prot(buf2);
+    OneOfEach ooe2;
+    double elapsed = 0.0;
+    Timer timer;
+
+    for (int i = 0; i < num; i++) {
+      ooe2.read(&prot);
+    }
+    elapsed = timer.frame();
+    cout << " Read big endian: " << num / (1000 * elapsed) << " kHz" << endl;
+  }
+
+
+  data = NULL;
+  datasize = 0;
+  num = 10000000;
+
+  ListDoublePerf listDoublePerf;
+  listDoublePerf.field.reserve(num);
+  for (int x = 0; x < num; ++x)
+    listDoublePerf.field.push_back(double(x));
+
+  buf.reset(new TMemoryBuffer(num * 100));
+
+  {
+    buf->resetBuffer();
+    TBinaryProtocolT<TMemoryBuffer> prot(buf);
+    double elapsed = 0.0;
+    Timer timer;
+
+    listDoublePerf.write(&prot);
+    elapsed = timer.frame();
+    cout << "Double write big endian: " << num / (1000 * elapsed) << " kHz" << endl;
+  }
+
+  buf->getBuffer(&data, &datasize);
+
+  {
+    boost::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
+    TBinaryProtocolT<TMemoryBuffer> prot(buf2);
+    ListDoublePerf listDoublePerf2;
+    double elapsed = 0.0;
+    Timer timer;
+
+    listDoublePerf2.read(&prot);
+    elapsed = timer.frame();
+    cout << " Double read big endian: " << num / (1000 * elapsed) << " kHz" << endl;
+  }
+
+  {
+    buf->resetBuffer();
+    TBinaryProtocolT<TMemoryBuffer, TNetworkLittleEndian> prot(buf);
+    double elapsed = 0.0;
+    Timer timer;
+
+    listDoublePerf.write(&prot);
+    elapsed = timer.frame();
+    cout << "Double write little endian: " << num / (1000 * elapsed) << " kHz" << endl;
   }
 
+  {
+    ListDoublePerf listDoublePerf2;
+    boost::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
+    TBinaryProtocolT<TMemoryBuffer, TNetworkLittleEndian> prot(buf2);
+    double elapsed = 0.0;
+    Timer timer;
+
+    listDoublePerf2.read(&prot);
+    elapsed = timer.frame();
+    cout << " Double read little endian: " << num / (1000 * elapsed) << " kHz" << endl;
+  }
+
+  {
+    buf->resetBuffer();
+    TBinaryProtocolT<TMemoryBuffer> prot(buf);
+    double elapsed = 0.0;
+    Timer timer;
+
+    listDoublePerf.write(&prot);
+    elapsed = timer.frame();
+    cout << "Double write big endian: " << num / (1000 * elapsed) << " kHz" << endl;
+  }
+
+  {
+    boost::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
+    TBinaryProtocolT<TMemoryBuffer> prot(buf2);
+    ListDoublePerf listDoublePerf2;
+    double elapsed = 0.0;
+    Timer timer;
+
+    listDoublePerf2.read(&prot);
+    elapsed = timer.frame();
+    cout << " Double read big endian: " << num / (1000 * elapsed) << " kHz" << endl;
+  }
+
+
   return 0;
 }

http://git-wip-us.apache.org/repos/asf/thrift/blob/384f976a/test/DebugProtoTest.thrift
----------------------------------------------------------------------
diff --git a/test/DebugProtoTest.thrift b/test/DebugProtoTest.thrift
index fb16982..4e9fb47 100644
--- a/test/DebugProtoTest.thrift
+++ b/test/DebugProtoTest.thrift
@@ -364,4 +364,8 @@ struct TupleProtocolTestStruct {
   optional i32 field10;
   optional i32 field11;
   optional i32 field12;
-}
\ No newline at end of file
+}
+
+struct ListDoublePerf {
+  1: list<double> field;
+}