summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWez Furlong <wez@php.net>2003-10-17 20:52:18 +0000
committerWez Furlong <wez@php.net>2003-10-17 20:52:18 +0000
commitd8d1ca3f3bfd9fdb628c9ab3a986adb5f10d6e93 (patch)
tree9f63182d86c4fdae4552b18d27aa43c3049498de
parent65657103ad848011edad2b6d866de57f172962f5 (diff)
downloadphp-git-d8d1ca3f3bfd9fdb628c9ab3a986adb5f10d6e93.tar.gz
add com iterator support
-rw-r--r--ext/com_dotnet/com_extension.c3
-rw-r--r--ext/com_dotnet/com_iterator.c178
-rw-r--r--ext/com_dotnet/php_com_dotnet_internal.h3
-rw-r--r--win32/php4dllts.dsp4
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