1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20#ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_
21#define _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_ 1
22
23#include <thrift/protocol/TBinaryProtocol.h>
24
25#include <limits>
26
27namespace apache {
28namespace thrift {
29namespace protocol {
30
31template <class Transport_, class ByteOrder_>
32uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeMessageBegin(const std::string& name,
33 const TMessageType messageType,
34 const int32_t seqid) {
35 if (this->strict_write_) {
36 int32_t version = (VERSION_1) | ((int32_t)messageType);
37 uint32_t wsize = 0;
38 wsize += writeI32(version);
39 wsize += writeString(name);
40 wsize += writeI32(seqid);
41 return wsize;
42 } else {
43 uint32_t wsize = 0;
44 wsize += writeString(name);
45 wsize += writeByte((int8_t)messageType);
46 wsize += writeI32(seqid);
47 return wsize;
48 }
49}
50
51template <class Transport_, class ByteOrder_>
52uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeMessageEnd() {
53 return 0;
54}
55
56template <class Transport_, class ByteOrder_>
57uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeStructBegin(const char* name) {
58 (void)name;
59 return 0;
60}
61
62template <class Transport_, class ByteOrder_>
63uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeStructEnd() {
64 return 0;
65}
66
67template <class Transport_, class ByteOrder_>
68uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeFieldBegin(const char* name,
69 const TType fieldType,
70 const int16_t fieldId) {
71 (void)name;
72 uint32_t wsize = 0;
73 wsize += writeByte((int8_t)fieldType);
74 wsize += writeI16(fieldId);
75 return wsize;
76}
77
78template <class Transport_, class ByteOrder_>
79uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeFieldEnd() {
80 return 0;
81}
82
83template <class Transport_, class ByteOrder_>
84uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeFieldStop() {
85 return writeByte((int8_t)T_STOP);
86}
87
88template <class Transport_, class ByteOrder_>
89uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeMapBegin(const TType keyType,
90 const TType valType,
91 const uint32_t size) {
92 uint32_t wsize = 0;
93 wsize += writeByte((int8_t)keyType);
94 wsize += writeByte((int8_t)valType);
95 wsize += writeI32((int32_t)size);
96 return wsize;
97}
98
99template <class Transport_, class ByteOrder_>
100uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeMapEnd() {
101 return 0;
102}
103
104template <class Transport_, class ByteOrder_>
105uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeListBegin(const TType elemType,
106 const uint32_t size) {
107 uint32_t wsize = 0;
108 wsize += writeByte((int8_t)elemType);
109 wsize += writeI32((int32_t)size);
110 return wsize;
111}
112
113template <class Transport_, class ByteOrder_>
114uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeListEnd() {
115 return 0;
116}
117
118template <class Transport_, class ByteOrder_>
119uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeSetBegin(const TType elemType,
120 const uint32_t size) {
121 uint32_t wsize = 0;
122 wsize += writeByte((int8_t)elemType);
123 wsize += writeI32((int32_t)size);
124 return wsize;
125}
126
127template <class Transport_, class ByteOrder_>
128uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeSetEnd() {
129 return 0;
130}
131
132template <class Transport_, class ByteOrder_>
133uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeBool(const bool value) {
134 uint8_t tmp = value ? 1 : 0;
135 this->trans_->write(&tmp, 1);
136 return 1;
137}
138
139template <class Transport_, class ByteOrder_>
140uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeByte(const int8_t byte) {
141 this->trans_->write((uint8_t*)&byte, 1);
142 return 1;
143}
144
145template <class Transport_, class ByteOrder_>
146uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeI16(const int16_t i16) {
147 int16_t net = (int16_t)ByteOrder_::toWire16(i16);
148 this->trans_->write((uint8_t*)&net, 2);
149 return 2;
150}
151
152template <class Transport_, class ByteOrder_>
153uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeI32(const int32_t i32) {
154 int32_t net = (int32_t)ByteOrder_::toWire32(i32);
155 this->trans_->write((uint8_t*)&net, 4);
156 return 4;
157}
158
159template <class Transport_, class ByteOrder_>
160uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeI64(const int64_t i64) {
161 int64_t net = (int64_t)ByteOrder_::toWire64(i64);
162 this->trans_->write((uint8_t*)&net, 8);
163 return 8;
164}
165
166template <class Transport_, class ByteOrder_>
167uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeDouble(const double dub) {
168 BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
169 BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
170
171 uint64_t bits = bitwise_cast<uint64_t>(dub);
172 bits = ByteOrder_::toWire64(bits);
173 this->trans_->write((uint8_t*)&bits, 8);
174 return 8;
175}
176
177template <class Transport_, class ByteOrder_>
178template <typename StrType>
179uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeString(const StrType& str) {
180 if (str.size() > static_cast<size_t>((std::numeric_limits<int32_t>::max)()))
181 throw TProtocolException(TProtocolException::SIZE_LIMIT);
182 uint32_t size = static_cast<uint32_t>(str.size());
183 uint32_t result = writeI32((int32_t)size);
184 if (size > 0) {
185 this->trans_->write((uint8_t*)str.data(), size);
186 }
187 return result + size;
188}
189
190template <class Transport_, class ByteOrder_>
191uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeBinary(const std::string& str) {
192 return TBinaryProtocolT<Transport_, ByteOrder_>::writeString(str);
193}
194
195/**
196 * Reading functions
197 */
198
199template <class Transport_, class ByteOrder_>
200uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readMessageBegin(std::string& name,
201 TMessageType& messageType,
202 int32_t& seqid) {
203 uint32_t result = 0;
204 int32_t sz;
205 result += readI32(sz);
206
207 if (sz < 0) {
208 // Check for correct version number
209 int32_t version = sz & VERSION_MASK;
210 if (version != VERSION_1) {
211 throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier");
212 }
213 messageType = (TMessageType)(sz & 0x000000ff);
214 result += readString(name);
215 result += readI32(seqid);
216 } else {
217 if (this->strict_read_) {
218 throw TProtocolException(TProtocolException::BAD_VERSION,
219 "No version identifier... old protocol client in strict mode?");
220 } else {
221 // Handle pre-versioned input
222 int8_t type;
223 result += readStringBody(name, sz);
224 result += readByte(type);
225 messageType = (TMessageType)type;
226 result += readI32(seqid);
227 }
228 }
229 return result;
230}
231
232template <class Transport_, class ByteOrder_>
233uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readMessageEnd() {
234 return 0;
235}
236
237template <class Transport_, class ByteOrder_>
238uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readStructBegin(std::string& name) {
239 name = "";
240 return 0;
241}
242
243template <class Transport_, class ByteOrder_>
244uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readStructEnd() {
245 return 0;
246}
247
248template <class Transport_, class ByteOrder_>
249uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readFieldBegin(std::string& name,
250 TType& fieldType,
251 int16_t& fieldId) {
252 (void)name;
253 uint32_t result = 0;
254 int8_t type;
255 result += readByte(type);
256 fieldType = (TType)type;
257 if (fieldType == T_STOP) {
258 fieldId = 0;
259 return result;
260 }
261 result += readI16(fieldId);
262 return result;
263}
264
265template <class Transport_, class ByteOrder_>
266uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readFieldEnd() {
267 return 0;
268}
269
270template <class Transport_, class ByteOrder_>
271uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readMapBegin(TType& keyType,
272 TType& valType,
273 uint32_t& size) {
274 int8_t k, v;
275 uint32_t result = 0;
276 int32_t sizei;
277 result += readByte(k);
278 keyType = (TType)k;
279 result += readByte(v);
280 valType = (TType)v;
281 result += readI32(sizei);
282 if (sizei < 0) {
283 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
284 } else if (this->container_limit_ && sizei > this->container_limit_) {
285 throw TProtocolException(TProtocolException::SIZE_LIMIT);
286 }
287 size = (uint32_t)sizei;
288 return result;
289}
290
291template <class Transport_, class ByteOrder_>
292uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readMapEnd() {
293 return 0;
294}
295
296template <class Transport_, class ByteOrder_>
297uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readListBegin(TType& elemType, uint32_t& size) {
298 int8_t e;
299 uint32_t result = 0;
300 int32_t sizei;
301 result += readByte(e);
302 elemType = (TType)e;
303 result += readI32(sizei);
304 if (sizei < 0) {
305 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
306 } else if (this->container_limit_ && sizei > this->container_limit_) {
307 throw TProtocolException(TProtocolException::SIZE_LIMIT);
308 }
309 size = (uint32_t)sizei;
310 return result;
311}
312
313template <class Transport_, class ByteOrder_>
314uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readListEnd() {
315 return 0;
316}
317
318template <class Transport_, class ByteOrder_>
319uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readSetBegin(TType& elemType, uint32_t& size) {
320 int8_t e;
321 uint32_t result = 0;
322 int32_t sizei;
323 result += readByte(e);
324 elemType = (TType)e;
325 result += readI32(sizei);
326 if (sizei < 0) {
327 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
328 } else if (this->container_limit_ && sizei > this->container_limit_) {
329 throw TProtocolException(TProtocolException::SIZE_LIMIT);
330 }
331 size = (uint32_t)sizei;
332 return result;
333}
334
335template <class Transport_, class ByteOrder_>
336uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readSetEnd() {
337 return 0;
338}
339
340template <class Transport_, class ByteOrder_>
341uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readBool(bool& value) {
342 uint8_t b[1];
343 this->trans_->readAll(b, 1);
344 value = *(int8_t*)b != 0;
345 return 1;
346}
347
348template <class Transport_, class ByteOrder_>
349uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readByte(int8_t& byte) {
350 uint8_t b[1];
351 this->trans_->readAll(b, 1);
352 byte = *(int8_t*)b;
353 return 1;
354}
355
356template <class Transport_, class ByteOrder_>
357uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readI16(int16_t& i16) {
358 union bytes {
359 uint8_t b[2];
360 int16_t all;
361 } theBytes;
362 this->trans_->readAll(theBytes.b, 2);
363 i16 = (int16_t)ByteOrder_::fromWire16(theBytes.all);
364 return 2;
365}
366
367template <class Transport_, class ByteOrder_>
368uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readI32(int32_t& i32) {
369 union bytes {
370 uint8_t b[4];
371 int32_t all;
372 } theBytes;
373 this->trans_->readAll(theBytes.b, 4);
374 i32 = (int32_t)ByteOrder_::fromWire32(theBytes.all);
375 return 4;
376}
377
378template <class Transport_, class ByteOrder_>
379uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readI64(int64_t& i64) {
380 union bytes {
381 uint8_t b[8];
382 int64_t all;
383 } theBytes;
384 this->trans_->readAll(theBytes.b, 8);
385 i64 = (int64_t)ByteOrder_::fromWire64(theBytes.all);
386 return 8;
387}
388
389template <class Transport_, class ByteOrder_>
390uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readDouble(double& dub) {
391 BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
392 BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
393
394 union bytes {
395 uint8_t b[8];
396 uint64_t all;
397 } theBytes;
398 this->trans_->readAll(theBytes.b, 8);
399 theBytes.all = ByteOrder_::fromWire64(theBytes.all);
400 dub = bitwise_cast<double>(theBytes.all);
401 return 8;
402}
403
404template <class Transport_, class ByteOrder_>
405template <typename StrType>
406uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readString(StrType& str) {
407 uint32_t result;
408 int32_t size;
409 result = readI32(size);
410 return result + readStringBody(str, size);
411}
412
413template <class Transport_, class ByteOrder_>
414uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readBinary(std::string& str) {
415 return TBinaryProtocolT<Transport_, ByteOrder_>::readString(str);
416}
417
418template <class Transport_, class ByteOrder_>
419template <typename StrType>
420uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readStringBody(StrType& str, int32_t size) {
421 uint32_t result = 0;
422
423 // Catch error cases
424 if (size < 0) {
425 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
426 }
427 if (this->string_limit_ > 0 && size > this->string_limit_) {
428 throw TProtocolException(TProtocolException::SIZE_LIMIT);
429 }
430
431 // Catch empty string case
432 if (size == 0) {
433 str.clear();
434 return result;
435 }
436
437 // Try to borrow first
438 const uint8_t* borrow_buf;
439 uint32_t got = size;
440 if ((borrow_buf = this->trans_->borrow(NULL, &got))) {
441 str.assign((const char*)borrow_buf, size);
442 this->trans_->consume(size);
443 return size;
444 }
445
446 str.resize(size);
447 this->trans_->readAll(reinterpret_cast<uint8_t*>(&str[0]), size);
448 return (uint32_t)size;
449}
450}
451}
452} // apache::thrift::protocol
453
454#endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_
455