PHP Thrift improvements, Binary code skipping, etc
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664821 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/php/src/Thrift.php b/lib/php/src/Thrift.php
index ee48092..fc4034b 100644
--- a/lib/php/src/Thrift.php
+++ b/lib/php/src/Thrift.php
@@ -1,6 +1,8 @@
<?php
-/** Set global THRIFT ROOT automatically via inclusion here */
+/**
+ * Set global THRIFT ROOT automatically via inclusion here
+ */
if (!isset($GLOBALS['THRIFT_ROOT'])) {
$GLOBALS['THRIFT_ROOT'] = dirname(__FILE__);
}
diff --git a/lib/php/src/protocol/TProtocol.php b/lib/php/src/protocol/TProtocol.php
index 3d9c466..40266dd 100644
--- a/lib/php/src/protocol/TProtocol.php
+++ b/lib/php/src/protocol/TProtocol.php
@@ -5,7 +5,6 @@
*/
include_once $GLOBALS['THRIFT_ROOT'].'/protocol/TType.php';
-
/**
* Protocol module.
*
@@ -214,6 +213,100 @@
return 0;
}
}
+
+ /**
+ * Utility for skipping binary data
+ *
+ * @param TTransport $itrans TTransport object
+ * @param int $type Field type
+ */
+ public static function skipBinary($itrans, $type) {
+ switch ($type) {
+ case TType::BOOL:
+ return $itrans->readAll(1);
+ case TType::BYTE:
+ return $itrans->readAll(1);
+ case TType::I16;
+ return $itrans->readAll(2);
+ case TType::I32:
+ return $itrans->readAll(4);
+ case TType::I64:
+ return $itrans->readAll(8);
+ case TType::DOUBLE:
+ return $itrans->readAll(8);
+ case TType::STRING:
+ $len = unpack('N', $itrans->readAll(4));
+ $len = $len[1];
+ if ($len > 0x7fffffff) {
+ $len = 0 - (($len - 1) ^ 0xffffffff);
+ }
+ return 4 + $itrans->readAll($len);
+ case TType::STRUCT:
+ {
+ $result = 0;
+ while (true) {
+ $ftype = 0;
+ $fid = 0;
+ $data = $in->readAll(1);
+ $arr = unpack('c', $data);
+ $ftype = $arr[1];
+ if ($ftype == TType::STOP) {
+ break;
+ }
+ // I16 field id
+ $result += $itrans->readAll(2);
+ $result += self::skipBinary($itrans, $ftype);
+ }
+ return $result;
+ }
+ case TType::MAP:
+ {
+ // Ktype
+ $data = $itrans->readAll(1);
+ $arr = unpack('c', $data);
+ $ktype = $arr[1];
+ // Vtype
+ $data = $itrans->readAll(1);
+ $arr = unpack('c', $data);
+ $vtype = $arr[1];
+ // Size
+ $data = $itrans->readAll(4);
+ $arr = unpack('N', $data);
+ $size = $arr[1];
+ if ($size > 0x7fffffff) {
+ $size = 0 - (($size - 1) ^ 0xffffffff);
+ }
+ $result = 6;
+ for ($i = 0; $i < $size; $i++) {
+ $result += self::skipBinary($itrans, $ktype);
+ $result += self::skipBinary($itrans, $vtype);
+ }
+ return $result;
+ }
+ case TType::SET:
+ case TType::LST:
+ {
+ // Vtype
+ $data = $itrans->readAll(1);
+ $arr = unpack('c', $data);
+ $vtype = $arr[1];
+ // Size
+ $data = $itrans->readAll(4);
+ $arr = unpack('N', $data);
+ $size = $arr[1];
+ if ($size > 0x7fffffff) {
+ $size = 0 - (($size - 1) ^ 0xffffffff);
+ }
+ $result = 5;
+ for ($i = 0; $i < $size; $i++) {
+ $result += self::skipBinary($itrans, $vtype);
+ }
+ return $result;
+ }
+ default:
+ return 0;
+ }
+ }
}
?>
diff --git a/lib/php/src/transport/TPhpStream.php b/lib/php/src/transport/TPhpStream.php
new file mode 100644
index 0000000..d650935
--- /dev/null
+++ b/lib/php/src/transport/TPhpStream.php
@@ -0,0 +1,84 @@
+<?php
+
+/**
+ * Php stream transport. Reads to and writes from the php standard streams
+ * php://input and php://output
+ *
+ * @package thrift.transport
+ * @author Mark Slee <mcslee@facebook.com>
+ */
+class TPhpStream extends TTransport {
+
+ const MODE_R = 1;
+ const MODE_W = 2;
+
+ private $inStream_ = null;
+
+ private $outStream_ = null;
+
+ private $read_ = false;
+
+ private $write_ = false;
+
+ public function __construct($mode) {
+ $this->read_ = $mode & self::MODE_R;
+ $this->write_ = $mode & self::MODE_W;
+ }
+
+ public function open() {
+ if ($this->read_) {
+ $this->inStream_ = @fopen('php://input', 'r');
+ if (!is_resource($this->inStream_)) {
+ throw new Exception('TPhpStream: Could not open php://input');
+ }
+ }
+ if ($this->write_) {
+ $this->outStream_ = @fopen('php://output', 'w');
+ if (!is_resource($this->outStream_)) {
+ throw new Exception('TPhpStream: Could not open php://output');
+ }
+ }
+ }
+
+ public function close() {
+ if ($this->read_) {
+ @fclose($this->inStream_);
+ $this->inStream_ = null;
+ }
+ if ($this->write_) {
+ @fclose($this->outStream_);
+ $this->outStream_ = null;
+ }
+ }
+
+ public function isOpen() {
+ return
+ (!$this->read_ || is_resource($this->inStream_)) &&
+ (!$this->write_ || is_resource($this->outStream_));
+ }
+
+ public function read($len) {
+ $data = @fread($this->inStream_, $len);
+ if (!$data) {
+ throw new Exception('TPhpStream: Could not read '.$len.' bytes');
+ }
+ return $data;
+ }
+
+ public function write($buf) {
+ while (!empty($buf)) {
+ $got = @fwrite($this->outStream_, $buf);
+ if ($got === 0 || $got === FALSE) {
+ throw new Exception('TPhpStream: Could not write '.strlen($buf).' bytes');
+ }
+ $buf = substr($buf, $got);
+ }
+ }
+
+ public function flush() {
+ @fflush($this->outStream_);
+ }
+
+}
+
+?>
diff --git a/lib/php/src/transport/TSocket.php b/lib/php/src/transport/TSocket.php
index c94d075..d05f351 100644
--- a/lib/php/src/transport/TSocket.php
+++ b/lib/php/src/transport/TSocket.php
@@ -201,7 +201,7 @@
$this->sendTimeoutSet_ = FALSE;
}
$data = @fread($this->handle_, $len);
- if ($data === FALSE) {
+ if (!$data) {
throw new Exception('TSocket: Could not read '.$len.' bytes from '.
$this->host_.':'.$this->port_);
}