Annotation of embedaddon/php/ext/com_dotnet/com_saproxy.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_saproxy.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            20: 
        !            21: /* This module implements a SafeArray proxy which is used internally
        !            22:  * by the engine when resolving multi-dimensional array accesses on
        !            23:  * SafeArray types.
        !            24:  * In addition, the proxy is now able to handle properties of COM objects
        !            25:  * that smell like PHP arrays.
        !            26:  * */
        !            27: 
        !            28: #ifdef HAVE_CONFIG_H
        !            29: #include "config.h"
        !            30: #endif
        !            31: 
        !            32: #include "php.h"
        !            33: #include "php_ini.h"
        !            34: #include "ext/standard/info.h"
        !            35: #include "php_com_dotnet.h"
        !            36: #include "php_com_dotnet_internal.h"
        !            37: #include "Zend/zend_exceptions.h"
        !            38: 
        !            39: typedef struct {
        !            40:        /* the object we a proxying for; we hold a refcount to it */
        !            41:        zval *zobj;
        !            42:        php_com_dotnet_object *obj;
        !            43: 
        !            44:        /* how many dimensions we are indirecting to get into this element */
        !            45:        LONG dimensions;
        !            46:        
        !            47:        /* this is an array whose size_is(dimensions) */
        !            48:        zval **indices;
        !            49: 
        !            50: } php_com_saproxy;
        !            51: 
        !            52: typedef struct {
        !            53:        zend_object_iterator iter;
        !            54:        zval *proxy_obj;
        !            55:        php_com_saproxy *proxy;
        !            56:        LONG key;
        !            57:        LONG imin, imax;
        !            58:        LONG *indices;
        !            59: } php_com_saproxy_iter;
        !            60: 
        !            61: #define SA_FETCH(zv)                   (php_com_saproxy*)zend_object_store_get_object(zv TSRMLS_CC)
        !            62: 
        !            63: static inline void clone_indices(php_com_saproxy *dest, php_com_saproxy *src, int ndims)
        !            64: {
        !            65:        int i;
        !            66: 
        !            67:        for (i = 0; i < ndims; i++) {
        !            68:                MAKE_STD_ZVAL(dest->indices[i]);
        !            69:                *dest->indices[i] = *src->indices[i];
        !            70:                zval_copy_ctor(dest->indices[i]);
        !            71:        }
        !            72: }
        !            73: 
        !            74: static zval *saproxy_property_read(zval *object, zval *member, int type TSRMLS_DC)
        !            75: {
        !            76:        zval *return_value;
        !            77:        
        !            78:        MAKE_STD_ZVAL(return_value);
        !            79:        ZVAL_NULL(return_value);
        !            80: 
        !            81:        php_com_throw_exception(E_INVALIDARG, "safearray has no properties" TSRMLS_CC);
        !            82: 
        !            83:        return return_value;
        !            84: }
        !            85: 
        !            86: static void saproxy_property_write(zval *object, zval *member, zval *value TSRMLS_DC)
        !            87: {
        !            88:        php_com_throw_exception(E_INVALIDARG, "safearray has no properties" TSRMLS_CC);
        !            89: }
        !            90: 
        !            91: static zval *saproxy_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
        !            92: {
        !            93:        php_com_saproxy *proxy = SA_FETCH(object);
        !            94:        zval *return_value;
        !            95:        UINT dims, i;
        !            96:        SAFEARRAY *sa;
        !            97:        LONG ubound, lbound;
        !            98:        HRESULT res;
        !            99:        
        !           100:        MAKE_STD_ZVAL(return_value);
        !           101:        ZVAL_NULL(return_value);
        !           102:        
        !           103:        if (V_VT(&proxy->obj->v) == VT_DISPATCH) {
        !           104:                VARIANT v;
        !           105:                zval **args;
        !           106: 
        !           107:                /* prop-get using first dimension as the property name,
        !           108:                 * all subsequent dimensions and the offset as parameters */
        !           109: 
        !           110:                args = safe_emalloc(proxy->dimensions + 1, sizeof(zval *), 0);
        !           111: 
        !           112:                for (i = 1; i < (UINT) proxy->dimensions; i++) {
        !           113:                        args[i-1] = proxy->indices[i];
        !           114:                }
        !           115:                args[i-1] = offset;
        !           116: 
        !           117:                convert_to_string(proxy->indices[0]);
        !           118:                VariantInit(&v);
        !           119: 
        !           120:                res = php_com_do_invoke(proxy->obj, Z_STRVAL_P(proxy->indices[0]),
        !           121:                                Z_STRLEN_P(proxy->indices[0]), DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v,
        !           122:                                proxy->dimensions, args, 0 TSRMLS_CC);
        !           123: 
        !           124:                if (res == SUCCESS) {
        !           125:                        php_com_zval_from_variant(return_value, &v, proxy->obj->code_page TSRMLS_CC);
        !           126:                        VariantClear(&v);
        !           127:                } else if (res == DISP_E_BADPARAMCOUNT) {
        !           128:                        /* return another proxy */
        !           129:                        php_com_saproxy_create(object, return_value, offset TSRMLS_CC);
        !           130:                }
        !           131: 
        !           132:                return return_value;
        !           133: 
        !           134:        } else if (!V_ISARRAY(&proxy->obj->v)) {
        !           135:                php_com_throw_exception(E_INVALIDARG, "invalid read from com proxy object" TSRMLS_CC);
        !           136:                return return_value;
        !           137:        }
        !           138: 
        !           139:        /* the SafeArray case */
        !           140:        
        !           141:        /* offset/index must be an integer */
        !           142:        convert_to_long(offset);
        !           143:        
        !           144:        sa = V_ARRAY(&proxy->obj->v);
        !           145:        dims = SafeArrayGetDim(sa);
        !           146: 
        !           147:        if ((UINT) proxy->dimensions >= dims) {
        !           148:                /* too many dimensions */
        !           149:                php_com_throw_exception(E_INVALIDARG, "too many dimensions!" TSRMLS_CC);
        !           150:                return return_value;
        !           151:        }
        !           152: 
        !           153:        /* bounds check */
        !           154:        SafeArrayGetLBound(sa, proxy->dimensions, &lbound);
        !           155:        SafeArrayGetUBound(sa, proxy->dimensions, &ubound);
        !           156: 
        !           157:        if (Z_LVAL_P(offset) < lbound || Z_LVAL_P(offset) > ubound) {
        !           158:                php_com_throw_exception(DISP_E_BADINDEX, "index out of bounds" TSRMLS_CC);
        !           159:                return return_value;
        !           160:        }
        !           161:        
        !           162:        if (dims - 1 == proxy->dimensions) {
        !           163:                LONG *indices;
        !           164:                VARTYPE vt;
        !           165:                VARIANT v;
        !           166:                
        !           167:                VariantInit(&v);
        !           168:                
        !           169:                /* we can return a real value */
        !           170:                indices = safe_emalloc(dims, sizeof(LONG), 0);
        !           171: 
        !           172:                /* copy indices from proxy */
        !           173:                for (i = 0; i < dims; i++) {
        !           174:                        convert_to_long(proxy->indices[i]);
        !           175:                        indices[i] = Z_LVAL_P(proxy->indices[i]);
        !           176:                }
        !           177: 
        !           178:                /* add user-supplied index */
        !           179:                indices[dims-1] = Z_LVAL_P(offset);
        !           180: 
        !           181:                /* now fetch the value */
        !           182:                if (FAILED(SafeArrayGetVartype(sa, &vt)) || vt == VT_EMPTY) {
        !           183:                        vt = V_VT(&proxy->obj->v) & ~VT_ARRAY;
        !           184:                }
        !           185: 
        !           186:                if (vt == VT_VARIANT) {
        !           187:                        res = SafeArrayGetElement(sa, indices, &v);
        !           188:                } else {
        !           189:                        V_VT(&v) = vt;
        !           190:                        res = SafeArrayGetElement(sa, indices, &v.lVal);
        !           191:                }
        !           192: 
        !           193:                efree(indices);
        !           194: 
        !           195:                if (SUCCEEDED(res)) {
        !           196:                        php_com_wrap_variant(return_value, &v, proxy->obj->code_page TSRMLS_CC);
        !           197:                } else {
        !           198:                        php_com_throw_exception(res, NULL TSRMLS_CC);
        !           199:                }
        !           200: 
        !           201:                VariantClear(&v);
        !           202:                
        !           203:        } else {
        !           204:                /* return another proxy */
        !           205:                php_com_saproxy_create(object, return_value, offset TSRMLS_CC);
        !           206:        }
        !           207: 
        !           208:        return return_value;
        !           209: }
        !           210: 
        !           211: static void saproxy_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
        !           212: {
        !           213:        php_com_saproxy *proxy = SA_FETCH(object);
        !           214:        UINT dims, i;
        !           215:        HRESULT res;
        !           216:        VARIANT v;
        !           217:        
        !           218:        if (V_VT(&proxy->obj->v) == VT_DISPATCH) {
        !           219:                /* We do a prop-set using the first dimension as the property name,
        !           220:                 * all subsequent dimensions and offset as parameters, with value as
        !           221:                 * the final value */
        !           222:                zval **args = safe_emalloc(proxy->dimensions + 2, sizeof(zval *), 0);
        !           223: 
        !           224:                for (i = 1; i < (UINT) proxy->dimensions; i++) {
        !           225:                        args[i-1] = proxy->indices[i];
        !           226:                }
        !           227:                args[i-1] = offset;
        !           228:                args[i] = value;
        !           229: 
        !           230:                convert_to_string(proxy->indices[0]);
        !           231:                VariantInit(&v);
        !           232:                if (SUCCESS == php_com_do_invoke(proxy->obj, Z_STRVAL_P(proxy->indices[0]),
        !           233:                                        Z_STRLEN_P(proxy->indices[0]), DISPATCH_PROPERTYPUT, &v, proxy->dimensions + 1,
        !           234:                                        args, 0 TSRMLS_CC)) {
        !           235:                        VariantClear(&v);
        !           236:                }
        !           237: 
        !           238:                efree(args);
        !           239:                
        !           240:        } else if (V_ISARRAY(&proxy->obj->v)) {
        !           241:                LONG *indices;
        !           242:                VARTYPE vt;
        !           243: 
        !           244:                dims = SafeArrayGetDim(V_ARRAY(&proxy->obj->v));
        !           245:                indices = safe_emalloc(dims, sizeof(LONG), 0);
        !           246:                /* copy indices from proxy */
        !           247:                for (i = 0; i < dims; i++) {
        !           248:                        convert_to_long(proxy->indices[i]);
        !           249:                        indices[i] = Z_LVAL_P(proxy->indices[i]);
        !           250:                }
        !           251: 
        !           252:                /* add user-supplied index */
        !           253:                convert_to_long(offset);
        !           254:                indices[dims-1] = Z_LVAL_P(offset);
        !           255: 
        !           256:                if (FAILED(SafeArrayGetVartype(V_ARRAY(&proxy->obj->v), &vt)) || vt == VT_EMPTY) {
        !           257:                        vt = V_VT(&proxy->obj->v) & ~VT_ARRAY;
        !           258:                }
        !           259: 
        !           260:                VariantInit(&v);
        !           261:                php_com_variant_from_zval(&v, value, proxy->obj->code_page TSRMLS_CC);
        !           262: 
        !           263:                if (V_VT(&v) != vt) {
        !           264:                        VariantChangeType(&v, &v, 0, vt);
        !           265:                }
        !           266: 
        !           267:                if (vt == VT_VARIANT) {
        !           268:                        res = SafeArrayPutElement(V_ARRAY(&proxy->obj->v), indices, &v);
        !           269:                } else {
        !           270:                        res = SafeArrayPutElement(V_ARRAY(&proxy->obj->v), indices, &v.lVal);
        !           271:                }
        !           272:        
        !           273:                efree(indices);
        !           274:                VariantClear(&v);
        !           275: 
        !           276:                if (FAILED(res)) {
        !           277:                        php_com_throw_exception(res, NULL TSRMLS_CC);
        !           278:                }
        !           279:        } else {
        !           280:                php_com_throw_exception(E_NOTIMPL, "invalid write to com proxy object" TSRMLS_CC);
        !           281:        }
        !           282: }
        !           283: 
        !           284: #if 0
        !           285: static void saproxy_object_set(zval **property, zval *value TSRMLS_DC)
        !           286: {
        !           287: }
        !           288: 
        !           289: static zval *saproxy_object_get(zval *property TSRMLS_DC)
        !           290: {
        !           291:        /* Not yet implemented in the engine */
        !           292:        return NULL;
        !           293: }
        !           294: #endif
        !           295: 
        !           296: static int saproxy_property_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
        !           297: {
        !           298:        /* no properties */
        !           299:        return 0;
        !           300: }
        !           301: 
        !           302: static int saproxy_dimension_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
        !           303: {
        !           304:        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Operation not yet supported on a COM object");
        !           305:        return 0;
        !           306: }
        !           307: 
        !           308: static void saproxy_property_delete(zval *object, zval *member TSRMLS_DC)
        !           309: {
        !           310:        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a COM object");
        !           311: }
        !           312: 
        !           313: static void saproxy_dimension_delete(zval *object, zval *offset TSRMLS_DC)
        !           314: {
        !           315:        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a COM object");
        !           316: }
        !           317: 
        !           318: static HashTable *saproxy_properties_get(zval *object TSRMLS_DC)
        !           319: {
        !           320:        /* no properties */
        !           321:        return NULL;
        !           322: }
        !           323: 
        !           324: static union _zend_function *saproxy_method_get(zval **object, char *name, int len TSRMLS_DC)
        !           325: {
        !           326:        /* no methods */
        !           327:        return NULL;
        !           328: }
        !           329: 
        !           330: static int saproxy_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
        !           331: {
        !           332:        return FAILURE;
        !           333: }
        !           334: 
        !           335: static union _zend_function *saproxy_constructor_get(zval *object TSRMLS_DC)
        !           336: {
        !           337:        /* user cannot instantiate */
        !           338:        return NULL;
        !           339: }
        !           340: 
        !           341: static zend_class_entry *saproxy_class_entry_get(const zval *object TSRMLS_DC)
        !           342: {
        !           343:        return php_com_saproxy_class_entry;
        !           344: }
        !           345: 
        !           346: static int saproxy_class_name_get(const zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
        !           347: {
        !           348:        *class_name = estrndup(php_com_saproxy_class_entry->name, php_com_saproxy_class_entry->name_length);
        !           349:        *class_name_len = php_com_saproxy_class_entry->name_length;
        !           350:        return 0;
        !           351: }
        !           352: 
        !           353: static int saproxy_objects_compare(zval *object1, zval *object2 TSRMLS_DC)
        !           354: {
        !           355:        return -1;
        !           356: }
        !           357: 
        !           358: static int saproxy_object_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC)
        !           359: {
        !           360:        return FAILURE;
        !           361: }
        !           362: 
        !           363: static int saproxy_count_elements(zval *object, long *count TSRMLS_DC)
        !           364: {
        !           365:        php_com_saproxy *proxy = SA_FETCH(object);
        !           366:        LONG ubound, lbound;
        !           367:        
        !           368:        if (!V_ISARRAY(&proxy->obj->v)) {
        !           369:                return FAILURE;
        !           370:        }
        !           371: 
        !           372:        SafeArrayGetLBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &lbound);
        !           373:        SafeArrayGetUBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &ubound);
        !           374: 
        !           375:        *count = ubound - lbound + 1;
        !           376: 
        !           377:        return SUCCESS;
        !           378: }
        !           379: 
        !           380: zend_object_handlers php_com_saproxy_handlers = {
        !           381:        ZEND_OBJECTS_STORE_HANDLERS,
        !           382:        saproxy_property_read,
        !           383:        saproxy_property_write,
        !           384:        saproxy_read_dimension,
        !           385:        saproxy_write_dimension,
        !           386:        NULL,
        !           387:        NULL, /* saproxy_object_get, */
        !           388:        NULL, /* saproxy_object_set, */
        !           389:        saproxy_property_exists,
        !           390:        saproxy_property_delete,
        !           391:        saproxy_dimension_exists,
        !           392:        saproxy_dimension_delete,
        !           393:        saproxy_properties_get,
        !           394:        saproxy_method_get,
        !           395:        saproxy_call_method,
        !           396:        saproxy_constructor_get,
        !           397:        saproxy_class_entry_get,
        !           398:        saproxy_class_name_get,
        !           399:        saproxy_objects_compare,
        !           400:        saproxy_object_cast,
        !           401:        saproxy_count_elements
        !           402: };
        !           403: 
        !           404: static void saproxy_free_storage(void *object TSRMLS_DC)
        !           405: {
        !           406:        php_com_saproxy *proxy = (php_com_saproxy *)object;
        !           407:        int i;
        !           408: 
        !           409:        for (i = 0; i < proxy->dimensions; i++) {
        !           410:                if (proxy->indices) {
        !           411:                                FREE_ZVAL(proxy->indices[i]);
        !           412:                }
        !           413:        }
        !           414: 
        !           415:        zval_ptr_dtor(&proxy->zobj);
        !           416:        efree(proxy->indices);
        !           417:        efree(proxy);
        !           418: }
        !           419: 
        !           420: static void saproxy_clone(void *object, void **clone_ptr TSRMLS_DC)
        !           421: {
        !           422:        php_com_saproxy *proxy = (php_com_saproxy *)object;
        !           423:        php_com_saproxy *cloneproxy;
        !           424: 
        !           425:        cloneproxy = emalloc(sizeof(*cloneproxy));
        !           426:        memcpy(cloneproxy, proxy, sizeof(*cloneproxy));
        !           427: 
        !           428:        Z_ADDREF_P(cloneproxy->zobj);
        !           429:        cloneproxy->indices = safe_emalloc(cloneproxy->dimensions, sizeof(zval *), 0);
        !           430:        clone_indices(cloneproxy, proxy, proxy->dimensions);
        !           431: 
        !           432:        *clone_ptr = cloneproxy;
        !           433: }
        !           434: 
        !           435: int php_com_saproxy_create(zval *com_object, zval *proxy_out, zval *index TSRMLS_DC)
        !           436: {
        !           437:        php_com_saproxy *proxy, *rel = NULL;
        !           438: 
        !           439:        proxy = ecalloc(1, sizeof(*proxy));
        !           440:        proxy->dimensions = 1;
        !           441: 
        !           442:        if (Z_OBJCE_P(com_object) == php_com_saproxy_class_entry) {
        !           443:                rel = SA_FETCH(com_object);
        !           444:                proxy->obj = rel->obj;
        !           445:                proxy->zobj = rel->zobj;
        !           446:                proxy->dimensions += rel->dimensions;
        !           447:        } else {
        !           448:                proxy->obj = CDNO_FETCH(com_object);
        !           449:                proxy->zobj = com_object;
        !           450:        }
        !           451: 
        !           452:        Z_ADDREF_P(proxy->zobj);
        !           453:        proxy->indices = safe_emalloc(proxy->dimensions, sizeof(zval *), 0);
        !           454: 
        !           455:        if (rel) {
        !           456:                clone_indices(proxy, rel, rel->dimensions);
        !           457:        }
        !           458: 
        !           459:        MAKE_STD_ZVAL(proxy->indices[proxy->dimensions-1]);
        !           460:        *proxy->indices[proxy->dimensions-1] = *index;
        !           461:        zval_copy_ctor(proxy->indices[proxy->dimensions-1]);
        !           462: 
        !           463:        Z_TYPE_P(proxy_out) = IS_OBJECT;
        !           464:        Z_OBJ_HANDLE_P(proxy_out) = zend_objects_store_put(proxy, NULL, saproxy_free_storage, saproxy_clone TSRMLS_CC);
        !           465:        Z_OBJ_HT_P(proxy_out) = &php_com_saproxy_handlers;
        !           466:        
        !           467:        return 1;
        !           468: }
        !           469: 
        !           470: /* iterator */
        !           471: 
        !           472: static void saproxy_iter_dtor(zend_object_iterator *iter TSRMLS_DC)
        !           473: {
        !           474:        php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
        !           475: 
        !           476:        zval_ptr_dtor(&I->proxy_obj);
        !           477: 
        !           478:        efree(I->indices);
        !           479:        efree(I);
        !           480: }
        !           481: 
        !           482: static int saproxy_iter_valid(zend_object_iterator *iter TSRMLS_DC)
        !           483: {
        !           484:        php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
        !           485: 
        !           486:        return (I->key < I->imax) ? SUCCESS : FAILURE;
        !           487: }
        !           488: 
        !           489: static void saproxy_iter_get_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
        !           490: {
        !           491:        php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
        !           492:        VARIANT v;
        !           493:        VARTYPE vt;
        !           494:        zval *return_value, **ptr_ptr;
        !           495:        SAFEARRAY *sa;
        !           496: 
        !           497:        I->indices[I->proxy->dimensions-1] = I->key;
        !           498:        
        !           499:        sa = V_ARRAY(&I->proxy->obj->v);
        !           500:        
        !           501:        if (FAILED(SafeArrayGetVartype(sa, &vt)) || vt == VT_EMPTY) {
        !           502:                vt = V_VT(&I->proxy->obj->v) & ~VT_ARRAY;
        !           503:        }
        !           504: 
        !           505:        VariantInit(&v);
        !           506:        if (vt == VT_VARIANT) {
        !           507:                SafeArrayGetElement(sa, I->indices, &v);
        !           508:        } else {
        !           509:                V_VT(&v) = vt;
        !           510:                SafeArrayGetElement(sa, I->indices, &v.lVal);
        !           511:        }
        !           512: 
        !           513:        MAKE_STD_ZVAL(return_value);
        !           514:        php_com_wrap_variant(return_value, &v, I->proxy->obj->code_page TSRMLS_CC);
        !           515:        VariantClear(&v);
        !           516: 
        !           517:        ptr_ptr = emalloc(sizeof(*ptr_ptr));
        !           518:        *ptr_ptr = return_value;
        !           519:        *data = ptr_ptr;
        !           520: }
        !           521: 
        !           522: static int saproxy_iter_get_key(zend_object_iterator *iter, char **str_key, uint *str_key_len,
        !           523:        ulong *int_key TSRMLS_DC)
        !           524: {
        !           525:        php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
        !           526: 
        !           527:        if (I->key == -1) {
        !           528:                return HASH_KEY_NON_EXISTANT;
        !           529:        }
        !           530:        *int_key = (ulong)I->key;
        !           531:        return HASH_KEY_IS_LONG;
        !           532: }
        !           533: 
        !           534: static int saproxy_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC)
        !           535: {
        !           536:        php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
        !           537: 
        !           538:        if (++I->key >= I->imax) {
        !           539:                I->key = -1;
        !           540:                return FAILURE;
        !           541:        }
        !           542:        return SUCCESS;
        !           543: }
        !           544: 
        !           545: static zend_object_iterator_funcs saproxy_iter_funcs = {
        !           546:        saproxy_iter_dtor,
        !           547:        saproxy_iter_valid,
        !           548:        saproxy_iter_get_data,
        !           549:        saproxy_iter_get_key,
        !           550:        saproxy_iter_move_forwards,
        !           551:        NULL
        !           552: };
        !           553: 
        !           554: 
        !           555: zend_object_iterator *php_com_saproxy_iter_get(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
        !           556: {
        !           557:        php_com_saproxy *proxy = SA_FETCH(object);
        !           558:        php_com_saproxy_iter *I;
        !           559:        int i;
        !           560: 
        !           561:        if (by_ref) {
        !           562:                zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
        !           563:        }
        !           564: 
        !           565:        I = ecalloc(1, sizeof(*I));
        !           566:        I->iter.funcs = &saproxy_iter_funcs;
        !           567:        I->iter.data = I;
        !           568: 
        !           569:        I->proxy = proxy;
        !           570:        I->proxy_obj = object;
        !           571:        Z_ADDREF_P(I->proxy_obj);
        !           572: 
        !           573:        I->indices = safe_emalloc(proxy->dimensions + 1, sizeof(LONG), 0);
        !           574:        for (i = 0; i < proxy->dimensions; i++) {
        !           575:                convert_to_long(proxy->indices[i]);
        !           576:                I->indices[i] = Z_LVAL_P(proxy->indices[i]);
        !           577:        }
        !           578: 
        !           579:        SafeArrayGetLBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &I->imin);
        !           580:        SafeArrayGetUBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &I->imax);
        !           581: 
        !           582:        I->key = I->imin;       
        !           583:        
        !           584:        return &I->iter;
        !           585: }
        !           586: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>