diff options
author | Jose <jose@zeroc.com> | 2017-01-19 11:49:04 +0100 |
---|---|---|
committer | Jose <jose@zeroc.com> | 2017-01-19 11:49:04 +0100 |
commit | 404a62d1c8455a7d6f9a74b14c56e8e9ee1640ab (patch) | |
tree | c6bf8cfa188dbb78b19c3017084d499c913e4cd0 /php/src | |
parent | Removed unused Info.plist file for Objective-C controller project (diff) | |
download | ice-404a62d1c8455a7d6f9a74b14c56e8e9ee1640ab.tar.bz2 ice-404a62d1c8455a7d6f9a74b14c56e8e9ee1640ab.tar.xz ice-404a62d1c8455a7d6f9a74b14c56e8e9ee1640ab.zip |
IcePHP Ice::Value implementation & minor extension cleanup
Diffstat (limited to 'php/src')
-rw-r--r-- | php/src/php5/Communicator.cpp | 24 | ||||
-rw-r--r-- | php/src/php5/Operation.cpp | 30 | ||||
-rw-r--r-- | php/src/php5/Proxy.cpp | 68 | ||||
-rw-r--r-- | php/src/php5/Proxy.h | 6 | ||||
-rw-r--r-- | php/src/php5/Types.cpp | 315 | ||||
-rw-r--r-- | php/src/php5/Types.h | 30 | ||||
-rw-r--r-- | php/src/php7/Communicator.cpp | 29 | ||||
-rw-r--r-- | php/src/php7/Operation.cpp | 28 | ||||
-rw-r--r-- | php/src/php7/Proxy.cpp | 69 | ||||
-rw-r--r-- | php/src/php7/Proxy.h | 6 | ||||
-rw-r--r-- | php/src/php7/Types.cpp | 313 | ||||
-rw-r--r-- | php/src/php7/Types.h | 30 |
12 files changed, 517 insertions, 431 deletions
diff --git a/php/src/php5/Communicator.cpp b/php/src/php5/Communicator.cpp index 2d8fcc0b919..c22723e53d7 100644 --- a/php/src/php5/Communicator.cpp +++ b/php/src/php5/Communicator.cpp @@ -354,7 +354,7 @@ ZEND_METHOD(Ice_Communicator, proxyToString) if(zv) { Ice::ObjectPrx prx; - ClassInfoPtr info; + ProxyInfoPtr info; if(!fetchProxy(zv, prx, info TSRMLS_CC)) { RETURN_NULL(); @@ -420,7 +420,7 @@ ZEND_METHOD(Ice_Communicator, proxyToProperty) if(zv) { Ice::ObjectPrx prx; - ClassInfoPtr info; + ProxyInfoPtr info; if(!fetchProxy(zv, prx, info TSRMLS_CC)) { RETURN_NULL(); @@ -664,7 +664,7 @@ ZEND_METHOD(Ice_Communicator, getDefaultRouter) Ice::RouterPrx router = _this->getCommunicator()->getDefaultRouter(); if(router) { - ClassInfoPtr info = getClassInfoById("::Ice::Router" TSRMLS_CC); + ProxyInfoPtr info = getProxyInfo("::Ice::Router" TSRMLS_CC); if(!info) { runtimeError("no definition for Ice::Router" TSRMLS_CC); @@ -700,7 +700,7 @@ ZEND_METHOD(Ice_Communicator, setDefaultRouter) } Ice::ObjectPrx proxy; - ClassInfoPtr info; + ProxyInfoPtr info; if(zv && !fetchProxy(zv, proxy, info TSRMLS_CC)) { RETURN_NULL(); @@ -742,7 +742,7 @@ ZEND_METHOD(Ice_Communicator, getDefaultLocator) Ice::LocatorPrx locator = _this->getCommunicator()->getDefaultLocator(); if(locator) { - ClassInfoPtr info = getClassInfoById("::Ice::Locator" TSRMLS_CC); + ProxyInfoPtr info = getProxyInfo("::Ice::Locator" TSRMLS_CC); if(!info) { runtimeError("no definition for Ice::Locator" TSRMLS_CC); @@ -778,7 +778,7 @@ ZEND_METHOD(Ice_Communicator, setDefaultLocator) } Ice::ObjectPrx proxy; - ClassInfoPtr info; + ProxyInfoPtr info; if(zv && !fetchProxy(zv, proxy, info TSRMLS_CC)) { RETURN_NULL(); @@ -1850,7 +1850,7 @@ IcePHP::FactoryWrapper::create(const string& id) // 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); + cls = getClassInfoById("::Ice::UnknownSlicedValue" TSRMLS_CC); } else { @@ -1961,7 +1961,7 @@ IcePHP::DefaultValueFactory::create(const string& id) // 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); + cls = getClassInfoById("::Ice::UnknownSlicedValue" TSRMLS_CC); } else { @@ -1974,14 +1974,6 @@ IcePHP::DefaultValueFactory::create(const string& id) } // - // If the requested type is an abstract class, then we give up. - // - if(cls->isAbstract) - { - return 0; - } - - // // Instantiate the object. // zval* obj; diff --git a/php/src/php5/Operation.cpp b/php/src/php5/Operation.cpp index 0117b62a9ed..ede0a594807 100644 --- a/php/src/php5/Operation.cpp +++ b/php/src/php5/Operation.cpp @@ -390,19 +390,19 @@ 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->optional = zend_hash_num_elements(arr) > 1; + if(param->optional) + { + zend_hash_index_find(arr, 1, reinterpret_cast<void**>(&m)); + assert(Z_TYPE_PP(m) == IS_LONG); + param->tag = Z_LVAL_PP(m); + } param->pos = pos; return param; @@ -875,11 +875,13 @@ ZEND_FUNCTION(IcePHP_defineOperation) } TypeInfoPtr type = Wrapper<TypeInfoPtr>::value(cls TSRMLS_CC); - ClassInfoPtr c = ClassInfoPtr::dynamicCast(type); + ProxyInfoPtr c = ProxyInfoPtr::dynamicCast(type); assert(c); - OperationIPtr op = new OperationI(name, static_cast<Ice::OperationMode>(mode), - static_cast<Ice::OperationMode>(sendMode), static_cast<Ice::FormatType>(format), + OperationIPtr op = new OperationI(name, + static_cast<Ice::OperationMode>(mode), + static_cast<Ice::OperationMode>(sendMode), + static_cast<Ice::FormatType>(format), inParams, outParams, returnType, exceptions TSRMLS_CC); c->addOperation(name, op); @@ -888,17 +890,17 @@ ZEND_FUNCTION(IcePHP_defineOperation) ZEND_FUNCTION(IcePHP_Operation_call) { Ice::ObjectPrx proxy; - ClassInfoPtr cls; + ProxyInfoPtr info; CommunicatorInfoPtr comm; #ifndef NDEBUG bool b = #endif - fetchProxy(getThis(), proxy, cls, comm TSRMLS_CC); + fetchProxy(getThis(), proxy, info, comm TSRMLS_CC); assert(b); assert(proxy); - assert(cls); + assert(info); - OperationPtr op = cls->getOperation(get_active_function_name(TSRMLS_C)); + OperationPtr op = info->getOperation(get_active_function_name(TSRMLS_C)); assert(op); // handleGetMethod should have already verified the operation's existence. OperationIPtr opi = OperationIPtr::dynamicCast(op); assert(opi); diff --git a/php/src/php5/Proxy.cpp b/php/src/php5/Proxy.cpp index 48c30c2782e..d9f60b79d2a 100644 --- a/php/src/php5/Proxy.cpp +++ b/php/src/php5/Proxy.cpp @@ -67,8 +67,6 @@ static union _zend_function* handleGetMethod(zval**, char*, int, const _zend_lit static int handleCompare(zval*, zval* TSRMLS_DC); } -static ClassInfoPtr lookupClass(const string& TSRMLS_DC); - namespace IcePHP { @@ -79,15 +77,15 @@ class Proxy : public IceUtil::Shared { public: - Proxy(const Ice::ObjectPrx&, const ClassInfoPtr&, const CommunicatorInfoPtr& TSRMLS_DC); + Proxy(const Ice::ObjectPrx&, const ProxyInfoPtr&, const CommunicatorInfoPtr& TSRMLS_DC); ~Proxy(); bool clone(zval*, const Ice::ObjectPrx& TSRMLS_DC); bool cloneUntyped(zval*, const Ice::ObjectPrx& TSRMLS_DC); - static bool create(zval*, const Ice::ObjectPrx&, const ClassInfoPtr&, const CommunicatorInfoPtr& TSRMLS_DC); + static bool create(zval*, const Ice::ObjectPrx&, const ProxyInfoPtr&, const CommunicatorInfoPtr& TSRMLS_DC); Ice::ObjectPrx proxy; - ClassInfoPtr info; + ProxyInfoPtr info; CommunicatorInfoPtr communicator; zval* connection; zval* cachedConnection; @@ -763,7 +761,7 @@ ZEND_METHOD(Ice_ObjectPrx, ice_getRouter) Ice::RouterPrx router = _this->proxy->ice_getRouter(); if(router) { - ClassInfoPtr info = lookupClass("::Ice::Router" TSRMLS_CC); + ProxyInfoPtr info = getProxyInfo("::Ice::Router" TSRMLS_CC); if(!info) { RETURN_NULL(); @@ -801,7 +799,7 @@ ZEND_METHOD(Ice_ObjectPrx, ice_router) } Ice::ObjectPrx proxy; - ClassInfoPtr def; + ProxyInfoPtr def; if(zprx && !fetchProxy(zprx, proxy, def TSRMLS_CC)) { RETURN_NULL(); @@ -847,7 +845,7 @@ ZEND_METHOD(Ice_ObjectPrx, ice_getLocator) Ice::LocatorPrx locator = _this->proxy->ice_getLocator(); if(locator) { - ClassInfoPtr info = lookupClass("::Ice::Locator" TSRMLS_CC); + ProxyInfoPtr info = getProxyInfo("::Ice::Locator" TSRMLS_CC); if(!info) { RETURN_NULL(); @@ -883,7 +881,7 @@ ZEND_METHOD(Ice_ObjectPrx, ice_locator) } Ice::ObjectPrx proxy; - ClassInfoPtr def; + ProxyInfoPtr def; if(zprx && !fetchProxy(zprx, proxy, def TSRMLS_CC)) { RETURN_NULL(); @@ -1290,30 +1288,6 @@ ZEND_METHOD(Ice_ObjectPrx, ice_flushBatchRequests) } } -static ClassInfoPtr -lookupClass(const string& id TSRMLS_DC) -{ - ClassInfoPtr info = getClassInfoById(id TSRMLS_CC); - if(!info) - { - if(!id.empty() && id[id.size() - 1] == '*') - { - info = getClassInfoById(id.substr(0, id.size() - 1) TSRMLS_CC); - } - } - - if(info && !info->defined) - { - runtimeError("%s is declared but not defined" TSRMLS_CC, id.c_str()); - } - else if(!info) - { - runtimeError("no definition found for class or interface %s" TSRMLS_CC, id.c_str()); - } - - return info; -} - static void do_cast(INTERNAL_FUNCTION_PARAMETERS, bool check) { @@ -1359,7 +1333,7 @@ do_cast(INTERNAL_FUNCTION_PARAMETERS, bool check) try { - ClassInfoPtr info = lookupClass(id TSRMLS_CC); + ProxyInfoPtr info = getProxyInfo(id TSRMLS_CC); if(!info) { RETURN_NULL(); @@ -1413,7 +1387,7 @@ ZEND_METHOD(Ice_ObjectPrx, ice_checkedCast) do_cast(INTERNAL_FUNCTION_PARAM_PASSTHRU, true); } -IcePHP::Proxy::Proxy(const Ice::ObjectPrx& p, const ClassInfoPtr& i, const CommunicatorInfoPtr& comm TSRMLS_DC) : +IcePHP::Proxy::Proxy(const Ice::ObjectPrx& p, const ProxyInfoPtr& i, const CommunicatorInfoPtr& comm TSRMLS_DC) : proxy(p), info(i), communicator(comm), connection(0), cachedConnection(0) { #ifdef ZTS @@ -1453,14 +1427,14 @@ IcePHP::Proxy::cloneUntyped(zval* zv, const Ice::ObjectPrx& p TSRMLS_DC) } bool -IcePHP::Proxy::create(zval* zv, const Ice::ObjectPrx& p, const ClassInfoPtr& info, const CommunicatorInfoPtr& comm +IcePHP::Proxy::create(zval* zv, const Ice::ObjectPrx& p, const ProxyInfoPtr& info, const CommunicatorInfoPtr& comm TSRMLS_DC) { - ClassInfoPtr cls = info; - if(!cls) + ProxyInfoPtr prx = info; + if(!prx) { - cls = getClassInfoById("::Ice::Object" TSRMLS_CC); - assert(cls); + prx = getProxyInfo("::Ice::Object" TSRMLS_CC); + assert(prx); } if(object_init_ex(zv, proxyClassEntry) != SUCCESS) @@ -1470,7 +1444,7 @@ IcePHP::Proxy::create(zval* zv, const Ice::ObjectPrx& p, const ClassInfoPtr& inf } Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::extract(zv TSRMLS_CC); - ProxyPtr proxy = new Proxy(p, cls, comm TSRMLS_CC); + ProxyPtr proxy = new Proxy(p, prx, comm TSRMLS_CC); assert(!obj->ptr); obj->ptr = new ProxyPtr(proxy); @@ -1571,7 +1545,7 @@ handleGetMethod(zval** zv, char* method, int len, const _zend_literal* key TSRML assert(obj->ptr); ProxyPtr _this = *obj->ptr; - ClassInfoPtr info = _this->info; + ProxyInfoPtr info = _this->info; assert(info); OperationPtr op = info->getOperation(method); @@ -1724,21 +1698,21 @@ IcePHP::createProxy(zval* zv, const Ice::ObjectPrx& p, const CommunicatorInfoPtr } bool -IcePHP::createProxy(zval* zv, const Ice::ObjectPrx& p, const ClassInfoPtr& info, const CommunicatorInfoPtr& comm +IcePHP::createProxy(zval* zv, const Ice::ObjectPrx& p, const ProxyInfoPtr& info, const CommunicatorInfoPtr& comm TSRMLS_DC) { return Proxy::create(zv, p, info, comm TSRMLS_CC); } bool -IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ClassInfoPtr& cls TSRMLS_DC) +IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ProxyInfoPtr& info TSRMLS_DC) { CommunicatorInfoPtr comm; - return fetchProxy(zv, prx, cls, comm TSRMLS_CC); + return fetchProxy(zv, prx, info, comm TSRMLS_CC); } bool -IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ClassInfoPtr& cls, CommunicatorInfoPtr& comm TSRMLS_DC) +IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ProxyInfoPtr& info, CommunicatorInfoPtr& comm TSRMLS_DC) { if(!ZVAL_IS_NULL(zv)) { @@ -1755,7 +1729,7 @@ IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ClassInfoPtr& cls, Communicato } assert(obj->ptr); prx = (*obj->ptr)->proxy; - cls = (*obj->ptr)->info; + info = (*obj->ptr)->info; comm = (*obj->ptr)->communicator; } return true; diff --git a/php/src/php5/Proxy.h b/php/src/php5/Proxy.h index 235a427c2f5..4becbbdd906 100644 --- a/php/src/php5/Proxy.h +++ b/php/src/php5/Proxy.h @@ -20,9 +20,9 @@ namespace IcePHP bool proxyInit(TSRMLS_D); bool createProxy(zval*, const Ice::ObjectPrx&, const CommunicatorInfoPtr& TSRMLS_DC); -bool createProxy(zval*, const Ice::ObjectPrx&, const ClassInfoPtr&, const CommunicatorInfoPtr& TSRMLS_DC); -bool fetchProxy(zval*, Ice::ObjectPrx&, ClassInfoPtr& TSRMLS_DC); -bool fetchProxy(zval*, Ice::ObjectPrx&, ClassInfoPtr&, CommunicatorInfoPtr& TSRMLS_DC); +bool createProxy(zval*, const Ice::ObjectPrx&, const ProxyInfoPtr&, const CommunicatorInfoPtr& TSRMLS_DC); +bool fetchProxy(zval*, Ice::ObjectPrx&, ProxyInfoPtr& TSRMLS_DC); +bool fetchProxy(zval*, Ice::ObjectPrx&, ProxyInfoPtr&, CommunicatorInfoPtr& TSRMLS_DC); // // Class entry. diff --git a/php/src/php5/Types.cpp b/php/src/php5/Types.cpp index 188c512552f..93d9f655b24 100644 --- a/php/src/php5/Types.cpp +++ b/php/src/php5/Types.cpp @@ -75,8 +75,8 @@ addProxyInfo(const ProxyInfoPtr& p TSRMLS_DC) // // getProxyInfo() // -static IcePHP::ProxyInfoPtr -getProxyInfo(const string& id TSRMLS_DC) +IcePHP::ProxyInfoPtr +IcePHP::getProxyInfo(const string& id TSRMLS_DC) { if(ICE_G(proxyInfoMap)) { @@ -2487,17 +2487,17 @@ IcePHP::DictionaryInfo::destroy() // ClassInfo implementation. // IcePHP::ClassInfo::ClassInfo(const string& ident TSRMLS_DC) : - id(ident), compactId(-1), isAbstract(false), preserve(false), zce(0), defined(false) + id(ident), compactId(-1), preserve(false), interface(false), zce(0), defined(false) { } void -IcePHP::ClassInfo::define(const string& n, Ice::Int compact, bool isAbs, bool pres, zval* b, zval* i, zval* m TSRMLS_DC) +IcePHP::ClassInfo::define(const string& n, Ice::Int compact, bool pres, bool intf, zval* b, zval* m TSRMLS_DC) { const_cast<string&>(name) = n; const_cast<Ice::Int&>(compactId) = static_cast<Ice::Int>(compact); - const_cast<bool&>(isAbstract) = isAbs; const_cast<bool&>(preserve) = pres; + const_cast<bool&>(interface) = intf; if(b) { @@ -2506,23 +2506,6 @@ IcePHP::ClassInfo::define(const string& n, Ice::Int compact, bool isAbs, bool pr 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), @@ -2530,8 +2513,14 @@ IcePHP::ClassInfo::define(const string& n, Ice::Int compact, bool isAbs, bool pr } 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. +#ifdef ICEPHP_USE_NAMESPACES + const string valueClass = "Ice\\Value"; +#else + const string valueClass = "Ice_Value"; +#endif + const_cast<zend_class_entry*&>(zce) = nameToClass(interface ? valueClass : name TSRMLS_CC); + // LocalObject and interfaces does not have a native PHP equivalent. + assert(zce || id == "::Ice::LocalObject" || interface); } string @@ -2689,7 +2678,6 @@ void IcePHP::ClassInfo::destroy() { const_cast<ClassInfoPtr&>(base) = 0; - const_cast<ClassInfoList&>(interfaces).clear(); if(!members.empty()) { DataMemberList ml = members; @@ -2761,63 +2749,44 @@ IcePHP::ClassInfo::isA(const string& typeId) const return true; } - if(base && base->isA(typeId)) - { - return true; - } - - for(ClassInfoList::const_iterator p = interfaces.begin(); p != interfaces.end(); ++p) - { - if((*p)->isA(typeId)) - { - return true; - } - } - - return false; + return base && base->isA(typeId); } -void -IcePHP::ClassInfo::addOperation(const string& name, const OperationPtr& op) +// +// ProxyInfo implementation. +// +IcePHP::ProxyInfo::ProxyInfo(const string& ident TSRMLS_DC) : + id(ident), defined(false) { - operations.insert(OperationMap::value_type(Slice::PHP::fixIdent(name), op)); } -IcePHP::OperationPtr -IcePHP::ClassInfo::getOperation(const string& name) const +void +IcePHP::ProxyInfo::define(zval* b, zval* i TSRMLS_DC) { - OperationPtr op; - OperationMap::const_iterator p = operations.find(name); - if(p != operations.end()) - { - op = p->second; - } - if(!op && base) + if(b) { - op = base->getOperation(name); + TypeInfoPtr p = Wrapper<TypeInfoPtr>::value(b); + const_cast<ProxyInfoPtr&>(base) = ProxyInfoPtr::dynamicCast(p); + assert(base); } - if(!op && !interfaces.empty()) + + if(i) { - for(ClassInfoList::const_iterator q = interfaces.begin(); q != interfaces.end() && !op; ++q) + 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) { - op = (*q)->getOperation(name); + zval** interfaceType = reinterpret_cast<zval**>(data); + TypeInfoPtr t = Wrapper<TypeInfoPtr>::value(*interfaceType TSRMLS_CC); + ProxyInfoPtr c = ProxyInfoPtr::dynamicCast(t); + assert(c); + const_cast<ProxyInfoList&>(interfaces).push_back(c); + zend_hash_move_forward_ex(interfacesArray, &pos); } } - return op; -} -// -// 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; } @@ -2881,7 +2850,7 @@ IcePHP::ProxyInfo::marshal(zval* zv, Ice::OutputStream* os, ObjectMap*, bool opt { assert(Z_TYPE_P(zv) == IS_OBJECT && Z_OBJCE_P(zv) == proxyClassEntry); // validate() should have caught this. Ice::ObjectPrx proxy; - ClassInfoPtr info; + ProxyInfoPtr info; if(!fetchProxy(zv, proxy, info TSRMLS_CC)) { throw AbortMarshaling(); @@ -2923,13 +2892,13 @@ IcePHP::ProxyInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& c return; } - if(!cls->defined) + if(!defined) { - runtimeError("class or interface %s is declared but not defined" TSRMLS_CC, id.c_str()); + runtimeError("proxy %s is declared but not defined" TSRMLS_CC, id.c_str()); throw AbortMarshaling(); } - if(!createProxy(zv, proxy, cls, comm TSRMLS_CC)) + if(!createProxy(zv, proxy, this, comm TSRMLS_CC)) { throw AbortMarshaling(); } @@ -2952,8 +2921,8 @@ IcePHP::ProxyInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHist else { Ice::ObjectPrx proxy; - ClassInfoPtr cls; - if(!fetchProxy(zv, proxy, cls TSRMLS_CC)) + ProxyInfoPtr info; + if(!fetchProxy(zv, proxy, info TSRMLS_CC)) { return; } @@ -2964,14 +2933,68 @@ IcePHP::ProxyInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHist void IcePHP::ProxyInfo::destroy() { - const_cast<ClassInfoPtr&>(cls) = 0; + const_cast<ProxyInfoPtr&>(base) = 0; + const_cast<ProxyInfoList&>(interfaces).clear(); +} + +bool +IcePHP::ProxyInfo::isA(const string& typeId) const +{ + if(id == typeId) + { + return true; + } + + if(base && base->isA(typeId)) + { + return true; + } + + for(ProxyInfoList::const_iterator p = interfaces.begin(); p != interfaces.end(); ++p) + { + if((*p)->isA(typeId)) + { + return true; + } + } + + return false; +} + +void +IcePHP::ProxyInfo::addOperation(const string& name, const OperationPtr& op) +{ + operations.insert(OperationMap::value_type(Slice::PHP::fixIdent(name), op)); +} + +IcePHP::OperationPtr +IcePHP::ProxyInfo::getOperation(const string& name) const +{ + OperationPtr op; + OperationMap::const_iterator p = operations.find(name); + if(p != operations.end()) + { + op = p->second; + } + if(!op && base) + { + op = base->getOperation(name); + } + if(!op && !interfaces.empty()) + { + for(ProxyInfoList::const_iterator q = interfaces.begin(); q != interfaces.end() && !op; ++q) + { + op = (*q)->getOperation(name); + } + } + return op; } // // ObjectWriter implementation. // IcePHP::ObjectWriter::ObjectWriter(zval* object, ObjectMap* objectMap, const ClassInfoPtr& formal TSRMLS_DC) : - _object(object), _map(objectMap) + _object(object), _map(objectMap), _formal(formal) { #ifdef ZTS this->TSRMLS_C = TSRMLS_C; @@ -2979,15 +3002,18 @@ IcePHP::ObjectWriter::ObjectWriter(zval* object, ObjectMap* objectMap, const Cla Z_ADDREF_P(_object); - // - // We need to determine the most-derived Slice type supported by this object. - // This is typically a Slice class, but it can also be an interface. - // - // 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 ? const_cast<zend_class_entry*>(formal->zce) : 0 TSRMLS_CC); - assert(_info); + if(!_formal || !_formal->interface) + { + // + // For no interface types We need to determine the most-derived Slice type supported by this object. + // This is typically a Slice class, but it can also be an interface. + // + // 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 ? const_cast<zend_class_entry*>(formal->zce) : 0 TSRMLS_CC); + assert(_info); + } } IcePHP::ObjectWriter::~ObjectWriter() @@ -3013,7 +3039,7 @@ IcePHP::ObjectWriter::_iceWrite(Ice::OutputStream* os) const { Ice::SlicedDataPtr slicedData; - if(_info->preserve) + if(_info && _info->preserve) { // // Retrieve the SlicedData object that we stored as a hidden member of the PHP object. @@ -3023,21 +3049,64 @@ IcePHP::ObjectWriter::_iceWrite(Ice::OutputStream* os) const os->startValue(slicedData); - if(_info->id != "::Ice::UnknownSlicedObject") + if(_formal && _formal->interface) { - ClassInfoPtr info = _info; - while(info && info->id != Ice::Object::ice_staticId()) + // + // For an interface by value we just marshal the Ice type id + // of the object in its own slice. + // + zval* ret = 0; + + zend_try { - 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, info->compactId, lastSlice); + const char* func = "ice_id"; + zval* obj = const_cast<zval*>(_object); + zend_call_method(&obj, 0, 0, const_cast<char*>(func), static_cast<int>(strlen(func)), &ret, 0, 0, + 0 TSRMLS_CC); + } + zend_catch + { + ret = 0; + } + zend_end_try(); - writeMembers(os, info->members); - writeMembers(os, info->optionalMembers); // The optional members have already been sorted by tag. + // + // Bail out if an exception has already been thrown. + // + if(!ret || EG(exception)) + { + throw AbortMarshaling(); + } - os->endSlice(); + AutoDestroy destroy(ret); + + if(Z_TYPE_P(ret) != IS_STRING) + { + throw AbortMarshaling(); + } - info = info->base; + string id(Z_STRVAL_P(ret), Z_STRLEN_P(ret)); + os->startSlice(id, -1, true); + os->endSlice(); + } + else + { + if(_info->id != "::Ice::UnknownSlicedValue") + { + ClassInfoPtr info = _info; + while(info && info->id != Ice::Object::ice_staticId()) + { + 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, info->compactId, lastSlice); + + writeMembers(os, info->members); + writeMembers(os, info->optionalMembers); // The optional members have already been sorted by tag. + + os->endSlice(); + + info = info->base; + } } } @@ -3126,7 +3195,7 @@ IcePHP::ObjectReader::_iceRead(Ice::InputStream* is) { is->startValue(); - const bool unknown = _info->id == "::Ice::UnknownSlicedObject"; + const bool unknown = _info->id == "::Ice::UnknownSlicedValue"; // // Unmarshal the slices of a user-defined class. @@ -3256,7 +3325,7 @@ IcePHP::ReadObjectCallback::invoke(const Ice::ObjectPtr& p) // Verify that the unmarshaled object is compatible with the formal type. // zval* obj = reader->getObject(); - if(!reader->getInfo()->isA(_info->id)) + if(!_info->interface && !reader->getInfo()->isA(_info->id)) { Ice::UnexpectedObjectException ex(__FILE__, __LINE__); ex.reason = "unmarshaled object is not an instance of " + _info->id; @@ -3694,25 +3763,26 @@ ZEND_FUNCTION(IcePHP_declareProxy) ZEND_FUNCTION(IcePHP_defineProxy) { - zval* cls; + char* id; + size_t idLen; + zval* base; + zval* interfaces; + - if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("o"), &cls) == FAILURE) + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("so!a!"), &id, &idLen, &base, &interfaces) == + FAILURE) { return; } - TypeInfoPtr p = Wrapper<TypeInfoPtr>::value(cls TSRMLS_CC); - ClassInfoPtr c = ClassInfoPtr::dynamicCast(p); - assert(c); - - ProxyInfoPtr type = getProxyInfo(c->id TSRMLS_CC); + ProxyInfoPtr type = getProxyInfo(id TSRMLS_CC); if(!type) { - type = new ProxyInfo(c->id TSRMLS_CC); + type = new ProxyInfo(id TSRMLS_CC); addProxyInfo(type TSRMLS_CC); } - type->define(c TSRMLS_CC); + type->define(base, interfaces TSRMLS_CC); if(!createTypeInfo(return_value, type TSRMLS_CC)) { @@ -3750,14 +3820,13 @@ ZEND_FUNCTION(IcePHP_defineClass) char* name; int nameLen; long compactId; - zend_bool isAbstract; zend_bool preserve; + zend_bool interface; zval* base; - zval* interfaces; zval* members; - if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("sslbbo!a!a!"), &id, &idLen, &name, &nameLen, - &compactId, &isAbstract, &preserve, &base, &interfaces, &members) == FAILURE) + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("sslbbo!a!"), &id, &idLen, &name, &nameLen, + &compactId, &preserve, &interface, &base, &members) == FAILURE) { return; } @@ -3769,17 +3838,23 @@ ZEND_FUNCTION(IcePHP_defineClass) addClassInfoById(type TSRMLS_CC); } - type->define(name, static_cast<Ice::Int>(compactId), isAbstract ? true : false, preserve ? true : false, base, - interfaces, members TSRMLS_CC); - addClassInfoByName(type TSRMLS_CC); + type->define(name, static_cast<Ice::Int>(compactId), preserve ? true : false, interface ? true : false, base, + members TSRMLS_CC); + if(!interface) + { + addClassInfoByName(type TSRMLS_CC); + } - CompactIdMap* m = reinterpret_cast<CompactIdMap*>(ICE_G(compactIdToClassInfoMap)); - if(!m) + if(type->compactId != -1) { - m = new CompactIdMap; - ICE_G(compactIdToClassInfoMap) = m; + CompactIdMap* m = reinterpret_cast<CompactIdMap*>(ICE_G(compactIdToClassInfoMap)); + if(!m) + { + m = new CompactIdMap; + ICE_G(compactIdToClassInfoMap) = m; + } + m->insert(CompactIdMap::value_type(type->compactId, type)); } - m->insert(CompactIdMap::value_type(type->compactId, type)); if(!createTypeInfo(return_value, type TSRMLS_CC)) { diff --git a/php/src/php5/Types.h b/php/src/php5/Types.h index 6777990217c..62309e93648 100644 --- a/php/src/php5/Types.h +++ b/php/src/php5/Types.h @@ -45,7 +45,10 @@ class AbortMarshaling class ClassInfo; typedef IceUtil::Handle<ClassInfo> ClassInfoPtr; -typedef std::vector<ClassInfoPtr> ClassInfoList; + +class ProxyInfo; +typedef IceUtil::Handle<ProxyInfo> ProxyInfoPtr; +typedef std::vector<ProxyInfoPtr> ProxyInfoList; typedef std::map<unsigned int, Ice::ObjectPtr> ObjectMap; @@ -417,7 +420,7 @@ public: ClassInfo(const std::string& TSRMLS_DC); - void define(const std::string&, Ice::Int, bool, bool, zval*, zval*, zval* TSRMLS_DC); + void define(const std::string&, Ice::Int, bool, bool, zval*, zval* TSRMLS_DC); virtual std::string getId() const; @@ -441,23 +444,16 @@ public: bool isA(const std::string&) const; - void addOperation(const std::string&, const OperationPtr&); - OperationPtr getOperation(const std::string&) const; - const std::string id; const std::string name; // PHP class name const Ice::Int compactId; - const bool isAbstract; const bool preserve; + const bool interface; const ClassInfoPtr base; - const ClassInfoList interfaces; const DataMemberList members; const DataMemberList optionalMembers; const zend_class_entry* zce; bool defined; - - typedef std::map<std::string, OperationPtr> OperationMap; - OperationMap operations; }; // @@ -469,7 +465,7 @@ public: ProxyInfo(const std::string& TSRMLS_DC); - void define(const ClassInfoPtr& TSRMLS_DC); + void define(zval*, zval* TSRMLS_DC); virtual std::string getId() const; @@ -487,9 +483,17 @@ public: virtual void destroy(); + bool isA(const std::string&) const; + + void addOperation(const std::string&, const OperationPtr&); + OperationPtr getOperation(const std::string&) const; + const std::string id; - const ClassInfoPtr cls; + const ProxyInfoPtr base; + const ProxyInfoList interfaces; bool defined; + typedef std::map<std::string, OperationPtr> OperationMap; + OperationMap operations; }; typedef IceUtil::Handle<ProxyInfo> ProxyInfoPtr; @@ -519,6 +523,7 @@ public: ClassInfoPtr getClassInfoById(const std::string& TSRMLS_DC); ClassInfoPtr getClassInfoByName(const std::string& TSRMLS_DC); +ProxyInfoPtr getProxyInfo(const std::string& TSRMLS_DC); ExceptionInfoPtr getExceptionInfo(const std::string& TSRMLS_DC); bool isUnset(zval* TSRMLS_DC); @@ -550,6 +555,7 @@ private: zval* _object; ObjectMap* _map; ClassInfoPtr _info; + ClassInfoPtr _formal; #if ZTS TSRMLS_D; #endif diff --git a/php/src/php7/Communicator.cpp b/php/src/php7/Communicator.cpp index 18a080b1d66..b707cf962c6 100644 --- a/php/src/php7/Communicator.cpp +++ b/php/src/php7/Communicator.cpp @@ -21,7 +21,7 @@ #include <fstream> #ifdef getcwd -#undef getcwd +# undef getcwd #endif #include <IceUtil/FileUtil.h> @@ -360,7 +360,7 @@ ZEND_METHOD(Ice_Communicator, proxyToString) if(zv) { Ice::ObjectPrx prx; - ClassInfoPtr info; + ProxyInfoPtr info; if(!fetchProxy(zv, prx, info)) { RETURN_NULL(); @@ -426,7 +426,7 @@ ZEND_METHOD(Ice_Communicator, proxyToProperty) if(zv) { Ice::ObjectPrx prx; - ClassInfoPtr info; + ProxyInfoPtr info; if(!fetchProxy(zv, prx, info)) { RETURN_NULL(); @@ -670,7 +670,7 @@ ZEND_METHOD(Ice_Communicator, getDefaultRouter) Ice::RouterPrx router = _this->getCommunicator()->getDefaultRouter(); if(router) { - ClassInfoPtr info = getClassInfoById("::Ice::Router"); + ProxyInfoPtr info = getProxyInfo("::Ice::Router"); if(!info) { runtimeError("no definition for Ice::Router"); @@ -706,7 +706,7 @@ ZEND_METHOD(Ice_Communicator, setDefaultRouter) } Ice::ObjectPrx proxy; - ClassInfoPtr info; + ProxyInfoPtr info; if(zv && !fetchProxy(zv, proxy, info)) { RETURN_NULL(); @@ -748,7 +748,7 @@ ZEND_METHOD(Ice_Communicator, getDefaultLocator) Ice::LocatorPrx locator = _this->getCommunicator()->getDefaultLocator(); if(locator) { - ClassInfoPtr info = getClassInfoById("::Ice::Locator"); + ProxyInfoPtr info = getProxyInfo("::Ice::Locator"); if(!info) { runtimeError("no definition for Ice::Locator"); @@ -784,7 +784,7 @@ ZEND_METHOD(Ice_Communicator, setDefaultLocator) } Ice::ObjectPrx proxy; - ClassInfoPtr info; + ProxyInfoPtr info; if(zv && !fetchProxy(zv, proxy, info)) { RETURN_NULL(); @@ -1855,7 +1855,7 @@ IcePHP::FactoryWrapper::create(const string& id) // 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"); + cls = getClassInfoById("::Ice::UnknownSlicedValue"); } else { @@ -1940,7 +1940,6 @@ IcePHP::DefaultValueFactory::create(const string& id) // // Get the TSRM id for the current request. // - if(_delegate) { Ice::ValuePtr v = _delegate->create(id); @@ -1960,7 +1959,7 @@ IcePHP::DefaultValueFactory::create(const string& id) // 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"); + cls = getClassInfoById("::Ice::UnknownSlicedValue"); } else { @@ -1973,14 +1972,6 @@ IcePHP::DefaultValueFactory::create(const string& id) } // - // If the requested type is an abstract class, then we give up. - // - if(cls->isAbstract) - { - return 0; - } - - // // Instantiate the object. // zval obj; @@ -2068,7 +2059,6 @@ IcePHP::CommunicatorInfoI::addFactory(zval* factory, const string& id, bool isOb throwException(ex); return false; } - _factories.insert(FactoryMap::value_type(id, new FactoryWrapper(factory, isObjectFactory, this))); } @@ -2091,7 +2081,6 @@ IcePHP::CommunicatorInfoI::findFactory(const string& id) const return p->second; } } - return 0; } diff --git a/php/src/php7/Operation.cpp b/php/src/php7/Operation.cpp index e4afea75a8d..2e9c91b29f6 100644 --- a/php/src/php7/Operation.cpp +++ b/php/src/php7/Operation.cpp @@ -368,13 +368,13 @@ IcePHP::OperationI::convertParam(zval* p, int pos) ParamInfoPtr param = new ParamInfo; param->type = Wrapper<TypeInfoPtr>::value(zend_hash_index_find(arr, 0)); + param->optional = zend_hash_num_elements(arr) > 1; - assert(Z_TYPE_P(zend_hash_index_find(arr, 1)) == IS_TRUE || Z_TYPE_P(zend_hash_index_find(arr, 1)) == IS_FALSE); - param->optional = Z_TYPE_P(zend_hash_index_find(arr, 1)) == IS_TRUE; - - assert(Z_TYPE_P(zend_hash_index_find(arr, 2)) == IS_LONG); - param->tag = static_cast<int>(Z_LVAL_P(zend_hash_index_find(arr, 2))); - + if(param->optional) + { + assert(Z_TYPE_P(zend_hash_index_find(arr, 1)) == IS_LONG); + param->tag = static_cast<int>(Z_LVAL_P(zend_hash_index_find(arr, 1))); + } param->pos = pos; return param; @@ -840,11 +840,13 @@ ZEND_FUNCTION(IcePHP_defineOperation) } TypeInfoPtr type = Wrapper<TypeInfoPtr>::value(cls); - ClassInfoPtr c = ClassInfoPtr::dynamicCast(type); + ProxyInfoPtr c = ProxyInfoPtr::dynamicCast(type); assert(c); - OperationIPtr op = new OperationI(name, static_cast<Ice::OperationMode>(mode), - static_cast<Ice::OperationMode>(sendMode), static_cast<Ice::FormatType>(format), + OperationIPtr op = new OperationI(name, + static_cast<Ice::OperationMode>(mode), + static_cast<Ice::OperationMode>(sendMode), + static_cast<Ice::FormatType>(format), inParams, outParams, returnType, exceptions); c->addOperation(name, op); @@ -853,17 +855,17 @@ ZEND_FUNCTION(IcePHP_defineOperation) ZEND_FUNCTION(IcePHP_Operation_call) { Ice::ObjectPrx proxy; - ClassInfoPtr cls; + ProxyInfoPtr info; CommunicatorInfoPtr comm; #ifndef NDEBUG bool b = #endif - fetchProxy(getThis(), proxy, cls, comm); + fetchProxy(getThis(), proxy, info, comm); assert(b); assert(proxy); - assert(cls); + assert(info); - OperationPtr op = cls->getOperation(get_active_function_name()); + OperationPtr op = info->getOperation(get_active_function_name()); assert(op); // handleGetMethod should have already verified the operation's existence. OperationIPtr opi = OperationIPtr::dynamicCast(op); assert(opi); diff --git a/php/src/php7/Proxy.cpp b/php/src/php7/Proxy.cpp index 99a722d7e21..c3675f89f47 100644 --- a/php/src/php7/Proxy.cpp +++ b/php/src/php7/Proxy.cpp @@ -63,8 +63,6 @@ static union _zend_function* handleGetMethod(zend_object**, zend_string*, const static int handleCompare(zval*, zval*); } -static ClassInfoPtr lookupClass(const string&); - namespace IcePHP { @@ -75,15 +73,15 @@ class Proxy : public IceUtil::Shared { public: - Proxy(const Ice::ObjectPrx&, const ClassInfoPtr&, const CommunicatorInfoPtr&); + Proxy(const Ice::ObjectPrx&, const ProxyInfoPtr&, const CommunicatorInfoPtr&); ~Proxy(); bool clone(zval*, const Ice::ObjectPrx&); bool cloneUntyped(zval*, const Ice::ObjectPrx&); - static bool create(zval*, const Ice::ObjectPrx&, const ClassInfoPtr&, const CommunicatorInfoPtr&); + static bool create(zval*, const Ice::ObjectPrx&, const ProxyInfoPtr&, const CommunicatorInfoPtr&); Ice::ObjectPrx proxy; - ClassInfoPtr info; + ProxyInfoPtr info; CommunicatorInfoPtr communicator; zval* connection; zval* cachedConnection; @@ -750,7 +748,7 @@ ZEND_METHOD(Ice_ObjectPrx, ice_getRouter) Ice::RouterPrx router = _this->proxy->ice_getRouter(); if(router) { - ClassInfoPtr info = lookupClass("::Ice::Router"); + ProxyInfoPtr info = getProxyInfo("::Ice::Router"); if(!info) { RETURN_NULL(); @@ -788,7 +786,7 @@ ZEND_METHOD(Ice_ObjectPrx, ice_router) } Ice::ObjectPrx proxy; - ClassInfoPtr def; + ProxyInfoPtr def; if(zprx && !fetchProxy(zprx, proxy, def)) { RETURN_NULL(); @@ -834,7 +832,7 @@ ZEND_METHOD(Ice_ObjectPrx, ice_getLocator) Ice::LocatorPrx locator = _this->proxy->ice_getLocator(); if(locator) { - ClassInfoPtr info = lookupClass("::Ice::Locator"); + ProxyInfoPtr info = getProxyInfo("::Ice::Locator"); if(!info) { RETURN_NULL(); @@ -870,7 +868,7 @@ ZEND_METHOD(Ice_ObjectPrx, ice_locator) } Ice::ObjectPrx proxy; - ClassInfoPtr def; + ProxyInfoPtr def; if(zprx && !fetchProxy(zprx, proxy, def)) { RETURN_NULL(); @@ -1277,30 +1275,6 @@ ZEND_METHOD(Ice_ObjectPrx, ice_flushBatchRequests) } } -static ClassInfoPtr -lookupClass(const string& id) -{ - ClassInfoPtr info = getClassInfoById(id); - if(!info) - { - if(!id.empty() && id[id.size() - 1] == '*') - { - info = getClassInfoById(id.substr(0, id.size() - 1)); - } - } - - if(info && !info->defined) - { - runtimeError("%s is declared but not defined", id.c_str()); - } - else if(!info) - { - runtimeError("no definition found for class or interface %s", id.c_str()); - } - - return info; -} - static void do_cast(INTERNAL_FUNCTION_PARAMETERS, bool check) { @@ -1346,7 +1320,7 @@ do_cast(INTERNAL_FUNCTION_PARAMETERS, bool check) try { - ClassInfoPtr info = lookupClass(id); + ProxyInfoPtr info = getProxyInfo(id); if(!info) { RETURN_NULL(); @@ -1400,7 +1374,7 @@ ZEND_METHOD(Ice_ObjectPrx, ice_checkedCast) do_cast(INTERNAL_FUNCTION_PARAM_PASSTHRU, true); } -IcePHP::Proxy::Proxy(const Ice::ObjectPrx& p, const ClassInfoPtr& i, const CommunicatorInfoPtr& comm) : +IcePHP::Proxy::Proxy(const Ice::ObjectPrx& p, const ProxyInfoPtr& i, const CommunicatorInfoPtr& comm) : proxy(p), info(i), communicator(comm), connection(0), cachedConnection(0) { // @@ -1436,14 +1410,13 @@ IcePHP::Proxy::cloneUntyped(zval* zv, const Ice::ObjectPrx& p) } bool -IcePHP::Proxy::create(zval* zv, const Ice::ObjectPrx& p, const ClassInfoPtr& info, const CommunicatorInfoPtr& comm - ) +IcePHP::Proxy::create(zval* zv, const Ice::ObjectPrx& p, const ProxyInfoPtr& info, const CommunicatorInfoPtr& comm) { - ClassInfoPtr cls = info; - if(!cls) + ProxyInfoPtr prx = info; + if(!prx) { - cls = getClassInfoById("::Ice::Object"); - assert(cls); + prx = getProxyInfo("::Ice::Object"); + assert(prx); } if(object_init_ex(zv, proxyClassEntry) != SUCCESS) @@ -1453,7 +1426,7 @@ IcePHP::Proxy::create(zval* zv, const Ice::ObjectPrx& p, const ClassInfoPtr& inf } Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::extract(zv); - ProxyPtr proxy = new Proxy(p, cls, comm); + ProxyPtr proxy = new Proxy(p, prx, comm); assert(!obj->ptr); obj->ptr = new ProxyPtr(proxy); return true; @@ -1525,7 +1498,7 @@ handleGetMethod(zend_object **object, zend_string *name, const zval *key ) assert(obj->ptr); ProxyPtr _this = *obj->ptr; - ClassInfoPtr info = _this->info; + ProxyInfoPtr info = _this->info; assert(info); OperationPtr op = info->getOperation(name->val); @@ -1680,21 +1653,21 @@ IcePHP::createProxy(zval* zv, const Ice::ObjectPrx& p, const CommunicatorInfoPtr } bool -IcePHP::createProxy(zval* zv, const Ice::ObjectPrx& p, const ClassInfoPtr& info, const CommunicatorInfoPtr& comm +IcePHP::createProxy(zval* zv, const Ice::ObjectPrx& p, const ProxyInfoPtr& info, const CommunicatorInfoPtr& comm ) { return Proxy::create(zv, p, info, comm); } bool -IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ClassInfoPtr& cls) +IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ProxyInfoPtr& info) { CommunicatorInfoPtr comm; - return fetchProxy(zv, prx, cls, comm); + return fetchProxy(zv, prx, info, comm); } bool -IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ClassInfoPtr& cls, CommunicatorInfoPtr& comm) +IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ProxyInfoPtr& info, CommunicatorInfoPtr& comm) { if(!ZVAL_IS_NULL(zv)) { @@ -1711,7 +1684,7 @@ IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ClassInfoPtr& cls, Communicato } assert(obj->ptr); prx = (*obj->ptr)->proxy; - cls = (*obj->ptr)->info; + info = (*obj->ptr)->info; comm = (*obj->ptr)->communicator; } return true; diff --git a/php/src/php7/Proxy.h b/php/src/php7/Proxy.h index 771e999ea88..a2b02bdc3b4 100644 --- a/php/src/php7/Proxy.h +++ b/php/src/php7/Proxy.h @@ -20,9 +20,9 @@ namespace IcePHP bool proxyInit(void); bool createProxy(zval*, const Ice::ObjectPrx&, const CommunicatorInfoPtr&); -bool createProxy(zval*, const Ice::ObjectPrx&, const ClassInfoPtr&, const CommunicatorInfoPtr&); -bool fetchProxy(zval*, Ice::ObjectPrx&, ClassInfoPtr&); -bool fetchProxy(zval*, Ice::ObjectPrx&, ClassInfoPtr&, CommunicatorInfoPtr&); +bool createProxy(zval*, const Ice::ObjectPrx&, const ProxyInfoPtr&, const CommunicatorInfoPtr&); +bool fetchProxy(zval*, Ice::ObjectPrx&, ProxyInfoPtr&); +bool fetchProxy(zval*, Ice::ObjectPrx&, ProxyInfoPtr&, CommunicatorInfoPtr&); // // Class entry. diff --git a/php/src/php7/Types.cpp b/php/src/php7/Types.cpp index ce454528f80..586e438ab21 100644 --- a/php/src/php7/Types.cpp +++ b/php/src/php7/Types.cpp @@ -75,8 +75,8 @@ addProxyInfo(const ProxyInfoPtr& p) // // getProxyInfo() // -static IcePHP::ProxyInfoPtr -getProxyInfo(const string& id) +IcePHP::ProxyInfoPtr +IcePHP::getProxyInfo(const string& id) { if(ICE_G(proxyInfoMap)) { @@ -2386,17 +2386,17 @@ IcePHP::DictionaryInfo::destroy() // ClassInfo implementation. // IcePHP::ClassInfo::ClassInfo(const string& ident) : - id(ident), compactId(-1), isAbstract(false), preserve(false), zce(0), defined(false) + id(ident), compactId(-1), preserve(false), interface(false), zce(0), defined(false) { } void -IcePHP::ClassInfo::define(const string& n, Ice::Int compact, bool isAbs, bool pres, zval* b, zval* i, zval* m) +IcePHP::ClassInfo::define(const string& n, Ice::Int compact, bool pres, bool intf, zval* b, zval* m) { const_cast<string&>(name) = n; const_cast<Ice::Int&>(compactId) = static_cast<Ice::Int>(compact); - const_cast<bool&>(isAbstract) = isAbs; const_cast<bool&>(preserve) = pres; + const_cast<bool&>(interface) = intf; if(b) { @@ -2405,21 +2405,6 @@ IcePHP::ClassInfo::define(const string& n, Ice::Int compact, bool isAbs, bool pr assert(base); } - if(i) - { - HashTable* interfacesArray = Z_ARRVAL_P(i); - zval* interfaceType; - - ZEND_HASH_FOREACH_VAL(interfacesArray, interfaceType) - { - TypeInfoPtr t = Wrapper<TypeInfoPtr>::value(interfaceType); - ClassInfoPtr c = ClassInfoPtr::dynamicCast(t); - assert(c); - const_cast<ClassInfoList&>(interfaces).push_back(c); - } - ZEND_HASH_FOREACH_END(); - } - if(m) { convertDataMembers(m, const_cast<DataMemberList&>(members), const_cast<DataMemberList&>(optionalMembers), @@ -2427,8 +2412,13 @@ IcePHP::ClassInfo::define(const string& n, Ice::Int compact, bool isAbs, bool pr } const_cast<bool&>(defined) = true; - const_cast<zend_class_entry*&>(zce) = nameToClass(name); - assert(zce || id == "::Ice::LocalObject"); // LocalObject does not have a native PHP equivalent. +#ifdef ICEPHP_USE_NAMESPACES + const string valueClass = "Ice\\Value"; +#else + const string valueClass = "Ice_Value"; +#endif + const_cast<zend_class_entry*&>(zce) = nameToClass(interface ? valueClass : name); + assert(zce || id == "::Ice::LocalObject" || interface); // LocalObject and interfaces does not have a native PHP equivalent. } string @@ -2586,7 +2576,6 @@ void IcePHP::ClassInfo::destroy() { const_cast<ClassInfoPtr&>(base) = 0; - const_cast<ClassInfoList&>(interfaces).clear(); if(!members.empty()) { DataMemberList ml = members; @@ -2660,49 +2649,7 @@ IcePHP::ClassInfo::isA(const string& typeId) const return true; } - if(base && base->isA(typeId)) - { - return true; - } - - for(ClassInfoList::const_iterator p = interfaces.begin(); p != interfaces.end(); ++p) - { - if((*p)->isA(typeId)) - { - return true; - } - } - - return false; -} - -void -IcePHP::ClassInfo::addOperation(const string& name, const OperationPtr& op) -{ - operations.insert(OperationMap::value_type(Slice::PHP::fixIdent(name), op)); -} - -IcePHP::OperationPtr -IcePHP::ClassInfo::getOperation(const string& name) const -{ - OperationPtr op; - OperationMap::const_iterator p = operations.find(name); - if(p != operations.end()) - { - op = p->second; - } - if(!op && base) - { - op = base->getOperation(name); - } - if(!op && !interfaces.empty()) - { - for(ClassInfoList::const_iterator q = interfaces.begin(); q != interfaces.end() && !op; ++q) - { - op = (*q)->getOperation(name); - } - } - return op; + return base && base->isA(typeId); } // @@ -2714,9 +2661,30 @@ IcePHP::ProxyInfo::ProxyInfo(const string& ident) : } void -IcePHP::ProxyInfo::define(const ClassInfoPtr& c) +IcePHP::ProxyInfo::define(zval* b, zval* i) { - const_cast<ClassInfoPtr&>(cls) = c; + if(b) + { + TypeInfoPtr p = Wrapper<TypeInfoPtr>::value(b); + const_cast<ProxyInfoPtr&>(base) = ProxyInfoPtr::dynamicCast(p); + assert(base); + } + + if(i) + { + HashTable* interfacesArray = Z_ARRVAL_P(i); + zval* interfaceType; + + ZEND_HASH_FOREACH_VAL(interfacesArray, interfaceType) + { + TypeInfoPtr t = Wrapper<TypeInfoPtr>::value(interfaceType); + ProxyInfoPtr c = ProxyInfoPtr::dynamicCast(t); + assert(c); + const_cast<ProxyInfoList&>(interfaces).push_back(c); + } + ZEND_HASH_FOREACH_END(); + } + const_cast<bool&>(defined) = true; } @@ -2780,7 +2748,7 @@ IcePHP::ProxyInfo::marshal(zval* zv, Ice::OutputStream* os, ObjectMap*, bool opt { assert(Z_TYPE_P(zv) == IS_OBJECT && Z_OBJCE_P(zv) == proxyClassEntry); // validate() should have caught this. Ice::ObjectPrx proxy; - ClassInfoPtr info; + ProxyInfoPtr info; if(!fetchProxy(zv, proxy, info)) { throw AbortMarshaling(); @@ -2821,13 +2789,13 @@ IcePHP::ProxyInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& c return; } - if(!cls->defined) + if(!defined) { - runtimeError("class or interface %s is declared but not defined", id.c_str()); + runtimeError("proxy %s is declared but not defined" TSRMLS_CC, id.c_str()); throw AbortMarshaling(); } - if(!createProxy(&zv, proxy, cls, comm)) + if(!createProxy(&zv, proxy, this, comm)) { throw AbortMarshaling(); } @@ -2850,8 +2818,8 @@ IcePHP::ProxyInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHist else { Ice::ObjectPrx proxy; - ClassInfoPtr cls; - if(!fetchProxy(zv, proxy, cls)) + ProxyInfoPtr info; + if(!fetchProxy(zv, proxy, info)) { return; } @@ -2862,27 +2830,83 @@ IcePHP::ProxyInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHist void IcePHP::ProxyInfo::destroy() { - const_cast<ClassInfoPtr&>(cls) = 0; + const_cast<ProxyInfoPtr&>(base) = 0; + const_cast<ProxyInfoList&>(interfaces).clear(); +} + +bool +IcePHP::ProxyInfo::isA(const string& typeId) const +{ + if(id == typeId) + { + return true; + } + + if(base && base->isA(typeId)) + { + return true; + } + + for(ProxyInfoList::const_iterator p = interfaces.begin(); p != interfaces.end(); ++p) + { + if((*p)->isA(typeId)) + { + return true; + } + } + + return false; +} + +void +IcePHP::ProxyInfo::addOperation(const string& name, const OperationPtr& op) +{ + operations.insert(OperationMap::value_type(Slice::PHP::fixIdent(name), op)); +} + +IcePHP::OperationPtr +IcePHP::ProxyInfo::getOperation(const string& name) const +{ + OperationPtr op; + OperationMap::const_iterator p = operations.find(name); + if(p != operations.end()) + { + op = p->second; + } + if(!op && base) + { + op = base->getOperation(name); + } + if(!op && !interfaces.empty()) + { + for(ProxyInfoList::const_iterator q = interfaces.begin(); q != interfaces.end() && !op; ++q) + { + op = (*q)->getOperation(name); + } + } + return op; } // // ObjectWriter implementation. // IcePHP::ObjectWriter::ObjectWriter(zval* object, ObjectMap* objectMap, const ClassInfoPtr& formal) : - _map(objectMap) + _map(objectMap), _formal(formal) { // Copy zval and increase ref count ZVAL_COPY(&_object, object); - - // - // We need to determine the most-derived Slice type supported by this object. - // This is typically a Slice class, but it can also be an interface. - // - // 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 ? const_cast<zend_class_entry*>(formal->zce) : 0); - assert(_info); + if(!_formal || !_formal->interface) + { + // + // For non interface types we need to determine the most-derived Slice type supported by + // this object. This is typically a Slice class, but it can also be an interface. + // + // 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 ? const_cast<zend_class_entry*>(formal->zce) : 0); + assert(_info); + } } IcePHP::ObjectWriter::~ObjectWriter() @@ -2908,7 +2932,7 @@ IcePHP::ObjectWriter::_iceWrite(Ice::OutputStream* os) const { Ice::SlicedDataPtr slicedData; - if(_info->preserve) + if(_info && _info->preserve) { // // Retrieve the SlicedData object that we stored as a hidden member of the PHP object. @@ -2917,25 +2941,66 @@ IcePHP::ObjectWriter::_iceWrite(Ice::OutputStream* os) const } os->startValue(slicedData); + + if(_formal && _formal->interface) + { + // + // For an interface by value we just marshal the Ice type id + // of the object in its own slice. + // + zval ret; + ZVAL_UNDEF(&ret); + + zend_try + { + assert(Z_TYPE(_object) == IS_OBJECT); + zend_call_method(const_cast<zval*>(&_object), 0, 0, const_cast<char*>("ice_id"), sizeof("ice_id") - 1, &ret, 0, 0, 0); + } + zend_catch + { + // ret; + } + zend_end_try(); + + // + // Bail out if an exception has already been thrown. + // + if(Z_ISUNDEF(ret) || EG(exception)) + { + throw AbortMarshaling(); + } - if(_info->id != "::Ice::UnknownSlicedObject") + AutoDestroy destroy(&ret); + + if(Z_TYPE(ret) != IS_STRING) + { + throw AbortMarshaling(); + } + + string id(Z_STRVAL(ret), Z_STRLEN(ret)); + os->startSlice(id, -1, true); + os->endSlice(); + } + else { - ClassInfoPtr info = _info; - while(info && info->id != Ice::Object::ice_staticId()) + if(_info->id != "::Ice::UnknownSlicedValue") { - 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, info->compactId, lastSlice); + ClassInfoPtr info = _info; + while(info && info->id != Ice::Object::ice_staticId()) + { + 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, info->compactId, lastSlice); - writeMembers(os, info->members); - writeMembers(os, info->optionalMembers); // The optional members have already been sorted by tag. + writeMembers(os, info->members); + writeMembers(os, info->optionalMembers); // The optional members have already been sorted by tag. - os->endSlice(); + os->endSlice(); - info = info->base; + info = info->base; + } } } - os->endValue(); } @@ -3022,8 +3087,7 @@ void IcePHP::ObjectReader::_iceRead(Ice::InputStream* is) { is->startValue(); - - const bool unknown = _info->id == "::Ice::UnknownSlicedObject"; + const bool unknown = _info->id == "::Ice::UnknownSlicedValue"; // // Unmarshal the slices of a user-defined class. @@ -3144,7 +3208,7 @@ IcePHP::ReadObjectCallback::invoke(const Ice::ObjectPtr& p) // Verify that the unmarshaled object is compatible with the formal type. // zval* obj = reader->getObject(); - if(!reader->getInfo()->isA(_info->id)) + if(!_info->interface && !reader->getInfo()->isA(_info->id)) { Ice::UnexpectedObjectException ex(__FILE__, __LINE__); ex.reason = "unmarshaled object is not an instance of " + _info->id; @@ -3573,25 +3637,23 @@ ZEND_FUNCTION(IcePHP_declareProxy) ZEND_FUNCTION(IcePHP_defineProxy) { - zval* cls; + char* id; + size_t idLen; + zval* base; + zval* interfaces; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("o"), &cls) == FAILURE) + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("so!a!"), &id, &idLen, &base, &interfaces) == FAILURE) { return; } - TypeInfoPtr p = Wrapper<TypeInfoPtr>::value(cls); - ClassInfoPtr c = ClassInfoPtr::dynamicCast(p); - assert(c); - - ProxyInfoPtr type = getProxyInfo(c->id); + ProxyInfoPtr type = getProxyInfo(id); if(!type) { - type = new ProxyInfo(c->id); + type = new ProxyInfo(id); addProxyInfo(type); } - - type->define(c); + type->define(base, interfaces); if(!createTypeInfo(return_value, type)) { @@ -3629,14 +3691,13 @@ ZEND_FUNCTION(IcePHP_defineClass) char* name; size_t nameLen; long compactId; - zend_bool isAbstract; zend_bool preserve; + zend_bool interface; zval* base; - zval* interfaces; zval* members; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("sslbbo!a!a!"), &id, &idLen, &name, &nameLen, - &compactId, &isAbstract, &preserve, &base, &interfaces, &members) == FAILURE) + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("sslbbo!a!"), &id, &idLen, &name, &nameLen, + &compactId, &preserve, &interface, &base, &members) == FAILURE) { return; } @@ -3648,17 +3709,23 @@ ZEND_FUNCTION(IcePHP_defineClass) addClassInfoById(type); } - type->define(name, static_cast<Ice::Int>(compactId), isAbstract ? true : false, preserve ? true : false, base, - interfaces, members); - addClassInfoByName(type); + type->define(name, static_cast<Ice::Int>(compactId), preserve ? true : false, interface ? true : false, base, members); + + if(!interface) + { + addClassInfoByName(type); + } - CompactIdMap* m = reinterpret_cast<CompactIdMap*>(ICE_G(compactIdToClassInfoMap)); - if(!m) + if(type->compactId != -1) { - m = new CompactIdMap; - ICE_G(compactIdToClassInfoMap) = m; + CompactIdMap* m = reinterpret_cast<CompactIdMap*>(ICE_G(compactIdToClassInfoMap)); + if(!m) + { + m = new CompactIdMap; + ICE_G(compactIdToClassInfoMap) = m; + } + m->insert(CompactIdMap::value_type(type->compactId, type)); } - m->insert(CompactIdMap::value_type(type->compactId, type)); if(!createTypeInfo(return_value, type)) { diff --git a/php/src/php7/Types.h b/php/src/php7/Types.h index 111c5f77c76..971f7837cf6 100644 --- a/php/src/php7/Types.h +++ b/php/src/php7/Types.h @@ -414,7 +414,7 @@ public: ClassInfo(const std::string&); - void define(const std::string&, Ice::Int, bool, bool, zval*, zval*, zval*); + void define(const std::string&, Ice::Int, bool, bool, zval*, zval*); virtual std::string getId() const; @@ -438,35 +438,33 @@ public: bool isA(const std::string&) const; - void addOperation(const std::string&, const OperationPtr&); - OperationPtr getOperation(const std::string&) const; - const std::string id; const std::string name; // PHP class name const Ice::Int compactId; - const bool isAbstract; const bool preserve; + const bool interface; const ClassInfoPtr base; - const ClassInfoList interfaces; const DataMemberList members; const DataMemberList optionalMembers; const zend_class_entry* zce; bool defined; - - typedef std::map<std::string, OperationPtr> OperationMap; - OperationMap operations; }; // // Proxy information. // + +class ProxyInfo; +typedef IceUtil::Handle<ProxyInfo> ProxyInfoPtr; +typedef std::vector<ProxyInfoPtr> ProxyInfoList; + class ProxyInfo : public TypeInfo { public: ProxyInfo(const std::string&); - void define(const ClassInfoPtr&); + void define(zval*, zval*); virtual std::string getId() const; @@ -483,12 +481,18 @@ public: virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory*); virtual void destroy(); + bool isA(const std::string&) const; + + void addOperation(const std::string&, const OperationPtr&); + OperationPtr getOperation(const std::string&) const; const std::string id; - const ClassInfoPtr cls; + const ProxyInfoPtr base; + const ProxyInfoList interfaces; bool defined; + typedef std::map<std::string, OperationPtr> OperationMap; + OperationMap operations; }; -typedef IceUtil::Handle<ProxyInfo> ProxyInfoPtr; // // Exception information. @@ -516,6 +520,7 @@ public: ClassInfoPtr getClassInfoById(const std::string&); ClassInfoPtr getClassInfoByName(const std::string&); +ProxyInfoPtr getProxyInfo(const std::string&); ExceptionInfoPtr getExceptionInfo(const std::string&); bool isUnset(zval*); @@ -547,6 +552,7 @@ private: zval _object; ObjectMap* _map; ClassInfoPtr _info; + ClassInfoPtr _formal; }; // |