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