summaryrefslogtreecommitdiff
path: root/php/src
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2012-10-12 15:31:48 -0700
committerMark Spruiell <mes@zeroc.com>2012-10-12 15:31:48 -0700
commited09446f6ab09a14abbbf3080bfa5986927a070d (patch)
tree4b3735e7b7b1c2ffe8056f7b9be7adbeb4d50f16 /php/src
parentWinRT port updates (diff)
downloadice-ed09446f6ab09a14abbbf3080bfa5986927a070d.tar.bz2
ice-ed09446f6ab09a14abbbf3080bfa5986927a070d.tar.xz
ice-ed09446f6ab09a14abbbf3080bfa5986927a070d.zip
PHP optionals
Diffstat (limited to 'php/src')
-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
7 files changed, 1186 insertions, 472 deletions
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;