blob: 6a4838b4446f76a913dc03a8854572afb286a718 [file] [log] [blame]
Gavin McDonald0b75e1a2010-10-28 02:12:01 +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#include "TBinaryProtocol.h"
21
22#include <limits>
23
24using std::string;
25
26namespace apache { namespace thrift { namespace protocol {
27
28uint32_t TBinaryProtocol::writeMessageBegin(const std::string& name,
29 const TMessageType messageType,
30 const int32_t seqid) {
31 if (strict_write_) {
32 int32_t version = (VERSION_1) | ((int32_t)messageType);
33 uint32_t wsize = 0;
34 wsize += writeI32(version);
35 wsize += writeString(name);
36 wsize += writeI32(seqid);
37 return wsize;
38 } else {
39 uint32_t wsize = 0;
40 wsize += writeString(name);
41 wsize += writeByte((int8_t)messageType);
42 wsize += writeI32(seqid);
43 return wsize;
44 }
45}
46
47uint32_t TBinaryProtocol::writeMessageEnd() {
48 return 0;
49}
50
51uint32_t TBinaryProtocol::writeStructBegin(const char* name) {
52 return 0;
53}
54
55uint32_t TBinaryProtocol::writeStructEnd() {
56 return 0;
57}
58
59uint32_t TBinaryProtocol::writeFieldBegin(const char* name,
60 const TType fieldType,
61 const int16_t fieldId) {
62 uint32_t wsize = 0;
63 wsize += writeByte((int8_t)fieldType);
64 wsize += writeI16(fieldId);
65 return wsize;
66}
67
68uint32_t TBinaryProtocol::writeFieldEnd() {
69 return 0;
70}
71
72uint32_t TBinaryProtocol::writeFieldStop() {
73 return
74 writeByte((int8_t)T_STOP);
75}
76
77uint32_t TBinaryProtocol::writeMapBegin(const TType keyType,
78 const TType valType,
79 const uint32_t size) {
80 uint32_t wsize = 0;
81 wsize += writeByte((int8_t)keyType);
82 wsize += writeByte((int8_t)valType);
83 wsize += writeI32((int32_t)size);
84 return wsize;
85}
86
87uint32_t TBinaryProtocol::writeMapEnd() {
88 return 0;
89}
90
91uint32_t TBinaryProtocol::writeListBegin(const TType elemType,
92 const uint32_t size) {
93 uint32_t wsize = 0;
94 wsize += writeByte((int8_t) elemType);
95 wsize += writeI32((int32_t)size);
96 return wsize;
97}
98
99uint32_t TBinaryProtocol::writeListEnd() {
100 return 0;
101}
102
103uint32_t TBinaryProtocol::writeSetBegin(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
111uint32_t TBinaryProtocol::writeSetEnd() {
112 return 0;
113}
114
115uint32_t TBinaryProtocol::writeBool(const bool value) {
116 uint8_t tmp = value ? 1 : 0;
117 trans_->write(&tmp, 1);
118 return 1;
119}
120
121uint32_t TBinaryProtocol::writeByte(const int8_t byte) {
122 trans_->write((uint8_t*)&byte, 1);
123 return 1;
124}
125
126uint32_t TBinaryProtocol::writeI16(const int16_t i16) {
127 int16_t net = (int16_t)htons(i16);
128 trans_->write((uint8_t*)&net, 2);
129 return 2;
130}
131
132uint32_t TBinaryProtocol::writeI32(const int32_t i32) {
133 int32_t net = (int32_t)htonl(i32);
134 trans_->write((uint8_t*)&net, 4);
135 return 4;
136}
137
138uint32_t TBinaryProtocol::writeI64(const int64_t i64) {
139 int64_t net = (int64_t)htonll(i64);
140 trans_->write((uint8_t*)&net, 8);
141 return 8;
142}
143
144uint32_t TBinaryProtocol::writeDouble(const double dub) {
145 BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
146 BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
147
148 uint64_t bits = bitwise_cast<uint64_t>(dub);
149 bits = htonll(bits);
150 trans_->write((uint8_t*)&bits, 8);
151 return 8;
152}
153
154
155uint32_t TBinaryProtocol::writeString(const string& str) {
156 uint32_t size = str.size();
157 uint32_t result = writeI32((int32_t)size);
158 if (size > 0) {
159 trans_->write((uint8_t*)str.data(), size);
160 }
161 return result + size;
162}
163
164uint32_t TBinaryProtocol::writeBinary(const string& str) {
165 return TBinaryProtocol::writeString(str);
166}
167
168/**
169 * Reading functions
170 */
171
172uint32_t TBinaryProtocol::readMessageBegin(std::string& name,
173 TMessageType& messageType,
174 int32_t& seqid) {
175 uint32_t result = 0;
176 int32_t sz;
177 result += readI32(sz);
178
179 if (sz < 0) {
180 // Check for correct version number
181 int32_t version = sz & VERSION_MASK;
182 if (version != VERSION_1) {
183 throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier");
184 }
185 messageType = (TMessageType)(sz & 0x000000ff);
186 result += readString(name);
187 result += readI32(seqid);
188 } else {
189 if (strict_read_) {
190 throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?");
191 } else {
192 // Handle pre-versioned input
193 int8_t type;
194 result += readStringBody(name, sz);
195 result += readByte(type);
196 messageType = (TMessageType)type;
197 result += readI32(seqid);
198 }
199 }
200 return result;
201}
202
203uint32_t TBinaryProtocol::readMessageEnd() {
204 return 0;
205}
206
207uint32_t TBinaryProtocol::readStructBegin(string& name) {
208 name = "";
209 return 0;
210}
211
212uint32_t TBinaryProtocol::readStructEnd() {
213 return 0;
214}
215
216uint32_t TBinaryProtocol::readFieldBegin(string& name,
217 TType& fieldType,
218 int16_t& fieldId) {
219 uint32_t result = 0;
220 int8_t type;
221 result += readByte(type);
222 fieldType = (TType)type;
223 if (fieldType == T_STOP) {
224 fieldId = 0;
225 return result;
226 }
227 result += readI16(fieldId);
228 return result;
229}
230
231uint32_t TBinaryProtocol::readFieldEnd() {
232 return 0;
233}
234
235uint32_t TBinaryProtocol::readMapBegin(TType& keyType,
236 TType& valType,
237 uint32_t& size) {
238 int8_t k, v;
239 uint32_t result = 0;
240 int32_t sizei;
241 result += readByte(k);
242 keyType = (TType)k;
243 result += readByte(v);
244 valType = (TType)v;
245 result += readI32(sizei);
246 if (sizei < 0) {
247 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
248 } else if (container_limit_ && sizei > container_limit_) {
249 throw TProtocolException(TProtocolException::SIZE_LIMIT);
250 }
251 size = (uint32_t)sizei;
252 return result;
253}
254
255uint32_t TBinaryProtocol::readMapEnd() {
256 return 0;
257}
258
259uint32_t TBinaryProtocol::readListBegin(TType& elemType,
260 uint32_t& size) {
261 int8_t e;
262 uint32_t result = 0;
263 int32_t sizei;
264 result += readByte(e);
265 elemType = (TType)e;
266 result += readI32(sizei);
267 if (sizei < 0) {
268 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
269 } else if (container_limit_ && sizei > container_limit_) {
270 throw TProtocolException(TProtocolException::SIZE_LIMIT);
271 }
272 size = (uint32_t)sizei;
273 return result;
274}
275
276uint32_t TBinaryProtocol::readListEnd() {
277 return 0;
278}
279
280uint32_t TBinaryProtocol::readSetBegin(TType& elemType,
281 uint32_t& size) {
282 int8_t e;
283 uint32_t result = 0;
284 int32_t sizei;
285 result += readByte(e);
286 elemType = (TType)e;
287 result += readI32(sizei);
288 if (sizei < 0) {
289 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
290 } else if (container_limit_ && sizei > container_limit_) {
291 throw TProtocolException(TProtocolException::SIZE_LIMIT);
292 }
293 size = (uint32_t)sizei;
294 return result;
295}
296
297uint32_t TBinaryProtocol::readSetEnd() {
298 return 0;
299}
300
301uint32_t TBinaryProtocol::readBool(bool& value) {
302 uint8_t b[1];
303 trans_->readAll(b, 1);
304 value = *(int8_t*)b != 0;
305 return 1;
306}
307
308uint32_t TBinaryProtocol::readByte(int8_t& byte) {
309 uint8_t b[1];
310 trans_->readAll(b, 1);
311 byte = *(int8_t*)b;
312 return 1;
313}
314
315uint32_t TBinaryProtocol::readI16(int16_t& i16) {
316 uint8_t b[2];
317 trans_->readAll(b, 2);
318 i16 = *(int16_t*)b;
319 i16 = (int16_t)ntohs(i16);
320 return 2;
321}
322
323uint32_t TBinaryProtocol::readI32(int32_t& i32) {
324 uint8_t b[4];
325 trans_->readAll(b, 4);
326 i32 = *(int32_t*)b;
327 i32 = (int32_t)ntohl(i32);
328 return 4;
329}
330
331uint32_t TBinaryProtocol::readI64(int64_t& i64) {
332 uint8_t b[8];
333 trans_->readAll(b, 8);
334 i64 = *(int64_t*)b;
335 i64 = (int64_t)ntohll(i64);
336 return 8;
337}
338
339uint32_t TBinaryProtocol::readDouble(double& dub) {
340 BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
341 BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
342
343 uint64_t bits;
344 uint8_t b[8];
345 trans_->readAll(b, 8);
346 bits = *(uint64_t*)b;
347 bits = ntohll(bits);
348 dub = bitwise_cast<double>(bits);
349 return 8;
350}
351
352uint32_t TBinaryProtocol::readString(string& str) {
353 uint32_t result;
354 int32_t size;
355 result = readI32(size);
356 return result + readStringBody(str, size);
357}
358
359uint32_t TBinaryProtocol::readBinary(string& str) {
360 return TBinaryProtocol::readString(str);
361}
362
363uint32_t TBinaryProtocol::readStringBody(string& str, int32_t size) {
364 uint32_t result = 0;
365
366 // Catch error cases
367 if (size < 0) {
368 throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
369 }
370 if (string_limit_ > 0 && size > string_limit_) {
371 throw TProtocolException(TProtocolException::SIZE_LIMIT);
372 }
373
374 // Catch empty string case
375 if (size == 0) {
376 str = "";
377 return result;
378 }
379
380 // Use the heap here to prevent stack overflow for v. large strings
381 if (size > string_buf_size_ || string_buf_ == NULL) {
382 void* new_string_buf = std::realloc(string_buf_, (uint32_t)size);
383 if (new_string_buf == NULL) {
384 throw TProtocolException(TProtocolException::UNKNOWN, "Out of memory in TBinaryProtocol::readString");
385 }
386 string_buf_ = (uint8_t*)new_string_buf;
387 string_buf_size_ = size;
388 }
389 trans_->readAll(string_buf_, size);
390 str = string((char*)string_buf_, size);
391 return (uint32_t)size;
392}
393
394}}} // apache::thrift::protocol