Annotation of embedaddon/php/ext/com_dotnet/com_iterator.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 The PHP Group |
! 6: +----------------------------------------------------------------------+
! 7: | This source file is subject to version 3.01 of the PHP license, |
! 8: | that is bundled with this package in the file LICENSE, and is |
! 9: | available through the world-wide-web at the following url: |
! 10: | http://www.php.net/license/3_01.txt |
! 11: | If you did not receive a copy of the PHP license and are unable to |
! 12: | obtain it through the world-wide-web, please send a note to |
! 13: | license@php.net so we can mail you a copy immediately. |
! 14: +----------------------------------------------------------------------+
! 15: | Author: Wez Furlong <wez@thebrainroom.com> |
! 16: +----------------------------------------------------------------------+
! 17: */
! 18:
! 19: /* $Id: com_iterator.c 321634 2012-01-01 13:15:04Z felipe $ */
! 20:
! 21: #ifdef HAVE_CONFIG_H
! 22: #include "config.h"
! 23: #endif
! 24:
! 25: #include "php.h"
! 26: #include "php_ini.h"
! 27: #include "ext/standard/info.h"
! 28: #include "php_com_dotnet.h"
! 29: #include "php_com_dotnet_internal.h"
! 30: #include "Zend/zend_exceptions.h"
! 31:
! 32: struct php_com_iterator {
! 33: zend_object_iterator iter;
! 34: IEnumVARIANT *ev;
! 35: ulong key;
! 36: VARIANT v; /* cached element */
! 37: int code_page;
! 38: VARIANT safe_array;
! 39: VARTYPE sa_type;
! 40: LONG sa_max;
! 41: zval *zdata;
! 42: };
! 43:
! 44: static void com_iter_dtor(zend_object_iterator *iter TSRMLS_DC)
! 45: {
! 46: struct php_com_iterator *I = (struct php_com_iterator*)iter->data;
! 47:
! 48: if (I->ev) {
! 49: IEnumVARIANT_Release(I->ev);
! 50: }
! 51: VariantClear(&I->v);
! 52: VariantClear(&I->safe_array);
! 53: if (I->zdata) {
! 54: zval_ptr_dtor((zval**)&I->zdata);
! 55: }
! 56: efree(I);
! 57: }
! 58:
! 59: static int com_iter_valid(zend_object_iterator *iter TSRMLS_DC)
! 60: {
! 61: struct php_com_iterator *I = (struct php_com_iterator*)iter->data;
! 62:
! 63: if (I->zdata) {
! 64: return SUCCESS;
! 65: }
! 66:
! 67: return FAILURE;
! 68: }
! 69:
! 70: static void com_iter_get_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
! 71: {
! 72: struct php_com_iterator *I = (struct php_com_iterator*)iter->data;
! 73:
! 74: *data = &I->zdata;
! 75: }
! 76:
! 77: static int com_iter_get_key(zend_object_iterator *iter, char **str_key, uint *str_key_len,
! 78: ulong *int_key TSRMLS_DC)
! 79: {
! 80: struct php_com_iterator *I = (struct php_com_iterator*)iter->data;
! 81:
! 82: if (I->key == (ulong)-1) {
! 83: return HASH_KEY_NON_EXISTANT;
! 84: }
! 85: *int_key = I->key;
! 86: return HASH_KEY_IS_LONG;
! 87: }
! 88:
! 89: static int com_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC)
! 90: {
! 91: struct php_com_iterator *I = (struct php_com_iterator*)iter->data;
! 92: unsigned long n_fetched;
! 93: zval *ptr;
! 94:
! 95: /* release current cached element */
! 96: VariantClear(&I->v);
! 97:
! 98: if (I->zdata) {
! 99: zval_ptr_dtor((zval**)&I->zdata);
! 100: I->zdata = NULL;
! 101: }
! 102:
! 103: if (I->ev) {
! 104: /* Get the next element */
! 105: if (SUCCEEDED(IEnumVARIANT_Next(I->ev, 1, &I->v, &n_fetched)) && n_fetched > 0) {
! 106: I->key++;
! 107: } else {
! 108: /* indicate that there are no more items */
! 109: I->key = (ulong)-1;
! 110: return FAILURE;
! 111: }
! 112: } else {
! 113: /* safe array */
! 114: if (I->key >= (ULONG) I->sa_max) {
! 115: I->key = (ulong)-1;
! 116: return FAILURE;
! 117: }
! 118: I->key++;
! 119: if (php_com_safearray_get_elem(&I->safe_array, &I->v, (LONG)I->key TSRMLS_CC) == 0) {
! 120: I->key = (ulong)-1;
! 121: return FAILURE;
! 122: }
! 123: }
! 124:
! 125: MAKE_STD_ZVAL(ptr);
! 126: php_com_zval_from_variant(ptr, &I->v, I->code_page TSRMLS_CC);
! 127: /* php_com_wrap_variant(ptr, &I->v, I->code_page TSRMLS_CC); */
! 128: I->zdata = ptr;
! 129: return SUCCESS;
! 130: }
! 131:
! 132:
! 133: static zend_object_iterator_funcs com_iter_funcs = {
! 134: com_iter_dtor,
! 135: com_iter_valid,
! 136: com_iter_get_data,
! 137: com_iter_get_key,
! 138: com_iter_move_forwards,
! 139: NULL
! 140: };
! 141:
! 142: zend_object_iterator *php_com_iter_get(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
! 143: {
! 144: php_com_dotnet_object *obj;
! 145: struct php_com_iterator *I;
! 146: IEnumVARIANT *iev = NULL;
! 147: DISPPARAMS dp;
! 148: VARIANT v;
! 149: unsigned long n_fetched;
! 150: zval *ptr;
! 151:
! 152: if (by_ref) {
! 153: zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
! 154: }
! 155:
! 156: obj = CDNO_FETCH(object);
! 157:
! 158: if (V_VT(&obj->v) != VT_DISPATCH && !V_ISARRAY(&obj->v)) {
! 159: php_error_docref(NULL TSRMLS_CC, E_WARNING, "variant is not an object or array VT=%d", V_VT(&obj->v));
! 160: return NULL;
! 161: }
! 162:
! 163: memset(&dp, 0, sizeof(dp));
! 164: VariantInit(&v);
! 165:
! 166: I = (struct php_com_iterator*)ecalloc(1, sizeof(*I));
! 167: I->iter.funcs = &com_iter_funcs;
! 168: I->iter.data = I;
! 169: I->code_page = obj->code_page;
! 170: I->zdata = NULL;
! 171: VariantInit(&I->safe_array);
! 172: VariantInit(&I->v);
! 173:
! 174: if (V_ISARRAY(&obj->v)) {
! 175: LONG bound;
! 176: UINT dims;
! 177:
! 178: dims = SafeArrayGetDim(V_ARRAY(&obj->v));
! 179:
! 180: if (dims != 1) {
! 181: php_error_docref(NULL TSRMLS_CC, E_WARNING,
! 182: "Can only handle single dimension variant arrays (this array has %d)", dims);
! 183: goto fail;
! 184: }
! 185:
! 186: /* same semantics as foreach on a PHP array;
! 187: * make a copy and enumerate that copy */
! 188: VariantCopy(&I->safe_array, &obj->v);
! 189:
! 190: /* determine the key value for the array */
! 191: SafeArrayGetLBound(V_ARRAY(&I->safe_array), 1, &bound);
! 192: SafeArrayGetUBound(V_ARRAY(&I->safe_array), 1, &I->sa_max);
! 193:
! 194: /* pre-fetch the element */
! 195: if (php_com_safearray_get_elem(&I->safe_array, &I->v, bound TSRMLS_CC)) {
! 196: I->key = bound;
! 197: MAKE_STD_ZVAL(ptr);
! 198: php_com_zval_from_variant(ptr, &I->v, I->code_page TSRMLS_CC);
! 199: I->zdata = ptr;
! 200: } else {
! 201: I->key = (ulong)-1;
! 202: }
! 203:
! 204: } else {
! 205: /* can we enumerate it? */
! 206: if (FAILED(IDispatch_Invoke(V_DISPATCH(&obj->v), DISPID_NEWENUM,
! 207: &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD|DISPATCH_PROPERTYGET,
! 208: &dp, &v, NULL, NULL))) {
! 209: goto fail;
! 210: }
! 211:
! 212: /* get something useful out of it */
! 213: if (V_VT(&v) == VT_UNKNOWN) {
! 214: IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IEnumVARIANT, (void**)&iev);
! 215: } else if (V_VT(&v) == VT_DISPATCH) {
! 216: IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IEnumVARIANT, (void**)&iev);
! 217: }
! 218:
! 219: VariantClear(&v);
! 220:
! 221: if (iev == NULL) {
! 222: goto fail;
! 223: }
! 224:
! 225: I->ev = iev;
! 226:
! 227: /* Get the first element now */
! 228: if (SUCCEEDED(IEnumVARIANT_Next(I->ev, 1, &I->v, &n_fetched)) && n_fetched > 0) {
! 229: /* indicate that we have element 0 */
! 230: I->key = 0;
! 231: MAKE_STD_ZVAL(ptr);
! 232: php_com_zval_from_variant(ptr, &I->v, I->code_page TSRMLS_CC);
! 233: I->zdata = ptr;
! 234: } else {
! 235: /* indicate that there are no more items */
! 236: I->key = (ulong)-1;
! 237: }
! 238: }
! 239:
! 240: return &I->iter;
! 241:
! 242: fail:
! 243: if (I) {
! 244: VariantClear(&I->safe_array);
! 245: VariantClear(&I->v);
! 246: efree(I);
! 247: }
! 248: return NULL;
! 249: }
! 250:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>