PageRenderTime 36ms CodeModel.GetById 1ms app.highlight 28ms RepoModel.GetById 2ms app.codeStats 0ms

/tags/release-0.0.0-rc0/hive/external/service/lib/php/protocol/TBinaryProtocol.php

#
PHP | 431 lines | 319 code | 67 blank | 45 comment | 38 complexity | 5c5c93548ffcfd792c85b11f599afcde MD5 | raw file
  1<?php
  2/*
  3 * Licensed to the Apache Software Foundation (ASF) under one
  4 * or more contributor license agreements. See the NOTICE file
  5 * distributed with this work for additional information
  6 * regarding copyright ownership. The ASF licenses this file
  7 * to you under the Apache License, Version 2.0 (the
  8 * "License"); you may not use this file except in compliance
  9 * with the License. You may obtain a copy of the License at
 10 *
 11 *   http://www.apache.org/licenses/LICENSE-2.0
 12 *
 13 * Unless required by applicable law or agreed to in writing,
 14 * software distributed under the License is distributed on an
 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 16 * KIND, either express or implied. See the License for the
 17 * specific language governing permissions and limitations
 18 * under the License.
 19 *
 20 * @package thrift.protocol
 21 */
 22
 23include_once $GLOBALS['THRIFT_ROOT'].'/transport/TBufferedTransport.php';
 24
 25/**
 26 * Binary implementation of the Thrift protocol.
 27 *
 28 */
 29class TBinaryProtocol extends TProtocol {
 30
 31  const VERSION_MASK = 0xffff0000;
 32  const VERSION_1 = 0x80010000;
 33
 34  protected $strictRead_ = false;
 35  protected $strictWrite_ = true;
 36
 37  public function __construct($trans, $strictRead=false, $strictWrite=true) {
 38    parent::__construct($trans);
 39    $this->strictRead_ = $strictRead;
 40    $this->strictWrite_ = $strictWrite;
 41  }
 42
 43  public function writeMessageBegin($name, $type, $seqid) {
 44    if ($this->strictWrite_) {
 45      $version = self::VERSION_1 | $type;
 46      return
 47        $this->writeI32($version) +
 48        $this->writeString($name) +
 49        $this->writeI32($seqid);
 50    } else {
 51      return
 52        $this->writeString($name) +
 53        $this->writeByte($type) +
 54        $this->writeI32($seqid);
 55    }
 56  }
 57
 58  public function writeMessageEnd() {
 59    return 0;
 60  }
 61
 62  public function writeStructBegin($name) {
 63    return 0;
 64  }
 65
 66  public function writeStructEnd() {
 67    return 0;
 68  }
 69
 70  public function writeFieldBegin($fieldName, $fieldType, $fieldId) {
 71    return
 72      $this->writeByte($fieldType) +
 73      $this->writeI16($fieldId);
 74  }
 75
 76  public function writeFieldEnd() {
 77    return 0;
 78  }
 79
 80  public function writeFieldStop() {
 81    return
 82      $this->writeByte(TType::STOP);
 83  }
 84
 85  public function writeMapBegin($keyType, $valType, $size) {
 86    return
 87      $this->writeByte($keyType) +
 88      $this->writeByte($valType) +
 89      $this->writeI32($size);
 90  }
 91
 92  public function writeMapEnd() {
 93    return 0;
 94  }
 95
 96  public function writeListBegin($elemType, $size) {
 97    return
 98      $this->writeByte($elemType) +
 99      $this->writeI32($size);
100  }
101
102  public function writeListEnd() {
103    return 0;
104  }
105
106  public function writeSetBegin($elemType, $size) {
107    return
108      $this->writeByte($elemType) +
109      $this->writeI32($size);
110  }
111
112  public function writeSetEnd() {
113    return 0;
114  }
115
116  public function writeBool($value) {
117    $data = pack('c', $value ? 1 : 0);
118    $this->trans_->write($data, 1);
119    return 1;
120  }
121
122  public function writeByte($value) {
123    $data = pack('c', $value);
124    $this->trans_->write($data, 1);
125    return 1;
126  }
127
128  public function writeI16($value) {
129    $data = pack('n', $value);
130    $this->trans_->write($data, 2);
131    return 2;
132  }
133
134  public function writeI32($value) {
135    $data = pack('N', $value);
136    $this->trans_->write($data, 4);
137    return 4;
138  }
139
140  public function writeI64($value) {
141    // If we are on a 32bit architecture we have to explicitly deal with
142    // 64-bit twos-complement arithmetic since PHP wants to treat all ints
143    // as signed and any int over 2^31 - 1 as a float
144    if (PHP_INT_SIZE == 4) {
145      $neg = $value < 0;
146
147      if ($neg) {
148        $value *= -1;
149      }
150
151      $hi = (int)($value / 4294967296);
152      $lo = (int)$value;
153
154      if ($neg) {
155        $hi = ~$hi;
156        $lo = ~$lo;
157        if (($lo & (int)0xffffffff) == (int)0xffffffff) {
158          $lo = 0;
159          $hi++;
160        } else {
161          $lo++;
162        }
163      }
164      $data = pack('N2', $hi, $lo);
165
166    } else {
167      $hi = $value >> 32;
168      $lo = $value & 0xFFFFFFFF;
169      $data = pack('N2', $hi, $lo);
170    }
171
172    $this->trans_->write($data, 8);
173    return 8;
174  }
175
176  public function writeDouble($value) {
177    $data = pack('d', $value);
178    $this->trans_->write(strrev($data), 8);
179    return 8;
180  }
181
182  public function writeString($value) {
183    $len = strlen($value);
184    $result = $this->writeI32($len);
185    if ($len) {
186      $this->trans_->write($value, $len);
187    }
188    return $result + $len;
189  }
190
191  public function readMessageBegin(&$name, &$type, &$seqid) {
192    $result = $this->readI32($sz);
193    if ($sz < 0) {
194      $version = (int) ($sz & self::VERSION_MASK);
195      if ($version != (int) self::VERSION_1) {
196        throw new TProtocolException('Bad version identifier: '.$sz, TProtocolException::BAD_VERSION);
197      }
198      $type = $sz & 0x000000ff;
199      $result +=
200        $this->readString($name) +
201        $this->readI32($seqid);
202    } else {
203      if ($this->strictRead_) {
204        throw new TProtocolException('No version identifier, old protocol client?', TProtocolException::BAD_VERSION);
205      } else {
206        // Handle pre-versioned input
207        $name = $this->trans_->readAll($sz);
208        $result +=
209          $sz +
210          $this->readByte($type) +
211          $this->readI32($seqid);
212      }
213    }
214    return $result;
215  }
216
217  public function readMessageEnd() {
218    return 0;
219  }
220
221  public function readStructBegin(&$name) {
222    $name = '';
223    return 0;
224  }
225
226  public function readStructEnd() {
227    return 0;
228  }
229
230  public function readFieldBegin(&$name, &$fieldType, &$fieldId) {
231    $result = $this->readByte($fieldType);
232    if ($fieldType == TType::STOP) {
233      $fieldId = 0;
234      return $result;
235    }
236    $result += $this->readI16($fieldId);
237    return $result;
238  }
239
240  public function readFieldEnd() {
241    return 0;
242  }
243
244  public function readMapBegin(&$keyType, &$valType, &$size) {
245    return
246      $this->readByte($keyType) +
247      $this->readByte($valType) +
248      $this->readI32($size);
249  }
250
251  public function readMapEnd() {
252    return 0;
253  }
254
255  public function readListBegin(&$elemType, &$size) {
256    return
257      $this->readByte($elemType) +
258      $this->readI32($size);
259  }
260
261  public function readListEnd() {
262    return 0;
263  }
264
265  public function readSetBegin(&$elemType, &$size) {
266    return
267      $this->readByte($elemType) +
268      $this->readI32($size);
269  }
270
271  public function readSetEnd() {
272    return 0;
273  }
274
275  public function readBool(&$value) {
276    $data = $this->trans_->readAll(1);
277    $arr = unpack('c', $data);
278    $value = $arr[1] == 1;
279    return 1;
280  }
281
282  public function readByte(&$value) {
283    $data = $this->trans_->readAll(1);
284    $arr = unpack('c', $data);
285    $value = $arr[1];
286    return 1;
287  }
288
289  public function readI16(&$value) {
290    $data = $this->trans_->readAll(2);
291    $arr = unpack('n', $data);
292    $value = $arr[1];
293    if ($value > 0x7fff) {
294      $value = 0 - (($value - 1) ^ 0xffff);
295    }
296    return 2;
297  }
298
299  public function readI32(&$value) {
300    $data = $this->trans_->readAll(4);
301    $arr = unpack('N', $data);
302    $value = $arr[1];
303    if ($value > 0x7fffffff) {
304      $value = 0 - (($value - 1) ^ 0xffffffff);
305    }
306    return 4;
307  }
308
309  public function readI64(&$value) {
310    $data = $this->trans_->readAll(8);
311
312    $arr = unpack('N2', $data);
313
314    // If we are on a 32bit architecture we have to explicitly deal with
315    // 64-bit twos-complement arithmetic since PHP wants to treat all ints
316    // as signed and any int over 2^31 - 1 as a float
317    if (PHP_INT_SIZE == 4) {
318
319      $hi = $arr[1];
320      $lo = $arr[2];
321      $isNeg = $hi  < 0;
322
323      // Check for a negative
324      if ($isNeg) {
325        $hi = ~$hi & (int)0xffffffff;
326        $lo = ~$lo & (int)0xffffffff;
327
328        if ($lo == (int)0xffffffff) {
329          $hi++;
330          $lo = 0;
331        } else {
332          $lo++;
333        }
334      }
335
336      // Force 32bit words in excess of 2G to pe positive - we deal wigh sign
337      // explicitly below
338
339      if ($hi & (int)0x80000000) {
340        $hi &= (int)0x7fffffff;
341        $hi += 0x80000000;
342      }
343
344      if ($lo & (int)0x80000000) {
345        $lo &= (int)0x7fffffff;
346        $lo += 0x80000000;
347      }
348
349      $value = $hi * 4294967296 + $lo;
350
351      if ($isNeg) {
352        $value = 0 - $value;
353      }
354    } else {
355
356      // Upcast negatives in LSB bit
357      if ($arr[2] & 0x80000000) {
358        $arr[2] = $arr[2] & 0xffffffff;
359      }
360
361      // Check for a negative
362      if ($arr[1] & 0x80000000) {
363        $arr[1] = $arr[1] & 0xffffffff;
364        $arr[1] = $arr[1] ^ 0xffffffff;
365        $arr[2] = $arr[2] ^ 0xffffffff;
366        $value = 0 - $arr[1]*4294967296 - $arr[2] - 1;
367      } else {
368        $value = $arr[1]*4294967296 + $arr[2];
369      }
370    }
371
372    return 8;
373  }
374
375  public function readDouble(&$value) {
376    $data = strrev($this->trans_->readAll(8));
377    $arr = unpack('d', $data);
378    $value = $arr[1];
379    return 8;
380  }
381
382  public function readString(&$value) {
383    $result = $this->readI32($len);
384    if ($len) {
385      $value = $this->trans_->readAll($len);
386    } else {
387      $value = '';
388    }
389    return $result + $len;
390  }
391}
392
393/**
394 * Binary Protocol Factory
395 */
396class TBinaryProtocolFactory implements TProtocolFactory {
397  private $strictRead_ = false;
398  private $strictWrite_ = false;
399
400  public function __construct($strictRead=false, $strictWrite=false) {
401    $this->strictRead_ = $strictRead;
402    $this->strictWrite_ = $strictWrite;
403  }
404
405  public function getProtocol($trans) {
406    return new TBinaryProtocol($trans, $this->strictRead, $this->strictWrite);
407  }
408}
409
410/**
411 * Accelerated binary protocol: used in conjunction with the thrift_protocol
412 * extension for faster deserialization
413 */
414class TBinaryProtocolAccelerated extends TBinaryProtocol {
415  public function __construct($trans, $strictRead=false, $strictWrite=true) {
416    // If the transport doesn't implement putBack, wrap it in a
417    // TBufferedTransport (which does)
418    if (!method_exists($trans, 'putBack')) {
419      $trans = new TBufferedTransport($trans);
420    }
421    parent::__construct($trans, $strictRead, $strictWrite);
422  }
423  public function isStrictRead() {
424    return $this->strictRead_;
425  }
426  public function isStrictWrite() {
427    return $this->strictWrite_;
428  }
429}
430
431?>