Annotation of embedaddon/php/ext/spl/spl_heap.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
1.1.1.3 ! misho       5:    | Copyright (c) 1997-2013 The PHP Group                                |
1.1       misho       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:    | Authors: Etienne Kneuss <colder@php.net>                             |
                     16:    +----------------------------------------------------------------------+
                     17:  */
                     18: 
1.1.1.2   misho      19: /* $Id$ */
1.1       misho      20: 
                     21: #ifdef HAVE_CONFIG_H
                     22: # include "config.h"
                     23: #endif
                     24: 
                     25: #include "php.h"
                     26: #include "zend_exceptions.h"
                     27: 
                     28: #include "php_spl.h"
                     29: #include "spl_functions.h"
                     30: #include "spl_engine.h"
                     31: #include "spl_iterators.h"
                     32: #include "spl_heap.h"
                     33: #include "spl_exceptions.h"
                     34: 
                     35: #define PTR_HEAP_BLOCK_SIZE 64
                     36: 
                     37: #define SPL_HEAP_CORRUPTED       0x00000001
                     38: 
                     39: #define SPL_PQUEUE_EXTR_MASK     0x00000003
                     40: #define SPL_PQUEUE_EXTR_BOTH     0x00000003
                     41: #define SPL_PQUEUE_EXTR_DATA     0x00000001
                     42: #define SPL_PQUEUE_EXTR_PRIORITY 0x00000002
                     43: 
                     44: zend_object_handlers spl_handler_SplHeap;
                     45: zend_object_handlers spl_handler_SplPriorityQueue;
                     46: 
                     47: PHPAPI zend_class_entry  *spl_ce_SplHeap;
                     48: PHPAPI zend_class_entry  *spl_ce_SplMaxHeap;
                     49: PHPAPI zend_class_entry  *spl_ce_SplMinHeap;
                     50: PHPAPI zend_class_entry  *spl_ce_SplPriorityQueue;
                     51: 
                     52: typedef void *spl_ptr_heap_element;
                     53: 
                     54: typedef void (*spl_ptr_heap_dtor_func)(spl_ptr_heap_element TSRMLS_DC);
                     55: typedef void (*spl_ptr_heap_ctor_func)(spl_ptr_heap_element TSRMLS_DC);
                     56: typedef int  (*spl_ptr_heap_cmp_func)(spl_ptr_heap_element, spl_ptr_heap_element, void* TSRMLS_DC);
                     57: 
                     58: typedef struct _spl_ptr_heap {
                     59:        spl_ptr_heap_element   *elements;
                     60:        spl_ptr_heap_ctor_func  ctor;
                     61:        spl_ptr_heap_dtor_func  dtor;
                     62:        spl_ptr_heap_cmp_func   cmp;
                     63:        int                     count;
                     64:        int                     max_size;
                     65:        int                     flags;
                     66: } spl_ptr_heap;
                     67: 
                     68: typedef struct _spl_heap_object spl_heap_object;
                     69: typedef struct _spl_heap_it spl_heap_it;
                     70: 
                     71: struct _spl_heap_object {
                     72:        zend_object         std;
                     73:        spl_ptr_heap       *heap;
                     74:        zval               *retval;
                     75:        int                 flags;
                     76:        zend_class_entry   *ce_get_iterator;
                     77:        zend_function      *fptr_cmp;
                     78:        zend_function      *fptr_count;
                     79:        HashTable          *debug_info;
                     80: };
                     81: 
                     82: /* define an overloaded iterator structure */
                     83: struct _spl_heap_it {
                     84:        zend_user_iterator  intern;
                     85:        int                 flags;
                     86:        spl_heap_object    *object;
                     87: };
                     88: 
                     89: /* {{{  spl_ptr_heap */
                     90: static void spl_ptr_heap_zval_dtor(spl_ptr_heap_element elem TSRMLS_DC) { /* {{{ */
                     91:        if (elem) {
                     92:                zval_ptr_dtor((zval **)&elem);
                     93:        }
                     94: }
                     95: /* }}} */
                     96: 
                     97: static void spl_ptr_heap_zval_ctor(spl_ptr_heap_element elem TSRMLS_DC) { /* {{{ */
                     98:        Z_ADDREF_P((zval *)elem);
                     99: }
                    100: /* }}} */
                    101: 
                    102: static int spl_ptr_heap_cmp_cb_helper(zval *object, spl_heap_object *heap_object, zval *a, zval *b, long *result TSRMLS_DC) { /* {{{ */
                    103:                zval *result_p = NULL;
                    104: 
                    105:                zend_call_method_with_2_params(&object, heap_object->std.ce, &heap_object->fptr_cmp, "compare", &result_p, a, b);
                    106: 
                    107:                if (EG(exception)) {
                    108:                        return FAILURE;
                    109:                }
                    110: 
                    111:                convert_to_long(result_p);
                    112:                *result = Z_LVAL_P(result_p);
                    113: 
                    114:                zval_ptr_dtor(&result_p);
                    115: 
                    116:                return SUCCESS;
                    117: }
                    118: /* }}} */
                    119: 
                    120: static zval **spl_pqueue_extract_helper(zval **value, int flags) /* {{{ */
                    121: {
                    122:        if ((flags & SPL_PQUEUE_EXTR_BOTH) == SPL_PQUEUE_EXTR_BOTH) {
                    123:                return value;
                    124:        } else if ((flags & SPL_PQUEUE_EXTR_BOTH) > 0) {
                    125: 
                    126:                if ((flags & SPL_PQUEUE_EXTR_DATA) == SPL_PQUEUE_EXTR_DATA) {
                    127:                        zval **data;
                    128:                        if (zend_hash_find(Z_ARRVAL_PP(value), "data", sizeof("data"), (void **) &data) == SUCCESS) {
                    129:                                return data;
                    130:                        }
                    131:                } else {
                    132:                        zval **priority;
                    133:                        if (zend_hash_find(Z_ARRVAL_PP(value), "priority", sizeof("priority"), (void **) &priority) == SUCCESS) {
                    134:                                return priority;
                    135:                        }
                    136:                }
                    137:        }
                    138: 
                    139:        return NULL;
                    140: }
                    141: /* }}} */
                    142: 
                    143: static int spl_ptr_heap_zval_max_cmp(spl_ptr_heap_element a, spl_ptr_heap_element b, void* object TSRMLS_DC) { /* {{{ */
                    144:        zval result;
                    145: 
                    146:        if (EG(exception)) {
                    147:                return 0;
                    148:        }
                    149: 
                    150:        if (object) {
                    151:                spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object((zval *)object TSRMLS_CC);
                    152:                if (heap_object->fptr_cmp) {
                    153:                        long lval = 0;
                    154:                        if (spl_ptr_heap_cmp_cb_helper((zval *)object, heap_object, (zval *)a, (zval *)b, &lval TSRMLS_CC) == FAILURE) {
                    155:                                /* exception or call failure */
                    156:                                return 0;
                    157:                        }
                    158:                        return lval;
                    159:                }
                    160:        }
                    161: 
                    162:        INIT_ZVAL(result);
                    163:        compare_function(&result, (zval *)a, (zval *)b TSRMLS_CC);
                    164:        return Z_LVAL(result);
                    165: }
                    166: /* }}} */
                    167: 
                    168: static int spl_ptr_heap_zval_min_cmp(spl_ptr_heap_element a, spl_ptr_heap_element b, void* object TSRMLS_DC) { /* {{{ */
                    169:        zval result;
                    170: 
                    171:        if (EG(exception)) {
                    172:                return 0;
                    173:        }
                    174: 
                    175:        if (object) {
                    176:                spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object((zval *)object TSRMLS_CC);
                    177:                if (heap_object->fptr_cmp) {
                    178:                        long lval = 0;
                    179:                        if (spl_ptr_heap_cmp_cb_helper((zval *)object, heap_object, (zval *)a, (zval *)b, &lval TSRMLS_CC) == FAILURE) {
                    180:                                /* exception or call failure */
                    181:                                return 0;
                    182:                        }
                    183:                        return lval;
                    184:                }
                    185:        }
                    186: 
                    187:        INIT_ZVAL(result);
                    188:        compare_function(&result, (zval *)b, (zval *)a TSRMLS_CC);
                    189:        return Z_LVAL(result);
                    190: }
                    191: /* }}} */
                    192: 
                    193: static int spl_ptr_pqueue_zval_cmp(spl_ptr_heap_element a, spl_ptr_heap_element b, void* object TSRMLS_DC) { /* {{{ */
                    194:        zval result;
                    195:        zval **a_priority_pp = spl_pqueue_extract_helper((zval **)&a, SPL_PQUEUE_EXTR_PRIORITY);
                    196:        zval **b_priority_pp = spl_pqueue_extract_helper((zval **)&b, SPL_PQUEUE_EXTR_PRIORITY);
                    197: 
                    198:        if ((!a_priority_pp) || (!b_priority_pp)) {
                    199:                zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node");
                    200:                return 0;
                    201:        }
                    202:        if (EG(exception)) {
                    203:                return 0;
                    204:        }
                    205: 
                    206:        if (object) {
                    207:                spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object(object TSRMLS_CC);
                    208:                if (heap_object->fptr_cmp) {
                    209:                        long lval = 0;
                    210:                        if (spl_ptr_heap_cmp_cb_helper((zval *)object, heap_object, *a_priority_pp, *b_priority_pp, &lval TSRMLS_CC) == FAILURE) {
                    211:                                /* exception or call failure */
                    212:                                return 0;
                    213:                        }
                    214:                        return lval;
                    215:                }
                    216:        }
                    217: 
                    218:        INIT_ZVAL(result);
                    219:        compare_function(&result, *a_priority_pp, *b_priority_pp TSRMLS_CC);
                    220:        return Z_LVAL(result);
                    221: }
                    222: /* }}} */
                    223: 
                    224: static spl_ptr_heap *spl_ptr_heap_init(spl_ptr_heap_cmp_func cmp, spl_ptr_heap_ctor_func ctor, spl_ptr_heap_dtor_func dtor) /* {{{ */
                    225: {
                    226:        spl_ptr_heap *heap = emalloc(sizeof(spl_ptr_heap));
                    227: 
                    228:        heap->dtor     = dtor;
                    229:        heap->ctor     = ctor;
                    230:        heap->cmp      = cmp;
                    231:        heap->elements = safe_emalloc(sizeof(spl_ptr_heap_element), PTR_HEAP_BLOCK_SIZE, 0);
                    232:        heap->max_size = PTR_HEAP_BLOCK_SIZE;
                    233:        heap->count    = 0;
                    234:        heap->flags    = 0;
                    235: 
                    236:        return heap;
                    237: }
                    238: /* }}} */
                    239: 
                    240: static void spl_ptr_heap_insert(spl_ptr_heap *heap, spl_ptr_heap_element elem, void *cmp_userdata TSRMLS_DC) { /* {{{ */
                    241:        int i;
                    242: 
                    243:        if (heap->count+1 > heap->max_size) {
                    244:                /* we need to allocate more memory */
                    245:                heap->elements  = (void **) safe_erealloc(heap->elements, sizeof(spl_ptr_heap_element), (heap->max_size), (sizeof(spl_ptr_heap_element) * (heap->max_size)));
                    246:                heap->max_size *= 2;
                    247:        }
                    248: 
                    249:        heap->ctor(elem TSRMLS_CC);
                    250: 
                    251:        /* sifting up */
                    252:        for(i = heap->count++; i > 0 && heap->cmp(heap->elements[(i-1)/2], elem, cmp_userdata TSRMLS_CC) < 0; i = (i-1)/2) {
                    253:                heap->elements[i] = heap->elements[(i-1)/2];
                    254:        }
                    255: 
                    256:        if (EG(exception)) {
                    257:                /* exception thrown during comparison */
                    258:                heap->flags |= SPL_HEAP_CORRUPTED;
                    259:        }
                    260: 
                    261:        heap->elements[i] = elem;
                    262: 
                    263: }
                    264: /* }}} */
                    265: 
                    266: static spl_ptr_heap_element spl_ptr_heap_top(spl_ptr_heap *heap) { /* {{{ */
                    267:        if (heap->count == 0) {
                    268:                return NULL;
                    269:        }
                    270: 
                    271:        return heap->elements[0];
                    272: }
                    273: /* }}} */
                    274: 
                    275: static spl_ptr_heap_element spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *cmp_userdata TSRMLS_DC) { /* {{{ */
                    276:        int i, j;
                    277:        const int limit = (heap->count-1)/2;
                    278:        spl_ptr_heap_element top;
                    279:        spl_ptr_heap_element bottom;
                    280: 
                    281:        if (heap->count == 0) {
                    282:                return NULL;
                    283:        }
                    284: 
                    285:        top    = heap->elements[0];
                    286:        bottom = heap->elements[--heap->count];
                    287: 
                    288:        for( i = 0; i < limit; i = j)
                    289:        {
                    290:                /* Find smaller child */
                    291:                j = i*2+1;
                    292:                if(j != heap->count && heap->cmp(heap->elements[j+1], heap->elements[j], cmp_userdata TSRMLS_CC) > 0) {
                    293:                        j++; /* next child is bigger */
                    294:                }
                    295: 
                    296:                /* swap elements between two levels */
                    297:                if(heap->cmp(bottom, heap->elements[j], cmp_userdata TSRMLS_CC) < 0) {
                    298:                        heap->elements[i] = heap->elements[j];
                    299:                } else {
                    300:                        break;
                    301:                }
                    302:        }
                    303: 
                    304:        if (EG(exception)) {
                    305:                /* exception thrown during comparison */
                    306:                heap->flags |= SPL_HEAP_CORRUPTED;
                    307:        }
                    308: 
                    309:        heap->elements[i] = bottom;
                    310:        heap->dtor(top TSRMLS_CC);
                    311:        return top;
                    312: }
                    313: /* }}} */
                    314: 
                    315: static spl_ptr_heap *spl_ptr_heap_clone(spl_ptr_heap *from TSRMLS_DC) { /* {{{ */
                    316:        int i;
                    317: 
                    318:        spl_ptr_heap *heap = emalloc(sizeof(spl_ptr_heap));
                    319: 
                    320:        heap->dtor     = from->dtor;
                    321:        heap->ctor     = from->ctor;
                    322:        heap->cmp      = from->cmp;
                    323:        heap->max_size = from->max_size;
                    324:        heap->count    = from->count;
                    325:        heap->flags    = from->flags;
                    326: 
                    327:        heap->elements = safe_emalloc(sizeof(spl_ptr_heap_element),from->max_size,0);
                    328:        memcpy(heap->elements, from->elements, sizeof(spl_ptr_heap_element)*from->max_size);
                    329: 
                    330:        for (i=0; i < heap->count; ++i) {
                    331:                heap->ctor(heap->elements[i] TSRMLS_CC);
                    332:        }
                    333: 
                    334:        return heap;
                    335: }
                    336: /* }}} */
                    337: 
                    338: static void spl_ptr_heap_destroy(spl_ptr_heap *heap TSRMLS_DC) { /* {{{ */
                    339:        int i;
                    340: 
                    341:        for (i=0; i < heap->count; ++i) {
                    342:                heap->dtor(heap->elements[i] TSRMLS_CC);
                    343:        }
                    344: 
                    345:        efree(heap->elements);
                    346:        efree(heap);
                    347: }
                    348: /* }}} */
                    349: 
                    350: static int spl_ptr_heap_count(spl_ptr_heap *heap) { /* {{{ */
                    351:        return heap->count;
                    352: }
                    353: /* }}} */
                    354: /* }}} */
                    355: 
                    356: zend_object_iterator *spl_heap_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC);
                    357: 
                    358: static void spl_heap_object_free_storage(void *object TSRMLS_DC) /* {{{ */
                    359: {
                    360:        int i;
                    361:        spl_heap_object *intern = (spl_heap_object *)object;
                    362: 
                    363:        zend_object_std_dtor(&intern->std TSRMLS_CC);
                    364: 
                    365:        for (i = 0; i < intern->heap->count; ++i) {
                    366:                if (intern->heap->elements[i]) {
                    367:                        zval_ptr_dtor((zval **)&intern->heap->elements[i]);
                    368:                }
                    369:        }
                    370: 
                    371:        spl_ptr_heap_destroy(intern->heap TSRMLS_CC);
                    372: 
                    373:        zval_ptr_dtor(&intern->retval);
                    374: 
                    375:        if (intern->debug_info != NULL) {
                    376:                zend_hash_destroy(intern->debug_info);
                    377:                efree(intern->debug_info);
                    378:        }
                    379: 
                    380:        efree(object);
                    381: }
                    382: /* }}} */
                    383: 
                    384: static zend_object_value spl_heap_object_new_ex(zend_class_entry *class_type, spl_heap_object **obj, zval *orig, int clone_orig TSRMLS_DC) /* {{{ */
                    385: {
                    386:        zend_object_value  retval;
                    387:        spl_heap_object   *intern;
                    388:        zend_class_entry  *parent = class_type;
                    389:        int                inherited = 0;
                    390: 
                    391:        intern = ecalloc(1, sizeof(spl_heap_object));
                    392:        *obj = intern;
                    393:        ALLOC_INIT_ZVAL(intern->retval);
                    394: 
                    395:        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
1.1.1.2   misho     396:        object_properties_init(&intern->std, class_type);
1.1       misho     397: 
                    398:        intern->flags      = 0;
                    399:        intern->fptr_cmp   = NULL;
                    400:        intern->debug_info = NULL;
                    401: 
                    402:        if (orig) {
                    403:                spl_heap_object *other = (spl_heap_object*)zend_object_store_get_object(orig TSRMLS_CC);
                    404:                intern->ce_get_iterator = other->ce_get_iterator;
                    405: 
                    406:                if (clone_orig) {
                    407:                        int i;
                    408:                        intern->heap = spl_ptr_heap_clone(other->heap TSRMLS_CC);
                    409:                        for (i = 0; i < intern->heap->count; ++i) {
                    410:                                if (intern->heap->elements[i]) {
                    411:                                        Z_ADDREF_P((zval *)intern->heap->elements[i]);
                    412:                                }
                    413:                        }
                    414:                } else {
                    415:                        intern->heap = other->heap;
                    416:                }
                    417: 
                    418:                intern->flags = other->flags;
                    419:        } else {
                    420:                intern->heap = spl_ptr_heap_init(spl_ptr_heap_zval_max_cmp, spl_ptr_heap_zval_ctor, spl_ptr_heap_zval_dtor);
                    421:        }
                    422: 
                    423:        retval.handlers = &spl_handler_SplHeap;
                    424: 
                    425:        while (parent) {
                    426:                if (parent == spl_ce_SplPriorityQueue) {
                    427:                        intern->heap->cmp = spl_ptr_pqueue_zval_cmp;
                    428:                        intern->flags     = SPL_PQUEUE_EXTR_DATA;
                    429:                        retval.handlers   = &spl_handler_SplPriorityQueue;
                    430:                        break;
                    431:                }
                    432: 
                    433:                if (parent == spl_ce_SplMinHeap) {
                    434:                        intern->heap->cmp = spl_ptr_heap_zval_min_cmp;
                    435:                        break;
                    436:                }
                    437: 
                    438:                if (parent == spl_ce_SplMaxHeap) {
                    439:                        intern->heap->cmp = spl_ptr_heap_zval_max_cmp;
                    440:                        break;
                    441:                }
                    442: 
                    443:                if (parent == spl_ce_SplHeap) {
                    444:                        break;
                    445:                }
                    446: 
                    447:                parent = parent->parent;
                    448:                inherited = 1;
                    449:        }
                    450: 
                    451:        retval.handle   = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, spl_heap_object_free_storage, NULL TSRMLS_CC);
                    452: 
                    453:        if (!parent) { /* this must never happen */
                    454:                php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplHeap");
                    455:        }
                    456: 
                    457:        if (inherited) {
                    458:                zend_hash_find(&class_type->function_table, "compare",    sizeof("compare"),    (void **) &intern->fptr_cmp);
                    459:                if (intern->fptr_cmp->common.scope == parent) {
                    460:                        intern->fptr_cmp = NULL;
                    461:                }
                    462:                zend_hash_find(&class_type->function_table, "count",        sizeof("count"),        (void **) &intern->fptr_count);
                    463:                if (intern->fptr_count->common.scope == parent) {
                    464:                        intern->fptr_count = NULL;
                    465:                }
                    466:        }
                    467: 
                    468:        return retval;
                    469: }
                    470: /* }}} */
                    471: 
                    472: static zend_object_value spl_heap_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
                    473: {
                    474:        spl_heap_object *tmp;
                    475:        return spl_heap_object_new_ex(class_type, &tmp, NULL, 0 TSRMLS_CC);
                    476: }
                    477: /* }}} */
                    478: 
                    479: static zend_object_value spl_heap_object_clone(zval *zobject TSRMLS_DC) /* {{{ */
                    480: {
                    481:        zend_object_value   new_obj_val;
                    482:        zend_object        *old_object;
                    483:        zend_object        *new_object;
                    484:        zend_object_handle  handle = Z_OBJ_HANDLE_P(zobject);
                    485:        spl_heap_object    *intern;
                    486: 
                    487:        old_object  = zend_objects_get_address(zobject TSRMLS_CC);
                    488:        new_obj_val = spl_heap_object_new_ex(old_object->ce, &intern, zobject, 1 TSRMLS_CC);
                    489:        new_object  = &intern->std;
                    490: 
                    491:        zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
                    492: 
                    493:        return new_obj_val;
                    494: }
                    495: /* }}} */
                    496: 
                    497: static int spl_heap_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
                    498: {
                    499:        spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(object TSRMLS_CC);
                    500: 
                    501:        if (intern->fptr_count) {
                    502:                zval *rv;
                    503:                zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_count, "count", &rv);
                    504:                if (rv) {
                    505:                        zval_ptr_dtor(&intern->retval);
                    506:                        MAKE_STD_ZVAL(intern->retval);
                    507:                        ZVAL_ZVAL(intern->retval, rv, 1, 1);
                    508:                        convert_to_long(intern->retval);
                    509:                        *count = (long) Z_LVAL_P(intern->retval);
                    510:                        return SUCCESS;
                    511:                }
                    512:                *count = 0;
                    513:                return FAILURE;
                    514:        }
                    515:        
                    516:        *count = spl_ptr_heap_count(intern->heap);
                    517: 
                    518:        return SUCCESS;
                    519: } 
                    520: /* }}} */
                    521: 
                    522: static HashTable* spl_heap_object_get_debug_info_helper(zend_class_entry *ce, zval *obj, int *is_temp TSRMLS_DC) { /* {{{ */
                    523:        spl_heap_object *intern  = (spl_heap_object*)zend_object_store_get_object(obj TSRMLS_CC);
                    524:        zval *tmp, zrv, *heap_array;
                    525:        char *pnstr;
                    526:        int  pnlen;
                    527:        int  i;
                    528: 
                    529:        *is_temp = 0;
                    530: 
1.1.1.2   misho     531:        if (!intern->std.properties) {
                    532:                rebuild_object_properties(&intern->std);
                    533:        }
                    534: 
1.1       misho     535:        if (intern->debug_info == NULL) {
                    536:                ALLOC_HASHTABLE(intern->debug_info);
                    537:                ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
                    538:        }
                    539: 
                    540:        if (intern->debug_info->nApplyCount == 0) {
                    541:                INIT_PZVAL(&zrv);
                    542:                Z_ARRVAL(zrv) = intern->debug_info;
                    543: 
                    544:                zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
                    545: 
                    546:                pnstr = spl_gen_private_prop_name(ce, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
                    547:                add_assoc_long_ex(&zrv, pnstr, pnlen+1, intern->flags);
                    548:                efree(pnstr);
                    549: 
                    550:                pnstr = spl_gen_private_prop_name(ce, "isCorrupted", sizeof("isCorrupted")-1, &pnlen TSRMLS_CC);
                    551:                add_assoc_bool_ex(&zrv, pnstr, pnlen+1, intern->heap->flags&SPL_HEAP_CORRUPTED);
                    552:                efree(pnstr);
                    553: 
                    554:                ALLOC_INIT_ZVAL(heap_array);
                    555:                array_init(heap_array);
                    556: 
                    557:                for (i = 0; i < intern->heap->count; ++i) {
                    558:                        add_index_zval(heap_array, i, (zval *)intern->heap->elements[i]);
                    559:                        Z_ADDREF_P(intern->heap->elements[i]);
                    560:                }
                    561: 
                    562:                pnstr = spl_gen_private_prop_name(ce, "heap", sizeof("heap")-1, &pnlen TSRMLS_CC);
                    563:                add_assoc_zval_ex(&zrv, pnstr, pnlen+1, heap_array);
                    564:                efree(pnstr);
                    565:        }
                    566: 
                    567:        return intern->debug_info;
                    568: }
                    569: /* }}} */
                    570: 
                    571: static HashTable* spl_heap_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */
                    572: {
                    573:        return spl_heap_object_get_debug_info_helper(spl_ce_SplHeap, obj, is_temp TSRMLS_CC);
                    574: }
                    575: /* }}} */
                    576: 
                    577: static HashTable* spl_pqueue_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */
                    578: {
                    579:        return spl_heap_object_get_debug_info_helper(spl_ce_SplPriorityQueue, obj, is_temp TSRMLS_CC);
                    580: }
                    581: /* }}} */
                    582: 
                    583: /* {{{ proto int SplHeap::count() U
                    584:  Return the number of elements in the heap. */
                    585: SPL_METHOD(SplHeap, count)
                    586: {
                    587:        long count;
                    588:        spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                    589: 
                    590:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
                    591:                return;
                    592:        }
                    593: 
                    594:        count = spl_ptr_heap_count(intern->heap);
                    595:        RETURN_LONG(count);
                    596: }
                    597: /* }}} */
                    598: 
                    599: /* {{{ proto int SplHeap::isEmpty() U
                    600:  Return true if the heap is empty. */
                    601: SPL_METHOD(SplHeap, isEmpty)
                    602: {
                    603:        spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                    604: 
                    605:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
                    606:                return;
                    607:        }
                    608: 
                    609:        RETURN_BOOL(spl_ptr_heap_count(intern->heap)==0);
                    610: }
                    611: /* }}} */
                    612: 
                    613: /* {{{ proto bool SplHeap::insert(mixed $value) U
                    614:           Push $value on the heap */
                    615: SPL_METHOD(SplHeap, insert)
                    616: {
                    617:        zval *value;
                    618:        spl_heap_object *intern;
                    619: 
                    620:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
                    621:                return;
                    622:        }
                    623: 
                    624:        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                    625: 
                    626:        if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
                    627:                zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
                    628:                return;
                    629:        }
                    630: 
                    631:        SEPARATE_ARG_IF_REF(value);
                    632: 
                    633:        spl_ptr_heap_insert(intern->heap, value, getThis() TSRMLS_CC);
                    634: 
                    635:        RETURN_TRUE;
                    636: } 
                    637: /* }}} */
                    638: 
                    639: /* {{{ proto mixed SplHeap::extract() U
                    640:           extract the element out of the top of the heap */
                    641: SPL_METHOD(SplHeap, extract)
                    642: {
                    643:        zval *value;
                    644:        spl_heap_object *intern;
                    645: 
                    646:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
                    647:                return;
                    648:        }
                    649: 
                    650:        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                    651: 
                    652:        if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
                    653:                zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
                    654:                return;
                    655:        }
                    656: 
                    657:        value  = (zval *)spl_ptr_heap_delete_top(intern->heap, getThis() TSRMLS_CC);
                    658: 
                    659:        if (!value) {
                    660:                zend_throw_exception(spl_ce_RuntimeException, "Can't extract from an empty heap", 0 TSRMLS_CC);
                    661:                return;
                    662:        }
                    663: 
                    664:        RETURN_ZVAL(value, 1, 1);
                    665: } 
                    666: /* }}} */
                    667: 
                    668: /* {{{ proto bool SplPriorityQueue::insert(mixed $value, mixed $priority) U
                    669:           Push $value with the priority $priodiry on the priorityqueue */
                    670: SPL_METHOD(SplPriorityQueue, insert)
                    671: {
                    672:        zval *data, *priority, *elem;
                    673:        spl_heap_object *intern;
                    674: 
                    675:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &data, &priority) == FAILURE) {
                    676:                return;
                    677:        }
                    678: 
                    679:        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                    680: 
                    681:        if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
                    682:                zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
                    683:                return;
                    684:        }
                    685: 
                    686:        SEPARATE_ARG_IF_REF(data);
                    687:        SEPARATE_ARG_IF_REF(priority);
                    688: 
                    689:        ALLOC_INIT_ZVAL(elem);
                    690: 
                    691:        array_init(elem);
                    692:        add_assoc_zval_ex(elem, "data",     sizeof("data"),     data);
                    693:        add_assoc_zval_ex(elem, "priority", sizeof("priority"), priority);
                    694: 
                    695:        spl_ptr_heap_insert(intern->heap, elem, getThis() TSRMLS_CC);
                    696: 
                    697:        RETURN_TRUE;
                    698: } 
                    699: /* }}} */
                    700: 
                    701: /* {{{ proto mixed SplPriorityQueue::extract() U
                    702:           extract the element out of the top of the priority queue */
                    703: SPL_METHOD(SplPriorityQueue, extract)
                    704: {
                    705:        zval *value, *value_out, **value_out_pp;
                    706:        spl_heap_object *intern;
                    707: 
                    708:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
                    709:                return;
                    710:        }
                    711: 
                    712:        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                    713: 
                    714:        if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
                    715:                zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
                    716:                return;
                    717:        }
                    718: 
                    719:        value  = (zval *)spl_ptr_heap_delete_top(intern->heap, getThis() TSRMLS_CC);
                    720: 
                    721:        if (!value) {
                    722:                zend_throw_exception(spl_ce_RuntimeException, "Can't extract from an empty heap", 0 TSRMLS_CC);
                    723:                return;
                    724:        }
                    725: 
                    726:        value_out_pp = spl_pqueue_extract_helper(&value, intern->flags);
                    727: 
                    728: 
                    729:        if (!value_out_pp) {
                    730:                zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node");
                    731:                zval_ptr_dtor(&value);
                    732:                return;
                    733:        }
                    734: 
                    735:        value_out = *value_out_pp;
                    736: 
                    737:        Z_ADDREF_P(value_out);
                    738:        zval_ptr_dtor(&value);
                    739: 
                    740:        RETURN_ZVAL(value_out, 1, 1);
                    741: } 
                    742: /* }}} */
                    743: 
                    744: /* {{{ proto mixed SplPriorityQueue::top() U
                    745:           Peek at the top element of the priority queue */
                    746: SPL_METHOD(SplPriorityQueue, top)
                    747: {
                    748:        zval *value, **value_out;
                    749:        spl_heap_object *intern;
                    750: 
                    751:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
                    752:                return;
                    753:        }
                    754: 
                    755:        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                    756: 
                    757:        if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
                    758:                zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
                    759:                return;
                    760:        }
                    761: 
                    762:        value  = (zval *)spl_ptr_heap_top(intern->heap);
                    763: 
                    764:        if (!value) {
                    765:                zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty heap", 0 TSRMLS_CC);
                    766:                return;
                    767:        }
                    768: 
                    769:        value_out = spl_pqueue_extract_helper(&value, intern->flags);
                    770: 
                    771:        if (!value_out) {
                    772:                zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node");
                    773:                return;
                    774:        }
                    775: 
                    776:        RETURN_ZVAL(*value_out, 1, 0);
                    777: }
                    778: /* }}} */
                    779: 
                    780: /* {{{ proto int SplPriorityQueue::setIteratorMode($flags) U
                    781:  Set the flags of extraction*/
                    782: SPL_METHOD(SplPriorityQueue, setExtractFlags)
                    783: {
                    784:        long value;
                    785:        spl_heap_object *intern;
                    786: 
                    787:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) == FAILURE) {
                    788:                return;
                    789:        }
                    790: 
                    791:        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                    792: 
                    793:        intern->flags = value & SPL_PQUEUE_EXTR_MASK;
                    794: 
                    795:        RETURN_LONG(intern->flags);
                    796: }
                    797: /* }}} */
                    798: 
                    799: /* {{{ proto int SplHeap::recoverFromCorruption() U
                    800:  Recover from a corrupted state*/
                    801: SPL_METHOD(SplHeap, recoverFromCorruption)
                    802: {
                    803:        spl_heap_object *intern;
                    804: 
                    805:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
                    806:                return;
                    807:        }
                    808: 
                    809:        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                    810: 
                    811:        intern->heap->flags = intern->heap->flags & ~SPL_HEAP_CORRUPTED;
                    812: 
                    813:        RETURN_TRUE;
                    814: }
                    815: /* }}} */
                    816: 
                    817: /* {{{ proto bool SplPriorityQueue::compare(mixed $a, mixed $b) U
                    818:           compare the priorities */
                    819: SPL_METHOD(SplPriorityQueue, compare)
                    820: {
                    821:        zval *a, *b;
                    822: 
                    823:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a, &b) == FAILURE) {
                    824:                return;
                    825:        }
                    826: 
                    827:        RETURN_LONG(spl_ptr_heap_zval_max_cmp(a, b, NULL TSRMLS_CC));
                    828: } 
                    829: /* }}} */
                    830: 
                    831: /* {{{ proto mixed SplHeap::top() U
                    832:           Peek at the top element of the heap */
                    833: SPL_METHOD(SplHeap, top)
                    834: {
                    835:        zval *value;
                    836:        spl_heap_object *intern;
                    837: 
                    838:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
                    839:                return;
                    840:        }
                    841: 
                    842:        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                    843: 
                    844:        if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
                    845:                zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
                    846:                return;
                    847:        }
                    848: 
                    849:        value  = (zval *)spl_ptr_heap_top(intern->heap);
                    850: 
                    851:        if (!value) {
                    852:                zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty heap", 0 TSRMLS_CC);
                    853:                return;
                    854:        }
                    855: 
                    856:        RETURN_ZVAL(value, 1, 0);
                    857: }
                    858: /* }}} */
                    859: 
                    860: /* {{{ proto bool SplMinHeap::compare(mixed $a, mixed $b) U
                    861:           compare the values */
                    862: SPL_METHOD(SplMinHeap, compare)
                    863: {
                    864:        zval *a, *b;
                    865: 
                    866:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a, &b) == FAILURE) {
                    867:                return;
                    868:        }
                    869: 
                    870:        RETURN_LONG(spl_ptr_heap_zval_min_cmp(a, b, NULL TSRMLS_CC));
                    871: } 
                    872: /* }}} */
                    873: 
                    874: /* {{{ proto bool SplMaxHeap::compare(mixed $a, mixed $b) U
                    875:           compare the values */
                    876: SPL_METHOD(SplMaxHeap, compare)
                    877: {
                    878:        zval *a, *b;
                    879: 
                    880:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a, &b) == FAILURE) {
                    881:                return;
                    882:        }
                    883: 
                    884:        RETURN_LONG(spl_ptr_heap_zval_max_cmp(a, b, NULL TSRMLS_CC));
                    885: } 
                    886: /* }}} */
                    887: 
                    888: static void spl_heap_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
                    889: {
                    890:        spl_heap_it *iterator = (spl_heap_it *)iter;
                    891: 
                    892:        zend_user_it_invalidate_current(iter TSRMLS_CC);
                    893:        zval_ptr_dtor((zval**)&iterator->intern.it.data);
                    894: 
                    895:        efree(iterator);
                    896: }
                    897: /* }}} */
                    898: 
                    899: static void spl_heap_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
                    900: {
                    901:        /* do nothing, the iterator always points to the top element */
                    902: }
                    903: /* }}} */
                    904: 
                    905: static int spl_heap_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
                    906: {
                    907:        spl_heap_it         *iterator = (spl_heap_it *)iter;
                    908: 
                    909:        return (iterator->object->heap->count != 0 ? SUCCESS : FAILURE);
                    910: }
                    911: /* }}} */
                    912: 
                    913: static void spl_heap_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
                    914: {
                    915:        spl_heap_it  *iterator = (spl_heap_it *)iter;
                    916:        zval        **element  = (zval **)&iterator->object->heap->elements[0];
                    917: 
                    918:        if (iterator->object->heap->flags & SPL_HEAP_CORRUPTED) {
                    919:                zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
                    920:                return;
                    921:        }
                    922: 
                    923:        if (iterator->object->heap->count == 0 || !*element) {
                    924:                *data = NULL;
                    925:        } else {
                    926:                *data = element;
                    927:        }
                    928: }
                    929: /* }}} */
                    930: 
                    931: static void spl_pqueue_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
                    932: {
                    933:        spl_heap_it  *iterator = (spl_heap_it *)iter;
                    934:        zval        **element  = (zval **)&iterator->object->heap->elements[0];
                    935: 
                    936:        if (iterator->object->heap->flags & SPL_HEAP_CORRUPTED) {
                    937:                zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
                    938:                return;
                    939:        }
                    940: 
                    941:        if (iterator->object->heap->count == 0 || !*element) {
                    942:                *data = NULL;
                    943:        } else {
                    944:                *data = spl_pqueue_extract_helper(element, iterator->object->flags);
                    945:                if (!*data) {
                    946:                        zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node");
                    947:                }
                    948:        }
                    949: }
                    950: /* }}} */
                    951: 
                    952: static int spl_heap_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
                    953: {
                    954:        spl_heap_it *iterator = (spl_heap_it *)iter;
                    955: 
1.1.1.3 ! misho     956:        *int_key = (ulong) iterator->object->heap->count - 1;
1.1       misho     957:        return HASH_KEY_IS_LONG;
                    958: }
                    959: /* }}} */
                    960: 
                    961: static void spl_heap_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
                    962: {
                    963:        zval                 *object   = (zval*)((zend_user_iterator *)iter)->it.data;
                    964:        spl_heap_it          *iterator = (spl_heap_it *)iter;
                    965:        spl_ptr_heap_element elem;
                    966: 
                    967:        if (iterator->object->heap->flags & SPL_HEAP_CORRUPTED) {
                    968:                zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
                    969:                return;
                    970:        }
                    971: 
                    972:        elem = spl_ptr_heap_delete_top(iterator->object->heap, object TSRMLS_CC);
                    973: 
                    974:        if (elem != NULL) {
                    975:                zval_ptr_dtor((zval **)&elem);
                    976:        }
                    977: 
                    978:        zend_user_it_invalidate_current(iter TSRMLS_CC);
                    979: }
                    980: /* }}} */
                    981: 
                    982: /* {{{  proto int SplHeap::key() U
                    983:    Return current array key */
                    984: SPL_METHOD(SplHeap, key)
                    985: {
                    986:        spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                    987:        
                    988:        if (zend_parse_parameters_none() == FAILURE) {
                    989:                return;
                    990:        }               
                    991:        
                    992:        RETURN_LONG(intern->heap->count - 1);
                    993: }
                    994: /* }}} */
                    995: 
                    996: /* {{{ proto void SplHeap::next() U
                    997:    Move to next entry */
                    998: SPL_METHOD(SplHeap, next)
                    999: {
                   1000:        spl_heap_object      *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                   1001:        spl_ptr_heap_element  elem   = spl_ptr_heap_delete_top(intern->heap, getThis() TSRMLS_CC);
                   1002:        
                   1003:        if (zend_parse_parameters_none() == FAILURE) {
                   1004:                return;
                   1005:        }
                   1006: 
                   1007:        if (elem != NULL) {
                   1008:                zval_ptr_dtor((zval **)&elem);
                   1009:        }
                   1010: }
                   1011: /* }}} */
                   1012: 
                   1013: /* {{{ proto bool SplHeap::valid() U
                   1014:    Check whether the datastructure contains more entries */
                   1015: SPL_METHOD(SplHeap, valid)
                   1016: {
                   1017:        spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                   1018:        
                   1019:        if (zend_parse_parameters_none() == FAILURE) {
                   1020:                return;
                   1021:        }
                   1022: 
                   1023:        RETURN_BOOL(intern->heap->count != 0);
                   1024: }
                   1025: /* }}} */
                   1026: 
                   1027: /* {{{ proto void SplHeap::rewind() U
                   1028:    Rewind the datastructure back to the start */
                   1029: SPL_METHOD(SplHeap, rewind)
                   1030: {
                   1031:        if (zend_parse_parameters_none() == FAILURE) {
                   1032:                return;
                   1033:        }
                   1034:        /* do nothing, the iterator always points to the top element */
                   1035: }
                   1036: /* }}} */
                   1037: 
                   1038: /* {{{ proto mixed|NULL SplHeap::current() U
                   1039:    Return current datastructure entry */
                   1040: SPL_METHOD(SplHeap, current)
                   1041: {
                   1042:        spl_heap_object *intern  = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                   1043:        zval            *element = (zval *)intern->heap->elements[0];
                   1044:        
                   1045:        if (zend_parse_parameters_none() == FAILURE) {
                   1046:                return;
                   1047:        }
                   1048: 
                   1049:        if (!intern->heap->count || !element) {
                   1050:                RETURN_NULL();
                   1051:        } else {
                   1052:                RETURN_ZVAL(element, 1, 0);
                   1053:        }
                   1054: }
                   1055: /* }}} */
                   1056: 
                   1057: /* {{{ proto mixed|NULL SplPriorityQueue::current() U
                   1058:    Return current datastructure entry */
                   1059: SPL_METHOD(SplPriorityQueue, current)
                   1060: {
                   1061:        spl_heap_object  *intern  = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                   1062:        zval            **element = (zval **)&intern->heap->elements[0];
                   1063:        
                   1064:        if (zend_parse_parameters_none() == FAILURE) {
                   1065:                return;
                   1066:        }
                   1067: 
                   1068:        if (!intern->heap->count || !*element) {
                   1069:                RETURN_NULL();
                   1070:        } else {
                   1071:                zval **data = spl_pqueue_extract_helper(element, intern->flags);
                   1072: 
                   1073:                if (!data) {
                   1074:                        zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node");
                   1075:                        RETURN_NULL();
                   1076:                }
                   1077: 
                   1078:                RETURN_ZVAL(*data, 1, 0);
                   1079:        }
                   1080: }
                   1081: /* }}} */
                   1082: 
                   1083: /* iterator handler table */
                   1084: zend_object_iterator_funcs spl_heap_it_funcs = {
                   1085:        spl_heap_it_dtor,
                   1086:        spl_heap_it_valid,
                   1087:        spl_heap_it_get_current_data,
                   1088:        spl_heap_it_get_current_key,
                   1089:        spl_heap_it_move_forward,
                   1090:        spl_heap_it_rewind
                   1091: };
                   1092: 
                   1093: zend_object_iterator_funcs spl_pqueue_it_funcs = {
                   1094:        spl_heap_it_dtor,
                   1095:        spl_heap_it_valid,
                   1096:        spl_pqueue_it_get_current_data,
                   1097:        spl_heap_it_get_current_key,
                   1098:        spl_heap_it_move_forward,
                   1099:        spl_heap_it_rewind
                   1100: };
                   1101: 
                   1102: zend_object_iterator *spl_heap_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
                   1103: {
                   1104:        spl_heap_it     *iterator;
                   1105:        spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object(object TSRMLS_CC);
                   1106: 
                   1107:        if (by_ref) {
                   1108:                zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC);
                   1109:                return NULL;
                   1110:        }
                   1111: 
                   1112:        Z_ADDREF_P(object);
                   1113: 
                   1114:        iterator                  = emalloc(sizeof(spl_heap_it));
                   1115:        iterator->intern.it.data  = (void*)object;
                   1116:        iterator->intern.it.funcs = &spl_heap_it_funcs;
                   1117:        iterator->intern.ce       = ce;
                   1118:        iterator->intern.value    = NULL;
                   1119:        iterator->flags           = heap_object->flags;
                   1120:        iterator->object          = heap_object;
                   1121: 
                   1122:        return (zend_object_iterator*)iterator;
                   1123: }
                   1124: /* }}} */
                   1125: 
                   1126: zend_object_iterator *spl_pqueue_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
                   1127: {
                   1128:        spl_heap_it     *iterator;
                   1129:        spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object(object TSRMLS_CC);
                   1130: 
                   1131:        if (by_ref) {
                   1132:                zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC);
                   1133:                return NULL;
                   1134:        }
                   1135: 
                   1136:        Z_ADDREF_P(object);
                   1137: 
                   1138:        iterator                  = emalloc(sizeof(spl_heap_it));
                   1139:        iterator->intern.it.data  = (void*)object;
                   1140:        iterator->intern.it.funcs = &spl_pqueue_it_funcs;
                   1141:        iterator->intern.ce       = ce;
                   1142:        iterator->intern.value    = NULL;
                   1143:        iterator->flags           = heap_object->flags;
                   1144:        iterator->object          = heap_object;
                   1145: 
                   1146:        return (zend_object_iterator*)iterator;
                   1147: }
                   1148: /* }}} */
                   1149: 
                   1150: ZEND_BEGIN_ARG_INFO(arginfo_heap_insert, 0)
                   1151:        ZEND_ARG_INFO(0, value)
                   1152: ZEND_END_ARG_INFO()
                   1153: 
                   1154: ZEND_BEGIN_ARG_INFO(arginfo_heap_compare, 0)
                   1155:        ZEND_ARG_INFO(0, a)
                   1156:        ZEND_ARG_INFO(0, b)
                   1157: ZEND_END_ARG_INFO()
                   1158: 
                   1159: ZEND_BEGIN_ARG_INFO(arginfo_pqueue_insert, 0)
                   1160:        ZEND_ARG_INFO(0, value)
                   1161:        ZEND_ARG_INFO(0, priority)
                   1162: ZEND_END_ARG_INFO()
                   1163: 
                   1164: ZEND_BEGIN_ARG_INFO(arginfo_pqueue_setflags, 0)
                   1165:        ZEND_ARG_INFO(0, flags)
                   1166: ZEND_END_ARG_INFO()
                   1167: 
                   1168: ZEND_BEGIN_ARG_INFO(arginfo_splheap_void, 0)
                   1169: ZEND_END_ARG_INFO()
                   1170: 
                   1171: static const zend_function_entry spl_funcs_SplMinHeap[] = {
                   1172:        SPL_ME(SplMinHeap, compare, arginfo_heap_compare, ZEND_ACC_PROTECTED)
                   1173:        {NULL, NULL, NULL}
                   1174: };
                   1175: static const zend_function_entry spl_funcs_SplMaxHeap[] = {
                   1176:        SPL_ME(SplMaxHeap, compare, arginfo_heap_compare, ZEND_ACC_PROTECTED)
                   1177:        {NULL, NULL, NULL}
                   1178: };
                   1179: 
                   1180: static const zend_function_entry spl_funcs_SplPriorityQueue[] = {
                   1181:        SPL_ME(SplPriorityQueue, compare,               arginfo_heap_compare,    ZEND_ACC_PUBLIC)
                   1182:        SPL_ME(SplPriorityQueue, insert,                arginfo_pqueue_insert,   ZEND_ACC_PUBLIC)
                   1183:        SPL_ME(SplPriorityQueue, setExtractFlags,       arginfo_pqueue_setflags, ZEND_ACC_PUBLIC)
                   1184:        SPL_ME(SplPriorityQueue, top,                   arginfo_splheap_void,    ZEND_ACC_PUBLIC)
                   1185:        SPL_ME(SplPriorityQueue, extract,               arginfo_splheap_void,    ZEND_ACC_PUBLIC)
                   1186:        SPL_ME(SplHeap,          count,                 arginfo_splheap_void,    ZEND_ACC_PUBLIC)
                   1187:        SPL_ME(SplHeap,          isEmpty,               arginfo_splheap_void,    ZEND_ACC_PUBLIC)
                   1188:        SPL_ME(SplHeap,          rewind,                arginfo_splheap_void,    ZEND_ACC_PUBLIC)
                   1189:        SPL_ME(SplPriorityQueue, current,               arginfo_splheap_void,    ZEND_ACC_PUBLIC)
                   1190:        SPL_ME(SplHeap,          key,                   arginfo_splheap_void,    ZEND_ACC_PUBLIC)
                   1191:        SPL_ME(SplHeap,          next,                  arginfo_splheap_void,    ZEND_ACC_PUBLIC)
                   1192:        SPL_ME(SplHeap,          valid,                 arginfo_splheap_void,    ZEND_ACC_PUBLIC)
                   1193:        SPL_ME(SplHeap,          recoverFromCorruption, arginfo_splheap_void,    ZEND_ACC_PUBLIC)
                   1194:        {NULL, NULL, NULL}
                   1195: };
                   1196: 
                   1197: static const zend_function_entry spl_funcs_SplHeap[] = {
                   1198:        SPL_ME(SplHeap, extract,               arginfo_splheap_void, ZEND_ACC_PUBLIC)
                   1199:        SPL_ME(SplHeap, insert,                arginfo_heap_insert, ZEND_ACC_PUBLIC)
                   1200:        SPL_ME(SplHeap, top,                   arginfo_splheap_void, ZEND_ACC_PUBLIC)
                   1201:        SPL_ME(SplHeap, count,                 arginfo_splheap_void, ZEND_ACC_PUBLIC)
                   1202:        SPL_ME(SplHeap, isEmpty,               arginfo_splheap_void, ZEND_ACC_PUBLIC)
                   1203:        SPL_ME(SplHeap, rewind,                arginfo_splheap_void, ZEND_ACC_PUBLIC)
                   1204:        SPL_ME(SplHeap, current,               arginfo_splheap_void, ZEND_ACC_PUBLIC)
                   1205:        SPL_ME(SplHeap, key,                   arginfo_splheap_void, ZEND_ACC_PUBLIC)
                   1206:        SPL_ME(SplHeap, next,                  arginfo_splheap_void, ZEND_ACC_PUBLIC)
                   1207:        SPL_ME(SplHeap, valid,                 arginfo_splheap_void, ZEND_ACC_PUBLIC)
                   1208:        SPL_ME(SplHeap, recoverFromCorruption, arginfo_splheap_void, ZEND_ACC_PUBLIC)
                   1209:        ZEND_FENTRY(compare, NULL, NULL, ZEND_ACC_PROTECTED|ZEND_ACC_ABSTRACT)
                   1210:        {NULL, NULL, NULL}
                   1211: };
                   1212: /* }}} */
                   1213: 
                   1214: PHP_MINIT_FUNCTION(spl_heap) /* {{{ */
                   1215: {
                   1216:        REGISTER_SPL_STD_CLASS_EX(SplHeap, spl_heap_object_new, spl_funcs_SplHeap);
                   1217:        memcpy(&spl_handler_SplHeap, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
                   1218: 
                   1219:        spl_handler_SplHeap.clone_obj      = spl_heap_object_clone;
                   1220:        spl_handler_SplHeap.count_elements = spl_heap_object_count_elements;
                   1221:        spl_handler_SplHeap.get_debug_info = spl_heap_object_get_debug_info;
                   1222: 
                   1223:        REGISTER_SPL_IMPLEMENTS(SplHeap, Iterator);
                   1224:        REGISTER_SPL_IMPLEMENTS(SplHeap, Countable);
                   1225: 
                   1226:        spl_ce_SplHeap->get_iterator = spl_heap_get_iterator;
                   1227: 
                   1228:        REGISTER_SPL_SUB_CLASS_EX(SplMinHeap,           SplHeap,        spl_heap_object_new, spl_funcs_SplMinHeap);
                   1229:        REGISTER_SPL_SUB_CLASS_EX(SplMaxHeap,           SplHeap,        spl_heap_object_new, spl_funcs_SplMaxHeap);
                   1230: 
                   1231:        spl_ce_SplMaxHeap->get_iterator = spl_heap_get_iterator;
                   1232:        spl_ce_SplMinHeap->get_iterator = spl_heap_get_iterator;
                   1233: 
                   1234:        REGISTER_SPL_STD_CLASS_EX(SplPriorityQueue, spl_heap_object_new, spl_funcs_SplPriorityQueue);
                   1235:        memcpy(&spl_handler_SplPriorityQueue, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
                   1236: 
                   1237:        spl_handler_SplPriorityQueue.clone_obj      = spl_heap_object_clone;
                   1238:        spl_handler_SplPriorityQueue.count_elements = spl_heap_object_count_elements;
                   1239:        spl_handler_SplPriorityQueue.get_debug_info = spl_pqueue_object_get_debug_info;
                   1240: 
                   1241:        REGISTER_SPL_IMPLEMENTS(SplPriorityQueue, Iterator);
                   1242:        REGISTER_SPL_IMPLEMENTS(SplPriorityQueue, Countable);
                   1243: 
                   1244:        spl_ce_SplPriorityQueue->get_iterator = spl_pqueue_get_iterator;
                   1245: 
                   1246:        REGISTER_SPL_CLASS_CONST_LONG(SplPriorityQueue, "EXTR_BOTH",      SPL_PQUEUE_EXTR_BOTH);
                   1247:        REGISTER_SPL_CLASS_CONST_LONG(SplPriorityQueue, "EXTR_PRIORITY",  SPL_PQUEUE_EXTR_PRIORITY);
                   1248:        REGISTER_SPL_CLASS_CONST_LONG(SplPriorityQueue, "EXTR_DATA",      SPL_PQUEUE_EXTR_DATA);
                   1249: 
                   1250:        return SUCCESS;
                   1251: }
                   1252: /* }}} */
                   1253: 
                   1254: /*
                   1255:  * Local variables:
                   1256:  * tab-width: 4
                   1257:  * c-basic-offset: 4
                   1258:  * End:
                   1259:  * vim600: fdm=marker
                   1260:  * vim: noet sw=4 ts=4
                   1261:  */
                   1262: 

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