blob: 0d2349e7324f57725d34c3df3c1339bfa80e037f [file] [log] [blame]
Mark Slee6e536442006-06-30 18:28:50 +00001<?php
2
3/** For transport operations */
Marc Slemkod97eb612006-08-24 23:37:36 +00004require_once PREFIX.'thrift/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) {
15 return
16 $this->writeString($out, $name) +
17 $this->writeByte($out, $type) +
18 $this->writeU32($out, $seqid);
19 }
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
91 public function writeI08($out, $value) {
92 $data = pack('c', $value);
93 $out->write($data, 1);
94 return 1;
95 }
96
97 public function writeI16($out, $value) {
98 $data = pack('n', $value);
99 $out->write($data, 2);
100 return 2;
101 }
102
103 public function writeI32($out, $value) {
104 $data = pack('N', $value);
Mark Slee6e536442006-06-30 18:28:50 +0000105 $out->write($data, 4);
106 return 4;
107 }
108
Marc Slemkod97eb612006-08-24 23:37:36 +0000109 public function writeI64($out, $value) {
110
111 /* If we are on a 32bit architecture we have to explicitly deal with 64-bit twos-complement arithmetic
112 since PHP wants to treat all ints as signed and any int over 2^31 - 1 as a float */
113
114 if(PHP_INT_SIZE == 4) {
115
116 $neg = $value < 0;
117
118 if($neg) {
119 $value*= -1;
120 }
121
122 $hi = (int)($value / 4294967296);
123 $lo = (int)$value;
124
125 if($neg) {
126 $hi = ~$hi;
127 $lo = ~$lo;
128 if(($lo & (int)0xffffffff) == (int)0xffffffff) {
129 $lo = 0;
130 $hi++;
131 } else {
132 $lo++;
133 }
134 }
Mark Slee6e536442006-06-30 18:28:50 +0000135 $data = pack('N2', $hi, $lo);
Marc Slemkod97eb612006-08-24 23:37:36 +0000136
Mark Slee6e536442006-06-30 18:28:50 +0000137 } else {
Marc Slemkod97eb612006-08-24 23:37:36 +0000138 $hi = $value >> 32;
139 $lo = $value & 0xFFFFFFFF;
140 $data = pack('N2', $hi, $lo);
Mark Slee6e536442006-06-30 18:28:50 +0000141 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000142
Mark Slee6e536442006-06-30 18:28:50 +0000143 $out->write($data, 8);
144 return 8;
145 }
146
Marc Slemkod97eb612006-08-24 23:37:36 +0000147 public function writeU08($out, $value) {
148 $data = pack('c', $value);
149 $out->write($data, 1);
150 return 1;
151 }
152
153 public function writeU16($out, $value) {
154 $data = pack('n', $value);
155 $out->write($data, 2);
156 return 2;
157 }
158
159 public function writeU32($out, $value) {
160 $data = pack('N', $value);
161 $out->write($data, 4);
162 return 4;
163 }
164
165 public function writeU64($out, $value) {
166
167 /* If we are on a 32bit architecture we have to explicitly deal with 64-bit twos-complement arithmetic
168 since PHP wants to treat all ints as signed and any int over 2^31 - 1 as a float */
169
170 if(PHP_INT_SIZE == 4) {
171
172 $hi = (int)($value / 4294967296);
173 $lo = (int)$value;
174 $data = pack('N2', $hi, $lo);
175
176 } else {
177 $hi = $value >> 32;
178 $lo = $value & 0xFFFFFFFF;
179 $data = pack('N2', $hi, $lo);
180 }
181
182 $out->write($data, 8);
183 return 8;
184 }
185
186 public function writeString($out, $value) {
187 $len = strlen($value);
188 $result = $this->writeU32($out, $len);
189 $out->write($value, $len);
Mark Slee6e536442006-06-30 18:28:50 +0000190 return $result + $len;
191 }
192
Marc Slemkod97eb612006-08-24 23:37:36 +0000193 public function readMessageBegin($in, &$name, &$type, &$seqid) {
194 $result = $this->readString($in, $name);
195 $result+= $this->readByte($in, $type);
196 $result+= $this->readU32($in, $seqid);
197 }
198
199 public function readMessageEnd($out) {
200 return 0;
201 }
202
Mark Slee6e536442006-06-30 18:28:50 +0000203 public function readStructBegin($in, &$name) {
204 $name = '';
205 return 0;
206 }
207
208 public function readStructEnd($in) {
209 return 0;
210 }
211
212 public function readFieldBegin($in, &$name, &$fieldType, &$fieldId) {
213 $result = $this->readByte($in, $fieldType);
214 if ($fieldType == TType::STOP) {
215 $fieldId = 0;
216 return $result;
217 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000218 $result += $this->readI16($in, $fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000219 return $result;
220 }
221
222 public function readFieldEnd($in) {
223 return 0;
224 }
225
226 public function readMapBegin($in, &$keyType, &$valType, &$size) {
227 $result = $this->readByte($in, $keyType);
228 $result += $this->readByte($in, $valType);
229 $result += $this->readI32($in, $size);
230 return $result;
231 }
232
233 public function readMapEnd($in) {
234 return 0;
235 }
236
237 public function readListBegin($in, &$elemType, &$size) {
238 $result = $this->readByte($in, $elemType);
239 $result += $this->readI32($in, $size);
240 return $result;
241 }
242
243 public function readListEnd($in) {
244 return 0;
245 }
246
247 public function readSetBegin($in, &$elemType, &$size) {
248 $result = $this->readByte($in, $elemType);
249 $result += $this->readI32($in, $size);
250 return $result;
251 }
252
253 public function readSetEnd($in) {
254 return 0;
255 }
256
Marc Slemkod97eb612006-08-24 23:37:36 +0000257 public function readBool($in, &$value) {
Mark Slee6e536442006-06-30 18:28:50 +0000258 $data = $in->readAll(1);
259 $arr = unpack('c', $data);
Marc Slemkod97eb612006-08-24 23:37:36 +0000260 $value = $arr[1] == 1;
Mark Slee6e536442006-06-30 18:28:50 +0000261 return 1;
262 }
263
Marc Slemkod97eb612006-08-24 23:37:36 +0000264 public function readByte($in, &$value) {
265 $data = $in->readAll(1);
266 $arr = unpack('c', $data);
267 $value = $arr[1];
268 return 1;
269 }
270
271 public function readI08($in, &$value) {
272 $data = $in->readAll(1);
273 $arr = unpack('c', $data);
274 $value = $arr[1];
275 return 1;
276 }
277
278 public function readI16($in, &$value) {
279 $data = $in->readAll(2);
280 $arr = unpack('n', $data);
281 $value = $arr[1];
282 if($value > 0x7fff) {
283 $value = 0 - (($value - 1) ^ 0xffff);
Mark Slee6e536442006-06-30 18:28:50 +0000284 }
Marc Slemkod97eb612006-08-24 23:37:36 +0000285 return 2;
286 }
287
288 public function readI32($in, &$value) {
289 $data = $in->readAll(4);
290 $arr = unpack('N', $data);
291 $value = $arr[1];
292 if($value > 0x7fffffff) {
293 $value = 0 - (($value - 1) ^ 0xffffffff);
294 }
Mark Slee6e536442006-06-30 18:28:50 +0000295 return 4;
296 }
297
Marc Slemkod97eb612006-08-24 23:37:36 +0000298 public function readI64($in, &$value) {
299
300 $data = $in->readAll(8);
301
302 $arr = unpack('N2', $data);
303
304 /* If we are on a 32bit architecture we have to explicitly deal with 64-bit twos-complement arithmetic
305 since PHP wants to treat all ints as signed and any int over 2^31 - 1 as a float */
306
307 if(PHP_INT_SIZE == 4) {
308
309 $hi = $arr[1];
310 $lo = $arr[2];
311 $isNeg = $hi < 0;
312
313 // Check for a negative
314 if($isNeg) {
315 $hi = ~$hi & (int)0xffffffff;
316 $lo = ~$lo & (int)0xffffffff;
317
318 if($lo == (int)0xffffffff) {
319 $hi++;
320 $lo = 0;
321 } else {
322 $lo++;
323 }
324 }
325
326 /* Force 32bit words in excess of 2G to pe positive - we deal wigh sign
327 explicitly below */
328
329 if($hi & (int)0x80000000) {
330 $hi&= (int)0x7fffffff;
331 $hi += 0x80000000;
332 }
333
334 if($lo & (int)0x80000000) {
335 $lo&= (int)0x7fffffff;
336 $lo += 0x80000000;
337 }
338
339 $value = $hi * 4294967296 + $lo;
340
341 if($isNeg) {
342 $value = 0 - $value;
343 }
344 } else {
345
346 // Check for a negative
347 if ($arr[1] & 0x80000000) {
348 $arr[1] = $arr[1] ^ 0xFFFFFFFF;
349 $arr[2] = $arr[2] ^ 0xFFFFFFFF;
350 $value = 0 - $arr[1]*4294967296 - $arr[2] - 1;
351 } else {
352 $value = $arr[1]*4294967296 + $arr[2];
353 }
354 }
355
356 return 8;
357 }
358
359 public function readU08($in, &$value) {
360 $data = $in->readAll(1);
361 $arr = unpack('c', $data);
362 $value = $arr[1];
363 return 1;
364 }
365
366 public function readU16($in, &$value) {
367 $data = $in->readAll(2);
368 $arr = unpack('n', $data);
369 $value = $arr[1];
370 return 2;
371 }
372
373 public function readU32($in, &$value) {
374 $data = $in->readAll(4);
375 $arr = unpack('N', $data);
376 $value = $arr[1];
377 return 4;
378 }
379
380 public function readU64($in, &$value) {
Mark Slee6e536442006-06-30 18:28:50 +0000381 $data = $in->readAll(8);
382 $arr = unpack('N2', $data);
383
Marc Slemkod97eb612006-08-24 23:37:36 +0000384 /* If we are on a 32bit architecture we have to explicitly deal with 64-bit twos-complement arithmetic
385 since PHP wants to treat all ints as signed and any int over 2^31 - 1 as a float */
386
387 if(PHP_INT_SIZE == 4) {
388
389 $hi = $arr[1];
390 $lo = $arr[2];
391
392 /* Prevent implicit integer sign extension */
393
394 if($hi & (int)0x80000000) {
395 $hi&= (int)0x7fffffff;
396 $hi += 0x80000000;
397 }
398
399 if($lo & (int)0x80000000) {
400 $lo&= (int)0x7fffffff;
401 $lo += 0x80000000;
402 }
403
404 $value = $hi * 4294967296 + $lo;
405
Mark Slee6e536442006-06-30 18:28:50 +0000406 } else {
Marc Slemkod97eb612006-08-24 23:37:36 +0000407
408 $value = $arr[1]*4294967296 + $arr[2];
Mark Slee6e536442006-06-30 18:28:50 +0000409 }
410 return 8;
411 }
412
Marc Slemkod97eb612006-08-24 23:37:36 +0000413 public function readString($in, &$value) {
414 $result = $this->readU32($in, $len);
415 $value = $in->readAll($len);
Mark Slee6e536442006-06-30 18:28:50 +0000416 return $result + $len;
417 }
418}
419
Marc Slemkod97eb612006-08-24 23:37:36 +0000420?>