blob: 3d9334838f3f8ff4a7a2b889e2d0455be04dd652 [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
23#include "TBinaryProtocol.h"
24
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_>
179uint32_t TBinaryProtocolT<Transport_>::writeString(const std::string& str) {
180 uint32_t size = str.size();
181 uint32_t result = writeI32((int32_t)size);
182 if (size > 0) {
183 this->trans_->write((uint8_t*)str.data(), size);
184 }
185 return result + size;
186}
187
188template <class Transport_>
189uint32_t TBinaryProtocolT<Transport_>::writeBinary(const std::string& str) {
190 return TBinaryProtocolT<Transport_>::writeString(str);
191}
192
193/**
194 * Reading functions
195 */
196
197template <class Transport_>
198uint32_t TBinaryProtocolT<Transport_>::readMessageBegin(std::string& name,
199 TMessageType& messageType,
200 int32_t& seqid) {
201 uint32_t result = 0;
202 int32_t sz;
203 result += readI32(sz);
204
205 if (sz < 0) {
206 // Check for correct version number
207 int32_t version = sz & VERSION_MASK;
208 if (version != VERSION_1) {
209 throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier");
210 }
211 messageType = (TMessageType)(sz & 0x000000ff);
212 result += readString(name);
213 result += readI32(seqid);
214 } else {
215 if (this->strict_read_) {
216 throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?");
217 } else {
218 // Handle pre-versioned input
219 int8_t type;
220 result += readStringBody(name, sz);
221 result += readByte(type);
222 messageType = (TMessageType)type;
223 result += readI32(seqid);
224 }
225 }
226 return result;
227}
228
229template <class Transport_>
230uint32_t TBinaryProtocolT<Transport_>::readMessageEnd() {
231 return 0;
232}
233
234template <class Transport_>
235uint32_t TBinaryProtocolT<Transport_>::readStructBegin(std::string& name) {
236 name = "";
237 return 0;
238}
239
240template <class Transport_>
241uint32_t TBinaryProtocolT<Transport_>::readStructEnd() {
242 return 0;
243}
244
245template <class Transport_>
246uint32_t TBinaryProtocolT<Transport_>::readFieldBegin(std::string& name,
247 TType& fieldType,
248 int16_t& fieldId) {
Roger Meier3b771a12010-11-17 22:11:26 +0000249 (void) name;
David Reisse71115b2010-10-06 17:09:56 +0000250 uint32_t result = 0;
251 int8_t type;
252 result += readByte(type);
253 fieldType = (TType)type;
254 if (fieldType == T_STOP) {
255 fieldId = 0;
256 return result;
257 }
258 result += readI16(fieldId);
259 return result;
260}
261
262template <class Transport_>
263uint32_t TBinaryProtocolT<Transport_>::readFieldEnd() {
264 return 0;
265}
266
267template <class Transport_>
268uint32_t TBinaryProtocolT<Transport_>::readMapBegin(TType& keyType,
269 TType& valType,
270 uint32_t& size) {
271 int8_t k, v;
272 uint32_t result = 0;
273 int32_t sizei;
274 result += readByte(k);
275 keyType = (TType)k;
276 result += readByte(v);
277 valType = (TType)v;
278 result += readI32(sizei);
279 if (sizei < 0) {
280 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
281 } else if (this->container_limit_ && sizei > this->container_limit_) {
282 throw TProtocolException(TProtocolException::SIZE_LIMIT);
283 }
284 size = (uint32_t)sizei;
285 return result;
286}
287
288template <class Transport_>
289uint32_t TBinaryProtocolT<Transport_>::readMapEnd() {
290 return 0;
291}
292
293template <class Transport_>
294uint32_t TBinaryProtocolT<Transport_>::readListBegin(TType& elemType,
295 uint32_t& size) {
296 int8_t e;
297 uint32_t result = 0;
298 int32_t sizei;
299 result += readByte(e);
300 elemType = (TType)e;
301 result += readI32(sizei);
302 if (sizei < 0) {
303 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
304 } else if (this->container_limit_ && sizei > this->container_limit_) {
305 throw TProtocolException(TProtocolException::SIZE_LIMIT);
306 }
307 size = (uint32_t)sizei;
308 return result;
309}
310
311template <class Transport_>
312uint32_t TBinaryProtocolT<Transport_>::readListEnd() {
313 return 0;
314}
315
316template <class Transport_>
317uint32_t TBinaryProtocolT<Transport_>::readSetBegin(TType& elemType,
318 uint32_t& size) {
319 int8_t e;
320 uint32_t result = 0;
321 int32_t sizei;
322 result += readByte(e);
323 elemType = (TType)e;
324 result += readI32(sizei);
325 if (sizei < 0) {
326 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
327 } else if (this->container_limit_ && sizei > this->container_limit_) {
328 throw TProtocolException(TProtocolException::SIZE_LIMIT);
329 }
330 size = (uint32_t)sizei;
331 return result;
332}
333
334template <class Transport_>
335uint32_t TBinaryProtocolT<Transport_>::readSetEnd() {
336 return 0;
337}
338
339template <class Transport_>
340uint32_t TBinaryProtocolT<Transport_>::readBool(bool& value) {
341 uint8_t b[1];
342 this->trans_->readAll(b, 1);
343 value = *(int8_t*)b != 0;
344 return 1;
345}
346
347template <class Transport_>
348uint32_t TBinaryProtocolT<Transport_>::readByte(int8_t& byte) {
349 uint8_t b[1];
350 this->trans_->readAll(b, 1);
351 byte = *(int8_t*)b;
352 return 1;
353}
354
355template <class Transport_>
356uint32_t TBinaryProtocolT<Transport_>::readI16(int16_t& i16) {
357 uint8_t b[2];
358 this->trans_->readAll(b, 2);
359 i16 = *(int16_t*)b;
360 i16 = (int16_t)ntohs(i16);
361 return 2;
362}
363
364template <class Transport_>
365uint32_t TBinaryProtocolT<Transport_>::readI32(int32_t& i32) {
366 uint8_t b[4];
367 this->trans_->readAll(b, 4);
368 i32 = *(int32_t*)b;
369 i32 = (int32_t)ntohl(i32);
370 return 4;
371}
372
373template <class Transport_>
374uint32_t TBinaryProtocolT<Transport_>::readI64(int64_t& i64) {
375 uint8_t b[8];
376 this->trans_->readAll(b, 8);
377 i64 = *(int64_t*)b;
378 i64 = (int64_t)ntohll(i64);
379 return 8;
380}
381
382template <class Transport_>
383uint32_t TBinaryProtocolT<Transport_>::readDouble(double& dub) {
384 BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
385 BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
386
387 uint64_t bits;
388 uint8_t b[8];
389 this->trans_->readAll(b, 8);
390 bits = *(uint64_t*)b;
391 bits = ntohll(bits);
392 dub = bitwise_cast<double>(bits);
393 return 8;
394}
395
396template <class Transport_>
397uint32_t TBinaryProtocolT<Transport_>::readString(std::string& str) {
398 uint32_t result;
399 int32_t size;
400 result = readI32(size);
401 return result + readStringBody(str, size);
402}
403
404template <class Transport_>
405uint32_t TBinaryProtocolT<Transport_>::readBinary(std::string& str) {
406 return TBinaryProtocolT<Transport_>::readString(str);
407}
408
409template <class Transport_>
410uint32_t TBinaryProtocolT<Transport_>::readStringBody(std::string& str,
411 int32_t size) {
412 uint32_t result = 0;
413
414 // Catch error cases
415 if (size < 0) {
416 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
417 }
418 if (this->string_limit_ > 0 && size > this->string_limit_) {
419 throw TProtocolException(TProtocolException::SIZE_LIMIT);
420 }
421
422 // Catch empty string case
423 if (size == 0) {
424 str = "";
425 return result;
426 }
427
428 // Try to borrow first
429 const uint8_t* borrow_buf;
430 uint32_t got = size;
431 if ((borrow_buf = this->trans_->borrow(NULL, &got))) {
432 str.assign((const char*)borrow_buf, size);
433 this->trans_->consume(size);
434 return size;
435 }
436
437 // Use the heap here to prevent stack overflow for v. large strings
438 if (size > this->string_buf_size_ || this->string_buf_ == NULL) {
439 void* new_string_buf = std::realloc(this->string_buf_, (uint32_t)size);
440 if (new_string_buf == NULL) {
David Reissf6735092010-10-06 17:10:49 +0000441 throw std::bad_alloc();
David Reisse71115b2010-10-06 17:09:56 +0000442 }
443 this->string_buf_ = (uint8_t*)new_string_buf;
444 this->string_buf_size_ = size;
445 }
446 this->trans_->readAll(this->string_buf_, size);
447 str = std::string((char*)this->string_buf_, size);
448 return (uint32_t)size;
449}
450
451}}} // apache::thrift::protocol
452
453#endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_