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_TPROTOCOL_H_
21 #define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1
22
23 #ifdef _WIN32
24 // Need to come before any Windows.h includes
25 #include <winsock2.h>
26 #endif
27
28 #include <thrift/transport/TTransport.h>
29 #include <thrift/protocol/TProtocolException.h>
30 #include <thrift/protocol/TEnum.h>
31 #include <thrift/protocol/TList.h>
32 #include <thrift/protocol/TSet.h>
33 #include <thrift/protocol/TMap.h>
34
35 #include <memory>
36
37 #ifdef HAVE_NETINET_IN_H
38 #include <netinet/in.h>
39 #endif
40 #include <sys/types.h>
41 #include <string>
42 #include <map>
43 #include <vector>
44 #include <climits>
45
46 // Use this to get around strict aliasing rules.
47 // For example, uint64_t i = bitwise_cast<uint64_t>(returns_double());
48 // The most obvious implementation is to just cast a pointer,
49 // but that doesn't work.
50 // For a pretty in-depth explanation of the problem, see
51 // http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
52 template <typename To, typename From>
bitwise_cast(From from)53 static inline To bitwise_cast(From from) {
54 static_assert(sizeof(From) == sizeof(To), "sizeof(From) == sizeof(To)");
55
56 // BAD!!! These are all broken with -O2.
57 //return *reinterpret_cast<To*>(&from); // BAD!!!
58 //return *static_cast<To*>(static_cast<void*>(&from)); // BAD!!!
59 //return *(To*)(void*)&from; // BAD!!!
60
61 // Super clean and paritally blessed by section 3.9 of the standard.
62 //unsigned char c[sizeof(from)];
63 //memcpy(c, &from, sizeof(from));
64 //To to;
65 //memcpy(&to, c, sizeof(c));
66 //return to;
67
68 // Slightly more questionable.
69 // Same code emitted by GCC.
70 //To to;
71 //memcpy(&to, &from, sizeof(from));
72 //return to;
73
74 // Technically undefined, but almost universally supported,
75 // and the most efficient implementation.
76 union {
77 From f;
78 To t;
79 } u;
80 u.f = from;
81 return u.t;
82 }
83
84
85 #ifdef HAVE_SYS_PARAM_H
86 #include <sys/param.h>
87 #endif
88
89 #ifdef __ZEPHYR__
90 # include <zephyr/sys/byteorder.h>
91
92 # define __THRIFT_BYTE_ORDER __BYTE_ORDER__
93 # define __THRIFT_LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
94 # define __THRIFT_BIG_ENDIAN __ORDER_BIG_ENDIAN__
95
96 # if __THRIFT_BYTE_ORDER == __THRIFT_BIG_ENDIAN
97 # undef bswap_64
98 # undef bswap_32
99 # undef bswap_16
100 # endif
101 #endif
102
103 #ifndef __THRIFT_BYTE_ORDER
104 # if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
105 # define __THRIFT_BYTE_ORDER BYTE_ORDER
106 # define __THRIFT_LITTLE_ENDIAN LITTLE_ENDIAN
107 # define __THRIFT_BIG_ENDIAN BIG_ENDIAN
108 # else
109 # include <boost/predef/other/endian.h>
110 # if BOOST_ENDIAN_BIG_BYTE
111 # define __THRIFT_BYTE_ORDER 4321
112 # define __THRIFT_LITTLE_ENDIAN 0
113 # define __THRIFT_BIG_ENDIAN __THRIFT_BYTE_ORDER
114 # elif BOOST_ENDIAN_LITTLE_BYTE
115 # define __THRIFT_BYTE_ORDER 1234
116 # define __THRIFT_LITTLE_ENDIAN __THRIFT_BYTE_ORDER
117 # define __THRIFT_BIG_ENDIAN 0
118 # endif
119 # ifdef BOOST_LITTLE_ENDIAN
120 # else
121 # endif
122 # endif
123 #endif
124
125 #if __THRIFT_BYTE_ORDER == __THRIFT_BIG_ENDIAN
126 # if !defined(THRIFT_ntohll)
127 # define THRIFT_ntohll(n) (n)
128 # define THRIFT_htonll(n) (n)
129 # endif
130 # if defined(__GNUC__) && defined(__GLIBC__)
131 # include <byteswap.h>
132 # define THRIFT_htolell(n) bswap_64(n)
133 # define THRIFT_letohll(n) bswap_64(n)
134 # define THRIFT_htolel(n) bswap_32(n)
135 # define THRIFT_letohl(n) bswap_32(n)
136 # define THRIFT_htoles(n) bswap_16(n)
137 # define THRIFT_letohs(n) bswap_16(n)
138 # else /* GNUC & GLIBC */
139 # define bswap_64(n) \
140 ( (((n) & 0xff00000000000000ull) >> 56) \
141 | (((n) & 0x00ff000000000000ull) >> 40) \
142 | (((n) & 0x0000ff0000000000ull) >> 24) \
143 | (((n) & 0x000000ff00000000ull) >> 8) \
144 | (((n) & 0x00000000ff000000ull) << 8) \
145 | (((n) & 0x0000000000ff0000ull) << 24) \
146 | (((n) & 0x000000000000ff00ull) << 40) \
147 | (((n) & 0x00000000000000ffull) << 56) )
148 # define bswap_32(n) \
149 ( (((n) & 0xff000000ul) >> 24) \
150 | (((n) & 0x00ff0000ul) >> 8) \
151 | (((n) & 0x0000ff00ul) << 8) \
152 | (((n) & 0x000000fful) << 24) )
153 # define bswap_16(n) \
154 ( (((n) & ((unsigned short)0xff00ul)) >> 8) \
155 | (((n) & ((unsigned short)0x00fful)) << 8) )
156 # define THRIFT_htolell(n) bswap_64(n)
157 # define THRIFT_letohll(n) bswap_64(n)
158 # define THRIFT_htolel(n) bswap_32(n)
159 # define THRIFT_letohl(n) bswap_32(n)
160 # define THRIFT_htoles(n) bswap_16(n)
161 # define THRIFT_letohs(n) bswap_16(n)
162 # endif /* GNUC & GLIBC */
163 #elif __THRIFT_BYTE_ORDER == __THRIFT_LITTLE_ENDIAN
164 # define THRIFT_htolell(n) (n)
165 # define THRIFT_letohll(n) (n)
166 # define THRIFT_htolel(n) (n)
167 # define THRIFT_letohl(n) (n)
168 # define THRIFT_htoles(n) (n)
169 # define THRIFT_letohs(n) (n)
170 # if defined(__GNUC__) && defined(__GLIBC__)
171 # include <byteswap.h>
172 # define THRIFT_ntohll(n) bswap_64(n)
173 # define THRIFT_htonll(n) bswap_64(n)
174 # elif defined(_MSC_VER) /* Microsoft Visual C++ */
175 # define THRIFT_ntohll(n) ( _byteswap_uint64((uint64_t)n) )
176 # define THRIFT_htonll(n) ( _byteswap_uint64((uint64_t)n) )
177 # elif !defined(THRIFT_ntohll) /* Not GNUC/GLIBC or MSVC */
178 # define THRIFT_ntohll(n) ( (((uint64_t)ntohl((uint32_t)n)) << 32) + ntohl((uint32_t)(n >> 32)) )
179 # define THRIFT_htonll(n) ( (((uint64_t)htonl((uint32_t)n)) << 32) + htonl((uint32_t)(n >> 32)) )
180 # endif /* GNUC/GLIBC or MSVC or something else */
181 #else /* __THRIFT_BYTE_ORDER */
182 # error "Can't define THRIFT_htonll or THRIFT_ntohll!"
183 #endif
184
185 namespace apache {
186 namespace thrift {
187 namespace protocol {
188
189 using apache::thrift::transport::TTransport;
190
191 /**
192 * Abstract class for a thrift protocol driver. These are all the methods that
193 * a protocol must implement. Essentially, there must be some way of reading
194 * and writing all the base types, plus a mechanism for writing out structs
195 * with indexed fields.
196 *
197 * TProtocol objects should not be shared across multiple encoding contexts,
198 * as they may need to maintain internal state in some protocols (i.e. XML).
199 * Note that is is acceptable for the TProtocol module to do its own internal
200 * buffered reads/writes to the underlying TTransport where appropriate (i.e.
201 * when parsing an input XML stream, reading should be batched rather than
202 * looking ahead character by character for a close tag).
203 *
204 */
205 class TProtocol {
206 public:
207 virtual ~TProtocol();
208
209 /**
210 * Writing functions.
211 */
212
213 virtual uint32_t writeMessageBegin_virt(const std::string& name,
214 const TMessageType messageType,
215 const int32_t seqid) = 0;
216
217 virtual uint32_t writeMessageEnd_virt() = 0;
218
219 virtual uint32_t writeStructBegin_virt(const char* name) = 0;
220
221 virtual uint32_t writeStructEnd_virt() = 0;
222
223 virtual uint32_t writeFieldBegin_virt(const char* name,
224 const TType fieldType,
225 const int16_t fieldId) = 0;
226
227 virtual uint32_t writeFieldEnd_virt() = 0;
228
229 virtual uint32_t writeFieldStop_virt() = 0;
230
231 virtual uint32_t writeMapBegin_virt(const TType keyType, const TType valType, const uint32_t size)
232 = 0;
233
234 virtual uint32_t writeMapEnd_virt() = 0;
235
236 virtual uint32_t writeListBegin_virt(const TType elemType, const uint32_t size) = 0;
237
238 virtual uint32_t writeListEnd_virt() = 0;
239
240 virtual uint32_t writeSetBegin_virt(const TType elemType, const uint32_t size) = 0;
241
242 virtual uint32_t writeSetEnd_virt() = 0;
243
244 virtual uint32_t writeBool_virt(const bool value) = 0;
245
246 virtual uint32_t writeByte_virt(const int8_t byte) = 0;
247
248 virtual uint32_t writeI16_virt(const int16_t i16) = 0;
249
250 virtual uint32_t writeI32_virt(const int32_t i32) = 0;
251
252 virtual uint32_t writeI64_virt(const int64_t i64) = 0;
253
254 virtual uint32_t writeDouble_virt(const double dub) = 0;
255
256 virtual uint32_t writeString_virt(const std::string& str) = 0;
257
258 virtual uint32_t writeBinary_virt(const std::string& str) = 0;
259
writeMessageBegin(const std::string & name,const TMessageType messageType,const int32_t seqid)260 uint32_t writeMessageBegin(const std::string& name,
261 const TMessageType messageType,
262 const int32_t seqid) {
263 T_VIRTUAL_CALL();
264 return writeMessageBegin_virt(name, messageType, seqid);
265 }
266
writeMessageEnd()267 uint32_t writeMessageEnd() {
268 T_VIRTUAL_CALL();
269 return writeMessageEnd_virt();
270 }
271
writeStructBegin(const char * name)272 uint32_t writeStructBegin(const char* name) {
273 T_VIRTUAL_CALL();
274 return writeStructBegin_virt(name);
275 }
276
writeStructEnd()277 uint32_t writeStructEnd() {
278 T_VIRTUAL_CALL();
279 return writeStructEnd_virt();
280 }
281
writeFieldBegin(const char * name,const TType fieldType,const int16_t fieldId)282 uint32_t writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId) {
283 T_VIRTUAL_CALL();
284 return writeFieldBegin_virt(name, fieldType, fieldId);
285 }
286
writeFieldEnd()287 uint32_t writeFieldEnd() {
288 T_VIRTUAL_CALL();
289 return writeFieldEnd_virt();
290 }
291
writeFieldStop()292 uint32_t writeFieldStop() {
293 T_VIRTUAL_CALL();
294 return writeFieldStop_virt();
295 }
296
writeMapBegin(const TType keyType,const TType valType,const uint32_t size)297 uint32_t writeMapBegin(const TType keyType, const TType valType, const uint32_t size) {
298 T_VIRTUAL_CALL();
299 return writeMapBegin_virt(keyType, valType, size);
300 }
301
writeMapEnd()302 uint32_t writeMapEnd() {
303 T_VIRTUAL_CALL();
304 return writeMapEnd_virt();
305 }
306
writeListBegin(const TType elemType,const uint32_t size)307 uint32_t writeListBegin(const TType elemType, const uint32_t size) {
308 T_VIRTUAL_CALL();
309 return writeListBegin_virt(elemType, size);
310 }
311
writeListEnd()312 uint32_t writeListEnd() {
313 T_VIRTUAL_CALL();
314 return writeListEnd_virt();
315 }
316
writeSetBegin(const TType elemType,const uint32_t size)317 uint32_t writeSetBegin(const TType elemType, const uint32_t size) {
318 T_VIRTUAL_CALL();
319 return writeSetBegin_virt(elemType, size);
320 }
321
writeSetEnd()322 uint32_t writeSetEnd() {
323 T_VIRTUAL_CALL();
324 return writeSetEnd_virt();
325 }
326
writeBool(const bool value)327 uint32_t writeBool(const bool value) {
328 T_VIRTUAL_CALL();
329 return writeBool_virt(value);
330 }
331
writeByte(const int8_t byte)332 uint32_t writeByte(const int8_t byte) {
333 T_VIRTUAL_CALL();
334 return writeByte_virt(byte);
335 }
336
writeI16(const int16_t i16)337 uint32_t writeI16(const int16_t i16) {
338 T_VIRTUAL_CALL();
339 return writeI16_virt(i16);
340 }
341
writeI32(const int32_t i32)342 uint32_t writeI32(const int32_t i32) {
343 T_VIRTUAL_CALL();
344 return writeI32_virt(i32);
345 }
346
writeI64(const int64_t i64)347 uint32_t writeI64(const int64_t i64) {
348 T_VIRTUAL_CALL();
349 return writeI64_virt(i64);
350 }
351
writeDouble(const double dub)352 uint32_t writeDouble(const double dub) {
353 T_VIRTUAL_CALL();
354 return writeDouble_virt(dub);
355 }
356
writeString(const std::string & str)357 uint32_t writeString(const std::string& str) {
358 T_VIRTUAL_CALL();
359 return writeString_virt(str);
360 }
361
writeBinary(const std::string & str)362 uint32_t writeBinary(const std::string& str) {
363 T_VIRTUAL_CALL();
364 return writeBinary_virt(str);
365 }
366
367 /**
368 * Reading functions
369 */
370
371 virtual uint32_t readMessageBegin_virt(std::string& name,
372 TMessageType& messageType,
373 int32_t& seqid) = 0;
374
375 virtual uint32_t readMessageEnd_virt() = 0;
376
377 virtual uint32_t readStructBegin_virt(std::string& name) = 0;
378
379 virtual uint32_t readStructEnd_virt() = 0;
380
381 virtual uint32_t readFieldBegin_virt(std::string& name, TType& fieldType, int16_t& fieldId) = 0;
382
383 virtual uint32_t readFieldEnd_virt() = 0;
384
385 virtual uint32_t readMapBegin_virt(TType& keyType, TType& valType, uint32_t& size) = 0;
386
387 virtual uint32_t readMapEnd_virt() = 0;
388
389 virtual uint32_t readListBegin_virt(TType& elemType, uint32_t& size) = 0;
390
391 virtual uint32_t readListEnd_virt() = 0;
392
393 virtual uint32_t readSetBegin_virt(TType& elemType, uint32_t& size) = 0;
394
395 virtual uint32_t readSetEnd_virt() = 0;
396
397 virtual uint32_t readBool_virt(bool& value) = 0;
398
399 virtual uint32_t readBool_virt(std::vector<bool>::reference value) = 0;
400
401 virtual uint32_t readByte_virt(int8_t& byte) = 0;
402
403 virtual uint32_t readI16_virt(int16_t& i16) = 0;
404
405 virtual uint32_t readI32_virt(int32_t& i32) = 0;
406
407 virtual uint32_t readI64_virt(int64_t& i64) = 0;
408
409 virtual uint32_t readDouble_virt(double& dub) = 0;
410
411 virtual uint32_t readString_virt(std::string& str) = 0;
412
413 virtual uint32_t readBinary_virt(std::string& str) = 0;
414
readMessageBegin(std::string & name,TMessageType & messageType,int32_t & seqid)415 uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) {
416 T_VIRTUAL_CALL();
417 return readMessageBegin_virt(name, messageType, seqid);
418 }
419
readMessageEnd()420 uint32_t readMessageEnd() {
421 T_VIRTUAL_CALL();
422 return readMessageEnd_virt();
423 }
424
readStructBegin(std::string & name)425 uint32_t readStructBegin(std::string& name) {
426 T_VIRTUAL_CALL();
427 return readStructBegin_virt(name);
428 }
429
readStructEnd()430 uint32_t readStructEnd() {
431 T_VIRTUAL_CALL();
432 return readStructEnd_virt();
433 }
434
readFieldBegin(std::string & name,TType & fieldType,int16_t & fieldId)435 uint32_t readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId) {
436 T_VIRTUAL_CALL();
437 return readFieldBegin_virt(name, fieldType, fieldId);
438 }
439
readFieldEnd()440 uint32_t readFieldEnd() {
441 T_VIRTUAL_CALL();
442 return readFieldEnd_virt();
443 }
444
readMapBegin(TType & keyType,TType & valType,uint32_t & size)445 uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size) {
446 T_VIRTUAL_CALL();
447 return readMapBegin_virt(keyType, valType, size);
448 }
449
readMapEnd()450 uint32_t readMapEnd() {
451 T_VIRTUAL_CALL();
452 return readMapEnd_virt();
453 }
454
readListBegin(TType & elemType,uint32_t & size)455 uint32_t readListBegin(TType& elemType, uint32_t& size) {
456 T_VIRTUAL_CALL();
457 return readListBegin_virt(elemType, size);
458 }
459
readListEnd()460 uint32_t readListEnd() {
461 T_VIRTUAL_CALL();
462 return readListEnd_virt();
463 }
464
readSetBegin(TType & elemType,uint32_t & size)465 uint32_t readSetBegin(TType& elemType, uint32_t& size) {
466 T_VIRTUAL_CALL();
467 return readSetBegin_virt(elemType, size);
468 }
469
readSetEnd()470 uint32_t readSetEnd() {
471 T_VIRTUAL_CALL();
472 return readSetEnd_virt();
473 }
474
readBool(bool & value)475 uint32_t readBool(bool& value) {
476 T_VIRTUAL_CALL();
477 return readBool_virt(value);
478 }
479
readByte(int8_t & byte)480 uint32_t readByte(int8_t& byte) {
481 T_VIRTUAL_CALL();
482 return readByte_virt(byte);
483 }
484
readI16(int16_t & i16)485 uint32_t readI16(int16_t& i16) {
486 T_VIRTUAL_CALL();
487 return readI16_virt(i16);
488 }
489
readI32(int32_t & i32)490 uint32_t readI32(int32_t& i32) {
491 T_VIRTUAL_CALL();
492 return readI32_virt(i32);
493 }
494
readI64(int64_t & i64)495 uint32_t readI64(int64_t& i64) {
496 T_VIRTUAL_CALL();
497 return readI64_virt(i64);
498 }
499
readDouble(double & dub)500 uint32_t readDouble(double& dub) {
501 T_VIRTUAL_CALL();
502 return readDouble_virt(dub);
503 }
504
readString(std::string & str)505 uint32_t readString(std::string& str) {
506 T_VIRTUAL_CALL();
507 return readString_virt(str);
508 }
509
readBinary(std::string & str)510 uint32_t readBinary(std::string& str) {
511 T_VIRTUAL_CALL();
512 return readBinary_virt(str);
513 }
514
515 /*
516 * std::vector is specialized for bool, and its elements are individual bits
517 * rather than bools. We need to define a different version of readBool()
518 * to work with std::vector<bool>.
519 */
readBool(std::vector<bool>::reference value)520 uint32_t readBool(std::vector<bool>::reference value) {
521 T_VIRTUAL_CALL();
522 return readBool_virt(value);
523 }
524
525 /**
526 * Method to arbitrarily skip over data.
527 */
skip(TType type)528 uint32_t skip(TType type) {
529 T_VIRTUAL_CALL();
530 return skip_virt(type);
531 }
532 virtual uint32_t skip_virt(TType type);
533
getTransport()534 inline std::shared_ptr<TTransport> getTransport() { return ptrans_; }
535
536 // TODO: remove these two calls, they are for backwards
537 // compatibility
getInputTransport()538 inline std::shared_ptr<TTransport> getInputTransport() { return ptrans_; }
getOutputTransport()539 inline std::shared_ptr<TTransport> getOutputTransport() { return ptrans_; }
540
541 // input and output recursion depth are kept separate so that one protocol
542 // can be used concurrently for both input and output.
incrementInputRecursionDepth()543 void incrementInputRecursionDepth() {
544 if (recursion_limit_ < ++input_recursion_depth_) {
545 throw TProtocolException(TProtocolException::DEPTH_LIMIT);
546 }
547 }
decrementInputRecursionDepth()548 void decrementInputRecursionDepth() { --input_recursion_depth_; }
549
incrementOutputRecursionDepth()550 void incrementOutputRecursionDepth() {
551 if (recursion_limit_ < ++output_recursion_depth_) {
552 throw TProtocolException(TProtocolException::DEPTH_LIMIT);
553 }
554 }
decrementOutputRecursionDepth()555 void decrementOutputRecursionDepth() { --output_recursion_depth_; }
556
getRecursionLimit()557 uint32_t getRecursionLimit() const {return recursion_limit_;}
setRecurisionLimit(uint32_t depth)558 void setRecurisionLimit(uint32_t depth) {recursion_limit_ = depth;}
559
560 // Returns the minimum amount of bytes needed to store the smallest possible instance of TType.
getMinSerializedSize(TType type)561 virtual int getMinSerializedSize(TType type) {
562 THRIFT_UNUSED_VARIABLE(type);
563 return 0;
564 }
565
566 protected:
TProtocol(std::shared_ptr<TTransport> ptrans)567 TProtocol(std::shared_ptr<TTransport> ptrans)
568 : ptrans_(ptrans), input_recursion_depth_(0), output_recursion_depth_(0),
569 recursion_limit_(ptrans->getConfiguration()->getRecursionLimit())
570 {}
571
checkReadBytesAvailable(TSet & set)572 virtual void checkReadBytesAvailable(TSet& set)
573 {
574 ptrans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_));
575 }
576
checkReadBytesAvailable(TList & list)577 virtual void checkReadBytesAvailable(TList& list)
578 {
579 ptrans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_));
580 }
581
checkReadBytesAvailable(TMap & map)582 virtual void checkReadBytesAvailable(TMap& map)
583 {
584 int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_);
585 ptrans_->checkReadBytesAvailable(map.size_ * elmSize);
586 }
587
588 std::shared_ptr<TTransport> ptrans_;
589
590 private:
591 TProtocol() = default;
592 uint32_t input_recursion_depth_;
593 uint32_t output_recursion_depth_;
594 uint32_t recursion_limit_;
595 };
596
597 /**
598 * Constructs input and output protocol objects given transports.
599 */
600 class TProtocolFactory {
601 public:
602 TProtocolFactory() = default;
603
604 virtual ~TProtocolFactory();
605
606 virtual std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> trans) = 0;
getProtocol(std::shared_ptr<TTransport> inTrans,std::shared_ptr<TTransport> outTrans)607 virtual std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> inTrans,
608 std::shared_ptr<TTransport> outTrans) {
609 (void)outTrans;
610 return getProtocol(inTrans);
611 }
612 };
613
614 /**
615 * Dummy protocol class.
616 *
617 * This class does nothing, and should never be instantiated.
618 * It is used only by the generator code.
619 */
620 class TDummyProtocol : public TProtocol {};
621
622 // This is the default / legacy choice
623 struct TNetworkBigEndian
624 {
toWire16TNetworkBigEndian625 static uint16_t toWire16(uint16_t x) {return htons(x);}
toWire32TNetworkBigEndian626 static uint32_t toWire32(uint32_t x) {return htonl(x);}
toWire64TNetworkBigEndian627 static uint64_t toWire64(uint64_t x) {return THRIFT_htonll(x);}
fromWire16TNetworkBigEndian628 static uint16_t fromWire16(uint16_t x) {return ntohs(x);}
fromWire32TNetworkBigEndian629 static uint32_t fromWire32(uint32_t x) {return ntohl(x);}
fromWire64TNetworkBigEndian630 static uint64_t fromWire64(uint64_t x) {return THRIFT_ntohll(x);}
631 };
632
633 // On most systems, this will be a bit faster than TNetworkBigEndian
634 struct TNetworkLittleEndian
635 {
toWire16TNetworkLittleEndian636 static uint16_t toWire16(uint16_t x) {return THRIFT_htoles(x);}
toWire32TNetworkLittleEndian637 static uint32_t toWire32(uint32_t x) {return THRIFT_htolel(x);}
toWire64TNetworkLittleEndian638 static uint64_t toWire64(uint64_t x) {return THRIFT_htolell(x);}
fromWire16TNetworkLittleEndian639 static uint16_t fromWire16(uint16_t x) {return THRIFT_letohs(x);}
fromWire32TNetworkLittleEndian640 static uint32_t fromWire32(uint32_t x) {return THRIFT_letohl(x);}
fromWire64TNetworkLittleEndian641 static uint64_t fromWire64(uint64_t x) {return THRIFT_letohll(x);}
642 };
643
644 struct TOutputRecursionTracker {
645 TProtocol &prot_;
TOutputRecursionTrackerTOutputRecursionTracker646 TOutputRecursionTracker(TProtocol &prot) : prot_(prot) {
647 prot_.incrementOutputRecursionDepth();
648 }
~TOutputRecursionTrackerTOutputRecursionTracker649 ~TOutputRecursionTracker() {
650 prot_.decrementOutputRecursionDepth();
651 }
652 };
653
654 struct TInputRecursionTracker {
655 TProtocol &prot_;
TInputRecursionTrackerTInputRecursionTracker656 TInputRecursionTracker(TProtocol &prot) : prot_(prot) {
657 prot_.incrementInputRecursionDepth();
658 }
~TInputRecursionTrackerTInputRecursionTracker659 ~TInputRecursionTracker() {
660 prot_.decrementInputRecursionDepth();
661 }
662 };
663
664 /**
665 * Helper template for implementing TProtocol::skip().
666 *
667 * Templatized to avoid having to make virtual function calls.
668 */
669 template <class Protocol_>
skip(Protocol_ & prot,TType type)670 uint32_t skip(Protocol_& prot, TType type) {
671 TInputRecursionTracker tracker(prot);
672
673 switch (type) {
674 case T_BOOL: {
675 bool boolv;
676 return prot.readBool(boolv);
677 }
678 case T_BYTE: {
679 int8_t bytev = 0;
680 return prot.readByte(bytev);
681 }
682 case T_I16: {
683 int16_t i16;
684 return prot.readI16(i16);
685 }
686 case T_I32: {
687 int32_t i32;
688 return prot.readI32(i32);
689 }
690 case T_I64: {
691 int64_t i64;
692 return prot.readI64(i64);
693 }
694 case T_DOUBLE: {
695 double dub;
696 return prot.readDouble(dub);
697 }
698 case T_STRING: {
699 std::string str;
700 return prot.readBinary(str);
701 }
702 case T_STRUCT: {
703 uint32_t result = 0;
704 std::string name;
705 int16_t fid;
706 TType ftype;
707 result += prot.readStructBegin(name);
708 while (true) {
709 result += prot.readFieldBegin(name, ftype, fid);
710 if (ftype == T_STOP) {
711 break;
712 }
713 result += skip(prot, ftype);
714 result += prot.readFieldEnd();
715 }
716 result += prot.readStructEnd();
717 return result;
718 }
719 case T_MAP: {
720 uint32_t result = 0;
721 TType keyType;
722 TType valType;
723 uint32_t i, size;
724 result += prot.readMapBegin(keyType, valType, size);
725 for (i = 0; i < size; i++) {
726 result += skip(prot, keyType);
727 result += skip(prot, valType);
728 }
729 result += prot.readMapEnd();
730 return result;
731 }
732 case T_SET: {
733 uint32_t result = 0;
734 TType elemType;
735 uint32_t i, size;
736 result += prot.readSetBegin(elemType, size);
737 for (i = 0; i < size; i++) {
738 result += skip(prot, elemType);
739 }
740 result += prot.readSetEnd();
741 return result;
742 }
743 case T_LIST: {
744 uint32_t result = 0;
745 TType elemType;
746 uint32_t i, size;
747 result += prot.readListBegin(elemType, size);
748 for (i = 0; i < size; i++) {
749 result += skip(prot, elemType);
750 }
751 result += prot.readListEnd();
752 return result;
753 }
754 default:
755 break;
756 }
757
758 throw TProtocolException(TProtocolException::INVALID_DATA,
759 "invalid TType");
760 }
761
762 }}} // apache::thrift::protocol
763
764 #endif // #define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1
765