]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
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 | auto 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 | auto 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 | auto 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 | static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)"); | |
169 | static_assert(std::numeric_limits<double>::is_iec559, "std::numeric_limits<double>::is_iec559"); | |
170 | ||
171 | auto 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 | auto 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 | static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)"); | |
392 | static_assert(std::numeric_limits<double>::is_iec559, "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(nullptr, &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_ |