summaryrefslogtreecommitdiff
path: root/lib/cpp/src/protocol/TBinaryProtocol.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/cpp/src/protocol/TBinaryProtocol.cpp')
-rw-r--r--lib/cpp/src/protocol/TBinaryProtocol.cpp394
1 files changed, 394 insertions, 0 deletions
diff --git a/lib/cpp/src/protocol/TBinaryProtocol.cpp b/lib/cpp/src/protocol/TBinaryProtocol.cpp
new file mode 100644
index 000000000..6a4838b44
--- /dev/null
+++ b/lib/cpp/src/protocol/TBinaryProtocol.cpp
@@ -0,0 +1,394 @@
+/*
+ * 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.
+ */
+
+#include "TBinaryProtocol.h"
+
+#include <limits>
+
+using std::string;
+
+namespace apache { namespace thrift { namespace protocol {
+
+uint32_t TBinaryProtocol::writeMessageBegin(const std::string& name,
+ const TMessageType messageType,
+ const int32_t seqid) {
+ if (strict_write_) {
+ int32_t version = (VERSION_1) | ((int32_t)messageType);
+ uint32_t wsize = 0;
+ wsize += writeI32(version);
+ wsize += writeString(name);
+ wsize += writeI32(seqid);
+ return wsize;
+ } else {
+ uint32_t wsize = 0;
+ wsize += writeString(name);
+ wsize += writeByte((int8_t)messageType);
+ wsize += writeI32(seqid);
+ return wsize;
+ }
+}
+
+uint32_t TBinaryProtocol::writeMessageEnd() {
+ return 0;
+}
+
+uint32_t TBinaryProtocol::writeStructBegin(const char* name) {
+ return 0;
+}
+
+uint32_t TBinaryProtocol::writeStructEnd() {
+ return 0;
+}
+
+uint32_t TBinaryProtocol::writeFieldBegin(const char* name,
+ const TType fieldType,
+ const int16_t fieldId) {
+ uint32_t wsize = 0;
+ wsize += writeByte((int8_t)fieldType);
+ wsize += writeI16(fieldId);
+ return wsize;
+}
+
+uint32_t TBinaryProtocol::writeFieldEnd() {
+ return 0;
+}
+
+uint32_t TBinaryProtocol::writeFieldStop() {
+ return
+ writeByte((int8_t)T_STOP);
+}
+
+uint32_t TBinaryProtocol::writeMapBegin(const TType keyType,
+ const TType valType,
+ const uint32_t size) {
+ uint32_t wsize = 0;
+ wsize += writeByte((int8_t)keyType);
+ wsize += writeByte((int8_t)valType);
+ wsize += writeI32((int32_t)size);
+ return wsize;
+}
+
+uint32_t TBinaryProtocol::writeMapEnd() {
+ return 0;
+}
+
+uint32_t TBinaryProtocol::writeListBegin(const TType elemType,
+ const uint32_t size) {
+ uint32_t wsize = 0;
+ wsize += writeByte((int8_t) elemType);
+ wsize += writeI32((int32_t)size);
+ return wsize;
+}
+
+uint32_t TBinaryProtocol::writeListEnd() {
+ return 0;
+}
+
+uint32_t TBinaryProtocol::writeSetBegin(const TType elemType,
+ const uint32_t size) {
+ uint32_t wsize = 0;
+ wsize += writeByte((int8_t)elemType);
+ wsize += writeI32((int32_t)size);
+ return wsize;
+}
+
+uint32_t TBinaryProtocol::writeSetEnd() {
+ return 0;
+}
+
+uint32_t TBinaryProtocol::writeBool(const bool value) {
+ uint8_t tmp = value ? 1 : 0;
+ trans_->write(&tmp, 1);
+ return 1;
+}
+
+uint32_t TBinaryProtocol::writeByte(const int8_t byte) {
+ trans_->write((uint8_t*)&byte, 1);
+ return 1;
+}
+
+uint32_t TBinaryProtocol::writeI16(const int16_t i16) {
+ int16_t net = (int16_t)htons(i16);
+ trans_->write((uint8_t*)&net, 2);
+ return 2;
+}
+
+uint32_t TBinaryProtocol::writeI32(const int32_t i32) {
+ int32_t net = (int32_t)htonl(i32);
+ trans_->write((uint8_t*)&net, 4);
+ return 4;
+}
+
+uint32_t TBinaryProtocol::writeI64(const int64_t i64) {
+ int64_t net = (int64_t)htonll(i64);
+ trans_->write((uint8_t*)&net, 8);
+ return 8;
+}
+
+uint32_t TBinaryProtocol::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);
+ trans_->write((uint8_t*)&bits, 8);
+ return 8;
+}
+
+
+uint32_t TBinaryProtocol::writeString(const string& str) {
+ uint32_t size = str.size();
+ uint32_t result = writeI32((int32_t)size);
+ if (size > 0) {
+ trans_->write((uint8_t*)str.data(), size);
+ }
+ return result + size;
+}
+
+uint32_t TBinaryProtocol::writeBinary(const string& str) {
+ return TBinaryProtocol::writeString(str);
+}
+
+/**
+ * Reading functions
+ */
+
+uint32_t TBinaryProtocol::readMessageBegin(std::string& name,
+ TMessageType& messageType,
+ int32_t& seqid) {
+ uint32_t result = 0;
+ int32_t sz;
+ result += readI32(sz);
+
+ if (sz < 0) {
+ // Check for correct version number
+ int32_t version = sz & VERSION_MASK;
+ if (version != VERSION_1) {
+ throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier");
+ }
+ messageType = (TMessageType)(sz & 0x000000ff);
+ result += readString(name);
+ result += readI32(seqid);
+ } else {
+ if (strict_read_) {
+ throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?");
+ } else {
+ // Handle pre-versioned input
+ int8_t type;
+ result += readStringBody(name, sz);
+ result += readByte(type);
+ messageType = (TMessageType)type;
+ result += readI32(seqid);
+ }
+ }
+ return result;
+}
+
+uint32_t TBinaryProtocol::readMessageEnd() {
+ return 0;
+}
+
+uint32_t TBinaryProtocol::readStructBegin(string& name) {
+ name = "";
+ return 0;
+}
+
+uint32_t TBinaryProtocol::readStructEnd() {
+ return 0;
+}
+
+uint32_t TBinaryProtocol::readFieldBegin(string& name,
+ TType& fieldType,
+ int16_t& fieldId) {
+ uint32_t result = 0;
+ int8_t type;
+ result += readByte(type);
+ fieldType = (TType)type;
+ if (fieldType == T_STOP) {
+ fieldId = 0;
+ return result;
+ }
+ result += readI16(fieldId);
+ return result;
+}
+
+uint32_t TBinaryProtocol::readFieldEnd() {
+ return 0;
+}
+
+uint32_t TBinaryProtocol::readMapBegin(TType& keyType,
+ TType& valType,
+ uint32_t& size) {
+ int8_t k, v;
+ uint32_t result = 0;
+ int32_t sizei;
+ result += readByte(k);
+ keyType = (TType)k;
+ result += readByte(v);
+ valType = (TType)v;
+ result += readI32(sizei);
+ if (sizei < 0) {
+ throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
+ } else if (container_limit_ && sizei > container_limit_) {
+ throw TProtocolException(TProtocolException::SIZE_LIMIT);
+ }
+ size = (uint32_t)sizei;
+ return result;
+}
+
+uint32_t TBinaryProtocol::readMapEnd() {
+ return 0;
+}
+
+uint32_t TBinaryProtocol::readListBegin(TType& elemType,
+ uint32_t& size) {
+ int8_t e;
+ uint32_t result = 0;
+ int32_t sizei;
+ result += readByte(e);
+ elemType = (TType)e;
+ result += readI32(sizei);
+ if (sizei < 0) {
+ throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
+ } else if (container_limit_ && sizei > container_limit_) {
+ throw TProtocolException(TProtocolException::SIZE_LIMIT);
+ }
+ size = (uint32_t)sizei;
+ return result;
+}
+
+uint32_t TBinaryProtocol::readListEnd() {
+ return 0;
+}
+
+uint32_t TBinaryProtocol::readSetBegin(TType& elemType,
+ uint32_t& size) {
+ int8_t e;
+ uint32_t result = 0;
+ int32_t sizei;
+ result += readByte(e);
+ elemType = (TType)e;
+ result += readI32(sizei);
+ if (sizei < 0) {
+ throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
+ } else if (container_limit_ && sizei > container_limit_) {
+ throw TProtocolException(TProtocolException::SIZE_LIMIT);
+ }
+ size = (uint32_t)sizei;
+ return result;
+}
+
+uint32_t TBinaryProtocol::readSetEnd() {
+ return 0;
+}
+
+uint32_t TBinaryProtocol::readBool(bool& value) {
+ uint8_t b[1];
+ trans_->readAll(b, 1);
+ value = *(int8_t*)b != 0;
+ return 1;
+}
+
+uint32_t TBinaryProtocol::readByte(int8_t& byte) {
+ uint8_t b[1];
+ trans_->readAll(b, 1);
+ byte = *(int8_t*)b;
+ return 1;
+}
+
+uint32_t TBinaryProtocol::readI16(int16_t& i16) {
+ uint8_t b[2];
+ trans_->readAll(b, 2);
+ i16 = *(int16_t*)b;
+ i16 = (int16_t)ntohs(i16);
+ return 2;
+}
+
+uint32_t TBinaryProtocol::readI32(int32_t& i32) {
+ uint8_t b[4];
+ trans_->readAll(b, 4);
+ i32 = *(int32_t*)b;
+ i32 = (int32_t)ntohl(i32);
+ return 4;
+}
+
+uint32_t TBinaryProtocol::readI64(int64_t& i64) {
+ uint8_t b[8];
+ trans_->readAll(b, 8);
+ i64 = *(int64_t*)b;
+ i64 = (int64_t)ntohll(i64);
+ return 8;
+}
+
+uint32_t TBinaryProtocol::readDouble(double& dub) {
+ BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
+ BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
+
+ uint64_t bits;
+ uint8_t b[8];
+ trans_->readAll(b, 8);
+ bits = *(uint64_t*)b;
+ bits = ntohll(bits);
+ dub = bitwise_cast<double>(bits);
+ return 8;
+}
+
+uint32_t TBinaryProtocol::readString(string& str) {
+ uint32_t result;
+ int32_t size;
+ result = readI32(size);
+ return result + readStringBody(str, size);
+}
+
+uint32_t TBinaryProtocol::readBinary(string& str) {
+ return TBinaryProtocol::readString(str);
+}
+
+uint32_t TBinaryProtocol::readStringBody(string& str, int32_t size) {
+ uint32_t result = 0;
+
+ // Catch error cases
+ if (size < 0) {
+ throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
+ }
+ if (string_limit_ > 0 && size > string_limit_) {
+ throw TProtocolException(TProtocolException::SIZE_LIMIT);
+ }
+
+ // Catch empty string case
+ if (size == 0) {
+ str = "";
+ return result;
+ }
+
+ // Use the heap here to prevent stack overflow for v. large strings
+ if (size > string_buf_size_ || string_buf_ == NULL) {
+ void* new_string_buf = std::realloc(string_buf_, (uint32_t)size);
+ if (new_string_buf == NULL) {
+ throw TProtocolException(TProtocolException::UNKNOWN, "Out of memory in TBinaryProtocol::readString");
+ }
+ string_buf_ = (uint8_t*)new_string_buf;
+ string_buf_size_ = size;
+ }
+ trans_->readAll(string_buf_, size);
+ str = string((char*)string_buf_, size);
+ return (uint32_t)size;
+}
+
+}}} // apache::thrift::protocol