diff options
author | Wez Furlong <wez@php.net> | 2003-10-17 20:52:18 +0000 |
---|---|---|
committer | Wez Furlong <wez@php.net> | 2003-10-17 20:52:18 +0000 |
commit | d8d1ca3f3bfd9fdb628c9ab3a986adb5f10d6e93 (patch) | |
tree | 9f63182d86c4fdae4552b18d27aa43c3049498de | |
parent | 65657103ad848011edad2b6d866de57f172962f5 (diff) | |
download | php-git-d8d1ca3f3bfd9fdb628c9ab3a986adb5f10d6e93.tar.gz |
add com iterator support
-rw-r--r-- | ext/com_dotnet/com_extension.c | 3 | ||||
-rw-r--r-- | ext/com_dotnet/com_iterator.c | 178 | ||||
-rw-r--r-- | ext/com_dotnet/php_com_dotnet_internal.h | 3 | ||||
-rw-r--r-- | win32/php4dllts.dsp | 4 |
4 files changed, 188 insertions, 0 deletions
diff --git a/ext/com_dotnet/com_extension.c b/ext/com_dotnet/com_extension.c index 3ba68e6b2f..ec155ead19 100644 --- a/ext/com_dotnet/com_extension.c +++ b/ext/com_dotnet/com_extension.c @@ -112,10 +112,12 @@ PHP_MINIT_FUNCTION(com_dotnet) INIT_CLASS_ENTRY(ce, "variant", NULL); ce.create_object = php_com_object_new; + ce.get_iterator = php_com_iter_get; php_com_variant_class_entry = zend_register_internal_class(&ce TSRMLS_CC); INIT_CLASS_ENTRY(ce, "com", NULL); ce.create_object = php_com_object_new; + ce.get_iterator = php_com_iter_get; zend_register_internal_class_ex(&ce, php_com_variant_class_entry, "variant" TSRMLS_CC); zend_ts_hash_init(&php_com_typelibraries, 0, NULL, php_com_typelibrary_dtor, 1); @@ -123,6 +125,7 @@ PHP_MINIT_FUNCTION(com_dotnet) #if HAVE_MSCOREE_H INIT_CLASS_ENTRY(ce, "dotnet", NULL); ce.create_object = php_com_object_new; + ce.get_iterator = php_com_iter_get; zend_register_internal_class_ex(&ce, php_com_variant_class_entry, "variant" TSRMLS_CC); #endif diff --git a/ext/com_dotnet/com_iterator.c b/ext/com_dotnet/com_iterator.c new file mode 100644 index 0000000000..c47218bb00 --- /dev/null +++ b/ext/com_dotnet/com_iterator.c @@ -0,0 +1,178 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2003 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.0 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_0.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Wez Furlong <wez@thebrainroom.com> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "php_com_dotnet.h" +#include "php_com_dotnet_internal.h" +#include "Zend/zend_default_classes.h" + +struct php_com_iterator { + zend_object_iterator iter; + IEnumVARIANT *ev; + ulong key; + VARIANT v; + int code_page; +}; + +static void com_iter_dtor(zend_object_iterator *iter TSRMLS_DC) +{ + struct php_com_iterator *I = (struct php_com_iterator*)iter->data; + + if (I->ev) { + IEnumVARIANT_Release(I->ev); + } + VariantClear(&I->v); + efree(I); +} + +static int com_iter_has_more(zend_object_iterator *iter TSRMLS_DC) +{ + struct php_com_iterator *I = (struct php_com_iterator*)iter->data; + + if (I->key == (ulong)-1) { + return FAILURE; + } + return SUCCESS; +} + +static void com_iter_get_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) +{ + struct php_com_iterator *I = (struct php_com_iterator*)iter->data; + zval **ptr_ptr; + zval *ptr; + + if (I->key == (ulong)-1) { + *data = NULL; + return FAILURE; + } + + MAKE_STD_ZVAL(ptr); + php_com_wrap_variant(ptr, &I->v, I->code_page TSRMLS_CC); + ptr_ptr = emalloc(sizeof(*ptr_ptr)); + *ptr_ptr = ptr; + *data = ptr_ptr; + + return SUCCESS; +} + +static int com_iter_get_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, + ulong *int_key TSRMLS_DC) +{ + struct php_com_iterator *I = (struct php_com_iterator*)iter->data; + + if (I->key == (ulong)-1) { + return HASH_KEY_NON_EXISTANT; + } + *int_key = I->key; + return HASH_KEY_IS_LONG; +} + +static int com_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC) +{ + struct php_com_iterator *I = (struct php_com_iterator*)iter->data; + unsigned long n_fetched; + + /* release current cached element */ + VariantClear(&I->v); + + /* Get the next element */ + if (SUCCEEDED(IEnumVARIANT_Next(I->ev, 1, &I->v, &n_fetched)) && n_fetched > 0) { + I->key++; + return SUCCESS; + } else { + /* indicate that there are no more items */ + I->key = (ulong)-1; + return FAILURE; + } +} + + +static zend_object_iterator_funcs com_iter_funcs = { + com_iter_dtor, + NULL, /* rewind */ + com_iter_has_more, + com_iter_get_data, + com_iter_get_key, + com_iter_move_forwards +}; + +zend_object_iterator *php_com_iter_get(zend_class_entry *ce, zval *object TSRMLS_DC) +{ + php_com_dotnet_object *obj; + struct php_com_iterator *I; + IEnumVARIANT *iev = NULL; + DISPPARAMS dp; + VARIANT v; + unsigned long n_fetched; + + obj = CDNO_FETCH(object); + + /* TODO: support enumerating through SafeArrays */ + if (V_VT(&obj->v) != VT_DISPATCH) { + return NULL; + } + + memset(&dp, 0, sizeof(dp)); + VariantInit(&v); + + /* can we enumerate it? */ + if (FAILED(IDispatch_Invoke(V_DISPATCH(&obj->v), DISPID_NEWENUM, + &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD|DISPATCH_PROPERTYGET, + &dp, &v, NULL, NULL))) { + return NULL; + } + + /* get something useful out of it */ + if (V_VT(&v) == VT_UNKNOWN) { + IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IEnumVARIANT, (void**)&iev); + } else if (V_VT(&v) == VT_DISPATCH) { + IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IEnumVARIANT, (void**)&iev); + } + + VariantClear(&v); + + if (iev == NULL) { + return NULL; + } + + I = (struct php_com_iterator*)ecalloc(1, sizeof(*I)); + I->iter.funcs = &com_iter_funcs; + I->iter.data = I; + I->ev = iev; + I->code_page = obj->code_page; + + /* Get the first element now */ + if (SUCCEEDED(IEnumVARIANT_Next(I->ev, 1, &I->v, &n_fetched)) && n_fetched > 0) { + /* indicate that we have element 0 */ + I->key = 0; + } else { + /* indicate that there are no more items */ + I->key = (ulong)-1; + } + + return &I->iter; +} + diff --git a/ext/com_dotnet/php_com_dotnet_internal.h b/ext/com_dotnet/php_com_dotnet_internal.h index 749306e12b..150a925792 100644 --- a/ext/com_dotnet/php_com_dotnet_internal.h +++ b/ext/com_dotnet/php_com_dotnet_internal.h @@ -141,5 +141,8 @@ PHPAPI int php_com_import_typelib(ITypeLib *TL, int mode, int codepage TSRMLS_DC); void php_com_typelibrary_dtor(void *pDest); +/* com_iterator.c */ +zend_object_iterator *php_com_iter_get(zend_class_entry *ce, zval *object TSRMLS_DC); + #endif diff --git a/win32/php4dllts.dsp b/win32/php4dllts.dsp index 2b9bfd93a6..448f69de18 100644 --- a/win32/php4dllts.dsp +++ b/win32/php4dllts.dsp @@ -2324,6 +2324,10 @@ SOURCE=..\ext\com_dotnet\com_handlers.c # End Source File
# Begin Source File
+SOURCE=..\ext\com_dotnet\com_iterator.c
+# End Source File
+# Begin Source File
+
SOURCE=..\ext\com_dotnet\com_misc.c
# End Source File
# Begin Source File
|