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