Annotation of embedaddon/php/ext/spl/spl_heap.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: | Authors: Etienne Kneuss <colder@php.net> |
! 16: +----------------------------------------------------------------------+
! 17: */
! 18:
! 19: /* $Id: spl_heap.c 321634 2012-01-01 13:15:04Z felipe $ */
! 20:
! 21: #ifdef HAVE_CONFIG_H
! 22: # include "config.h"
! 23: #endif
! 24:
! 25: #include "php.h"
! 26: #include "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: zval *tmp;
! 389: zend_class_entry *parent = class_type;
! 390: int inherited = 0;
! 391:
! 392: intern = ecalloc(1, sizeof(spl_heap_object));
! 393: *obj = intern;
! 394: ALLOC_INIT_ZVAL(intern->retval);
! 395:
! 396: zend_object_std_init(&intern->std, class_type TSRMLS_CC);
! 397: zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
! 398:
! 399: intern->flags = 0;
! 400: intern->fptr_cmp = NULL;
! 401: intern->debug_info = NULL;
! 402:
! 403: if (orig) {
! 404: spl_heap_object *other = (spl_heap_object*)zend_object_store_get_object(orig TSRMLS_CC);
! 405: intern->ce_get_iterator = other->ce_get_iterator;
! 406:
! 407: if (clone_orig) {
! 408: int i;
! 409: intern->heap = spl_ptr_heap_clone(other->heap TSRMLS_CC);
! 410: for (i = 0; i < intern->heap->count; ++i) {
! 411: if (intern->heap->elements[i]) {
! 412: Z_ADDREF_P((zval *)intern->heap->elements[i]);
! 413: }
! 414: }
! 415: } else {
! 416: intern->heap = other->heap;
! 417: }
! 418:
! 419: intern->flags = other->flags;
! 420: } else {
! 421: intern->heap = spl_ptr_heap_init(spl_ptr_heap_zval_max_cmp, spl_ptr_heap_zval_ctor, spl_ptr_heap_zval_dtor);
! 422: }
! 423:
! 424: retval.handlers = &spl_handler_SplHeap;
! 425:
! 426: while (parent) {
! 427: if (parent == spl_ce_SplPriorityQueue) {
! 428: intern->heap->cmp = spl_ptr_pqueue_zval_cmp;
! 429: intern->flags = SPL_PQUEUE_EXTR_DATA;
! 430: retval.handlers = &spl_handler_SplPriorityQueue;
! 431: break;
! 432: }
! 433:
! 434: if (parent == spl_ce_SplMinHeap) {
! 435: intern->heap->cmp = spl_ptr_heap_zval_min_cmp;
! 436: break;
! 437: }
! 438:
! 439: if (parent == spl_ce_SplMaxHeap) {
! 440: intern->heap->cmp = spl_ptr_heap_zval_max_cmp;
! 441: break;
! 442: }
! 443:
! 444: if (parent == spl_ce_SplHeap) {
! 445: break;
! 446: }
! 447:
! 448: parent = parent->parent;
! 449: inherited = 1;
! 450: }
! 451:
! 452: retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, spl_heap_object_free_storage, NULL TSRMLS_CC);
! 453:
! 454: if (!parent) { /* this must never happen */
! 455: php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplHeap");
! 456: }
! 457:
! 458: if (inherited) {
! 459: zend_hash_find(&class_type->function_table, "compare", sizeof("compare"), (void **) &intern->fptr_cmp);
! 460: if (intern->fptr_cmp->common.scope == parent) {
! 461: intern->fptr_cmp = NULL;
! 462: }
! 463: zend_hash_find(&class_type->function_table, "count", sizeof("count"), (void **) &intern->fptr_count);
! 464: if (intern->fptr_count->common.scope == parent) {
! 465: intern->fptr_count = NULL;
! 466: }
! 467: }
! 468:
! 469: return retval;
! 470: }
! 471: /* }}} */
! 472:
! 473: static zend_object_value spl_heap_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
! 474: {
! 475: spl_heap_object *tmp;
! 476: return spl_heap_object_new_ex(class_type, &tmp, NULL, 0 TSRMLS_CC);
! 477: }
! 478: /* }}} */
! 479:
! 480: static zend_object_value spl_heap_object_clone(zval *zobject TSRMLS_DC) /* {{{ */
! 481: {
! 482: zend_object_value new_obj_val;
! 483: zend_object *old_object;
! 484: zend_object *new_object;
! 485: zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
! 486: spl_heap_object *intern;
! 487:
! 488: old_object = zend_objects_get_address(zobject TSRMLS_CC);
! 489: new_obj_val = spl_heap_object_new_ex(old_object->ce, &intern, zobject, 1 TSRMLS_CC);
! 490: new_object = &intern->std;
! 491:
! 492: zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
! 493:
! 494: return new_obj_val;
! 495: }
! 496: /* }}} */
! 497:
! 498: static int spl_heap_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
! 499: {
! 500: spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(object TSRMLS_CC);
! 501:
! 502: if (intern->fptr_count) {
! 503: zval *rv;
! 504: zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_count, "count", &rv);
! 505: if (rv) {
! 506: zval_ptr_dtor(&intern->retval);
! 507: MAKE_STD_ZVAL(intern->retval);
! 508: ZVAL_ZVAL(intern->retval, rv, 1, 1);
! 509: convert_to_long(intern->retval);
! 510: *count = (long) Z_LVAL_P(intern->retval);
! 511: return SUCCESS;
! 512: }
! 513: *count = 0;
! 514: return FAILURE;
! 515: }
! 516:
! 517: *count = spl_ptr_heap_count(intern->heap);
! 518:
! 519: return SUCCESS;
! 520: }
! 521: /* }}} */
! 522:
! 523: static HashTable* spl_heap_object_get_debug_info_helper(zend_class_entry *ce, zval *obj, int *is_temp TSRMLS_DC) { /* {{{ */
! 524: spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(obj TSRMLS_CC);
! 525: zval *tmp, zrv, *heap_array;
! 526: char *pnstr;
! 527: int pnlen;
! 528: int i;
! 529:
! 530: *is_temp = 0;
! 531:
! 532: if (intern->debug_info == NULL) {
! 533: ALLOC_HASHTABLE(intern->debug_info);
! 534: ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
! 535: }
! 536:
! 537: if (intern->debug_info->nApplyCount == 0) {
! 538: INIT_PZVAL(&zrv);
! 539: Z_ARRVAL(zrv) = intern->debug_info;
! 540:
! 541: zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
! 542:
! 543: pnstr = spl_gen_private_prop_name(ce, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
! 544: add_assoc_long_ex(&zrv, pnstr, pnlen+1, intern->flags);
! 545: efree(pnstr);
! 546:
! 547: pnstr = spl_gen_private_prop_name(ce, "isCorrupted", sizeof("isCorrupted")-1, &pnlen TSRMLS_CC);
! 548: add_assoc_bool_ex(&zrv, pnstr, pnlen+1, intern->heap->flags&SPL_HEAP_CORRUPTED);
! 549: efree(pnstr);
! 550:
! 551: ALLOC_INIT_ZVAL(heap_array);
! 552: array_init(heap_array);
! 553:
! 554: for (i = 0; i < intern->heap->count; ++i) {
! 555: add_index_zval(heap_array, i, (zval *)intern->heap->elements[i]);
! 556: Z_ADDREF_P(intern->heap->elements[i]);
! 557: }
! 558:
! 559: pnstr = spl_gen_private_prop_name(ce, "heap", sizeof("heap")-1, &pnlen TSRMLS_CC);
! 560: add_assoc_zval_ex(&zrv, pnstr, pnlen+1, heap_array);
! 561: efree(pnstr);
! 562: }
! 563:
! 564: return intern->debug_info;
! 565: }
! 566: /* }}} */
! 567:
! 568: static HashTable* spl_heap_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */
! 569: {
! 570: return spl_heap_object_get_debug_info_helper(spl_ce_SplHeap, obj, is_temp TSRMLS_CC);
! 571: }
! 572: /* }}} */
! 573:
! 574: static HashTable* spl_pqueue_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */
! 575: {
! 576: return spl_heap_object_get_debug_info_helper(spl_ce_SplPriorityQueue, obj, is_temp TSRMLS_CC);
! 577: }
! 578: /* }}} */
! 579:
! 580: /* {{{ proto int SplHeap::count() U
! 581: Return the number of elements in the heap. */
! 582: SPL_METHOD(SplHeap, count)
! 583: {
! 584: long count;
! 585: spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
! 586:
! 587: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
! 588: return;
! 589: }
! 590:
! 591: count = spl_ptr_heap_count(intern->heap);
! 592: RETURN_LONG(count);
! 593: }
! 594: /* }}} */
! 595:
! 596: /* {{{ proto int SplHeap::isEmpty() U
! 597: Return true if the heap is empty. */
! 598: SPL_METHOD(SplHeap, isEmpty)
! 599: {
! 600: spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
! 601:
! 602: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
! 603: return;
! 604: }
! 605:
! 606: RETURN_BOOL(spl_ptr_heap_count(intern->heap)==0);
! 607: }
! 608: /* }}} */
! 609:
! 610: /* {{{ proto bool SplHeap::insert(mixed $value) U
! 611: Push $value on the heap */
! 612: SPL_METHOD(SplHeap, insert)
! 613: {
! 614: zval *value;
! 615: spl_heap_object *intern;
! 616:
! 617: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
! 618: return;
! 619: }
! 620:
! 621: intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
! 622:
! 623: if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
! 624: zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
! 625: return;
! 626: }
! 627:
! 628: SEPARATE_ARG_IF_REF(value);
! 629:
! 630: spl_ptr_heap_insert(intern->heap, value, getThis() TSRMLS_CC);
! 631:
! 632: RETURN_TRUE;
! 633: }
! 634: /* }}} */
! 635:
! 636: /* {{{ proto mixed SplHeap::extract() U
! 637: extract the element out of the top of the heap */
! 638: SPL_METHOD(SplHeap, extract)
! 639: {
! 640: zval *value;
! 641: spl_heap_object *intern;
! 642:
! 643: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
! 644: return;
! 645: }
! 646:
! 647: intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
! 648:
! 649: if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
! 650: zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
! 651: return;
! 652: }
! 653:
! 654: value = (zval *)spl_ptr_heap_delete_top(intern->heap, getThis() TSRMLS_CC);
! 655:
! 656: if (!value) {
! 657: zend_throw_exception(spl_ce_RuntimeException, "Can't extract from an empty heap", 0 TSRMLS_CC);
! 658: return;
! 659: }
! 660:
! 661: RETURN_ZVAL(value, 1, 1);
! 662: }
! 663: /* }}} */
! 664:
! 665: /* {{{ proto bool SplPriorityQueue::insert(mixed $value, mixed $priority) U
! 666: Push $value with the priority $priodiry on the priorityqueue */
! 667: SPL_METHOD(SplPriorityQueue, insert)
! 668: {
! 669: zval *data, *priority, *elem;
! 670: spl_heap_object *intern;
! 671:
! 672: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &data, &priority) == FAILURE) {
! 673: return;
! 674: }
! 675:
! 676: intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
! 677:
! 678: if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
! 679: zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
! 680: return;
! 681: }
! 682:
! 683: SEPARATE_ARG_IF_REF(data);
! 684: SEPARATE_ARG_IF_REF(priority);
! 685:
! 686: ALLOC_INIT_ZVAL(elem);
! 687:
! 688: array_init(elem);
! 689: add_assoc_zval_ex(elem, "data", sizeof("data"), data);
! 690: add_assoc_zval_ex(elem, "priority", sizeof("priority"), priority);
! 691:
! 692: spl_ptr_heap_insert(intern->heap, elem, getThis() TSRMLS_CC);
! 693:
! 694: RETURN_TRUE;
! 695: }
! 696: /* }}} */
! 697:
! 698: /* {{{ proto mixed SplPriorityQueue::extract() U
! 699: extract the element out of the top of the priority queue */
! 700: SPL_METHOD(SplPriorityQueue, extract)
! 701: {
! 702: zval *value, *value_out, **value_out_pp;
! 703: spl_heap_object *intern;
! 704:
! 705: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
! 706: return;
! 707: }
! 708:
! 709: intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
! 710:
! 711: if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
! 712: zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
! 713: return;
! 714: }
! 715:
! 716: value = (zval *)spl_ptr_heap_delete_top(intern->heap, getThis() TSRMLS_CC);
! 717:
! 718: if (!value) {
! 719: zend_throw_exception(spl_ce_RuntimeException, "Can't extract from an empty heap", 0 TSRMLS_CC);
! 720: return;
! 721: }
! 722:
! 723: value_out_pp = spl_pqueue_extract_helper(&value, intern->flags);
! 724:
! 725:
! 726: if (!value_out_pp) {
! 727: zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node");
! 728: zval_ptr_dtor(&value);
! 729: return;
! 730: }
! 731:
! 732: value_out = *value_out_pp;
! 733:
! 734: Z_ADDREF_P(value_out);
! 735: zval_ptr_dtor(&value);
! 736:
! 737: RETURN_ZVAL(value_out, 1, 1);
! 738: }
! 739: /* }}} */
! 740:
! 741: /* {{{ proto mixed SplPriorityQueue::top() U
! 742: Peek at the top element of the priority queue */
! 743: SPL_METHOD(SplPriorityQueue, top)
! 744: {
! 745: zval *value, **value_out;
! 746: spl_heap_object *intern;
! 747:
! 748: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
! 749: return;
! 750: }
! 751:
! 752: intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
! 753:
! 754: if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
! 755: zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
! 756: return;
! 757: }
! 758:
! 759: value = (zval *)spl_ptr_heap_top(intern->heap);
! 760:
! 761: if (!value) {
! 762: zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty heap", 0 TSRMLS_CC);
! 763: return;
! 764: }
! 765:
! 766: value_out = spl_pqueue_extract_helper(&value, intern->flags);
! 767:
! 768: if (!value_out) {
! 769: zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node");
! 770: return;
! 771: }
! 772:
! 773: RETURN_ZVAL(*value_out, 1, 0);
! 774: }
! 775: /* }}} */
! 776:
! 777: /* {{{ proto int SplPriorityQueue::setIteratorMode($flags) U
! 778: Set the flags of extraction*/
! 779: SPL_METHOD(SplPriorityQueue, setExtractFlags)
! 780: {
! 781: long value;
! 782: spl_heap_object *intern;
! 783:
! 784: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) == FAILURE) {
! 785: return;
! 786: }
! 787:
! 788: intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
! 789:
! 790: intern->flags = value & SPL_PQUEUE_EXTR_MASK;
! 791:
! 792: RETURN_LONG(intern->flags);
! 793: }
! 794: /* }}} */
! 795:
! 796: /* {{{ proto int SplHeap::recoverFromCorruption() U
! 797: Recover from a corrupted state*/
! 798: SPL_METHOD(SplHeap, recoverFromCorruption)
! 799: {
! 800: spl_heap_object *intern;
! 801:
! 802: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
! 803: return;
! 804: }
! 805:
! 806: intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
! 807:
! 808: intern->heap->flags = intern->heap->flags & ~SPL_HEAP_CORRUPTED;
! 809:
! 810: RETURN_TRUE;
! 811: }
! 812: /* }}} */
! 813:
! 814: /* {{{ proto bool SplPriorityQueue::compare(mixed $a, mixed $b) U
! 815: compare the priorities */
! 816: SPL_METHOD(SplPriorityQueue, compare)
! 817: {
! 818: zval *a, *b;
! 819:
! 820: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a, &b) == FAILURE) {
! 821: return;
! 822: }
! 823:
! 824: RETURN_LONG(spl_ptr_heap_zval_max_cmp(a, b, NULL TSRMLS_CC));
! 825: }
! 826: /* }}} */
! 827:
! 828: /* {{{ proto mixed SplHeap::top() U
! 829: Peek at the top element of the heap */
! 830: SPL_METHOD(SplHeap, top)
! 831: {
! 832: zval *value;
! 833: spl_heap_object *intern;
! 834:
! 835: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
! 836: return;
! 837: }
! 838:
! 839: intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
! 840:
! 841: if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
! 842: zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
! 843: return;
! 844: }
! 845:
! 846: value = (zval *)spl_ptr_heap_top(intern->heap);
! 847:
! 848: if (!value) {
! 849: zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty heap", 0 TSRMLS_CC);
! 850: return;
! 851: }
! 852:
! 853: RETURN_ZVAL(value, 1, 0);
! 854: }
! 855: /* }}} */
! 856:
! 857: /* {{{ proto bool SplMinHeap::compare(mixed $a, mixed $b) U
! 858: compare the values */
! 859: SPL_METHOD(SplMinHeap, compare)
! 860: {
! 861: zval *a, *b;
! 862:
! 863: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a, &b) == FAILURE) {
! 864: return;
! 865: }
! 866:
! 867: RETURN_LONG(spl_ptr_heap_zval_min_cmp(a, b, NULL TSRMLS_CC));
! 868: }
! 869: /* }}} */
! 870:
! 871: /* {{{ proto bool SplMaxHeap::compare(mixed $a, mixed $b) U
! 872: compare the values */
! 873: SPL_METHOD(SplMaxHeap, compare)
! 874: {
! 875: zval *a, *b;
! 876:
! 877: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a, &b) == FAILURE) {
! 878: return;
! 879: }
! 880:
! 881: RETURN_LONG(spl_ptr_heap_zval_max_cmp(a, b, NULL TSRMLS_CC));
! 882: }
! 883: /* }}} */
! 884:
! 885: static void spl_heap_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
! 886: {
! 887: spl_heap_it *iterator = (spl_heap_it *)iter;
! 888:
! 889: zend_user_it_invalidate_current(iter TSRMLS_CC);
! 890: zval_ptr_dtor((zval**)&iterator->intern.it.data);
! 891:
! 892: efree(iterator);
! 893: }
! 894: /* }}} */
! 895:
! 896: static void spl_heap_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
! 897: {
! 898: /* do nothing, the iterator always points to the top element */
! 899: }
! 900: /* }}} */
! 901:
! 902: static int spl_heap_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
! 903: {
! 904: spl_heap_it *iterator = (spl_heap_it *)iter;
! 905:
! 906: return (iterator->object->heap->count != 0 ? SUCCESS : FAILURE);
! 907: }
! 908: /* }}} */
! 909:
! 910: static void spl_heap_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
! 911: {
! 912: spl_heap_it *iterator = (spl_heap_it *)iter;
! 913: zval **element = (zval **)&iterator->object->heap->elements[0];
! 914:
! 915: if (iterator->object->heap->flags & SPL_HEAP_CORRUPTED) {
! 916: zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
! 917: return;
! 918: }
! 919:
! 920: if (iterator->object->heap->count == 0 || !*element) {
! 921: *data = NULL;
! 922: } else {
! 923: *data = element;
! 924: }
! 925: }
! 926: /* }}} */
! 927:
! 928: static void spl_pqueue_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
! 929: {
! 930: spl_heap_it *iterator = (spl_heap_it *)iter;
! 931: zval **element = (zval **)&iterator->object->heap->elements[0];
! 932:
! 933: if (iterator->object->heap->flags & SPL_HEAP_CORRUPTED) {
! 934: zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
! 935: return;
! 936: }
! 937:
! 938: if (iterator->object->heap->count == 0 || !*element) {
! 939: *data = NULL;
! 940: } else {
! 941: *data = spl_pqueue_extract_helper(element, iterator->object->flags);
! 942: if (!*data) {
! 943: zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node");
! 944: }
! 945: }
! 946: }
! 947: /* }}} */
! 948:
! 949: static int spl_heap_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
! 950: {
! 951: spl_heap_it *iterator = (spl_heap_it *)iter;
! 952:
! 953: *int_key = (ulong) iterator->object->heap->count;
! 954: return HASH_KEY_IS_LONG;
! 955: }
! 956: /* }}} */
! 957:
! 958: static void spl_heap_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
! 959: {
! 960: zval *object = (zval*)((zend_user_iterator *)iter)->it.data;
! 961: spl_heap_it *iterator = (spl_heap_it *)iter;
! 962: spl_ptr_heap_element elem;
! 963:
! 964: if (iterator->object->heap->flags & SPL_HEAP_CORRUPTED) {
! 965: zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
! 966: return;
! 967: }
! 968:
! 969: elem = spl_ptr_heap_delete_top(iterator->object->heap, object TSRMLS_CC);
! 970:
! 971: if (elem != NULL) {
! 972: zval_ptr_dtor((zval **)&elem);
! 973: }
! 974:
! 975: zend_user_it_invalidate_current(iter TSRMLS_CC);
! 976: }
! 977: /* }}} */
! 978:
! 979: /* {{{ proto int SplHeap::key() U
! 980: Return current array key */
! 981: SPL_METHOD(SplHeap, key)
! 982: {
! 983: spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
! 984:
! 985: if (zend_parse_parameters_none() == FAILURE) {
! 986: return;
! 987: }
! 988:
! 989: RETURN_LONG(intern->heap->count - 1);
! 990: }
! 991: /* }}} */
! 992:
! 993: /* {{{ proto void SplHeap::next() U
! 994: Move to next entry */
! 995: SPL_METHOD(SplHeap, next)
! 996: {
! 997: spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
! 998: spl_ptr_heap_element elem = spl_ptr_heap_delete_top(intern->heap, getThis() TSRMLS_CC);
! 999:
! 1000: if (zend_parse_parameters_none() == FAILURE) {
! 1001: return;
! 1002: }
! 1003:
! 1004: if (elem != NULL) {
! 1005: zval_ptr_dtor((zval **)&elem);
! 1006: }
! 1007: }
! 1008: /* }}} */
! 1009:
! 1010: /* {{{ proto bool SplHeap::valid() U
! 1011: Check whether the datastructure contains more entries */
! 1012: SPL_METHOD(SplHeap, valid)
! 1013: {
! 1014: spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
! 1015:
! 1016: if (zend_parse_parameters_none() == FAILURE) {
! 1017: return;
! 1018: }
! 1019:
! 1020: RETURN_BOOL(intern->heap->count != 0);
! 1021: }
! 1022: /* }}} */
! 1023:
! 1024: /* {{{ proto void SplHeap::rewind() U
! 1025: Rewind the datastructure back to the start */
! 1026: SPL_METHOD(SplHeap, rewind)
! 1027: {
! 1028: if (zend_parse_parameters_none() == FAILURE) {
! 1029: return;
! 1030: }
! 1031: /* do nothing, the iterator always points to the top element */
! 1032: }
! 1033: /* }}} */
! 1034:
! 1035: /* {{{ proto mixed|NULL SplHeap::current() U
! 1036: Return current datastructure entry */
! 1037: SPL_METHOD(SplHeap, current)
! 1038: {
! 1039: spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
! 1040: zval *element = (zval *)intern->heap->elements[0];
! 1041:
! 1042: if (zend_parse_parameters_none() == FAILURE) {
! 1043: return;
! 1044: }
! 1045:
! 1046: if (!intern->heap->count || !element) {
! 1047: RETURN_NULL();
! 1048: } else {
! 1049: RETURN_ZVAL(element, 1, 0);
! 1050: }
! 1051: }
! 1052: /* }}} */
! 1053:
! 1054: /* {{{ proto mixed|NULL SplPriorityQueue::current() U
! 1055: Return current datastructure entry */
! 1056: SPL_METHOD(SplPriorityQueue, current)
! 1057: {
! 1058: spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
! 1059: zval **element = (zval **)&intern->heap->elements[0];
! 1060:
! 1061: if (zend_parse_parameters_none() == FAILURE) {
! 1062: return;
! 1063: }
! 1064:
! 1065: if (!intern->heap->count || !*element) {
! 1066: RETURN_NULL();
! 1067: } else {
! 1068: zval **data = spl_pqueue_extract_helper(element, intern->flags);
! 1069:
! 1070: if (!data) {
! 1071: zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node");
! 1072: RETURN_NULL();
! 1073: }
! 1074:
! 1075: RETURN_ZVAL(*data, 1, 0);
! 1076: }
! 1077: }
! 1078: /* }}} */
! 1079:
! 1080: /* iterator handler table */
! 1081: zend_object_iterator_funcs spl_heap_it_funcs = {
! 1082: spl_heap_it_dtor,
! 1083: spl_heap_it_valid,
! 1084: spl_heap_it_get_current_data,
! 1085: spl_heap_it_get_current_key,
! 1086: spl_heap_it_move_forward,
! 1087: spl_heap_it_rewind
! 1088: };
! 1089:
! 1090: zend_object_iterator_funcs spl_pqueue_it_funcs = {
! 1091: spl_heap_it_dtor,
! 1092: spl_heap_it_valid,
! 1093: spl_pqueue_it_get_current_data,
! 1094: spl_heap_it_get_current_key,
! 1095: spl_heap_it_move_forward,
! 1096: spl_heap_it_rewind
! 1097: };
! 1098:
! 1099: zend_object_iterator *spl_heap_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
! 1100: {
! 1101: spl_heap_it *iterator;
! 1102: spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object(object TSRMLS_CC);
! 1103:
! 1104: if (by_ref) {
! 1105: zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC);
! 1106: return NULL;
! 1107: }
! 1108:
! 1109: Z_ADDREF_P(object);
! 1110:
! 1111: iterator = emalloc(sizeof(spl_heap_it));
! 1112: iterator->intern.it.data = (void*)object;
! 1113: iterator->intern.it.funcs = &spl_heap_it_funcs;
! 1114: iterator->intern.ce = ce;
! 1115: iterator->intern.value = NULL;
! 1116: iterator->flags = heap_object->flags;
! 1117: iterator->object = heap_object;
! 1118:
! 1119: return (zend_object_iterator*)iterator;
! 1120: }
! 1121: /* }}} */
! 1122:
! 1123: zend_object_iterator *spl_pqueue_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
! 1124: {
! 1125: spl_heap_it *iterator;
! 1126: spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object(object TSRMLS_CC);
! 1127:
! 1128: if (by_ref) {
! 1129: zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC);
! 1130: return NULL;
! 1131: }
! 1132:
! 1133: Z_ADDREF_P(object);
! 1134:
! 1135: iterator = emalloc(sizeof(spl_heap_it));
! 1136: iterator->intern.it.data = (void*)object;
! 1137: iterator->intern.it.funcs = &spl_pqueue_it_funcs;
! 1138: iterator->intern.ce = ce;
! 1139: iterator->intern.value = NULL;
! 1140: iterator->flags = heap_object->flags;
! 1141: iterator->object = heap_object;
! 1142:
! 1143: return (zend_object_iterator*)iterator;
! 1144: }
! 1145: /* }}} */
! 1146:
! 1147: ZEND_BEGIN_ARG_INFO(arginfo_heap_insert, 0)
! 1148: ZEND_ARG_INFO(0, value)
! 1149: ZEND_END_ARG_INFO()
! 1150:
! 1151: ZEND_BEGIN_ARG_INFO(arginfo_heap_compare, 0)
! 1152: ZEND_ARG_INFO(0, a)
! 1153: ZEND_ARG_INFO(0, b)
! 1154: ZEND_END_ARG_INFO()
! 1155:
! 1156: ZEND_BEGIN_ARG_INFO(arginfo_pqueue_insert, 0)
! 1157: ZEND_ARG_INFO(0, value)
! 1158: ZEND_ARG_INFO(0, priority)
! 1159: ZEND_END_ARG_INFO()
! 1160:
! 1161: ZEND_BEGIN_ARG_INFO(arginfo_pqueue_setflags, 0)
! 1162: ZEND_ARG_INFO(0, flags)
! 1163: ZEND_END_ARG_INFO()
! 1164:
! 1165: ZEND_BEGIN_ARG_INFO(arginfo_splheap_void, 0)
! 1166: ZEND_END_ARG_INFO()
! 1167:
! 1168: static const zend_function_entry spl_funcs_SplMinHeap[] = {
! 1169: SPL_ME(SplMinHeap, compare, arginfo_heap_compare, ZEND_ACC_PROTECTED)
! 1170: {NULL, NULL, NULL}
! 1171: };
! 1172: static const zend_function_entry spl_funcs_SplMaxHeap[] = {
! 1173: SPL_ME(SplMaxHeap, compare, arginfo_heap_compare, ZEND_ACC_PROTECTED)
! 1174: {NULL, NULL, NULL}
! 1175: };
! 1176:
! 1177: static const zend_function_entry spl_funcs_SplPriorityQueue[] = {
! 1178: SPL_ME(SplPriorityQueue, compare, arginfo_heap_compare, ZEND_ACC_PUBLIC)
! 1179: SPL_ME(SplPriorityQueue, insert, arginfo_pqueue_insert, ZEND_ACC_PUBLIC)
! 1180: SPL_ME(SplPriorityQueue, setExtractFlags, arginfo_pqueue_setflags, ZEND_ACC_PUBLIC)
! 1181: SPL_ME(SplPriorityQueue, top, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1182: SPL_ME(SplPriorityQueue, extract, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1183: SPL_ME(SplHeap, count, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1184: SPL_ME(SplHeap, isEmpty, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1185: SPL_ME(SplHeap, rewind, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1186: SPL_ME(SplPriorityQueue, current, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1187: SPL_ME(SplHeap, key, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1188: SPL_ME(SplHeap, next, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1189: SPL_ME(SplHeap, valid, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1190: SPL_ME(SplHeap, recoverFromCorruption, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1191: {NULL, NULL, NULL}
! 1192: };
! 1193:
! 1194: static const zend_function_entry spl_funcs_SplHeap[] = {
! 1195: SPL_ME(SplHeap, extract, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1196: SPL_ME(SplHeap, insert, arginfo_heap_insert, ZEND_ACC_PUBLIC)
! 1197: SPL_ME(SplHeap, top, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1198: SPL_ME(SplHeap, count, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1199: SPL_ME(SplHeap, isEmpty, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1200: SPL_ME(SplHeap, rewind, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1201: SPL_ME(SplHeap, current, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1202: SPL_ME(SplHeap, key, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1203: SPL_ME(SplHeap, next, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1204: SPL_ME(SplHeap, valid, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1205: SPL_ME(SplHeap, recoverFromCorruption, arginfo_splheap_void, ZEND_ACC_PUBLIC)
! 1206: ZEND_FENTRY(compare, NULL, NULL, ZEND_ACC_PROTECTED|ZEND_ACC_ABSTRACT)
! 1207: {NULL, NULL, NULL}
! 1208: };
! 1209: /* }}} */
! 1210:
! 1211: PHP_MINIT_FUNCTION(spl_heap) /* {{{ */
! 1212: {
! 1213: REGISTER_SPL_STD_CLASS_EX(SplHeap, spl_heap_object_new, spl_funcs_SplHeap);
! 1214: memcpy(&spl_handler_SplHeap, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
! 1215:
! 1216: spl_handler_SplHeap.clone_obj = spl_heap_object_clone;
! 1217: spl_handler_SplHeap.count_elements = spl_heap_object_count_elements;
! 1218: spl_handler_SplHeap.get_debug_info = spl_heap_object_get_debug_info;
! 1219:
! 1220: REGISTER_SPL_IMPLEMENTS(SplHeap, Iterator);
! 1221: REGISTER_SPL_IMPLEMENTS(SplHeap, Countable);
! 1222:
! 1223: spl_ce_SplHeap->get_iterator = spl_heap_get_iterator;
! 1224:
! 1225: REGISTER_SPL_SUB_CLASS_EX(SplMinHeap, SplHeap, spl_heap_object_new, spl_funcs_SplMinHeap);
! 1226: REGISTER_SPL_SUB_CLASS_EX(SplMaxHeap, SplHeap, spl_heap_object_new, spl_funcs_SplMaxHeap);
! 1227:
! 1228: spl_ce_SplMaxHeap->get_iterator = spl_heap_get_iterator;
! 1229: spl_ce_SplMinHeap->get_iterator = spl_heap_get_iterator;
! 1230:
! 1231: REGISTER_SPL_STD_CLASS_EX(SplPriorityQueue, spl_heap_object_new, spl_funcs_SplPriorityQueue);
! 1232: memcpy(&spl_handler_SplPriorityQueue, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
! 1233:
! 1234: spl_handler_SplPriorityQueue.clone_obj = spl_heap_object_clone;
! 1235: spl_handler_SplPriorityQueue.count_elements = spl_heap_object_count_elements;
! 1236: spl_handler_SplPriorityQueue.get_debug_info = spl_pqueue_object_get_debug_info;
! 1237:
! 1238: REGISTER_SPL_IMPLEMENTS(SplPriorityQueue, Iterator);
! 1239: REGISTER_SPL_IMPLEMENTS(SplPriorityQueue, Countable);
! 1240:
! 1241: spl_ce_SplPriorityQueue->get_iterator = spl_pqueue_get_iterator;
! 1242:
! 1243: REGISTER_SPL_CLASS_CONST_LONG(SplPriorityQueue, "EXTR_BOTH", SPL_PQUEUE_EXTR_BOTH);
! 1244: REGISTER_SPL_CLASS_CONST_LONG(SplPriorityQueue, "EXTR_PRIORITY", SPL_PQUEUE_EXTR_PRIORITY);
! 1245: REGISTER_SPL_CLASS_CONST_LONG(SplPriorityQueue, "EXTR_DATA", SPL_PQUEUE_EXTR_DATA);
! 1246:
! 1247: return SUCCESS;
! 1248: }
! 1249: /* }}} */
! 1250:
! 1251: /*
! 1252: * Local variables:
! 1253: * tab-width: 4
! 1254: * c-basic-offset: 4
! 1255: * End:
! 1256: * vim600: fdm=marker
! 1257: * vim: noet sw=4 ts=4
! 1258: */
! 1259:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>