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