blob: 40226a5d8e14657e4f8b0b8cfcc1451a85b4b8a0 [file] [log] [blame]
David Reisse71115b2010-10-06 17:09:56 +00001/*
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
Roger Meier4285ba22013-06-10 21:17:23 +020023#include <thrift/protocol/TBinaryProtocol.h>
David Reisse71115b2010-10-06 17:09:56 +000024
25#include <limits>
26
27
28namespace apache { namespace thrift { namespace protocol {
29
30template <class Transport_>
31uint32_t TBinaryProtocolT<Transport_>::writeMessageBegin(const std::string& name,
32 const TMessageType messageType,
33 const int32_t seqid) {
34 if (this->strict_write_) {
35 int32_t version = (VERSION_1) | ((int32_t)messageType);
36 uint32_t wsize = 0;
37 wsize += writeI32(version);
38 wsize += writeString(name);
39 wsize += writeI32(seqid);
40 return wsize;
41 } else {
42 uint32_t wsize = 0;
43 wsize += writeString(name);
44 wsize += writeByte((int8_t)messageType);
45 wsize += writeI32(seqid);
46 return wsize;
47 }
48}
49
50template <class Transport_>
51uint32_t TBinaryProtocolT<Transport_>::writeMessageEnd() {
52 return 0;
53}
54
55template <class Transport_>
56uint32_t TBinaryProtocolT<Transport_>::writeStructBegin(const char* name) {
Roger Meier3b771a12010-11-17 22:11:26 +000057 (void) name;
David Reisse71115b2010-10-06 17:09:56 +000058 return 0;
59}
60
61template <class Transport_>
62uint32_t TBinaryProtocolT<Transport_>::writeStructEnd() {
63 return 0;
64}
65
66template <class Transport_>
67uint32_t TBinaryProtocolT<Transport_>::writeFieldBegin(const char* name,
68 const TType fieldType,
69 const int16_t fieldId) {
Roger Meier3b771a12010-11-17 22:11:26 +000070 (void) name;
David Reisse71115b2010-10-06 17:09:56 +000071 uint32_t wsize = 0;
72 wsize += writeByte((int8_t)fieldType);
73 wsize += writeI16(fieldId);
74 return wsize;
75}
76
77template <class Transport_>
78uint32_t TBinaryProtocolT<Transport_>::writeFieldEnd() {
79 return 0;
80}
81
82template <class Transport_>
83uint32_t TBinaryProtocolT<Transport_>::writeFieldStop() {
84 return
85 writeByte((int8_t)T_STOP);
86}
87
88template <class Transport_>
89uint32_t TBinaryProtocolT<Transport_>::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_>
100uint32_t TBinaryProtocolT<Transport_>::writeMapEnd() {
101 return 0;
102}
103
104template <class Transport_>
105uint32_t TBinaryProtocolT<Transport_>::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_>
114uint32_t TBinaryProtocolT<Transport_>::writeListEnd() {
115 return 0;
116}
117
118template <class Transport_>
119uint32_t TBinaryProtocolT<Transport_>::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_>
128uint32_t TBinaryProtocolT<Transport_>::writeSetEnd() {
129 return 0;
130}
131
132template <class Transport_>
133uint32_t TBinaryProtocolT<Transport_>::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_>
140uint32_t TBinaryProtocolT<Transport_>::writeByte(const int8_t byte) {
141 this->trans_->write((uint8_t*)&byte, 1);
142 return 1;
143}
144
145template <class Transport_>
146uint32_t TBinaryProtocolT<Transport_>::writeI16(const int16_t i16) {
147 int16_t net = (int16_t)htons(i16);
148 this->trans_->write((uint8_t*)&net, 2);
149 return 2;
150}
151
152template <class Transport_>
153uint32_t TBinaryProtocolT<Transport_>::writeI32(const int32_t i32) {
154 int32_t net = (int32_t)htonl(i32);
155 this->trans_->write((uint8_t*)&net, 4);
156 return 4;
157}
158
159template <class Transport_>
160uint32_t TBinaryProtocolT<Transport_>::writeI64(const int64_t i64) {
161 int64_t net = (int64_t)htonll(i64);
162 this->trans_->write((uint8_t*)&net, 8);
163 return 8;
164}
165
166template <class Transport_>
167uint32_t TBinaryProtocolT<Transport_>::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 = htonll(bits);
173 this->trans_->write((uint8_t*)&bits, 8);
174 return 8;
175}
176
177
178template <class Transport_>
Jake Farrellf42ae012012-06-22 03:22:53 +0000179template<typename StrType>
180uint32_t TBinaryProtocolT<Transport_>::writeString(const StrType& str) {
Roger Meierb69d24d2012-10-04 18:02:15 +0000181 if(str.size() > static_cast<size_t>((std::numeric_limits<int32_t>::max)()))
182 throw TProtocolException(TProtocolException::SIZE_LIMIT);
183 uint32_t size = static_cast<uint32_t>(str.size());
David Reisse71115b2010-10-06 17:09:56 +0000184 uint32_t result = writeI32((int32_t)size);
185 if (size > 0) {
186 this->trans_->write((uint8_t*)str.data(), size);
187 }
188 return result + size;
189}
190
191template <class Transport_>
192uint32_t TBinaryProtocolT<Transport_>::writeBinary(const std::string& str) {
193 return TBinaryProtocolT<Transport_>::writeString(str);
194}
195
196/**
197 * Reading functions
198 */
199
200template <class Transport_>
201uint32_t TBinaryProtocolT<Transport_>::readMessageBegin(std::string& name,
202 TMessageType& messageType,
203 int32_t& seqid) {
204 uint32_t result = 0;
205 int32_t sz;
206 result += readI32(sz);
207
208 if (sz < 0) {
209 // Check for correct version number
210 int32_t version = sz & VERSION_MASK;
211 if (version != VERSION_1) {
212 throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier");
213 }
214 messageType = (TMessageType)(sz & 0x000000ff);
215 result += readString(name);
216 result += readI32(seqid);
217 } else {
218 if (this->strict_read_) {
219 throw TProtocolException(TProtocolException::BAD_VERSION, "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_>
233uint32_t TBinaryProtocolT<Transport_>::readMessageEnd() {
234 return 0;
235}
236
237template <class Transport_>
238uint32_t TBinaryProtocolT<Transport_>::readStructBegin(std::string& name) {
239 name = "";
240 return 0;
241}
242
243template <class Transport_>
244uint32_t TBinaryProtocolT<Transport_>::readStructEnd() {
245 return 0;
246}
247
248template <class Transport_>
249uint32_t TBinaryProtocolT<Transport_>::readFieldBegin(std::string& name,
250 TType& fieldType,
251 int16_t& fieldId) {
Roger Meier3b771a12010-11-17 22:11:26 +0000252 (void) name;
David Reisse71115b2010-10-06 17:09:56 +0000253 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_>
266uint32_t TBinaryProtocolT<Transport_>::readFieldEnd() {
267 return 0;
268}
269
270template <class Transport_>
271uint32_t TBinaryProtocolT<Transport_>::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_>
292uint32_t TBinaryProtocolT<Transport_>::readMapEnd() {
293 return 0;
294}
295
296template <class Transport_>
297uint32_t TBinaryProtocolT<Transport_>::readListBegin(TType& elemType,
298 uint32_t& size) {
299 int8_t e;
300 uint32_t result = 0;
301 int32_t sizei;
302 result += readByte(e);
303 elemType = (TType)e;
304 result += readI32(sizei);
305 if (sizei < 0) {
306 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
307 } else if (this->container_limit_ && sizei > this->container_limit_) {
308 throw TProtocolException(TProtocolException::SIZE_LIMIT);
309 }
310 size = (uint32_t)sizei;
311 return result;
312}
313
314template <class Transport_>
315uint32_t TBinaryProtocolT<Transport_>::readListEnd() {
316 return 0;
317}
318
319template <class Transport_>
320uint32_t TBinaryProtocolT<Transport_>::readSetBegin(TType& elemType,
321 uint32_t& size) {
322 int8_t e;
323 uint32_t result = 0;
324 int32_t sizei;
325 result += readByte(e);
326 elemType = (TType)e;
327 result += readI32(sizei);
328 if (sizei < 0) {
329 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
330 } else if (this->container_limit_ && sizei > this->container_limit_) {
331 throw TProtocolException(TProtocolException::SIZE_LIMIT);
332 }
333 size = (uint32_t)sizei;
334 return result;
335}
336
337template <class Transport_>
338uint32_t TBinaryProtocolT<Transport_>::readSetEnd() {
339 return 0;
340}
341
342template <class Transport_>
343uint32_t TBinaryProtocolT<Transport_>::readBool(bool& value) {
344 uint8_t b[1];
345 this->trans_->readAll(b, 1);
346 value = *(int8_t*)b != 0;
347 return 1;
348}
349
350template <class Transport_>
351uint32_t TBinaryProtocolT<Transport_>::readByte(int8_t& byte) {
352 uint8_t b[1];
353 this->trans_->readAll(b, 1);
354 byte = *(int8_t*)b;
355 return 1;
356}
357
358template <class Transport_>
359uint32_t TBinaryProtocolT<Transport_>::readI16(int16_t& i16) {
Christian Lavoie2bbc3282011-02-08 23:05:47 +0000360 union bytes {
361 uint8_t b[2];
362 int16_t all;
363 } theBytes;
364 this->trans_->readAll(theBytes.b, 2);
365 i16 = (int16_t)ntohs(theBytes.all);
David Reisse71115b2010-10-06 17:09:56 +0000366 return 2;
367}
368
369template <class Transport_>
370uint32_t TBinaryProtocolT<Transport_>::readI32(int32_t& i32) {
Christian Lavoie2bbc3282011-02-08 23:05:47 +0000371 union bytes {
372 uint8_t b[4];
373 int32_t all;
374 } theBytes;
375 this->trans_->readAll(theBytes.b, 4);
376 i32 = (int32_t)ntohl(theBytes.all);
David Reisse71115b2010-10-06 17:09:56 +0000377 return 4;
378}
379
380template <class Transport_>
381uint32_t TBinaryProtocolT<Transport_>::readI64(int64_t& i64) {
Christian Lavoie2bbc3282011-02-08 23:05:47 +0000382 union bytes {
383 uint8_t b[8];
384 int64_t all;
385 } theBytes;
386 this->trans_->readAll(theBytes.b, 8);
387 i64 = (int64_t)ntohll(theBytes.all);
David Reisse71115b2010-10-06 17:09:56 +0000388 return 8;
389}
390
391template <class Transport_>
392uint32_t TBinaryProtocolT<Transport_>::readDouble(double& dub) {
393 BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
394 BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
395
Christian Lavoie2bbc3282011-02-08 23:05:47 +0000396 union bytes {
397 uint8_t b[8];
398 uint64_t all;
399 } theBytes;
400 this->trans_->readAll(theBytes.b, 8);
401 theBytes.all = ntohll(theBytes.all);
402 dub = bitwise_cast<double>(theBytes.all);
David Reisse71115b2010-10-06 17:09:56 +0000403 return 8;
404}
405
406template <class Transport_>
Jake Farrellf42ae012012-06-22 03:22:53 +0000407template<typename StrType>
408uint32_t TBinaryProtocolT<Transport_>::readString(StrType& str) {
David Reisse71115b2010-10-06 17:09:56 +0000409 uint32_t result;
410 int32_t size;
411 result = readI32(size);
412 return result + readStringBody(str, size);
413}
414
415template <class Transport_>
416uint32_t TBinaryProtocolT<Transport_>::readBinary(std::string& str) {
417 return TBinaryProtocolT<Transport_>::readString(str);
418}
419
420template <class Transport_>
Jake Farrellf42ae012012-06-22 03:22:53 +0000421template<typename StrType>
422uint32_t TBinaryProtocolT<Transport_>::readStringBody(StrType& str,
David Reisse71115b2010-10-06 17:09:56 +0000423 int32_t size) {
424 uint32_t result = 0;
425
426 // Catch error cases
427 if (size < 0) {
428 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
429 }
430 if (this->string_limit_ > 0 && size > this->string_limit_) {
431 throw TProtocolException(TProtocolException::SIZE_LIMIT);
432 }
433
434 // Catch empty string case
435 if (size == 0) {
Roger Meier92a90ff2012-04-13 14:50:32 +0000436 str.clear();
David Reisse71115b2010-10-06 17:09:56 +0000437 return result;
438 }
439
440 // Try to borrow first
441 const uint8_t* borrow_buf;
442 uint32_t got = size;
443 if ((borrow_buf = this->trans_->borrow(NULL, &got))) {
444 str.assign((const char*)borrow_buf, size);
445 this->trans_->consume(size);
446 return size;
447 }
448
Ben Craigfd64c152013-10-09 15:26:05 -0500449 str.resize(size);
450 this->trans_->readAll(reinterpret_cast<uint8_t *>(&str[0]), size);
David Reisse71115b2010-10-06 17:09:56 +0000451 return (uint32_t)size;
452}
453
454}}} // apache::thrift::protocol
455
456#endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_