summaryrefslogtreecommitdiff
path: root/php
diff options
context:
space:
mode:
Diffstat (limited to 'php')
-rwxr-xr-xphp/allTests.py1
-rw-r--r--php/lib/Ice.php17
-rw-r--r--php/lib/Ice_ns.php17
-rw-r--r--php/src/IcePHP/Communicator.cpp17
-rw-r--r--php/src/IcePHP/Config.h1
-rw-r--r--php/src/IcePHP/Init.cpp4
-rw-r--r--php/src/IcePHP/Makefile2
-rw-r--r--php/src/IcePHP/Operation.cpp239
-rw-r--r--php/src/IcePHP/Types.cpp1251
-rw-r--r--php/src/IcePHP/Types.h144
-rw-r--r--php/test/Ice/Makefile3
-rw-r--r--php/test/Ice/Makefile.mak3
-rw-r--r--php/test/Ice/optional/.depend2
-rw-r--r--php/test/Ice/optional/.depend.mak2
-rw-r--r--php/test/Ice/optional/.gitignore2
-rw-r--r--php/test/Ice/optional/Client.php736
-rw-r--r--php/test/Ice/optional/ClientPrivate.ice37
-rw-r--r--php/test/Ice/optional/Makefile27
-rw-r--r--php/test/Ice/optional/Makefile.mak25
-rw-r--r--php/test/Ice/optional/Test.ice246
-rwxr-xr-xphp/test/Ice/optional/run.py26
-rw-r--r--php/test/Ice/slicing/objects/Client.php13
-rw-r--r--php/test/Ice/slicing/objects/Test.ice1
23 files changed, 2334 insertions, 482 deletions
diff --git a/php/allTests.py b/php/allTests.py
index 6c64a6cfb09..6b8cd64291d 100755
--- a/php/allTests.py
+++ b/php/allTests.py
@@ -37,6 +37,7 @@ tests = [
("Ice/slicing/exceptions", ["core"]),
("Ice/slicing/objects", ["core"]),
("Ice/defaultValue", ["core"]),
+ ("Ice/optional", ["core"]),
("Ice/ini", ["once"]),
("Ice/scope", ["once"]),
("Slice/keyword", ["once"]),
diff --git a/php/lib/Ice.php b/php/lib/Ice.php
index c146f96a503..ea718c923a6 100644
--- a/php/lib/Ice.php
+++ b/php/lib/Ice.php
@@ -93,6 +93,17 @@ $Ice__t_LocalObject = IcePHP_defineClass('::Ice::LocalObject', "Ice_LocalObject"
$Ice__t_ObjectPrx = IcePHP_defineProxy($Ice__t_Object);
$Ice__t_ObjectProxySeq = IcePHP_defineSequence('::Ice::ObjectProxySeq', $Ice__t_ObjectPrx);
+class Ice_UnknownSlicedObject extends Ice_ObjectImpl
+{
+ public function __construct()
+ {
+ }
+
+ public $unknownTypeId;
+}
+
+$Ice__t_UnknownSlicedObject = IcePHP_defineClass('::Ice::UnknownSlicedObject', 'Ice_UnknownSlicedObject', false, true, $Ice__t_Object, null, null);
+
interface Ice_ObjectFactory
{
public function create($id);
@@ -149,10 +160,10 @@ $Ice_Protocol_1_0 = new Ice_ProtocolVersion(1, 0);
$Ice_Encoding_1_0 = new Ice_EncodingVersion(1, 0);
$Ice_Encoding_1_1 = new Ice_EncodingVersion(1, 1);
-IcePHP_defineOperation($Ice__t_Object, 'ice_isA', 2, 1, 0, array($IcePHP__t_string), null, $IcePHP__t_bool, null);
+IcePHP_defineOperation($Ice__t_Object, 'ice_isA', 2, 1, 0, array(array($IcePHP__t_string, false, 0)), null, array($IcePHP__t_bool, false, 0), null);
IcePHP_defineOperation($Ice__t_Object, 'ice_ping', 2, 1, 0, null, null, null, null);
-IcePHP_defineOperation($Ice__t_Object, 'ice_id', 2, 1, 0, null, null, $IcePHP__t_string, null);
-IcePHP_defineOperation($Ice__t_Object, 'ice_ids', 2, 1, 0, null, null, $Ice__t_StringSeq, null);
+IcePHP_defineOperation($Ice__t_Object, 'ice_id', 2, 1, 0, null, null, array($IcePHP__t_string, false, 0), null);
+IcePHP_defineOperation($Ice__t_Object, 'ice_ids', 2, 1, 0, null, null, array($Ice__t_StringSeq, false, 0), null);
//
// Proxy comparison functions.
diff --git a/php/lib/Ice_ns.php b/php/lib/Ice_ns.php
index f1229986f9d..81df7b84817 100644
--- a/php/lib/Ice_ns.php
+++ b/php/lib/Ice_ns.php
@@ -98,6 +98,17 @@ namespace Ice
$Ice__t_ObjectPrx = IcePHP_defineProxy($Ice__t_Object);
$Ice__t_ObjectProxySeq = IcePHP_defineSequence('::Ice::ObjectProxySeq', $Ice__t_ObjectPrx);
+ class UnknownSlicedObject extends ObjectImpl
+ {
+ public function __construct()
+ {
+ }
+
+ public $unknownTypeId;
+ }
+
+ $Ice__t_UnknownSlicedObject = IcePHP_defineClass('::Ice::UnknownSlicedObject', "\\Ice\\UnknownSlicedObject", false, true, $Ice__t_Object, null, null);
+
interface ObjectFactory
{
public function create($id);
@@ -157,10 +168,10 @@ $Ice_Protocol_1_0 = new Ice\ProtocolVersion(1, 0);
$Ice_Encoding_1_0 = new Ice\EncodingVersion(1, 0);
$Ice_Encoding_1_1 = new Ice\EncodingVersion(1, 1);
-IcePHP_defineOperation($Ice__t_Object, 'ice_isA', 2, 1, 0, array($IcePHP__t_string), array(), $IcePHP__t_bool, null);
+IcePHP_defineOperation($Ice__t_Object, 'ice_isA', 2, 1, 0, array(array($IcePHP__t_string, false, 0)), null, array($IcePHP__t_bool, false, 0), null);
IcePHP_defineOperation($Ice__t_Object, 'ice_ping', 2, 1, 0, null, null, null, null);
-IcePHP_defineOperation($Ice__t_Object, 'ice_id', 2, 1, 0, null, null, $IcePHP__t_string, null);
-IcePHP_defineOperation($Ice__t_Object, 'ice_ids', 2, 1, 0, null, null, $Ice__t_StringSeq, null);
+IcePHP_defineOperation($Ice__t_Object, 'ice_id', 2, 1, 0, null, null, array($IcePHP__t_string, false, 0), null);
+IcePHP_defineOperation($Ice__t_Object, 'ice_ids', 2, 1, 0, null, null, array($Ice__t_StringSeq, false, 0), null);
}
namespace Ice
diff --git a/php/src/IcePHP/Communicator.cpp b/php/src/IcePHP/Communicator.cpp
index 57e766eab31..d03801ade74 100644
--- a/php/src/IcePHP/Communicator.cpp
+++ b/php/src/IcePHP/Communicator.cpp
@@ -1592,7 +1592,20 @@ IcePHP::ObjectFactoryI::create(const string& id)
//
// Get the type information.
//
- ClassInfoPtr cls = getClassInfoById(id TSRMLS_CC);
+ ClassInfoPtr cls;
+ if(id == Ice::Object::ice_staticId())
+ {
+ //
+ // When the ID is that of Ice::Object, it indicates that the stream has not
+ // found a factory and is providing us an opportunity to preserve the object.
+ //
+ cls = getClassInfoById("::Ice::UnknownSlicedObject" TSRMLS_CC);
+ }
+ else
+ {
+ cls = getClassInfoById(id TSRMLS_CC);
+ }
+
if(!cls)
{
return 0;
@@ -1652,7 +1665,7 @@ IcePHP::ObjectFactoryI::create(const string& id)
MAKE_STD_ZVAL(obj);
AutoDestroy destroy(obj);
- if(object_init_ex(obj, cls->zce) != SUCCESS)
+ if(object_init_ex(obj, const_cast<zend_class_entry*>(cls->zce)) != SUCCESS)
{
throw AbortMarshaling();
}
diff --git a/php/src/IcePHP/Config.h b/php/src/IcePHP/Config.h
index 055e732a6c2..891640b12f1 100644
--- a/php/src/IcePHP/Config.h
+++ b/php/src/IcePHP/Config.h
@@ -87,6 +87,7 @@ ZEND_BEGIN_MODULE_GLOBALS(ice)
void* nameToClassInfoMap;
void* proxyInfoMap;
void* exceptionInfoMap;
+ zval* unset;
ZEND_END_MODULE_GLOBALS(ice)
#ifdef ZTS
diff --git a/php/src/IcePHP/Init.cpp b/php/src/IcePHP/Init.cpp
index 5f2f3f7d3a0..8e8e436df81 100644
--- a/php/src/IcePHP/Init.cpp
+++ b/php/src/IcePHP/Init.cpp
@@ -64,6 +64,7 @@ ZEND_END_ARG_INFO()
ZEND_FE(IcePHP_defineStruct, NULL) \
ZEND_FE(IcePHP_defineSequence, NULL) \
ZEND_FE(IcePHP_defineDictionary, NULL) \
+ ZEND_FE(IcePHP_declareProxy, NULL) \
ZEND_FE(IcePHP_defineProxy, NULL) \
ZEND_FE(IcePHP_declareClass, NULL) \
ZEND_FE(IcePHP_defineClass, NULL) \
@@ -149,6 +150,7 @@ int initIceGlobals(zend_ice_globals* g)
g->nameToClassInfoMap = 0;
g->proxyInfoMap = 0;
g->exceptionInfoMap = 0;
+ g->unset = 0;
return SUCCESS;
}
@@ -172,7 +174,7 @@ ZEND_MINIT_FUNCTION(ice)
return FAILURE;
}
- if(!typesInit(TSRMLS_C))
+ if(!typesInit(INIT_FUNC_ARGS_PASSTHRU))
{
return FAILURE;
}
diff --git a/php/src/IcePHP/Makefile b/php/src/IcePHP/Makefile
index 910b4e6e031..f596e15861d 100644
--- a/php/src/IcePHP/Makefile
+++ b/php/src/IcePHP/Makefile
@@ -29,7 +29,7 @@ SRCS = $(OBJS:.o=.cpp)
include $(top_srcdir)/config/Make.rules.php
-CPPFLAGS := -I. $(CPPFLAGS) $(ICE_FLAGS) $(PHP_FLAGS)
+CPPFLAGS := -I. $(CPPFLAGS) $(ICE_FLAGS) $(PHP_FLAGS) -DPHP_DEBUG
LINKWITH := $(ICE_LIBS) $(PHP_LIBS) $(CXXLIBS)
diff --git a/php/src/IcePHP/Operation.cpp b/php/src/IcePHP/Operation.cpp
index db68b52ee24..bb8c1e3cebb 100644
--- a/php/src/IcePHP/Operation.cpp
+++ b/php/src/IcePHP/Operation.cpp
@@ -26,6 +26,18 @@ ZEND_FUNCTION(IcePHP_Operation_call);
namespace IcePHP
{
+class ParamInfo : public IceUtil::Shared
+{
+public:
+
+ TypeInfoPtr type;
+ bool optional;
+ int tag;
+ int pos;
+};
+typedef IceUtil::Handle<ParamInfo> ParamInfoPtr;
+typedef list<ParamInfoPtr> ParamInfoList;
+
//
// Receives an out parameter or return value.
//
@@ -38,6 +50,8 @@ public:
virtual void unmarshaled(zval*, zval*, void* TSRMLS_DC);
+ void unset(TSRMLS_D);
+
zval* zv;
};
typedef IceUtil::Handle<ResultCallback> ResultCallbackPtr;
@@ -60,20 +74,21 @@ public:
Ice::OperationMode mode;
Ice::OperationMode sendMode;
Ice::FormatType format;
- TypeInfoList inParams;
- TypeInfoList outParams;
- TypeInfoPtr returnType;
+ ParamInfoList inParams;
+ ParamInfoList optionalInParams;
+ ParamInfoList outParams;
+ ParamInfoList optionalOutParams;
+ ParamInfoPtr returnType;
ExceptionInfoList exceptions;
- bool sendsClasses;
- bool returnsClasses;
int numParams;
private:
zend_internal_function* _zendFunction;
- static void convertParams(zval*, TypeInfoList&, bool& TSRMLS_DC);
- static void getArgInfo(zend_arg_info&, const TypeInfoPtr&, bool);
+ static void convertParams(zval*, ParamInfoList& TSRMLS_DC);
+ static ParamInfoPtr convertParam(zval*, int TSRMLS_DC);
+ static void getArgInfo(zend_arg_info&, const ParamInfoPtr&, bool);
};
typedef IceUtil::Handle<OperationI> OperationIPtr;
@@ -188,19 +203,26 @@ IcePHP::ResultCallback::unmarshaled(zval* val, zval*, void* TSRMLS_DC)
Z_ADDREF_P(zv);
}
+void
+IcePHP::ResultCallback::unset(TSRMLS_D)
+{
+ MAKE_STD_ZVAL(zv);
+ IcePHP::unset(zv TSRMLS_DC);
+}
+
//
// OperationI implementation.
//
IcePHP::OperationI::OperationI(const char* n, Ice::OperationMode m, Ice::OperationMode sm, Ice::FormatType f, zval* in,
zval* out, zval* ret, zval* ex TSRMLS_DC) :
- name(n), mode(m), sendMode(sm), format(f), sendsClasses(false), returnsClasses(false), _zendFunction(0)
+ name(n), mode(m), sendMode(sm), format(f), _zendFunction(0)
{
//
// inParams
//
if(in)
{
- convertParams(in, inParams, sendsClasses TSRMLS_CC);
+ convertParams(in, inParams TSRMLS_CC);
}
//
@@ -208,22 +230,53 @@ IcePHP::OperationI::OperationI(const char* n, Ice::OperationMode m, Ice::Operati
//
if(out)
{
- convertParams(out, outParams, returnsClasses TSRMLS_CC);
+ convertParams(out, outParams TSRMLS_CC);
}
- numParams = static_cast<int>(inParams.size() + outParams.size());
-
//
// returnType
//
if(ret)
{
- returnType = Wrapper<TypeInfoPtr>::value(ret TSRMLS_CC);
- if(!returnsClasses)
+ returnType = convertParam(ret, 0 TSRMLS_CC);
+ }
+
+ numParams = static_cast<int>(inParams.size() + outParams.size());
+
+ class SortFn
+ {
+ public:
+ static bool compare(const ParamInfoPtr& lhs, const ParamInfoPtr& rhs)
{
- returnsClasses = returnType->usesClasses();
+ return lhs->tag < rhs->tag;
}
+
+ static bool isRequired(const ParamInfoPtr& i)
+ {
+ return !i->optional;
+ }
+ };
+
+ //
+ // The inParams list represents the parameters in the order of declaration.
+ // We also need a sorted list of optional parameters.
+ //
+ ParamInfoList l = inParams;
+ copy(l.begin(), remove_if(l.begin(), l.end(), SortFn::isRequired), back_inserter(optionalInParams));
+ optionalInParams.sort(SortFn::compare);
+
+ //
+ // The outParams list represents the parameters in the order of declaration.
+ // We also need a sorted list of optional parameters. If the return value is
+ // optional, we must include it in this list.
+ //
+ l = outParams;
+ copy(l.begin(), remove_if(l.begin(), l.end(), SortFn::isRequired), back_inserter(optionalOutParams));
+ if(returnType && returnType->optional)
+ {
+ optionalOutParams.push_back(returnType);
}
+ optionalOutParams.sort(SortFn::compare);
//
// exceptions
@@ -265,7 +318,7 @@ IcePHP::OperationI::function()
zend_arg_info* argInfo = new zend_arg_info[numParams];
int i = 0;
- TypeInfoList::const_iterator p;
+ ParamInfoList::const_iterator p;
for(p = inParams.begin(); p != inParams.end(); ++p, ++i)
{
getArgInfo(argInfo[i], *p, false);
@@ -302,43 +355,73 @@ IcePHP::OperationI::function()
}
void
-IcePHP::OperationI::convertParams(zval* p, TypeInfoList& params, bool& usesClasses TSRMLS_DC)
+IcePHP::OperationI::convertParams(zval* p, ParamInfoList& params TSRMLS_DC)
{
- usesClasses = false;
-
assert(Z_TYPE_P(p) == IS_ARRAY);
HashTable* arr = Z_ARRVAL_P(p);
HashPosition pos;
zend_hash_internal_pointer_reset_ex(arr, &pos);
void* data;
+ int i = 0;
while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
{
zval** val = reinterpret_cast<zval**>(data);
- TypeInfoPtr type = Wrapper<TypeInfoPtr>::value(*val TSRMLS_CC);
- params.push_back(type);
- if(!usesClasses)
- {
- usesClasses = type->usesClasses();
- }
+ params.push_back(convertParam(*val, i TSRMLS_CC));
zend_hash_move_forward_ex(arr, &pos);
+ ++i;
}
}
+ParamInfoPtr
+IcePHP::OperationI::convertParam(zval* p, int pos TSRMLS_DC)
+{
+ assert(Z_TYPE_P(p) == IS_ARRAY);
+ HashTable* arr = Z_ARRVAL_P(p);
+ assert(zend_hash_num_elements(arr) == 3);
+
+ ParamInfoPtr param = new ParamInfo;
+ zval** m;
+
+ zend_hash_index_find(arr, 0, reinterpret_cast<void**>(&m));
+ param->type = Wrapper<TypeInfoPtr>::value(*m TSRMLS_CC);
+ zend_hash_index_find(arr, 1, reinterpret_cast<void**>(&m));
+ assert(Z_TYPE_PP(m) == IS_BOOL);
+ param->optional = Z_BVAL_PP(m) ? true : false;
+ zend_hash_index_find(arr, 2, reinterpret_cast<void**>(&m));
+ assert(Z_TYPE_PP(m) == IS_LONG);
+ param->tag = Z_LVAL_PP(m);
+ param->pos = pos;
+
+ return param;
+}
+
void
-IcePHP::OperationI::getArgInfo(zend_arg_info& arg, const TypeInfoPtr& info, bool out)
+IcePHP::OperationI::getArgInfo(zend_arg_info& arg, const ParamInfoPtr& info, bool out)
{
arg.name = 0;
arg.class_name = 0;
arg.allow_null = 1;
- const bool isArray = SequenceInfoPtr::dynamicCast(info) || DictionaryInfoPtr::dynamicCast(info);
+ if(!info->optional)
+ {
+ const bool isArray = SequenceInfoPtr::dynamicCast(info->type) || DictionaryInfoPtr::dynamicCast(info->type);
#if PHP_VERSION_ID < 50400
- arg.array_type_hint = isArray ? 1 : 0;
- arg.return_reference = 0;
+ arg.array_type_hint = isArray ? 1 : 0;
+ arg.return_reference = 0;
+#else
+ arg.type_hint = isArray ? IS_ARRAY : 0;
+#endif
+ }
+ else
+ {
+#if PHP_VERSION_ID < 50400
+ arg.array_type_hint = 0;
+ arg.return_reference = 0;
#else
- arg.type_hint = isArray ? IS_ARRAY : 0;
+ arg.type_hint = 0;
#endif
+ }
arg.pass_by_reference = out ? 1 : 0;
}
@@ -395,16 +478,47 @@ IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::ByteSeq& byt
os->startEncapsulation(_prx->ice_getEncodingVersion(), _op->format);
ObjectMap objectMap;
- int i = 0;
- for(TypeInfoList::iterator p = _op->inParams.begin(); p != _op->inParams.end(); ++p, ++i)
+ ParamInfoList::iterator p;
+
+ //
+ // Validate the supplied arguments.
+ //
+ for(p = _op->inParams.begin(); p != _op->inParams.end(); ++p)
{
- zval* arg = args[i];
- if(!(*p)->validate(arg TSRMLS_CC))
+ ParamInfoPtr info = *p;
+ zval* arg = args[info->pos];
+ if((!info->optional || !isUnset(arg TSRMLS_CC)) && !info->type->validate(arg TSRMLS_CC))
{
- invalidArgument("invalid value for argument %d in operation `%s'" TSRMLS_CC, i, _op->name.c_str());
+ invalidArgument("invalid value for argument %d in operation `%s'" TSRMLS_CC, info->pos + 1,
+ _op->name.c_str());
return false;
}
- (*p)->marshal(arg, os, &objectMap TSRMLS_CC);
+ }
+
+ //
+ // Marshal the required parameters.
+ //
+ for(p = _op->inParams.begin(); p != _op->inParams.end(); ++p)
+ {
+ ParamInfoPtr info = *p;
+ if(!info->optional)
+ {
+ zval* arg = args[info->pos];
+ info->type->marshal(arg, os, &objectMap, false TSRMLS_CC);
+ }
+ }
+
+ //
+ // Marshal the optional parameters.
+ //
+ for(p = _op->optionalInParams.begin(); p != _op->optionalInParams.end(); ++p)
+ {
+ ParamInfoPtr info = *p;
+ zval* arg = args[info->pos];
+ if(!isUnset(arg TSRMLS_CC) && os->writeOptional(info->tag, info->type->optionalFormat()))
+ {
+ info->type->marshal(arg, os, &objectMap, true TSRMLS_CC);
+ }
}
os->endEncapsulation();
@@ -440,6 +554,8 @@ IcePHP::TypedInvocation::unmarshalResults(int argc, zval** args, zval* ret,
is->startEncapsulation();
+ ParamInfoList::iterator p;
+
//
// These callbacks collect references to the unmarshaled values. We copy them into
// the argument list *after* any pending objects have been unmarshaled.
@@ -447,23 +563,56 @@ IcePHP::TypedInvocation::unmarshalResults(int argc, zval** args, zval* ret,
ResultCallbackList outParamCallbacks;
ResultCallbackPtr retCallback;
+ outParamCallbacks.resize(_op->outParams.size());
+
//
- // Unmarshal the out parameters.
+ // Unmarshal the required out parameters.
//
- for(TypeInfoList::iterator p = _op->outParams.begin(); p != _op->outParams.end(); ++p)
+ for(p = _op->outParams.begin(); p != _op->outParams.end(); ++p)
{
- ResultCallbackPtr cb = new ResultCallback;
- outParamCallbacks.push_back(cb);
- (*p)->unmarshal(is, cb, _communicator, 0, 0 TSRMLS_CC);
+ ParamInfoPtr info = *p;
+ if(!info->optional)
+ {
+ ResultCallbackPtr cb = new ResultCallback;
+ outParamCallbacks[info->pos] = cb;
+ info->type->unmarshal(is, cb, _communicator, 0, 0, false TSRMLS_CC);
+ }
}
//
- // Unmarshal the return value.
+ // Unmarshal the required return value, if any.
//
- if(_op->returnType)
+ if(_op->returnType && !_op->returnType->optional)
{
retCallback = new ResultCallback;
- _op->returnType->unmarshal(is, retCallback, _communicator, 0, 0 TSRMLS_CC);
+ _op->returnType->type->unmarshal(is, retCallback, _communicator, 0, 0, false TSRMLS_CC);
+ }
+
+ //
+ // Unmarshal the optional results. This includes an optional return value.
+ //
+ for(p = _op->optionalOutParams.begin(); p != _op->optionalOutParams.end(); ++p)
+ {
+ ParamInfoPtr info = *p;
+
+ ResultCallbackPtr cb = new ResultCallback;
+ if(info->tag == _op->returnType->tag)
+ {
+ retCallback = cb;
+ }
+ else
+ {
+ outParamCallbacks[info->pos] = cb;
+ }
+
+ if(is->readOptional(info->tag, info->type->optionalFormat()))
+ {
+ info->type->unmarshal(is, cb, _communicator, 0, 0, true TSRMLS_CC);
+ }
+ else
+ {
+ cb->unset(TSRMLS_C);
+ }
}
is->endEncapsulation();
@@ -695,7 +844,7 @@ ZEND_FUNCTION(IcePHP_defineOperation)
zval* returnType;
zval* exceptions;
- if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("osllla!a!o!a!"), &cls, &name, &nameLen,
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("osllla!a!a!a!"), &cls, &name, &nameLen,
&mode, &sendMode, &format, &inParams, &outParams, &returnType, &exceptions) == FAILURE)
{
return;
diff --git a/php/src/IcePHP/Types.cpp b/php/src/IcePHP/Types.cpp
index 7a3892feba8..4e34f204ce2 100644
--- a/php/src/IcePHP/Types.cpp
+++ b/php/src/IcePHP/Types.cpp
@@ -35,6 +35,8 @@ zend_class_entry* exceptionInfoClassEntry = 0;
static zend_object_handlers _typeInfoHandlers;
static zend_object_handlers _exceptionInfoHandlers;
+static string _unsetGUID = "710A52F2-A014-4CB2-AF40-348D48DBCDDD";
+
extern "C"
{
static zend_object_value handleTypeInfoAlloc(zend_class_entry* TSRMLS_DC);
@@ -49,6 +51,25 @@ typedef map<string, ClassInfoPtr> ClassInfoMap;
typedef map<string, ExceptionInfoPtr> ExceptionInfoMap;
//
+// addProxyInfo()
+//
+static void
+addProxyInfo(const ProxyInfoPtr& p TSRMLS_DC)
+{
+ ProxyInfoMap* m;
+ if(ICE_G(proxyInfoMap))
+ {
+ m = reinterpret_cast<ProxyInfoMap*>(ICE_G(proxyInfoMap));
+ }
+ else
+ {
+ m = new ProxyInfoMap;
+ ICE_G(proxyInfoMap) = m;
+ }
+ m->insert(ProxyInfoMap::value_type(p->id, p));
+}
+
+//
// getProxyInfo()
//
static IcePHP::ProxyInfoPtr
@@ -444,12 +465,17 @@ IcePHP::SlicedDataUtil::getMember(zval* obj, ObjectMap* objectMap TSRMLS_DC)
if(Z_TYPE_P(sd) != IS_NULL)
{
+#ifndef NDEBUG
int status;
+#endif
//
// The "slices" member is an array of Ice_SliceInfo objects.
//
- status = zend_hash_find(Z_OBJPROP_P(sd), STRCAST("slices"), sizeof("slices"), &data);
+#ifndef NDEBUG
+ status =
+#endif
+ zend_hash_find(Z_OBJPROP_P(sd), STRCAST("slices"), sizeof("slices"), &data);
assert(status == SUCCESS);
zval* sl = *(reinterpret_cast<zval**>(data));
assert(Z_TYPE_P(sl) == IS_ARRAY);
@@ -468,13 +494,19 @@ IcePHP::SlicedDataUtil::getMember(zval* obj, ObjectMap* objectMap TSRMLS_DC)
Ice::SliceInfoPtr info = new Ice::SliceInfo;
- status = zend_hash_find(Z_OBJPROP_P(s), STRCAST("typeId"), sizeof("typeId"), &data);
+#ifndef NDEBUG
+ status =
+#endif
+ zend_hash_find(Z_OBJPROP_P(s), STRCAST("typeId"), sizeof("typeId"), &data);
assert(status == SUCCESS);
zval* typeId = *(reinterpret_cast<zval**>(data));
assert(Z_TYPE_P(typeId) == IS_STRING);
info->typeId = string(Z_STRVAL_P(typeId), Z_STRLEN_P(typeId));
- status = zend_hash_find(Z_OBJPROP_P(s), STRCAST("bytes"), sizeof("bytes"), &data);
+#ifndef NDEBUG
+ status =
+#endif
+ zend_hash_find(Z_OBJPROP_P(s), STRCAST("bytes"), sizeof("bytes"), &data);
assert(status == SUCCESS);
zval* bytes = *(reinterpret_cast<zval**>(data));
assert(Z_TYPE_P(bytes) == IS_ARRAY);
@@ -493,7 +525,10 @@ IcePHP::SlicedDataUtil::getMember(zval* obj, ObjectMap* objectMap TSRMLS_DC)
zend_hash_move_forward_ex(barr, &bpos);
}
- status = zend_hash_find(Z_OBJPROP_P(s), STRCAST("objects"), sizeof("objects"), &data);
+#ifndef NDEBUG
+ status =
+#endif
+ zend_hash_find(Z_OBJPROP_P(s), STRCAST("objects"), sizeof("objects"), &data);
assert(status == SUCCESS);
zval* objects = *(reinterpret_cast<zval**>(data));
assert(Z_TYPE_P(objects) == IS_ARRAY);
@@ -548,12 +583,6 @@ IcePHP::TypeInfo::TypeInfo()
{
}
-bool
-IcePHP::TypeInfo::usesClasses()
-{
- return false;
-}
-
void
IcePHP::TypeInfo::unmarshaled(zval*, zval*, void* TSRMLS_DC)
{
@@ -720,8 +749,65 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC)
return true;
}
+bool
+IcePHP::PrimitiveInfo::variableLength() const
+{
+ return kind == KindString;
+}
+
+int
+IcePHP::PrimitiveInfo::wireSize() const
+{
+ switch(kind)
+ {
+ case KindBool:
+ case KindByte:
+ return 1;
+ case KindShort:
+ return 2;
+ case KindInt:
+ return 4;
+ case KindLong:
+ return 8;
+ case KindFloat:
+ return 4;
+ case KindDouble:
+ return 8;
+ case KindString:
+ return 1;
+ }
+ assert(false);
+ return 0;
+}
+
+Ice::OptionalFormat
+IcePHP::PrimitiveInfo::optionalFormat() const
+{
+ switch(kind)
+ {
+ case KindBool:
+ case KindByte:
+ return Ice::OptionalFormatF1;
+ case KindShort:
+ return Ice::OptionalFormatF2;
+ case KindInt:
+ return Ice::OptionalFormatF4;
+ case KindLong:
+ return Ice::OptionalFormatF8;
+ case KindFloat:
+ return Ice::OptionalFormatF4;
+ case KindDouble:
+ return Ice::OptionalFormatF8;
+ case KindString:
+ return Ice::OptionalFormatVSize;
+ }
+
+ assert(false);
+ return Ice::OptionalFormatF1;
+}
+
void
-IcePHP::PrimitiveInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* TSRMLS_DC)
+IcePHP::PrimitiveInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap*, bool TSRMLS_DC)
{
switch(kind)
{
@@ -830,7 +916,7 @@ IcePHP::PrimitiveInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectM
void
IcePHP::PrimitiveInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb,
- const CommunicatorInfoPtr&, zval* target, void* closure TSRMLS_DC)
+ const CommunicatorInfoPtr&, zval* target, void* closure, bool TSRMLS_DC)
{
zval* zv;
MAKE_STD_ZVAL(zv);
@@ -931,6 +1017,22 @@ IcePHP::PrimitiveInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObject
//
// EnumInfo implementation.
//
+IcePHP::EnumInfo::EnumInfo(const string& ident, zval* en TSRMLS_DC) :
+ id(ident)
+{
+ HashTable* arr = Z_ARRVAL_P(en);
+ void* data;
+ HashPosition pos;
+ zend_hash_internal_pointer_reset_ex(arr, &pos);
+ while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
+ {
+ zval** val = reinterpret_cast<zval**>(data);
+ assert(Z_TYPE_PP(val) == IS_STRING);
+ const_cast<Ice::StringSeq&>(enumerators).push_back(Z_STRVAL_PP(val));
+ zend_hash_move_forward_ex(arr, &pos);
+ }
+}
+
string
IcePHP::EnumInfo::getId() const
{
@@ -948,54 +1050,45 @@ IcePHP::EnumInfo::validate(zval* zv TSRMLS_DC)
return false;
}
+bool
+IcePHP::EnumInfo::variableLength() const
+{
+ return true;
+}
+
+int
+IcePHP::EnumInfo::wireSize() const
+{
+ return 1;
+}
+
+Ice::OptionalFormat
+IcePHP::EnumInfo::optionalFormat() const
+{
+ return Ice::OptionalFormatSize;
+}
+
void
-IcePHP::EnumInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* TSRMLS_DC)
+IcePHP::EnumInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap*, bool TSRMLS_DC)
{
assert(Z_TYPE_P(zv) == IS_LONG); // validate() should have caught this.
Ice::Int val = static_cast<Ice::Int>(Z_LVAL_P(zv));
- Ice::Int count = static_cast<Ice::Int>(enumerators.size());
+ const Ice::Int count = static_cast<Ice::Int>(enumerators.size());
assert(val >= 0 && val < count); // validate() should have caught this.
- if(count <= 127)
- {
- os->write(static_cast<Ice::Byte>(val));
- }
- else if(count <= 32767)
- {
- os->write(static_cast<Ice::Short>(val));
- }
- else
- {
- os->write(val);
- }
+ os->writeEnum(val, count);
}
void
IcePHP::EnumInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb,
- const CommunicatorInfoPtr&, zval* target, void* closure TSRMLS_DC)
+ const CommunicatorInfoPtr&, zval* target, void* closure, bool TSRMLS_DC)
{
zval* zv;
ALLOC_INIT_ZVAL(zv);
AutoDestroy destroy(zv);
- Ice::Int val;
- Ice::Int count = static_cast<Ice::Int>(enumerators.size());
- if(count <= 127)
- {
- Ice::Byte b;
- is->read(b);
- val = b;
- }
- else if(count <= 32767)
- {
- Ice::Short sh;
- is->read(sh);
- val = sh;
- }
- else
- {
- is->read(val);
- }
+ const Ice::Int count = static_cast<Ice::Int>(enumerators.size());
+ Ice::Int val = is->readEnum(count);
if(val < 0 || val >= count)
{
@@ -1025,6 +1118,12 @@ IcePHP::EnumInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHisto
void
IcePHP::DataMember::unmarshaled(zval* zv, zval* target, void* TSRMLS_DC)
{
+ setMember(target, zv TSRMLS_CC);
+}
+
+void
+IcePHP::DataMember::setMember(zval* target, zval* zv TSRMLS_DC)
+{
assert(Z_TYPE_P(target) == IS_OBJECT);
//
@@ -1049,9 +1148,100 @@ IcePHP::DataMember::unmarshaled(zval* zv, zval* target, void* TSRMLS_DC)
}
}
+static void
+convertDataMembers(zval* zv, DataMemberList& reqMembers, DataMemberList& optMembers, bool allowOptional TSRMLS_DC)
+{
+ list<DataMemberPtr> optList;
+
+ assert(Z_TYPE_P(zv) == IS_ARRAY);
+ HashTable* membersArray = Z_ARRVAL_P(zv);
+ void* data;
+ HashPosition pos;
+ zend_hash_internal_pointer_reset_ex(membersArray, &pos);
+ while(zend_hash_get_current_data_ex(membersArray, &data, &pos) != FAILURE)
+ {
+ zval** arr = reinterpret_cast<zval**>(data);
+
+ DataMemberPtr m = new DataMember();
+ zval** elem;
+
+ assert(Z_TYPE_PP(arr) == IS_ARRAY);
+ HashTable* member = Z_ARRVAL_PP(arr);
+ assert(zend_hash_num_elements(member) == allowOptional ? 4 : 2);
+ zend_hash_index_find(member, 0, reinterpret_cast<void**>(&elem));
+ assert(Z_TYPE_PP(elem) == IS_STRING);
+ m->name = Z_STRVAL_PP(elem);
+ zend_hash_index_find(member, 1, reinterpret_cast<void**>(&elem));
+ assert(Z_TYPE_PP(elem) == IS_OBJECT);
+ m->type = Wrapper<TypeInfoPtr>::value(*elem TSRMLS_CC);
+
+ if(allowOptional)
+ {
+ zend_hash_index_find(member, 2, reinterpret_cast<void**>(&elem));
+ assert(Z_TYPE_PP(elem) == IS_BOOL);
+ m->optional = Z_BVAL_PP(elem) ? true : false;
+ zend_hash_index_find(member, 3, reinterpret_cast<void**>(&elem));
+ assert(Z_TYPE_PP(elem) == IS_LONG);
+ m->tag = static_cast<int>(Z_LVAL_PP(elem));
+ }
+ else
+ {
+ m->optional = false;
+ m->tag = 0;
+ }
+
+ if(m->optional)
+ {
+ optList.push_back(m);
+ }
+ else
+ {
+ reqMembers.push_back(m);
+ }
+
+ zend_hash_move_forward_ex(membersArray, &pos);
+ }
+
+ if(allowOptional)
+ {
+ class SortFn
+ {
+ public:
+ static bool compare(const DataMemberPtr& lhs, const DataMemberPtr& rhs)
+ {
+ return lhs->tag < rhs->tag;
+ }
+ };
+
+ optList.sort(SortFn::compare);
+ copy(optList.begin(), optList.end(), back_inserter(optMembers));
+ }
+}
+
//
// StructInfo implementation.
//
+IcePHP::StructInfo::StructInfo(const string& ident, const string& n, zval* m TSRMLS_DC) :
+ id(ident), name(n)
+{
+ DataMemberList opt;
+ convertDataMembers(m, const_cast<DataMemberList&>(members), opt, false TSRMLS_CC);
+ assert(opt.empty());
+ const_cast<zend_class_entry*&>(zce) = nameToClass(name TSRMLS_CC);
+ assert(zce);
+
+ _variableLength = false;
+ _wireSize = 0;
+ for(DataMemberList::const_iterator p = members.begin(); p != members.end(); ++p)
+ {
+ if(!_variableLength && (*p)->type->variableLength())
+ {
+ _variableLength = true;
+ }
+ _wireSize += (*p)->type->wireSize();
+ }
+}
+
string
IcePHP::StructInfo::getId() const
{
@@ -1082,26 +1272,42 @@ IcePHP::StructInfo::validate(zval* zv TSRMLS_DC)
}
bool
-IcePHP::StructInfo::usesClasses()
+IcePHP::StructInfo::variableLength() const
{
- for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q)
- {
- if((*q)->type->usesClasses())
- {
- return true;
- }
- }
+ return _variableLength;
+}
- return false;
+int
+IcePHP::StructInfo::wireSize() const
+{
+ return _wireSize;
+}
+
+Ice::OptionalFormat
+IcePHP::StructInfo::optionalFormat() const
+{
+ return _variableLength ? Ice::OptionalFormatFSize : Ice::OptionalFormatVSize;
}
void
-IcePHP::StructInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap TSRMLS_DC)
+IcePHP::StructInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional TSRMLS_DC)
{
assert(Z_TYPE_P(zv) == IS_OBJECT); // validate() should have caught this.
assert(Z_OBJCE_P(zv) == zce); // validate() should have caught this.
- for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q)
+ if(optional)
+ {
+ if(_variableLength)
+ {
+ os->startSize();
+ }
+ else
+ {
+ os->writeSize(_wireSize);
+ }
+ }
+
+ for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q)
{
DataMemberPtr member = *q;
@@ -1118,28 +1324,46 @@ IcePHP::StructInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap*
invalidArgument("invalid value for %s member `%s'" TSRMLS_CC, id.c_str(), member->name.c_str());
throw AbortMarshaling();
}
- member->type->marshal(*val, os, objectMap TSRMLS_CC);
+
+ member->type->marshal(*val, os, objectMap, false TSRMLS_CC);
+ }
+
+ if(optional && _variableLength)
+ {
+ os->endSize();
}
}
void
IcePHP::StructInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb,
- const CommunicatorInfoPtr& comm, zval* target, void* closure TSRMLS_DC)
+ const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional TSRMLS_DC)
{
zval* zv;
MAKE_STD_ZVAL(zv);
AutoDestroy destroy(zv);
- if(object_init_ex(zv, zce) != SUCCESS)
+ if(object_init_ex(zv, const_cast<zend_class_entry*>(zce)) != SUCCESS)
{
runtimeError("unable to initialize object of type %s" TSRMLS_CC, zce->name);
throw AbortMarshaling();
}
- for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q)
+ if(optional)
+ {
+ if(_variableLength)
+ {
+ is->skip(4);
+ }
+ else
+ {
+ is->skipSize();
+ }
+ }
+
+ for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q)
{
DataMemberPtr member = *q;
- member->type->unmarshal(is, member, comm, zv, 0 TSRMLS_CC);
+ member->type->unmarshal(is, member, comm, zv, 0, false TSRMLS_CC);
}
cb->unmarshaled(zv, target, closure TSRMLS_CC);
@@ -1154,7 +1378,7 @@ IcePHP::StructInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHis
return;
}
out.sb();
- for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q)
+ for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q)
{
DataMemberPtr member = *q;
@@ -1176,16 +1400,22 @@ IcePHP::StructInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHis
void
IcePHP::StructInfo::destroy()
{
- for(DataMemberList::iterator p = members.begin(); p != members.end(); ++p)
+ for(DataMemberList::const_iterator p = members.begin(); p != members.end(); ++p)
{
(*p)->type->destroy();
}
- members.clear();
+ const_cast<DataMemberList&>(members).clear();
}
//
// SequenceInfo implementation.
//
+IcePHP::SequenceInfo::SequenceInfo(const string& ident, zval* e TSRMLS_DC) :
+ id(ident)
+{
+ const_cast<TypeInfoPtr&>(elementType) = Wrapper<TypeInfoPtr>::value(e TSRMLS_CC);
+}
+
string
IcePHP::SequenceInfo::getId() const
{
@@ -1199,62 +1429,102 @@ IcePHP::SequenceInfo::validate(zval* zv TSRMLS_DC)
}
bool
-IcePHP::SequenceInfo::usesClasses()
+IcePHP::SequenceInfo::variableLength() const
{
- return elementType->usesClasses();
+ return true;
+}
+
+int
+IcePHP::SequenceInfo::wireSize() const
+{
+ return 1;
+}
+
+Ice::OptionalFormat
+IcePHP::SequenceInfo::optionalFormat() const
+{
+ return elementType->variableLength() ? Ice::OptionalFormatFSize : Ice::OptionalFormatVSize;
}
void
-IcePHP::SequenceInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap TSRMLS_DC)
+IcePHP::SequenceInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional TSRMLS_DC)
{
- if(Z_TYPE_P(zv) == IS_NULL)
+ Ice::Int sz = 0;
+ HashTable* arr = 0;
+
+ if(Z_TYPE_P(zv) != IS_NULL)
{
- os->writeSize(0);
- return;
+ assert(Z_TYPE_P(zv) == IS_ARRAY); // validate() should have caught this.
+ arr = Z_ARRVAL_P(zv);
+ sz = static_cast<Ice::Int>(zend_hash_num_elements(arr));
}
- assert(Z_TYPE_P(zv) == IS_ARRAY); // validate() should have caught this.
-
- HashTable* arr = Z_ARRVAL_P(zv);
-
- Ice::Int sz = static_cast<Ice::Int>(zend_hash_num_elements(arr));
+ if(optional)
+ {
+ if(elementType->variableLength())
+ {
+ os->startSize();
+ }
+ else if(elementType->wireSize() > 1)
+ {
+ os->writeSize(sz == 0 ? 1 : sz * elementType->wireSize() + (sz > 254 ? 5 : 1));
+ }
+ }
if(sz == 0)
{
os->writeSize(0);
- return;
}
-
- PrimitiveInfoPtr pi = PrimitiveInfoPtr::dynamicCast(elementType);
- if(pi)
+ else
{
- marshalPrimitiveSequence(pi, zv, os TSRMLS_CC);
- return;
- }
+ PrimitiveInfoPtr pi = PrimitiveInfoPtr::dynamicCast(elementType);
+ if(pi)
+ {
+ marshalPrimitiveSequence(pi, zv, os TSRMLS_CC);
+ return;
+ }
- HashPosition pos;
- zend_hash_internal_pointer_reset_ex(arr, &pos);
+ HashPosition pos;
+ zend_hash_internal_pointer_reset_ex(arr, &pos);
- os->writeSize(sz);
+ os->writeSize(sz);
- void* data;
- while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
- {
- zval** val = reinterpret_cast<zval**>(data);
- if(!elementType->validate(*val TSRMLS_CC))
+ void* data;
+ while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
{
- invalidArgument("invalid value for sequence element `%s'" TSRMLS_CC, id.c_str());
- throw AbortMarshaling();
+ zval** val = reinterpret_cast<zval**>(data);
+ if(!elementType->validate(*val TSRMLS_CC))
+ {
+ invalidArgument("invalid value for sequence element `%s'" TSRMLS_CC, id.c_str());
+ throw AbortMarshaling();
+ }
+ elementType->marshal(*val, os, objectMap, false TSRMLS_CC);
+ zend_hash_move_forward_ex(arr, &pos);
}
- elementType->marshal(*val, os, objectMap TSRMLS_CC);
- zend_hash_move_forward_ex(arr, &pos);
+ }
+
+ if(optional && elementType->variableLength())
+ {
+ os->endSize();
}
}
void
IcePHP::SequenceInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb,
- const CommunicatorInfoPtr& comm, zval* target, void* closure TSRMLS_DC)
+ const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional TSRMLS_DC)
{
+ if(optional)
+ {
+ if(elementType->variableLength())
+ {
+ is->skip(4);
+ }
+ else if(elementType->wireSize() > 1)
+ {
+ is->skipSize();
+ }
+ }
+
PrimitiveInfoPtr pi = PrimitiveInfoPtr::dynamicCast(elementType);
if(pi)
{
@@ -1271,7 +1541,7 @@ IcePHP::SequenceInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCa
for(Ice::Int i = 0; i < sz; ++i)
{
void* cl = reinterpret_cast<void*>(i);
- elementType->unmarshal(is, this, comm, zv, cl TSRMLS_CC);
+ elementType->unmarshal(is, this, comm, zv, cl, false TSRMLS_CC);
}
cb->unmarshaled(zv, target, closure TSRMLS_CC);
@@ -1331,7 +1601,7 @@ IcePHP::SequenceInfo::destroy()
if(elementType)
{
elementType->destroy();
- elementType = 0;
+ const_cast<TypeInfoPtr&>(elementType) = 0;
}
}
@@ -1689,6 +1959,16 @@ IcePHP::SequenceInfo::unmarshalPrimitiveSequence(const PrimitiveInfoPtr& pi, con
//
// DictionaryInfo implementation.
//
+IcePHP::DictionaryInfo::DictionaryInfo(const string& ident, zval* k, zval* v TSRMLS_DC) :
+ id(ident)
+{
+ const_cast<TypeInfoPtr&>(keyType) = Wrapper<TypeInfoPtr>::value(k TSRMLS_CC);
+ const_cast<TypeInfoPtr&>(valueType) = Wrapper<TypeInfoPtr>::value(v TSRMLS_CC);
+
+ _variableLength = keyType->variableLength() || valueType->variableLength();
+ _wireSize = keyType->wireSize() + valueType->wireSize();
+}
+
string
IcePHP::DictionaryInfo::getId() const
{
@@ -1702,21 +1982,47 @@ IcePHP::DictionaryInfo::validate(zval* zv TSRMLS_DC)
}
bool
-IcePHP::DictionaryInfo::usesClasses()
+IcePHP::DictionaryInfo::variableLength() const
+{
+ return true;
+}
+
+int
+IcePHP::DictionaryInfo::wireSize() const
+{
+ return 1;
+}
+
+Ice::OptionalFormat
+IcePHP::DictionaryInfo::optionalFormat() const
{
- return valueType->usesClasses();
+ return _variableLength ? Ice::OptionalFormatFSize : Ice::OptionalFormatVSize;
}
void
-IcePHP::DictionaryInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap TSRMLS_DC)
+IcePHP::DictionaryInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional TSRMLS_DC)
{
- if(Z_TYPE_P(zv) == IS_NULL)
+ Ice::Int sz = 0;
+ HashTable* arr = 0;
+
+ if(Z_TYPE_P(zv) != IS_NULL)
{
- os->writeSize(0);
- return;
+ assert(Z_TYPE_P(zv) == IS_ARRAY); // validate() should have caught this.
+ arr = Z_ARRVAL_P(zv);
+ sz = static_cast<Ice::Int>(zend_hash_num_elements(arr));
}
- assert(Z_TYPE_P(zv) == IS_ARRAY); // validate() should have caught this.
+ if(optional)
+ {
+ if(_variableLength)
+ {
+ os->startSize();
+ }
+ else
+ {
+ os->writeSize(sz == 0 ? 1 : sz * _wireSize + (sz > 254 ? 5 : 1));
+ }
+ }
PrimitiveInfoPtr piKey = PrimitiveInfoPtr::dynamicCast(keyType);
EnumInfoPtr enKey = EnumInfoPtr::dynamicCast(keyType);
@@ -1726,123 +2032,135 @@ IcePHP::DictionaryInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, Object
throw AbortMarshaling();
}
- HashTable* arr = Z_ARRVAL_P(zv);
-
- Ice::Int sz = static_cast<Ice::Int>(zend_hash_num_elements(arr));
os->writeSize(sz);
- if(sz == 0)
+ if(sz > 0)
{
- return;
- }
-
- HashPosition pos;
- void* data;
-
- zend_hash_internal_pointer_reset_ex(arr, &pos);
- while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
- {
- zval** val = reinterpret_cast<zval**>(data);
+ HashPosition pos;
+ void* data;
- //
- // Get the key (which can be a long or a string).
- //
- char* keyStr;
- uint keyLen;
- ulong keyNum;
- int hashKeyType = zend_hash_get_current_key_ex(arr, &keyStr, &keyLen, &keyNum, 0, &pos);
+ zend_hash_internal_pointer_reset_ex(arr, &pos);
+ while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
+ {
+ zval** val = reinterpret_cast<zval**>(data);
- //
- // Store the key in a zval so that we can reuse the marshaling logic.
- //
- zval* zkey;
- MAKE_STD_ZVAL(zkey);
- AutoDestroy destroy(zkey);
+ //
+ // Get the key (which can be a long or a string).
+ //
+ char* keyStr;
+ uint keyLen;
+ ulong keyNum;
+ int hashKeyType = zend_hash_get_current_key_ex(arr, &keyStr, &keyLen, &keyNum, 0, &pos);
- if(hashKeyType == HASH_KEY_IS_LONG)
- {
- ZVAL_LONG(zkey, keyNum);
- }
- else
- {
- ZVAL_STRINGL(zkey, keyStr, keyLen - 1, 1);
- }
+ //
+ // Store the key in a zval so that we can reuse the marshaling logic.
+ //
+ zval* zkey;
+ MAKE_STD_ZVAL(zkey);
+ AutoDestroy destroy(zkey);
- //
- // Convert the zval to the required type, if necessary.
- //
- if(piKey)
- {
- switch(piKey->kind)
+ if(hashKeyType == HASH_KEY_IS_LONG)
{
- case PrimitiveInfo::KindBool:
+ ZVAL_LONG(zkey, keyNum);
+ }
+ else
{
- convert_to_boolean(zkey);
- break;
+ ZVAL_STRINGL(zkey, keyStr, keyLen - 1, 1);
}
- case PrimitiveInfo::KindByte:
- case PrimitiveInfo::KindShort:
- case PrimitiveInfo::KindInt:
- case PrimitiveInfo::KindLong:
+ //
+ // Convert the zval to the required type, if necessary.
+ //
+ if(piKey)
{
- if(hashKeyType == HASH_KEY_IS_STRING)
+ switch(piKey->kind)
{
- convert_to_long(zkey);
+ case PrimitiveInfo::KindBool:
+ {
+ convert_to_boolean(zkey);
+ break;
}
- break;
- }
- case PrimitiveInfo::KindString:
+ case PrimitiveInfo::KindByte:
+ case PrimitiveInfo::KindShort:
+ case PrimitiveInfo::KindInt:
+ case PrimitiveInfo::KindLong:
+ {
+ if(hashKeyType == HASH_KEY_IS_STRING)
+ {
+ convert_to_long(zkey);
+ }
+ break;
+ }
+
+ case PrimitiveInfo::KindString:
+ {
+ if(hashKeyType == HASH_KEY_IS_LONG)
+ {
+ convert_to_string(zkey);
+ }
+ break;
+ }
+
+ case PrimitiveInfo::KindFloat:
+ case PrimitiveInfo::KindDouble:
+ assert(false);
+ }
+ }
+ else
{
- if(hashKeyType == HASH_KEY_IS_LONG)
+ if(hashKeyType == HASH_KEY_IS_STRING)
{
- convert_to_string(zkey);
+ convert_to_long(zkey);
}
- break;
}
- case PrimitiveInfo::KindFloat:
- case PrimitiveInfo::KindDouble:
- assert(false);
- }
- }
- else
- {
- if(hashKeyType == HASH_KEY_IS_STRING)
+ //
+ // Marshal the key.
+ //
+ if(!keyType->validate(zkey TSRMLS_CC))
{
- convert_to_long(zkey);
+ invalidArgument("invalid key in `%s' element" TSRMLS_CC, id.c_str());
+ throw AbortMarshaling();
}
- }
+ keyType->marshal(zkey, os, objectMap, false TSRMLS_CC);
- //
- // Marshal the key.
- //
- if(!keyType->validate(zkey TSRMLS_CC))
- {
- invalidArgument("invalid key in `%s' element" TSRMLS_CC, id.c_str());
- throw AbortMarshaling();
- }
- keyType->marshal(zkey, os, objectMap TSRMLS_CC);
+ //
+ // Marshal the value.
+ //
+ if(!valueType->validate(*val TSRMLS_CC))
+ {
+ invalidArgument("invalid value in `%s' element" TSRMLS_CC, id.c_str());
+ throw AbortMarshaling();
+ }
+ valueType->marshal(*val, os, objectMap, false TSRMLS_CC);
- //
- // Marshal the value.
- //
- if(!valueType->validate(*val TSRMLS_CC))
- {
- invalidArgument("invalid value in `%s' element" TSRMLS_CC, id.c_str());
- throw AbortMarshaling();
+ zend_hash_move_forward_ex(arr, &pos);
}
- valueType->marshal(*val, os, objectMap TSRMLS_CC);
+ }
- zend_hash_move_forward_ex(arr, &pos);
+ if(optional && _variableLength)
+ {
+ os->endSize();
}
}
void
IcePHP::DictionaryInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb,
- const CommunicatorInfoPtr& comm, zval* target, void* closure TSRMLS_DC)
+ const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional TSRMLS_DC)
{
+ if(optional)
+ {
+ if(_variableLength)
+ {
+ is->skip(4);
+ }
+ else
+ {
+ is->skipSize();
+ }
+ }
+
PrimitiveInfoPtr piKey = PrimitiveInfoPtr::dynamicCast(keyType);
EnumInfoPtr enKey = EnumInfoPtr::dynamicCast(keyType);
if(!enKey && (!piKey || piKey->kind == PrimitiveInfo::KindFloat || piKey->kind == PrimitiveInfo::KindDouble))
@@ -1865,7 +2183,7 @@ IcePHP::DictionaryInfo::unmarshal(const Ice::InputStreamPtr& is, const Unmarshal
// A dictionary key cannot be a class (or contain one), so the key must be
// available immediately.
//
- keyType->unmarshal(is, keyCB, comm, 0, 0 TSRMLS_CC);
+ keyType->unmarshal(is, keyCB, comm, 0, 0, false TSRMLS_CC);
assert(keyCB->key);
//
@@ -1876,7 +2194,7 @@ IcePHP::DictionaryInfo::unmarshal(const Ice::InputStreamPtr& is, const Unmarshal
//
// Pass the key to the callback.
//
- valueType->unmarshal(is, valueCB, comm, zv, 0 TSRMLS_CC);
+ valueType->unmarshal(is, valueCB, comm, zv, 0, false TSRMLS_CC);
}
cb->unmarshaled(zv, target, closure TSRMLS_CC);
@@ -2021,6 +2339,53 @@ IcePHP::DictionaryInfo::destroy()
//
// ClassInfo implementation.
//
+IcePHP::ClassInfo::ClassInfo(const string& ident TSRMLS_DC) :
+ id(ident), isAbstract(false), preserve(false), zce(0), defined(false)
+{
+}
+
+void
+IcePHP::ClassInfo::define(const string& n, bool isAbs, bool pres, zval* b, zval* i, zval* m TSRMLS_DC)
+{
+ const_cast<string&>(name) = n;
+ const_cast<bool&>(isAbstract) = isAbs;
+ const_cast<bool&>(preserve) = pres;
+
+ if(b)
+ {
+ TypeInfoPtr p = Wrapper<TypeInfoPtr>::value(b TSRMLS_CC);
+ const_cast<ClassInfoPtr&>(base) = ClassInfoPtr::dynamicCast(p);
+ assert(base);
+ }
+
+ if(i)
+ {
+ HashTable* interfacesArray = Z_ARRVAL_P(i);
+ void* data;
+ HashPosition pos;
+ zend_hash_internal_pointer_reset_ex(interfacesArray, &pos);
+ while(zend_hash_get_current_data_ex(interfacesArray, &data, &pos) != FAILURE)
+ {
+ zval** interfaceType = reinterpret_cast<zval**>(data);
+ TypeInfoPtr t = Wrapper<TypeInfoPtr>::value(*interfaceType TSRMLS_CC);
+ ClassInfoPtr c = ClassInfoPtr::dynamicCast(t);
+ assert(c);
+ const_cast<ClassInfoList&>(interfaces).push_back(c);
+ zend_hash_move_forward_ex(interfacesArray, &pos);
+ }
+ }
+
+ if(m)
+ {
+ convertDataMembers(m, const_cast<DataMemberList&>(members), const_cast<DataMemberList&>(optionalMembers),
+ true TSRMLS_CC);
+ }
+
+ const_cast<bool&>(defined) = true;
+ const_cast<zend_class_entry*&>(zce) = nameToClass(name TSRMLS_CC);
+ assert(zce || id == "::Ice::LocalObject"); // LocalObject does not have a native PHP equivalent.
+}
+
string
IcePHP::ClassInfo::getId() const
{
@@ -2032,19 +2397,31 @@ IcePHP::ClassInfo::validate(zval* val TSRMLS_DC)
{
if(Z_TYPE_P(val) == IS_OBJECT)
{
- return checkClass(Z_OBJCE_P(val), zce);
+ return checkClass(Z_OBJCE_P(val), const_cast<zend_class_entry*>(zce));
}
return Z_TYPE_P(val) == IS_NULL;
}
bool
-IcePHP::ClassInfo::usesClasses()
+IcePHP::ClassInfo::variableLength() const
{
return true;
}
+int
+IcePHP::ClassInfo::wireSize() const
+{
+ return 1;
+}
+
+Ice::OptionalFormat
+IcePHP::ClassInfo::optionalFormat() const
+{
+ return Ice::OptionalFormatSize;
+}
+
void
-IcePHP::ClassInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap TSRMLS_DC)
+IcePHP::ClassInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool TSRMLS_DC)
{
if(!defined)
{
@@ -2088,7 +2465,7 @@ IcePHP::ClassInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap*
void
IcePHP::ClassInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb,
- const CommunicatorInfoPtr& comm, zval* target, void* closure TSRMLS_DC)
+ const CommunicatorInfoPtr& comm, zval* target, void* closure, bool TSRMLS_DC)
{
if(!defined)
{
@@ -2134,12 +2511,12 @@ IcePHP::ClassInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHist
void
IcePHP::ClassInfo::destroy()
{
- base = 0;
- interfaces.clear();
+ const_cast<ClassInfoPtr&>(base) = 0;
+ const_cast<ClassInfoList&>(interfaces).clear();
if(!members.empty())
{
DataMemberList ml = members;
- members.clear();
+ const_cast<DataMemberList&>(members).clear();
for(DataMemberList::iterator p = ml.begin(); p != ml.end(); ++p)
{
(*p)->type->destroy();
@@ -2155,7 +2532,9 @@ IcePHP::ClassInfo::printMembers(zval* zv, IceUtilInternal::Output& out, PrintObj
base->printMembers(zv, out, history TSRMLS_CC);
}
- for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q)
+ DataMemberList::const_iterator q;
+
+ for(q = members.begin(); q != members.end(); ++q)
{
DataMemberPtr member = *q;
@@ -2171,6 +2550,30 @@ IcePHP::ClassInfo::printMembers(zval* zv, IceUtilInternal::Output& out, PrintObj
out << "<not defined>";
}
}
+
+ for(q = optionalMembers.begin(); q != optionalMembers.end(); ++q)
+ {
+ DataMemberPtr member = *q;
+
+ out << nl << member->name << " = ";
+ void* data;
+ if(zend_hash_find(Z_OBJPROP_P(zv), STRCAST(member->name.c_str()), member->name.size() + 1, &data) == SUCCESS)
+ {
+ zval** val = reinterpret_cast<zval**>(data);
+ if(isUnset(*val TSRMLS_CC))
+ {
+ out << "<unset>";
+ }
+ else
+ {
+ member->type->print(*val, out, history TSRMLS_CC);
+ }
+ }
+ else
+ {
+ out << "<not defined>";
+ }
+ }
}
bool
@@ -2229,6 +2632,18 @@ IcePHP::ClassInfo::getOperation(const string& name) const
//
// ProxyInfo implementation.
//
+IcePHP::ProxyInfo::ProxyInfo(const string& ident TSRMLS_DC) :
+ id(ident), defined(false)
+{
+}
+
+void
+IcePHP::ProxyInfo::define(const ClassInfoPtr& c TSRMLS_DC)
+{
+ const_cast<ClassInfoPtr&>(cls) = c;
+ const_cast<bool&>(defined) = true;
+}
+
string
IcePHP::ProxyInfo::getId() const
{
@@ -2251,9 +2666,32 @@ IcePHP::ProxyInfo::validate(zval* zv TSRMLS_DC)
return true;
}
+bool
+IcePHP::ProxyInfo::variableLength() const
+{
+ return true;
+}
+
+int
+IcePHP::ProxyInfo::wireSize() const
+{
+ return 1;
+}
+
+Ice::OptionalFormat
+IcePHP::ProxyInfo::optionalFormat() const
+{
+ return Ice::OptionalFormatFSize;
+}
+
void
-IcePHP::ProxyInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* TSRMLS_DC)
+IcePHP::ProxyInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap*, bool optional TSRMLS_DC)
{
+ if(optional)
+ {
+ os->startSize();
+ }
+
if(Z_TYPE_P(zv) == IS_NULL)
{
os->write(Ice::ObjectPrx());
@@ -2274,16 +2712,26 @@ IcePHP::ProxyInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap*
}
os->write(proxy);
}
+
+ if(optional)
+ {
+ os->endSize();
+ }
}
void
IcePHP::ProxyInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb,
- const CommunicatorInfoPtr& comm, zval* target, void* closure TSRMLS_DC)
+ const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional TSRMLS_DC)
{
zval* zv;
MAKE_STD_ZVAL(zv);
AutoDestroy destroy(zv);
+ if(optional)
+ {
+ is->skip(4);
+ }
+
Ice::ObjectPrx proxy;
is->read(proxy);
@@ -2335,7 +2783,7 @@ IcePHP::ProxyInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHist
void
IcePHP::ProxyInfo::destroy()
{
- cls = 0;
+ const_cast<ClassInfoPtr&>(cls) = 0;
}
//
@@ -2357,7 +2805,7 @@ IcePHP::ObjectWriter::ObjectWriter(zval* object, ObjectMap* objectMap, const Cla
// The caller may have provided a ClassInfo representing the formal type, in
// which case we ensure that the actual type is compatible with the formal type.
//
- _info = getClassInfoByClass(Z_OBJCE_P(object), formal ? formal->zce : 0 TSRMLS_CC);
+ _info = getClassInfoByClass(Z_OBJCE_P(object), formal ? const_cast<zend_class_entry*>(formal->zce) : 0 TSRMLS_CC);
assert(_info);
}
@@ -2394,40 +2842,61 @@ IcePHP::ObjectWriter::write(const Ice::OutputStreamPtr& os) const
os->startObject(slicedData);
- ClassInfoPtr info = _info;
- while(info && info->id != Ice::Object::ice_staticId())
+ if(_info->id != "::Ice::UnknownSlicedObject")
{
- assert(info->base); // All classes have the Ice::Object base type.
- const bool lastSlice = info->base->id == Ice::Object::ice_staticId();
- os->startSlice(info->id, lastSlice);
- for(DataMemberList::iterator q = info->members.begin(); q != info->members.end(); ++q)
+ ClassInfoPtr info = _info;
+ while(info && info->id != Ice::Object::ice_staticId())
{
- DataMemberPtr member = *q;
+ assert(info->base); // All classes have the Ice::Object base type.
+ const bool lastSlice = info->base->id == Ice::Object::ice_staticId();
+ os->startSlice(info->id, lastSlice);
- void* data;
- if(zend_hash_find(Z_OBJPROP_P(_object), STRCAST(member->name.c_str()), member->name.size() + 1, &data) ==
- FAILURE)
- {
- runtimeError("member `%s' of %s is not defined" TSRMLS_CC, member->name.c_str(), _info->id.c_str());
- throw AbortMarshaling();
- }
+ writeMembers(os, info->members);
+ writeMembers(os, info->optionalMembers); // The optional members have already been sorted by tag.
- zval** val = reinterpret_cast<zval**>(data);
- if(!member->type->validate(*val TSRMLS_CC))
- {
- invalidArgument("invalid value for %s member `%s'" TSRMLS_CC, _info->id.c_str(), member->name.c_str());
- throw AbortMarshaling();
- }
- member->type->marshal(*val, os, _map TSRMLS_CC);
- }
- os->endSlice();
+ os->endSlice();
- info = info->base;
+ info = info->base;
+ }
}
os->endObject();
}
+void
+IcePHP::ObjectWriter::writeMembers(const Ice::OutputStreamPtr& os, const DataMemberList& members) const
+{
+ for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q)
+ {
+ DataMemberPtr member = *q;
+
+ void* data;
+ if(zend_hash_find(Z_OBJPROP_P(_object), STRCAST(member->name.c_str()), member->name.size() + 1, &data) ==
+ FAILURE)
+ {
+ runtimeError("member `%s' of %s is not defined" TSRMLS_CC, member->name.c_str(), _info->id.c_str());
+ throw AbortMarshaling();
+ }
+
+ zval** val = reinterpret_cast<zval**>(data);
+
+ if(member->optional && (isUnset(*val TSRMLS_CC) ||
+ !os->writeOptional(member->tag, member->type->optionalFormat())))
+ {
+ continue;
+ }
+
+ if(!member->type->validate(*val TSRMLS_CC))
+ {
+ invalidArgument("invalid value for %s member `%s'" TSRMLS_CC, _info->id.c_str(),
+ member->name.c_str());
+ throw AbortMarshaling();
+ }
+
+ member->type->marshal(*val, os, _map, member->optional TSRMLS_CC);
+ }
+}
+
//
// ObjectReader implementation.
//
@@ -2464,21 +2933,50 @@ IcePHP::ObjectReader::read(const Ice::InputStreamPtr& is)
{
is->startObject();
+ const bool unknown = _info->id == "::Ice::UnknownSlicedObject";
+
//
// Unmarshal the slices of a user-defined class.
//
- ClassInfoPtr info = _info;
- while(info && info->id != Ice::Object::ice_staticId())
+ if(!unknown)
{
- is->startSlice();
- for(DataMemberList::iterator p = info->members.begin(); p != info->members.end(); ++p)
+ ClassInfoPtr info = _info;
+ while(info && info->id != Ice::Object::ice_staticId())
{
- DataMemberPtr member = *p;
- member->type->unmarshal(is, member, _communicator, _object, 0 TSRMLS_CC);
- }
- is->endSlice();
+ is->startSlice();
- info = info->base;
+ DataMemberList::const_iterator p;
+
+ for(p = info->members.begin(); p != info->members.end(); ++p)
+ {
+ DataMemberPtr member = *p;
+ member->type->unmarshal(is, member, _communicator, _object, 0, false TSRMLS_CC);
+ }
+
+ //
+ // The optional members have already been sorted by tag.
+ //
+ for(p = info->optionalMembers.begin(); p != info->optionalMembers.end(); ++p)
+ {
+ DataMemberPtr member = *p;
+ if(is->readOptional(member->tag, member->type->optionalFormat()))
+ {
+ member->type->unmarshal(is, member, _communicator, _object, 0, true TSRMLS_CC);
+ }
+ else
+ {
+ zval* zv;
+ MAKE_STD_ZVAL(zv);
+ AutoDestroy destroy(zv);
+ unset(zv);
+ member->setMember(_object, zv TSRMLS_CC);
+ }
+ }
+
+ is->endSlice();
+
+ info = info->base;
+ }
}
_slicedData = is->endObject(_info->preserve);
@@ -2488,6 +2986,21 @@ IcePHP::ObjectReader::read(const Ice::InputStreamPtr& is)
SlicedDataUtil* util = reinterpret_cast<SlicedDataUtil*>(is->closure());
assert(util);
util->add(this);
+
+ //
+ // Define the "unknownTypeId" member for an instance of UnknownSlicedObject.
+ //
+ if(unknown)
+ {
+ assert(!_slicedData->slices.empty());
+
+ const string typeId = _slicedData->slices[0]->typeId;
+ zval* zv;
+ MAKE_STD_ZVAL(zv);
+ AutoDestroy typeIdDestroyer(zv);
+ ZVAL_STRINGL(zv, STRCAST(typeId.c_str()), typeId.size(), 1);
+ add_property_zval(_object, STRCAST("unknownTypeId"), zv);
+ }
}
}
@@ -2594,11 +3107,35 @@ IcePHP::ExceptionInfo::unmarshal(const Ice::InputStreamPtr& is, const Communicat
while(info)
{
is->startSlice();
- for(DataMemberList::iterator q = info->members.begin(); q != info->members.end(); ++q)
+
+ DataMemberList::iterator q;
+
+ for(q = info->members.begin(); q != info->members.end(); ++q)
{
DataMemberPtr member = *q;
- member->type->unmarshal(is, member, comm, zv, 0 TSRMLS_CC);
+ member->type->unmarshal(is, member, comm, zv, 0, false TSRMLS_CC);
}
+
+ //
+ // The optional members have already been sorted by tag.
+ //
+ for(q = info->optionalMembers.begin(); q != info->optionalMembers.end(); ++q)
+ {
+ DataMemberPtr member = *q;
+ if(is->readOptional(member->tag, member->type->optionalFormat()))
+ {
+ member->type->unmarshal(is, member, comm, zv, 0, true TSRMLS_CC);
+ }
+ else
+ {
+ zval* un;
+ MAKE_STD_ZVAL(un);
+ AutoDestroy destroy(un);
+ unset(un);
+ member->setMember(zv, un TSRMLS_CC);
+ }
+ }
+
is->endSlice();
info = info->base;
@@ -2644,7 +3181,9 @@ IcePHP::ExceptionInfo::printMembers(zval* zv, IceUtilInternal::Output& out, Prin
base->printMembers(zv, out, history TSRMLS_CC);
}
- for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q)
+ DataMemberList::iterator q;
+
+ for(q = members.begin(); q != members.end(); ++q)
{
DataMemberPtr member = *q;
@@ -2660,6 +3199,30 @@ IcePHP::ExceptionInfo::printMembers(zval* zv, IceUtilInternal::Output& out, Prin
out << "<not defined>";
}
}
+
+ for(q = optionalMembers.begin(); q != optionalMembers.end(); ++q)
+ {
+ DataMemberPtr member = *q;
+
+ out << nl << member->name << " = ";
+ void* data;
+ if(zend_hash_find(Z_OBJPROP_P(zv), STRCAST(member->name.c_str()), member->name.size() + 1, &data) == SUCCESS)
+ {
+ zval** val = reinterpret_cast<zval**>(data);
+ if(isUnset(*val TSRMLS_CC))
+ {
+ out << "<unset>";
+ }
+ else
+ {
+ member->type->print(*val, out, history TSRMLS_CC);
+ }
+ }
+ else
+ {
+ out << "<not defined>";
+ }
+ }
}
bool
@@ -2705,17 +3268,6 @@ IcePHP::ExceptionReader::read(const Ice::InputStreamPtr& is) const
const_cast<Ice::SlicedDataPtr&>(_slicedData) = is->endException(_info->preserve);
}
-bool
-IcePHP::ExceptionReader::usesClasses() const
-{
- return _info->usesClasses;
-}
-
-void
-IcePHP::ExceptionReader::usesClasses(bool)
-{
-}
-
string
IcePHP::ExceptionReader::ice_name() const
{
@@ -2811,19 +3363,7 @@ ZEND_FUNCTION(IcePHP_defineEnum)
return;
}
- EnumInfoPtr type = new EnumInfo();
- type->id = id;
- HashTable* arr = Z_ARRVAL_P(enumerators);
- void* data;
- HashPosition pos;
- zend_hash_internal_pointer_reset_ex(arr, &pos);
- while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
- {
- zval** val = reinterpret_cast<zval**>(data);
- assert(Z_TYPE_PP(val) == IS_STRING);
- type->enumerators.push_back(Z_STRVAL_PP(val));
- zend_hash_move_forward_ex(arr, &pos);
- }
+ EnumInfoPtr type = new EnumInfo(id, enumerators TSRMLS_CC);
if(!createTypeInfo(return_value, type TSRMLS_CC))
{
@@ -2831,36 +3371,6 @@ ZEND_FUNCTION(IcePHP_defineEnum)
}
}
-static void
-convertDataMembers(zval* zv, DataMemberList& l TSRMLS_DC)
-{
- assert(Z_TYPE_P(zv) == IS_ARRAY);
- HashTable* membersArray = Z_ARRVAL_P(zv);
- void* data;
- HashPosition pos;
- zend_hash_internal_pointer_reset_ex(membersArray, &pos);
- while(zend_hash_get_current_data_ex(membersArray, &data, &pos) != FAILURE)
- {
- zval** arr = reinterpret_cast<zval**>(data);
-
- DataMemberPtr m = new DataMember();
- zval** elem;
-
- assert(Z_TYPE_PP(arr) == IS_ARRAY);
- HashTable* member = Z_ARRVAL_PP(arr);
- assert(zend_hash_num_elements(member) == 2);
- zend_hash_index_find(member, 0, reinterpret_cast<void**>(&elem));
- assert(Z_TYPE_PP(elem) == IS_STRING);
- m->name = Z_STRVAL_PP(elem);
- zend_hash_index_find(member, 1, reinterpret_cast<void**>(&elem));
- assert(Z_TYPE_PP(elem) == IS_OBJECT);
- m->type = Wrapper<TypeInfoPtr>::value(*elem TSRMLS_CC);
- l.push_back(m);
-
- zend_hash_move_forward_ex(membersArray, &pos);
- }
-}
-
ZEND_FUNCTION(IcePHP_defineStruct)
{
char* id;
@@ -2875,12 +3385,7 @@ ZEND_FUNCTION(IcePHP_defineStruct)
return;
}
- StructInfoPtr type = new StructInfo();
- type->id = id;
- type->name = name;
- convertDataMembers(members, type->members TSRMLS_CC);
- type->zce = nameToClass(type->name TSRMLS_CC);
- assert(type->zce);
+ StructInfoPtr type = new StructInfo(id, name, members TSRMLS_CC);
if(!createTypeInfo(return_value, type TSRMLS_CC))
{
@@ -2899,9 +3404,7 @@ ZEND_FUNCTION(IcePHP_defineSequence)
return;
}
- SequenceInfoPtr type = new SequenceInfo();
- type->id = id;
- type->elementType = Wrapper<TypeInfoPtr>::value(element TSRMLS_CC);
+ SequenceInfoPtr type = new SequenceInfo(id, element TSRMLS_CC);
if(!createTypeInfo(return_value, type TSRMLS_CC))
{
@@ -2921,10 +3424,30 @@ ZEND_FUNCTION(IcePHP_defineDictionary)
return;
}
- DictionaryInfoPtr type = new DictionaryInfo();
- type->id = id;
- type->keyType = Wrapper<TypeInfoPtr>::value(key TSRMLS_CC);
- type->valueType = Wrapper<TypeInfoPtr>::value(value TSRMLS_CC);
+ DictionaryInfoPtr type = new DictionaryInfo(id, key, value TSRMLS_CC);
+
+ if(!createTypeInfo(return_value, type TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+}
+
+ZEND_FUNCTION(IcePHP_declareProxy)
+{
+ char* id;
+ int idLen;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &id, &idLen) == FAILURE)
+ {
+ return;
+ }
+
+ ProxyInfoPtr type = getProxyInfo(id TSRMLS_CC);
+ if(!type)
+ {
+ type = new ProxyInfo(id TSRMLS_CC);
+ addProxyInfo(type TSRMLS_CC);
+ }
if(!createTypeInfo(return_value, type TSRMLS_CC))
{
@@ -2948,23 +3471,11 @@ ZEND_FUNCTION(IcePHP_defineProxy)
ProxyInfoPtr type = getProxyInfo(c->id TSRMLS_CC);
if(!type)
{
- type = new ProxyInfo();
- type->id = c->id;
-
- ProxyInfoMap* m;
- if(ICE_G(proxyInfoMap))
- {
- m = reinterpret_cast<ProxyInfoMap*>(ICE_G(proxyInfoMap));
- }
- else
- {
- m = new ProxyInfoMap;
- ICE_G(proxyInfoMap) = m;
- }
- m->insert(ProxyInfoMap::value_type(type->id, type));
+ type = new ProxyInfo(c->id TSRMLS_CC);
+ addProxyInfo(type TSRMLS_CC);
}
- type->cls = c;
+ type->define(c TSRMLS_CC);
if(!createTypeInfo(return_value, type TSRMLS_CC))
{
@@ -2974,11 +3485,6 @@ ZEND_FUNCTION(IcePHP_defineProxy)
ZEND_FUNCTION(IcePHP_declareClass)
{
- if(ZEND_NUM_ARGS() != 1)
- {
- WRONG_PARAM_COUNT;
- }
-
char* id;
int idLen;
@@ -2987,11 +3493,12 @@ ZEND_FUNCTION(IcePHP_declareClass)
return;
}
- ClassInfoPtr type = new ClassInfo();
- type->id = id;
- type->defined = false;
-
- addClassInfoById(type TSRMLS_CC);
+ ClassInfoPtr type = getClassInfoById(id TSRMLS_CC);
+ if(!type)
+ {
+ type = new ClassInfo(id TSRMLS_CC);
+ addClassInfoById(type TSRMLS_CC);
+ }
if(!createTypeInfo(return_value, type TSRMLS_CC))
{
@@ -3020,49 +3527,13 @@ ZEND_FUNCTION(IcePHP_defineClass)
ClassInfoPtr type = getClassInfoById(id TSRMLS_CC);
if(!type)
{
- type = new ClassInfo();
- type->id = id;
+ type = new ClassInfo(id TSRMLS_CC);
addClassInfoById(type TSRMLS_CC);
}
- type->name = name;
+ type->define(name, isAbstract ? true : false, preserve ? true : false, base, interfaces, members TSRMLS_CC);
addClassInfoByName(type TSRMLS_CC);
- type->isAbstract = isAbstract ? true : false;
- type->preserve = preserve ? true : false;
- if(base)
- {
- TypeInfoPtr p = Wrapper<TypeInfoPtr>::value(base TSRMLS_CC);
- type->base = ClassInfoPtr::dynamicCast(p);
- assert(type->base);
- }
-
- if(interfaces)
- {
- HashTable* interfacesArray = Z_ARRVAL_P(interfaces);
- void* data;
- HashPosition pos;
- zend_hash_internal_pointer_reset_ex(interfacesArray, &pos);
- while(zend_hash_get_current_data_ex(interfacesArray, &data, &pos) != FAILURE)
- {
- zval** interfaceType = reinterpret_cast<zval**>(data);
- TypeInfoPtr t = Wrapper<TypeInfoPtr>::value(*interfaceType TSRMLS_CC);
- ClassInfoPtr c = ClassInfoPtr::dynamicCast(t);
- assert(c);
- type->interfaces.push_back(c);
- zend_hash_move_forward_ex(interfacesArray, &pos);
- }
- }
-
- if(members)
- {
- convertDataMembers(members, type->members TSRMLS_CC);
- }
-
- type->defined = true;
- type->zce = nameToClass(type->name TSRMLS_CC);
- assert(type->zce || type->id == "::Ice::LocalObject"); // LocalObject does not have a native PHP equivalent.
-
if(!createTypeInfo(return_value, type TSRMLS_CC))
{
RETURN_NULL();
@@ -3143,16 +3614,7 @@ ZEND_FUNCTION(IcePHP_defineException)
}
if(members)
{
- convertDataMembers(members, ex->members TSRMLS_CC);
- }
-
- ex->usesClasses = false;
- for(DataMemberList::iterator p = ex->members.begin(); p != ex->members.end(); ++p)
- {
- if(!ex->usesClasses)
- {
- ex->usesClasses = (*p)->type->usesClasses();
- }
+ convertDataMembers(members, ex->members, ex->optionalMembers, true TSRMLS_CC);
}
ex->zce = nameToClass(ex->name TSRMLS_CC);
@@ -3248,7 +3710,24 @@ static zend_function_entry _exceptionInfoMethods[] =
};
bool
-IcePHP::typesInit(TSRMLS_D)
+IcePHP::isUnset(zval* zv TSRMLS_DC)
+{
+ if(Z_TYPE_P(zv) == IS_STRING)
+ {
+ return _unsetGUID == string(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
+ }
+ return false;
+}
+
+void
+IcePHP::unset(zval* zv TSRMLS_DC)
+{
+ *zv = *ICE_G(unset);
+ zval_copy_ctor(zv);
+}
+
+bool
+IcePHP::typesInit(INIT_FUNC_ARGS)
{
zend_class_entry ce;
@@ -3268,6 +3747,11 @@ IcePHP::typesInit(TSRMLS_D)
exceptionInfoClassEntry = zend_register_internal_class(&ce TSRMLS_CC);
memcpy(&_exceptionInfoHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ REGISTER_STRING_CONSTANT("Ice_Unset", const_cast<char*>(_unsetGUID.c_str()), CONST_CS|CONST_PERSISTENT);
+#ifdef ICEPHP_USE_NAMESPACES
+ REGISTER_NS_STRING_CONSTANT("Ice", "Unset", const_cast<char*>(_unsetGUID.c_str()), CONST_CS|CONST_PERSISTENT);
+#endif
+
return true;
}
@@ -3298,6 +3782,11 @@ IcePHP::typesRequestInit(TSRMLS_D)
ICE_G(proxyInfoMap) = 0;
ICE_G(exceptionInfoMap) = 0;
+ zval* unset;
+ MAKE_STD_ZVAL(unset);
+ ZVAL_STRINGL(unset, STRCAST(_unsetGUID.c_str()), _unsetGUID.length(), 1);
+ ICE_G(unset) = unset;
+
return true;
}
@@ -3332,5 +3821,7 @@ IcePHP::typesRequestShutdown(TSRMLS_D)
delete static_cast<ExceptionInfoMap*>(ICE_G(exceptionInfoMap));
+ zval_ptr_dtor(&ICE_G(unset));
+
return true;
}
diff --git a/php/src/IcePHP/Types.h b/php/src/IcePHP/Types.h
index 059a5ebd8bc..4e07412bf66 100644
--- a/php/src/IcePHP/Types.h
+++ b/php/src/IcePHP/Types.h
@@ -25,6 +25,7 @@ ZEND_FUNCTION(IcePHP_defineEnum);
ZEND_FUNCTION(IcePHP_defineStruct);
ZEND_FUNCTION(IcePHP_defineSequence);
ZEND_FUNCTION(IcePHP_defineDictionary);
+ZEND_FUNCTION(IcePHP_declareProxy);
ZEND_FUNCTION(IcePHP_defineProxy);
ZEND_FUNCTION(IcePHP_declareClass);
ZEND_FUNCTION(IcePHP_defineClass);
@@ -112,7 +113,9 @@ public:
virtual bool validate(zval* TSRMLS_DC) = 0;
- virtual bool usesClasses(); // Default implementation returns false.
+ virtual bool variableLength() const = 0;
+ virtual int wireSize() const = 0;
+ virtual Ice::OptionalFormat optionalFormat() const = 0;
virtual void unmarshaled(zval*, zval*, void* TSRMLS_DC); // Default implementation is assert(false).
@@ -128,9 +131,9 @@ public:
// The marshal and unmarshal functions can raise Ice exceptions, and may raise
// AbortMarshaling if an error occurs.
//
- virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap* TSRMLS_DC) = 0;
+ virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC) = 0;
virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&,
- zval*, void* TSRMLS_DC) = 0;
+ zval*, void*, bool TSRMLS_DC) = 0;
virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC) = 0;
};
@@ -147,9 +150,13 @@ public:
virtual bool validate(zval* TSRMLS_DC);
- virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap* TSRMLS_DC);
+ virtual bool variableLength() const;
+ virtual int wireSize() const;
+ virtual Ice::OptionalFormat optionalFormat() const;
+
+ virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC);
virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&,
- zval*, void* TSRMLS_DC);
+ zval*, void*, bool TSRMLS_DC);
virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC);
@@ -176,18 +183,24 @@ class EnumInfo : public TypeInfo
{
public:
+ EnumInfo(const std::string&, zval* TSRMLS_DC);
+
virtual std::string getId() const;
virtual bool validate(zval* TSRMLS_DC);
- virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap* TSRMLS_DC);
+ virtual bool variableLength() const;
+ virtual int wireSize() const;
+ virtual Ice::OptionalFormat optionalFormat() const;
+
+ virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC);
virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&,
- zval*, void* TSRMLS_DC);
+ zval*, void*, bool TSRMLS_DC);
virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC);
- std::string id;
- Ice::StringSeq enumerators;
+ const std::string id;
+ const Ice::StringSeq enumerators;
};
typedef IceUtil::Handle<EnumInfo> EnumInfoPtr;
@@ -197,8 +210,12 @@ public:
virtual void unmarshaled(zval*, zval*, void* TSRMLS_DC);
+ void setMember(zval*, zval* TSRMLS_DC);
+
std::string name;
TypeInfoPtr type;
+ bool optional;
+ int tag;
};
typedef IceUtil::Handle<DataMember> DataMemberPtr;
typedef std::vector<DataMemberPtr> DataMemberList;
@@ -210,24 +227,33 @@ class StructInfo : public TypeInfo
{
public:
+ StructInfo(const std::string&, const std::string&, zval* TSRMLS_DC);
+
virtual std::string getId() const;
virtual bool validate(zval* TSRMLS_DC);
- virtual bool usesClasses();
+ virtual bool variableLength() const;
+ virtual int wireSize() const;
+ virtual Ice::OptionalFormat optionalFormat() const;
- virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap* TSRMLS_DC);
+ virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC);
virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&,
- zval*, void* TSRMLS_DC);
+ zval*, void*, bool TSRMLS_DC);
virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC);
virtual void destroy();
- std::string id;
- std::string name; // PHP class name
- DataMemberList members;
- zend_class_entry* zce;
+ const std::string id;
+ const std::string name; // PHP class name
+ const DataMemberList members;
+ const zend_class_entry* zce;
+
+private:
+
+ bool _variableLength;
+ int _wireSize;
};
typedef IceUtil::Handle<StructInfo> StructInfoPtr;
@@ -238,15 +264,19 @@ class SequenceInfo : public TypeInfo
{
public:
+ SequenceInfo(const std::string&, zval* TSRMLS_DC);
+
virtual std::string getId() const;
virtual bool validate(zval* TSRMLS_DC);
- virtual bool usesClasses();
+ virtual bool variableLength() const;
+ virtual int wireSize() const;
+ virtual Ice::OptionalFormat optionalFormat() const;
- virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap* TSRMLS_DC);
+ virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC);
virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&,
- zval*, void* TSRMLS_DC);
+ zval*, void*, bool TSRMLS_DC);
virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC);
@@ -254,8 +284,8 @@ public:
virtual void destroy();
- std::string id;
- TypeInfoPtr elementType;
+ const std::string id;
+ const TypeInfoPtr elementType;
private:
@@ -272,15 +302,19 @@ class DictionaryInfo : public TypeInfo
{
public:
+ DictionaryInfo(const std::string&, zval*, zval* TSRMLS_DC);
+
virtual std::string getId() const;
virtual bool validate(zval* TSRMLS_DC);
- virtual bool usesClasses();
+ virtual bool variableLength() const;
+ virtual int wireSize() const;
+ virtual Ice::OptionalFormat optionalFormat() const;
- virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap* TSRMLS_DC);
+ virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC);
virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&,
- zval*, void* TSRMLS_DC);
+ zval*, void*, bool TSRMLS_DC);
virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC);
@@ -315,6 +349,11 @@ public:
std::string id;
TypeInfoPtr keyType;
TypeInfoPtr valueType;
+
+private:
+
+ bool _variableLength;
+ int _wireSize;
};
typedef IceUtil::Handle<DictionaryInfo> DictionaryInfoPtr;
@@ -332,15 +371,21 @@ class ClassInfo : public TypeInfo
{
public:
+ ClassInfo(const std::string& TSRMLS_DC);
+
+ void define(const std::string&, bool, bool, zval*, zval*, zval* TSRMLS_DC);
+
virtual std::string getId() const;
virtual bool validate(zval* TSRMLS_DC);
- virtual bool usesClasses();
+ virtual bool variableLength() const;
+ virtual int wireSize() const;
+ virtual Ice::OptionalFormat optionalFormat() const;
- virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap* TSRMLS_DC);
+ virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC);
virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&,
- zval*, void* TSRMLS_DC);
+ zval*, void*, bool TSRMLS_DC);
virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC);
@@ -353,15 +398,16 @@ public:
void addOperation(const std::string&, const OperationPtr&);
OperationPtr getOperation(const std::string&) const;
- std::string id;
- std::string name; // PHP class name
- bool isAbstract;
- bool preserve;
- ClassInfoPtr base;
- ClassInfoList interfaces;
- DataMemberList members;
+ const std::string id;
+ const std::string name; // PHP class name
+ const bool isAbstract;
+ const bool preserve;
+ const ClassInfoPtr base;
+ const ClassInfoList interfaces;
+ const DataMemberList members;
+ const DataMemberList optionalMembers;
+ const zend_class_entry* zce;
bool defined;
- zend_class_entry* zce;
typedef std::map<std::string, OperationPtr> OperationMap;
OperationMap operations;
@@ -374,20 +420,29 @@ class ProxyInfo : public TypeInfo
{
public:
+ ProxyInfo(const std::string& TSRMLS_DC);
+
+ void define(const ClassInfoPtr& TSRMLS_DC);
+
virtual std::string getId() const;
virtual bool validate(zval* TSRMLS_DC);
- virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap* TSRMLS_DC);
+ virtual bool variableLength() const;
+ virtual int wireSize() const;
+ virtual Ice::OptionalFormat optionalFormat() const;
+
+ virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC);
virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&,
- zval*, void* TSRMLS_DC);
+ zval*, void*, bool TSRMLS_DC);
virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC);
virtual void destroy();
- std::string id;
- ClassInfoPtr cls;
+ const std::string id;
+ const ClassInfoPtr cls;
+ bool defined;
};
typedef IceUtil::Handle<ProxyInfo> ProxyInfoPtr;
@@ -410,7 +465,7 @@ public:
bool preserve;
ExceptionInfoPtr base;
DataMemberList members;
- bool usesClasses;
+ DataMemberList optionalMembers;
zend_class_entry* zce;
};
@@ -418,7 +473,10 @@ ClassInfoPtr getClassInfoById(const std::string& TSRMLS_DC);
ClassInfoPtr getClassInfoByName(const std::string& TSRMLS_DC);
ExceptionInfoPtr getExceptionInfo(const std::string& TSRMLS_DC);
-bool typesInit(TSRMLS_D);
+bool isUnset(zval* TSRMLS_DC);
+void unset(zval* TSRMLS_DC);
+
+bool typesInit(INIT_FUNC_ARGS);
bool typesRequestInit(TSRMLS_D);
bool typesRequestShutdown(TSRMLS_D);
@@ -438,6 +496,8 @@ public:
private:
+ void writeMembers(const Ice::OutputStreamPtr&, const DataMemberList&) const;
+
zval* _object;
ObjectMap* _map;
ClassInfoPtr _info;
@@ -488,8 +548,6 @@ public:
~ExceptionReader() throw();
virtual void read(const Ice::InputStreamPtr&) const;
- virtual bool usesClasses() const;
- virtual void usesClasses(bool);
virtual std::string ice_name() const;
virtual ExceptionReader* ice_clone() const;
diff --git a/php/test/Ice/Makefile b/php/test/Ice/Makefile
index 8aa9b1b4cc1..03fa41079bf 100644
--- a/php/test/Ice/Makefile
+++ b/php/test/Ice/Makefile
@@ -11,7 +11,8 @@ top_srcdir = ../..
include $(top_srcdir)/config/Make.rules.php
-SUBDIRS = binding checksum exceptions facets info inheritance objects operations proxy slicing defaultValue
+SUBDIRS = binding checksum exceptions facets info inheritance objects operations proxy slicing defaultValue \
+ optional
$(EVERYTHING)::
@for subdir in $(SUBDIRS); \
diff --git a/php/test/Ice/Makefile.mak b/php/test/Ice/Makefile.mak
index 3a850306641..fdf514dc7b7 100644
--- a/php/test/Ice/Makefile.mak
+++ b/php/test/Ice/Makefile.mak
@@ -11,7 +11,8 @@ top_srcdir = ..\..
!include $(top_srcdir)\config\Make.rules.mak.php
-SUBDIRS = binding checksum exceptions facets info inheritance objects operations proxy slicing defaultValue
+SUBDIRS = binding checksum exceptions facets info inheritance objects operations proxy slicing defaultValue \
+ optional
$(EVERYTHING)::
@for %i in ( $(SUBDIRS) ) do \
diff --git a/php/test/Ice/optional/.depend b/php/test/Ice/optional/.depend
new file mode 100644
index 00000000000..ef3f3f858ca
--- /dev/null
+++ b/php/test/Ice/optional/.depend
@@ -0,0 +1,2 @@
+ClientPrivate.php: ClientPrivate.ice ./Test.ice $(SLICE2PHP) $(SLICEPARSERLIB)
+Test.php: Test.ice $(SLICE2PHP) $(SLICEPARSERLIB)
diff --git a/php/test/Ice/optional/.depend.mak b/php/test/Ice/optional/.depend.mak
new file mode 100644
index 00000000000..c0d82ee1596
--- /dev/null
+++ b/php/test/Ice/optional/.depend.mak
@@ -0,0 +1,2 @@
+ClientPrivate.php: ClientPrivate.ice ./Test.ice "$(SLICE2PHP)" "$(SLICEPARSERLIB)"
+Test.php: Test.ice "$(SLICE2PHP)" "$(SLICEPARSERLIB)"
diff --git a/php/test/Ice/optional/.gitignore b/php/test/Ice/optional/.gitignore
new file mode 100644
index 00000000000..a3053d5debf
--- /dev/null
+++ b/php/test/Ice/optional/.gitignore
@@ -0,0 +1,2 @@
+ClientPrivate.php
+Test.php
diff --git a/php/test/Ice/optional/Client.php b/php/test/Ice/optional/Client.php
new file mode 100644
index 00000000000..f3f8b469da4
--- /dev/null
+++ b/php/test/Ice/optional/Client.php
@@ -0,0 +1,736 @@
+<?
+// **********************************************************************
+//
+// Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+error_reporting(E_ALL | E_STRICT);
+
+if(!extension_loaded("ice"))
+{
+ echo "\nerror: Ice extension is not loaded.\n\n";
+ exit(1);
+}
+
+$NS = function_exists("Ice\\initialize");
+require_once ($NS ? 'Ice_ns.php' : 'Ice.php');
+require_once 'ClientPrivate.php';
+
+function test($b)
+{
+ if(!$b)
+ {
+ $bt = debug_backtrace();
+ die("\ntest failed in ".$bt[0]["file"]." line ".$bt[0]["line"]."\n");
+ }
+}
+
+function allTests($communicator)
+{
+ global $NS;
+
+ $enum = $NS ? constant("Test\\MyEnum::MyEnumMember") : constant("Test_MyEnum::MyEnumMember");
+
+ echo "testing stringToProxy... ";
+ flush();
+ $ref = "initial:default -p 12010";
+ $base = $communicator->stringToProxy($ref);
+ echo "ok\n";
+
+ echo "testing checked cast... ";
+ flush();
+ $initial = $base->ice_checkedCast("::Test::Initial");
+ echo "ok\n";
+
+ echo "testing optional data members... ";
+ flush();
+
+ $oocls = $NS ? "Test\\OneOptional" : "Test_OneOptional";
+ $oo1 = new $oocls;
+ test($oo1->a == Ice_Unset);
+ $oo1->a = 15;
+
+ $oo2 = new $oocls(16);
+ test($oo2->a == 16);
+
+ $mocls = $NS ? "Test\\MultiOptional" : "Test_MultiOptional";
+ $mo1 = new $mocls;
+ test($mo1->a == Ice_Unset);
+ test($mo1->b == Ice_Unset);
+ test($mo1->c == Ice_Unset);
+ test($mo1->d == Ice_Unset);
+ test($mo1->e == Ice_Unset);
+ test($mo1->f == Ice_Unset);
+ test($mo1->g == Ice_Unset);
+ test($mo1->h == Ice_Unset);
+ test($mo1->i == Ice_Unset);
+ test($mo1->j == Ice_Unset);
+ test($mo1->k == Ice_Unset);
+ test($mo1->bs == Ice_Unset);
+ test($mo1->ss == Ice_Unset);
+ test($mo1->iid == Ice_Unset);
+ test($mo1->sid == Ice_Unset);
+ test($mo1->fs == Ice_Unset);
+ test($mo1->vs == Ice_Unset);
+
+ test($mo1->shs == Ice_Unset);
+ test($mo1->es == Ice_Unset);
+ test($mo1->fss == Ice_Unset);
+ test($mo1->vss == Ice_Unset);
+ test($mo1->oos == Ice_Unset);
+ test($mo1->oops == Ice_Unset);
+
+ test($mo1->ied == Ice_Unset);
+ test($mo1->ifsd == Ice_Unset);
+ test($mo1->ivsd == Ice_Unset);
+ test($mo1->iood == Ice_Unset);
+ test($mo1->ioopd == Ice_Unset);
+
+ test($mo1->bos == Ice_Unset);
+
+ $fscls = $NS ? "Test\\FixedStruct" : "Test_FixedStruct";
+ $fs = new $fscls(78);
+ $vscls = $NS ? "Test\\VarStruct" : "Test_VarStruct";
+ $vs = new $vscls("hello");
+ $prx = $communicator->stringToProxy("test");
+ $moprx = $NS ? eval("return Test\\MultiOptionalPrxHelper::uncheckedCast(\$prx);") :
+ eval("return Test_MultiOptionalPrxHelper::uncheckedCast(\$prx);");
+ $ooprx = $NS ? eval("return Test\\OneOptionalPrxHelper::uncheckedCast(\$prx);") :
+ eval("return Test_OneOptionalPrxHelper::uncheckedCast(\$prx);");
+ $oo15 = new $oocls(15);
+ $mocls = $NS ? "Test\\MultiOptional" : "Test_MultiOptional";
+ $mo1 = new $mocls(15, true, 19, 78, 99, 5.5, 1.0, 'test', $enum,
+ $moprx, null, array(5), array('test', 'test2'), array(4=>3), array('test'=>10),
+ $fs, $vs, array(1), array($enum, $enum), array($fs), array($vs), array($oo1),
+ array($ooprx), array(4=>$enum), array(4=>$fs), array(5=>$vs),
+ array(5=>$oo15), array(5=>$ooprx), array(false, true, false));
+
+ test($mo1->a == 15);
+ test($mo1->b == true);
+ test($mo1->c == 19);
+ test($mo1->d == 78);
+ test($mo1->e == 99);
+ test($mo1->f == 5.5);
+ test($mo1->g == 1.0);
+ test($mo1->h == "test");
+ test($mo1->i == $enum);
+ test($mo1->j == $moprx);
+ test($mo1->k == null);
+ test($mo1->bs == array(5));
+ test($mo1->ss == array("test", "test2"));
+ test($mo1->iid[4] == 3);
+ test($mo1->sid["test"] == 10);
+ test($mo1->fs == $fs);
+ test($mo1->vs == $vs);
+
+ test($mo1->shs[0] == 1);
+ test($mo1->es[0] == $enum && $mo1->es[1] == $enum);
+ test($mo1->fss[0] == $fs);
+ test($mo1->vss[0] == $vs);
+ test($mo1->oos[0] == $oo1);
+ test($mo1->oops[0] == $ooprx);
+
+ test($mo1->ied[4] == $enum);
+ test($mo1->ifsd[4] == $fs);
+ test($mo1->ivsd[5] == $vs);
+ test($mo1->iood[5]->a == 15);
+ test($mo1->ioopd[5] == $ooprx);
+
+ test($mo1->bos == array(false, true, false));
+
+ echo "ok\n";
+
+ echo "testing marshaling... ";
+ flush();
+
+ $oo4 = $initial->pingPong(new $oocls);
+ test($oo4->a == Ice_Unset);
+
+ $oo5 = $initial->pingPong($oo1);
+ test($oo1->a == $oo5->a);
+
+ $mo4 = $initial->pingPong(new $mocls);
+ test($mo4->a == Ice_Unset);
+ test($mo4->b == Ice_Unset);
+ test($mo4->c == Ice_Unset);
+ test($mo4->d == Ice_Unset);
+ test($mo4->e == Ice_Unset);
+ test($mo4->f == Ice_Unset);
+ test($mo4->g == Ice_Unset);
+ test($mo4->h == Ice_Unset);
+ test($mo4->i == Ice_Unset);
+ test($mo4->j == Ice_Unset);
+ test($mo4->k == Ice_Unset);
+ test($mo4->bs == Ice_Unset);
+ test($mo4->ss == Ice_Unset);
+ test($mo4->iid == Ice_Unset);
+ test($mo4->sid == Ice_Unset);
+ test($mo4->fs == Ice_Unset);
+ test($mo4->vs == Ice_Unset);
+
+ test($mo4->shs == Ice_Unset);
+ test($mo4->es == Ice_Unset);
+ test($mo4->fss == Ice_Unset);
+ test($mo4->vss == Ice_Unset);
+ test($mo4->oos == Ice_Unset);
+ test($mo4->oops == Ice_Unset);
+
+ test($mo4->ied == Ice_Unset);
+ test($mo4->ifsd == Ice_Unset);
+ test($mo4->ivsd == Ice_Unset);
+ test($mo4->iood == Ice_Unset);
+ test($mo4->ioopd == Ice_Unset);
+
+ test($mo4->bos == Ice_Unset);
+
+ $mo5 = $initial->pingPong($mo1);
+ test($mo5->a == $mo1->a);
+ test($mo5->b == $mo1->b);
+ test($mo5->c == $mo1->c);
+ test($mo5->d == $mo1->d);
+ test($mo5->e == $mo1->e);
+ test($mo5->f == $mo1->f);
+ test($mo5->g == $mo1->g);
+ test($mo5->h == $mo1->h);
+ test($mo5->i == $mo1->i);
+ test($mo5->j == $mo1->j);
+ test($mo5->k == null);
+ test($mo5->bs[0] == 5);
+ test($mo5->ss == $mo1->ss);
+ test($mo5->iid[4] == 3);
+ test($mo5->sid["test"] == 10);
+ test($mo5->fs == $mo1->fs);
+ test($mo5->vs == $mo1->vs);
+ test($mo5->shs == $mo1->shs);
+ test($mo5->es[0] == $enum && $mo1->es[1] == $enum);
+ test($mo5->fss[0] == $fs);
+ test($mo5->vss[0] == $vs);
+ test($mo5->oos[0]->a == 15);
+ test($mo5->oops[0] == $ooprx);
+
+ test($mo5->ied[4] == $enum);
+ test($mo5->ifsd[4] == $fs);
+ test($mo5->ivsd[5] == $vs);
+ test($mo5->iood[5]->a == 15);
+ test($mo5->ioopd[5] == $ooprx);
+
+ test($mo5->bos == $mo1->bos);
+
+ // Clear the first half of the optional members
+ $mo6 = new $mocls;
+ $mo6->b = $mo5->b;
+ $mo6->d = $mo5->d;
+ $mo6->f = $mo5->f;
+ $mo6->h = $mo5->h;
+ $mo6->j = $mo5->j;
+ $mo6->bs = $mo5->bs;
+ $mo6->iid = $mo5->iid;
+ $mo6->fs = $mo5->fs;
+ $mo6->shs = $mo5->shs;
+ $mo6->fss = $mo5->fss;
+ $mo6->oos = $mo5->oos;
+ $mo6->ifsd = $mo5->ifsd;
+ $mo6->iood = $mo5->iood;
+ $mo6->bos = $mo5->bos;
+
+ $mo7 = $initial->pingPong($mo6);
+ test($mo7->a == Ice_Unset);
+ test($mo7->b == $mo1->b);
+ test($mo7->c == Ice_Unset);
+ test($mo7->d == $mo1->d);
+ test($mo7->e == Ice_Unset);
+ test($mo7->f == $mo1->f);
+ test($mo7->g == Ice_Unset);
+ test($mo7->h == $mo1->h);
+ test($mo7->i == Ice_Unset);
+ test($mo7->j == $mo1->j);
+ test($mo7->k == Ice_Unset);
+ test($mo7->bs[0] == 5);
+ test($mo7->ss == Ice_Unset);
+ test($mo7->iid[4] == 3);
+ test($mo7->sid == Ice_Unset);
+ test($mo7->fs == $mo1->fs);
+ test($mo7->vs == Ice_Unset);
+
+ test($mo7->shs == $mo1->shs);
+ test($mo7->es == Ice_Unset);
+ test($mo7->fss[0] == $fs);
+ test($mo7->vss == Ice_Unset);
+ test($mo7->oos[0]->a == 15);
+ test($mo7->oops == Ice_Unset);
+
+ test($mo7->ied == Ice_Unset);
+ test($mo7->ifsd[4] == $fs);
+ test($mo7->ivsd == Ice_Unset);
+ test($mo7->iood[5]->a == 15);
+ test($mo7->ioopd == Ice_Unset);
+
+ test($mo7->bos == array(false, true, false));
+
+ // Clear the second half of the optional members
+ $mo8 = new $mocls;
+ $mo8->a = $mo5->a;
+ $mo8->c = $mo5->c;
+ $mo8->e = $mo5->e;
+ $mo8->g = $mo5->g;
+ $mo8->i = $mo5->i;
+ $mo8->k = $mo8;
+ $mo8->ss = $mo5->ss;
+ $mo8->sid = $mo5->sid;
+ $mo8->vs = $mo5->vs;
+
+ $mo8->es = $mo5->es;
+ $mo8->vss = $mo5->vss;
+ $mo8->oops = $mo5->oops;
+
+ $mo8->ied = $mo5->ied;
+ $mo8->ivsd = $mo5->ivsd;
+ $mo8->ioopd = $mo5->ioopd;
+
+ $mo9 = $initial->pingPong($mo8);
+ test($mo9->a == $mo1->a);
+ test($mo9->b == Ice_Unset);
+ test($mo9->c == $mo1->c);
+ test($mo9->d == Ice_Unset);
+ test($mo9->e == $mo1->e);
+ test($mo9->f == Ice_Unset);
+ test($mo9->g == $mo1->g);
+ test($mo9->h == Ice_Unset);
+ test($mo9->i == $mo1->i);
+ test($mo9->j == Ice_Unset);
+ test($mo9->k == $mo9);
+ test($mo9->bs == Ice_Unset);
+ test($mo9->ss == $mo1->ss);
+ test($mo9->iid == Ice_Unset);
+ test($mo9->sid["test"] == 10);
+ test($mo9->fs == Ice_Unset);
+ test($mo9->vs == $mo1->vs);
+
+ test($mo9->shs == Ice_Unset);
+ test($mo9->es[0] == $enum && $mo1->es[1] == $enum);
+ test($mo9->fss == Ice_Unset);
+ test($mo9->vss[0] == $vs);
+ test($mo9->oos == Ice_Unset);
+ test($mo9->oops[0] == $ooprx);
+
+ test($mo9->ied[4] == $enum);
+ test($mo9->ifsd == Ice_Unset);
+ test($mo9->ivsd[5] == $vs);
+ test($mo9->iood == Ice_Unset);
+ test($mo9->ioopd[5] == $ooprx);
+
+ test($mo9->bos == Ice_Unset);
+
+ echo "ok\n";
+
+ echo "testing marshaling of large containers with fixed size elements... ";
+ flush();
+
+ $mc = new $mocls;
+ $mc->bs = array();
+ for($i = 0; $i < 1000; $i++)
+ {
+ $mc->bs[$i] = 0;
+ }
+ $mc->shs = array();
+ for($i = 0; $i < 300; $i++)
+ {
+ $mc->shs[$i] = 0;
+ }
+ $mc->fss = array();
+ for($i = 0; $i < 300; $i++)
+ {
+ $mc->fss[$i] = new $fscls;
+ }
+ $mc->ifsd = array();
+ for($i = 0; $i < 300; $i++)
+ {
+ $mc->ifsd[$i] = new $fscls;
+ }
+
+ $mc = $initial->pingPong($mc);
+ test(count($mc->bs) == 1000);
+ test(count($mc->shs) == 300);
+ test(count($mc->fss) == 300);
+ test(count($mc->ifsd) == 300);
+
+ echo "ok\n";
+
+ echo "testing tag marshaling... ";
+ flush();
+
+ $bcls = $NS ? "Test\\B" : "Test_B";
+ $b = new $bcls;
+ $b2 = $initial->pingPong($b);
+ test($b2->ma == Ice_Unset);
+ test($b2->mb == Ice_Unset);
+ test($b2->mc == Ice_Unset);
+
+ $b->ma = 10;
+ $b->mb = 11;
+ $b->mc = 12;
+ $b->md = 13;
+
+ $b2 = $initial->pingPong($b);
+ test($b2->ma == 10);
+ test($b2->mb == 11);
+ test($b2->mc == 12);
+ test($b2->md == 13);
+
+ echo "ok\n";
+
+ echo "testing optional with default values... ";
+ flush();
+
+ $wdcls = $NS ? "Test\\WD" : "Test_WD";
+ $wd = $initial->pingPong(new $wdcls);
+ test($wd->a == 5);
+ test($wd->s == "test");
+ $wd->a = Ice_Unset;
+ $wd->s = Ice_Unset;
+ $wd = $initial->pingPong($wd);
+ test($wd->a == Ice_Unset);
+ test($wd->s == Ice_Unset);
+
+ echo "ok\n";
+
+ if($communicator->getProperties()->getPropertyAsInt("Ice.Default.SlicedFormat") > 0)
+ {
+ echo "testing marshaling with unknown class slices... ";
+ flush();
+
+ $ccls = $NS ? "Test\\C" : "Test_C";
+ $c = new $ccls;
+ $c->ss = "test";
+ $c->ms = "testms";
+ $c = $initial->pingPong($c);
+ test($c->ma == Ice_Unset);
+ test($c->mb == Ice_Unset);
+ test($c->mc == Ice_Unset);
+ test($c->md == Ice_Unset);
+ test($c->ss == "test");
+ test($c->ms == "testms");
+
+ echo "ok\n";
+
+ echo "testing optionals with unknown classes... ";
+ flush();
+
+ $initial2 = $NS ? eval("return Test\\Initial2PrxHelper::uncheckedCast(\$base);") :
+ eval("return Test_Initial2PrxHelper::uncheckedCast(\$base);");
+ $acls = $NS ? "Test\\A" : "Test_A";
+ $dcls = $NS ? "Test\\D" : "Test_D";
+ $d = new $dcls;
+ $d->ds = "test";
+ $d->seq = array("test1", "test2", "test3", "test4");
+ $d->ao = new $acls(18);
+ $d->requiredB = 14;
+ $d->requiredA = 14;
+ $initial2->opClassAndUnknownOptional(new $acls, $d);
+
+ echo "ok\n";
+ }
+
+ echo "testing optional parameters... ";
+ flush();
+
+ $p2 = 0;
+ $p3 = $initial->opByte(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p3 = $initial->opByte(56, $p2);
+ test($p2 == 56 && $p3 == 56);
+
+ $p3 = $initial->opBool(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p3 = $initial->opBool(true, $p2);
+ test($p2 == true && $p3 == true);
+
+ $p3 = $initial->opShort(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p3 = $initial->opShort(56, $p2);
+ test($p2 == 56 && $p3 == 56);
+
+ $p3 = $initial->opInt(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p3 = $initial->opInt(56, $p2);
+ test($p2 == 56 && $p3 == 56);
+
+ $p3 = $initial->opLong(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p3 = $initial->opLong(56, $p2);
+ test($p2 == 56 && $p3 == 56);
+
+ $p3 = $initial->opFloat(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p3 = $initial->opFloat(1.0, $p2);
+ test($p2 == 1.0 && $p3 == 1.0);
+
+ $p3 = $initial->opDouble(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p3 = $initial->opDouble(1.0, $p2);
+ test($p2 == 1.0 && $p3 == 1.0);
+
+ $p3 = $initial->opString(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p3 = $initial->opString("test", $p2);
+ test($p2 == "test" && $p3 == "test");
+
+ $p3 = $initial->opMyEnum(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p3 = $initial->opMyEnum($enum, $p2);
+ test($p2 == $enum && $p3 == $enum);
+
+ $sscls = $NS ? "Test\\SmallStruct" : "Test_SmallStruct";
+ $p3 = $initial->opSmallStruct(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = new $sscls(56);
+ $p3 = $initial->opSmallStruct($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ $p3 = $initial->opFixedStruct(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = new $fscls(56);
+ $p3 = $initial->opFixedStruct($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ $p3 = $initial->opVarStruct(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = new $vscls("test");
+ $p3 = $initial->opVarStruct($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ $p3 = $initial->opOneOptional(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = new $oocls(58);
+ $p3 = $initial->opOneOptional($p1, $p2);
+ test($p2->a == $p1->a && $p3->a == $p1->a);
+
+ $p3 = $initial->opOneOptionalProxy(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p3 = $initial->opOneOptionalProxy($ooprx, $p2);
+ test($p2 == $ooprx && $p3 == $ooprx);
+
+ $p3 = $initial->opByteSeq(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = array();
+ for($i = 0; $i < 100; $i++)
+ {
+ $p1[$i] = 56;
+ }
+ $p3 = $initial->opByteSeq($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ $p3 = $initial->opBoolSeq(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = array();
+ for($i = 0; $i < 100; $i++)
+ {
+ $p1[$i] = true;
+ }
+ $p3 = $initial->opBoolSeq($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ $p3 = $initial->opShortSeq(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = array();
+ for($i = 0; $i < 100; $i++)
+ {
+ $p1[$i] = 56;
+ }
+ $p3 = $initial->opShortSeq($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ $p3 = $initial->opIntSeq(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = array();
+ for($i = 0; $i < 100; $i++)
+ {
+ $p1[$i] = 56;
+ }
+ $p3 = $initial->opIntSeq($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ $p3 = $initial->opLongSeq(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = array();
+ for($i = 0; $i < 100; $i++)
+ {
+ $p1[$i] = 56;
+ }
+ $p3 = $initial->opLongSeq($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ $p3 = $initial->opFloatSeq(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = array();
+ for($i = 0; $i < 100; $i++)
+ {
+ $p1[$i] = 1.0;
+ }
+ $p3 = $initial->opFloatSeq($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ $p3 = $initial->opDoubleSeq(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = array();
+ for($i = 0; $i < 100; $i++)
+ {
+ $p1[$i] = 1.0;
+ }
+ $p3 = $initial->opDoubleSeq($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ $p3 = $initial->opStringSeq(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = array();
+ for($i = 0; $i < 100; $i++)
+ {
+ $p1[$i] = "test1";
+ }
+ $p3 = $initial->opStringSeq($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ $p3 = $initial->opSmallStructSeq(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = array();
+ for($i = 0; $i < 10; $i++)
+ {
+ $p1[$i] = new $sscls(1);
+ }
+ $p3 = $initial->opSmallStructSeq($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ $p3 = $initial->opFixedStructSeq(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = array();
+ for($i = 0; $i < 10; $i++)
+ {
+ $p1[$i] = new $fscls(1);
+ }
+ $p3 = $initial->opFixedStructSeq($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ $p3 = $initial->opVarStructSeq(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = array();
+ for($i = 0; $i < 10; $i++)
+ {
+ $p1[$i] = new $vscls("test");
+ }
+ $p3 = $initial->opVarStructSeq($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ $p3 = $initial->opIntIntDict(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = array(1=>2, 2=>3);
+ $p3 = $initial->opIntIntDict($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ $p3 = $initial->opStringIntDict(Ice_Unset, $p2);
+ test($p2 == Ice_Unset && $p3 == Ice_Unset);
+ $p1 = array("1"=>2, "2"=>3);
+ $p3 = $initial->opStringIntDict($p1, $p2);
+ test($p2 == $p1 && $p3 == $p1);
+
+ echo "ok\n";
+
+ echo "testing exception optionals... ";
+ flush();
+
+ try
+ {
+ $initial->opOptionalException(Ice_Unset, Ice_Unset, Ice_Unset);
+ }
+ catch(Exception $ex)
+ {
+ $excls = $NS ? "Test\\OptionalException" : "Test_OptionalException";
+ if(!($ex instanceof $excls))
+ {
+ throw $ex;
+ }
+ test($ex->a == Ice_Unset);
+ test($ex->b == Ice_Unset);
+ test($ex->o == Ice_Unset);
+ }
+
+ try
+ {
+ $initial->opOptionalException(30, "test", new $oocls(53));
+ }
+ catch(Exception $ex)
+ {
+ test($ex->a == 30);
+ test($ex->b == "test");
+ test($ex->o->a == 53);
+ }
+
+ try
+ {
+ $initial->opDerivedException(Ice_Unset, Ice_Unset, Ice_Unset);
+ }
+ catch(Exception $ex)
+ {
+ test($ex->a == Ice_Unset);
+ test($ex->b == Ice_Unset);
+ test($ex->o == Ice_Unset);
+ test($ex->ss == Ice_Unset);
+ test($ex->o2 == Ice_Unset);
+ }
+
+ try
+ {
+ $initial->opDerivedException(30, "test", new $oocls(53));
+ }
+ catch(Exception $ex)
+ {
+ test($ex->a == 30);
+ test($ex->b == "test");
+ test($ex->o->a == 53);
+ test($ex->ss == "test");
+ test($ex->o2 == $ex->o);
+ }
+
+ try
+ {
+ $initial->opRequiredException(Ice_Unset, Ice_Unset, Ice_Unset);
+ }
+ catch(Exception $ex)
+ {
+ test($ex->a == Ice_Unset);
+ test($ex->b == Ice_Unset);
+ test($ex->o == Ice_Unset);
+ test($ex->ss != Ice_Unset);
+ test($ex->o2 != Ice_Unset);
+ }
+
+ try
+ {
+ $initial->opRequiredException(30, "test", new $oocls(53));
+ }
+ catch(Exception $ex)
+ {
+ test($ex->a == 30);
+ test($ex->b == "test");
+ test($ex->o->a == 53);
+ test($ex->ss == "test");
+ test($ex->o2 == $ex->o);
+ }
+
+ echo "ok\n";
+
+ return $initial;
+}
+
+$communicator = Ice_initialize($argv);
+
+$initial = allTests($communicator);
+
+$initial->shutdown();
+$communicator->destroy();
+
+exit();
+?>
diff --git a/php/test/Ice/optional/ClientPrivate.ice b/php/test/Ice/optional/ClientPrivate.ice
new file mode 100644
index 00000000000..a456124b4ec
--- /dev/null
+++ b/php/test/Ice/optional/ClientPrivate.ice
@@ -0,0 +1,37 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#pragma once
+
+#include <Test.ice>
+
+module Test
+{
+
+//
+// The server doesn't know this class.
+//
+class D extends B
+{
+ string ds;
+ optional(990) StringSeq seq;
+ optional(1000) A ao;
+};
+
+//
+// This class is a hack that allows us to invoke the opClassAndUnknownOptional operation
+// on the server and pass an optional argument. This isn't necessary in other language
+// mappings where the public stream API is available.
+//
+class Initial2
+{
+ void opClassAndUnknownOptional(A p, optional(1) Object o);
+};
+
+};
diff --git a/php/test/Ice/optional/Makefile b/php/test/Ice/optional/Makefile
new file mode 100644
index 00000000000..a390fe5e62b
--- /dev/null
+++ b/php/test/Ice/optional/Makefile
@@ -0,0 +1,27 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+top_srcdir = ../../..
+
+SLICE_SRCS = ClientPrivate.ice Test.ice
+
+include $(top_srcdir)/config/Make.rules.php
+
+SRCS = ClientPrivate.php Test.php
+SLICE2PHPFLAGS := -I. $(SLICE2PHPFLAGS)
+
+all:: $(SRCS)
+
+%.php: %.ice
+ $(SLICE2PHP) $(SLICE2PHPFLAGS) $<
+
+clean::
+ rm -f $(SRCS)
+
+include .depend
diff --git a/php/test/Ice/optional/Makefile.mak b/php/test/Ice/optional/Makefile.mak
new file mode 100644
index 00000000000..7d43d824315
--- /dev/null
+++ b/php/test/Ice/optional/Makefile.mak
@@ -0,0 +1,25 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+top_srcdir = ..\..\..
+
+!include $(top_srcdir)\config\Make.rules.mak.php
+
+SRCS = ClientPrivate.php Test.php
+SLICE2PHPFLAGS = -I. $(SLICE2PHPFLAGS)
+
+all:: $(SRCS)
+
+$(SRCS): $*.ice
+ -"$(SLICE2PHP)" $(SLICE2PHPFLAGS) $*.ice
+
+clean::
+ del /q $(SRCS)
+
+include .depend.mak
diff --git a/php/test/Ice/optional/Test.ice b/php/test/Ice/optional/Test.ice
new file mode 100644
index 00000000000..7f0342b8df4
--- /dev/null
+++ b/php/test/Ice/optional/Test.ice
@@ -0,0 +1,246 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#pragma once
+
+module Test
+{
+
+class OneOptional
+{
+ optional(1) int a;
+};
+
+enum MyEnum
+{
+ MyEnumMember
+};
+
+struct SmallStruct
+{
+ byte m;
+};
+
+struct FixedStruct
+{
+ int m;
+};
+
+struct VarStruct
+{
+ string m;
+};
+
+struct ClassVarStruct
+{
+ int a;
+};
+
+sequence<byte> ByteSeq;
+sequence<bool> BoolSeq;
+sequence<short> ShortSeq;
+sequence<int> IntSeq;
+sequence<long> LongSeq;
+sequence<float> FloatSeq;
+sequence<double> DoubleSeq;
+sequence<string> StringSeq;
+sequence<MyEnum> MyEnumSeq;
+sequence<SmallStruct> SmallStructSeq;
+sequence<SmallStruct> SmallStructList;
+sequence<FixedStruct> FixedStructSeq;
+sequence<FixedStruct> FixedStructList;
+sequence<VarStruct> VarStructSeq;
+sequence<OneOptional> OneOptionalSeq;
+sequence<OneOptional*> OneOptionalPrxSeq;
+
+sequence<byte> Serializable;
+
+dictionary<int, int> IntIntDict;
+dictionary<string, int> StringIntDict;
+dictionary<int, MyEnum> IntEnumDict;
+dictionary<int, FixedStruct> IntFixedStructDict;
+dictionary<int, VarStruct> IntVarStructDict;
+dictionary<int, OneOptional> IntOneOptionalDict;
+dictionary<int, OneOptional*> IntOneOptionalPrxDict;
+
+class MultiOptional
+{
+ optional(1) byte a;
+ optional(2) bool b;
+ optional(3) short c;
+ optional(4) int d;
+ optional(5) long e;
+ optional(6) float f;
+ optional(7) double g;
+ optional(8) string h;
+ optional(9) MyEnum i;
+ optional(10) MultiOptional* j;
+ optional(11) MultiOptional k;
+ optional(12) ByteSeq bs;
+ optional(13) StringSeq ss;
+ optional(14) IntIntDict iid;
+ optional(15) StringIntDict sid;
+ optional(16) FixedStruct fs;
+ optional(17) VarStruct vs;
+
+ optional(18) ShortSeq shs;
+ optional(19) MyEnumSeq es;
+ optional(20) FixedStructSeq fss;
+ optional(21) VarStructSeq vss;
+ optional(22) OneOptionalSeq oos;
+ optional(23) OneOptionalPrxSeq oops;
+
+ optional(24) IntEnumDict ied;
+ optional(25) IntFixedStructDict ifsd;
+ optional(26) IntVarStructDict ivsd;
+ optional(27) IntOneOptionalDict iood;
+ optional(28) IntOneOptionalPrxDict ioopd;
+
+ optional(29) BoolSeq bos;
+
+ optional(30) Serializable ser;
+};
+
+class A
+{
+ int requiredA;
+ optional(1) int ma;
+ optional(50) int mb;
+ optional(500) int mc;
+};
+
+["preserve-slice"]
+class B extends A
+{
+ int requiredB;
+ optional(10) int md;
+};
+
+class C extends B
+{
+ string ss;
+ optional(890) string ms;
+};
+
+class WD
+{
+ optional(1) int a = 5;
+ optional(2) string s = "test";
+};
+
+exception OptionalException
+{
+ optional(1) int a = 5;
+ optional(2) string b;
+ optional(50) OneOptional o;
+};
+
+exception DerivedException extends OptionalException
+{
+ optional(600) string ss = "test";
+ optional(601) OneOptional o2;
+};
+
+exception RequiredException extends OptionalException
+{
+ string ss = "test";
+ OneOptional o2;
+};
+
+class OptionalWithCustom
+{
+ optional(1) SmallStructList l;
+ ["protected"] optional(2) SmallStructList lp;
+ optional(3) ClassVarStruct s;
+};
+
+["ami"]
+class Initial
+{
+ void shutdown();
+
+ Object pingPong(Object o);
+
+ void opOptionalException(optional(1) int a, optional(2) string b, optional(3) OneOptional o)
+ throws OptionalException;
+
+ void opDerivedException(optional(1) int a, optional(2) string b, optional(3) OneOptional o)
+ throws OptionalException;
+
+ void opRequiredException(optional(1) int a, optional(2) string b, optional(3) OneOptional o)
+ throws OptionalException;
+
+ optional(1) byte opByte(optional(2) byte p1, out optional(3) byte p3);
+
+ optional(1) bool opBool(optional(2) bool p1, out optional(3) bool p3);
+
+ optional(1) short opShort(optional(2) short p1, out optional(3) short p3);
+
+ optional(1) int opInt(optional(2) int p1, out optional(3) int p3);
+
+ optional(3) long opLong(optional(1) long p1, out optional(2) long p3);
+
+ optional(1) float opFloat(optional(2) float p1, out optional(3) float p3);
+
+ optional(1) double opDouble(optional(2) double p1, out optional(3) double p3);
+
+ optional(1) string opString(optional(2) string p1, out optional(3) string p3);
+
+ optional(1) MyEnum opMyEnum(optional(2) MyEnum p1, out optional(3) MyEnum p3);
+
+ optional(1) SmallStruct opSmallStruct(optional(2) SmallStruct p1, out optional(3) SmallStruct p3);
+
+ optional(1) FixedStruct opFixedStruct(optional(2) FixedStruct p1, out optional(3) FixedStruct p3);
+
+ optional(1) VarStruct opVarStruct(optional(2) VarStruct p1, out optional(3) VarStruct p3);
+
+ optional(1) OneOptional opOneOptional(optional(2) OneOptional p1, out optional(3) OneOptional p3);
+
+ optional(1) OneOptional* opOneOptionalProxy(optional(2) OneOptional* p1, out optional(3) OneOptional* p3);
+
+ optional(1) ByteSeq opByteSeq(optional(2) ByteSeq p1, out optional(3) ByteSeq p3);
+
+ optional(1) BoolSeq opBoolSeq(optional(2) BoolSeq p1, out optional(3) BoolSeq p3);
+
+ optional(1) ShortSeq opShortSeq(optional(2) ShortSeq p1, out optional(3) ShortSeq p3);
+
+ optional(1) IntSeq opIntSeq(optional(2) IntSeq p1, out optional(3) IntSeq p3);
+
+ optional(1) LongSeq opLongSeq(optional(2) LongSeq p1, out optional(3) LongSeq p3);
+
+ optional(1) FloatSeq opFloatSeq(optional(2) FloatSeq p1, out optional(3) FloatSeq p3);
+
+ optional(1) DoubleSeq opDoubleSeq(optional(2) DoubleSeq p1, out optional(3) DoubleSeq p3);
+
+ optional(1) StringSeq opStringSeq(optional(2) StringSeq p1, out optional(3) StringSeq p3);
+
+ optional(1) SmallStructSeq opSmallStructSeq(optional(2) SmallStructSeq p1, out optional(3) SmallStructSeq p3);
+
+ optional(1) SmallStructList opSmallStructList(optional(2) SmallStructList p1, out optional(3) SmallStructList p3);
+
+ optional(1) FixedStructSeq opFixedStructSeq(optional(2) FixedStructSeq p1, out optional(3) FixedStructSeq p3);
+
+ optional(1) FixedStructList opFixedStructList(optional(2) FixedStructList p1, out optional(3) FixedStructList p3);
+
+ optional(1) VarStructSeq opVarStructSeq(optional(2) VarStructSeq p1, out optional(3) VarStructSeq p3);
+
+ optional(1) IntIntDict opIntIntDict(optional(2) IntIntDict p1, out optional(3) IntIntDict p3);
+
+ optional(1) StringIntDict opStringIntDict(optional(2) StringIntDict p1, out optional(3) StringIntDict p3);
+
+ void opClassAndUnknownOptional(A p);
+
+ bool supportsRequiredParams();
+
+ bool supportsJavaSerializable();
+
+ bool supportsCsharpSerializable();
+};
+
+};
diff --git a/php/test/Ice/optional/run.py b/php/test/Ice/optional/run.py
new file mode 100755
index 00000000000..13f58435db4
--- /dev/null
+++ b/php/test/Ice/optional/run.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+# **********************************************************************
+#
+# Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+import os, sys
+
+path = [ ".", "..", "../..", "../../..", "../../../..", "../../../../.." ]
+head = os.path.dirname(sys.argv[0])
+if len(head) > 0:
+ path = [os.path.join(head, p) for p in path]
+path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ]
+if len(path) == 0:
+ raise RuntimeError("can't find toplevel directory!")
+sys.path.append(os.path.join(path[0], "scripts"))
+import TestUtil
+
+print("Running test with compact (default) format.")
+TestUtil.clientServerTest()
+print("Running test with sliced format.")
+TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.SlicedFormat", additionalServerOptions="--Ice.Default.SlicedFormat")
diff --git a/php/test/Ice/slicing/objects/Client.php b/php/test/Ice/slicing/objects/Client.php
index e57f3b44269..a2e817ef2ad 100644
--- a/php/test/Ice/slicing/objects/Client.php
+++ b/php/test/Ice/slicing/objects/Client.php
@@ -110,15 +110,24 @@ function allTests($communicator)
echo "unknown with Object as Object... ";
flush();
{
+ $usocls = $NS ? "Ice\\UnknownSlicedObject" : "Ice_UnknownSlicedObject";
try
{
$o = $test->SUnknownAsObject();
- test(false);
+ test($test->ice_getEncodingVersion() != $Ice_Encoding_1_0);
+ test($o instanceof $usocls);
+ test($o->unknownTypeId == "::Test::SUnknown");
+ test($o->_ice_slicedData != null);
+ $test->checkSUnknown($o);
}
catch(Exception $b)
{
$excls = $NS ? "Ice\\NoObjectFactoryException" : "Ice_NoObjectFactoryException";
- if(!($b instanceof $excls))
+ if($b instanceof $excls)
+ {
+ test($test->ice_getEncodingVersion() == $Ice_Encoding_1_0);
+ }
+ else
{
throw $ex;
}
diff --git a/php/test/Ice/slicing/objects/Test.ice b/php/test/Ice/slicing/objects/Test.ice
index 8e20db55def..1272f947d8b 100644
--- a/php/test/Ice/slicing/objects/Test.ice
+++ b/php/test/Ice/slicing/objects/Test.ice
@@ -110,6 +110,7 @@ interface TestIntf
["format:compact"] SBase SBSUnknownDerivedAsSBaseCompact();
Object SUnknownAsObject();
+ void checkSUnknown(Object o);
B oneElementCycle();
B twoElementCycle();