blob: 4507d91b7104a4878d0fafbf16d825f86c4e72c9 [file] [log] [blame]
Mark Slee9f0c6512007-02-28 23:58:26 +00001// Copyright (c) 2006- Facebook
2// Distributed under the Thrift Software License
3//
4// See accompanying file LICENSE or visit the Thrift site at:
5// http://developers.facebook.com/thrift/
6
Mark Sleef5f2be42006-09-05 21:05:31 +00007#ifndef _THRIFT_PROTOCOL_TPROTOCOL_H_
8#define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1
Mark Sleee8540632006-05-30 09:24:40 +00009
Marc Slemko16698852006-08-04 03:16:10 +000010#include <transport/TTransport.h>
Mark Sleef9831082007-02-20 20:59:21 +000011#include <protocol/TProtocolException.h>
Marc Slemko16698852006-08-04 03:16:10 +000012
13#include <boost/shared_ptr.hpp>
14
Mark Slee8d7e1f62006-06-07 06:48:56 +000015#include <netinet/in.h>
Mark Sleee8540632006-05-30 09:24:40 +000016#include <sys/types.h>
17#include <string>
18#include <map>
19
T Jake Lucianib5e62212009-01-31 22:36:20 +000020namespace apache { namespace thrift { namespace protocol {
Marc Slemko6f038a72006-08-03 18:58:09 +000021
T Jake Lucianib5e62212009-01-31 22:36:20 +000022using apache::thrift::transport::TTransport;
Marc Slemko6f038a72006-08-03 18:58:09 +000023
Mark Slee4f261c52007-04-13 00:33:24 +000024#ifdef HAVE_ENDIAN_H
25#include <endian.h>
26#endif
27
Mark Slee1d2ead32007-06-09 01:23:04 +000028#ifndef __BYTE_ORDER
29# if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
30# define __BYTE_ORDER BYTE_ORDER
31# define __LITTLE_ENDIAN LITTLE_ENDIAN
32# define __BIG_ENDIAN BIG_ENDIAN
33# else
34# error "Cannot determine endianness"
35# endif
36#endif
37
Mark Sleedc8a2a22006-09-19 22:20:18 +000038#if __BYTE_ORDER == __BIG_ENDIAN
Mark Slee4f261c52007-04-13 00:33:24 +000039# define ntohll(n) (n)
40# define htonll(n) (n)
41#elif __BYTE_ORDER == __LITTLE_ENDIAN
42# if defined(__GNUC__) && defined(__GLIBC__)
43# include <byteswap.h>
44# define ntohll(n) bswap_64(n)
45# define htonll(n) bswap_64(n)
46# else /* GNUC & GLIBC */
47# define ntohll(n) ( (((unsigned long long)ntohl(n)) << 32) + ntohl(n >> 32) )
48# define htonll(n) ( (((unsigned long long)htonl(n)) << 32) + htonl(n >> 32) )
49# endif /* GNUC & GLIBC */
50#else /* __BYTE_ORDER */
51# error "Can't define htonll or ntohll!"
Mark Sleedc8a2a22006-09-19 22:20:18 +000052#endif
Mark Slee8d7e1f62006-06-07 06:48:56 +000053
Mark Sleee8540632006-05-30 09:24:40 +000054/**
Mark Slee8d7e1f62006-06-07 06:48:56 +000055 * Enumerated definition of the types that the Thrift protocol supports.
56 * Take special note of the T_END type which is used specifically to mark
57 * the end of a sequence of fields.
58 */
59enum TType {
Marc Slemkod42a2c22006-08-10 03:30:18 +000060 T_STOP = 0,
Marc Slemko5b126d62006-08-11 23:03:42 +000061 T_VOID = 1,
62 T_BOOL = 2,
63 T_BYTE = 3,
Mark Sleecfc01932006-09-01 22:18:16 +000064 T_I08 = 3,
Marc Slemko5b126d62006-08-11 23:03:42 +000065 T_I16 = 6,
Marc Slemko5b126d62006-08-11 23:03:42 +000066 T_I32 = 8,
67 T_U64 = 9,
68 T_I64 = 10,
Mark Sleec98d0502006-09-06 02:42:25 +000069 T_DOUBLE = 4,
Marc Slemko5b126d62006-08-11 23:03:42 +000070 T_STRING = 11,
Marc Slemkod97eb612006-08-24 23:37:36 +000071 T_UTF7 = 11,
72 T_STRUCT = 12,
73 T_MAP = 13,
74 T_SET = 14,
75 T_LIST = 15,
76 T_UTF8 = 16,
77 T_UTF16 = 17
Mark Slee8d7e1f62006-06-07 06:48:56 +000078};
79
80/**
Mark Sleef5f2be42006-09-05 21:05:31 +000081 * Enumerated definition of the message types that the Thrift protocol
82 * supports.
Marc Slemko16698852006-08-04 03:16:10 +000083 */
84enum TMessageType {
85 T_CALL = 1,
Mark Sleef9831082007-02-20 20:59:21 +000086 T_REPLY = 2,
87 T_EXCEPTION = 3
Marc Slemko16698852006-08-04 03:16:10 +000088};
89
90/**
Mark Sleee8540632006-05-30 09:24:40 +000091 * Abstract class for a thrift protocol driver. These are all the methods that
92 * a protocol must implement. Essentially, there must be some way of reading
93 * and writing all the base types, plus a mechanism for writing out structs
Mark Slee5d06fea2007-03-05 22:18:18 +000094 * with indexed fields.
95 *
96 * TProtocol objects should not be shared across multiple encoding contexts,
97 * as they may need to maintain internal state in some protocols (i.e. XML).
98 * Note that is is acceptable for the TProtocol module to do its own internal
99 * buffered reads/writes to the underlying TTransport where appropriate (i.e.
100 * when parsing an input XML stream, reading should be batched rather than
101 * looking ahead character by character for a close tag).
Mark Sleee8540632006-05-30 09:24:40 +0000102 *
103 * @author Mark Slee <mcslee@facebook.com>
104 */
105class TProtocol {
106 public:
107 virtual ~TProtocol() {}
108
109 /**
Mark Slee8d7e1f62006-06-07 06:48:56 +0000110 * Writing functions.
Mark Sleee8540632006-05-30 09:24:40 +0000111 */
112
Mark Slee82a6c0f2007-04-04 21:08:21 +0000113 virtual uint32_t writeMessageBegin(const std::string& name,
114 const TMessageType messageType,
115 const int32_t seqid) = 0;
Marc Slemko16698852006-08-04 03:16:10 +0000116
Mark Slee4af6ed72006-10-25 19:02:49 +0000117 virtual uint32_t writeMessageEnd() = 0;
Marc Slemko16698852006-08-04 03:16:10 +0000118
119
David Reiss64120002008-04-29 23:12:24 +0000120 virtual uint32_t writeStructBegin(const char* name) = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000121
Mark Slee4af6ed72006-10-25 19:02:49 +0000122 virtual uint32_t writeStructEnd() = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000123
David Reiss64120002008-04-29 23:12:24 +0000124 virtual uint32_t writeFieldBegin(const char* name,
David Reiss96d23882007-07-26 21:10:32 +0000125 const TType fieldType,
126 const int16_t fieldId) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000127
Mark Slee4af6ed72006-10-25 19:02:49 +0000128 virtual uint32_t writeFieldEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000129
Mark Slee4af6ed72006-10-25 19:02:49 +0000130 virtual uint32_t writeFieldStop() = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000131
Mark Slee4af6ed72006-10-25 19:02:49 +0000132 virtual uint32_t writeMapBegin(const TType keyType,
David Reiss96d23882007-07-26 21:10:32 +0000133 const TType valType,
134 const uint32_t size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000135
Mark Slee4af6ed72006-10-25 19:02:49 +0000136 virtual uint32_t writeMapEnd() = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000137
Mark Slee4af6ed72006-10-25 19:02:49 +0000138 virtual uint32_t writeListBegin(const TType elemType,
David Reiss96d23882007-07-26 21:10:32 +0000139 const uint32_t size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000140
Mark Slee4af6ed72006-10-25 19:02:49 +0000141 virtual uint32_t writeListEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000142
Mark Slee4af6ed72006-10-25 19:02:49 +0000143 virtual uint32_t writeSetBegin(const TType elemType,
David Reiss96d23882007-07-26 21:10:32 +0000144 const uint32_t size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000145
Mark Slee4af6ed72006-10-25 19:02:49 +0000146 virtual uint32_t writeSetEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000147
Mark Slee4af6ed72006-10-25 19:02:49 +0000148 virtual uint32_t writeBool(const bool value) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000149
Mark Slee4af6ed72006-10-25 19:02:49 +0000150 virtual uint32_t writeByte(const int8_t byte) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000151
Mark Slee4af6ed72006-10-25 19:02:49 +0000152 virtual uint32_t writeI16(const int16_t i16) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000153
Mark Slee4af6ed72006-10-25 19:02:49 +0000154 virtual uint32_t writeI32(const int32_t i32) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000155
Mark Slee4af6ed72006-10-25 19:02:49 +0000156 virtual uint32_t writeI64(const int64_t i64) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000157
Mark Slee4af6ed72006-10-25 19:02:49 +0000158 virtual uint32_t writeDouble(const double dub) = 0;
Mark Sleec98d0502006-09-06 02:42:25 +0000159
Mark Slee4af6ed72006-10-25 19:02:49 +0000160 virtual uint32_t writeString(const std::string& str) = 0;
Mark Sleee8540632006-05-30 09:24:40 +0000161
David Reissc005b1b2008-02-15 01:38:18 +0000162 virtual uint32_t writeBinary(const std::string& str) = 0;
163
Mark Sleee8540632006-05-30 09:24:40 +0000164 /**
Mark Slee8d7e1f62006-06-07 06:48:56 +0000165 * Reading functions
Mark Sleee8540632006-05-30 09:24:40 +0000166 */
167
Mark Slee4af6ed72006-10-25 19:02:49 +0000168 virtual uint32_t readMessageBegin(std::string& name,
David Reiss96d23882007-07-26 21:10:32 +0000169 TMessageType& messageType,
170 int32_t& seqid) = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000171
Mark Slee4af6ed72006-10-25 19:02:49 +0000172 virtual uint32_t readMessageEnd() = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000173
Mark Slee4af6ed72006-10-25 19:02:49 +0000174 virtual uint32_t readStructBegin(std::string& name) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000175
Mark Slee4af6ed72006-10-25 19:02:49 +0000176 virtual uint32_t readStructEnd() = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000177
Mark Slee4af6ed72006-10-25 19:02:49 +0000178 virtual uint32_t readFieldBegin(std::string& name,
David Reiss96d23882007-07-26 21:10:32 +0000179 TType& fieldType,
180 int16_t& fieldId) = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000181
Mark Slee4af6ed72006-10-25 19:02:49 +0000182 virtual uint32_t readFieldEnd() = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000183
Mark Slee4af6ed72006-10-25 19:02:49 +0000184 virtual uint32_t readMapBegin(TType& keyType,
David Reiss96d23882007-07-26 21:10:32 +0000185 TType& valType,
186 uint32_t& size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000187
Mark Slee4af6ed72006-10-25 19:02:49 +0000188 virtual uint32_t readMapEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000189
Mark Slee4af6ed72006-10-25 19:02:49 +0000190 virtual uint32_t readListBegin(TType& elemType,
David Reiss96d23882007-07-26 21:10:32 +0000191 uint32_t& size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000192
Mark Slee4af6ed72006-10-25 19:02:49 +0000193 virtual uint32_t readListEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000194
Mark Slee4af6ed72006-10-25 19:02:49 +0000195 virtual uint32_t readSetBegin(TType& elemType,
David Reiss96d23882007-07-26 21:10:32 +0000196 uint32_t& size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000197
Mark Slee4af6ed72006-10-25 19:02:49 +0000198 virtual uint32_t readSetEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000199
Mark Slee4af6ed72006-10-25 19:02:49 +0000200 virtual uint32_t readBool(bool& value) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000201
Mark Slee4af6ed72006-10-25 19:02:49 +0000202 virtual uint32_t readByte(int8_t& byte) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000203
Mark Slee4af6ed72006-10-25 19:02:49 +0000204 virtual uint32_t readI16(int16_t& i16) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000205
Mark Slee4af6ed72006-10-25 19:02:49 +0000206 virtual uint32_t readI32(int32_t& i32) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000207
Mark Slee4af6ed72006-10-25 19:02:49 +0000208 virtual uint32_t readI64(int64_t& i64) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000209
Mark Slee4af6ed72006-10-25 19:02:49 +0000210 virtual uint32_t readDouble(double& dub) = 0;
Mark Sleec98d0502006-09-06 02:42:25 +0000211
Mark Slee4af6ed72006-10-25 19:02:49 +0000212 virtual uint32_t readString(std::string& str) = 0;
Mark Sleee8540632006-05-30 09:24:40 +0000213
David Reissc005b1b2008-02-15 01:38:18 +0000214 virtual uint32_t readBinary(std::string& str) = 0;
215
David Reiss035aed92009-02-10 21:38:48 +0000216 uint32_t readBool(std::vector<bool>::reference ref) {
217 bool value;
218 uint32_t rv = readBool(value);
219 ref = value;
David Reiss57b50062009-02-25 00:59:55 +0000220 return rv;
David Reiss035aed92009-02-10 21:38:48 +0000221 }
222
Mark Sleee8540632006-05-30 09:24:40 +0000223 /**
Mark Slee8d7e1f62006-06-07 06:48:56 +0000224 * Method to arbitrarily skip over data.
Mark Sleee8540632006-05-30 09:24:40 +0000225 */
Mark Slee4af6ed72006-10-25 19:02:49 +0000226 uint32_t skip(TType type) {
Mark Slee8d7e1f62006-06-07 06:48:56 +0000227 switch (type) {
Mark Slee78f58e22006-09-02 04:17:07 +0000228 case T_BOOL:
229 {
230 bool boolv;
Mark Slee4af6ed72006-10-25 19:02:49 +0000231 return readBool(boolv);
Mark Slee78f58e22006-09-02 04:17:07 +0000232 }
Mark Slee8d7e1f62006-06-07 06:48:56 +0000233 case T_BYTE:
234 {
Mark Slee78f58e22006-09-02 04:17:07 +0000235 int8_t bytev;
Mark Slee4af6ed72006-10-25 19:02:49 +0000236 return readByte(bytev);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000237 }
Mark Sleecfc01932006-09-01 22:18:16 +0000238 case T_I16:
Mark Slee8d7e1f62006-06-07 06:48:56 +0000239 {
Mark Sleecfc01932006-09-01 22:18:16 +0000240 int16_t i16;
Mark Slee4af6ed72006-10-25 19:02:49 +0000241 return readI16(i16);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000242 }
243 case T_I32:
244 {
245 int32_t i32;
Mark Slee4af6ed72006-10-25 19:02:49 +0000246 return readI32(i32);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000247 }
Mark Slee8d7e1f62006-06-07 06:48:56 +0000248 case T_I64:
249 {
250 int64_t i64;
Mark Slee4af6ed72006-10-25 19:02:49 +0000251 return readI64(i64);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000252 }
Mark Sleec98d0502006-09-06 02:42:25 +0000253 case T_DOUBLE:
254 {
255 double dub;
Mark Slee4af6ed72006-10-25 19:02:49 +0000256 return readDouble(dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000257 }
Mark Slee8d7e1f62006-06-07 06:48:56 +0000258 case T_STRING:
259 {
260 std::string str;
David Reissc005b1b2008-02-15 01:38:18 +0000261 return readBinary(str);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000262 }
263 case T_STRUCT:
264 {
265 uint32_t result = 0;
266 std::string name;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000267 int16_t fid;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000268 TType ftype;
Mark Slee4af6ed72006-10-25 19:02:49 +0000269 result += readStructBegin(name);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000270 while (true) {
Mark Slee4af6ed72006-10-25 19:02:49 +0000271 result += readFieldBegin(name, ftype, fid);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000272 if (ftype == T_STOP) {
273 break;
274 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000275 result += skip(ftype);
276 result += readFieldEnd();
Mark Slee8d7e1f62006-06-07 06:48:56 +0000277 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000278 result += readStructEnd();
Mark Slee8d7e1f62006-06-07 06:48:56 +0000279 return result;
280 }
281 case T_MAP:
282 {
283 uint32_t result = 0;
284 TType keyType;
285 TType valType;
Marc Slemkob09f5882006-08-23 22:03:34 +0000286 uint32_t i, size;
Mark Slee4af6ed72006-10-25 19:02:49 +0000287 result += readMapBegin(keyType, valType, size);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000288 for (i = 0; i < size; i++) {
Mark Slee4af6ed72006-10-25 19:02:49 +0000289 result += skip(keyType);
290 result += skip(valType);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000291 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000292 result += readMapEnd();
Mark Slee8d7e1f62006-06-07 06:48:56 +0000293 return result;
294 }
295 case T_SET:
296 {
297 uint32_t result = 0;
298 TType elemType;
Marc Slemkob09f5882006-08-23 22:03:34 +0000299 uint32_t i, size;
Mark Slee4af6ed72006-10-25 19:02:49 +0000300 result += readSetBegin(elemType, size);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000301 for (i = 0; i < size; i++) {
Mark Slee4af6ed72006-10-25 19:02:49 +0000302 result += skip(elemType);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000303 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000304 result += readSetEnd();
Mark Slee8d7e1f62006-06-07 06:48:56 +0000305 return result;
306 }
307 case T_LIST:
308 {
309 uint32_t result = 0;
310 TType elemType;
Marc Slemkob09f5882006-08-23 22:03:34 +0000311 uint32_t i, size;
Mark Slee4af6ed72006-10-25 19:02:49 +0000312 result += readListBegin(elemType, size);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000313 for (i = 0; i < size; i++) {
Mark Slee4af6ed72006-10-25 19:02:49 +0000314 result += skip(elemType);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000315 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000316 result += readListEnd();
Mark Slee8d7e1f62006-06-07 06:48:56 +0000317 return result;
318 }
319 default:
320 return 0;
321 }
322 }
Mark Sleee8540632006-05-30 09:24:40 +0000323
Mark Slee5ea15f92007-03-05 22:55:59 +0000324 inline boost::shared_ptr<TTransport> getTransport() {
Mark Slee43b6c632007-02-07 00:54:17 +0000325 return ptrans_;
Mark Slee4af6ed72006-10-25 19:02:49 +0000326 }
327
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000328 // TODO: remove these two calls, they are for backwards
329 // compatibility
Mark Slee5ea15f92007-03-05 22:55:59 +0000330 inline boost::shared_ptr<TTransport> getInputTransport() {
Mark Slee43b6c632007-02-07 00:54:17 +0000331 return ptrans_;
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000332 }
Mark Slee5ea15f92007-03-05 22:55:59 +0000333 inline boost::shared_ptr<TTransport> getOutputTransport() {
Mark Slee43b6c632007-02-07 00:54:17 +0000334 return ptrans_;
Mark Slee4af6ed72006-10-25 19:02:49 +0000335 }
336
Mark Sleee8540632006-05-30 09:24:40 +0000337 protected:
Mark Slee5ea15f92007-03-05 22:55:59 +0000338 TProtocol(boost::shared_ptr<TTransport> ptrans):
Mark Slee43b6c632007-02-07 00:54:17 +0000339 ptrans_(ptrans) {
340 trans_ = ptrans.get();
341 }
David Reiss0c90f6f2008-02-06 22:18:40 +0000342
Mark Slee5ea15f92007-03-05 22:55:59 +0000343 boost::shared_ptr<TTransport> ptrans_;
Mark Slee43b6c632007-02-07 00:54:17 +0000344 TTransport* trans_;
Mark Slee4af6ed72006-10-25 19:02:49 +0000345
346 private:
Mark Sleee8540632006-05-30 09:24:40 +0000347 TProtocol() {}
348};
349
Mark Slee4af6ed72006-10-25 19:02:49 +0000350/**
351 * Constructs input and output protocol objects given transports.
352 */
353class TProtocolFactory {
354 public:
355 TProtocolFactory() {}
356
357 virtual ~TProtocolFactory() {}
358
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000359 virtual boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> trans) = 0;
Mark Slee4af6ed72006-10-25 19:02:49 +0000360};
361
T Jake Lucianib5e62212009-01-31 22:36:20 +0000362}}} // apache::thrift::protocol
Marc Slemko6f038a72006-08-03 18:58:09 +0000363
Mark Sleef5f2be42006-09-05 21:05:31 +0000364#endif // #define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1