diff options
Diffstat (limited to 'php/src/IcePHP/Util.cpp')
-rw-r--r-- | php/src/IcePHP/Util.cpp | 874 |
1 files changed, 455 insertions, 419 deletions
diff --git a/php/src/IcePHP/Util.cpp b/php/src/IcePHP/Util.cpp index 693d8a5385c..da6e282e4ff 100644 --- a/php/src/IcePHP/Util.cpp +++ b/php/src/IcePHP/Util.cpp @@ -8,86 +8,97 @@ // ********************************************************************** #include <Util.h> -#include <IceUtil/DisableWarnings.h> +#include <IceUtil/UUID.h> +#include <Slice/PHPUtil.h> #include <algorithm> #include <ctype.h> using namespace std; using namespace IcePHP; +using namespace Slice::PHP; -static string -lookupKwd(const string& name) +#ifdef _WIN32 +extern "C" +#endif +static void +dtor_wrapper(void* p) { - string lower = lowerCase(name); // PHP is case insensitive. + zval_ptr_dtor(static_cast<zval**>(p)); +} - // - // Keyword list. *Must* be kept in alphabetical order. - // - static const string keywordList[] = - { - "abstract", "and", "array", "as", "break", "case", "catch", "class", "clone", "const", "continue", "declare", - "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", - "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "if", - "implements", "include", "include_once", "interface", "isset", "list", "new", "or", "print", "private", - "protected", "public", "require", "require_once", "return", "static", "switch", "this", "throw", "try", - "unset", "use", "var", "while", "xor" - }; - bool found = binary_search(&keywordList[0], - &keywordList[sizeof(keywordList) / sizeof(*keywordList)], - lower); - return found ? "_" + name : name; +void* +IcePHP::createWrapper(zend_class_entry* ce, size_t sz TSRMLS_DC) +{ + zend_object* obj; + zval* tmp; + + obj = static_cast<zend_object*>(emalloc(sz)); + obj->ce = ce; + obj->guards = 0; + + obj->properties = static_cast<HashTable*>(emalloc(sizeof(HashTable))); + zend_hash_init(obj->properties, 0, 0, dtor_wrapper, 0); + zend_hash_copy(obj->properties, &ce->default_properties, (copy_ctor_func_t)zval_add_ref, &tmp, sizeof(zval*)); + + return obj; } -// -// Split a scoped name into its components and return the components as a list of (unscoped) identifiers. -// -static vector<string> -splitScopedName(const string& scoped) +void* +IcePHP::extractWrapper(zval* zv TSRMLS_DC) { - assert(scoped[0] == ':'); - vector<string> ids; - string::size_type next = 0; - string::size_type pos; - while((pos = scoped.find("::", next)) != string::npos) - { - pos += 2; - if(pos != scoped.size()) - { - string::size_type endpos = scoped.find("::", pos); - if(endpos != string::npos) - { - ids.push_back(scoped.substr(pos, endpos - pos)); - } - } - next = pos; - } - if(next != scoped.size()) + if(!zv) { - ids.push_back(scoped.substr(next)); + runtimeError("method %s() must be invoked on an object" TSRMLS_CC, get_active_function_name(TSRMLS_C)); + return 0; } - else + + zend_object* obj = static_cast<zend_object*>(zend_object_store_get_object(zv TSRMLS_CC)); + if(!obj) { - ids.push_back(""); + runtimeError("no object found in %s()" TSRMLS_CC, get_active_function_name(TSRMLS_C)); + return 0; } - return ids; + return obj; +} + +zend_class_entry* +IcePHP::idToClass(const string& id TSRMLS_DC) +{ +#ifdef ICEPHP_USE_NAMESPACES + string cls = scopedToName(id, true); +#else + string cls = scopedToName(id, false); +#endif + + return nameToClass(cls TSRMLS_CC); +} + +zend_class_entry* +IcePHP::nameToClass(const string& name TSRMLS_DC) +{ + zend_class_entry** result; + if(zend_lookup_class(STRCAST(name.c_str()), name.length(), &result TSRMLS_CC) == FAILURE) + { + return 0; + } + return *result; } bool IcePHP::createIdentity(zval* zv, const Ice::Identity& id TSRMLS_DC) { - zend_class_entry* cls = findClass("Ice_Identity" TSRMLS_CC); + zend_class_entry* cls = idToClass("::Ice::Identity" TSRMLS_CC); assert(cls); if(object_init_ex(zv, cls) != SUCCESS) { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to initialize Ice::Identity"); + runtimeError("unable to initialize Ice::Identity" TSRMLS_CC); return false; } - zend_update_property_string(cls, zv, "name", sizeof("name") - 1, const_cast<char*>(id.name.c_str()) TSRMLS_CC); - zend_update_property_string(cls, zv, "category", sizeof("category") - 1, - const_cast<char*>(id.category.c_str()) TSRMLS_CC); + zend_update_property_string(cls, zv, "name", sizeof("name") - 1, STRCAST(id.name.c_str()) TSRMLS_CC); + zend_update_property_string(cls, zv, "category", sizeof("category") - 1, STRCAST(id.category.c_str()) TSRMLS_CC); return true; } @@ -97,17 +108,17 @@ IcePHP::extractIdentity(zval* zv, Ice::Identity& id TSRMLS_DC) { if(Z_TYPE_P(zv) != IS_OBJECT) { - php_error_docref(0 TSRMLS_CC, E_ERROR, "value does not contain an object"); + invalidArgument("value does not contain an object" TSRMLS_CC); return false; } - zend_class_entry* cls = findClass("Ice_Identity" TSRMLS_CC); + zend_class_entry* cls = idToClass("::Ice::Identity" TSRMLS_CC); assert(cls); zend_class_entry* ce = Z_OBJCE_P(zv); if(ce != cls) { - php_error_docref(0 TSRMLS_CC, E_ERROR, "expected an identity but received %s", ce->name); + invalidArgument("expected an identity but received %s" TSRMLS_CC, ce->name); return false; } @@ -118,7 +129,7 @@ IcePHP::extractIdentity(zval* zv, Ice::Identity& id TSRMLS_DC) void* nameData; if(zend_hash_find(Z_OBJPROP_P(zv), "name", sizeof("name"), &nameData) == FAILURE) { - php_error_docref(0 TSRMLS_CC, E_ERROR, "identity value does not contain member `name'"); + invalidArgument("identity value does not contain member `name'" TSRMLS_CC); return false; } zend_hash_find(Z_OBJPROP_P(zv), "category", sizeof("category"), &categoryData); @@ -128,16 +139,14 @@ IcePHP::extractIdentity(zval* zv, Ice::Identity& id TSRMLS_DC) if(Z_TYPE_PP(nameVal) != IS_STRING) { string s = zendTypeToString(Z_TYPE_PP(nameVal)); - php_error_docref(0 TSRMLS_CC, E_ERROR, "expected a string value for identity member `name' but received %s", - s.c_str()); + invalidArgument("expected a string value for identity member `name' but received %s" TSRMLS_CC, s.c_str()); return false; } if(categoryVal && Z_TYPE_PP(categoryVal) != IS_STRING && Z_TYPE_PP(categoryVal) != IS_NULL) { string s = zendTypeToString(Z_TYPE_PP(categoryVal)); - php_error_docref(0 TSRMLS_CC, E_ERROR, - "expected a string value for identity member `category' but received %s", s.c_str()); + invalidArgument("expected a string value for identity member `category' but received %s" TSRMLS_CC, s.c_str()); return false; } @@ -155,28 +164,28 @@ IcePHP::extractIdentity(zval* zv, Ice::Identity& id TSRMLS_DC) } bool -IcePHP::createContext(zval* zv, const Ice::Context& ctx TSRMLS_DC) +IcePHP::createStringMap(zval* zv, const map<string, string>& ctx TSRMLS_DC) { array_init(zv); - for(Ice::Context::const_iterator p = ctx.begin(); p != ctx.end(); ++p) + for(map<string, string>::const_iterator p = ctx.begin(); p != ctx.end(); ++p) { - zval* val; - MAKE_STD_ZVAL(val); - ZVAL_STRINGL(val, const_cast<char*>(p->second.c_str()), p->second.length(), 1); - add_assoc_zval_ex(zv, const_cast<char*>(p->first.c_str()), p->first.length() + 1, val); + if(add_assoc_stringl_ex(zv, const_cast<char*>(p->first.c_str()), p->first.length() + 1, + const_cast<char*>(p->second.c_str()), p->second.length(), 1) == FAILURE) + { + return false; + } } return true; } bool -IcePHP::extractContext(zval* zv, Ice::Context& ctx TSRMLS_DC) +IcePHP::extractStringMap(zval* zv, map<string, string>& ctx TSRMLS_DC) { if(Z_TYPE_P(zv) != IS_ARRAY) { string s = zendTypeToString(Z_TYPE_P(zv)); - php_error_docref(0 TSRMLS_CC, E_ERROR, "expected an array for the context argument but received %s", - s.c_str()); + invalidArgument("expected an associative array but received %s" TSRMLS_CC, s.c_str()); return false; } @@ -202,13 +211,13 @@ IcePHP::extractContext(zval* zv, Ice::Context& ctx TSRMLS_DC) // if(keyType != HASH_KEY_IS_STRING) { - php_error_docref(0 TSRMLS_CC, E_ERROR, "context key must be a string"); + invalidArgument("array key must be a string" TSRMLS_CC); return false; } if(Z_TYPE_PP(val) != IS_STRING) { - php_error_docref(0 TSRMLS_CC, E_ERROR, "context value must be a string"); + invalidArgument("array value must be a string" TSRMLS_CC); return false; } @@ -220,384 +229,288 @@ IcePHP::extractContext(zval* zv, Ice::Context& ctx TSRMLS_DC) return true; } -#ifdef _WIN32 -extern "C" -#endif -static void -dtor_wrapper(void* p) -{ - zval_ptr_dtor(static_cast<zval**>(p)); -} - -ice_object* -IcePHP::newObject(zend_class_entry* ce TSRMLS_DC) +bool +IcePHP::createStringArray(zval* zv, const Ice::StringSeq& seq TSRMLS_DC) { - ice_object* obj; - zval* tmp; - - obj = static_cast<ice_object*>(emalloc(sizeof(ice_object))); - obj->zobj.ce = ce; - obj->zobj.guards = 0; - obj->ptr = 0; - - obj->zobj.properties = static_cast<HashTable*>(emalloc(sizeof(HashTable))); - zend_hash_init(obj->zobj.properties, 0, 0, dtor_wrapper, 0); - zend_hash_copy(obj->zobj.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, &tmp, - sizeof(zval*)); + array_init(zv); + for(Ice::StringSeq::const_iterator p = seq.begin(); p != seq.end(); ++p) + { + if(add_next_index_stringl(zv, STRCAST(p->c_str()), p->length(), 1) == FAILURE) + { + return false; + } + } - return obj; + return true; } -ice_object* -IcePHP::getObject(zval* zv TSRMLS_DC) +bool +IcePHP::extractStringArray(zval* zv, Ice::StringSeq& seq TSRMLS_DC) { - if(!zv) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "method %s() must be invoked on an object", - get_active_function_name(TSRMLS_C)); - return 0; - } - - ice_object* obj = static_cast<ice_object*>(zend_object_store_get_object(zv TSRMLS_CC)); - if(!obj) + if(Z_TYPE_P(zv) != IS_ARRAY) { - php_error_docref(0 TSRMLS_CC, E_ERROR, "no object found in %s()", get_active_function_name(TSRMLS_C)); - return 0; + string s = zendTypeToString(Z_TYPE_P(zv)); + invalidArgument("expected an array of strings but received %s" TSRMLS_CC, s.c_str()); + return false; } - return obj; -} + HashTable* arr = Z_ARRVAL_P(zv); + void* data; + HashPosition pos; -void -IcePHP::throwException(const IceUtil::Exception& ex TSRMLS_DC) -{ - try + zend_hash_internal_pointer_reset_ex(arr, &pos); + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { - try + zval** val = reinterpret_cast<zval**>(data); + + if(Z_TYPE_PP(val) != IS_STRING) { - ex.ice_throw(); + invalidArgument("array element must be a string" TSRMLS_CC); + return false; } - catch(const Ice::TwowayOnlyException& e) - { - string name = e.ice_name(); - zend_class_entry* cls = findClassScoped(name TSRMLS_CC); - if(!cls) - { - throw; - } - zval* zex; - MAKE_STD_ZVAL(zex); - if(object_init_ex(zex, cls) != SUCCESS) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to create exception %s", cls->name); - return; - } + string s(Z_STRVAL_PP(val), Z_STRLEN_PP(val)); + seq.push_back(s); - // - // Set the unknown member. - // - zend_update_property_string(cls, zex, "operation", sizeof("operation") - 1, - const_cast<char*>(e.operation.c_str()) TSRMLS_CC); + zend_hash_move_forward_ex(arr, &pos); + } - // - // Throw the exception. - // - zend_throw_exception_object(zex TSRMLS_CC); - } - catch(const Ice::UnknownException& e) - { - string name = e.ice_name(); - zend_class_entry* cls = findClassScoped(name TSRMLS_CC); - if(!cls) - { - throw; - } + return true; +} - zval* zex; - MAKE_STD_ZVAL(zex); - if(object_init_ex(zex, cls) != SUCCESS) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to create exception %s", cls->name); - return; - } +static void +setStringMember(zval* obj, const string& name, const string& val TSRMLS_DC) +{ + zend_class_entry* cls = Z_OBJCE_P(obj); + assert(cls); + zend_update_property_stringl(cls, obj, const_cast<char*>(name.c_str()), static_cast<int>(name.size()), + const_cast<char*>(val.c_str()), static_cast<int>(val.size()) TSRMLS_CC); +} - // - // Set the unknown member. - // - zend_update_property_string(cls, zex, "unknown", sizeof("unknown") - 1, - const_cast<char*>(e.unknown.c_str()) TSRMLS_CC); +static bool +convertLocalException(const Ice::LocalException& ex, zval* zex TSRMLS_DC) +{ + zend_class_entry* cls = Z_OBJCE_P(zex); + assert(cls); - // - // Throw the exception. - // - zend_throw_exception_object(zex TSRMLS_CC); - } - catch(const Ice::RequestFailedException& e) + // + // Transfer data members from Ice exception to PHP object. + // + try + { + ex.ice_throw(); + } + catch(const Ice::InitializationException& e) + { + setStringMember(zex, "reason", e.reason TSRMLS_CC); + } + catch(const Ice::PluginInitializationException& e) + { + setStringMember(zex, "reason", e.reason TSRMLS_CC); + } + catch(const Ice::AlreadyRegisteredException& e) + { + setStringMember(zex, "kindOfObject", e.kindOfObject TSRMLS_CC); + setStringMember(zex, "id", e.id TSRMLS_CC); + } + catch(const Ice::NotRegisteredException& e) + { + setStringMember(zex, "kindOfObject", e.kindOfObject TSRMLS_CC); + setStringMember(zex, "id", e.id TSRMLS_CC); + } + catch(const Ice::TwowayOnlyException& e) + { + setStringMember(zex, "operation", e.operation TSRMLS_CC); + } + catch(const Ice::UnknownException& e) + { + setStringMember(zex, "unknown", e.unknown TSRMLS_CC); + } + catch(const Ice::ObjectAdapterDeactivatedException& e) + { + setStringMember(zex, "name", e.name TSRMLS_CC); + } + catch(const Ice::ObjectAdapterIdInUseException& e) + { + setStringMember(zex, "id", e.id TSRMLS_CC); + } + catch(const Ice::NoEndpointException& e) + { + setStringMember(zex, "proxy", e.proxy TSRMLS_CC); + } + catch(const Ice::EndpointParseException& e) + { + setStringMember(zex, "str", e.str TSRMLS_CC); + } + catch(const Ice::IdentityParseException& e) + { + setStringMember(zex, "str", e.str TSRMLS_CC); + } + catch(const Ice::ProxyParseException& e) + { + setStringMember(zex, "str", e.str TSRMLS_CC); + } + catch(const Ice::IllegalIdentityException& e) + { + zval* id; + MAKE_STD_ZVAL(id); + if(!createIdentity(id, e.id TSRMLS_CC)) { - string name = e.ice_name(); - zend_class_entry* cls = findClassScoped(name TSRMLS_CC); - if(!cls) - { - throw; - } - - zval* zex; - MAKE_STD_ZVAL(zex); - if(object_init_ex(zex, cls) != SUCCESS) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to create exception %s", cls->name); - return; - } - - // - // Set the id member. - // - zval* id; - MAKE_STD_ZVAL(id); - if(!createIdentity(id, e.id TSRMLS_CC)) - { - return; - } - zend_update_property(cls, zex, "id", sizeof("id") - 1, id TSRMLS_CC); - - // - // Set the facet member. - // - zval* facet; - MAKE_STD_ZVAL(facet); - ZVAL_STRINGL(facet, const_cast<char*>(e.facet.c_str()), e.facet.length(), 1); - zend_update_property(cls, zex, "facet", sizeof("facet") - 1, facet TSRMLS_CC); - - // - // Set the operation member. - // - zend_update_property_string(cls, zex, "operation", sizeof("operation") - 1, - const_cast<char*>(e.operation.c_str()) TSRMLS_CC); - - // - // Throw the exception. - // - zend_throw_exception_object(zex TSRMLS_CC); + zval_ptr_dtor(&id); + return false; } - catch(const Ice::NoObjectFactoryException& e) + zend_update_property(cls, zex, "id", sizeof("id") - 1, id TSRMLS_CC); + } + catch(const Ice::RequestFailedException& e) + { + zval* id; + MAKE_STD_ZVAL(id); + if(!createIdentity(id, e.id TSRMLS_CC)) { - string name = e.ice_name(); - zend_class_entry* cls = findClassScoped(name TSRMLS_CC); - if(!cls) - { - throw; - } - - zval* zex; - MAKE_STD_ZVAL(zex); - if(object_init_ex(zex, cls) != SUCCESS) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to create exception %s", cls->name); - return; - } - - // - // Set the reason member. - // - zend_update_property_string(cls, zex, "reason", sizeof("reason") - 1, - const_cast<char*>(e.reason.c_str()) TSRMLS_CC); - - // - // Set the type member. - // - zend_update_property_string(cls, zex, "type", sizeof("type") - 1, const_cast<char*>(e.type.c_str()) - TSRMLS_CC); - - // - // Throw the exception. - // - zend_throw_exception_object(zex TSRMLS_CC); + zval_ptr_dtor(&id); + return false; } - catch(const Ice::UnexpectedObjectException& e) - { - string name = e.ice_name(); - zend_class_entry* cls = findClassScoped(name TSRMLS_CC); - if(!cls) - { - throw; - } - - zval* zex; - MAKE_STD_ZVAL(zex); - if(object_init_ex(zex, cls) != SUCCESS) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to create exception %s", cls->name); - return; - } + zend_update_property(cls, zex, "id", sizeof("id") - 1, id TSRMLS_CC); + setStringMember(zex, "facet", e.facet TSRMLS_CC); + setStringMember(zex, "operation", e.operation TSRMLS_CC); + } + catch(const Ice::FileException& e) + { + zend_update_property_long(cls, zex, "error", sizeof("error") - 1, e.error TSRMLS_CC); + setStringMember(zex, "path", e.path TSRMLS_CC); + } + catch(const Ice::SyscallException& e) // This must appear after all subclasses of SyscallException. + { + zend_update_property_long(cls, zex, "error", sizeof("error") - 1, e.error TSRMLS_CC); + } + catch(const Ice::DNSException& e) + { + zend_update_property_long(cls, zex, "error", sizeof("error") - 1, e.error TSRMLS_CC); + setStringMember(zex, "host", e.host TSRMLS_CC); + } + catch(const Ice::UnsupportedProtocolException& e) + { + zend_update_property_long(cls, zex, "badMajor", sizeof("badMajor") - 1, e.badMajor TSRMLS_CC); + zend_update_property_long(cls, zex, "badMinor", sizeof("badMinor") - 1, e.badMinor TSRMLS_CC); + zend_update_property_long(cls, zex, "major", sizeof("major") - 1, e.major TSRMLS_CC); + zend_update_property_long(cls, zex, "minor", sizeof("minor") - 1, e.minor TSRMLS_CC); + } + catch(const Ice::UnsupportedEncodingException& e) + { + zend_update_property_long(cls, zex, "badMajor", sizeof("badMajor") - 1, e.badMajor TSRMLS_CC); + zend_update_property_long(cls, zex, "badMinor", sizeof("badMinor") - 1, e.badMinor TSRMLS_CC); + zend_update_property_long(cls, zex, "major", sizeof("major") - 1, e.major TSRMLS_CC); + zend_update_property_long(cls, zex, "minor", sizeof("minor") - 1, e.minor TSRMLS_CC); + } + catch(const Ice::NoObjectFactoryException& e) + { + setStringMember(zex, "reason", e.reason TSRMLS_CC); + setStringMember(zex, "type", e.type TSRMLS_CC); + } + catch(const Ice::UnexpectedObjectException& e) + { + setStringMember(zex, "reason", e.reason TSRMLS_CC); + setStringMember(zex, "type", e.type TSRMLS_CC); + setStringMember(zex, "expectedType", e.expectedType TSRMLS_CC); + } + catch(const Ice::ProtocolException& e) // This must appear after all subclasses of ProtocolException. + { + setStringMember(zex, "reason", e.reason TSRMLS_CC); + } + catch(const Ice::FeatureNotSupportedException& e) + { + setStringMember(zex, "unsupportedFeature", e.unsupportedFeature TSRMLS_CC); + } + catch(const Ice::SecurityException& e) + { + setStringMember(zex, "reason", e.reason TSRMLS_CC); + } + catch(const Ice::LocalException&) + { + // + // Nothing to do. + // + } - // - // Set the reason member. - // - zend_update_property_string(cls, zex, "reason", sizeof("reason") - 1, - const_cast<char*>(e.reason.c_str()) TSRMLS_CC); - - // - // Set the type and exptected type members. - // - zend_update_property_string(cls, zex, "type", sizeof("type") - 1, const_cast<char*>(e.type.c_str()) - TSRMLS_CC); - zend_update_property_string(cls, zex, "expectedType", sizeof("expectedType") - 1, - const_cast<char*>(e.expectedType.c_str()) TSRMLS_CC); - - // - // Throw the exception. - // - zend_throw_exception_object(zex TSRMLS_CC); - } - catch(const Ice::MarshalException& e) - { - string name = e.ice_name(); - zend_class_entry* cls = findClassScoped(name TSRMLS_CC); - if(!cls) - { - throw; - } + return true; +} - zval* zex; - MAKE_STD_ZVAL(zex); - if(object_init_ex(zex, cls) != SUCCESS) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to create exception %s", cls->name); - return; - } +zval* +IcePHP::convertException(const Ice::Exception& ex TSRMLS_DC) +{ + zval* zex; + MAKE_STD_ZVAL(zex); + AutoDestroy destroy(zex); - // - // Set the reason member. - // - zend_update_property_string(cls, zex, "reason", sizeof("reason") - 1, - const_cast<char*>(e.reason.c_str()) TSRMLS_CC); + ostringstream ostr; + ostr << ex; + string str = ostr.str(); - // - // Throw the exception. - // - zend_throw_exception_object(zex TSRMLS_CC); - } + try + { + ex.ice_throw(); } catch(const Ice::LocalException& e) { - zval* zex; - MAKE_STD_ZVAL(zex); - - // - // See if we have a PHP class for the exception, otherwise raise UnknownLocalException. - // - string name = e.ice_name(); - zend_class_entry* cls = findClassScoped(name TSRMLS_CC); + zend_class_entry* cls = idToClass(e.ice_name() TSRMLS_CC); if(cls) { if(object_init_ex(zex, cls) != SUCCESS) { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to create exception %s", cls->name); - return; + runtimeError("unable to create exception %s" TSRMLS_CC, cls->name); + return 0; + } + if(!convertLocalException(e, zex TSRMLS_CC)) + { + return 0; } } else { - cls = findClass("Ice_UnknownLocalException" TSRMLS_CC); - if(!cls) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to find class Ice_UnknownLocalException"); - return; - } - + cls = idToClass("Ice::UnknownLocalException" TSRMLS_CC); + assert(cls); if(object_init_ex(zex, cls) != SUCCESS) { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to create exception %s", cls->name); - return; + runtimeError("unable to create exception %s" TSRMLS_CC, cls->name); + return 0; } - - // - // Set the unknown member. - // - ostringstream ostr; - e.ice_print(ostr); - string str = ostr.str(); - zend_update_property_string(cls, zex, "unknown", sizeof("unknown") - 1, - const_cast<char*>(str.c_str()) TSRMLS_CC); + setStringMember(zex, "unknown", str TSRMLS_CC); } - - // - // Throw the exception. - // - zend_throw_exception_object(zex TSRMLS_CC); } catch(const Ice::UserException&) { - assert(false); - } - catch(const IceUtil::Exception& e) - { - ostringstream ostr; - e.ice_print(ostr); - php_error_docref(0 TSRMLS_CC, E_ERROR, "exception: %s", ostr.str().c_str()); - } -} - -zend_class_entry* -IcePHP::findClass(const string& flat TSRMLS_DC) -{ - zend_class_entry** result; - string lower = lowerCase(flat); - if(zend_lookup_class(const_cast<char*>(lower.c_str()), lower.length(), &result TSRMLS_CC) == FAILURE) - { - return 0; - } - return *result; -} - -zend_class_entry* -IcePHP::findClassScoped(const string& scoped TSRMLS_DC) -{ - return findClass(flatten(scoped) TSRMLS_CC); -} - -string -IcePHP::lowerCase(const string& s) -{ - string result(s); - transform(result.begin(), result.end(), result.begin(), ::tolower); - return result; -} - -string -IcePHP::flatten(const string& scoped) -{ - string result = scoped; - if(result.find("::") == 0) - { - result.erase(0, 2); + zend_class_entry* cls = idToClass("Ice::UnknownUserException" TSRMLS_CC); + assert(cls); + if(object_init_ex(zex, cls) != SUCCESS) + { + runtimeError("unable to create exception %s" TSRMLS_CC, cls->name); + return 0; + } + setStringMember(zex, "unknown", str TSRMLS_CC); } - - string::size_type pos; - while((pos = result.find("::")) != string::npos) + catch(const Ice::Exception&) { - result.replace(pos, 2, "_"); + zend_class_entry* cls = idToClass("Ice::UnknownException" TSRMLS_CC); + assert(cls); + if(object_init_ex(zex, cls) != SUCCESS) + { + runtimeError("unable to create exception %s" TSRMLS_CC, cls->name); + return 0; + } + setStringMember(zex, "unknown", str TSRMLS_CC); } - return fixIdent(result); + return destroy.release(); } -string -IcePHP::fixIdent(const string& ident) +void +IcePHP::throwException(const Ice::Exception& ex TSRMLS_DC) { - if(ident[0] != ':') - { - return lookupKwd(ident); - } - vector<string> ids = splitScopedName(ident); - transform(ids.begin(), ids.end(), ids.begin(), ptr_fun(lookupKwd)); - stringstream result; - for(vector<string>::const_iterator i = ids.begin(); i != ids.end(); ++i) + zval* zex = convertException(ex TSRMLS_CC); + if(zex) { - result << "::" + *i; + zend_throw_exception_object(zex TSRMLS_CC); } - return result.str(); } std::string @@ -643,36 +556,128 @@ IcePHP::zendTypeToString(int type) return result; } -bool -IcePHP::isNativeKey(const Slice::TypePtr& type) +static void +throwError(const string& name, const string& msg TSRMLS_DC) { + zval* ex; + MAKE_STD_ZVAL(ex); + AutoDestroy destroy(ex); + + zend_class_entry* cls; + { + zend_class_entry** p; + if(zend_lookup_class(STRCAST(name.c_str()), name.size(), &p TSRMLS_CC) == FAILURE) + { + assert(false); + } + cls = *p; + } + if(object_init_ex(ex, cls) == FAILURE) + { + assert(false); + } + // - // PHP's native associative array supports only integer and string types for the key. - // For Slice dictionaries that meet this criteria, we use the native array type. + // Invoke constructor. // - Slice::BuiltinPtr b = Slice::BuiltinPtr::dynamicCast(type); - if(b) + if(!invokeMethod(ex, ZEND_CONSTRUCTOR_FUNC_NAME, msg TSRMLS_CC)) { - switch(b->kind()) - { - case Slice::Builtin::KindByte: - case Slice::Builtin::KindBool: // We allow bool even though PHP doesn't support it directly. - case Slice::Builtin::KindShort: - case Slice::Builtin::KindInt: - case Slice::Builtin::KindLong: - case Slice::Builtin::KindString: - return true; + assert(false); + } - case Slice::Builtin::KindFloat: - case Slice::Builtin::KindDouble: - case Slice::Builtin::KindObject: - case Slice::Builtin::KindObjectProxy: - case Slice::Builtin::KindLocalObject: - break; - } + zend_throw_exception_object(ex TSRMLS_CC); + destroy.release(); +} + +void +IcePHP::runtimeError(const char* fmt TSRMLS_DC, ...) +{ + va_list args; + char msg[1024]; + +#if ZTS + va_start(args, TSRMLS_C); +#else + va_start(args, fmt); +#endif + +#if defined(_MSC_VER) && (_MSC_VER >= 1500) + vsprintf_s(msg, fmt, args); +#else + vsprintf(msg, fmt, args); +#endif + + va_end(args); + + throwError("RuntimeException", msg TSRMLS_CC); +} + +void +IcePHP::invalidArgument(const char* fmt TSRMLS_DC, ...) +{ + va_list args; + char msg[1024]; + +#if ZTS + va_start(args, TSRMLS_C); +#else + va_start(args, fmt); +#endif + +#if defined(_MSC_VER) && (_MSC_VER >= 1500) + vsprintf_s(msg, fmt, args); +#else + vsprintf(msg, fmt, args); +#endif + + va_end(args); + + throwError("InvalidArgumentException", msg TSRMLS_CC); +} + +static bool +invokeMethodHelper(zval* obj, const string& name, zval* param TSRMLS_DC) +{ + assert(zend_hash_exists(&Z_OBJCE_P(obj)->function_table, STRCAST(name.c_str()), name.size() + 1)); + zval ret, method; + INIT_ZVAL(ret); + INIT_ZVAL(method); + ZVAL_STRING(&method, STRCAST(name.c_str()), 1); + zend_uint numParams = param ? 1 : 0; + zval** params = param ? ¶m : 0; + int status = 0; + zend_try + { + status = call_user_function(0, &obj, &method, &ret, numParams, params TSRMLS_CC); + } + zend_catch + { + status = FAILURE; } + zend_end_try(); + zval_dtor(&method); + zval_dtor(&ret); + if(status == FAILURE || EG(exception)) + { + return false; + } + return true; +} - return false; +bool +IcePHP::invokeMethod(zval* obj, const string& name TSRMLS_DC) +{ + return invokeMethodHelper(obj, name, 0 TSRMLS_CC); +} + +bool +IcePHP::invokeMethod(zval* obj, const string& name, const string& arg TSRMLS_DC) +{ + zval* param; + MAKE_STD_ZVAL(param); + ZVAL_STRINGL(param, STRCAST(arg.c_str()), arg.size(), 1); + AutoDestroy destroy(param); + return invokeMethodHelper(obj, name, param TSRMLS_CC); } bool @@ -698,3 +703,34 @@ IcePHP::checkClass(zend_class_entry* ce, zend_class_entry* base) return false; } + +ZEND_FUNCTION(Ice_stringVersion) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + RETURN_STRINGL(STRCAST(ICE_STRING_VERSION), strlen(ICE_STRING_VERSION), 1); +} + +ZEND_FUNCTION(Ice_intVersion) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + RETURN_LONG(ICE_INT_VERSION); +} + +ZEND_FUNCTION(Ice_generateUUID) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + string uuid = IceUtil::generateUUID(); + RETURN_STRINGL(STRCAST(uuid.c_str()), uuid.size(), 1); +} |