blob: 91fcd5fbdb39ba4829663a71250c0c6a0ef4d91e [file] [log] [blame]
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +00001<?php
Mark Slee6e536442006-06-30 18:28:50 +00002
Mark Slee6e536442006-06-30 18:28:50 +00003/**
4 * Binary implementation of the Thrift protocol.
5 *
6 * @package thrift.protocol
7 * @author Mark Slee <mcslee@facebook.com>
8 */
9class TBinaryProtocol extends TProtocol {
10
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000011 public function __construct($trans) {
12 parent::__construct($trans);
Mark Slee5f8237d2006-10-26 04:57:03 +000013 }
14
15 public function writeMessageBegin($name, $type, $seqid) {
Mark Sleecfc01932006-09-01 22:18:16 +000016 return
Mark Slee5f8237d2006-10-26 04:57:03 +000017 $this->writeString($name) +
18 $this->writeByte($type) +
19 $this->writeI32($seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +000020 }
21
Mark Slee5f8237d2006-10-26 04:57:03 +000022 public function writeMessageEnd() {
Marc Slemkod97eb612006-08-24 23:37:36 +000023 return 0;
24 }
25
Mark Slee5f8237d2006-10-26 04:57:03 +000026 public function writeStructBegin($name) {
Mark Slee6e536442006-06-30 18:28:50 +000027 return 0;
28 }
29
Mark Slee5f8237d2006-10-26 04:57:03 +000030 public function writeStructEnd() {
Mark Slee6e536442006-06-30 18:28:50 +000031 return 0;
32 }
33
Mark Slee5f8237d2006-10-26 04:57:03 +000034 public function writeFieldBegin($fieldName, $fieldType, $fieldId) {
Mark Slee6e536442006-06-30 18:28:50 +000035 return
Mark Slee5f8237d2006-10-26 04:57:03 +000036 $this->writeByte($fieldType) +
37 $this->writeI16($fieldId);
Mark Slee6e536442006-06-30 18:28:50 +000038 }
39
Mark Slee5f8237d2006-10-26 04:57:03 +000040 public function writeFieldEnd() {
Mark Slee6e536442006-06-30 18:28:50 +000041 return 0;
42 }
43
Mark Slee5f8237d2006-10-26 04:57:03 +000044 public function writeFieldStop() {
Mark Slee6e536442006-06-30 18:28:50 +000045 return
Mark Slee5f8237d2006-10-26 04:57:03 +000046 $this->writeByte(TType::STOP);
Mark Slee6e536442006-06-30 18:28:50 +000047 }
48
Mark Slee5f8237d2006-10-26 04:57:03 +000049 public function writeMapBegin($keyType, $valType, $size) {
Mark Slee6e536442006-06-30 18:28:50 +000050 return
Mark Slee5f8237d2006-10-26 04:57:03 +000051 $this->writeByte($keyType) +
52 $this->writeByte($valType) +
53 $this->writeI32($size);
Mark Slee6e536442006-06-30 18:28:50 +000054 }
55
Mark Slee5f8237d2006-10-26 04:57:03 +000056 public function writeMapEnd() {
Mark Slee6e536442006-06-30 18:28:50 +000057 return 0;
58 }
59
Mark Slee5f8237d2006-10-26 04:57:03 +000060 public function writeListBegin($elemType, $size) {
Mark Slee6e536442006-06-30 18:28:50 +000061 return
Mark Slee5f8237d2006-10-26 04:57:03 +000062 $this->writeByte($elemType) +
63 $this->writeI32($size);
Mark Slee6e536442006-06-30 18:28:50 +000064 }
65
Mark Slee5f8237d2006-10-26 04:57:03 +000066 public function writeListEnd() {
Mark Slee6e536442006-06-30 18:28:50 +000067 return 0;
68 }
69
Mark Slee5f8237d2006-10-26 04:57:03 +000070 public function writeSetBegin($elemType, $size) {
Mark Slee6e536442006-06-30 18:28:50 +000071 return
Mark Slee5f8237d2006-10-26 04:57:03 +000072 $this->writeByte($elemType) +
73 $this->writeI32($size);
Mark Slee6e536442006-06-30 18:28:50 +000074 }
75
Mark Slee5f8237d2006-10-26 04:57:03 +000076 public function writeSetEnd() {
Mark Slee6e536442006-06-30 18:28:50 +000077 return 0;
78 }
79
Mark Slee5f8237d2006-10-26 04:57:03 +000080 public function writeBool($value) {
Marc Slemkod97eb612006-08-24 23:37:36 +000081 $data = pack('c', $value ? 1 : 0);
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000082 $this->trans_->write($data, 1);
Mark Slee6e536442006-06-30 18:28:50 +000083 return 1;
84 }
85
Mark Slee5f8237d2006-10-26 04:57:03 +000086 public function writeByte($value) {
Marc Slemkod97eb612006-08-24 23:37:36 +000087 $data = pack('c', $value);
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000088 $this->trans_->write($data, 1);
Marc Slemkod97eb612006-08-24 23:37:36 +000089 return 1;
90 }
91
Mark Slee5f8237d2006-10-26 04:57:03 +000092 public function writeI16($value) {
Marc Slemkod97eb612006-08-24 23:37:36 +000093 $data = pack('n', $value);
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000094 $this->trans_->write($data, 2);
Marc Slemkod97eb612006-08-24 23:37:36 +000095 return 2;
96 }
97
Mark Slee5f8237d2006-10-26 04:57:03 +000098 public function writeI32($value) {
Marc Slemkod97eb612006-08-24 23:37:36 +000099 $data = pack('N', $value);
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000100 $this->trans_->write($data, 4);
Mark Slee6e536442006-06-30 18:28:50 +0000101 return 4;
102 }
103
Mark Slee5f8237d2006-10-26 04:57:03 +0000104 public function writeI64($value) {
Mark Sleecfc01932006-09-01 22:18:16 +0000105 // If we are on a 32bit architecture we have to explicitly deal with
106 // 64-bit twos-complement arithmetic since PHP wants to treat all ints
107 // as signed and any int over 2^31 - 1 as a float
108 if (PHP_INT_SIZE == 4) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000109 $neg = $value < 0;
Mark Sleecfc01932006-09-01 22:18:16 +0000110
111 if ($neg) {
112 $value *= -1;
Marc Slemkod97eb612006-08-24 23:37:36 +0000113 }
Mark Sleecfc01932006-09-01 22:18:16 +0000114
Marc Slemkod97eb612006-08-24 23:37:36 +0000115 $hi = (int)($value / 4294967296);
116 $lo = (int)$value;
117
Mark Sleecfc01932006-09-01 22:18:16 +0000118 if ($neg) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000119 $hi = ~$hi;
120 $lo = ~$lo;
Mark Sleecfc01932006-09-01 22:18:16 +0000121 if (($lo & (int)0xffffffff) == (int)0xffffffff) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000122 $lo = 0;
123 $hi++;
124 } else {
125 $lo++;
126 }
127 }
Mark Slee6e536442006-06-30 18:28:50 +0000128 $data = pack('N2', $hi, $lo);
Marc Slemkod97eb612006-08-24 23:37:36 +0000129
Mark Slee6e536442006-06-30 18:28:50 +0000130 } else {
Marc Slemkod97eb612006-08-24 23:37:36 +0000131 $hi = $value >> 32;
132 $lo = $value & 0xFFFFFFFF;
133 $data = pack('N2', $hi, $lo);
Mark Slee6e536442006-06-30 18:28:50 +0000134 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000135
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000136 $this->trans_->write($data, 8);
Mark Slee6e536442006-06-30 18:28:50 +0000137 return 8;
138 }
139
Mark Slee5f8237d2006-10-26 04:57:03 +0000140 public function writeDouble($value) {
Mark Sleec98d0502006-09-06 02:42:25 +0000141 $data = pack('d', $value);
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000142 $this->trans_->write(strrev($data), 8);
Mark Sleec98d0502006-09-06 02:42:25 +0000143 return 8;
144 }
145
Mark Slee5f8237d2006-10-26 04:57:03 +0000146 public function writeString($value) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000147 $len = strlen($value);
Mark Slee5f8237d2006-10-26 04:57:03 +0000148 $result = $this->writeI32($len);
Mark Sleeade2c832006-09-08 03:41:50 +0000149 if ($len) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000150 $this->trans_->write($value, $len);
Mark Sleeade2c832006-09-08 03:41:50 +0000151 }
Mark Slee6e536442006-06-30 18:28:50 +0000152 return $result + $len;
153 }
154
Mark Slee5f8237d2006-10-26 04:57:03 +0000155 public function readMessageBegin(&$name, &$type, &$seqid) {
Mark Sleecfc01932006-09-01 22:18:16 +0000156 return
Mark Slee5f8237d2006-10-26 04:57:03 +0000157 $this->readString($name) +
158 $this->readByte($type) +
159 $this->readI32($seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +0000160 }
161
Mark Slee5f8237d2006-10-26 04:57:03 +0000162 public function readMessageEnd() {
Marc Slemkod97eb612006-08-24 23:37:36 +0000163 return 0;
164 }
165
Mark Slee5f8237d2006-10-26 04:57:03 +0000166 public function readStructBegin(&$name) {
Mark Slee6e536442006-06-30 18:28:50 +0000167 $name = '';
168 return 0;
169 }
170
Mark Slee5f8237d2006-10-26 04:57:03 +0000171 public function readStructEnd() {
Mark Slee6e536442006-06-30 18:28:50 +0000172 return 0;
173 }
174
Mark Slee5f8237d2006-10-26 04:57:03 +0000175 public function readFieldBegin(&$name, &$fieldType, &$fieldId) {
176 $result = $this->readByte($fieldType);
Mark Slee6e536442006-06-30 18:28:50 +0000177 if ($fieldType == TType::STOP) {
178 $fieldId = 0;
179 return $result;
180 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000181 $result += $this->readI16($fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000182 return $result;
183 }
184
Mark Slee5f8237d2006-10-26 04:57:03 +0000185 public function readFieldEnd() {
Mark Slee6e536442006-06-30 18:28:50 +0000186 return 0;
187 }
188
Mark Slee5f8237d2006-10-26 04:57:03 +0000189 public function readMapBegin(&$keyType, &$valType, &$size) {
Mark Sleecfc01932006-09-01 22:18:16 +0000190 return
Mark Slee5f8237d2006-10-26 04:57:03 +0000191 $this->readByte($keyType) +
192 $this->readByte($valType) +
193 $this->readI32($size);
Mark Slee6e536442006-06-30 18:28:50 +0000194 }
195
Mark Slee5f8237d2006-10-26 04:57:03 +0000196 public function readMapEnd() {
Mark Slee6e536442006-06-30 18:28:50 +0000197 return 0;
198 }
199
Mark Slee5f8237d2006-10-26 04:57:03 +0000200 public function readListBegin(&$elemType, &$size) {
Mark Sleecfc01932006-09-01 22:18:16 +0000201 return
Mark Slee5f8237d2006-10-26 04:57:03 +0000202 $this->readByte($elemType) +
203 $this->readI32($size);
Mark Slee6e536442006-06-30 18:28:50 +0000204 }
205
Mark Slee5f8237d2006-10-26 04:57:03 +0000206 public function readListEnd() {
Mark Slee6e536442006-06-30 18:28:50 +0000207 return 0;
208 }
209
Mark Slee5f8237d2006-10-26 04:57:03 +0000210 public function readSetBegin(&$elemType, &$size) {
Mark Sleecfc01932006-09-01 22:18:16 +0000211 return
Mark Slee5f8237d2006-10-26 04:57:03 +0000212 $this->readByte($elemType) +
213 $this->readI32($size);
Mark Slee6e536442006-06-30 18:28:50 +0000214 }
215
Mark Slee5f8237d2006-10-26 04:57:03 +0000216 public function readSetEnd() {
Mark Slee6e536442006-06-30 18:28:50 +0000217 return 0;
218 }
219
Mark Slee5f8237d2006-10-26 04:57:03 +0000220 public function readBool(&$value) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000221 $data = $this->trans_->readAll(1);
Mark Slee6e536442006-06-30 18:28:50 +0000222 $arr = unpack('c', $data);
Marc Slemkod97eb612006-08-24 23:37:36 +0000223 $value = $arr[1] == 1;
Mark Slee6e536442006-06-30 18:28:50 +0000224 return 1;
225 }
226
Mark Slee5f8237d2006-10-26 04:57:03 +0000227 public function readByte(&$value) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000228 $data = $this->trans_->readAll(1);
Marc Slemkod97eb612006-08-24 23:37:36 +0000229 $arr = unpack('c', $data);
230 $value = $arr[1];
231 return 1;
232 }
233
Mark Slee5f8237d2006-10-26 04:57:03 +0000234 public function readI16(&$value) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000235 $data = $this->trans_->readAll(2);
Marc Slemkod97eb612006-08-24 23:37:36 +0000236 $arr = unpack('n', $data);
237 $value = $arr[1];
Mark Sleecfc01932006-09-01 22:18:16 +0000238 if ($value > 0x7fff) {
239 $value = 0 - (($value - 1) ^ 0xffff);
Mark Slee6e536442006-06-30 18:28:50 +0000240 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000241 return 2;
242 }
243
Mark Slee5f8237d2006-10-26 04:57:03 +0000244 public function readI32(&$value) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000245 $data = $this->trans_->readAll(4);
Marc Slemkod97eb612006-08-24 23:37:36 +0000246 $arr = unpack('N', $data);
247 $value = $arr[1];
Mark Sleecfc01932006-09-01 22:18:16 +0000248 if ($value > 0x7fffffff) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000249 $value = 0 - (($value - 1) ^ 0xffffffff);
250 }
Mark Slee6e536442006-06-30 18:28:50 +0000251 return 4;
252 }
253
Mark Slee5f8237d2006-10-26 04:57:03 +0000254 public function readI64(&$value) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000255 $data = $this->trans_->readAll(8);
Marc Slemkod97eb612006-08-24 23:37:36 +0000256
257 $arr = unpack('N2', $data);
258
Mark Sleecfc01932006-09-01 22:18:16 +0000259 // If we are on a 32bit architecture we have to explicitly deal with
260 // 64-bit twos-complement arithmetic since PHP wants to treat all ints
261 // as signed and any int over 2^31 - 1 as a float
262 if (PHP_INT_SIZE == 4) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000263
264 $hi = $arr[1];
265 $lo = $arr[2];
266 $isNeg = $hi < 0;
267
268 // Check for a negative
Mark Sleecfc01932006-09-01 22:18:16 +0000269 if ($isNeg) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000270 $hi = ~$hi & (int)0xffffffff;
271 $lo = ~$lo & (int)0xffffffff;
272
Mark Sleecfc01932006-09-01 22:18:16 +0000273 if ($lo == (int)0xffffffff) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000274 $hi++;
275 $lo = 0;
276 } else {
277 $lo++;
278 }
279 }
280
Mark Sleecfc01932006-09-01 22:18:16 +0000281 // Force 32bit words in excess of 2G to pe positive - we deal wigh sign
282 // explicitly below
Marc Slemkod97eb612006-08-24 23:37:36 +0000283
Mark Sleecfc01932006-09-01 22:18:16 +0000284 if ($hi & (int)0x80000000) {
285 $hi &= (int)0x7fffffff;
Marc Slemkod97eb612006-08-24 23:37:36 +0000286 $hi += 0x80000000;
287 }
288
Mark Sleecfc01932006-09-01 22:18:16 +0000289 if ($lo & (int)0x80000000) {
290 $lo &= (int)0x7fffffff;
Marc Slemkod97eb612006-08-24 23:37:36 +0000291 $lo += 0x80000000;
292 }
293
294 $value = $hi * 4294967296 + $lo;
295
Mark Sleecfc01932006-09-01 22:18:16 +0000296 if ($isNeg) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000297 $value = 0 - $value;
298 }
299 } else {
300
301 // Check for a negative
302 if ($arr[1] & 0x80000000) {
303 $arr[1] = $arr[1] ^ 0xFFFFFFFF;
304 $arr[2] = $arr[2] ^ 0xFFFFFFFF;
305 $value = 0 - $arr[1]*4294967296 - $arr[2] - 1;
306 } else {
307 $value = $arr[1]*4294967296 + $arr[2];
308 }
309 }
310
311 return 8;
312 }
313
Mark Slee5f8237d2006-10-26 04:57:03 +0000314 public function readDouble(&$value) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000315 $data = strrev($this->trans_->readAll(8));
Mark Sleec98d0502006-09-06 02:42:25 +0000316 $arr = unpack('d', $data);
317 $value = $arr[1];
318 return 8;
319 }
320
Mark Slee5f8237d2006-10-26 04:57:03 +0000321 public function readString(&$value) {
322 $result = $this->readI32($len);
Mark Sleeade2c832006-09-08 03:41:50 +0000323 if ($len) {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000324 $value = $this->trans_->readAll($len);
Mark Sleeade2c832006-09-08 03:41:50 +0000325 } else {
326 $value = '';
327 }
Mark Slee6e536442006-06-30 18:28:50 +0000328 return $result + $len;
329 }
330}
331
Mark Slee5f8237d2006-10-26 04:57:03 +0000332/**
333 * Binary Protocol Factory
334 */
335class TBinaryProtocolFactory implements TProtocolFactory {
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000336 public function getProtocol($trans) {
337 return new TBinaryProtocol($trans);
Mark Slee5f8237d2006-10-26 04:57:03 +0000338 }
339}
340
Marc Slemkod97eb612006-08-24 23:37:36 +0000341?>