1: <?php
  2: include_once $GLOBALS['THRIFT_ROOT'].'/transport/TBufferedTransport.php';
  3: 
  4:   5:   6:   7:   8:   9:  10:  11:  12:  13: 
 14: 
 15:  16:  17:  18:  19:  20: 
 21: class TBinaryProtocol extends TProtocol {
 22: 
 23:   const VERSION_MASK = 0xffff0000;
 24:   const VERSION_1 = 0x80010000;
 25: 
 26:   protected $strictRead_ = false;
 27:   protected $strictWrite_ = true;
 28: 
 29:   public function __construct($trans, $strictRead=false, $strictWrite=true) {
 30:     parent::__construct($trans);
 31:     $this->strictRead_ = $strictRead;
 32:     $this->strictWrite_ = $strictWrite;
 33:   }
 34: 
 35:   public function writeMessageBegin($name, $type, $seqid) {
 36:     if ($this->strictWrite_) {
 37:       $version = self::VERSION_1 | $type;
 38:       return
 39:         $this->writeI32($version) +
 40:         $this->writeString($name) +
 41:         $this->writeI32($seqid);
 42:     } else {
 43:       return
 44:         $this->writeString($name) +
 45:         $this->writeByte($type) +
 46:         $this->writeI32($seqid);
 47:     }
 48:   }
 49: 
 50:   public function writeMessageEnd() {
 51:     return 0;
 52:   }
 53: 
 54:   public function writeStructBegin($name) {
 55:     return 0;
 56:   }
 57: 
 58:   public function writeStructEnd() {
 59:     return 0;
 60:   }
 61: 
 62:   public function writeFieldBegin($fieldName, $fieldType, $fieldId) {
 63:     return
 64:       $this->writeByte($fieldType) +
 65:       $this->writeI16($fieldId);
 66:   }
 67: 
 68:   public function writeFieldEnd() {
 69:     return 0;
 70:   }
 71: 
 72:   public function writeFieldStop() {
 73:     return
 74:       $this->writeByte(TType::STOP);
 75:   }
 76: 
 77:   public function writeMapBegin($keyType, $valType, $size) {
 78:     return
 79:       $this->writeByte($keyType) +
 80:       $this->writeByte($valType) +
 81:       $this->writeI32($size);
 82:   }
 83: 
 84:   public function writeMapEnd() {
 85:     return 0;
 86:   }
 87: 
 88:   public function writeListBegin($elemType, $size) {
 89:     return
 90:       $this->writeByte($elemType) +
 91:       $this->writeI32($size);
 92:   }
 93: 
 94:   public function writeListEnd() {
 95:     return 0;
 96:   }
 97: 
 98:   public function writeSetBegin($elemType, $size) {
 99:     return
100:       $this->writeByte($elemType) +
101:       $this->writeI32($size);
102:   }
103: 
104:   public function writeSetEnd() {
105:     return 0;
106:   }
107: 
108:   public function writeBool($value) {
109:     $data = pack('c', $value ? 1 : 0);
110:     $this->trans_->write($data, 1);
111:     return 1;
112:   }
113: 
114:   public function writeByte($value) {
115:     $data = pack('c', $value);
116:     $this->trans_->write($data, 1);
117:     return 1;
118:   }
119: 
120:   public function writeI16($value) {
121:     $data = pack('n', $value);
122:     $this->trans_->write($data, 2);
123:     return 2;
124:   }
125: 
126:   public function writeI32($value) {
127:     $data = pack('N', $value);
128:     $this->trans_->write($data, 4);
129:     return 4;
130:   }
131: 
132:   public function writeI64($value) {
133:     
134:     
135:     
136:     if (PHP_INT_SIZE == 4) {
137:       $neg = $value < 0;
138: 
139:       if ($neg) {
140:         $value *= -1;
141:       }
142: 
143:       $hi = (int)($value / 4294967296);
144:       $lo = (int)$value;
145: 
146:       if ($neg) {
147:         $hi = ~$hi;
148:         $lo = ~$lo;
149:         if (($lo & (int)0xffffffff) == (int)0xffffffff) {
150:           $lo = 0;
151:           $hi++;
152:         } else {
153:           $lo++;
154:         }
155:       }
156:       $data = pack('N2', $hi, $lo);
157: 
158:     } else {
159:       $hi = $value >> 32;
160:       $lo = $value & 0xFFFFFFFF;
161:       $data = pack('N2', $hi, $lo);
162:     }
163: 
164:     $this->trans_->write($data, 8);
165:     return 8;
166:   }
167: 
168:   public function writeDouble($value) {
169:     $data = pack('d', $value);
170:     $this->trans_->write(strrev($data), 8);
171:     return 8;
172:   }
173: 
174:   public function writeString($value) {
175:     $len = strlen($value);
176:     $result = $this->writeI32($len);
177:     if ($len) {
178:       $this->trans_->write($value, $len);
179:     }
180:     return $result + $len;
181:   }
182: 
183:   public function readMessageBegin(&$name, &$type, &$seqid) {
184:     $result = $this->readI32($sz);
185:     if ($sz < 0) {
186:       $version = (int) ($sz & self::VERSION_MASK);
187:       if ($version != (int) self::VERSION_1) {
188:         throw new TProtocolException('Bad version identifier: '.$sz, TProtocolException::BAD_VERSION);
189:       }
190:       $type = $sz & 0x000000ff;
191:       $result +=
192:         $this->readString($name) +
193:         $this->readI32($seqid);
194:     } else {
195:       if ($this->strictRead_) {
196:         throw new TProtocolException('No version identifier, old protocol client?', TProtocolException::BAD_VERSION);
197:       } else {
198:         
199:         $name = $this->trans_->readAll($sz);
200:         $result +=
201:           $sz +
202:           $this->readByte($type) +
203:           $this->readI32($seqid);
204:       }
205:     }
206:     return $result;
207:   }
208: 
209:   public function readMessageEnd() {
210:     return 0;
211:   }
212: 
213:   public function readStructBegin(&$name) {
214:     $name = '';
215:     return 0;
216:   }
217: 
218:   public function readStructEnd() {
219:     return 0;
220:   }
221: 
222:   public function readFieldBegin(&$name, &$fieldType, &$fieldId) {
223:     $result = $this->readByte($fieldType);
224:     if ($fieldType == TType::STOP) {
225:       $fieldId = 0;
226:       return $result;
227:     }
228:     $result += $this->readI16($fieldId);
229:     return $result;
230:   }
231: 
232:   public function readFieldEnd() {
233:     return 0;
234:   }
235: 
236:   public function readMapBegin(&$keyType, &$valType, &$size) {
237:     return
238:       $this->readByte($keyType) +
239:       $this->readByte($valType) +
240:       $this->readI32($size);
241:   }
242: 
243:   public function readMapEnd() {
244:     return 0;
245:   }
246: 
247:   public function readListBegin(&$elemType, &$size) {
248:     return
249:       $this->readByte($elemType) +
250:       $this->readI32($size);
251:   }
252: 
253:   public function readListEnd() {
254:     return 0;
255:   }
256: 
257:   public function readSetBegin(&$elemType, &$size) {
258:     return
259:       $this->readByte($elemType) +
260:       $this->readI32($size);
261:   }
262: 
263:   public function readSetEnd() {
264:     return 0;
265:   }
266: 
267:   public function readBool(&$value) {
268:     $data = $this->trans_->readAll(1);
269:     $arr = unpack('c', $data);
270:     $value = $arr[1] == 1;
271:     return 1;
272:   }
273: 
274:   public function readByte(&$value) {
275:     $data = $this->trans_->readAll(1);
276:     $arr = unpack('c', $data);
277:     $value = $arr[1];
278:     return 1;
279:   }
280: 
281:   public function readI16(&$value) {
282:     $data = $this->trans_->readAll(2);
283:     $arr = unpack('n', $data);
284:     $value = $arr[1];
285:     if ($value > 0x7fff) {
286:       $value = 0 - (($value - 1) ^ 0xffff);
287:     }
288:     return 2;
289:   }
290: 
291:   public function readI32(&$value) {
292:     $data = $this->trans_->readAll(4);
293:     $arr = unpack('N', $data);
294:     $value = $arr[1];
295:     if ($value > 0x7fffffff) {
296:       $value = 0 - (($value - 1) ^ 0xffffffff);
297:     }
298:     return 4;
299:   }
300: 
301:   public function readI64(&$value) {
302:     $data = $this->trans_->readAll(8);
303: 
304:     $arr = unpack('N2', $data);
305: 
306:     
307:     
308:     
309:     if (PHP_INT_SIZE == 4) {
310: 
311:       $hi = $arr[1];
312:       $lo = $arr[2];
313:       $isNeg = $hi  < 0;
314: 
315:       
316:       if ($isNeg) {
317:         $hi = ~$hi & (int)0xffffffff;
318:         $lo = ~$lo & (int)0xffffffff;
319: 
320:         if ($lo == (int)0xffffffff) {
321:           $hi++;
322:           $lo = 0;
323:         } else {
324:           $lo++;
325:         }
326:       }
327: 
328:       
329:       
330: 
331:       if ($hi & (int)0x80000000) {
332:         $hi &= (int)0x7fffffff;
333:         $hi += 0x80000000;
334:       }
335: 
336:       if ($lo & (int)0x80000000) {
337:         $lo &= (int)0x7fffffff;
338:         $lo += 0x80000000;
339:       }
340: 
341:       $value = $hi * 4294967296 + $lo;
342: 
343:       if ($isNeg) {
344:         $value = 0 - $value;
345:       }
346:     } else {
347: 
348:       
349:       if ($arr[2] & 0x80000000) {
350:         $arr[2] = $arr[2] & 0xffffffff;
351:       }
352: 
353:       
354:       if ($arr[1] & 0x80000000) {
355:         $arr[1] = $arr[1] & 0xffffffff;
356:         $arr[1] = $arr[1] ^ 0xffffffff;
357:         $arr[2] = $arr[2] ^ 0xffffffff;
358:         $value = 0 - $arr[1]*4294967296 - $arr[2] - 1;
359:       } else {
360:         $value = $arr[1]*4294967296 + $arr[2];
361:       }
362:     }
363: 
364:     return 8;
365:   }
366: 
367:   public function readDouble(&$value) {
368:     $data = strrev($this->trans_->readAll(8));
369:     $arr = unpack('d', $data);
370:     $value = $arr[1];
371:     return 8;
372:   }
373: 
374:   public function readString(&$value) {
375:     $result = $this->readI32($len);
376:     if ($len) {
377:       $value = $this->trans_->readAll($len);
378:     } else {
379:       $value = '';
380:     }
381:     return $result + $len;
382:   }
383: }
384: 
385: 386: 387: 
388: class TBinaryProtocolFactory implements TProtocolFactory {
389:   private $strictRead_ = false;
390:   private $strictWrite_ = false;
391: 
392:   public function __construct($strictRead=false, $strictWrite=false) {
393:     $this->strictRead_ = $strictRead;
394:     $this->strictWrite_ = $strictWrite;
395:   }
396: 
397:   public function getProtocol($trans) {
398:     return new TBinaryProtocol($trans, $this->strictRead, $this->strictWrite);
399:   }
400: }
401: 
402: 403: 404: 405: 
406: class TBinaryProtocolAccelerated extends TBinaryProtocol {
407:   public function __construct($trans, $strictRead=false, $strictWrite=true) {
408:     
409:     
410:     if (!method_exists($trans, 'putBack')) {
411:       $trans = new TBufferedTransport($trans);
412:     }
413:     parent::__construct($trans, $strictRead, $strictWrite);
414:   }
415:   public function isStrictRead() {
416:     return $this->strictRead_;
417:   }
418:   public function isStrictWrite() {
419:     return $this->strictWrite_;
420:   }
421: }
422: 
423: ?>
424: