Moving from govendor to dep, updated dependencies (#48)

* Moving from govendor to dep.

* Making the pull request template more friendly.

* Fixing akward space in PR template.

* goimports run on whole project using ` goimports -w $(find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./gen-go/*")`

source of command: https://gist.github.com/bgentry/fd1ffef7dbde01857f66
This commit is contained in:
Renan DelValle 2018-01-07 13:13:47 -08:00 committed by GitHub
parent 9631aa3aab
commit 8d445c1c77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2186 changed files with 400410 additions and 352 deletions

150
vendor/git.apache.org/thrift.git/lib/php/Makefile.am generated vendored Executable file
View file

@ -0,0 +1,150 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
if WITH_TESTS
SUBDIRS = test
endif
if WITH_PHP_EXTENSION
%.so:
cd src/ext/thrift_protocol/ && $(MAKE)
phpconfdir=$(PHP_CONFIG_PREFIX)
phpconf_DATA=thrift_protocol.ini
phpmoduledir = `php-config --extension-dir`
phpmodule_SCRIPTS = src/ext/thrift_protocol/modules/thrift_protocol.so
distclean-local:
cd $(phpmodule_SCRIPTS) && $(PHPIZE) --clean
endif
phpdir = $(PHP_PREFIX)/Thrift
php_DATA = \
lib/Thrift/TMultiplexedProcessor.php
phpbasedir = $(phpdir)/Base
phpbase_DATA = \
lib/Thrift/Base/TBase.php
phpclassloaderdir = $(phpdir)/ClassLoader
phpclassloader_DATA = \
lib/Thrift/ClassLoader/ThriftClassLoader.php
phpexceptiondir = $(phpdir)/Exception
phpexception_DATA = \
lib/Thrift/Exception/TApplicationException.php \
lib/Thrift/Exception/TException.php \
lib/Thrift/Exception/TProtocolException.php \
lib/Thrift/Exception/TTransportException.php
phpfactorydir = $(phpdir)/Factory
phpfactory_DATA = \
lib/Thrift/Factory/TBinaryProtocolFactory.php \
lib/Thrift/Factory/TCompactProtocolFactory.php \
lib/Thrift/Factory/TJSONProtocolFactory.php \
lib/Thrift/Factory/TProtocolFactory.php \
lib/Thrift/Factory/TStringFuncFactory.php \
lib/Thrift/Factory/TTransportFactory.php
phpprotocoldir = $(phpdir)/Protocol
phpprotocol_DATA = \
lib/Thrift/Protocol/TBinaryProtocolAccelerated.php \
lib/Thrift/Protocol/TBinaryProtocol.php \
lib/Thrift/Protocol/TCompactProtocol.php \
lib/Thrift/Protocol/TJSONProtocol.php \
lib/Thrift/Protocol/TMultiplexedProtocol.php \
lib/Thrift/Protocol/TProtocol.php \
lib/Thrift/Protocol/TProtocolDecorator.php \
lib/Thrift/Protocol/TSimpleJSONProtocol.php
phpprotocoljsondir = $(phpprotocoldir)/JSON
phpprotocoljson_DATA = \
lib/Thrift/Protocol/JSON/BaseContext.php \
lib/Thrift/Protocol/JSON/ListContext.php \
lib/Thrift/Protocol/JSON/LookaheadReader.php \
lib/Thrift/Protocol/JSON/PairContext.php
phpprotocolsimplejsondir = $(phpprotocoldir)/SimpleJSON
phpprotocolsimplejson_DATA = \
lib/Thrift/Protocol/SimpleJSON/CollectionMapKeyException.php \
lib/Thrift/Protocol/SimpleJSON/Context.php \
lib/Thrift/Protocol/SimpleJSON/ListContext.php \
lib/Thrift/Protocol/SimpleJSON/MapContext.php \
lib/Thrift/Protocol/SimpleJSON/StructContext.php
phpserializerdir = $(phpdir)/Serializer
phpserializer_DATA = \
lib/Thrift/Serializer/TBinarySerializer.php
phpserverdir = $(phpdir)/Server
phpserver_DATA = \
lib/Thrift/Server/TServerSocket.php \
lib/Thrift/Server/TForkingServer.php \
lib/Thrift/Server/TServer.php \
lib/Thrift/Server/TServerTransport.php \
lib/Thrift/Server/TSimpleServer.php
phpstringfuncdir = $(phpdir)/StringFunc
phpstringfunc_DATA = \
lib/Thrift/StringFunc/Mbstring.php \
lib/Thrift/StringFunc/Core.php \
lib/Thrift/StringFunc/TStringFunc.php
phptransportdir = $(phpdir)/Transport
phptransport_DATA = \
lib/Thrift/Transport/TBufferedTransport.php \
lib/Thrift/Transport/TCurlClient.php \
lib/Thrift/Transport/TFramedTransport.php \
lib/Thrift/Transport/THttpClient.php \
lib/Thrift/Transport/TMemoryBuffer.php \
lib/Thrift/Transport/TNullTransport.php \
lib/Thrift/Transport/TPhpStream.php \
lib/Thrift/Transport/TSocket.php \
lib/Thrift/Transport/TSocketPool.php \
lib/Thrift/Transport/TTransport.php
phptypedir = $(phpdir)/Type
phptype_DATA = \
lib/Thrift/Type/TMessageType.php \
lib/Thrift/Type/TType.php \
lib/Thrift/Type/TConstant.php
EXTRA_DIST = \
lib \
src/autoload.php \
src/ext/thrift_protocol/config.m4 \
src/ext/thrift_protocol/config.w32 \
src/ext/thrift_protocol/php_thrift_protocol7.cpp \
src/ext/thrift_protocol/php_thrift_protocol.cpp \
src/ext/thrift_protocol/php_thrift_protocol.h \
src/ext/thrift_protocol/run-tests.php \
src/Thrift.php \
src/TStringUtils.php \
coding_standards.md \
thrift_protocol.ini \
README.apache.md \
README.md
MAINTAINERCLEANFILES = \
Makefile \
Makefile.in

View file

@ -0,0 +1,74 @@
Thrift PHP/Apache Integration
License
=======
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
Building PHP Thrift Services with Apache
========================================
Thrift can be embedded in the Apache webserver with PHP installed. Sample
code is provided below. Note that to make requests to this type of server
you must use a THttpClient transport.
Sample Code
===========
<?php
namespace MyNamespace;
/**
* Include path
*/
$THRIFT_ROOT = '/your/thrift/root/lib';
/**
* Init Autloader
*/
require_once $THRIFT_ROOT . '/Thrift/ClassLoader/ThriftClassLoader.php';
$loader = new ThriftClassLoader();
$loader->registerNamespace('Thrift', $THRIFT_ROOT);
$loader->registerDefinition('Thrift', $THRIFT_ROOT . '/packages');
$loader->register();
use Thrift\Transport\TPhpStream;
use Thrift\Protocol\TBinaryProtocol;
/**
* Example of how to build a Thrift server in Apache/PHP
*/
class ServiceHandler implements ServiceIf {
// Implement your interface and methods here
}
header('Content-Type: application/x-thrift');
$handler = new ServiceHandler();
$processor = new ServiceProcessor($handler);
// Use the TPhpStream transport to read/write directly from HTTP
$transport = new TPhpStream(TPhpStream::MODE_R | TPhpStream::MODE_W);
$protocol = new TBinaryProtocol($transport);
$transport->open();
$processor->process($protocol, $protocol);
$transport->close();

53
vendor/git.apache.org/thrift.git/lib/php/README.md generated vendored Normal file
View file

@ -0,0 +1,53 @@
Thrift PHP Software Library
License
=======
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
Using Thrift with PHP
=====================
Thrift requires PHP 5. Thrift makes as few assumptions about your PHP
environment as possible while trying to make some more advanced PHP
features (i.e. APC cacheing using asbolute path URLs) as simple as possible.
To use Thrift in your PHP codebase, take the following steps:
#1) Copy all of thrift/lib/php/lib into your PHP codebase
#2) Configure Symfony Autoloader (or whatever you usually use)
After that, you have to manually include the Thrift package
created by the compiler:
require_once 'packages/Service/Service.php';
require_once 'packages/Service/Types.php';
Dependencies
============
PHP_INT_SIZE
This built-in signals whether your architecture is 32 or 64 bit and is
used by the TBinaryProtocol to properly use pack() and unpack() to
serialize data.
apc_fetch(), apc_store()
APC cache is used by the TSocketPool class. If you do not have APC installed,
Thrift will fill in null stub function definitions.

View file

@ -0,0 +1 @@
Please follow [General Coding Standards](/doc/coding_standards.md)

View file

@ -0,0 +1,380 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift
*/
namespace Thrift\Base;
use Thrift\Type\TType;
/**
* Base class from which other Thrift structs extend. This is so that we can
* cut back on the size of the generated code which is turning out to have a
* nontrivial cost just to load thanks to the wondrously abysmal implementation
* of PHP. Note that code is intentionally duplicated in here to avoid making
* function calls for every field or member of a container..
*/
abstract class TBase
{
static $tmethod = array(TType::BOOL => 'Bool',
TType::BYTE => 'Byte',
TType::I16 => 'I16',
TType::I32 => 'I32',
TType::I64 => 'I64',
TType::DOUBLE => 'Double',
TType::STRING => 'String');
abstract public function read($input);
abstract public function write($output);
public function __construct($spec=null, $vals=null)
{
if (is_array($spec) && is_array($vals)) {
foreach ($spec as $fid => $fspec) {
$var = $fspec['var'];
if (isset($vals[$var])) {
$this->$var = $vals[$var];
}
}
}
}
public function __wakeup()
{
$this->__construct(get_object_vars($this));
}
private function _readMap(&$var, $spec, $input)
{
$xfer = 0;
$ktype = $spec['ktype'];
$vtype = $spec['vtype'];
$kread = $vread = null;
if (isset(TBase::$tmethod[$ktype])) {
$kread = 'read'.TBase::$tmethod[$ktype];
} else {
$kspec = $spec['key'];
}
if (isset(TBase::$tmethod[$vtype])) {
$vread = 'read'.TBase::$tmethod[$vtype];
} else {
$vspec = $spec['val'];
}
$var = array();
$_ktype = $_vtype = $size = 0;
$xfer += $input->readMapBegin($_ktype, $_vtype, $size);
for ($i = 0; $i < $size; ++$i) {
$key = $val = null;
if ($kread !== null) {
$xfer += $input->$kread($key);
} else {
switch ($ktype) {
case TType::STRUCT:
$class = $kspec['class'];
$key = new $class();
$xfer += $key->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($key, $kspec, $input);
break;
case TType::LST:
$xfer += $this->_readList($key, $kspec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($key, $kspec, $input, true);
break;
}
}
if ($vread !== null) {
$xfer += $input->$vread($val);
} else {
switch ($vtype) {
case TType::STRUCT:
$class = $vspec['class'];
$val = new $class();
$xfer += $val->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($val, $vspec, $input);
break;
case TType::LST:
$xfer += $this->_readList($val, $vspec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($val, $vspec, $input, true);
break;
}
}
$var[$key] = $val;
}
$xfer += $input->readMapEnd();
return $xfer;
}
private function _readList(&$var, $spec, $input, $set=false)
{
$xfer = 0;
$etype = $spec['etype'];
$eread = $vread = null;
if (isset(TBase::$tmethod[$etype])) {
$eread = 'read'.TBase::$tmethod[$etype];
} else {
$espec = $spec['elem'];
}
$var = array();
$_etype = $size = 0;
if ($set) {
$xfer += $input->readSetBegin($_etype, $size);
} else {
$xfer += $input->readListBegin($_etype, $size);
}
for ($i = 0; $i < $size; ++$i) {
$elem = null;
if ($eread !== null) {
$xfer += $input->$eread($elem);
} else {
$espec = $spec['elem'];
switch ($etype) {
case TType::STRUCT:
$class = $espec['class'];
$elem = new $class();
$xfer += $elem->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($elem, $espec, $input);
break;
case TType::LST:
$xfer += $this->_readList($elem, $espec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($elem, $espec, $input, true);
break;
}
}
if ($set) {
$var[$elem] = true;
} else {
$var []= $elem;
}
}
if ($set) {
$xfer += $input->readSetEnd();
} else {
$xfer += $input->readListEnd();
}
return $xfer;
}
protected function _read($class, $spec, $input)
{
$xfer = 0;
$fname = null;
$ftype = 0;
$fid = 0;
$xfer += $input->readStructBegin($fname);
while (true) {
$xfer += $input->readFieldBegin($fname, $ftype, $fid);
if ($ftype == TType::STOP) {
break;
}
if (isset($spec[$fid])) {
$fspec = $spec[$fid];
$var = $fspec['var'];
if ($ftype == $fspec['type']) {
$xfer = 0;
if (isset(TBase::$tmethod[$ftype])) {
$func = 'read'.TBase::$tmethod[$ftype];
$xfer += $input->$func($this->$var);
} else {
switch ($ftype) {
case TType::STRUCT:
$class = $fspec['class'];
$this->$var = new $class();
$xfer += $this->$var->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($this->$var, $fspec, $input);
break;
case TType::LST:
$xfer += $this->_readList($this->$var, $fspec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($this->$var, $fspec, $input, true);
break;
}
}
} else {
$xfer += $input->skip($ftype);
}
} else {
$xfer += $input->skip($ftype);
}
$xfer += $input->readFieldEnd();
}
$xfer += $input->readStructEnd();
return $xfer;
}
private function _writeMap($var, $spec, $output)
{
$xfer = 0;
$ktype = $spec['ktype'];
$vtype = $spec['vtype'];
$kwrite = $vwrite = null;
if (isset(TBase::$tmethod[$ktype])) {
$kwrite = 'write'.TBase::$tmethod[$ktype];
} else {
$kspec = $spec['key'];
}
if (isset(TBase::$tmethod[$vtype])) {
$vwrite = 'write'.TBase::$tmethod[$vtype];
} else {
$vspec = $spec['val'];
}
$xfer += $output->writeMapBegin($ktype, $vtype, count($var));
foreach ($var as $key => $val) {
if (isset($kwrite)) {
$xfer += $output->$kwrite($key);
} else {
switch ($ktype) {
case TType::STRUCT:
$xfer += $key->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($key, $kspec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($key, $kspec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($key, $kspec, $output, true);
break;
}
}
if (isset($vwrite)) {
$xfer += $output->$vwrite($val);
} else {
switch ($vtype) {
case TType::STRUCT:
$xfer += $val->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($val, $vspec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($val, $vspec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($val, $vspec, $output, true);
break;
}
}
}
$xfer += $output->writeMapEnd();
return $xfer;
}
private function _writeList($var, $spec, $output, $set=false)
{
$xfer = 0;
$etype = $spec['etype'];
$ewrite = null;
if (isset(TBase::$tmethod[$etype])) {
$ewrite = 'write'.TBase::$tmethod[$etype];
} else {
$espec = $spec['elem'];
}
if ($set) {
$xfer += $output->writeSetBegin($etype, count($var));
} else {
$xfer += $output->writeListBegin($etype, count($var));
}
foreach ($var as $key => $val) {
$elem = $set ? $key : $val;
if (isset($ewrite)) {
$xfer += $output->$ewrite($elem);
} else {
switch ($etype) {
case TType::STRUCT:
$xfer += $elem->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($elem, $espec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($elem, $espec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($elem, $espec, $output, true);
break;
}
}
}
if ($set) {
$xfer += $output->writeSetEnd();
} else {
$xfer += $output->writeListEnd();
}
return $xfer;
}
protected function _write($class, $spec, $output)
{
$xfer = 0;
$xfer += $output->writeStructBegin($class);
foreach ($spec as $fid => $fspec) {
$var = $fspec['var'];
if ($this->$var !== null) {
$ftype = $fspec['type'];
$xfer += $output->writeFieldBegin($var, $ftype, $fid);
if (isset(TBase::$tmethod[$ftype])) {
$func = 'write'.TBase::$tmethod[$ftype];
$xfer += $output->$func($this->$var);
} else {
switch ($ftype) {
case TType::STRUCT:
$xfer += $this->$var->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($this->$var, $fspec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($this->$var, $fspec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($this->$var, $fspec, $output, true);
break;
}
}
$xfer += $output->writeFieldEnd();
}
}
$xfer += $output->writeFieldStop();
$xfer += $output->writeStructEnd();
return $xfer;
}
}

View file

@ -0,0 +1,210 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* ClassLoader to load Thrift library and definitions
* Inspired from UniversalClassLoader from Symfony 2
*
* @package thrift.classloader
*/
namespace Thrift\ClassLoader;
class ThriftClassLoader
{
/**
* Namespaces path
* @var array
*/
protected $namespaces = array();
/**
* Thrift definition paths
* @var type
*/
protected $definitions = array();
/**
* Do we use APC cache ?
* @var boolean
*/
protected $apc = false;
/**
* APC Cache prefix
* @var string
*/
protected $apc_prefix;
/**
* Set autoloader to use APC cache
* @param boolean $apc
* @param string $apc_prefix
*/
public function __construct($apc = false, $apc_prefix = null)
{
$this->apc = $apc;
$this->apc_prefix = $apc_prefix;
}
/**
* Registers a namespace.
*
* @param string $namespace The namespace
* @param array|string $paths The location(s) of the namespace
*/
public function registerNamespace($namespace, $paths)
{
$this->namespaces[$namespace] = (array) $paths;
}
/**
* Registers a Thrift definition namespace.
*
* @param string $namespace The definition namespace
* @param array|string $paths The location(s) of the definition namespace
*/
public function registerDefinition($namespace, $paths)
{
$this->definitions[$namespace] = (array) $paths;
}
/**
* Registers this instance as an autoloader.
*
* @param Boolean $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Loads the given class, definition or interface.
*
* @param string $class The name of the class
*/
public function loadClass($class)
{
if (
(true === $this->apc && ($file = $this->findFileInApc($class))) or
($file = $this->findFile($class))
)
{
require_once $file;
}
}
/**
* Loads the given class or interface in APC.
* @param string $class The name of the class
* @return string
*/
protected function findFileInApc($class)
{
if (false === $file = apc_fetch($this->apc_prefix.$class)) {
apc_store($this->apc_prefix.$class, $file = $this->findFile($class));
}
return $file;
}
/**
* Find class in namespaces or definitions directories
* @param string $class
* @return string
*/
public function findFile($class)
{
// Remove first backslash
if ('\\' == $class[0]) {
$class = substr($class, 1);
}
if (false !== $pos = strrpos($class, '\\')) {
// Namespaced class name
$namespace = substr($class, 0, $pos);
// Iterate in normal namespaces
foreach ($this->namespaces as $ns => $dirs) {
//Don't interfere with other autoloaders
if (0 !== strpos($namespace, $ns)) {
continue;
}
foreach ($dirs as $dir) {
$className = substr($class, $pos + 1);
$file = $dir.DIRECTORY_SEPARATOR.
str_replace('\\', DIRECTORY_SEPARATOR, $namespace).
DIRECTORY_SEPARATOR.
$className.'.php';
if (file_exists($file)) {
return $file;
}
}
}
// Iterate in Thrift namespaces
// Remove first part of namespace
$m = explode('\\', $class);
// Ignore wrong call
if (count($m) <= 1) {
return;
}
$class = array_pop($m);
$namespace = implode('\\', $m);
foreach ($this->definitions as $ns => $dirs) {
//Don't interfere with other autoloaders
if (0 !== strpos($namespace, $ns)) {
continue;
}
foreach ($dirs as $dir) {
/**
* Available in service: Interface, Client, Processor, Rest
* And every service methods (_.+)
*/
if(
0 === preg_match('#(.+)(if|client|processor|rest)$#i', $class, $n) and
0 === preg_match('#(.+)_[a-z0-9]+_(args|result)$#i', $class, $n)
)
{
$className = 'Types';
} else {
$className = $n[1];
}
$file = $dir.DIRECTORY_SEPARATOR .
str_replace('\\', DIRECTORY_SEPARATOR, $namespace) .
DIRECTORY_SEPARATOR .
$className . '.php';
if (file_exists($file)) {
return $file;
}
}
}
}
}
}

View file

@ -0,0 +1,76 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift
*/
namespace Thrift\Exception;
use Thrift\Type\TType;
class TApplicationException extends TException
{
static $_TSPEC =
array(1 => array('var' => 'message',
'type' => TType::STRING),
2 => array('var' => 'code',
'type' => TType::I32));
const UNKNOWN = 0;
const UNKNOWN_METHOD = 1;
const INVALID_MESSAGE_TYPE = 2;
const WRONG_METHOD_NAME = 3;
const BAD_SEQUENCE_ID = 4;
const MISSING_RESULT = 5;
const INTERNAL_ERROR = 6;
const PROTOCOL_ERROR = 7;
const INVALID_TRANSFORM = 8;
const INVALID_PROTOCOL = 9;
const UNSUPPORTED_CLIENT_TYPE = 10;
public function __construct($message=null, $code=0)
{
parent::__construct($message, $code);
}
public function read($output)
{
return $this->_read('TApplicationException', self::$_TSPEC, $output);
}
public function write($output)
{
$xfer = 0;
$xfer += $output->writeStructBegin('TApplicationException');
if ($message = $this->getMessage()) {
$xfer += $output->writeFieldBegin('message', TType::STRING, 1);
$xfer += $output->writeString($message);
$xfer += $output->writeFieldEnd();
}
if ($code = $this->getCode()) {
$xfer += $output->writeFieldBegin('type', TType::I32, 2);
$xfer += $output->writeI32($code);
$xfer += $output->writeFieldEnd();
}
$xfer += $output->writeFieldStop();
$xfer += $output->writeStructEnd();
return $xfer;
}
}

View file

@ -0,0 +1,383 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift
*/
namespace Thrift\Exception;
use Thrift\Type\TType;
use Thrift\Base\TBase;
/**
* NOTE(mcslee): This currently contains a ton of duplicated code from TBase
* because we need to save CPU cycles and this is not yet in an extension.
* Ideally we'd multiply-inherit TException from both Exception and Base, but
* that's not possible in PHP and there are no modules either, so for now we
* apologetically take a trip to HackTown.
*
* Can be called with standard Exception constructor (message, code) or with
* Thrift Base object constructor (spec, vals).
*
* @param mixed $p1 Message (string) or type-spec (array)
* @param mixed $p2 Code (integer) or values (array)
*/
class TException extends \Exception
{
public function __construct($p1=null, $p2=0)
{
if (is_array($p1) && is_array($p2)) {
$spec = $p1;
$vals = $p2;
foreach ($spec as $fid => $fspec) {
$var = $fspec['var'];
if (isset($vals[$var])) {
$this->$var = $vals[$var];
}
}
} else {
parent::__construct($p1, $p2);
}
}
static $tmethod = array(TType::BOOL => 'Bool',
TType::BYTE => 'Byte',
TType::I16 => 'I16',
TType::I32 => 'I32',
TType::I64 => 'I64',
TType::DOUBLE => 'Double',
TType::STRING => 'String');
private function _readMap(&$var, $spec, $input)
{
$xfer = 0;
$ktype = $spec['ktype'];
$vtype = $spec['vtype'];
$kread = $vread = null;
if (isset(TBase::$tmethod[$ktype])) {
$kread = 'read'.TBase::$tmethod[$ktype];
} else {
$kspec = $spec['key'];
}
if (isset(TBase::$tmethod[$vtype])) {
$vread = 'read'.TBase::$tmethod[$vtype];
} else {
$vspec = $spec['val'];
}
$var = array();
$_ktype = $_vtype = $size = 0;
$xfer += $input->readMapBegin($_ktype, $_vtype, $size);
for ($i = 0; $i < $size; ++$i) {
$key = $val = null;
if ($kread !== null) {
$xfer += $input->$kread($key);
} else {
switch ($ktype) {
case TType::STRUCT:
$class = $kspec['class'];
$key = new $class();
$xfer += $key->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($key, $kspec, $input);
break;
case TType::LST:
$xfer += $this->_readList($key, $kspec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($key, $kspec, $input, true);
break;
}
}
if ($vread !== null) {
$xfer += $input->$vread($val);
} else {
switch ($vtype) {
case TType::STRUCT:
$class = $vspec['class'];
$val = new $class();
$xfer += $val->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($val, $vspec, $input);
break;
case TType::LST:
$xfer += $this->_readList($val, $vspec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($val, $vspec, $input, true);
break;
}
}
$var[$key] = $val;
}
$xfer += $input->readMapEnd();
return $xfer;
}
private function _readList(&$var, $spec, $input, $set=false)
{
$xfer = 0;
$etype = $spec['etype'];
$eread = $vread = null;
if (isset(TBase::$tmethod[$etype])) {
$eread = 'read'.TBase::$tmethod[$etype];
} else {
$espec = $spec['elem'];
}
$var = array();
$_etype = $size = 0;
if ($set) {
$xfer += $input->readSetBegin($_etype, $size);
} else {
$xfer += $input->readListBegin($_etype, $size);
}
for ($i = 0; $i < $size; ++$i) {
$elem = null;
if ($eread !== null) {
$xfer += $input->$eread($elem);
} else {
$espec = $spec['elem'];
switch ($etype) {
case TType::STRUCT:
$class = $espec['class'];
$elem = new $class();
$xfer += $elem->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($elem, $espec, $input);
break;
case TType::LST:
$xfer += $this->_readList($elem, $espec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($elem, $espec, $input, true);
break;
}
}
if ($set) {
$var[$elem] = true;
} else {
$var []= $elem;
}
}
if ($set) {
$xfer += $input->readSetEnd();
} else {
$xfer += $input->readListEnd();
}
return $xfer;
}
protected function _read($class, $spec, $input)
{
$xfer = 0;
$fname = null;
$ftype = 0;
$fid = 0;
$xfer += $input->readStructBegin($fname);
while (true) {
$xfer += $input->readFieldBegin($fname, $ftype, $fid);
if ($ftype == TType::STOP) {
break;
}
if (isset($spec[$fid])) {
$fspec = $spec[$fid];
$var = $fspec['var'];
if ($ftype == $fspec['type']) {
$xfer = 0;
if (isset(TBase::$tmethod[$ftype])) {
$func = 'read'.TBase::$tmethod[$ftype];
$xfer += $input->$func($this->$var);
} else {
switch ($ftype) {
case TType::STRUCT:
$class = $fspec['class'];
$this->$var = new $class();
$xfer += $this->$var->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($this->$var, $fspec, $input);
break;
case TType::LST:
$xfer += $this->_readList($this->$var, $fspec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($this->$var, $fspec, $input, true);
break;
}
}
} else {
$xfer += $input->skip($ftype);
}
} else {
$xfer += $input->skip($ftype);
}
$xfer += $input->readFieldEnd();
}
$xfer += $input->readStructEnd();
return $xfer;
}
private function _writeMap($var, $spec, $output)
{
$xfer = 0;
$ktype = $spec['ktype'];
$vtype = $spec['vtype'];
$kwrite = $vwrite = null;
if (isset(TBase::$tmethod[$ktype])) {
$kwrite = 'write'.TBase::$tmethod[$ktype];
} else {
$kspec = $spec['key'];
}
if (isset(TBase::$tmethod[$vtype])) {
$vwrite = 'write'.TBase::$tmethod[$vtype];
} else {
$vspec = $spec['val'];
}
$xfer += $output->writeMapBegin($ktype, $vtype, count($var));
foreach ($var as $key => $val) {
if (isset($kwrite)) {
$xfer += $output->$kwrite($key);
} else {
switch ($ktype) {
case TType::STRUCT:
$xfer += $key->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($key, $kspec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($key, $kspec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($key, $kspec, $output, true);
break;
}
}
if (isset($vwrite)) {
$xfer += $output->$vwrite($val);
} else {
switch ($vtype) {
case TType::STRUCT:
$xfer += $val->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($val, $vspec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($val, $vspec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($val, $vspec, $output, true);
break;
}
}
}
$xfer += $output->writeMapEnd();
return $xfer;
}
private function _writeList($var, $spec, $output, $set=false)
{
$xfer = 0;
$etype = $spec['etype'];
$ewrite = null;
if (isset(TBase::$tmethod[$etype])) {
$ewrite = 'write'.TBase::$tmethod[$etype];
} else {
$espec = $spec['elem'];
}
if ($set) {
$xfer += $output->writeSetBegin($etype, count($var));
} else {
$xfer += $output->writeListBegin($etype, count($var));
}
foreach ($var as $key => $val) {
$elem = $set ? $key : $val;
if (isset($ewrite)) {
$xfer += $output->$ewrite($elem);
} else {
switch ($etype) {
case TType::STRUCT:
$xfer += $elem->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($elem, $espec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($elem, $espec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($elem, $espec, $output, true);
break;
}
}
}
if ($set) {
$xfer += $output->writeSetEnd();
} else {
$xfer += $output->writeListEnd();
}
return $xfer;
}
protected function _write($class, $spec, $output)
{
$xfer = 0;
$xfer += $output->writeStructBegin($class);
foreach ($spec as $fid => $fspec) {
$var = $fspec['var'];
if ($this->$var !== null) {
$ftype = $fspec['type'];
$xfer += $output->writeFieldBegin($var, $ftype, $fid);
if (isset(TBase::$tmethod[$ftype])) {
$func = 'write'.TBase::$tmethod[$ftype];
$xfer += $output->$func($this->$var);
} else {
switch ($ftype) {
case TType::STRUCT:
$xfer += $this->$var->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($this->$var, $fspec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($this->$var, $fspec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($this->$var, $fspec, $output, true);
break;
}
}
$xfer += $output->writeFieldEnd();
}
}
$xfer += $output->writeFieldStop();
$xfer += $output->writeStructEnd();
return $xfer;
}
}

View file

@ -0,0 +1,50 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
* @author: rmarin (marin.radu@facebook.com)
*/
namespace Thrift\Exception;
/**
* Protocol module. Contains all the types and definitions needed to implement
* a protocol encoder/decoder.
*
* @package thrift.protocol
*/
/**
* Protocol exceptions
*/
class TProtocolException extends TException
{
const UNKNOWN = 0;
const INVALID_DATA = 1;
const NEGATIVE_SIZE = 2;
const SIZE_LIMIT = 3;
const BAD_VERSION = 4;
const NOT_IMPLEMENTED = 5;
const DEPTH_LIMIT = 6;
public function __construct($message=null, $code=0)
{
parent::__construct($message, $code);
}
}

View file

@ -0,0 +1,40 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.transport
*/
namespace Thrift\Exception;
/**
* Transport exceptions
*/
class TTransportException extends TException
{
const UNKNOWN = 0;
const NOT_OPEN = 1;
const ALREADY_OPEN = 2;
const TIMED_OUT = 3;
const END_OF_FILE = 4;
public function __construct($message=null, $code=0)
{
parent::__construct($message, $code);
}
}

View file

@ -0,0 +1,45 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Factory;
use Thrift\Protocol\TBinaryProtocol;
/**
* Binary Protocol Factory
*/
class TBinaryProtocolFactory implements TProtocolFactory
{
private $strictRead_ = false;
private $strictWrite_ = false;
public function __construct($strictRead=false, $strictWrite=false)
{
$this->strictRead_ = $strictRead;
$this->strictWrite_ = $strictWrite;
}
public function getProtocol($trans)
{
return new TBinaryProtocol($trans, $this->strictRead_, $this->strictWrite_);
}
}

View file

@ -0,0 +1,40 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Factory;
use Thrift\Protocol\TCompactProtocol;
/**
* Compact Protocol Factory
*/
class TCompactProtocolFactory implements TProtocolFactory
{
public function __construct()
{
}
public function getProtocol($trans)
{
return new TCompactProtocol($trans);
}
}

View file

@ -0,0 +1,40 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Factory;
use Thrift\Protocol\TJSONProtocol;
/**
* JSON Protocol Factory
*/
class TJSONProtocolFactory implements TProtocolFactory
{
public function __construct()
{
}
public function getProtocol($trans)
{
return new TJSONProtocol($trans);
}
}

View file

@ -0,0 +1,36 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Factory;
/**
* Protocol factory creates protocol objects from transports
*/
interface TProtocolFactory
{
/**
* Build a protocol from the base transport
*
* @return Thrift\Protocol\TProtocol protocol
*/
public function getProtocol($trans);
}

View file

@ -0,0 +1,66 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
namespace Thrift\Factory;
use Thrift\StringFunc\Mbstring;
use Thrift\StringFunc\Core;
class TStringFuncFactory
{
private static $_instance;
/**
* Get the Singleton instance of TStringFunc implementation that is
* compatible with the current system's mbstring.func_overload settings.
*
* @return TStringFunc
*/
public static function create()
{
if (!self::$_instance) {
self::_setInstance();
}
return self::$_instance;
}
private static function _setInstance()
{
/**
* Cannot use str* functions for byte counting because multibyte
* characters will be read a single bytes.
*
* See: http://us.php.net/manual/en/mbstring.overload.php
*/
if (ini_get('mbstring.func_overload') & 2) {
self::$_instance = new Mbstring();
}
/**
* mbstring is not installed or does not have function overloading
* of the str* functions enabled so use PHP core str* functions for
* byte counting.
*/
else {
self::$_instance = new Core();
}
}
}

View file

@ -0,0 +1,18 @@
<?php
namespace Thrift\Factory;
use Thrift\Transport\TTransport;
class TTransportFactory
{
/**
* @static
* @param TTransport $transport
* @return TTransport
*/
public static function getTransport(TTransport $transport)
{
return $transport;
}
}

View file

@ -0,0 +1,39 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol\JSON;
class BaseContext
{
public function escapeNum()
{
return false;
}
public function write()
{
}
public function read()
{
}
}

View file

@ -0,0 +1,54 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol\JSON;
use Thrift\Protocol\TJSONProtocol;
class ListContext extends BaseContext
{
private $first_ = true;
private $p_;
public function __construct($p)
{
$this->p_ = $p;
}
public function write()
{
if ($this->first_) {
$this->first_ = false;
} else {
$this->p_->getTransport()->write(TJSONProtocol::COMMA);
}
}
public function read()
{
if ($this->first_) {
$this->first_ = false;
} else {
$this->p_->readJSONSyntaxChar(TJSONProtocol::COMMA);
}
}
}

View file

@ -0,0 +1,57 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol\JSON;
class LookaheadReader
{
private $hasData_ = false;
private $data_ = array();
private $p_;
public function __construct($p)
{
$this->p_ = $p;
}
public function read()
{
if ($this->hasData_) {
$this->hasData_ = false;
} else {
$this->data_ = $this->p_->getTransport()->readAll(1);
}
return substr($this->data_, 0, 1);
}
public function peek()
{
if (!$this->hasData_) {
$this->data_ = $this->p_->getTransport()->readAll(1);
}
$this->hasData_ = true;
return substr($this->data_, 0, 1);
}
}

View file

@ -0,0 +1,64 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol\JSON;
use Thrift\Protocol\TJSONProtocol;
class PairContext extends BaseContext
{
private $first_ = true;
private $colon_ = true;
private $p_ = null;
public function __construct($p)
{
$this->p_ = $p;
}
public function write()
{
if ($this->first_) {
$this->first_ = false;
$this->colon_ = true;
} else {
$this->p_->getTransport()->write($this->colon_ ? TJSONProtocol::COLON : TJSONProtocol::COMMA);
$this->colon_ = !$this->colon_;
}
}
public function read()
{
if ($this->first_) {
$this->first_ = false;
$this->colon_ = true;
} else {
$this->p_->readJSONSyntaxChar($this->colon_ ? TJSONProtocol::COLON : TJSONProtocol::COMMA);
$this->colon_ = !$this->colon_;
}
}
public function escapeNum()
{
return $this->colon_;
}
}

View file

@ -0,0 +1,33 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol\SimpleJSON;
use Thrift\Exception\TException;
class CollectionMapKeyException extends TException
{
public function __construct($message)
{
parent::__construct($message);
}
}

View file

@ -0,0 +1,36 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol\SimpleJSON;
class Context
{
public function write()
{
}
public function isMapKey()
{
return false;
}
}

View file

@ -0,0 +1,45 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol\SimpleJSON;
use Thrift\Protocol\TSimpleJSONProtocol;
class ListContext extends Context
{
protected $first_ = true;
private $p_;
public function __construct($p)
{
$this->p_ = $p;
}
public function write()
{
if ($this->first_) {
$this->first_ = false;
} else {
$this->p_->getTransport()->write(TSimpleJSONProtocol::COMMA);
}
}
}

View file

@ -0,0 +1,51 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol\SimpleJSON;
use Thrift\Protocol\TSimpleJSONProtocol;
class MapContext extends StructContext
{
protected $isKey = true;
private $p_;
public function __construct($p)
{
parent::__construct($p);
}
public function write()
{
parent::write();
$this->isKey = !$this->isKey;
}
public function isMapKey()
{
// we want to coerce map keys to json strings regardless
// of their type
return $this->isKey;
}
}

View file

@ -0,0 +1,53 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol\SimpleJSON;
use Thrift\Protocol\TSimpleJSONProtocol;
class StructContext extends Context
{
protected $first_ = true;
protected $colon_ = true;
private $p_;
public function __construct($p)
{
$this->p_ = $p;
}
public function write()
{
if ($this->first_) {
$this->first_ = false;
$this->colon_ = true;
} else {
$this->p_->getTransport()->write(
$this->colon_ ?
TSimpleJSONProtocol::COLON :
TSimpleJSONProtocol::COMMA
);
$this->colon_ = !$this->colon_;
}
}
}

View file

@ -0,0 +1,453 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol;
use Thrift\Type\TType;
use Thrift\Exception\TProtocolException;
use Thrift\Factory\TStringFuncFactory;
/**
* Binary implementation of the Thrift protocol.
*
*/
class TBinaryProtocol extends TProtocol
{
const VERSION_MASK = 0xffff0000;
const VERSION_1 = 0x80010000;
protected $strictRead_ = false;
protected $strictWrite_ = true;
public function __construct($trans, $strictRead=false, $strictWrite=true)
{
parent::__construct($trans);
$this->strictRead_ = $strictRead;
$this->strictWrite_ = $strictWrite;
}
public function writeMessageBegin($name, $type, $seqid)
{
if ($this->strictWrite_) {
$version = self::VERSION_1 | $type;
return
$this->writeI32($version) +
$this->writeString($name) +
$this->writeI32($seqid);
} else {
return
$this->writeString($name) +
$this->writeByte($type) +
$this->writeI32($seqid);
}
}
public function writeMessageEnd()
{
return 0;
}
public function writeStructBegin($name)
{
return 0;
}
public function writeStructEnd()
{
return 0;
}
public function writeFieldBegin($fieldName, $fieldType, $fieldId)
{
return
$this->writeByte($fieldType) +
$this->writeI16($fieldId);
}
public function writeFieldEnd()
{
return 0;
}
public function writeFieldStop()
{
return
$this->writeByte(TType::STOP);
}
public function writeMapBegin($keyType, $valType, $size)
{
return
$this->writeByte($keyType) +
$this->writeByte($valType) +
$this->writeI32($size);
}
public function writeMapEnd()
{
return 0;
}
public function writeListBegin($elemType, $size)
{
return
$this->writeByte($elemType) +
$this->writeI32($size);
}
public function writeListEnd()
{
return 0;
}
public function writeSetBegin($elemType, $size)
{
return
$this->writeByte($elemType) +
$this->writeI32($size);
}
public function writeSetEnd()
{
return 0;
}
public function writeBool($value)
{
$data = pack('c', $value ? 1 : 0);
$this->trans_->write($data, 1);
return 1;
}
public function writeByte($value)
{
$data = pack('c', $value);
$this->trans_->write($data, 1);
return 1;
}
public function writeI16($value)
{
$data = pack('n', $value);
$this->trans_->write($data, 2);
return 2;
}
public function writeI32($value)
{
$data = pack('N', $value);
$this->trans_->write($data, 4);
return 4;
}
public function writeI64($value)
{
// If we are on a 32bit architecture we have to explicitly deal with
// 64-bit twos-complement arithmetic since PHP wants to treat all ints
// as signed and any int over 2^31 - 1 as a float
if (PHP_INT_SIZE == 4) {
$neg = $value < 0;
if ($neg) {
$value *= -1;
}
$hi = (int) ($value / 4294967296);
$lo = (int) $value;
if ($neg) {
$hi = ~$hi;
$lo = ~$lo;
if (($lo & (int) 0xffffffff) == (int) 0xffffffff) {
$lo = 0;
$hi++;
} else {
$lo++;
}
}
$data = pack('N2', $hi, $lo);
} else {
$hi = $value >> 32;
$lo = $value & 0xFFFFFFFF;
$data = pack('N2', $hi, $lo);
}
$this->trans_->write($data, 8);
return 8;
}
public function writeDouble($value)
{
$data = pack('d', $value);
$this->trans_->write(strrev($data), 8);
return 8;
}
public function writeString($value)
{
$len = TStringFuncFactory::create()->strlen($value);
$result = $this->writeI32($len);
if ($len) {
$this->trans_->write($value, $len);
}
return $result + $len;
}
public function readMessageBegin(&$name, &$type, &$seqid)
{
$result = $this->readI32($sz);
if ($sz < 0) {
$version = (int) ($sz & self::VERSION_MASK);
if ($version != (int) self::VERSION_1) {
throw new TProtocolException('Bad version identifier: '.$sz, TProtocolException::BAD_VERSION);
}
$type = $sz & 0x000000ff;
$result +=
$this->readString($name) +
$this->readI32($seqid);
} else {
if ($this->strictRead_) {
throw new TProtocolException('No version identifier, old protocol client?', TProtocolException::BAD_VERSION);
} else {
// Handle pre-versioned input
$name = $this->trans_->readAll($sz);
$result +=
$sz +
$this->readByte($type) +
$this->readI32($seqid);
}
}
return $result;
}
public function readMessageEnd()
{
return 0;
}
public function readStructBegin(&$name)
{
$name = '';
return 0;
}
public function readStructEnd()
{
return 0;
}
public function readFieldBegin(&$name, &$fieldType, &$fieldId)
{
$result = $this->readByte($fieldType);
if ($fieldType == TType::STOP) {
$fieldId = 0;
return $result;
}
$result += $this->readI16($fieldId);
return $result;
}
public function readFieldEnd()
{
return 0;
}
public function readMapBegin(&$keyType, &$valType, &$size)
{
return
$this->readByte($keyType) +
$this->readByte($valType) +
$this->readI32($size);
}
public function readMapEnd()
{
return 0;
}
public function readListBegin(&$elemType, &$size)
{
return
$this->readByte($elemType) +
$this->readI32($size);
}
public function readListEnd()
{
return 0;
}
public function readSetBegin(&$elemType, &$size)
{
return
$this->readByte($elemType) +
$this->readI32($size);
}
public function readSetEnd()
{
return 0;
}
public function readBool(&$value)
{
$data = $this->trans_->readAll(1);
$arr = unpack('c', $data);
$value = $arr[1] == 1;
return 1;
}
public function readByte(&$value)
{
$data = $this->trans_->readAll(1);
$arr = unpack('c', $data);
$value = $arr[1];
return 1;
}
public function readI16(&$value)
{
$data = $this->trans_->readAll(2);
$arr = unpack('n', $data);
$value = $arr[1];
if ($value > 0x7fff) {
$value = 0 - (($value - 1) ^ 0xffff);
}
return 2;
}
public function readI32(&$value)
{
$data = $this->trans_->readAll(4);
$arr = unpack('N', $data);
$value = $arr[1];
if ($value > 0x7fffffff) {
$value = 0 - (($value - 1) ^ 0xffffffff);
}
return 4;
}
public function readI64(&$value)
{
$data = $this->trans_->readAll(8);
$arr = unpack('N2', $data);
// If we are on a 32bit architecture we have to explicitly deal with
// 64-bit twos-complement arithmetic since PHP wants to treat all ints
// as signed and any int over 2^31 - 1 as a float
if (PHP_INT_SIZE == 4) {
$hi = $arr[1];
$lo = $arr[2];
$isNeg = $hi < 0;
// Check for a negative
if ($isNeg) {
$hi = ~$hi & (int) 0xffffffff;
$lo = ~$lo & (int) 0xffffffff;
if ($lo == (int) 0xffffffff) {
$hi++;
$lo = 0;
} else {
$lo++;
}
}
// Force 32bit words in excess of 2G to pe positive - we deal wigh sign
// explicitly below
if ($hi & (int) 0x80000000) {
$hi &= (int) 0x7fffffff;
$hi += 0x80000000;
}
if ($lo & (int) 0x80000000) {
$lo &= (int) 0x7fffffff;
$lo += 0x80000000;
}
$value = $hi * 4294967296 + $lo;
if ($isNeg) {
$value = 0 - $value;
}
} else {
// Upcast negatives in LSB bit
if ($arr[2] & 0x80000000) {
$arr[2] = $arr[2] & 0xffffffff;
}
// Check for a negative
if ($arr[1] & 0x80000000) {
$arr[1] = $arr[1] & 0xffffffff;
$arr[1] = $arr[1] ^ 0xffffffff;
$arr[2] = $arr[2] ^ 0xffffffff;
$value = 0 - $arr[1]*4294967296 - $arr[2] - 1;
} else {
$value = $arr[1]*4294967296 + $arr[2];
}
}
return 8;
}
public function readDouble(&$value)
{
$data = strrev($this->trans_->readAll(8));
$arr = unpack('d', $data);
$value = $arr[1];
return 8;
}
public function readString(&$value)
{
$result = $this->readI32($len);
if ($len) {
$value = $this->trans_->readAll($len);
} else {
$value = '';
}
return $result + $len;
}
}

View file

@ -0,0 +1,65 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol;
use Thrift\Transport\TBufferedTransport;
/**
* Accelerated binary protocol: used in conjunction with the thrift_protocol
* extension for faster deserialization
*/
class TBinaryProtocolAccelerated extends TBinaryProtocol
{
public function __construct($trans, $strictRead=false, $strictWrite=true)
{
// If the transport doesn't implement putBack, wrap it in a
// TBufferedTransport (which does)
// NOTE (t.heintz): This is very evil to do, because the TBufferedTransport may swallow bytes, which
// are then never written to the underlying transport. This happens precisely when a number of bytes
// less than the max buffer size (512 by default) is written to the transport and then flush() is NOT
// called. In that case the data stays in the writeBuffer of the transport, from where it can never be
// accessed again (for example through read()).
//
// Since the caller of this method does not know about the wrapping transport, this creates bugs which
// are very difficult to find. Hence the wrapping of a transport in a buffer should be left to the
// calling code. An interface could used to mandate the presence of the putBack() method in the transport.
//
// I am leaving this code in nonetheless, because there may be applications depending on this behavior.
//
// @see THRIFT-1579
if (!method_exists($trans, 'putBack')) {
$trans = new TBufferedTransport($trans);
}
parent::__construct($trans, $strictRead, $strictWrite);
}
public function isStrictRead()
{
return $this->strictRead_;
}
public function isStrictWrite()
{
return $this->strictWrite_;
}
}

View file

@ -0,0 +1,739 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol;
use Thrift\Type\TType;
use Thrift\Exception\TProtocolException;
use Thrift\Factory\TStringFuncFactory;
/**
* Compact implementation of the Thrift protocol.
*
*/
class TCompactProtocol extends TProtocol
{
const COMPACT_STOP = 0x00;
const COMPACT_TRUE = 0x01;
const COMPACT_FALSE = 0x02;
const COMPACT_BYTE = 0x03;
const COMPACT_I16 = 0x04;
const COMPACT_I32 = 0x05;
const COMPACT_I64 = 0x06;
const COMPACT_DOUBLE = 0x07;
const COMPACT_BINARY = 0x08;
const COMPACT_LIST = 0x09;
const COMPACT_SET = 0x0A;
const COMPACT_MAP = 0x0B;
const COMPACT_STRUCT = 0x0C;
const STATE_CLEAR = 0;
const STATE_FIELD_WRITE = 1;
const STATE_VALUE_WRITE = 2;
const STATE_CONTAINER_WRITE = 3;
const STATE_BOOL_WRITE = 4;
const STATE_FIELD_READ = 5;
const STATE_CONTAINER_READ = 6;
const STATE_VALUE_READ = 7;
const STATE_BOOL_READ = 8;
const VERSION_MASK = 0x1f;
const VERSION = 1;
const PROTOCOL_ID = 0x82;
const TYPE_MASK = 0xe0;
const TYPE_BITS = 0x07;
const TYPE_SHIFT_AMOUNT = 5;
protected static $ctypes = array(
TType::STOP => TCompactProtocol::COMPACT_STOP,
TType::BOOL => TCompactProtocol::COMPACT_TRUE, // used for collection
TType::BYTE => TCompactProtocol::COMPACT_BYTE,
TType::I16 => TCompactProtocol::COMPACT_I16,
TType::I32 => TCompactProtocol::COMPACT_I32,
TType::I64 => TCompactProtocol::COMPACT_I64,
TType::DOUBLE => TCompactProtocol::COMPACT_DOUBLE,
TType::STRING => TCompactProtocol::COMPACT_BINARY,
TType::STRUCT => TCompactProtocol::COMPACT_STRUCT,
TType::LST => TCompactProtocol::COMPACT_LIST,
TType::SET => TCompactProtocol::COMPACT_SET,
TType::MAP => TCompactProtocol::COMPACT_MAP,
);
protected static $ttypes = array(
TCompactProtocol::COMPACT_STOP => TType::STOP ,
TCompactProtocol::COMPACT_TRUE => TType::BOOL, // used for collection
TCompactProtocol::COMPACT_FALSE => TType::BOOL,
TCompactProtocol::COMPACT_BYTE => TType::BYTE,
TCompactProtocol::COMPACT_I16 => TType::I16,
TCompactProtocol::COMPACT_I32 => TType::I32,
TCompactProtocol::COMPACT_I64 => TType::I64,
TCompactProtocol::COMPACT_DOUBLE => TType::DOUBLE,
TCompactProtocol::COMPACT_BINARY => TType::STRING,
TCompactProtocol::COMPACT_STRUCT => TType::STRUCT,
TCompactProtocol::COMPACT_LIST => TType::LST,
TCompactProtocol::COMPACT_SET => TType::SET,
TCompactProtocol::COMPACT_MAP => TType::MAP,
);
protected $state = TCompactProtocol::STATE_CLEAR;
protected $lastFid = 0;
protected $boolFid = null;
protected $boolValue = null;
protected $structs = array();
protected $containers = array();
// Some varint / zigzag helper methods
public function toZigZag($n, $bits)
{
return ($n << 1) ^ ($n >> ($bits - 1));
}
public function fromZigZag($n)
{
return ($n >> 1) ^ -($n & 1);
}
public function getVarint($data)
{
$out = "";
while (true) {
if (($data & ~0x7f) === 0) {
$out .= chr($data);
break;
} else {
$out .= chr(($data & 0xff) | 0x80);
$data = $data >> 7;
}
}
return $out;
}
public function writeVarint($data)
{
$out = $this->getVarint($data);
$result = TStringFuncFactory::create()->strlen($out);
$this->trans_->write($out, $result);
return $result;
}
public function readVarint(&$result)
{
$idx = 0;
$shift = 0;
$result = 0;
while (true) {
$x = $this->trans_->readAll(1);
$arr = unpack('C', $x);
$byte = $arr[1];
$idx += 1;
$result |= ($byte & 0x7f) << $shift;
if (($byte >> 7) === 0) {
return $idx;
}
$shift += 7;
}
return $idx;
}
public function __construct($trans)
{
parent::__construct($trans);
}
public function writeMessageBegin($name, $type, $seqid)
{
$written =
$this->writeUByte(TCompactProtocol::PROTOCOL_ID) +
$this->writeUByte(TCompactProtocol::VERSION |
($type << TCompactProtocol::TYPE_SHIFT_AMOUNT)) +
$this->writeVarint($seqid) +
$this->writeString($name);
$this->state = TCompactProtocol::STATE_VALUE_WRITE;
return $written;
}
public function writeMessageEnd()
{
$this->state = TCompactProtocol::STATE_CLEAR;
return 0;
}
public function writeStructBegin($name)
{
$this->structs[] = array($this->state, $this->lastFid);
$this->state = TCompactProtocol::STATE_FIELD_WRITE;
$this->lastFid = 0;
return 0;
}
public function writeStructEnd()
{
$old_values = array_pop($this->structs);
$this->state = $old_values[0];
$this->lastFid = $old_values[1];
return 0;
}
public function writeFieldStop()
{
return $this->writeByte(0);
}
public function writeFieldHeader($type, $fid)
{
$written = 0;
$delta = $fid - $this->lastFid;
if (0 < $delta && $delta <= 15) {
$written = $this->writeUByte(($delta << 4) | $type);
} else {
$written = $this->writeByte($type) +
$this->writeI16($fid);
}
$this->lastFid = $fid;
return $written;
}
public function writeFieldBegin($field_name, $field_type, $field_id)
{
if ($field_type == TTYPE::BOOL) {
$this->state = TCompactProtocol::STATE_BOOL_WRITE;
$this->boolFid = $field_id;
return 0;
} else {
$this->state = TCompactProtocol::STATE_VALUE_WRITE;
return $this->writeFieldHeader(self::$ctypes[$field_type], $field_id);
}
}
public function writeFieldEnd()
{
$this->state = TCompactProtocol::STATE_FIELD_WRITE;
return 0;
}
public function writeCollectionBegin($etype, $size)
{
$written = 0;
if ($size <= 14) {
$written = $this->writeUByte($size << 4 |
self::$ctypes[$etype]);
} else {
$written = $this->writeUByte(0xf0 |
self::$ctypes[$etype]) +
$this->writeVarint($size);
}
$this->containers[] = $this->state;
$this->state = TCompactProtocol::STATE_CONTAINER_WRITE;
return $written;
}
public function writeMapBegin($key_type, $val_type, $size)
{
$written = 0;
if ($size == 0) {
$written = $this->writeByte(0);
} else {
$written = $this->writeVarint($size) +
$this->writeUByte(self::$ctypes[$key_type] << 4 |
self::$ctypes[$val_type]);
}
$this->containers[] = $this->state;
return $written;
}
public function writeCollectionEnd()
{
$this->state = array_pop($this->containers);
return 0;
}
public function writeMapEnd()
{
return $this->writeCollectionEnd();
}
public function writeListBegin($elem_type, $size)
{
return $this->writeCollectionBegin($elem_type, $size);
}
public function writeListEnd()
{
return $this->writeCollectionEnd();
}
public function writeSetBegin($elem_type, $size)
{
return $this->writeCollectionBegin($elem_type, $size);
}
public function writeSetEnd()
{
return $this->writeCollectionEnd();
}
public function writeBool($value)
{
if ($this->state == TCompactProtocol::STATE_BOOL_WRITE) {
$ctype = TCompactProtocol::COMPACT_FALSE;
if ($value) {
$ctype = TCompactProtocol::COMPACT_TRUE;
}
return $this->writeFieldHeader($ctype, $this->boolFid);
} elseif ($this->state == TCompactProtocol::STATE_CONTAINER_WRITE) {
return $this->writeByte($value ? 1 : 0);
} else {
throw new TProtocolException('Invalid state in compact protocol');
}
}
public function writeByte($value)
{
$data = pack('c', $value);
$this->trans_->write($data, 1);
return 1;
}
public function writeUByte($byte)
{
$this->trans_->write(pack('C', $byte), 1);
return 1;
}
public function writeI16($value)
{
$thing = $this->toZigZag($value, 16);
return $this->writeVarint($thing);
}
public function writeI32($value)
{
$thing = $this->toZigZag($value, 32);
return $this->writeVarint($thing);
}
public function writeDouble($value)
{
$data = pack('d', $value);
$this->trans_->write($data, 8);
return 8;
}
public function writeString($value)
{
$len = TStringFuncFactory::create()->strlen($value);
$result = $this->writeVarint($len);
if ($len) {
$this->trans_->write($value, $len);
}
return $result + $len;
}
public function readFieldBegin(&$name, &$field_type, &$field_id)
{
$result = $this->readUByte($compact_type_and_delta);
$compact_type = $compact_type_and_delta & 0x0f;
if ($compact_type == TType::STOP) {
$field_type = $compact_type;
$field_id = 0;
return $result;
}
$delta = $compact_type_and_delta >> 4;
if ($delta == 0) {
$result += $this->readI16($field_id);
} else {
$field_id = $this->lastFid + $delta;
}
$this->lastFid = $field_id;
$field_type = $this->getTType($compact_type);
if ($compact_type == TCompactProtocol::COMPACT_TRUE) {
$this->state = TCompactProtocol::STATE_BOOL_READ;
$this->boolValue = true;
} elseif ($compact_type == TCompactProtocol::COMPACT_FALSE) {
$this->state = TCompactProtocol::STATE_BOOL_READ;
$this->boolValue = false;
} else {
$this->state = TCompactProtocol::STATE_VALUE_READ;
}
return $result;
}
public function readFieldEnd()
{
$this->state = TCompactProtocol::STATE_FIELD_READ;
return 0;
}
public function readUByte(&$value)
{
$data = $this->trans_->readAll(1);
$arr = unpack('C', $data);
$value = $arr[1];
return 1;
}
public function readByte(&$value)
{
$data = $this->trans_->readAll(1);
$arr = unpack('c', $data);
$value = $arr[1];
return 1;
}
public function readZigZag(&$value)
{
$result = $this->readVarint($value);
$value = $this->fromZigZag($value);
return $result;
}
public function readMessageBegin(&$name, &$type, &$seqid)
{
$protoId = 0;
$result = $this->readUByte($protoId);
if ($protoId != TCompactProtocol::PROTOCOL_ID) {
throw new TProtocolException('Bad protocol id in TCompact message');
}
$verType = 0;
$result += $this->readUByte($verType);
$type = ($verType >> TCompactProtocol::TYPE_SHIFT_AMOUNT) & TCompactProtocol::TYPE_BITS;
$version = $verType & TCompactProtocol::VERSION_MASK;
if ($version != TCompactProtocol::VERSION) {
throw new TProtocolException('Bad version in TCompact message');
}
$result += $this->readVarint($seqid);
$result += $this->readString($name);
return $result;
}
public function readMessageEnd()
{
return 0;
}
public function readStructBegin(&$name)
{
$name = ''; // unused
$this->structs[] = array($this->state, $this->lastFid);
$this->state = TCompactProtocol::STATE_FIELD_READ;
$this->lastFid = 0;
return 0;
}
public function readStructEnd()
{
$last = array_pop($this->structs);
$this->state = $last[0];
$this->lastFid = $last[1];
return 0;
}
public function readCollectionBegin(&$type, &$size)
{
$sizeType = 0;
$result = $this->readUByte($sizeType);
$size = $sizeType >> 4;
$type = $this->getTType($sizeType);
if ($size == 15) {
$result += $this->readVarint($size);
}
$this->containers[] = $this->state;
$this->state = TCompactProtocol::STATE_CONTAINER_READ;
return $result;
}
public function readMapBegin(&$key_type, &$val_type, &$size)
{
$result = $this->readVarint($size);
$types = 0;
if ($size > 0) {
$result += $this->readUByte($types);
}
$val_type = $this->getTType($types);
$key_type = $this->getTType($types >> 4);
$this->containers[] = $this->state;
$this->state = TCompactProtocol::STATE_CONTAINER_READ;
return $result;
}
public function readCollectionEnd()
{
$this->state = array_pop($this->containers);
return 0;
}
public function readMapEnd()
{
return $this->readCollectionEnd();
}
public function readListBegin(&$elem_type, &$size)
{
return $this->readCollectionBegin($elem_type, $size);
}
public function readListEnd()
{
return $this->readCollectionEnd();
}
public function readSetBegin(&$elem_type, &$size)
{
return $this->readCollectionBegin($elem_type, $size);
}
public function readSetEnd()
{
return $this->readCollectionEnd();
}
public function readBool(&$value)
{
if ($this->state == TCompactProtocol::STATE_BOOL_READ) {
$value = $this->boolValue;
return 0;
} elseif ($this->state == TCompactProtocol::STATE_CONTAINER_READ) {
return $this->readByte($value);
} else {
throw new TProtocolException('Invalid state in compact protocol');
}
}
public function readI16(&$value)
{
return $this->readZigZag($value);
}
public function readI32(&$value)
{
return $this->readZigZag($value);
}
public function readDouble(&$value)
{
$data = $this->trans_->readAll(8);
$arr = unpack('d', $data);
$value = $arr[1];
return 8;
}
public function readString(&$value)
{
$result = $this->readVarint($len);
if ($len) {
$value = $this->trans_->readAll($len);
} else {
$value = '';
}
return $result + $len;
}
public function getTType($byte)
{
return self::$ttypes[$byte & 0x0f];
}
// If we are on a 32bit architecture we have to explicitly deal with
// 64-bit twos-complement arithmetic since PHP wants to treat all ints
// as signed and any int over 2^31 - 1 as a float
// Read and write I64 as two 32 bit numbers $hi and $lo
public function readI64(&$value)
{
// Read varint from wire
$hi = 0;
$lo = 0;
$idx = 0;
$shift = 0;
while (true) {
$x = $this->trans_->readAll(1);
$arr = unpack('C', $x);
$byte = $arr[1];
$idx += 1;
// Shift hi and lo together.
if ($shift < 28) {
$lo |= (($byte & 0x7f) << $shift);
} elseif ($shift == 28) {
$lo |= (($byte & 0x0f) << 28);
$hi |= (($byte & 0x70) >> 4);
} else {
$hi |= (($byte & 0x7f) << ($shift - 32));
}
if (($byte >> 7) === 0) {
break;
}
$shift += 7;
}
// Now, unzig it.
$xorer = 0;
if ($lo & 1) {
$xorer = 0xffffffff;
}
$lo = ($lo >> 1) & 0x7fffffff;
$lo = $lo | (($hi & 1) << 31);
$hi = ($hi >> 1) ^ $xorer;
$lo = $lo ^ $xorer;
// Now put $hi and $lo back together
$isNeg = $hi < 0 || $hi & 0x80000000;
// Check for a negative
if ($isNeg) {
$hi = ~$hi & (int) 0xffffffff;
$lo = ~$lo & (int) 0xffffffff;
if ($lo == (int) 0xffffffff) {
$hi++;
$lo = 0;
} else {
$lo++;
}
}
// Force 32bit words in excess of 2G to be positive - we deal with sign
// explicitly below
if ($hi & (int) 0x80000000) {
$hi &= (int) 0x7fffffff;
$hi += 0x80000000;
}
if ($lo & (int) 0x80000000) {
$lo &= (int) 0x7fffffff;
$lo += 0x80000000;
}
// Create as negative value first, since we can store -2^63 but not 2^63
$value = -$hi * 4294967296 - $lo;
if (!$isNeg) {
$value = -$value;
}
return $idx;
}
public function writeI64($value)
{
// If we are in an I32 range, use the easy method below.
if (($value > 4294967296) || ($value < -4294967296)) {
// Convert $value to $hi and $lo
$neg = $value < 0;
if ($neg) {
$value *= -1;
}
$hi = (int) $value >> 32;
$lo = (int) $value & 0xffffffff;
if ($neg) {
$hi = ~$hi;
$lo = ~$lo;
if (($lo & (int) 0xffffffff) == (int) 0xffffffff) {
$lo = 0;
$hi++;
} else {
$lo++;
}
}
// Now do the zigging and zagging.
$xorer = 0;
if ($neg) {
$xorer = 0xffffffff;
}
$lowbit = ($lo >> 31) & 1;
$hi = ($hi << 1) | $lowbit;
$lo = ($lo << 1);
$lo = ($lo ^ $xorer) & 0xffffffff;
$hi = ($hi ^ $xorer) & 0xffffffff;
// now write out the varint, ensuring we shift both hi and lo
$out = "";
while (true) {
if (($lo & ~0x7f) === 0 &&
$hi === 0) {
$out .= chr($lo);
break;
} else {
$out .= chr(($lo & 0xff) | 0x80);
$lo = $lo >> 7;
$lo = $lo | ($hi << 25);
$hi = $hi >> 7;
// Right shift carries sign, but we don't want it to.
$hi = $hi & (127 << 25);
}
}
$ret = TStringFuncFactory::create()->strlen($out);
$this->trans_->write($out, $ret);
return $ret;
} else {
return $this->writeVarint($this->toZigZag($value, 64));
}
}
}

View file

@ -0,0 +1,807 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol;
use Thrift\Type\TType;
use Thrift\Exception\TProtocolException;
use Thrift\Protocol\JSON\BaseContext;
use Thrift\Protocol\JSON\LookaheadReader;
use Thrift\Protocol\JSON\PairContext;
use Thrift\Protocol\JSON\ListContext;
/**
* JSON implementation of thrift protocol, ported from Java.
*/
class TJSONProtocol extends TProtocol
{
const COMMA = ',';
const COLON = ':';
const LBRACE = '{';
const RBRACE = '}';
const LBRACKET = '[';
const RBRACKET = ']';
const QUOTE = '"';
const BACKSLASH = '\\';
const ZERO = '0';
const ESCSEQ = '\\';
const DOUBLEESC = '__DOUBLE_ESCAPE_SEQUENCE__';
const VERSION = 1;
public static $JSON_CHAR_TABLE = array(
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, // 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
1, 1, '"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
);
public static $ESCAPE_CHARS = array('"', '\\', '/', "b", "f", "n", "r", "t");
public static $ESCAPE_CHAR_VALS = array(
'"', '\\', '/', "\x08", "\f", "\n", "\r", "\t",
);
const NAME_BOOL = "tf";
const NAME_BYTE = "i8";
const NAME_I16 = "i16";
const NAME_I32 = "i32";
const NAME_I64 = "i64";
const NAME_DOUBLE = "dbl";
const NAME_STRUCT = "rec";
const NAME_STRING = "str";
const NAME_MAP = "map";
const NAME_LIST = "lst";
const NAME_SET = "set";
private function getTypeNameForTypeID($typeID)
{
switch ($typeID) {
case TType::BOOL:
return self::NAME_BOOL;
case TType::BYTE:
return self::NAME_BYTE;
case TType::I16:
return self::NAME_I16;
case TType::I32:
return self::NAME_I32;
case TType::I64:
return self::NAME_I64;
case TType::DOUBLE:
return self::NAME_DOUBLE;
case TType::STRING:
return self::NAME_STRING;
case TType::STRUCT:
return self::NAME_STRUCT;
case TType::MAP:
return self::NAME_MAP;
case TType::SET:
return self::NAME_SET;
case TType::LST:
return self::NAME_LIST;
default:
throw new TProtocolException("Unrecognized type", TProtocolException::UNKNOWN);
}
}
private function getTypeIDForTypeName($name)
{
$result = TType::STOP;
if (strlen($name) > 1) {
switch (substr($name, 0, 1)) {
case 'd':
$result = TType::DOUBLE;
break;
case 'i':
switch (substr($name, 1, 1)) {
case '8':
$result = TType::BYTE;
break;
case '1':
$result = TType::I16;
break;
case '3':
$result = TType::I32;
break;
case '6':
$result = TType::I64;
break;
}
break;
case 'l':
$result = TType::LST;
break;
case 'm':
$result = TType::MAP;
break;
case 'r':
$result = TType::STRUCT;
break;
case 's':
if (substr($name, 1, 1) == 't') {
$result = TType::STRING;
} elseif (substr($name, 1, 1) == 'e') {
$result = TType::SET;
}
break;
case 't':
$result = TType::BOOL;
break;
}
}
if ($result == TType::STOP) {
throw new TProtocolException("Unrecognized type", TProtocolException::INVALID_DATA);
}
return $result;
}
public $contextStack_ = array();
public $context_;
public $reader_;
private function pushContext($c)
{
array_push($this->contextStack_, $this->context_);
$this->context_ = $c;
}
private function popContext()
{
$this->context_ = array_pop($this->contextStack_);
}
public function __construct($trans)
{
parent::__construct($trans);
$this->context_ = new BaseContext();
$this->reader_ = new LookaheadReader($this);
}
public function reset()
{
$this->contextStack_ = array();
$this->context_ = new BaseContext();
$this->reader_ = new LookaheadReader($this);
}
private $tmpbuf_ = array(4);
public function readJSONSyntaxChar($b)
{
$ch = $this->reader_->read();
if (substr($ch, 0, 1) != $b) {
throw new TProtocolException("Unexpected character: " . $ch, TProtocolException::INVALID_DATA);
}
}
private function hexVal($s)
{
for ($i = 0; $i < strlen($s); $i++) {
$ch = substr($s, $i, 1);
if (!($ch >= "a" && $ch <= "f") && !($ch >= "0" && $ch <= "9")) {
throw new TProtocolException("Expected hex character " . $ch, TProtocolException::INVALID_DATA);
}
}
return hexdec($s);
}
private function hexChar($val)
{
return dechex($val);
}
private function hasJSONUnescapedUnicode()
{
if (PHP_MAJOR_VERSION > 5
|| (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4))
return true;
return false;
}
private function unescapedUnicode($str)
{
if ($this->hasJSONUnescapedUnicode()) {
return json_encode($str, JSON_UNESCAPED_UNICODE);
}
$json = json_encode($str);
/*
* Unescaped character outside the Basic Multilingual Plane
* High surrogate: 0xD800 - 0xDBFF
* Low surrogate: 0xDC00 - 0xDFFF
*/
$json = preg_replace_callback('/\\\\u(d[89ab][0-9a-f]{2})\\\\u(d[cdef][0-9a-f]{2})/i',
function ($matches) {
return mb_convert_encoding(pack('H*', $matches[1].$matches[2]), 'UTF-8', 'UTF-16BE');
}, $json);
/*
* Unescaped characters within the Basic Multilingual Plane
*/
$json = preg_replace_callback('/\\\\u([0-9a-f]{4})/i',
function ($matches) {
return mb_convert_encoding(pack('H*', $matches[1]), 'UTF-8', 'UTF-16BE');
}, $json);
return $json;
}
private function writeJSONString($b)
{
$this->context_->write();
if (is_numeric($b) && $this->context_->escapeNum()) {
$this->trans_->write(self::QUOTE);
}
$this->trans_->write($this->unescapedUnicode($b));
if (is_numeric($b) && $this->context_->escapeNum()) {
$this->trans_->write(self::QUOTE);
}
}
private function writeJSONInteger($num)
{
$this->context_->write();
if ($this->context_->escapeNum()) {
$this->trans_->write(self::QUOTE);
}
$this->trans_->write($num);
if ($this->context_->escapeNum()) {
$this->trans_->write(self::QUOTE);
}
}
private function writeJSONDouble($num)
{
$this->context_->write();
if ($this->context_->escapeNum()) {
$this->trans_->write(self::QUOTE);
}
$this->trans_->write(json_encode($num));
if ($this->context_->escapeNum()) {
$this->trans_->write(self::QUOTE);
}
}
private function writeJSONBase64($data)
{
$this->context_->write();
$this->trans_->write(self::QUOTE);
$this->trans_->write(json_encode(base64_encode($data)));
$this->trans_->write(self::QUOTE);
}
private function writeJSONObjectStart()
{
$this->context_->write();
$this->trans_->write(self::LBRACE);
$this->pushContext(new PairContext($this));
}
private function writeJSONObjectEnd()
{
$this->popContext();
$this->trans_->write(self::RBRACE);
}
private function writeJSONArrayStart()
{
$this->context_->write();
$this->trans_->write(self::LBRACKET);
$this->pushContext(new ListContext($this));
}
private function writeJSONArrayEnd()
{
$this->popContext();
$this->trans_->write(self::RBRACKET);
}
private function readJSONString($skipContext)
{
if (!$skipContext) {
$this->context_->read();
}
$jsonString = '';
$lastChar = null;
while (true) {
$ch = $this->reader_->read();
$jsonString .= $ch;
if ($ch == self::QUOTE &&
$lastChar !== NULL &&
$lastChar !== self::ESCSEQ) {
break;
}
if ($ch == self::ESCSEQ && $lastChar == self::ESCSEQ) {
$lastChar = self::DOUBLEESC;
} else {
$lastChar = $ch;
}
}
return json_decode($jsonString);
}
private function isJSONNumeric($b)
{
switch ($b) {
case '+':
case '-':
case '.':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'E':
case 'e':
return true;
}
return false;
}
private function readJSONNumericChars()
{
$strbld = array();
while (true) {
$ch = $this->reader_->peek();
if (!$this->isJSONNumeric($ch)) {
break;
}
$strbld[] = $this->reader_->read();
}
return implode("", $strbld);
}
private function readJSONInteger()
{
$this->context_->read();
if ($this->context_->escapeNum()) {
$this->readJSONSyntaxChar(self::QUOTE);
}
$str = $this->readJSONNumericChars();
if ($this->context_->escapeNum()) {
$this->readJSONSyntaxChar(self::QUOTE);
}
if (!is_numeric($str)) {
throw new TProtocolException("Invalid data in numeric: " . $str, TProtocolException::INVALID_DATA);
}
return intval($str);
}
/**
* Identical to readJSONInteger but without the final cast.
* Needed for proper handling of i64 on 32 bit machines. Why a
* separate function? So we don't have to force the rest of the
* use cases through the extra conditional.
*/
private function readJSONIntegerAsString()
{
$this->context_->read();
if ($this->context_->escapeNum()) {
$this->readJSONSyntaxChar(self::QUOTE);
}
$str = $this->readJSONNumericChars();
if ($this->context_->escapeNum()) {
$this->readJSONSyntaxChar(self::QUOTE);
}
if (!is_numeric($str)) {
throw new TProtocolException("Invalid data in numeric: " . $str, TProtocolException::INVALID_DATA);
}
return $str;
}
private function readJSONDouble()
{
$this->context_->read();
if (substr($this->reader_->peek(), 0, 1) == self::QUOTE) {
$arr = $this->readJSONString(true);
if ($arr == "NaN") {
return NAN;
} elseif ($arr == "Infinity") {
return INF;
} elseif (!$this->context_->escapeNum()) {
throw new TProtocolException("Numeric data unexpectedly quoted " . $arr,
TProtocolException::INVALID_DATA);
}
return floatval($arr);
} else {
if ($this->context_->escapeNum()) {
$this->readJSONSyntaxChar(self::QUOTE);
}
return floatval($this->readJSONNumericChars());
}
}
private function readJSONBase64()
{
$arr = $this->readJSONString(false);
$data = base64_decode($arr, true);
if ($data === false) {
throw new TProtocolException("Invalid base64 data " . $arr, TProtocolException::INVALID_DATA);
}
return $data;
}
private function readJSONObjectStart()
{
$this->context_->read();
$this->readJSONSyntaxChar(self::LBRACE);
$this->pushContext(new PairContext($this));
}
private function readJSONObjectEnd()
{
$this->readJSONSyntaxChar(self::RBRACE);
$this->popContext();
}
private function readJSONArrayStart()
{
$this->context_->read();
$this->readJSONSyntaxChar(self::LBRACKET);
$this->pushContext(new ListContext($this));
}
private function readJSONArrayEnd()
{
$this->readJSONSyntaxChar(self::RBRACKET);
$this->popContext();
}
/**
* Writes the message header
*
* @param string $name Function name
* @param int $type message type TMessageType::CALL or TMessageType::REPLY
* @param int $seqid The sequence id of this message
*/
public function writeMessageBegin($name, $type, $seqid)
{
$this->writeJSONArrayStart();
$this->writeJSONInteger(self::VERSION);
$this->writeJSONString($name);
$this->writeJSONInteger($type);
$this->writeJSONInteger($seqid);
}
/**
* Close the message
*/
public function writeMessageEnd()
{
$this->writeJSONArrayEnd();
}
/**
* Writes a struct header.
*
* @param string $name Struct name
* @throws TException on write error
* @return int How many bytes written
*/
public function writeStructBegin($name)
{
$this->writeJSONObjectStart();
}
/**
* Close a struct.
*
* @throws TException on write error
* @return int How many bytes written
*/
public function writeStructEnd()
{
$this->writeJSONObjectEnd();
}
public function writeFieldBegin($fieldName, $fieldType, $fieldId)
{
$this->writeJSONInteger($fieldId);
$this->writeJSONObjectStart();
$this->writeJSONString($this->getTypeNameForTypeID($fieldType));
}
public function writeFieldEnd()
{
$this->writeJsonObjectEnd();
}
public function writeFieldStop()
{
}
public function writeMapBegin($keyType, $valType, $size)
{
$this->writeJSONArrayStart();
$this->writeJSONString($this->getTypeNameForTypeID($keyType));
$this->writeJSONString($this->getTypeNameForTypeID($valType));
$this->writeJSONInteger($size);
$this->writeJSONObjectStart();
}
public function writeMapEnd()
{
$this->writeJSONObjectEnd();
$this->writeJSONArrayEnd();
}
public function writeListBegin($elemType, $size)
{
$this->writeJSONArrayStart();
$this->writeJSONString($this->getTypeNameForTypeID($elemType));
$this->writeJSONInteger($size);
}
public function writeListEnd()
{
$this->writeJSONArrayEnd();
}
public function writeSetBegin($elemType, $size)
{
$this->writeJSONArrayStart();
$this->writeJSONString($this->getTypeNameForTypeID($elemType));
$this->writeJSONInteger($size);
}
public function writeSetEnd()
{
$this->writeJSONArrayEnd();
}
public function writeBool($bool)
{
$this->writeJSONInteger($bool ? 1 : 0);
}
public function writeByte($byte)
{
$this->writeJSONInteger($byte);
}
public function writeI16($i16)
{
$this->writeJSONInteger($i16);
}
public function writeI32($i32)
{
$this->writeJSONInteger($i32);
}
public function writeI64($i64)
{
$this->writeJSONInteger($i64);
}
public function writeDouble($dub)
{
$this->writeJSONDouble($dub);
}
public function writeString($str)
{
$this->writeJSONString($str);
}
/**
* Reads the message header
*
* @param string $name Function name
* @param int $type message type TMessageType::CALL or TMessageType::REPLY
* @parem int $seqid The sequence id of this message
*/
public function readMessageBegin(&$name, &$type, &$seqid)
{
$this->readJSONArrayStart();
if ($this->readJSONInteger() != self::VERSION) {
throw new TProtocolException("Message contained bad version", TProtocolException::BAD_VERSION);
}
$name = $this->readJSONString(false);
$type = $this->readJSONInteger();
$seqid = $this->readJSONInteger();
return true;
}
/**
* Read the close of message
*/
public function readMessageEnd()
{
$this->readJSONArrayEnd();
}
public function readStructBegin(&$name)
{
$this->readJSONObjectStart();
return 0;
}
public function readStructEnd()
{
$this->readJSONObjectEnd();
}
public function readFieldBegin(&$name, &$fieldType, &$fieldId)
{
$ch = $this->reader_->peek();
$name = "";
if (substr($ch, 0, 1) == self::RBRACE) {
$fieldType = TType::STOP;
} else {
$fieldId = $this->readJSONInteger();
$this->readJSONObjectStart();
$fieldType = $this->getTypeIDForTypeName($this->readJSONString(false));
}
}
public function readFieldEnd()
{
$this->readJSONObjectEnd();
}
public function readMapBegin(&$keyType, &$valType, &$size)
{
$this->readJSONArrayStart();
$keyType = $this->getTypeIDForTypeName($this->readJSONString(false));
$valType = $this->getTypeIDForTypeName($this->readJSONString(false));
$size = $this->readJSONInteger();
$this->readJSONObjectStart();
}
public function readMapEnd()
{
$this->readJSONObjectEnd();
$this->readJSONArrayEnd();
}
public function readListBegin(&$elemType, &$size)
{
$this->readJSONArrayStart();
$elemType = $this->getTypeIDForTypeName($this->readJSONString(false));
$size = $this->readJSONInteger();
return true;
}
public function readListEnd()
{
$this->readJSONArrayEnd();
}
public function readSetBegin(&$elemType, &$size)
{
$this->readJSONArrayStart();
$elemType = $this->getTypeIDForTypeName($this->readJSONString(false));
$size = $this->readJSONInteger();
return true;
}
public function readSetEnd()
{
$this->readJSONArrayEnd();
}
public function readBool(&$bool)
{
$bool = $this->readJSONInteger() == 0 ? false : true;
return true;
}
public function readByte(&$byte)
{
$byte = $this->readJSONInteger();
return true;
}
public function readI16(&$i16)
{
$i16 = $this->readJSONInteger();
return true;
}
public function readI32(&$i32)
{
$i32 = $this->readJSONInteger();
return true;
}
public function readI64(&$i64)
{
if (PHP_INT_SIZE === 4) {
$i64 = $this->readJSONIntegerAsString();
} else {
$i64 = $this->readJSONInteger();
}
return true;
}
public function readDouble(&$dub)
{
$dub = $this->readJSONDouble();
return true;
}
public function readString(&$str)
{
$str = $this->readJSONString(false);
return true;
}
}

View file

@ -0,0 +1,85 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol;
use Thrift\Type\TMessageType;
/**
* <code>TMultiplexedProtocol</code> is a protocol-independent concrete decorator
* that allows a Thrift client to communicate with a multiplexing Thrift server,
* by prepending the service name to the function name during function calls.
*
* @package Thrift\Protocol
*/
class TMultiplexedProtocol extends TProtocolDecorator
{
/**
* Separator between service name and function name.
* Should be the same as used at multiplexed Thrift server.
*
* @var string
*/
const SEPARATOR = ":";
/**
* The name of service.
*
* @var string
*/
private $serviceName_;
/**
* Constructor of <code>TMultiplexedProtocol</code> class.
*
* Wrap the specified protocol, allowing it to be used to communicate with a
* multiplexing server. The <code>$serviceName</code> is required as it is
* prepended to the message header so that the multiplexing server can broker
* the function call to the proper service.
*
* @param TProtocol $protocol
* @param string $serviceName The name of service.
*/
public function __construct(TProtocol $protocol, $serviceName)
{
parent::__construct($protocol);
$this->serviceName_ = $serviceName;
}
/**
* Writes the message header.
* Prepends the service name to the function name, separated by <code>TMultiplexedProtocol::SEPARATOR</code>.
*
* @param string $name Function name.
* @param int $type Message type.
* @param int $seqid The sequence id of this message.
*/
public function writeMessageBegin($name, $type, $seqid)
{
if ($type == TMessageType::CALL || $type == TMessageType::ONEWAY) {
$nameWithService = $this->serviceName_ . self::SEPARATOR . $name;
parent::writeMessageBegin($nameWithService, $type, $seqid);
} else {
parent::writeMessageBegin($name, $type, $seqid);
}
}
}

View file

@ -0,0 +1,352 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol;
use Thrift\Type\TType;
use Thrift\Exception\TProtocolException;
/**
* Protocol base class module.
*/
abstract class TProtocol
{
/**
* Underlying transport
*
* @var TTransport
*/
protected $trans_;
/**
* Constructor
*/
protected function __construct($trans)
{
$this->trans_ = $trans;
}
/**
* Accessor for transport
*
* @return TTransport
*/
public function getTransport()
{
return $this->trans_;
}
/**
* Writes the message header
*
* @param string $name Function name
* @param int $type message type TMessageType::CALL or TMessageType::REPLY
* @param int $seqid The sequence id of this message
*/
abstract public function writeMessageBegin($name, $type, $seqid);
/**
* Close the message
*/
abstract public function writeMessageEnd();
/**
* Writes a struct header.
*
* @param string $name Struct name
* @throws TException on write error
* @return int How many bytes written
*/
abstract public function writeStructBegin($name);
/**
* Close a struct.
*
* @throws TException on write error
* @return int How many bytes written
*/
abstract public function writeStructEnd();
/*
* Starts a field.
*
* @param string $name Field name
* @param int $type Field type
* @param int $fid Field id
* @throws TException on write error
* @return int How many bytes written
*/
abstract public function writeFieldBegin($fieldName, $fieldType, $fieldId);
abstract public function writeFieldEnd();
abstract public function writeFieldStop();
abstract public function writeMapBegin($keyType, $valType, $size);
abstract public function writeMapEnd();
abstract public function writeListBegin($elemType, $size);
abstract public function writeListEnd();
abstract public function writeSetBegin($elemType, $size);
abstract public function writeSetEnd();
abstract public function writeBool($bool);
abstract public function writeByte($byte);
abstract public function writeI16($i16);
abstract public function writeI32($i32);
abstract public function writeI64($i64);
abstract public function writeDouble($dub);
abstract public function writeString($str);
/**
* Reads the message header
*
* @param string $name Function name
* @param int $type message type TMessageType::CALL or TMessageType::REPLY
* @parem int $seqid The sequence id of this message
*/
abstract public function readMessageBegin(&$name, &$type, &$seqid);
/**
* Read the close of message
*/
abstract public function readMessageEnd();
abstract public function readStructBegin(&$name);
abstract public function readStructEnd();
abstract public function readFieldBegin(&$name, &$fieldType, &$fieldId);
abstract public function readFieldEnd();
abstract public function readMapBegin(&$keyType, &$valType, &$size);
abstract public function readMapEnd();
abstract public function readListBegin(&$elemType, &$size);
abstract public function readListEnd();
abstract public function readSetBegin(&$elemType, &$size);
abstract public function readSetEnd();
abstract public function readBool(&$bool);
abstract public function readByte(&$byte);
abstract public function readI16(&$i16);
abstract public function readI32(&$i32);
abstract public function readI64(&$i64);
abstract public function readDouble(&$dub);
abstract public function readString(&$str);
/**
* The skip function is a utility to parse over unrecognized date without
* causing corruption.
*
* @param TType $type What type is it
*/
public function skip($type)
{
switch ($type) {
case TType::BOOL:
return $this->readBool($bool);
case TType::BYTE:
return $this->readByte($byte);
case TType::I16:
return $this->readI16($i16);
case TType::I32:
return $this->readI32($i32);
case TType::I64:
return $this->readI64($i64);
case TType::DOUBLE:
return $this->readDouble($dub);
case TType::STRING:
return $this->readString($str);
case TType::STRUCT:
{
$result = $this->readStructBegin($name);
while (true) {
$result += $this->readFieldBegin($name, $ftype, $fid);
if ($ftype == TType::STOP) {
break;
}
$result += $this->skip($ftype);
$result += $this->readFieldEnd();
}
$result += $this->readStructEnd();
return $result;
}
case TType::MAP:
{
$result = $this->readMapBegin($keyType, $valType, $size);
for ($i = 0; $i < $size; $i++) {
$result += $this->skip($keyType);
$result += $this->skip($valType);
}
$result += $this->readMapEnd();
return $result;
}
case TType::SET:
{
$result = $this->readSetBegin($elemType, $size);
for ($i = 0; $i < $size; $i++) {
$result += $this->skip($elemType);
}
$result += $this->readSetEnd();
return $result;
}
case TType::LST:
{
$result = $this->readListBegin($elemType, $size);
for ($i = 0; $i < $size; $i++) {
$result += $this->skip($elemType);
}
$result += $this->readListEnd();
return $result;
}
default:
throw new TProtocolException('Unknown field type: '.$type,
TProtocolException::INVALID_DATA);
}
}
/**
* 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 = $itrans->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:
throw new TProtocolException('Unknown field type: '.$type,
TProtocolException::INVALID_DATA);
}
}
}

View file

@ -0,0 +1,284 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol;
use Thrift\Exception\TException;
/**
* <code>TProtocolDecorator</code> forwards all requests to an enclosed
* <code>TProtocol</code> instance, providing a way to author concise
* concrete decorator subclasses. While it has no abstract methods, it
* is marked abstract as a reminder that by itself, it does not modify
* the behaviour of the enclosed <code>TProtocol</code>.
*
* @package Thrift\Protocol
*/
abstract class TProtocolDecorator extends TProtocol
{
/**
* Instance of protocol, to which all operations will be forwarded.
*
* @var TProtocol
*/
private $concreteProtocol_;
/**
* Constructor of <code>TProtocolDecorator</code> class.
* Encloses the specified protocol.
*
* @param TProtocol $protocol All operations will be forward to this instance. Must be non-null.
*/
protected function __construct(TProtocol $protocol)
{
parent::__construct($protocol->getTransport());
$this->concreteProtocol_ = $protocol;
}
/**
* Writes the message header.
*
* @param string $name Function name
* @param int $type message type TMessageType::CALL or TMessageType::REPLY
* @param int $seqid The sequence id of this message
*/
public function writeMessageBegin($name, $type, $seqid)
{
return $this->concreteProtocol_->writeMessageBegin($name, $type, $seqid);
}
/**
* Closes the message.
*/
public function writeMessageEnd()
{
return $this->concreteProtocol_->writeMessageEnd();
}
/**
* Writes a struct header.
*
* @param string $name Struct name
*
* @throws TException on write error
* @return int How many bytes written
*/
public function writeStructBegin($name)
{
return $this->concreteProtocol_->writeStructBegin($name);
}
/**
* Close a struct.
*
* @throws TException on write error
* @return int How many bytes written
*/
public function writeStructEnd()
{
return $this->concreteProtocol_->writeStructEnd();
}
public function writeFieldBegin($fieldName, $fieldType, $fieldId)
{
return $this->concreteProtocol_->writeFieldBegin($fieldName, $fieldType, $fieldId);
}
public function writeFieldEnd()
{
return $this->concreteProtocol_->writeFieldEnd();
}
public function writeFieldStop()
{
return $this->concreteProtocol_->writeFieldStop();
}
public function writeMapBegin($keyType, $valType, $size)
{
return $this->concreteProtocol_->writeMapBegin($keyType, $valType, $size);
}
public function writeMapEnd()
{
return $this->concreteProtocol_->writeMapEnd();
}
public function writeListBegin($elemType, $size)
{
return $this->concreteProtocol_->writeListBegin($elemType, $size);
}
public function writeListEnd()
{
return $this->concreteProtocol_->writeListEnd();
}
public function writeSetBegin($elemType, $size)
{
return $this->concreteProtocol_->writeSetBegin($elemType, $size);
}
public function writeSetEnd()
{
return $this->concreteProtocol_->writeSetEnd();
}
public function writeBool($bool)
{
return $this->concreteProtocol_->writeBool($bool);
}
public function writeByte($byte)
{
return $this->concreteProtocol_->writeByte($byte);
}
public function writeI16($i16)
{
return $this->concreteProtocol_->writeI16($i16);
}
public function writeI32($i32)
{
return $this->concreteProtocol_->writeI32($i32);
}
public function writeI64($i64)
{
return $this->concreteProtocol_->writeI64($i64);
}
public function writeDouble($dub)
{
return $this->concreteProtocol_->writeDouble($dub);
}
public function writeString($str)
{
return $this->concreteProtocol_->writeString($str);
}
/**
* Reads the message header
*
* @param string $name Function name
* @param int $type message type TMessageType::CALL or TMessageType::REPLY
* @param int $seqid The sequence id of this message
*/
public function readMessageBegin(&$name, &$type, &$seqid)
{
return $this->concreteProtocol_->readMessageBegin($name, $type, $seqid);
}
/**
* Read the close of message
*/
public function readMessageEnd()
{
return $this->concreteProtocol_->readMessageEnd();
}
public function readStructBegin(&$name)
{
return $this->concreteProtocol_->readStructBegin($name);
}
public function readStructEnd()
{
return $this->concreteProtocol_->readStructEnd();
}
public function readFieldBegin(&$name, &$fieldType, &$fieldId)
{
return $this->concreteProtocol_->readFieldBegin($name, $fieldType, $fieldId);
}
public function readFieldEnd()
{
return $this->concreteProtocol_->readFieldEnd();
}
public function readMapBegin(&$keyType, &$valType, &$size)
{
$this->concreteProtocol_->readMapBegin($keyType, $valType, $size);
}
public function readMapEnd()
{
return $this->concreteProtocol_->readMapEnd();
}
public function readListBegin(&$elemType, &$size)
{
$this->concreteProtocol_->readListBegin($elemType, $size);
}
public function readListEnd()
{
return $this->concreteProtocol_->readListEnd();
}
public function readSetBegin(&$elemType, &$size)
{
return $this->concreteProtocol_->readSetBegin($elemType, $size);
}
public function readSetEnd()
{
return $this->concreteProtocol_->readSetEnd();
}
public function readBool(&$bool)
{
return $this->concreteProtocol_->readBool($bool);
}
public function readByte(&$byte)
{
return $this->concreteProtocol_->readByte($byte);
}
public function readI16(&$i16)
{
return $this->concreteProtocol_->readI16($i16);
}
public function readI32(&$i32)
{
return $this->concreteProtocol_->readI32($i32);
}
public function readI64(&$i64)
{
return $this->concreteProtocol_->readI64($i64);
}
public function readDouble(&$dub)
{
return $this->concreteProtocol_->readDouble($dub);
}
public function readString(&$str)
{
return $this->concreteProtocol_->readString($str);
}
}

View file

@ -0,0 +1,371 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol;
use Thrift\Exception\TException;
use Thrift\Exception\TProtocolException;
use Thrift\Protocol\SimpleJSON\Context;
use Thrift\Protocol\SimpleJSON\ListContext;
use Thrift\Protocol\SimpleJSON\StructContext;
use Thrift\Protocol\SimpleJSON\MapContext;
use Thrift\Protocol\SimpleJSON\CollectionMapKeyException;
/**
* SimpleJSON implementation of thrift protocol, ported from Java.
*/
class TSimpleJSONProtocol extends TProtocol
{
const COMMA = ',';
const COLON = ':';
const LBRACE = '{';
const RBRACE = '}';
const LBRACKET = '[';
const RBRACKET = ']';
const QUOTE = '"';
const NAME_MAP = "map";
const NAME_LIST = "lst";
const NAME_SET = "set";
protected $writeContext_ = null;
protected $writeContextStack_ = [];
/**
* Push a new write context onto the stack.
*/
protected function pushWriteContext(Context $c) {
$this->writeContextStack_[] = $this->writeContext_;
$this->writeContext_ = $c;
}
/**
* Pop the last write context off the stack
*/
protected function popWriteContext() {
$this->writeContext_ = array_pop($this->writeContextStack_);
}
/**
* Used to make sure that we are not encountering a map whose keys are containers
*/
protected function assertContextIsNotMapKey($invalidKeyType) {
if ($this->writeContext_->isMapKey()) {
throw new CollectionMapKeyException(
"Cannot serialize a map with keys that are of type " .
$invalidKeyType
);
}
}
private function writeJSONString($b)
{
$this->writeContext_->write();
$this->trans_->write(json_encode((string)$b));
}
private function writeJSONInteger($num)
{
$isMapKey = $this->writeContext_->isMapKey();
$this->writeContext_->write();
if ($isMapKey) {
$this->trans_->write(self::QUOTE);
}
$this->trans_->write((int)$num);
if ($isMapKey) {
$this->trans_->write(self::QUOTE);
}
}
private function writeJSONDouble($num)
{
$isMapKey = $this->writeContext_->isMapKey();
$this->writeContext_->write();
if ($isMapKey) {
$this->trans_->write(self::QUOTE);
}
$this->trans_->write(json_encode((float)$num));
if ($isMapKey) {
$this->trans_->write(self::QUOTE);
}
}
/**
* Constructor
*/
public function __construct($trans)
{
parent::__construct($trans);
$this->writeContext_ = new Context();
}
/**
* Writes the message header
*
* @param string $name Function name
* @param int $type message type TMessageType::CALL or TMessageType::REPLY
* @param int $seqid The sequence id of this message
*/
public function writeMessageBegin($name, $type, $seqid)
{
$this->trans_->write(self::LBRACKET);
$this->pushWriteContext(new ListContext($this));
$this->writeJSONString($name);
$this->writeJSONInteger($type);
$this->writeJSONInteger($seqid);
}
/**
* Close the message
*/
public function writeMessageEnd()
{
$this->popWriteContext();
$this->trans_->write(self::RBRACKET);
}
/**
* Writes a struct header.
*
* @param string $name Struct name
*/
public function writeStructBegin($name)
{
$this->writeContext_->write();
$this->trans_->write(self::LBRACE);
$this->pushWriteContext(new StructContext($this));
}
/**
* Close a struct.
*/
public function writeStructEnd()
{
$this->popWriteContext();
$this->trans_->write(self::RBRACE);
}
public function writeFieldBegin($fieldName, $fieldType, $fieldId)
{
$this->writeJSONString($fieldName);
}
public function writeFieldEnd()
{
}
public function writeFieldStop()
{
}
public function writeMapBegin($keyType, $valType, $size)
{
$this->assertContextIsNotMapKey(self::NAME_MAP);
$this->writeContext_->write();
$this->trans_->write(self::LBRACE);
$this->pushWriteContext(new MapContext($this));
}
public function writeMapEnd()
{
$this->popWriteContext();
$this->trans_->write(self::RBRACE);
}
public function writeListBegin($elemType, $size)
{
$this->assertContextIsNotMapKey(self::NAME_LIST);
$this->writeContext_->write();
$this->trans_->write(self::LBRACKET);
$this->pushWriteContext(new ListContext($this));
// No metadata!
}
public function writeListEnd()
{
$this->popWriteContext();
$this->trans_->write(self::RBRACKET);
}
public function writeSetBegin($elemType, $size)
{
$this->assertContextIsNotMapKey(self::NAME_SET);
$this->writeContext_->write();
$this->trans_->write(self::LBRACKET);
$this->pushWriteContext(new ListContext($this));
// No metadata!
}
public function writeSetEnd()
{
$this->popWriteContext();
$this->trans_->write(self::RBRACKET);
}
public function writeBool($bool)
{
$this->writeJSONInteger($bool ? 1 : 0);
}
public function writeByte($byte)
{
$this->writeJSONInteger($byte);
}
public function writeI16($i16)
{
$this->writeJSONInteger($i16);
}
public function writeI32($i32)
{
$this->writeJSONInteger($i32);
}
public function writeI64($i64)
{
$this->writeJSONInteger($i64);
}
public function writeDouble($dub)
{
$this->writeJSONDouble($dub);
}
public function writeString($str)
{
$this->writeJSONString($str);
}
/**
* Reading methods.
*
* simplejson is not meant to be read back into thrift
* - see http://wiki.apache.org/thrift/ThriftUsageJava
* - use JSON instead
*/
public function readMessageBegin(&$name, &$type, &$seqid)
{
throw new TException("Not implemented");
}
public function readMessageEnd()
{
throw new TException("Not implemented");
}
public function readStructBegin(&$name)
{
throw new TException("Not implemented");
}
public function readStructEnd()
{
throw new TException("Not implemented");
}
public function readFieldBegin(&$name, &$fieldType, &$fieldId)
{
throw new TException("Not implemented");
}
public function readFieldEnd()
{
throw new TException("Not implemented");
}
public function readMapBegin(&$keyType, &$valType, &$size)
{
throw new TException("Not implemented");
}
public function readMapEnd()
{
throw new TException("Not implemented");
}
public function readListBegin(&$elemType, &$size)
{
throw new TException("Not implemented");
}
public function readListEnd()
{
throw new TException("Not implemented");
}
public function readSetBegin(&$elemType, &$size)
{
throw new TException("Not implemented");
}
public function readSetEnd()
{
throw new TException("Not implemented");
}
public function readBool(&$bool)
{
throw new TException("Not implemented");
}
public function readByte(&$byte)
{
throw new TException("Not implemented");
}
public function readI16(&$i16)
{
throw new TException("Not implemented");
}
public function readI32(&$i32)
{
throw new TException("Not implemented");
}
public function readI64(&$i64)
{
throw new TException("Not implemented");
}
public function readDouble(&$dub)
{
throw new TException("Not implemented");
}
public function readString(&$str)
{
throw new TException("Not implemented");
}
}

View file

@ -0,0 +1,85 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
* @author: rmarin (marin.radu@facebook.com)
*/
namespace Thrift\Serializer;
use Thrift\Transport\TMemoryBuffer;
use Thrift\Protocol\TBinaryProtocolAccelerated;
use Thrift\Type\TMessageType;
/**
* Utility class for serializing and deserializing
* a thrift object using TBinaryProtocolAccelerated.
*/
class TBinarySerializer
{
// NOTE(rmarin): Because thrift_protocol_write_binary
// adds a begin message prefix, you cannot specify
// a transport in which to serialize an object. It has to
// be a string. Otherwise we will break the compatibility with
// normal deserialization.
public static function serialize($object)
{
$transport = new TMemoryBuffer();
$protocol = new TBinaryProtocolAccelerated($transport);
if (function_exists('thrift_protocol_write_binary')) {
thrift_protocol_write_binary($protocol, $object->getName(),
TMessageType::REPLY, $object,
0, $protocol->isStrictWrite());
$protocol->readMessageBegin($unused_name, $unused_type,
$unused_seqid);
} else {
$object->write($protocol);
}
$protocol->getTransport()->flush();
return $transport->getBuffer();
}
public static function deserialize($string_object, $class_name, $buffer_size = 8192)
{
$transport = new TMemoryBuffer();
$protocol = new TBinaryProtocolAccelerated($transport);
if (function_exists('thrift_protocol_read_binary')) {
// NOTE (t.heintz) TBinaryProtocolAccelerated internally wraps our TMemoryBuffer in a
// TBufferedTransport, so we have to retrieve it again or risk losing data when writing
// less than 512 bytes to the transport (see the comment there as well).
// @see THRIFT-1579
$protocol->writeMessageBegin('', TMessageType::REPLY, 0);
$protocolTransport = $protocol->getTransport();
$protocolTransport->write($string_object);
$protocolTransport->flush();
return thrift_protocol_read_binary($protocol, $class_name,
$protocol->isStrictRead(),
$buffer_size);
} else {
$transport->write($string_object);
$object = new $class_name();
$object->read($protocol);
return $object;
}
}
}

View file

@ -0,0 +1,120 @@
<?php
namespace Thrift\Server;
use Thrift\Transport\TTransport;
use Thrift\Exception\TException;
use Thrift\Exception\TTransportException;
/**
* A forking implementation of a Thrift server.
*
* @package thrift.server
*/
class TForkingServer extends TServer
{
/**
* Flag for the main serving loop
*
* @var bool
*/
private $stop_ = false;
/**
* List of children.
*
* @var array
*/
protected $children_ = array();
/**
* Listens for new client using the supplied
* transport. We fork when a new connection
* arrives.
*
* @return void
*/
public function serve()
{
$this->transport_->listen();
while (!$this->stop_) {
try {
$transport = $this->transport_->accept();
if ($transport != null) {
$pid = pcntl_fork();
if ($pid > 0) {
$this->handleParent($transport, $pid);
} elseif ($pid === 0) {
$this->handleChild($transport);
} else {
throw new TException('Failed to fork');
}
}
} catch (TTransportException $e) { }
$this->collectChildren();
}
}
/**
* Code run by the parent
*
* @param TTransport $transport
* @param int $pid
* @return void
*/
private function handleParent(TTransport $transport, $pid)
{
$this->children_[$pid] = $transport;
}
/**
* Code run by the child.
*
* @param TTransport $transport
* @return void
*/
private function handleChild(TTransport $transport)
{
try {
$inputTransport = $this->inputTransportFactory_->getTransport($transport);
$outputTransport = $this->outputTransportFactory_->getTransport($transport);
$inputProtocol = $this->inputProtocolFactory_->getProtocol($inputTransport);
$outputProtocol = $this->outputProtocolFactory_->getProtocol($outputTransport);
while ($this->processor_->process($inputProtocol, $outputProtocol)) { }
@$transport->close();
} catch (TTransportException $e) { }
exit(0);
}
/**
* Collects any children we may have
*
* @return void
*/
private function collectChildren()
{
foreach ($this->children_ as $pid => $transport) {
if (pcntl_waitpid($pid, $status, WNOHANG) > 0) {
unset($this->children_[$pid]);
if ($transport) @$transport->close();
}
}
}
/**
* Stops the server running. Kills the transport
* and then stops the main serving loop
*
* @return void
*/
public function stop()
{
$this->transport_->close();
$this->stop_ = true;
}
}

View file

@ -0,0 +1,94 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
namespace Thrift\Server;
use Thrift\Transport\TSSLSocket;
/**
* Socket implementation of a server agent.
*
* @package thrift.transport
*/
class TSSLServerSocket extends TServerSocket
{
/**
* Remote port
*
* @var resource
*/
protected $context_ = null;
/**
* ServerSocket constructor
*
* @param string $host Host to listen on
* @param int $port Port to listen on
* @param resource $context Stream context
* @return void
*/
public function __construct($host = 'localhost', $port = 9090, $context = null)
{
$ssl_host = $this->getSSLHost($host);
parent::__construct($ssl_host, $port);
$this->context_ = $context;
}
public function getSSLHost($host)
{
$transport_protocol_loc = strpos($host, "://");
if ($transport_protocol_loc === false) {
$host = 'ssl://'.$host;
}
return $host;
}
/**
* Opens a new socket server handle
*
* @return void
*/
public function listen()
{
$this->listener_ = @stream_socket_server(
$this->host_ . ':' . $this->port_,
$errno,
$errstr,
STREAM_SERVER_BIND|STREAM_SERVER_LISTEN,
$this->context_);
}
/**
* Implementation of accept. If not client is accepted in the given time
*
* @return TSocket
*/
protected function acceptImpl()
{
$handle = @stream_socket_accept($this->listener_, $this->acceptTimeout_ / 1000.0);
if(!$handle) return null;
$socket = new TSSLSocket();
$socket->setHandle($handle);
return $socket;
}
}

View file

@ -0,0 +1,100 @@
<?php
namespace Thrift\Server;
use Thrift\Factory\TTransportFactory;
use Thrift\Factory\TProtocolFactory;
/**
* Generic class for a Thrift server.
*
* @package thrift.server
*/
abstract class TServer
{
/**
* Processor to handle new clients
*
* @var TProcessor
*/
protected $processor_;
/**
* Server transport to be used for listening
* and accepting new clients
*
* @var TServerTransport
*/
protected $transport_;
/**
* Input transport factory
*
* @var TTransportFactory
*/
protected $inputTransportFactory_;
/**
* Output transport factory
*
* @var TTransportFactory
*/
protected $outputTransportFactory_;
/**
* Input protocol factory
*
* @var TProtocolFactory
*/
protected $inputProtocolFactory_;
/**
* Output protocol factory
*
* @var TProtocolFactory
*/
protected $outputProtocolFactory_;
/**
* Sets up all the factories, etc
*
* @param object $processor
* @param TServerTransport $transport
* @param TTransportFactory $inputTransportFactory
* @param TTransportFactory $outputTransportFactory
* @param TProtocolFactory $inputProtocolFactory
* @param TProtocolFactory $outputProtocolFactory
* @return void
*/
public function __construct($processor,
TServerTransport $transport,
TTransportFactory $inputTransportFactory,
TTransportFactory $outputTransportFactory,
TProtocolFactory $inputProtocolFactory,
TProtocolFactory $outputProtocolFactory) {
$this->processor_ = $processor;
$this->transport_ = $transport;
$this->inputTransportFactory_ = $inputTransportFactory;
$this->outputTransportFactory_ = $outputTransportFactory;
$this->inputProtocolFactory_ = $inputProtocolFactory;
$this->outputProtocolFactory_ = $outputProtocolFactory;
}
/**
* Serves the server. This should never return
* unless a problem permits it to do so or it
* is interrupted intentionally
*
* @abstract
* @return void
*/
abstract public function serve();
/**
* Stops the server serving
*
* @abstract
* @return void
*/
abstract public function stop();
}

View file

@ -0,0 +1,122 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.transport
*/
namespace Thrift\Server;
use Thrift\Transport\TSocket;
/**
* Socket implementation of a server agent.
*
* @package thrift.transport
*/
class TServerSocket extends TServerTransport
{
/**
* Handle for the listener socket
*
* @var resource
*/
protected $listener_;
/**
* Port for the listener to listen on
*
* @var int
*/
protected $port_;
/**
* Timeout when listening for a new client
*
* @var int
*/
protected $acceptTimeout_ = 30000;
/**
* Host to listen on
*
* @var string
*/
protected $host_;
/**
* ServerSocket constructor
*
* @param string $host Host to listen on
* @param int $port Port to listen on
* @return void
*/
public function __construct($host = 'localhost', $port = 9090)
{
$this->host_ = $host;
$this->port_ = $port;
}
/**
* Sets the accept timeout
*
* @param int $acceptTimeout
* @return void
*/
public function setAcceptTimeout($acceptTimeout)
{
$this->acceptTimeout_ = $acceptTimeout;
}
/**
* Opens a new socket server handle
*
* @return void
*/
public function listen()
{
$this->listener_ = stream_socket_server('tcp://' . $this->host_ . ':' . $this->port_);
}
/**
* Closes the socket server handle
*
* @return void
*/
public function close()
{
@fclose($this->listener_);
$this->listener_ = null;
}
/**
* Implementation of accept. If not client is accepted in the given time
*
* @return TSocket
*/
protected function acceptImpl()
{
$handle = @stream_socket_accept($this->listener_, $this->acceptTimeout_ / 1000.0);
if(!$handle) return null;
$socket = new TSocket();
$socket->setHandle($handle);
return $socket;
}
}

View file

@ -0,0 +1,56 @@
<?php
namespace Thrift\Server;
use Thrift\Exception\TTransportException;
/**
* Generic class for Server agent.
*
* @package thrift.transport
*/
abstract class TServerTransport
{
/**
* List for new clients
*
* @abstract
* @return void
*/
abstract public function listen();
/**
* Close the server
*
* @abstract
* @return void
*/
abstract public function close();
/**
* Subclasses should use this to implement
* accept.
*
* @abstract
* @return TTransport
*/
abstract protected function acceptImpl();
/**
* Uses the accept implemtation. If null is returned, an
* exception is thrown.
*
* @throws TTransportException
* @return TTransport
*/
public function accept()
{
$transport = $this->acceptImpl();
if ($transport == null) {
throw new TTransportException("accept() may not return NULL");
}
return $transport;
}
}

View file

@ -0,0 +1,58 @@
<?php
namespace Thrift\Server;
use Thrift\Exception\TTransportException;
/**
* Simple implemtation of a Thrift server.
*
* @package thrift.server
*/
class TSimpleServer extends TServer
{
/**
* Flag for the main serving loop
*
* @var bool
*/
private $stop_ = false;
/**
* Listens for new client using the supplied
* transport. It handles TTransportExceptions
* to avoid timeouts etc killing it
*
* @return void
*/
public function serve()
{
$this->transport_->listen();
while (!$this->stop_) {
try {
$transport = $this->transport_->accept();
if ($transport != null) {
$inputTransport = $this->inputTransportFactory_->getTransport($transport);
$outputTransport = $this->outputTransportFactory_->getTransport($transport);
$inputProtocol = $this->inputProtocolFactory_->getProtocol($inputTransport);
$outputProtocol = $this->outputProtocolFactory_->getProtocol($outputTransport);
while ($this->processor_->process($inputProtocol, $outputProtocol)) { }
}
} catch (TTransportException $e) { }
}
}
/**
* Stops the server running. Kills the transport
* and then stops the main serving loop
*
* @return void
*/
public function stop()
{
$this->transport_->close();
$this->stop_ = true;
}
}

View file

@ -0,0 +1,40 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
namespace Thrift\StringFunc;
class Core implements TStringFunc
{
public function substr($str, $start, $length = null)
{
// specifying a null $length would return an empty string
if ($length === null) {
return substr($str, $start);
}
return substr($str, $start, $length);
}
public function strlen($str)
{
return strlen($str);
}
}

View file

@ -0,0 +1,46 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
namespace Thrift\StringFunc;
class Mbstring implements TStringFunc
{
public function substr($str, $start, $length = null)
{
/**
* We need to set the charset parameter, which is the second
* optional parameter and the first optional parameter can't
* be null or false as a "magic" value because that would
* cause an empty string to be returned, so we need to
* actually calculate the proper length value.
*/
if ($length === null) {
$length = $this->strlen($str) - $start;
}
return mb_substr($str, $start, $length, '8bit');
}
public function strlen($str)
{
return mb_strlen($str, '8bit');
}
}

View file

@ -0,0 +1,28 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
namespace Thrift\StringFunc;
interface TStringFunc
{
public function substr($str, $start, $length = null);
public function strlen($str);
}

View file

@ -0,0 +1,143 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.processor
*/
namespace Thrift;
use Thrift\Exception\TException;
use Thrift\Protocol\TProtocol;
use Thrift\Protocol\TMultiplexedProtocol;
use Thrift\Protocol\TProtocolDecorator;
use Thrift\Type\TMessageType;
/**
* <code>TMultiplexedProcessor</code> is a Processor allowing
* a single <code>TServer</code> to provide multiple services.
*
* <p>To do so, you instantiate the processor and then register additional
* processors with it, as shown in the following example:</p>
*
* <blockquote><code>
* $processor = new TMultiplexedProcessor();
*
* processor->registerProcessor(
* "Calculator",
* new \tutorial\CalculatorProcessor(new CalculatorHandler()));
*
* processor->registerProcessor(
* "WeatherReport",
* new \tutorial\WeatherReportProcessor(new WeatherReportHandler()));
*
* $processor->process($protocol, $protocol);
* </code></blockquote>
*/
class TMultiplexedProcessor
{
private $serviceProcessorMap_;
/**
* 'Register' a service with this <code>TMultiplexedProcessor</code>. This
* allows us to broker requests to individual services by using the service
* name to select them at request time.
*
* @param serviceName Name of a service, has to be identical to the name
* declared in the Thrift IDL, e.g. "WeatherReport".
* @param processor Implementation of a service, usually referred to
* as "handlers", e.g. WeatherReportHandler implementing WeatherReport.Iface.
*/
public function registerProcessor($serviceName, $processor)
{
$this->serviceProcessorMap_[$serviceName] = $processor;
}
/**
* This implementation of <code>process</code> performs the following steps:
*
* <ol>
* <li>Read the beginning of the message.</li>
* <li>Extract the service name from the message.</li>
* <li>Using the service name to locate the appropriate processor.</li>
* <li>Dispatch to the processor, with a decorated instance of TProtocol
* that allows readMessageBegin() to return the original Message.</li>
* </ol>
*
* @throws TException If the message type is not CALL or ONEWAY, if
* the service name was not found in the message, or if the service
* name was not found in the service map.
*/
public function process(TProtocol $input, TProtocol $output)
{
/*
Use the actual underlying protocol (e.g. TBinaryProtocol) to read the
message header. This pulls the message "off the wire", which we'll
deal with at the end of this method.
*/
$input->readMessageBegin($fname, $mtype, $rseqid);
if ($mtype !== TMessageType::CALL && $mtype != TMessageType::ONEWAY) {
throw new TException("This should not have happened!?");
}
// Extract the service name and the new Message name.
if (strpos($fname, TMultiplexedProtocol::SEPARATOR) === false) {
throw new TException("Service name not found in message name: {$fname}. Did you " .
"forget to use a TMultiplexProtocol in your client?");
}
list($serviceName, $messageName) = explode(':', $fname, 2);
if (!array_key_exists($serviceName, $this->serviceProcessorMap_)) {
throw new TException("Service name not found: {$serviceName}. Did you forget " .
"to call registerProcessor()?");
}
// Dispatch processing to the stored processor
$processor = $this->serviceProcessorMap_[$serviceName];
return $processor->process(
new StoredMessageProtocol($input, $messageName, $mtype, $rseqid), $output
);
}
}
/**
* Our goal was to work with any protocol. In order to do that, we needed
* to allow them to call readMessageBegin() and get the Message in exactly
* the standard format, without the service name prepended to the Message name.
*/
class StoredMessageProtocol extends TProtocolDecorator
{
private $fname_, $mtype_, $rseqid_;
public function __construct(TProtocol $protocol, $fname, $mtype, $rseqid)
{
parent::__construct($protocol);
$this->fname_ = $fname;
$this->mtype_ = $mtype;
$this->rseqid_ = $rseqid;
}
public function readMessageBegin(&$name, &$type, &$seqid)
{
$name = $this->fname_;
$type = $this->mtype_;
$seqid = $this->rseqid_;
}
}

View file

@ -0,0 +1,181 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.transport
*/
namespace Thrift\Transport;
use Thrift\Factory\TStringFuncFactory;
/**
* Buffered transport. Stores data to an internal buffer that it doesn't
* actually write out until flush is called. For reading, we do a greedy
* read and then serve data out of the internal buffer.
*
* @package thrift.transport
*/
class TBufferedTransport extends TTransport
{
/**
* Constructor. Creates a buffered transport around an underlying transport
*/
public function __construct($transport=null, $rBufSize=512, $wBufSize=512)
{
$this->transport_ = $transport;
$this->rBufSize_ = $rBufSize;
$this->wBufSize_ = $wBufSize;
}
/**
* The underlying transport
*
* @var TTransport
*/
protected $transport_ = null;
/**
* The receive buffer size
*
* @var int
*/
protected $rBufSize_ = 512;
/**
* The write buffer size
*
* @var int
*/
protected $wBufSize_ = 512;
/**
* The write buffer.
*
* @var string
*/
protected $wBuf_ = '';
/**
* The read buffer.
*
* @var string
*/
protected $rBuf_ = '';
public function isOpen()
{
return $this->transport_->isOpen();
}
public function open()
{
$this->transport_->open();
}
public function close()
{
$this->transport_->close();
}
public function putBack($data)
{
if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
$this->rBuf_ = $data;
} else {
$this->rBuf_ = ($data . $this->rBuf_);
}
}
/**
* The reason that we customize readAll here is that the majority of PHP
* streams are already internally buffered by PHP. The socket stream, for
* example, buffers internally and blocks if you call read with $len greater
* than the amount of data available, unlike recv() in C.
*
* Therefore, use the readAll method of the wrapped transport inside
* the buffered readAll.
*/
public function readAll($len)
{
$have = TStringFuncFactory::create()->strlen($this->rBuf_);
if ($have == 0) {
$data = $this->transport_->readAll($len);
} elseif ($have < $len) {
$data = $this->rBuf_;
$this->rBuf_ = '';
$data .= $this->transport_->readAll($len - $have);
} elseif ($have == $len) {
$data = $this->rBuf_;
$this->rBuf_ = '';
} elseif ($have > $len) {
$data = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len);
$this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len);
}
return $data;
}
public function read($len)
{
if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
$this->rBuf_ = $this->transport_->read($this->rBufSize_);
}
if (TStringFuncFactory::create()->strlen($this->rBuf_) <= $len) {
$ret = $this->rBuf_;
$this->rBuf_ = '';
return $ret;
}
$ret = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len);
$this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len);
return $ret;
}
public function write($buf)
{
$this->wBuf_ .= $buf;
if (TStringFuncFactory::create()->strlen($this->wBuf_) >= $this->wBufSize_) {
$out = $this->wBuf_;
// Note that we clear the internal wBuf_ prior to the underlying write
// to ensure we're in a sane state (i.e. internal buffer cleaned)
// if the underlying write throws up an exception
$this->wBuf_ = '';
$this->transport_->write($out);
}
}
public function flush()
{
if (TStringFuncFactory::create()->strlen($this->wBuf_) > 0) {
$out = $this->wBuf_;
// Note that we clear the internal wBuf_ prior to the underlying write
// to ensure we're in a sane state (i.e. internal buffer cleaned)
// if the underlying write throws up an exception
$this->wBuf_ = '';
$this->transport_->write($out);
}
$this->transport_->flush();
}
}

View file

@ -0,0 +1,231 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.transport
*/
namespace Thrift\Transport;
use Thrift\Exception\TTransportException;
use Thrift\Factory\TStringFuncFactory;
/**
* HTTP client for Thrift
*
* @package thrift.transport
*/
class TCurlClient extends TTransport
{
private static $curlHandle;
/**
* The host to connect to
*
* @var string
*/
protected $host_;
/**
* The port to connect on
*
* @var int
*/
protected $port_;
/**
* The URI to request
*
* @var string
*/
protected $uri_;
/**
* The scheme to use for the request, i.e. http, https
*
* @var string
*/
protected $scheme_;
/**
* Buffer for the HTTP request data
*
* @var string
*/
protected $request_;
/**
* Buffer for the HTTP response data.
*
* @var binary string
*/
protected $response_;
/**
* Read timeout
*
* @var float
*/
protected $timeout_;
/**
* Make a new HTTP client.
*
* @param string $host
* @param int $port
* @param string $uri
*/
public function __construct($host, $port=80, $uri='', $scheme = 'http')
{
if ((TStringFuncFactory::create()->strlen($uri) > 0) && ($uri{0} != '/')) {
$uri = '/'.$uri;
}
$this->scheme_ = $scheme;
$this->host_ = $host;
$this->port_ = $port;
$this->uri_ = $uri;
$this->request_ = '';
$this->response_ = null;
$this->timeout_ = null;
}
/**
* Set read timeout
*
* @param float $timeout
*/
public function setTimeoutSecs($timeout)
{
$this->timeout_ = $timeout;
}
/**
* Whether this transport is open.
*
* @return boolean true if open
*/
public function isOpen()
{
return true;
}
/**
* Open the transport for reading/writing
*
* @throws TTransportException if cannot open
*/
public function open()
{
}
/**
* Close the transport.
*/
public function close()
{
$this->request_ = '';
$this->response_ = null;
}
/**
* Read some data into the array.
*
* @param int $len How much to read
* @return string The data that has been read
* @throws TTransportException if cannot read any more data
*/
public function read($len)
{
if ($len >= strlen($this->response_)) {
return $this->response_;
} else {
$ret = substr($this->response_, 0, $len);
$this->response_ = substr($this->response_, $len);
return $ret;
}
}
/**
* Writes some data into the pending buffer
*
* @param string $buf The data to write
* @throws TTransportException if writing fails
*/
public function write($buf)
{
$this->request_ .= $buf;
}
/**
* Opens and sends the actual request over the HTTP connection
*
* @throws TTransportException if a writing error occurs
*/
public function flush()
{
if (!self::$curlHandle) {
register_shutdown_function(array('Thrift\\Transport\\TCurlClient', 'closeCurlHandle'));
self::$curlHandle = curl_init();
curl_setopt(self::$curlHandle, CURLOPT_RETURNTRANSFER, true);
curl_setopt(self::$curlHandle, CURLOPT_BINARYTRANSFER, true);
curl_setopt(self::$curlHandle, CURLOPT_USERAGENT, 'PHP/TCurlClient');
curl_setopt(self::$curlHandle, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt(self::$curlHandle, CURLOPT_FOLLOWLOCATION, true);
curl_setopt(self::$curlHandle, CURLOPT_MAXREDIRS, 1);
}
// God, PHP really has some esoteric ways of doing simple things.
$host = $this->host_.($this->port_ != 80 ? ':'.$this->port_ : '');
$fullUrl = $this->scheme_."://".$host.$this->uri_;
$headers = array('Accept: application/x-thrift',
'Content-Type: application/x-thrift',
'Content-Length: '.TStringFuncFactory::create()->strlen($this->request_));
curl_setopt(self::$curlHandle, CURLOPT_HTTPHEADER, $headers);
if ($this->timeout_ > 0) {
curl_setopt(self::$curlHandle, CURLOPT_TIMEOUT, $this->timeout_);
}
curl_setopt(self::$curlHandle, CURLOPT_POSTFIELDS, $this->request_);
$this->request_ = '';
curl_setopt(self::$curlHandle, CURLOPT_URL, $fullUrl);
$this->response_ = curl_exec(self::$curlHandle);
// Connect failed?
if (!$this->response_) {
curl_close(self::$curlHandle);
self::$curlHandle = null;
$error = 'TCurlClient: Could not connect to '.$fullUrl;
throw new TTransportException($error, TTransportException::NOT_OPEN);
}
}
public static function closeCurlHandle()
{
try {
if (self::$curlHandle) {
curl_close(self::$curlHandle);
self::$curlHandle = null;
}
} catch (\Exception $x) {
error_log('There was an error closing the curl handle: ' . $x->getMessage());
}
}
}

View file

@ -0,0 +1,193 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.transport
*/
namespace Thrift\Transport;
use Thrift\Factory\TStringFuncFactory;
/**
* Framed transport. Writes and reads data in chunks that are stamped with
* their length.
*
* @package thrift.transport
*/
class TFramedTransport extends TTransport
{
/**
* Underlying transport object.
*
* @var TTransport
*/
private $transport_;
/**
* Buffer for read data.
*
* @var string
*/
private $rBuf_;
/**
* Buffer for queued output data
*
* @var string
*/
private $wBuf_;
/**
* Whether to frame reads
*
* @var bool
*/
private $read_;
/**
* Whether to frame writes
*
* @var bool
*/
private $write_;
/**
* Constructor.
*
* @param TTransport $transport Underlying transport
*/
public function __construct($transport=null, $read=true, $write=true)
{
$this->transport_ = $transport;
$this->read_ = $read;
$this->write_ = $write;
}
public function isOpen()
{
return $this->transport_->isOpen();
}
public function open()
{
$this->transport_->open();
}
public function close()
{
$this->transport_->close();
}
/**
* Reads from the buffer. When more data is required reads another entire
* chunk and serves future reads out of that.
*
* @param int $len How much data
*/
public function read($len)
{
if (!$this->read_) {
return $this->transport_->read($len);
}
if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
$this->readFrame();
}
// Just return full buff
if ($len >= TStringFuncFactory::create()->strlen($this->rBuf_)) {
$out = $this->rBuf_;
$this->rBuf_ = null;
return $out;
}
// Return TStringFuncFactory::create()->substr
$out = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len);
$this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len);
return $out;
}
/**
* Put previously read data back into the buffer
*
* @param string $data data to return
*/
public function putBack($data)
{
if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
$this->rBuf_ = $data;
} else {
$this->rBuf_ = ($data . $this->rBuf_);
}
}
/**
* Reads a chunk of data into the internal read buffer.
*/
private function readFrame()
{
$buf = $this->transport_->readAll(4);
$val = unpack('N', $buf);
$sz = $val[1];
$this->rBuf_ = $this->transport_->readAll($sz);
}
/**
* Writes some data to the pending output buffer.
*
* @param string $buf The data
* @param int $len Limit of bytes to write
*/
public function write($buf, $len=null)
{
if (!$this->write_) {
return $this->transport_->write($buf, $len);
}
if ($len !== null && $len < TStringFuncFactory::create()->strlen($buf)) {
$buf = TStringFuncFactory::create()->substr($buf, 0, $len);
}
$this->wBuf_ .= $buf;
}
/**
* Writes the output buffer to the stream in the format of a 4-byte length
* followed by the actual data.
*/
public function flush()
{
if (!$this->write_ || TStringFuncFactory::create()->strlen($this->wBuf_) == 0) {
return $this->transport_->flush();
}
$out = pack('N', TStringFuncFactory::create()->strlen($this->wBuf_));
$out .= $this->wBuf_;
// Note that we clear the internal wBuf_ prior to the underlying write
// to ensure we're in a sane state (i.e. internal buffer cleaned)
// if the underlying write throws up an exception
$this->wBuf_ = '';
$this->transport_->write($out);
$this->transport_->flush();
}
}

View file

@ -0,0 +1,229 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.transport
*/
namespace Thrift\Transport;
use Thrift\Exception\TTransportException;
use Thrift\Factory\TStringFuncFactory;
/**
* HTTP client for Thrift
*
* @package thrift.transport
*/
class THttpClient extends TTransport
{
/**
* The host to connect to
*
* @var string
*/
protected $host_;
/**
* The port to connect on
*
* @var int
*/
protected $port_;
/**
* The URI to request
*
* @var string
*/
protected $uri_;
/**
* The scheme to use for the request, i.e. http, https
*
* @var string
*/
protected $scheme_;
/**
* Buffer for the HTTP request data
*
* @var string
*/
protected $buf_;
/**
* Input socket stream.
*
* @var resource
*/
protected $handle_;
/**
* Read timeout
*
* @var float
*/
protected $timeout_;
/**
* http headers
*
* @var array
*/
protected $headers_;
/**
* Make a new HTTP client.
*
* @param string $host
* @param int $port
* @param string $uri
*/
public function __construct($host, $port=80, $uri='', $scheme = 'http')
{
if ((TStringFuncFactory::create()->strlen($uri) > 0) && ($uri{0} != '/')) {
$uri = '/'.$uri;
}
$this->scheme_ = $scheme;
$this->host_ = $host;
$this->port_ = $port;
$this->uri_ = $uri;
$this->buf_ = '';
$this->handle_ = null;
$this->timeout_ = null;
$this->headers_ = array();
}
/**
* Set read timeout
*
* @param float $timeout
*/
public function setTimeoutSecs($timeout)
{
$this->timeout_ = $timeout;
}
/**
* Whether this transport is open.
*
* @return boolean true if open
*/
public function isOpen()
{
return true;
}
/**
* Open the transport for reading/writing
*
* @throws TTransportException if cannot open
*/
public function open() {}
/**
* Close the transport.
*/
public function close()
{
if ($this->handle_) {
@fclose($this->handle_);
$this->handle_ = null;
}
}
/**
* Read some data into the array.
*
* @param int $len How much to read
* @return string The data that has been read
* @throws TTransportException if cannot read any more data
*/
public function read($len)
{
$data = @fread($this->handle_, $len);
if ($data === FALSE || $data === '') {
$md = stream_get_meta_data($this->handle_);
if ($md['timed_out']) {
throw new TTransportException('THttpClient: timed out reading '.$len.' bytes from '.$this->host_.':'.$this->port_.$this->uri_, TTransportException::TIMED_OUT);
} else {
throw new TTransportException('THttpClient: Could not read '.$len.' bytes from '.$this->host_.':'.$this->port_.$this->uri_, TTransportException::UNKNOWN);
}
}
return $data;
}
/**
* Writes some data into the pending buffer
*
* @param string $buf The data to write
* @throws TTransportException if writing fails
*/
public function write($buf)
{
$this->buf_ .= $buf;
}
/**
* Opens and sends the actual request over the HTTP connection
*
* @throws TTransportException if a writing error occurs
*/
public function flush()
{
// God, PHP really has some esoteric ways of doing simple things.
$host = $this->host_.($this->port_ != 80 ? ':'.$this->port_ : '');
$headers = array();
$defaultHeaders = array('Host' => $host,
'Accept' => 'application/x-thrift',
'User-Agent' => 'PHP/THttpClient',
'Content-Type' => 'application/x-thrift',
'Content-Length' => TStringFuncFactory::create()->strlen($this->buf_));
foreach (array_merge($defaultHeaders, $this->headers_) as $key => $value) {
$headers[] = "$key: $value";
}
$options = array('method' => 'POST',
'header' => implode("\r\n", $headers),
'max_redirects' => 1,
'content' => $this->buf_);
if ($this->timeout_ > 0) {
$options['timeout'] = $this->timeout_;
}
$this->buf_ = '';
$contextid = stream_context_create(array('http' => $options));
$this->handle_ = @fopen($this->scheme_.'://'.$host.$this->uri_, 'r', false, $contextid);
// Connect failed?
if ($this->handle_ === FALSE) {
$this->handle_ = null;
$error = 'THttpClient: Could not connect to '.$host.$this->uri_;
throw new TTransportException($error, TTransportException::NOT_OPEN);
}
}
public function addHeaders($headers)
{
$this->headers_ = array_merge($this->headers_, $headers);
}
}

View file

@ -0,0 +1,100 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.transport
*/
namespace Thrift\Transport;
use Thrift\Exception\TTransportException;
use Thrift\Factory\TStringFuncFactory;
/**
* A memory buffer is a tranpsort that simply reads from and writes to an
* in-memory string buffer. Anytime you call write on it, the data is simply
* placed into a buffer, and anytime you call read, data is read from that
* buffer.
*
* @package thrift.transport
*/
class TMemoryBuffer extends TTransport
{
/**
* Constructor. Optionally pass an initial value
* for the buffer.
*/
public function __construct($buf = '')
{
$this->buf_ = $buf;
}
protected $buf_ = '';
public function isOpen()
{
return true;
}
public function open() {}
public function close() {}
public function write($buf)
{
$this->buf_ .= $buf;
}
public function read($len)
{
$bufLength = TStringFuncFactory::create()->strlen($this->buf_);
if ($bufLength === 0) {
throw new TTransportException('TMemoryBuffer: Could not read ' .
$len . ' bytes from buffer.',
TTransportException::UNKNOWN);
}
if ($bufLength <= $len) {
$ret = $this->buf_;
$this->buf_ = '';
return $ret;
}
$ret = TStringFuncFactory::create()->substr($this->buf_, 0, $len);
$this->buf_ = TStringFuncFactory::create()->substr($this->buf_, $len);
return $ret;
}
public function getBuffer()
{
return $this->buf_;
}
public function available()
{
return TStringFuncFactory::create()->strlen($this->buf_);
}
public function putBack($data)
{
$this->buf_ = $data.$this->buf_;
}
}

View file

@ -0,0 +1,51 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.transport
*/
namespace Thrift\Transport;
use Thrift\Exception\TTransportException;
/**
* Transport that only accepts writes and ignores them.
* This is useful for measuring the serialized size of structures.
*
* @package thrift.transport
*/
class TNullTransport extends TTransport
{
public function isOpen()
{
return true;
}
public function open() {}
public function close() {}
public function read($len)
{
throw new TTransportException("Can't read from TNullTransport.");
}
public function write($buf) {}
}

View file

@ -0,0 +1,123 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.transport
*/
namespace Thrift\Transport;
use Thrift\Exception\TException;
use Thrift\Factory\TStringFuncFactory;
/**
* Php stream transport. Reads to and writes from the php standard streams
* php://input and php://output
*
* @package thrift.transport
*/
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(self::inStreamName(), 'r');
if (!is_resource($this->inStream_)) {
throw new TException('TPhpStream: Could not open php://input');
}
}
if ($this->write_) {
$this->outStream_ = @fopen('php://output', 'w');
if (!is_resource($this->outStream_)) {
throw new TException('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 === FALSE || $data === '') {
throw new TException('TPhpStream: Could not read '.$len.' bytes');
}
return $data;
}
public function write($buf)
{
while (TStringFuncFactory::create()->strlen($buf) > 0) {
$got = @fwrite($this->outStream_, $buf);
if ($got === 0 || $got === FALSE) {
throw new TException('TPhpStream: Could not write '.TStringFuncFactory::create()->strlen($buf).' bytes');
}
$buf = TStringFuncFactory::create()->substr($buf, $got);
}
}
public function flush()
{
@fflush($this->outStream_);
}
private static function inStreamName()
{
if (php_sapi_name() == 'cli') {
return 'php://stdin';
}
return 'php://input';
}
}

View file

@ -0,0 +1,112 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.transport
*/
namespace Thrift\Transport;
use Thrift\Exception\TException;
use Thrift\Exception\TTransportException;
use Thrift\Factory\TStringFuncFactory;
/**
* Sockets implementation of the TTransport interface.
*
* @package thrift.transport
*/
class TSSLSocket extends TSocket
{
/**
* Remote port
*
* @var resource
*/
protected $context_ = null;
/**
* Socket constructor
*
* @param string $host Remote hostname
* @param int $port Remote port
* @param resource $context Stream context
* @param bool $persist Whether to use a persistent socket
* @param string $debugHandler Function to call for error logging
*/
public function __construct($host='localhost',
$port=9090,
$context=null,
$debugHandler=null) {
$this->host_ = $this->getSSLHost($host);
$this->port_ = $port;
$this->context_ = $context;
$this->debugHandler_ = $debugHandler ? $debugHandler : 'error_log';
}
/**
* Creates a host name with SSL transport protocol
* if no transport protocol already specified in
* the host name.
*
* @param string $host Host to listen on
* @return string $host Host name with transport protocol
*/
private function getSSLHost($host)
{
$transport_protocol_loc = strpos($host, "://");
if ($transport_protocol_loc === false) {
$host = 'ssl://'.$host;
}
return $host;
}
/**
* Connects the socket.
*/
public function open()
{
if ($this->isOpen()) {
throw new TTransportException('Socket already connected', TTransportException::ALREADY_OPEN);
}
if (empty($this->host_)) {
throw new TTransportException('Cannot open null host', TTransportException::NOT_OPEN);
}
if ($this->port_ <= 0) {
throw new TTransportException('Cannot open without port', TTransportException::NOT_OPEN);
}
$this->handle_ = @stream_socket_client($this->host_.':'.$this->port_,
$errno,
$errstr,
$this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000),
STREAM_CLIENT_CONNECT,
$this->context_);
// Connect failed?
if ($this->handle_ === FALSE) {
$error = 'TSocket: Could not connect to '.$this->host_.':'.$this->port_.' ('.$errstr.' ['.$errno.'])';
if ($this->debug_) {
call_user_func($this->debugHandler_, $error);
}
throw new TException($error);
}
}
}

View file

@ -0,0 +1,337 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.transport
*/
namespace Thrift\Transport;
use Thrift\Exception\TException;
use Thrift\Exception\TTransportException;
use Thrift\Factory\TStringFuncFactory;
/**
* Sockets implementation of the TTransport interface.
*
* @package thrift.transport
*/
class TSocket extends TTransport
{
/**
* Handle to PHP socket
*
* @var resource
*/
protected $handle_ = null;
/**
* Remote hostname
*
* @var string
*/
protected $host_ = 'localhost';
/**
* Remote port
*
* @var int
*/
protected $port_ = '9090';
/**
* Send timeout in seconds.
*
* Combined with sendTimeoutUsec this is used for send timeouts.
*
* @var int
*/
protected $sendTimeoutSec_ = 0;
/**
* Send timeout in microseconds.
*
* Combined with sendTimeoutSec this is used for send timeouts.
*
* @var int
*/
protected $sendTimeoutUsec_ = 100000;
/**
* Recv timeout in seconds
*
* Combined with recvTimeoutUsec this is used for recv timeouts.
*
* @var int
*/
protected $recvTimeoutSec_ = 0;
/**
* Recv timeout in microseconds
*
* Combined with recvTimeoutSec this is used for recv timeouts.
*
* @var int
*/
protected $recvTimeoutUsec_ = 750000;
/**
* Persistent socket or plain?
*
* @var bool
*/
protected $persist_ = false;
/**
* Debugging on?
*
* @var bool
*/
protected $debug_ = false;
/**
* Debug handler
*
* @var mixed
*/
protected $debugHandler_ = null;
/**
* Socket constructor
*
* @param string $host Remote hostname
* @param int $port Remote port
* @param bool $persist Whether to use a persistent socket
* @param string $debugHandler Function to call for error logging
*/
public function __construct($host='localhost',
$port=9090,
$persist=false,
$debugHandler=null) {
$this->host_ = $host;
$this->port_ = $port;
$this->persist_ = $persist;
$this->debugHandler_ = $debugHandler ? $debugHandler : 'error_log';
}
/**
* @param resource $handle
* @return void
*/
public function setHandle($handle)
{
$this->handle_ = $handle;
}
/**
* Sets the send timeout.
*
* @param int $timeout Timeout in milliseconds.
*/
public function setSendTimeout($timeout)
{
$this->sendTimeoutSec_ = floor($timeout / 1000);
$this->sendTimeoutUsec_ =
($timeout - ($this->sendTimeoutSec_ * 1000)) * 1000;
}
/**
* Sets the receive timeout.
*
* @param int $timeout Timeout in milliseconds.
*/
public function setRecvTimeout($timeout)
{
$this->recvTimeoutSec_ = floor($timeout / 1000);
$this->recvTimeoutUsec_ =
($timeout - ($this->recvTimeoutSec_ * 1000)) * 1000;
}
/**
* Sets debugging output on or off
*
* @param bool $debug
*/
public function setDebug($debug)
{
$this->debug_ = $debug;
}
/**
* Get the host that this socket is connected to
*
* @return string host
*/
public function getHost()
{
return $this->host_;
}
/**
* Get the remote port that this socket is connected to
*
* @return int port
*/
public function getPort()
{
return $this->port_;
}
/**
* Tests whether this is open
*
* @return bool true if the socket is open
*/
public function isOpen()
{
return is_resource($this->handle_);
}
/**
* Connects the socket.
*/
public function open()
{
if ($this->isOpen()) {
throw new TTransportException('Socket already connected', TTransportException::ALREADY_OPEN);
}
if (empty($this->host_)) {
throw new TTransportException('Cannot open null host', TTransportException::NOT_OPEN);
}
if ($this->port_ <= 0) {
throw new TTransportException('Cannot open without port', TTransportException::NOT_OPEN);
}
if ($this->persist_) {
$this->handle_ = @pfsockopen($this->host_,
$this->port_,
$errno,
$errstr,
$this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000));
} else {
$this->handle_ = @fsockopen($this->host_,
$this->port_,
$errno,
$errstr,
$this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000));
}
// Connect failed?
if ($this->handle_ === FALSE) {
$error = 'TSocket: Could not connect to '.$this->host_.':'.$this->port_.' ('.$errstr.' ['.$errno.'])';
if ($this->debug_) {
call_user_func($this->debugHandler_, $error);
}
throw new TException($error);
}
}
/**
* Closes the socket.
*/
public function close()
{
if (!$this->persist_) {
@fclose($this->handle_);
$this->handle_ = null;
}
}
/**
* Read from the socket at most $len bytes.
*
* This method will not wait for all the requested data, it will return as
* soon as any data is received.
*
* @param int $len Maximum number of bytes to read.
* @return string Binary data
*/
public function read($len)
{
$null = null;
$read = array($this->handle_);
$readable = @stream_select($read, $null, $null, $this->recvTimeoutSec_, $this->recvTimeoutUsec_);
if ($readable > 0) {
$data = fread($this->handle_, $len);
if ($data === false) {
throw new TTransportException('TSocket: Could not read '.$len.' bytes from '.
$this->host_.':'.$this->port_);
} elseif ($data == '' && feof($this->handle_)) {
throw new TTransportException('TSocket read 0 bytes');
}
return $data;
} elseif ($readable === 0) {
throw new TTransportException('TSocket: timed out reading '.$len.' bytes from '.
$this->host_.':'.$this->port_);
} else {
throw new TTransportException('TSocket: Could not read '.$len.' bytes from '.
$this->host_.':'.$this->port_);
}
}
/**
* Write to the socket.
*
* @param string $buf The data to write
*/
public function write($buf)
{
$null = null;
$write = array($this->handle_);
// keep writing until all the data has been written
while (TStringFuncFactory::create()->strlen($buf) > 0) {
// wait for stream to become available for writing
$writable = @stream_select($null, $write, $null, $this->sendTimeoutSec_, $this->sendTimeoutUsec_);
if ($writable > 0) {
// write buffer to stream
$written = fwrite($this->handle_, $buf);
if ($written === -1 || $written === false) {
throw new TTransportException('TSocket: Could not write '.TStringFuncFactory::create()->strlen($buf).' bytes '.
$this->host_.':'.$this->port_);
}
// determine how much of the buffer is left to write
$buf = TStringFuncFactory::create()->substr($buf, $written);
} elseif ($writable === 0) {
throw new TTransportException('TSocket: timed out writing '.TStringFuncFactory::create()->strlen($buf).' bytes from '.
$this->host_.':'.$this->port_);
} else {
throw new TTransportException('TSocket: Could not write '.TStringFuncFactory::create()->strlen($buf).' bytes '.
$this->host_.':'.$this->port_);
}
}
}
/**
* Flush output to the socket.
*
* Since read(), readAll() and write() operate on the sockets directly,
* this is a no-op
*
* If you wish to have flushable buffering behaviour, wrap this TSocket
* in a TBufferedTransport.
*/
public function flush()
{
// no-op
}
}

View file

@ -0,0 +1,300 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.transport
*/
namespace Thrift\Transport;
use Thrift\Exception\TException;
/**
* This library makes use of APC cache to make hosts as down in a web
* environment. If you are running from the CLI or on a system without APC
* installed, then these null functions will step in and act like cache
* misses.
*/
if (!function_exists('apc_fetch')) {
function apc_fetch($key) { return FALSE; }
function apc_store($key, $var, $ttl=0) { return FALSE; }
}
/**
* Sockets implementation of the TTransport interface that allows connection
* to a pool of servers.
*
* @package thrift.transport
*/
class TSocketPool extends TSocket
{
/**
* Remote servers. Array of associative arrays with 'host' and 'port' keys
*/
private $servers_ = array();
/**
* How many times to retry each host in connect
*
* @var int
*/
private $numRetries_ = 1;
/**
* Retry interval in seconds, how long to not try a host if it has been
* marked as down.
*
* @var int
*/
private $retryInterval_ = 60;
/**
* Max consecutive failures before marking a host down.
*
* @var int
*/
private $maxConsecutiveFailures_ = 1;
/**
* Try hosts in order? or Randomized?
*
* @var bool
*/
private $randomize_ = true;
/**
* Always try last host, even if marked down?
*
* @var bool
*/
private $alwaysTryLast_ = true;
/**
* Socket pool constructor
*
* @param array $hosts List of remote hostnames
* @param mixed $ports Array of remote ports, or a single common port
* @param bool $persist Whether to use a persistent socket
* @param mixed $debugHandler Function for error logging
*/
public function __construct($hosts=array('localhost'),
$ports=array(9090),
$persist=false,
$debugHandler=null) {
parent::__construct(null, 0, $persist, $debugHandler);
if (!is_array($ports)) {
$port = $ports;
$ports = array();
foreach ($hosts as $key => $val) {
$ports[$key] = $port;
}
}
foreach ($hosts as $key => $host) {
$this->servers_ []= array('host' => $host,
'port' => $ports[$key]);
}
}
/**
* Add a server to the pool
*
* This function does not prevent you from adding a duplicate server entry.
*
* @param string $host hostname or IP
* @param int $port port
*/
public function addServer($host, $port)
{
$this->servers_[] = array('host' => $host, 'port' => $port);
}
/**
* Sets how many time to keep retrying a host in the connect function.
*
* @param int $numRetries
*/
public function setNumRetries($numRetries)
{
$this->numRetries_ = $numRetries;
}
/**
* Sets how long to wait until retrying a host if it was marked down
*
* @param int $numRetries
*/
public function setRetryInterval($retryInterval)
{
$this->retryInterval_ = $retryInterval;
}
/**
* Sets how many time to keep retrying a host before marking it as down.
*
* @param int $numRetries
*/
public function setMaxConsecutiveFailures($maxConsecutiveFailures)
{
$this->maxConsecutiveFailures_ = $maxConsecutiveFailures;
}
/**
* Turns randomization in connect order on or off.
*
* @param bool $randomize
*/
public function setRandomize($randomize)
{
$this->randomize_ = $randomize;
}
/**
* Whether to always try the last server.
*
* @param bool $alwaysTryLast
*/
public function setAlwaysTryLast($alwaysTryLast)
{
$this->alwaysTryLast_ = $alwaysTryLast;
}
/**
* Connects the socket by iterating through all the servers in the pool
* and trying to find one that works.
*/
public function open()
{
// Check if we want order randomization
if ($this->randomize_) {
shuffle($this->servers_);
}
// Count servers to identify the "last" one
$numServers = count($this->servers_);
for ($i = 0; $i < $numServers; ++$i) {
// This extracts the $host and $port variables
extract($this->servers_[$i]);
// Check APC cache for a record of this server being down
$failtimeKey = 'thrift_failtime:'.$host.':'.$port.'~';
// Cache miss? Assume it's OK
$lastFailtime = apc_fetch($failtimeKey);
if ($lastFailtime === FALSE) {
$lastFailtime = 0;
}
$retryIntervalPassed = false;
// Cache hit...make sure enough the retry interval has elapsed
if ($lastFailtime > 0) {
$elapsed = time() - $lastFailtime;
if ($elapsed > $this->retryInterval_) {
$retryIntervalPassed = true;
if ($this->debug_) {
call_user_func($this->debugHandler_,
'TSocketPool: retryInterval '.
'('.$this->retryInterval_.') '.
'has passed for host '.$host.':'.$port);
}
}
}
// Only connect if not in the middle of a fail interval, OR if this
// is the LAST server we are trying, just hammer away on it
$isLastServer = false;
if ($this->alwaysTryLast_) {
$isLastServer = ($i == ($numServers - 1));
}
if (($lastFailtime === 0) ||
($isLastServer) ||
($lastFailtime > 0 && $retryIntervalPassed)) {
// Set underlying TSocket params to this one
$this->host_ = $host;
$this->port_ = $port;
// Try up to numRetries_ connections per server
for ($attempt = 0; $attempt < $this->numRetries_; $attempt++) {
try {
// Use the underlying TSocket open function
parent::open();
// Only clear the failure counts if required to do so
if ($lastFailtime > 0) {
apc_store($failtimeKey, 0);
}
// Successful connection, return now
return;
} catch (TException $tx) {
// Connection failed
}
}
// Mark failure of this host in the cache
$consecfailsKey = 'thrift_consecfails:'.$host.':'.$port.'~';
// Ignore cache misses
$consecfails = apc_fetch($consecfailsKey);
if ($consecfails === FALSE) {
$consecfails = 0;
}
// Increment by one
$consecfails++;
// Log and cache this failure
if ($consecfails >= $this->maxConsecutiveFailures_) {
if ($this->debug_) {
call_user_func($this->debugHandler_,
'TSocketPool: marking '.$host.':'.$port.
' as down for '.$this->retryInterval_.' secs '.
'after '.$consecfails.' failed attempts.');
}
// Store the failure time
apc_store($failtimeKey, time());
// Clear the count of consecutive failures
apc_store($consecfailsKey, 0);
} else {
apc_store($consecfailsKey, $consecfails);
}
}
}
// Oh no; we failed them all. The system is totally ill!
$error = 'TSocketPool: All hosts in pool are down. ';
$hosts = array();
foreach ($this->servers_ as $server) {
$hosts []= $server['host'].':'.$server['port'];
}
$hostlist = implode(',', $hosts);
$error .= '('.$hostlist.')';
if ($this->debug_) {
call_user_func($this->debugHandler_, $error);
}
throw new TException($error);
}
}

View file

@ -0,0 +1,95 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.transport
*/
namespace Thrift\Transport;
use Thrift\Factory\TStringFuncFactory;
/**
* Base interface for a transport agent.
*
* @package thrift.transport
*/
abstract class TTransport
{
/**
* Whether this transport is open.
*
* @return boolean true if open
*/
abstract public function isOpen();
/**
* Open the transport for reading/writing
*
* @throws TTransportException if cannot open
*/
abstract public function open();
/**
* Close the transport.
*/
abstract public function close();
/**
* Read some data into the array.
*
* @param int $len How much to read
* @return string The data that has been read
* @throws TTransportException if cannot read any more data
*/
abstract public function read($len);
/**
* Guarantees that the full amount of data is read.
*
* @return string The data, of exact length
* @throws TTransportException if cannot read data
*/
public function readAll($len)
{
// return $this->read($len);
$data = '';
$got = 0;
while (($got = TStringFuncFactory::create()->strlen($data)) < $len) {
$data .= $this->read($len - $got);
}
return $data;
}
/**
* Writes the given data out.
*
* @param string $buf The data to write
* @throws TTransportException if writing fails
*/
abstract public function write($buf);
/**
* Flushes any pending data out of a buffer
*
* @throws TTransportException if a writing error occurs
*/
public function flush() {}
}

View file

@ -0,0 +1,50 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift
*/
namespace Thrift\Type;
/**
* Base class for constant Management
*/
abstract class TConstant
{
/**
* Don't instanciate this class
*/
protected function __construct() {}
/**
* Get a constant value
* @param string $constant
* @return mixed
*/
public static function get($constant)
{
if (is_null(static::$$constant)) {
static::$$constant = call_user_func(
sprintf('static::init_%s', $constant)
);
}
return static::$$constant;
}
}

View file

@ -0,0 +1,34 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift
*/
namespace Thrift\Type;
/**
* Message types for RPC
*/
class TMessageType
{
const CALL = 1;
const REPLY = 2;
const EXCEPTION = 3;
const ONEWAY = 4;
}

View file

@ -0,0 +1,47 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift
*/
namespace Thrift\Type;
/**
* Data types that can be sent via Thrift
*/
class TType
{
const STOP = 0;
const VOID = 1;
const BOOL = 2;
const BYTE = 3;
const I08 = 3;
const DOUBLE = 4;
const I16 = 6;
const I32 = 8;
const I64 = 10;
const STRING = 11;
const UTF7 = 11;
const STRUCT = 12;
const MAP = 13;
const SET = 14;
const LST = 15; // N.B. cannot use LIST keyword in PHP!
const UTF8 = 16;
const UTF16 = 17;
}

View file

@ -0,0 +1,90 @@
<?php
interface TStringFunc
{
public function substr($str, $start, $length = null);
public function strlen($str);
}
class TStringFunc_Core
implements TStringFunc {
public function substr($str, $start, $length = null)
{
// specifying a null $length would return an empty string
if ($length === null) {
return substr($str, $start);
}
return substr($str, $start, $length);
}
public function strlen($str)
{
return strlen($str);
}
}
class TStringFunc_Mbstring
implements TStringFunc {
public function substr($str, $start, $length = null)
{
/**
* We need to set the charset parameter, which is the second
* optional parameter and the first optional parameter can't
* be null or false as a "magic" value because that would
* cause an empty string to be returned, so we need to
* actually calculate the proper length value.
*/
if ($length === null) {
$length = $this->strlen($str) - $start;
}
return mb_substr($str, $start, $length, '8bit');
}
public function strlen($str)
{
return mb_strlen($str, '8bit');
}
}
class TStringFuncFactory
{
private static $_instance;
/**
* Get the Singleton instance of TStringFunc implementation that is
* compatible with the current system's mbstring.func_overload settings.
*
* @return TStringFunc
*/
public static function create()
{
if (!self::$_instance) {
self::_setInstance();
}
return self::$_instance;
}
private static function _setInstance()
{
/**
* Cannot use str* functions for byte counting because multibyte
* characters will be read a single bytes.
*
* See: http://us.php.net/manual/en/mbstring.overload.php
*/
if (ini_get('mbstring.func_overload') & 2) {
self::$_instance = new TStringFunc_Mbstring();
}
/**
* mbstring is not installed or does not have function overloading
* of the str* functions enabled so use PHP core str* functions for
* byte counting.
*/
else {
self::$_instance = new TStringFunc_Core();
}
}
}

821
vendor/git.apache.org/thrift.git/lib/php/src/Thrift.php generated vendored Normal file
View file

@ -0,0 +1,821 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift
*/
/**
* Data types that can be sent via Thrift
*/
class TType
{
const STOP = 0;
const VOID = 1;
const BOOL = 2;
const BYTE = 3;
const I08 = 3;
const DOUBLE = 4;
const I16 = 6;
const I32 = 8;
const I64 = 10;
const STRING = 11;
const UTF7 = 11;
const STRUCT = 12;
const MAP = 13;
const SET = 14;
const LST = 15; // N.B. cannot use LIST keyword in PHP!
const UTF8 = 16;
const UTF16 = 17;
}
/**
* Message types for RPC
*/
class TMessageType
{
const CALL = 1;
const REPLY = 2;
const EXCEPTION = 3;
const ONEWAY = 4;
}
/**
* NOTE(mcslee): This currently contains a ton of duplicated code from TBase
* because we need to save CPU cycles and this is not yet in an extension.
* Ideally we'd multiply-inherit TException from both Exception and Base, but
* that's not possible in PHP and there are no modules either, so for now we
* apologetically take a trip to HackTown.
*
* Can be called with standard Exception constructor (message, code) or with
* Thrift Base object constructor (spec, vals).
*
* @param mixed $p1 Message (string) or type-spec (array)
* @param mixed $p2 Code (integer) or values (array)
*/
class TException extends Exception
{
public function __construct($p1=null, $p2=0)
{
if (is_array($p1) && is_array($p2)) {
$spec = $p1;
$vals = $p2;
foreach ($spec as $fid => $fspec) {
$var = $fspec['var'];
if (isset($vals[$var])) {
$this->$var = $vals[$var];
}
}
} else {
parent::__construct($p1, $p2);
}
}
static $tmethod = array(TType::BOOL => 'Bool',
TType::BYTE => 'Byte',
TType::I16 => 'I16',
TType::I32 => 'I32',
TType::I64 => 'I64',
TType::DOUBLE => 'Double',
TType::STRING => 'String');
private function _readMap(&$var, $spec, $input)
{
$xfer = 0;
$ktype = $spec['ktype'];
$vtype = $spec['vtype'];
$kread = $vread = null;
if (isset(TBase::$tmethod[$ktype])) {
$kread = 'read'.TBase::$tmethod[$ktype];
} else {
$kspec = $spec['key'];
}
if (isset(TBase::$tmethod[$vtype])) {
$vread = 'read'.TBase::$tmethod[$vtype];
} else {
$vspec = $spec['val'];
}
$var = array();
$_ktype = $_vtype = $size = 0;
$xfer += $input->readMapBegin($_ktype, $_vtype, $size);
for ($i = 0; $i < $size; ++$i) {
$key = $val = null;
if ($kread !== null) {
$xfer += $input->$kread($key);
} else {
switch ($ktype) {
case TType::STRUCT:
$class = $kspec['class'];
$key = new $class();
$xfer += $key->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($key, $kspec, $input);
break;
case TType::LST:
$xfer += $this->_readList($key, $kspec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($key, $kspec, $input, true);
break;
}
}
if ($vread !== null) {
$xfer += $input->$vread($val);
} else {
switch ($vtype) {
case TType::STRUCT:
$class = $vspec['class'];
$val = new $class();
$xfer += $val->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($val, $vspec, $input);
break;
case TType::LST:
$xfer += $this->_readList($val, $vspec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($val, $vspec, $input, true);
break;
}
}
$var[$key] = $val;
}
$xfer += $input->readMapEnd();
return $xfer;
}
private function _readList(&$var, $spec, $input, $set=false)
{
$xfer = 0;
$etype = $spec['etype'];
$eread = $vread = null;
if (isset(TBase::$tmethod[$etype])) {
$eread = 'read'.TBase::$tmethod[$etype];
} else {
$espec = $spec['elem'];
}
$var = array();
$_etype = $size = 0;
if ($set) {
$xfer += $input->readSetBegin($_etype, $size);
} else {
$xfer += $input->readListBegin($_etype, $size);
}
for ($i = 0; $i < $size; ++$i) {
$elem = null;
if ($eread !== null) {
$xfer += $input->$eread($elem);
} else {
$espec = $spec['elem'];
switch ($etype) {
case TType::STRUCT:
$class = $espec['class'];
$elem = new $class();
$xfer += $elem->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($elem, $espec, $input);
break;
case TType::LST:
$xfer += $this->_readList($elem, $espec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($elem, $espec, $input, true);
break;
}
}
if ($set) {
$var[$elem] = true;
} else {
$var []= $elem;
}
}
if ($set) {
$xfer += $input->readSetEnd();
} else {
$xfer += $input->readListEnd();
}
return $xfer;
}
protected function _read($class, $spec, $input)
{
$xfer = 0;
$fname = null;
$ftype = 0;
$fid = 0;
$xfer += $input->readStructBegin($fname);
while (true) {
$xfer += $input->readFieldBegin($fname, $ftype, $fid);
if ($ftype == TType::STOP) {
break;
}
if (isset($spec[$fid])) {
$fspec = $spec[$fid];
$var = $fspec['var'];
if ($ftype == $fspec['type']) {
$xfer = 0;
if (isset(TBase::$tmethod[$ftype])) {
$func = 'read'.TBase::$tmethod[$ftype];
$xfer += $input->$func($this->$var);
} else {
switch ($ftype) {
case TType::STRUCT:
$class = $fspec['class'];
$this->$var = new $class();
$xfer += $this->$var->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($this->$var, $fspec, $input);
break;
case TType::LST:
$xfer += $this->_readList($this->$var, $fspec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($this->$var, $fspec, $input, true);
break;
}
}
} else {
$xfer += $input->skip($ftype);
}
} else {
$xfer += $input->skip($ftype);
}
$xfer += $input->readFieldEnd();
}
$xfer += $input->readStructEnd();
return $xfer;
}
private function _writeMap($var, $spec, $output)
{
$xfer = 0;
$ktype = $spec['ktype'];
$vtype = $spec['vtype'];
$kwrite = $vwrite = null;
if (isset(TBase::$tmethod[$ktype])) {
$kwrite = 'write'.TBase::$tmethod[$ktype];
} else {
$kspec = $spec['key'];
}
if (isset(TBase::$tmethod[$vtype])) {
$vwrite = 'write'.TBase::$tmethod[$vtype];
} else {
$vspec = $spec['val'];
}
$xfer += $output->writeMapBegin($ktype, $vtype, count($var));
foreach ($var as $key => $val) {
if (isset($kwrite)) {
$xfer += $output->$kwrite($key);
} else {
switch ($ktype) {
case TType::STRUCT:
$xfer += $key->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($key, $kspec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($key, $kspec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($key, $kspec, $output, true);
break;
}
}
if (isset($vwrite)) {
$xfer += $output->$vwrite($val);
} else {
switch ($vtype) {
case TType::STRUCT:
$xfer += $val->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($val, $vspec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($val, $vspec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($val, $vspec, $output, true);
break;
}
}
}
$xfer += $output->writeMapEnd();
return $xfer;
}
private function _writeList($var, $spec, $output, $set=false)
{
$xfer = 0;
$etype = $spec['etype'];
$ewrite = null;
if (isset(TBase::$tmethod[$etype])) {
$ewrite = 'write'.TBase::$tmethod[$etype];
} else {
$espec = $spec['elem'];
}
if ($set) {
$xfer += $output->writeSetBegin($etype, count($var));
} else {
$xfer += $output->writeListBegin($etype, count($var));
}
foreach ($var as $key => $val) {
$elem = $set ? $key : $val;
if (isset($ewrite)) {
$xfer += $output->$ewrite($elem);
} else {
switch ($etype) {
case TType::STRUCT:
$xfer += $elem->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($elem, $espec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($elem, $espec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($elem, $espec, $output, true);
break;
}
}
}
if ($set) {
$xfer += $output->writeSetEnd();
} else {
$xfer += $output->writeListEnd();
}
return $xfer;
}
protected function _write($class, $spec, $output)
{
$xfer = 0;
$xfer += $output->writeStructBegin($class);
foreach ($spec as $fid => $fspec) {
$var = $fspec['var'];
if ($this->$var !== null) {
$ftype = $fspec['type'];
$xfer += $output->writeFieldBegin($var, $ftype, $fid);
if (isset(TBase::$tmethod[$ftype])) {
$func = 'write'.TBase::$tmethod[$ftype];
$xfer += $output->$func($this->$var);
} else {
switch ($ftype) {
case TType::STRUCT:
$xfer += $this->$var->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($this->$var, $fspec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($this->$var, $fspec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($this->$var, $fspec, $output, true);
break;
}
}
$xfer += $output->writeFieldEnd();
}
}
$xfer += $output->writeFieldStop();
$xfer += $output->writeStructEnd();
return $xfer;
}
}
/**
* Base class from which other Thrift structs extend. This is so that we can
* cut back on the size of the generated code which is turning out to have a
* nontrivial cost just to load thanks to the wondrously abysmal implementation
* of PHP. Note that code is intentionally duplicated in here to avoid making
* function calls for every field or member of a container..
*/
abstract class TBase
{
static $tmethod = array(TType::BOOL => 'Bool',
TType::BYTE => 'Byte',
TType::I16 => 'I16',
TType::I32 => 'I32',
TType::I64 => 'I64',
TType::DOUBLE => 'Double',
TType::STRING => 'String');
abstract public function read($input);
abstract public function write($output);
public function __construct($spec=null, $vals=null)
{
if (is_array($spec) && is_array($vals)) {
foreach ($spec as $fid => $fspec) {
$var = $fspec['var'];
if (isset($vals[$var])) {
$this->$var = $vals[$var];
}
}
}
}
private function _readMap(&$var, $spec, $input)
{
$xfer = 0;
$ktype = $spec['ktype'];
$vtype = $spec['vtype'];
$kread = $vread = null;
if (isset(TBase::$tmethod[$ktype])) {
$kread = 'read'.TBase::$tmethod[$ktype];
} else {
$kspec = $spec['key'];
}
if (isset(TBase::$tmethod[$vtype])) {
$vread = 'read'.TBase::$tmethod[$vtype];
} else {
$vspec = $spec['val'];
}
$var = array();
$_ktype = $_vtype = $size = 0;
$xfer += $input->readMapBegin($_ktype, $_vtype, $size);
for ($i = 0; $i < $size; ++$i) {
$key = $val = null;
if ($kread !== null) {
$xfer += $input->$kread($key);
} else {
switch ($ktype) {
case TType::STRUCT:
$class = $kspec['class'];
$key = new $class();
$xfer += $key->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($key, $kspec, $input);
break;
case TType::LST:
$xfer += $this->_readList($key, $kspec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($key, $kspec, $input, true);
break;
}
}
if ($vread !== null) {
$xfer += $input->$vread($val);
} else {
switch ($vtype) {
case TType::STRUCT:
$class = $vspec['class'];
$val = new $class();
$xfer += $val->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($val, $vspec, $input);
break;
case TType::LST:
$xfer += $this->_readList($val, $vspec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($val, $vspec, $input, true);
break;
}
}
$var[$key] = $val;
}
$xfer += $input->readMapEnd();
return $xfer;
}
private function _readList(&$var, $spec, $input, $set=false)
{
$xfer = 0;
$etype = $spec['etype'];
$eread = $vread = null;
if (isset(TBase::$tmethod[$etype])) {
$eread = 'read'.TBase::$tmethod[$etype];
} else {
$espec = $spec['elem'];
}
$var = array();
$_etype = $size = 0;
if ($set) {
$xfer += $input->readSetBegin($_etype, $size);
} else {
$xfer += $input->readListBegin($_etype, $size);
}
for ($i = 0; $i < $size; ++$i) {
$elem = null;
if ($eread !== null) {
$xfer += $input->$eread($elem);
} else {
$espec = $spec['elem'];
switch ($etype) {
case TType::STRUCT:
$class = $espec['class'];
$elem = new $class();
$xfer += $elem->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($elem, $espec, $input);
break;
case TType::LST:
$xfer += $this->_readList($elem, $espec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($elem, $espec, $input, true);
break;
}
}
if ($set) {
$var[$elem] = true;
} else {
$var []= $elem;
}
}
if ($set) {
$xfer += $input->readSetEnd();
} else {
$xfer += $input->readListEnd();
}
return $xfer;
}
protected function _read($class, $spec, $input)
{
$xfer = 0;
$fname = null;
$ftype = 0;
$fid = 0;
$xfer += $input->readStructBegin($fname);
while (true) {
$xfer += $input->readFieldBegin($fname, $ftype, $fid);
if ($ftype == TType::STOP) {
break;
}
if (isset($spec[$fid])) {
$fspec = $spec[$fid];
$var = $fspec['var'];
if ($ftype == $fspec['type']) {
$xfer = 0;
if (isset(TBase::$tmethod[$ftype])) {
$func = 'read'.TBase::$tmethod[$ftype];
$xfer += $input->$func($this->$var);
} else {
switch ($ftype) {
case TType::STRUCT:
$class = $fspec['class'];
$this->$var = new $class();
$xfer += $this->$var->read($input);
break;
case TType::MAP:
$xfer += $this->_readMap($this->$var, $fspec, $input);
break;
case TType::LST:
$xfer += $this->_readList($this->$var, $fspec, $input, false);
break;
case TType::SET:
$xfer += $this->_readList($this->$var, $fspec, $input, true);
break;
}
}
} else {
$xfer += $input->skip($ftype);
}
} else {
$xfer += $input->skip($ftype);
}
$xfer += $input->readFieldEnd();
}
$xfer += $input->readStructEnd();
return $xfer;
}
private function _writeMap($var, $spec, $output)
{
$xfer = 0;
$ktype = $spec['ktype'];
$vtype = $spec['vtype'];
$kwrite = $vwrite = null;
if (isset(TBase::$tmethod[$ktype])) {
$kwrite = 'write'.TBase::$tmethod[$ktype];
} else {
$kspec = $spec['key'];
}
if (isset(TBase::$tmethod[$vtype])) {
$vwrite = 'write'.TBase::$tmethod[$vtype];
} else {
$vspec = $spec['val'];
}
$xfer += $output->writeMapBegin($ktype, $vtype, count($var));
foreach ($var as $key => $val) {
if (isset($kwrite)) {
$xfer += $output->$kwrite($key);
} else {
switch ($ktype) {
case TType::STRUCT:
$xfer += $key->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($key, $kspec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($key, $kspec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($key, $kspec, $output, true);
break;
}
}
if (isset($vwrite)) {
$xfer += $output->$vwrite($val);
} else {
switch ($vtype) {
case TType::STRUCT:
$xfer += $val->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($val, $vspec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($val, $vspec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($val, $vspec, $output, true);
break;
}
}
}
$xfer += $output->writeMapEnd();
return $xfer;
}
private function _writeList($var, $spec, $output, $set=false)
{
$xfer = 0;
$etype = $spec['etype'];
$ewrite = null;
if (isset(TBase::$tmethod[$etype])) {
$ewrite = 'write'.TBase::$tmethod[$etype];
} else {
$espec = $spec['elem'];
}
if ($set) {
$xfer += $output->writeSetBegin($etype, count($var));
} else {
$xfer += $output->writeListBegin($etype, count($var));
}
foreach ($var as $key => $val) {
$elem = $set ? $key : $val;
if (isset($ewrite)) {
$xfer += $output->$ewrite($elem);
} else {
switch ($etype) {
case TType::STRUCT:
$xfer += $elem->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($elem, $espec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($elem, $espec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($elem, $espec, $output, true);
break;
}
}
}
if ($set) {
$xfer += $output->writeSetEnd();
} else {
$xfer += $output->writeListEnd();
}
return $xfer;
}
protected function _write($class, $spec, $output)
{
$xfer = 0;
$xfer += $output->writeStructBegin($class);
foreach ($spec as $fid => $fspec) {
$var = $fspec['var'];
if ($this->$var !== null) {
$ftype = $fspec['type'];
$xfer += $output->writeFieldBegin($var, $ftype, $fid);
if (isset(TBase::$tmethod[$ftype])) {
$func = 'write'.TBase::$tmethod[$ftype];
$xfer += $output->$func($this->$var);
} else {
switch ($ftype) {
case TType::STRUCT:
$xfer += $this->$var->write($output);
break;
case TType::MAP:
$xfer += $this->_writeMap($this->$var, $fspec, $output);
break;
case TType::LST:
$xfer += $this->_writeList($this->$var, $fspec, $output, false);
break;
case TType::SET:
$xfer += $this->_writeList($this->$var, $fspec, $output, true);
break;
}
}
$xfer += $output->writeFieldEnd();
}
}
$xfer += $output->writeFieldStop();
$xfer += $output->writeStructEnd();
return $xfer;
}
}
class TApplicationException extends TException
{
static $_TSPEC =
array(1 => array('var' => 'message',
'type' => TType::STRING),
2 => array('var' => 'code',
'type' => TType::I32));
const UNKNOWN = 0;
const UNKNOWN_METHOD = 1;
const INVALID_MESSAGE_TYPE = 2;
const WRONG_METHOD_NAME = 3;
const BAD_SEQUENCE_ID = 4;
const MISSING_RESULT = 5;
const INTERNAL_ERROR = 6;
const PROTOCOL_ERROR = 7;
public function __construct($message=null, $code=0)
{
parent::__construct($message, $code);
}
public function read($output)
{
return $this->_read('TApplicationException', self::$_TSPEC, $output);
}
public function write($output)
{
$xfer = 0;
$xfer += $output->writeStructBegin('TApplicationException');
if ($message = $this->getMessage()) {
$xfer += $output->writeFieldBegin('message', TType::STRING, 1);
$xfer += $output->writeString($message);
$xfer += $output->writeFieldEnd();
}
if ($code = $this->getCode()) {
$xfer += $output->writeFieldBegin('type', TType::I32, 2);
$xfer += $output->writeI32($code);
$xfer += $output->writeFieldEnd();
}
$xfer += $output->writeFieldStop();
$xfer += $output->writeStructEnd();
return $xfer;
}
}
/**
* Set global THRIFT ROOT automatically via inclusion here
*/
if (!isset($GLOBALS['THRIFT_ROOT'])) {
$GLOBALS['THRIFT_ROOT'] = dirname(__FILE__);
}
include_once $GLOBALS['THRIFT_ROOT'].'/protocol/TProtocol.php';
include_once $GLOBALS['THRIFT_ROOT'].'/transport/TTransport.php';
include_once $GLOBALS['THRIFT_ROOT'].'/TStringUtils.php';

View file

@ -0,0 +1,51 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift
*/
/**
* Include this file if you wish to use autoload with your PHP generated Thrift
* code. The generated code will *not* include any defined Thrift classes by
* default, except for the service interfaces. The generated code will populate
* values into $GLOBALS['THRIFT_AUTOLOAD'] which can be used by the autoload
* method below. If you have your own autoload system already in place, rename your
* __autoload function to something else and then do:
* $GLOBALS['AUTOLOAD_HOOKS'][] = 'my_autoload_func';
*
* Generate this code using the --gen php:autoload Thrift generator flag.
*/
$GLOBALS['THRIFT_AUTOLOAD'] = array();
$GLOBALS['AUTOLOAD_HOOKS'] = array();
if (!function_exists('__autoload')) {
function __autoload($class)
{
global $THRIFT_AUTOLOAD;
$classl = strtolower($class);
if (isset($THRIFT_AUTOLOAD[$classl])) {
include_once $GLOBALS['THRIFT_ROOT'].'/packages/'.$THRIFT_AUTOLOAD[$classl];
} elseif (!empty($GLOBALS['AUTOLOAD_HOOKS'])) {
foreach ($GLOBALS['AUTOLOAD_HOOKS'] as $hook) {
$hook($class);
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#pragma once
PHP_FUNCTION(thrift_protocol_write_binary);
PHP_FUNCTION(thrift_protocol_read_binary);
extern zend_module_entry thrift_protocol_module_entry;
#define phpext_thrift_protocol_ptr &thrift_protocol_module_entry

File diff suppressed because it is too large Load diff

61
vendor/git.apache.org/thrift.git/lib/php/test/Makefile.am generated vendored Executable file
View file

@ -0,0 +1,61 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
THRIFT = $(top_builddir)/compiler/cpp/thrift
stubs: ../../../test/ThriftTest.thrift TestValidators.thrift
mkdir -p ./packages
$(THRIFT) --gen php -r --out ./packages ../../../test/ThriftTest.thrift
mkdir -p ./packages/phpv
mkdir -p ./packages/phpvo
mkdir -p ./packages/phpjs
$(THRIFT) --gen php:validate -r --out ./packages/phpv TestValidators.thrift
$(THRIFT) --gen php:validate,oop -r --out ./packages/phpvo TestValidators.thrift
$(THRIFT) --gen php:json -r --out ./packages/phpjs TestValidators.thrift
check-json-serializer: stubs
if HAVE_PHPUNIT
$(PHPUNIT) --log-junit=TEST-json-serializer.xml Test/Thrift/JsonSerialize/
endif
check-validator: stubs
php Test/Thrift/TestValidators.php
php Test/Thrift/TestValidators.php -oop
check-protocol: stubs
if HAVE_PHPUNIT
$(PHPUNIT) --log-junit=TEST-log-json-protocol.xml Test/Thrift/Protocol/TestTJSONProtocol.php
$(PHPUNIT) --log-junit=TEST-binary-serializer.xml Test/Thrift/Protocol/TestBinarySerializer.php
$(PHPUNIT) --log-junit=TEST-log-simple-json-protocol.xml Test/Thrift/Protocol/TestTSimpleJSONProtocol.php
endif
check: stubs \
check-protocol \
check-validator \
check-json-serializer
clean-local:
$(RM) -r ./packages
$(RM) TEST-*.xml
EXTRA_DIST = \
Test \
TestValidators.thrift

View file

@ -0,0 +1,194 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.test
*/
namespace Test\Thrift;
use ThriftTest\Xtruct;
use ThriftTest\Xtruct2;
use ThriftTest\Numberz;
use ThriftTest\Insanity;
class Fixtures
{
public static $testArgs = array();
public static function populateTestArgs()
{
self::$testArgs['testString1'] = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, Norsk (nynorsk), Norsk (bokmål), Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語";
self::$testArgs['testString2'] =
"quote: \\\" backslash:" .
" forwardslash-escaped: \\/ " .
" backspace: \b formfeed: \f newline: \n return: \r tab: " .
" now-all-of-them-together: \"\\\/\b\n\r\t" .
" now-a-bunch-of-junk: !@#\$%&()(&%$#{}{}<><><";
self::$testArgs['testString3'] =
"string that ends in double-backslash \\\\";
self::$testArgs['testUnicodeStringWithNonBMP'] =
"สวัสดี/𝒯";
self::$testArgs['testDouble'] = 3.1415926535898;
// TODO: add testBinary() call
self::$testArgs['testByte'] = 0x01;
self::$testArgs['testI32'] = pow( 2, 30 );
if (PHP_INT_SIZE == 8) {
self::$testArgs['testI64'] = pow( 2, 60 );
} else {
self::$testArgs['testI64'] = "1152921504606847000";
}
self::$testArgs['testStruct'] =
new Xtruct(
array(
'string_thing' => 'worked',
'byte_thing' => 0x01,
'i32_thing' => pow( 2, 30 ),
'i64_thing' => self::$testArgs['testI64']
)
);
self::$testArgs['testNestNested'] =
new Xtruct(
array(
'string_thing' => 'worked',
'byte_thing' => 0x01,
'i32_thing' => pow( 2, 30 ),
'i64_thing' => self::$testArgs['testI64']
)
);
self::$testArgs['testNest'] =
new Xtruct2(
array(
'byte_thing' => 0x01,
'struct_thing' => self::$testArgs['testNestNested'],
'i32_thing' => pow( 2, 15 )
)
);
self::$testArgs['testMap'] =
array(
7 => 77,
8 => 88,
9 => 99
);
self::$testArgs['testStringMap'] =
array(
"a" => "123",
"a b" => "with spaces ",
"same" => "same",
"0" => "numeric key",
"longValue" => self::$testArgs['testString1'],
self::$testArgs['testString1'] => "long key"
);
self::$testArgs['testSet'] = array( 1 => true, 5 => true, 6 => true );
self::$testArgs['testList'] = array( 1, 2, 3 );
self::$testArgs['testEnum'] = Numberz::ONE;
self::$testArgs['testTypedef'] = 69;
self::$testArgs['testMapMapExpectedResult'] =
array(
4 => array(
1 => 1,
2 => 2,
3 => 3,
4 => 4,
),
-4 => array(
-4 => -4,
-3 => -3,
-2 => -2,
-1 => -1
)
);
// testInsanity ... takes a few steps to set up!
$xtruct1 =
new Xtruct(
array(
'string_thing' => 'Goodbye4',
'byte_thing' => 4,
'i32_thing' => 4,
'i64_thing' => 4
)
);
$xtruct2 =
new Xtruct(
array(
'string_thing' => 'Hello2',
'byte_thing' =>2,
'i32_thing' => 2,
'i64_thing' => 2
)
);
$userMap =
array(
Numberz::FIVE => 5,
Numberz::EIGHT => 8
);
$insanity2 =
new Insanity(
array(
'userMap' => $userMap,
'xtructs' => array($xtruct1,$xtruct2)
)
);
$insanity3 = $insanity2;
$insanity6 =
new Insanity(
array(
'userMap' => null,
'xtructs' => null
)
);
self::$testArgs['testInsanityExpectedResult'] =
array(
"1" => array(
Numberz::TWO => $insanity2,
Numberz::THREE => $insanity3
),
"2" => array(
Numberz::SIX => $insanity6
)
);
}
}

View file

@ -0,0 +1,116 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
namespace Test\Thrift\JsonSerialize;
use stdClass;
use Thrift\ClassLoader\ThriftClassLoader;
require_once __DIR__.'/../../../../lib/Thrift/ClassLoader/ThriftClassLoader.php';
$loader = new ThriftClassLoader();
$loader->registerNamespace('Thrift', __DIR__ . '/../../../../lib');
$loader->registerNamespace('Test', __DIR__ . '/../../..');
$loader->registerDefinition('ThriftTest', __DIR__ . '/../../../packages/phpjs');
$loader->register();
class JsonSerializeTest extends \PHPUnit_Framework_TestCase
{
protected function setUp() {
if (version_compare(phpversion(), '5.4', '<')) {
$this->markTestSkipped('Requires PHP 5.4 or newer!');
}
}
public function testEmptyStruct()
{
$empty = new \ThriftTest\EmptyStruct(array('non_existing_key' => 'bar'));
$this->assertEquals(new stdClass(), json_decode(json_encode($empty)));
}
public function testStringsAndInts()
{
$input = array(
'string_thing' => 'foo',
'i64_thing' => 1234567890,
);
$xtruct = new \ThriftTest\Xtruct($input);
// Xtruct's 'i32_thing' and 'byte_thing' fields should not be present here!
$expected = new stdClass();
$expected->string_thing = $input['string_thing'];
$expected->i64_thing = $input['i64_thing'];
$this->assertEquals($expected, json_decode(json_encode($xtruct)));
}
public function testNestedStructs()
{
$xtruct2 = new \ThriftTest\Xtruct2(array(
'byte_thing' => 42,
'struct_thing' => new \ThriftTest\Xtruct(array(
'i32_thing' => 123456,
)),
));
$expected = new stdClass();
$expected->byte_thing = $xtruct2->byte_thing;
$expected->struct_thing = new stdClass();
$expected->struct_thing->i32_thing = $xtruct2->struct_thing->i32_thing;
$this->assertEquals($expected, json_decode(json_encode($xtruct2)));
}
public function testInsanity()
{
$xinput = array('string_thing' => 'foo');
$xtruct = new \ThriftTest\Xtruct($xinput);
$insanity = new \ThriftTest\Insanity(array(
'xtructs' => array($xtruct, $xtruct, $xtruct)
));
$expected = new stdClass();
$expected->xtructs = array((object) $xinput, (object) $xinput, (object) $xinput);
$this->assertEquals($expected, json_decode(json_encode($insanity)));
}
public function testNestedLists()
{
$bonk = new \ThriftTest\Bonk(array('message' => 'foo'));
$nested = new \ThriftTest\NestedListsBonk(array('bonk' => array(array(array($bonk)))));
$expected = new stdClass();
$expected->bonk = array(array(array((object) array('message' => 'foo'))));
$this->assertEquals($expected, json_decode(json_encode($nested)));
}
public function testMaps()
{
$intmap = new \ThriftTest\ThriftTest_testMap_args(['thing' => [0 => 'zero']]);
$emptymap = new \ThriftTest\ThriftTest_testMap_args([]);
$this->assertEquals('{"thing":{"0":"zero"}}', json_encode($intmap));
$this->assertEquals('{}', json_encode($emptymap));
}
public function testScalarTypes()
{
$b = new \ThriftTest\Bools(['im_true' => '1', 'im_false' => '0']);
$this->assertEquals('{"im_true":true,"im_false":false}', json_encode($b));
$s = new \ThriftTest\StructA(['s' => 42]);
$this->assertEquals('{"s":"42"}', json_encode($s));
}
}

View file

@ -0,0 +1,64 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.test
*/
namespace Test\Thrift\Protocol;
use Thrift\ClassLoader\ThriftClassLoader;
use Thrift\Serializer\TBinarySerializer;
require_once __DIR__.'/../../../../lib/Thrift/ClassLoader/ThriftClassLoader.php';
$loader = new ThriftClassLoader();
$loader->registerNamespace('Thrift', __DIR__ . '/../../../../lib');
$loader->registerNamespace('Test', __DIR__ . '/../../..');
$loader->registerDefinition('ThriftTest', __DIR__ . '/../../../packages');
$loader->register();
/***
* This test suite depends on running the compiler against the
* standard ThriftTest.thrift file:
*
* lib/php/test$ ../../../compiler/cpp/thrift --gen php -r \
* --out ./packages ../../../test/ThriftTest.thrift
*/
class TestBinarySerializer extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
}
/**
* We try to serialize and deserialize a random object to make sure no exceptions are thrown.
* @see THRIFT-1579
*/
public function testBinarySerializer()
{
$struct = new \ThriftTest\Xtruct(array('string_thing' => 'abc'));
$serialized = TBinarySerializer::serialize($struct, 'ThriftTest\\Xtruct');
$deserialized = TBinarySerializer::deserialize($serialized, 'ThriftTest\\Xtruct');
$this->assertEquals($struct, $deserialized);
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,156 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
namespace test\php;
require_once __DIR__.'/../../../lib/Thrift/ClassLoader/ThriftClassLoader.php';
use Thrift\ClassLoader\ThriftClassLoader;
use Thrift\Exception\TProtocolException;
use Thrift\Protocol\TBinaryProtocol;
use Thrift\Transport\TMemoryBuffer;
$oop_mode = (isset($argv[1]) && $argv[1] === '-oop');
$GEN_DIR = $oop_mode ? 'phpvo' : 'phpv';
$loader = new ThriftClassLoader();
$loader->registerNamespace('Thrift', __DIR__ . '/../../../lib');
$loader->registerDefinition('ThriftTest', __DIR__ . '/../../packages/' . $GEN_DIR);
$loader->registerDefinition('TestValidators', __DIR__ . '/../../packages/' . $GEN_DIR);
$loader->register();
// Would be nice to have PHPUnit here, but for now just hack it.
set_exception_handler(function ($e) {
my_assert(false, "Unexpected exception caught: " . $e->getMessage());
});
set_error_handler(function ($errno, $errmsg) {
my_assert(false, "Unexpected PHP error: " . $errmsg);
});
// Empty structs should not have validators
assert_has_no_read_validator('ThriftTest\EmptyStruct');
assert_has_no_write_validator('ThriftTest\EmptyStruct');
// Bonk has only opt_in_req_out fields
{
assert_has_no_read_validator('ThriftTest\Bonk');
assert_has_a_write_validator('ThriftTest\Bonk');
{
// Check that we can read an empty object
$bonk = new \ThriftTest\Bonk();
$transport = new TMemoryBuffer("\000");
$protocol = new TBinaryProtocol($transport);
$bonk->read($protocol);
}
{
// ...but not write an empty object
$bonk = new \ThriftTest\Bonk();
$transport = new TMemoryBuffer();
$protocol = new TBinaryProtocol($transport);
assert_protocol_exception_thrown(function () use ($bonk, $protocol) { $bonk->write($protocol); },
'Bonk was able to write an empty object');
}
}
// StructA has a single required field
{
assert_has_a_read_validator('ThriftTest\StructA');
assert_has_a_write_validator('ThriftTest\StructA');
{
// Check that we are not able to write StructA with a missing required field
$structa = new \ThriftTest\StructA();
$transport = new TMemoryBuffer();
$protocol = new TBinaryProtocol($transport);
assert_protocol_exception_thrown(function () use ($structa, $protocol) { $structa->write($protocol); },
'StructA was able to write an empty object');
}
{
// Check that we are able to read and write a message with a good StructA
$transport = new TMemoryBuffer(base64_decode('CwABAAAAA2FiYwA='));
$protocol = new TBinaryProtocol($transport);
$structa = new \ThriftTest\StructA();
$structa->read($protocol);
$structa->write($protocol);
}
}
// Unions should not get write validators
assert_has_no_write_validator('TestValidators\UnionOfStrings');
// Service _result classes should not get any validators
assert_has_no_read_validator('TestValidators\TestService_test_result');
assert_has_no_write_validator('TestValidators\TestService_test_result');
function assert_has_a_read_validator($class)
{
my_assert(has_read_validator_method($class),
$class . ' class should have a read validator');
}
function assert_has_no_read_validator($class)
{
my_assert(!has_read_validator_method($class),
$class . ' class should not have a read validator');
}
function assert_has_a_write_validator($class)
{
my_assert(has_write_validator_method($class),
$class . ' class should have a write validator');
}
function assert_has_no_write_validator($class)
{
my_assert(!has_write_validator_method($class),
$class . ' class should not have a write validator');
}
function assert_protocol_exception_thrown($callable, $message)
{
try {
call_user_func($callable);
my_assert(false, $message);
} catch (TProtocolException $e) {
}
}
function has_write_validator_method($class)
{
$rc = new \ReflectionClass($class);
return $rc->hasMethod('_validateForWrite');
}
function has_read_validator_method($class)
{
$rc = new \ReflectionClass($class);
return $rc->hasMethod('_validateForRead');
}
function my_assert($something, $message)
{
if (!$something) {
fwrite(STDERR, basename(__FILE__) . " FAILED: $message\n");
exit(1);
}
}

View file

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
namespace php TestValidators
include "../../../test/ThriftTest.thrift"
union UnionOfStrings {
1: string aa;
2: string bb;
}
service TestService {
void test() throws(1: ThriftTest.Xception xception);
}

View file

@ -0,0 +1 @@
extension=thrift_protocol.so