blob: 1433a4f03c9c45559db5b5af09c333884886d6ff [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) {
57 return 0;
58}
59
60template <class Transport_>
61uint32_t TBinaryProtocolT<Transport_>::writeStructEnd() {
62 return 0;
63}
64
65template <class Transport_>
66uint32_t TBinaryProtocolT<Transport_>::writeFieldBegin(const char* name,
67 const TType fieldType,
68 const int16_t fieldId) {
69 uint32_t wsize = 0;
70 wsize += writeByte((int8_t)fieldType);
71 wsize += writeI16(fieldId);
72 return wsize;
73}
74
75template <class Transport_>
76uint32_t TBinaryProtocolT<Transport_>::writeFieldEnd() {
77 return 0;
78}
79
80template <class Transport_>
81uint32_t TBinaryProtocolT<Transport_>::writeFieldStop() {
82 return
83 writeByte((int8_t)T_STOP);
84}
85
86template <class Transport_>
87uint32_t TBinaryProtocolT<Transport_>::writeMapBegin(const TType keyType,
88 const TType valType,
89 const uint32_t size) {
90 uint32_t wsize = 0;
91 wsize += writeByte((int8_t)keyType);
92 wsize += writeByte((int8_t)valType);
93 wsize += writeI32((int32_t)size);
94 return wsize;
95}
96
97template <class Transport_>
98uint32_t TBinaryProtocolT<Transport_>::writeMapEnd() {
99 return 0;
100}
101
102template <class Transport_>
103uint32_t TBinaryProtocolT<Transport_>::writeListBegin(const TType elemType,
104 const uint32_t size) {
105 uint32_t wsize = 0;
106 wsize += writeByte((int8_t) elemType);
107 wsize += writeI32((int32_t)size);
108 return wsize;
109}
110
111template <class Transport_>
112uint32_t TBinaryProtocolT<Transport_>::writeListEnd() {
113 return 0;
114}
115
116template <class Transport_>
117uint32_t TBinaryProtocolT<Transport_>::writeSetBegin(const TType elemType,
118 const uint32_t size) {
119 uint32_t wsize = 0;
120 wsize += writeByte((int8_t)elemType);
121 wsize += writeI32((int32_t)size);
122 return wsize;
123}
124
125template <class Transport_>
126uint32_t TBinaryProtocolT<Transport_>::writeSetEnd() {
127 return 0;
128}
129
130template <class Transport_>
131uint32_t TBinaryProtocolT<Transport_>::writeBool(const bool value) {
132 uint8_t tmp = value ? 1 : 0;
133 this->trans_->write(&tmp, 1);
134 return 1;
135}
136
137template <class Transport_>
138uint32_t TBinaryProtocolT<Transport_>::writeByte(const int8_t byte) {
139 this->trans_->write((uint8_t*)&byte, 1);
140 return 1;
141}
142
143template <class Transport_>
144uint32_t TBinaryProtocolT<Transport_>::writeI16(const int16_t i16) {
145 int16_t net = (int16_t)htons(i16);
146 this->trans_->write((uint8_t*)&net, 2);
147 return 2;
148}
149
150template <class Transport_>
151uint32_t TBinaryProtocolT<Transport_>::writeI32(const int32_t i32) {
152 int32_t net = (int32_t)htonl(i32);
153 this->trans_->write((uint8_t*)&net, 4);
154 return 4;
155}
156
157template <class Transport_>
158uint32_t TBinaryProtocolT<Transport_>::writeI64(const int64_t i64) {
159 int64_t net = (int64_t)htonll(i64);
160 this->trans_->write((uint8_t*)&net, 8);
161 return 8;
162}
163
164template <class Transport_>
165uint32_t TBinaryProtocolT<Transport_>::writeDouble(const double dub) {
166 BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
167 BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
168
169 uint64_t bits = bitwise_cast<uint64_t>(dub);
170 bits = htonll(bits);
171 this->trans_->write((uint8_t*)&bits, 8);
172 return 8;
173}
174
175
176template <class Transport_>
177uint32_t TBinaryProtocolT<Transport_>::writeString(const std::string& str) {
178 uint32_t size = str.size();
179 uint32_t result = writeI32((int32_t)size);
180 if (size > 0) {
181 this->trans_->write((uint8_t*)str.data(), size);
182 }
183 return result + size;
184}
185
186template <class Transport_>
187uint32_t TBinaryProtocolT<Transport_>::writeBinary(const std::string& str) {
188 return TBinaryProtocolT<Transport_>::writeString(str);
189}
190
191/**
192 * Reading functions
193 */
194
195template <class Transport_>
196uint32_t TBinaryProtocolT<Transport_>::readMessageBegin(std::string& name,
197 TMessageType& messageType,
198 int32_t& seqid) {
199 uint32_t result = 0;
200 int32_t sz;
201 result += readI32(sz);
202
203 if (sz < 0) {
204 // Check for correct version number
205 int32_t version = sz & VERSION_MASK;
206 if (version != VERSION_1) {
207 throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier");
208 }
209 messageType = (TMessageType)(sz & 0x000000ff);
210 result += readString(name);
211 result += readI32(seqid);
212 } else {
213 if (this->strict_read_) {
214 throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?");
215 } else {
216 // Handle pre-versioned input
217 int8_t type;
218 result += readStringBody(name, sz);
219 result += readByte(type);
220 messageType = (TMessageType)type;
221 result += readI32(seqid);
222 }
223 }
224 return result;
225}
226
227template <class Transport_>
228uint32_t TBinaryProtocolT<Transport_>::readMessageEnd() {
229 return 0;
230}
231
232template <class Transport_>
233uint32_t TBinaryProtocolT<Transport_>::readStructBegin(std::string& name) {
234 name = "";
235 return 0;
236}
237
238template <class Transport_>
239uint32_t TBinaryProtocolT<Transport_>::readStructEnd() {
240 return 0;
241}
242
243template <class Transport_>
244uint32_t TBinaryProtocolT<Transport_>::readFieldBegin(std::string& name,
245 TType& fieldType,
246 int16_t& fieldId) {
247 uint32_t result = 0;
248 int8_t type;
249 result += readByte(type);
250 fieldType = (TType)type;
251 if (fieldType == T_STOP) {
252 fieldId = 0;
253 return result;
254 }
255 result += readI16(fieldId);
256 return result;
257}
258
259template <class Transport_>
260uint32_t TBinaryProtocolT<Transport_>::readFieldEnd() {
261 return 0;
262}
263
264template <class Transport_>
265uint32_t TBinaryProtocolT<Transport_>::readMapBegin(TType& keyType,
266 TType& valType,
267 uint32_t& size) {
268 int8_t k, v;
269 uint32_t result = 0;
270 int32_t sizei;
271 result += readByte(k);
272 keyType = (TType)k;
273 result += readByte(v);
274 valType = (TType)v;
275 result += readI32(sizei);
276 if (sizei < 0) {
277 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
278 } else if (this->container_limit_ && sizei > this->container_limit_) {
279 throw TProtocolException(TProtocolException::SIZE_LIMIT);
280 }
281 size = (uint32_t)sizei;
282 return result;
283}
284
285template <class Transport_>
286uint32_t TBinaryProtocolT<Transport_>::readMapEnd() {
287 return 0;
288}
289
290template <class Transport_>
291uint32_t TBinaryProtocolT<Transport_>::readListBegin(TType& elemType,
292 uint32_t& size) {
293 int8_t e;
294 uint32_t result = 0;
295 int32_t sizei;
296 result += readByte(e);
297 elemType = (TType)e;
298 result += readI32(sizei);
299 if (sizei < 0) {
300 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
301 } else if (this->container_limit_ && sizei > this->container_limit_) {
302 throw TProtocolException(TProtocolException::SIZE_LIMIT);
303 }
304 size = (uint32_t)sizei;
305 return result;
306}
307
308template <class Transport_>
309uint32_t TBinaryProtocolT<Transport_>::readListEnd() {
310 return 0;
311}
312
313template <class Transport_>
314uint32_t TBinaryProtocolT<Transport_>::readSetBegin(TType& elemType,
315 uint32_t& size) {
316 int8_t e;
317 uint32_t result = 0;
318 int32_t sizei;
319 result += readByte(e);
320 elemType = (TType)e;
321 result += readI32(sizei);
322 if (sizei < 0) {
323 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
324 } else if (this->container_limit_ && sizei > this->container_limit_) {
325 throw TProtocolException(TProtocolException::SIZE_LIMIT);
326 }
327 size = (uint32_t)sizei;
328 return result;
329}
330
331template <class Transport_>
332uint32_t TBinaryProtocolT<Transport_>::readSetEnd() {
333 return 0;
334}
335
336template <class Transport_>
337uint32_t TBinaryProtocolT<Transport_>::readBool(bool& value) {
338 uint8_t b[1];
339 this->trans_->readAll(b, 1);
340 value = *(int8_t*)b != 0;
341 return 1;
342}
343
344template <class Transport_>
345uint32_t TBinaryProtocolT<Transport_>::readByte(int8_t& byte) {
346 uint8_t b[1];
347 this->trans_->readAll(b, 1);
348 byte = *(int8_t*)b;
349 return 1;
350}
351
352template <class Transport_>
353uint32_t TBinaryProtocolT<Transport_>::readI16(int16_t& i16) {
354 uint8_t b[2];
355 this->trans_->readAll(b, 2);
356 i16 = *(int16_t*)b;
357 i16 = (int16_t)ntohs(i16);
358 return 2;
359}
360
361template <class Transport_>
362uint32_t TBinaryProtocolT<Transport_>::readI32(int32_t& i32) {
363 uint8_t b[4];
364 this->trans_->readAll(b, 4);
365 i32 = *(int32_t*)b;
366 i32 = (int32_t)ntohl(i32);
367 return 4;
368}
369
370template <class Transport_>
371uint32_t TBinaryProtocolT<Transport_>::readI64(int64_t& i64) {
372 uint8_t b[8];
373 this->trans_->readAll(b, 8);
374 i64 = *(int64_t*)b;
375 i64 = (int64_t)ntohll(i64);
376 return 8;
377}
378
379template <class Transport_>
380uint32_t TBinaryProtocolT<Transport_>::readDouble(double& dub) {
381 BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
382 BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
383
384 uint64_t bits;
385 uint8_t b[8];
386 this->trans_->readAll(b, 8);
387 bits = *(uint64_t*)b;
388 bits = ntohll(bits);
389 dub = bitwise_cast<double>(bits);
390 return 8;
391}
392
393template <class Transport_>
394uint32_t TBinaryProtocolT<Transport_>::readString(std::string& str) {
395 uint32_t result;
396 int32_t size;
397 result = readI32(size);
398 return result + readStringBody(str, size);
399}
400
401template <class Transport_>
402uint32_t TBinaryProtocolT<Transport_>::readBinary(std::string& str) {
403 return TBinaryProtocolT<Transport_>::readString(str);
404}
405
406template <class Transport_>
407uint32_t TBinaryProtocolT<Transport_>::readStringBody(std::string& str,
408 int32_t size) {
409 uint32_t result = 0;
410
411 // Catch error cases
412 if (size < 0) {
413 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
414 }
415 if (this->string_limit_ > 0 && size > this->string_limit_) {
416 throw TProtocolException(TProtocolException::SIZE_LIMIT);
417 }
418
419 // Catch empty string case
420 if (size == 0) {
421 str = "";
422 return result;
423 }
424
425 // Try to borrow first
426 const uint8_t* borrow_buf;
427 uint32_t got = size;
428 if ((borrow_buf = this->trans_->borrow(NULL, &got))) {
429 str.assign((const char*)borrow_buf, size);
430 this->trans_->consume(size);
431 return size;
432 }
433
434 // Use the heap here to prevent stack overflow for v. large strings
435 if (size > this->string_buf_size_ || this->string_buf_ == NULL) {
436 void* new_string_buf = std::realloc(this->string_buf_, (uint32_t)size);
437 if (new_string_buf == NULL) {
438 throw TProtocolException(TProtocolException::UNKNOWN,
439 "Out of memory in TBinaryProtocolT::readString");
440 }
441 this->string_buf_ = (uint8_t*)new_string_buf;
442 this->string_buf_size_ = size;
443 }
444 this->trans_->readAll(this->string_buf_, size);
445 str = std::string((char*)this->string_buf_, size);
446 return (uint32_t)size;
447}
448
449}}} // apache::thrift::protocol
450
451#endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_