blob: 4123f5f8134488083fb2aafa73dd112787ab6f28 [file] [log] [blame]
Mark Slee6e536442006-06-30 18:28:50 +00001<?php
2
3/** For transport operations */
Mark Sleecfc01932006-09-01 22:18:16 +00004require_once $GLOBALS['THRIFT_ROOT'].'/transport/TTransport.php';
Mark Slee6e536442006-06-30 18:28:50 +00005
6/**
7 * Binary implementation of the Thrift protocol.
8 *
9 * @package thrift.protocol
10 * @author Mark Slee <mcslee@facebook.com>
11 */
12class TBinaryProtocol extends TProtocol {
13
Marc Slemkod97eb612006-08-24 23:37:36 +000014 public function writeMessageBegin($out, $name, $type, $seqid) {
Mark Sleecfc01932006-09-01 22:18:16 +000015 return
16 $this->writeString($out, $name) +
17 $this->writeByte($out, $type) +
18 $this->writeI32($out, $seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +000019 }
20
21 public function writeMessageEnd($out) {
22 return 0;
23 }
24
Mark Slee6e536442006-06-30 18:28:50 +000025 public function writeStructBegin($out, $name) {
26 return 0;
27 }
28
29 public function writeStructEnd($out) {
30 return 0;
31 }
32
33 public function writeFieldBegin($out, $fieldName, $fieldType, $fieldId) {
34 return
35 $this->writeByte($out, $fieldType) +
Marc Slemkod97eb612006-08-24 23:37:36 +000036 $this->writeI16($out, $fieldId);
Mark Slee6e536442006-06-30 18:28:50 +000037 }
38
39 public function writeFieldEnd($out) {
40 return 0;
41 }
42
43 public function writeFieldStop($out) {
44 return
45 $this->writeByte($out, TType::STOP);
46 }
47
48 public function writeMapBegin($out, $keyType, $valType, $size) {
49 return
50 $this->writeByte($out, $keyType) +
51 $this->writeByte($out, $valType) +
52 $this->writeI32($out, $size);
53 }
54
55 public function writeMapEnd($out) {
56 return 0;
57 }
58
59 public function writeListBegin($out, $elemType, $size) {
60 return
61 $this->writeByte($out, $elemType) +
62 $this->writeI32($out, $size);
63 }
64
65 public function writeListEnd($out) {
66 return 0;
67 }
68
69 public function writeSetBegin($out, $elemType, $size) {
70 return
71 $this->writeByte($out, $elemType) +
72 $this->writeI32($out, $size);
73 }
74
75 public function writeSetEnd($out) {
76 return 0;
77 }
78
Marc Slemkod97eb612006-08-24 23:37:36 +000079 public function writeBool($out, $value) {
80 $data = pack('c', $value ? 1 : 0);
Mark Slee6e536442006-06-30 18:28:50 +000081 $out->write($data, 1);
82 return 1;
83 }
84
Marc Slemkod97eb612006-08-24 23:37:36 +000085 public function writeByte($out, $value) {
86 $data = pack('c', $value);
87 $out->write($data, 1);
88 return 1;
89 }
90
Marc Slemkod97eb612006-08-24 23:37:36 +000091 public function writeI16($out, $value) {
92 $data = pack('n', $value);
93 $out->write($data, 2);
94 return 2;
95 }
96
97 public function writeI32($out, $value) {
98 $data = pack('N', $value);
Mark Slee6e536442006-06-30 18:28:50 +000099 $out->write($data, 4);
100 return 4;
101 }
102
Marc Slemkod97eb612006-08-24 23:37:36 +0000103 public function writeI64($out, $value) {
Mark Sleecfc01932006-09-01 22:18:16 +0000104 // If we are on a 32bit architecture we have to explicitly deal with
105 // 64-bit twos-complement arithmetic since PHP wants to treat all ints
106 // as signed and any int over 2^31 - 1 as a float
107 if (PHP_INT_SIZE == 4) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000108 $neg = $value < 0;
Mark Sleecfc01932006-09-01 22:18:16 +0000109
110 if ($neg) {
111 $value *= -1;
Marc Slemkod97eb612006-08-24 23:37:36 +0000112 }
Mark Sleecfc01932006-09-01 22:18:16 +0000113
Marc Slemkod97eb612006-08-24 23:37:36 +0000114 $hi = (int)($value / 4294967296);
115 $lo = (int)$value;
116
Mark Sleecfc01932006-09-01 22:18:16 +0000117 if ($neg) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000118 $hi = ~$hi;
119 $lo = ~$lo;
Mark Sleecfc01932006-09-01 22:18:16 +0000120 if (($lo & (int)0xffffffff) == (int)0xffffffff) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000121 $lo = 0;
122 $hi++;
123 } else {
124 $lo++;
125 }
126 }
Mark Slee6e536442006-06-30 18:28:50 +0000127 $data = pack('N2', $hi, $lo);
Marc Slemkod97eb612006-08-24 23:37:36 +0000128
Mark Slee6e536442006-06-30 18:28:50 +0000129 } else {
Marc Slemkod97eb612006-08-24 23:37:36 +0000130 $hi = $value >> 32;
131 $lo = $value & 0xFFFFFFFF;
132 $data = pack('N2', $hi, $lo);
Mark Slee6e536442006-06-30 18:28:50 +0000133 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000134
Mark Slee6e536442006-06-30 18:28:50 +0000135 $out->write($data, 8);
136 return 8;
137 }
138
Mark Sleec98d0502006-09-06 02:42:25 +0000139 public function writeDouble($out, $value) {
140 $data = pack('d', $value);
141 $out->write(strrev($data), 8);
142 return 8;
143 }
144
Marc Slemkod97eb612006-08-24 23:37:36 +0000145 public function writeString($out, $value) {
146 $len = strlen($value);
Mark Sleecfc01932006-09-01 22:18:16 +0000147 $result = $this->writeI32($out, $len);
Mark Sleeade2c832006-09-08 03:41:50 +0000148 if ($len) {
149 $out->write($value, $len);
150 }
Mark Slee6e536442006-06-30 18:28:50 +0000151 return $result + $len;
152 }
153
Marc Slemkod97eb612006-08-24 23:37:36 +0000154 public function readMessageBegin($in, &$name, &$type, &$seqid) {
Mark Sleecfc01932006-09-01 22:18:16 +0000155 return
156 $this->readString($in, $name) +
157 $this->readByte($in, $type) +
158 $this->readI32($in, $seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +0000159 }
160
161 public function readMessageEnd($out) {
162 return 0;
163 }
164
Mark Slee6e536442006-06-30 18:28:50 +0000165 public function readStructBegin($in, &$name) {
166 $name = '';
167 return 0;
168 }
169
170 public function readStructEnd($in) {
171 return 0;
172 }
173
174 public function readFieldBegin($in, &$name, &$fieldType, &$fieldId) {
175 $result = $this->readByte($in, $fieldType);
176 if ($fieldType == TType::STOP) {
177 $fieldId = 0;
178 return $result;
179 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000180 $result += $this->readI16($in, $fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000181 return $result;
182 }
183
184 public function readFieldEnd($in) {
185 return 0;
186 }
187
188 public function readMapBegin($in, &$keyType, &$valType, &$size) {
Mark Sleecfc01932006-09-01 22:18:16 +0000189 return
190 $this->readByte($in, $keyType) +
191 $this->readByte($in, $valType) +
192 $this->readI32($in, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000193 }
194
195 public function readMapEnd($in) {
196 return 0;
197 }
198
199 public function readListBegin($in, &$elemType, &$size) {
Mark Sleecfc01932006-09-01 22:18:16 +0000200 return
201 $this->readByte($in, $elemType) +
202 $this->readI32($in, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000203 }
204
205 public function readListEnd($in) {
206 return 0;
207 }
208
209 public function readSetBegin($in, &$elemType, &$size) {
Mark Sleecfc01932006-09-01 22:18:16 +0000210 return
211 $this->readByte($in, $elemType) +
212 $this->readI32($in, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000213 }
214
215 public function readSetEnd($in) {
216 return 0;
217 }
218
Marc Slemkod97eb612006-08-24 23:37:36 +0000219 public function readBool($in, &$value) {
Mark Slee6e536442006-06-30 18:28:50 +0000220 $data = $in->readAll(1);
221 $arr = unpack('c', $data);
Marc Slemkod97eb612006-08-24 23:37:36 +0000222 $value = $arr[1] == 1;
Mark Slee6e536442006-06-30 18:28:50 +0000223 return 1;
224 }
225
Marc Slemkod97eb612006-08-24 23:37:36 +0000226 public function readByte($in, &$value) {
227 $data = $in->readAll(1);
228 $arr = unpack('c', $data);
229 $value = $arr[1];
230 return 1;
231 }
232
Marc Slemkod97eb612006-08-24 23:37:36 +0000233 public function readI16($in, &$value) {
234 $data = $in->readAll(2);
235 $arr = unpack('n', $data);
236 $value = $arr[1];
Mark Sleecfc01932006-09-01 22:18:16 +0000237 if ($value > 0x7fff) {
238 $value = 0 - (($value - 1) ^ 0xffff);
Mark Slee6e536442006-06-30 18:28:50 +0000239 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000240 return 2;
241 }
242
243 public function readI32($in, &$value) {
244 $data = $in->readAll(4);
245 $arr = unpack('N', $data);
246 $value = $arr[1];
Mark Sleecfc01932006-09-01 22:18:16 +0000247 if ($value > 0x7fffffff) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000248 $value = 0 - (($value - 1) ^ 0xffffffff);
249 }
Mark Slee6e536442006-06-30 18:28:50 +0000250 return 4;
251 }
252
Marc Slemkod97eb612006-08-24 23:37:36 +0000253 public function readI64($in, &$value) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000254 $data = $in->readAll(8);
255
256 $arr = unpack('N2', $data);
257
Mark Sleecfc01932006-09-01 22:18:16 +0000258 // If we are on a 32bit architecture we have to explicitly deal with
259 // 64-bit twos-complement arithmetic since PHP wants to treat all ints
260 // as signed and any int over 2^31 - 1 as a float
261 if (PHP_INT_SIZE == 4) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000262
263 $hi = $arr[1];
264 $lo = $arr[2];
265 $isNeg = $hi < 0;
266
267 // Check for a negative
Mark Sleecfc01932006-09-01 22:18:16 +0000268 if ($isNeg) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000269 $hi = ~$hi & (int)0xffffffff;
270 $lo = ~$lo & (int)0xffffffff;
271
Mark Sleecfc01932006-09-01 22:18:16 +0000272 if ($lo == (int)0xffffffff) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000273 $hi++;
274 $lo = 0;
275 } else {
276 $lo++;
277 }
278 }
279
Mark Sleecfc01932006-09-01 22:18:16 +0000280 // Force 32bit words in excess of 2G to pe positive - we deal wigh sign
281 // explicitly below
Marc Slemkod97eb612006-08-24 23:37:36 +0000282
Mark Sleecfc01932006-09-01 22:18:16 +0000283 if ($hi & (int)0x80000000) {
284 $hi &= (int)0x7fffffff;
Marc Slemkod97eb612006-08-24 23:37:36 +0000285 $hi += 0x80000000;
286 }
287
Mark Sleecfc01932006-09-01 22:18:16 +0000288 if ($lo & (int)0x80000000) {
289 $lo &= (int)0x7fffffff;
Marc Slemkod97eb612006-08-24 23:37:36 +0000290 $lo += 0x80000000;
291 }
292
293 $value = $hi * 4294967296 + $lo;
294
Mark Sleecfc01932006-09-01 22:18:16 +0000295 if ($isNeg) {
Marc Slemkod97eb612006-08-24 23:37:36 +0000296 $value = 0 - $value;
297 }
298 } else {
299
300 // Check for a negative
301 if ($arr[1] & 0x80000000) {
302 $arr[1] = $arr[1] ^ 0xFFFFFFFF;
303 $arr[2] = $arr[2] ^ 0xFFFFFFFF;
304 $value = 0 - $arr[1]*4294967296 - $arr[2] - 1;
305 } else {
306 $value = $arr[1]*4294967296 + $arr[2];
307 }
308 }
309
310 return 8;
311 }
312
Mark Sleec98d0502006-09-06 02:42:25 +0000313 public function readDouble($in, &$value) {
314 $data = strrev($in->readAll(8));
315 $arr = unpack('d', $data);
316 $value = $arr[1];
317 return 8;
318 }
319
Marc Slemkod97eb612006-08-24 23:37:36 +0000320 public function readString($in, &$value) {
Mark Sleecfc01932006-09-01 22:18:16 +0000321 $result = $this->readI32($in, $len);
Mark Sleeade2c832006-09-08 03:41:50 +0000322 if ($len) {
323 $value = $in->readAll($len);
324 } else {
325 $value = '';
326 }
Mark Slee6e536442006-06-30 18:28:50 +0000327 return $result + $len;
328 }
329}
330
Marc Slemkod97eb612006-08-24 23:37:36 +0000331?>