blob: 962fcfedf9f70b1d0a3cb286b34a1d5ba55520b1 [file] [log] [blame]
Mark Slee4902c052007-03-01 00:31:30 +00001<?php
2
3/**
4 * Copyright (c) 2006- Facebook
5 * Distributed under the Thrift Software License
6 *
7 * See accompanying file LICENSE or visit the Thrift site at:
8 * http://developers.facebook.com/thrift/
9 *
10 * @package thrift.protocol
11 * @author Mark Slee <mcslee@facebook.com>
12 */
Mark Slee6e536442006-06-30 18:28:50 +000013
Mark Slee6e536442006-06-30 18:28:50 +000014/**
15 * Binary implementation of the Thrift protocol.
16 *
Mark Slee6e536442006-06-30 18:28:50 +000017 * @author Mark Slee <mcslee@facebook.com>
Mark Sleeadde9682007-03-01 00:37:56 +000018 * @author Marc Kwiatkowski <marc@facebook.com>
Mark Slee6e536442006-06-30 18:28:50 +000019 */
20class TBinaryProtocol extends TProtocol {
21
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000022 public function __construct($trans) {
23 parent::__construct($trans);
Mark Slee5f8237d2006-10-26 04:57:03 +000024 }
25
26 public function writeMessageBegin($name, $type, $seqid) {
Mark Sleecfc01932006-09-01 22:18:16 +000027 return
Mark Slee5f8237d2006-10-26 04:57:03 +000028 $this->writeString($name) +
29 $this->writeByte($type) +
30 $this->writeI32($seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +000031 }
32
Mark Slee5f8237d2006-10-26 04:57:03 +000033 public function writeMessageEnd() {
Marc Slemkod97eb612006-08-24 23:37:36 +000034 return 0;
35 }
36
Mark Slee5f8237d2006-10-26 04:57:03 +000037 public function writeStructBegin($name) {
Mark Slee6e536442006-06-30 18:28:50 +000038 return 0;
39 }
40
Mark Slee5f8237d2006-10-26 04:57:03 +000041 public function writeStructEnd() {
Mark Slee6e536442006-06-30 18:28:50 +000042 return 0;
43 }
44
Mark Slee5f8237d2006-10-26 04:57:03 +000045 public function writeFieldBegin($fieldName, $fieldType, $fieldId) {
Mark Slee6e536442006-06-30 18:28:50 +000046 return
Mark Slee5f8237d2006-10-26 04:57:03 +000047 $this->writeByte($fieldType) +
48 $this->writeI16($fieldId);
Mark Slee6e536442006-06-30 18:28:50 +000049 }
50
Mark Slee5f8237d2006-10-26 04:57:03 +000051 public function writeFieldEnd() {
Mark Slee6e536442006-06-30 18:28:50 +000052 return 0;
53 }
54
Mark Slee5f8237d2006-10-26 04:57:03 +000055 public function writeFieldStop() {
Mark Slee6e536442006-06-30 18:28:50 +000056 return
Mark Slee5f8237d2006-10-26 04:57:03 +000057 $this->writeByte(TType::STOP);
Mark Slee6e536442006-06-30 18:28:50 +000058 }
59
Mark Slee5f8237d2006-10-26 04:57:03 +000060 public function writeMapBegin($keyType, $valType, $size) {
Mark Slee6e536442006-06-30 18:28:50 +000061 return
Mark Slee5f8237d2006-10-26 04:57:03 +000062 $this->writeByte($keyType) +
63 $this->writeByte($valType) +
64 $this->writeI32($size);
Mark Slee6e536442006-06-30 18:28:50 +000065 }
66
Mark Slee5f8237d2006-10-26 04:57:03 +000067 public function writeMapEnd() {
Mark Slee6e536442006-06-30 18:28:50 +000068 return 0;
69 }
70
Mark Slee5f8237d2006-10-26 04:57:03 +000071 public function writeListBegin($elemType, $size) {
Mark Slee6e536442006-06-30 18:28:50 +000072 return
Mark Slee5f8237d2006-10-26 04:57:03 +000073 $this->writeByte($elemType) +
74 $this->writeI32($size);
Mark Slee6e536442006-06-30 18:28:50 +000075 }
76
Mark Slee5f8237d2006-10-26 04:57:03 +000077 public function writeListEnd() {
Mark Slee6e536442006-06-30 18:28:50 +000078 return 0;
79 }
80
Mark Slee5f8237d2006-10-26 04:57:03 +000081 public function writeSetBegin($elemType, $size) {
Mark Slee6e536442006-06-30 18:28:50 +000082 return
Mark Slee5f8237d2006-10-26 04:57:03 +000083 $this->writeByte($elemType) +
84 $this->writeI32($size);
Mark Slee6e536442006-06-30 18:28:50 +000085 }
86
Mark Slee5f8237d2006-10-26 04:57:03 +000087 public function writeSetEnd() {
Mark Slee6e536442006-06-30 18:28:50 +000088 return 0;
89 }
90
Mark Slee5f8237d2006-10-26 04:57:03 +000091 public function writeBool($value) {
Marc Slemkod97eb612006-08-24 23:37:36 +000092 $data = pack('c', $value ? 1 : 0);
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000093 $this->trans_->write($data, 1);
Mark Slee6e536442006-06-30 18:28:50 +000094 return 1;
95 }
96
Mark Slee5f8237d2006-10-26 04:57:03 +000097 public function writeByte($value) {
Marc Slemkod97eb612006-08-24 23:37:36 +000098 $data = pack('c', $value);
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000099 $this->trans_->write($data, 1);
Marc Slemkod97eb612006-08-24 23:37:36 +0000100 return 1;
101 }
102
Mark Slee5f8237d2006-10-26 04:57:03 +0000103 public function writeI16($value) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000104 $data = pack('n', $value);
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000105 $this->trans_->write($data, 2);
Marc Slemkod97eb612006-08-24 23:37:36 +0000106 return 2;
107 }
108
Mark Slee5f8237d2006-10-26 04:57:03 +0000109 public function writeI32($value) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000110 $data = pack('N', $value);
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000111 $this->trans_->write($data, 4);
Mark Slee6e536442006-06-30 18:28:50 +0000112 return 4;
113 }
114
Mark Slee5f8237d2006-10-26 04:57:03 +0000115 public function writeI64($value) {
Mark Sleecfc01932006-09-01 22:18:16 +0000116 // If we are on a 32bit architecture we have to explicitly deal with
117 // 64-bit twos-complement arithmetic since PHP wants to treat all ints
118 // as signed and any int over 2^31 - 1 as a float
119 if (PHP_INT_SIZE == 4) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000120 $neg = $value < 0;
Mark Sleecfc01932006-09-01 22:18:16 +0000121
122 if ($neg) {
123 $value *= -1;
Marc Slemkod97eb612006-08-24 23:37:36 +0000124 }
Mark Sleecfc01932006-09-01 22:18:16 +0000125
Marc Slemkod97eb612006-08-24 23:37:36 +0000126 $hi = (int)($value / 4294967296);
127 $lo = (int)$value;
128
Mark Sleecfc01932006-09-01 22:18:16 +0000129 if ($neg) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000130 $hi = ~$hi;
131 $lo = ~$lo;
Mark Sleecfc01932006-09-01 22:18:16 +0000132 if (($lo & (int)0xffffffff) == (int)0xffffffff) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000133 $lo = 0;
134 $hi++;
135 } else {
136 $lo++;
137 }
138 }
Mark Slee6e536442006-06-30 18:28:50 +0000139 $data = pack('N2', $hi, $lo);
Marc Slemkod97eb612006-08-24 23:37:36 +0000140
Mark Slee6e536442006-06-30 18:28:50 +0000141 } else {
Marc Slemkod97eb612006-08-24 23:37:36 +0000142 $hi = $value >> 32;
143 $lo = $value & 0xFFFFFFFF;
144 $data = pack('N2', $hi, $lo);
Mark Slee6e536442006-06-30 18:28:50 +0000145 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000146
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000147 $this->trans_->write($data, 8);
Mark Slee6e536442006-06-30 18:28:50 +0000148 return 8;
149 }
150
Mark Slee5f8237d2006-10-26 04:57:03 +0000151 public function writeDouble($value) {
Mark Sleec98d0502006-09-06 02:42:25 +0000152 $data = pack('d', $value);
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000153 $this->trans_->write(strrev($data), 8);
Mark Sleec98d0502006-09-06 02:42:25 +0000154 return 8;
155 }
156
Mark Slee5f8237d2006-10-26 04:57:03 +0000157 public function writeString($value) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000158 $len = strlen($value);
Mark Slee5f8237d2006-10-26 04:57:03 +0000159 $result = $this->writeI32($len);
Mark Sleeade2c832006-09-08 03:41:50 +0000160 if ($len) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000161 $this->trans_->write($value, $len);
Mark Sleeade2c832006-09-08 03:41:50 +0000162 }
Mark Slee6e536442006-06-30 18:28:50 +0000163 return $result + $len;
164 }
165
Mark Slee5f8237d2006-10-26 04:57:03 +0000166 public function readMessageBegin(&$name, &$type, &$seqid) {
Mark Sleecfc01932006-09-01 22:18:16 +0000167 return
Mark Slee5f8237d2006-10-26 04:57:03 +0000168 $this->readString($name) +
169 $this->readByte($type) +
170 $this->readI32($seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +0000171 }
172
Mark Slee5f8237d2006-10-26 04:57:03 +0000173 public function readMessageEnd() {
Marc Slemkod97eb612006-08-24 23:37:36 +0000174 return 0;
175 }
176
Mark Slee5f8237d2006-10-26 04:57:03 +0000177 public function readStructBegin(&$name) {
Mark Slee6e536442006-06-30 18:28:50 +0000178 $name = '';
179 return 0;
180 }
181
Mark Slee5f8237d2006-10-26 04:57:03 +0000182 public function readStructEnd() {
Mark Slee6e536442006-06-30 18:28:50 +0000183 return 0;
184 }
185
Mark Slee5f8237d2006-10-26 04:57:03 +0000186 public function readFieldBegin(&$name, &$fieldType, &$fieldId) {
187 $result = $this->readByte($fieldType);
Mark Slee6e536442006-06-30 18:28:50 +0000188 if ($fieldType == TType::STOP) {
189 $fieldId = 0;
190 return $result;
191 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000192 $result += $this->readI16($fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000193 return $result;
194 }
195
Mark Slee5f8237d2006-10-26 04:57:03 +0000196 public function readFieldEnd() {
Mark Slee6e536442006-06-30 18:28:50 +0000197 return 0;
198 }
199
Mark Slee5f8237d2006-10-26 04:57:03 +0000200 public function readMapBegin(&$keyType, &$valType, &$size) {
Mark Sleecfc01932006-09-01 22:18:16 +0000201 return
Mark Slee5f8237d2006-10-26 04:57:03 +0000202 $this->readByte($keyType) +
203 $this->readByte($valType) +
204 $this->readI32($size);
Mark Slee6e536442006-06-30 18:28:50 +0000205 }
206
Mark Slee5f8237d2006-10-26 04:57:03 +0000207 public function readMapEnd() {
Mark Slee6e536442006-06-30 18:28:50 +0000208 return 0;
209 }
210
Mark Slee5f8237d2006-10-26 04:57:03 +0000211 public function readListBegin(&$elemType, &$size) {
Mark Sleecfc01932006-09-01 22:18:16 +0000212 return
Mark Slee5f8237d2006-10-26 04:57:03 +0000213 $this->readByte($elemType) +
214 $this->readI32($size);
Mark Slee6e536442006-06-30 18:28:50 +0000215 }
216
Mark Slee5f8237d2006-10-26 04:57:03 +0000217 public function readListEnd() {
Mark Slee6e536442006-06-30 18:28:50 +0000218 return 0;
219 }
220
Mark Slee5f8237d2006-10-26 04:57:03 +0000221 public function readSetBegin(&$elemType, &$size) {
Mark Sleecfc01932006-09-01 22:18:16 +0000222 return
Mark Slee5f8237d2006-10-26 04:57:03 +0000223 $this->readByte($elemType) +
224 $this->readI32($size);
Mark Slee6e536442006-06-30 18:28:50 +0000225 }
226
Mark Slee5f8237d2006-10-26 04:57:03 +0000227 public function readSetEnd() {
Mark Slee6e536442006-06-30 18:28:50 +0000228 return 0;
229 }
230
Mark Slee5f8237d2006-10-26 04:57:03 +0000231 public function readBool(&$value) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000232 $data = $this->trans_->readAll(1);
Mark Slee6e536442006-06-30 18:28:50 +0000233 $arr = unpack('c', $data);
Marc Slemkod97eb612006-08-24 23:37:36 +0000234 $value = $arr[1] == 1;
Mark Slee6e536442006-06-30 18:28:50 +0000235 return 1;
236 }
237
Mark Slee5f8237d2006-10-26 04:57:03 +0000238 public function readByte(&$value) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000239 $data = $this->trans_->readAll(1);
Marc Slemkod97eb612006-08-24 23:37:36 +0000240 $arr = unpack('c', $data);
241 $value = $arr[1];
242 return 1;
243 }
244
Mark Slee5f8237d2006-10-26 04:57:03 +0000245 public function readI16(&$value) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000246 $data = $this->trans_->readAll(2);
Marc Slemkod97eb612006-08-24 23:37:36 +0000247 $arr = unpack('n', $data);
248 $value = $arr[1];
Mark Sleecfc01932006-09-01 22:18:16 +0000249 if ($value > 0x7fff) {
250 $value = 0 - (($value - 1) ^ 0xffff);
Mark Slee6e536442006-06-30 18:28:50 +0000251 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000252 return 2;
253 }
254
Mark Slee5f8237d2006-10-26 04:57:03 +0000255 public function readI32(&$value) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000256 $data = $this->trans_->readAll(4);
Marc Slemkod97eb612006-08-24 23:37:36 +0000257 $arr = unpack('N', $data);
258 $value = $arr[1];
Mark Sleecfc01932006-09-01 22:18:16 +0000259 if ($value > 0x7fffffff) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000260 $value = 0 - (($value - 1) ^ 0xffffffff);
261 }
Mark Slee6e536442006-06-30 18:28:50 +0000262 return 4;
263 }
264
Mark Slee5f8237d2006-10-26 04:57:03 +0000265 public function readI64(&$value) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000266 $data = $this->trans_->readAll(8);
Marc Slemkod97eb612006-08-24 23:37:36 +0000267
268 $arr = unpack('N2', $data);
269
Mark Sleecfc01932006-09-01 22:18:16 +0000270 // If we are on a 32bit architecture we have to explicitly deal with
271 // 64-bit twos-complement arithmetic since PHP wants to treat all ints
272 // as signed and any int over 2^31 - 1 as a float
273 if (PHP_INT_SIZE == 4) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000274
275 $hi = $arr[1];
276 $lo = $arr[2];
277 $isNeg = $hi < 0;
278
279 // Check for a negative
Mark Sleecfc01932006-09-01 22:18:16 +0000280 if ($isNeg) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000281 $hi = ~$hi & (int)0xffffffff;
282 $lo = ~$lo & (int)0xffffffff;
283
Mark Sleecfc01932006-09-01 22:18:16 +0000284 if ($lo == (int)0xffffffff) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000285 $hi++;
286 $lo = 0;
287 } else {
288 $lo++;
289 }
290 }
291
Mark Sleecfc01932006-09-01 22:18:16 +0000292 // Force 32bit words in excess of 2G to pe positive - we deal wigh sign
293 // explicitly below
Marc Slemkod97eb612006-08-24 23:37:36 +0000294
Mark Sleecfc01932006-09-01 22:18:16 +0000295 if ($hi & (int)0x80000000) {
296 $hi &= (int)0x7fffffff;
Marc Slemkod97eb612006-08-24 23:37:36 +0000297 $hi += 0x80000000;
298 }
299
Mark Sleecfc01932006-09-01 22:18:16 +0000300 if ($lo & (int)0x80000000) {
301 $lo &= (int)0x7fffffff;
Marc Slemkod97eb612006-08-24 23:37:36 +0000302 $lo += 0x80000000;
303 }
304
305 $value = $hi * 4294967296 + $lo;
306
Mark Sleecfc01932006-09-01 22:18:16 +0000307 if ($isNeg) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000308 $value = 0 - $value;
309 }
310 } else {
311
Mark Slee13a0d4a2007-04-03 03:16:11 +0000312 // Upcast negatives in LSB bit
313 if ($arr[2] & 0x80000000) {
314 $arr[2] = $arr[2] & 0xffffffff;
315 }
316
Marc Slemkod97eb612006-08-24 23:37:36 +0000317 // Check for a negative
318 if ($arr[1] & 0x80000000) {
Mark Slee13a0d4a2007-04-03 03:16:11 +0000319 $arr[1] = $arr[1] & 0xffffffff;
320 $arr[1] = $arr[1] ^ 0xffffffff;
321 $arr[2] = $arr[2] ^ 0xffffffff;
322 $value = 0 - $arr[1]*4294967296 - $arr[2] - 1;
Marc Slemkod97eb612006-08-24 23:37:36 +0000323 } else {
Mark Slee13a0d4a2007-04-03 03:16:11 +0000324 $value = $arr[1]*4294967296 + $arr[2];
Marc Slemkod97eb612006-08-24 23:37:36 +0000325 }
326 }
327
328 return 8;
329 }
330
Mark Slee5f8237d2006-10-26 04:57:03 +0000331 public function readDouble(&$value) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000332 $data = strrev($this->trans_->readAll(8));
Mark Sleec98d0502006-09-06 02:42:25 +0000333 $arr = unpack('d', $data);
334 $value = $arr[1];
335 return 8;
336 }
337
Mark Slee5f8237d2006-10-26 04:57:03 +0000338 public function readString(&$value) {
339 $result = $this->readI32($len);
Mark Sleeade2c832006-09-08 03:41:50 +0000340 if ($len) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000341 $value = $this->trans_->readAll($len);
Mark Sleeade2c832006-09-08 03:41:50 +0000342 } else {
343 $value = '';
344 }
Mark Slee6e536442006-06-30 18:28:50 +0000345 return $result + $len;
346 }
347}
348
Mark Slee5f8237d2006-10-26 04:57:03 +0000349/**
350 * Binary Protocol Factory
351 */
352class TBinaryProtocolFactory implements TProtocolFactory {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000353 public function getProtocol($trans) {
354 return new TBinaryProtocol($trans);
Mark Slee5f8237d2006-10-26 04:57:03 +0000355 }
356}
357
Marc Slemkod97eb612006-08-24 23:37:36 +0000358?>