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>