Back to index

php5  5.3.10
spl_heap.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Etienne Kneuss <colder@php.net>                             |
00016    +----------------------------------------------------------------------+
00017  */
00018 
00019 /* $Id: spl_heap.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #ifdef HAVE_CONFIG_H
00022 # include "config.h"
00023 #endif
00024 
00025 #include "php.h"
00026 #include "zend_exceptions.h"
00027 
00028 #include "php_spl.h"
00029 #include "spl_functions.h"
00030 #include "spl_engine.h"
00031 #include "spl_iterators.h"
00032 #include "spl_heap.h"
00033 #include "spl_exceptions.h"
00034 
00035 #define PTR_HEAP_BLOCK_SIZE 64
00036 
00037 #define SPL_HEAP_CORRUPTED       0x00000001
00038 
00039 #define SPL_PQUEUE_EXTR_MASK     0x00000003
00040 #define SPL_PQUEUE_EXTR_BOTH     0x00000003
00041 #define SPL_PQUEUE_EXTR_DATA     0x00000001
00042 #define SPL_PQUEUE_EXTR_PRIORITY 0x00000002
00043 
00044 zend_object_handlers spl_handler_SplHeap;
00045 zend_object_handlers spl_handler_SplPriorityQueue;
00046 
00047 PHPAPI zend_class_entry  *spl_ce_SplHeap;
00048 PHPAPI zend_class_entry  *spl_ce_SplMaxHeap;
00049 PHPAPI zend_class_entry  *spl_ce_SplMinHeap;
00050 PHPAPI zend_class_entry  *spl_ce_SplPriorityQueue;
00051 
00052 typedef void *spl_ptr_heap_element;
00053 
00054 typedef void (*spl_ptr_heap_dtor_func)(spl_ptr_heap_element TSRMLS_DC);
00055 typedef void (*spl_ptr_heap_ctor_func)(spl_ptr_heap_element TSRMLS_DC);
00056 typedef int  (*spl_ptr_heap_cmp_func)(spl_ptr_heap_element, spl_ptr_heap_element, void* TSRMLS_DC);
00057 
00058 typedef struct _spl_ptr_heap {
00059        spl_ptr_heap_element   *elements;
00060        spl_ptr_heap_ctor_func  ctor;
00061        spl_ptr_heap_dtor_func  dtor;
00062        spl_ptr_heap_cmp_func   cmp;
00063        int                     count;
00064        int                     max_size;
00065        int                     flags;
00066 } spl_ptr_heap;
00067 
00068 typedef struct _spl_heap_object spl_heap_object;
00069 typedef struct _spl_heap_it spl_heap_it;
00070 
00071 struct _spl_heap_object {
00072        zend_object         std;
00073        spl_ptr_heap       *heap;
00074        zval               *retval;
00075        int                 flags;
00076        zend_class_entry   *ce_get_iterator;
00077        zend_function      *fptr_cmp;
00078        zend_function      *fptr_count;
00079        HashTable          *debug_info;
00080 };
00081 
00082 /* define an overloaded iterator structure */
00083 struct _spl_heap_it {
00084        zend_user_iterator  intern;
00085        int                 flags;
00086        spl_heap_object    *object;
00087 };
00088 
00089 /* {{{  spl_ptr_heap */
00090 static void spl_ptr_heap_zval_dtor(spl_ptr_heap_element elem TSRMLS_DC) { /* {{{ */
00091        if (elem) {
00092               zval_ptr_dtor((zval **)&elem);
00093        }
00094 }
00095 /* }}} */
00096 
00097 static void spl_ptr_heap_zval_ctor(spl_ptr_heap_element elem TSRMLS_DC) { /* {{{ */
00098        Z_ADDREF_P((zval *)elem);
00099 }
00100 /* }}} */
00101 
00102 static int spl_ptr_heap_cmp_cb_helper(zval *object, spl_heap_object *heap_object, zval *a, zval *b, long *result TSRMLS_DC) { /* {{{ */
00103               zval *result_p = NULL;
00104 
00105               zend_call_method_with_2_params(&object, heap_object->std.ce, &heap_object->fptr_cmp, "compare", &result_p, a, b);
00106 
00107               if (EG(exception)) {
00108                      return FAILURE;
00109               }
00110 
00111               convert_to_long(result_p);
00112               *result = Z_LVAL_P(result_p);
00113 
00114               zval_ptr_dtor(&result_p);
00115 
00116               return SUCCESS;
00117 }
00118 /* }}} */
00119 
00120 static zval **spl_pqueue_extract_helper(zval **value, int flags) /* {{{ */
00121 {
00122        if ((flags & SPL_PQUEUE_EXTR_BOTH) == SPL_PQUEUE_EXTR_BOTH) {
00123               return value;
00124        } else if ((flags & SPL_PQUEUE_EXTR_BOTH) > 0) {
00125 
00126               if ((flags & SPL_PQUEUE_EXTR_DATA) == SPL_PQUEUE_EXTR_DATA) {
00127                      zval **data;
00128                      if (zend_hash_find(Z_ARRVAL_PP(value), "data", sizeof("data"), (void **) &data) == SUCCESS) {
00129                             return data;
00130                      }
00131               } else {
00132                      zval **priority;
00133                      if (zend_hash_find(Z_ARRVAL_PP(value), "priority", sizeof("priority"), (void **) &priority) == SUCCESS) {
00134                             return priority;
00135                      }
00136               }
00137        }
00138 
00139        return NULL;
00140 }
00141 /* }}} */
00142 
00143 static int spl_ptr_heap_zval_max_cmp(spl_ptr_heap_element a, spl_ptr_heap_element b, void* object TSRMLS_DC) { /* {{{ */
00144        zval result;
00145 
00146        if (EG(exception)) {
00147               return 0;
00148        }
00149 
00150        if (object) {
00151               spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object((zval *)object TSRMLS_CC);
00152               if (heap_object->fptr_cmp) {
00153                      long lval = 0;
00154                      if (spl_ptr_heap_cmp_cb_helper((zval *)object, heap_object, (zval *)a, (zval *)b, &lval TSRMLS_CC) == FAILURE) {
00155                             /* exception or call failure */
00156                             return 0;
00157                      }
00158                      return lval;
00159               }
00160        }
00161 
00162        INIT_ZVAL(result);
00163        compare_function(&result, (zval *)a, (zval *)b TSRMLS_CC);
00164        return Z_LVAL(result);
00165 }
00166 /* }}} */
00167 
00168 static int spl_ptr_heap_zval_min_cmp(spl_ptr_heap_element a, spl_ptr_heap_element b, void* object TSRMLS_DC) { /* {{{ */
00169        zval result;
00170 
00171        if (EG(exception)) {
00172               return 0;
00173        }
00174 
00175        if (object) {
00176               spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object((zval *)object TSRMLS_CC);
00177               if (heap_object->fptr_cmp) {
00178                      long lval = 0;
00179                      if (spl_ptr_heap_cmp_cb_helper((zval *)object, heap_object, (zval *)a, (zval *)b, &lval TSRMLS_CC) == FAILURE) {
00180                             /* exception or call failure */
00181                             return 0;
00182                      }
00183                      return lval;
00184               }
00185        }
00186 
00187        INIT_ZVAL(result);
00188        compare_function(&result, (zval *)b, (zval *)a TSRMLS_CC);
00189        return Z_LVAL(result);
00190 }
00191 /* }}} */
00192 
00193 static int spl_ptr_pqueue_zval_cmp(spl_ptr_heap_element a, spl_ptr_heap_element b, void* object TSRMLS_DC) { /* {{{ */
00194        zval result;
00195        zval **a_priority_pp = spl_pqueue_extract_helper((zval **)&a, SPL_PQUEUE_EXTR_PRIORITY);
00196        zval **b_priority_pp = spl_pqueue_extract_helper((zval **)&b, SPL_PQUEUE_EXTR_PRIORITY);
00197 
00198        if ((!a_priority_pp) || (!b_priority_pp)) {
00199               zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node");
00200               return 0;
00201        }
00202        if (EG(exception)) {
00203               return 0;
00204        }
00205 
00206        if (object) {
00207               spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object(object TSRMLS_CC);
00208               if (heap_object->fptr_cmp) {
00209                      long lval = 0;
00210                      if (spl_ptr_heap_cmp_cb_helper((zval *)object, heap_object, *a_priority_pp, *b_priority_pp, &lval TSRMLS_CC) == FAILURE) {
00211                             /* exception or call failure */
00212                             return 0;
00213                      }
00214                      return lval;
00215               }
00216        }
00217 
00218        INIT_ZVAL(result);
00219        compare_function(&result, *a_priority_pp, *b_priority_pp TSRMLS_CC);
00220        return Z_LVAL(result);
00221 }
00222 /* }}} */
00223 
00224 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) /* {{{ */
00225 {
00226        spl_ptr_heap *heap = emalloc(sizeof(spl_ptr_heap));
00227 
00228        heap->dtor     = dtor;
00229        heap->ctor     = ctor;
00230        heap->cmp      = cmp;
00231        heap->elements = safe_emalloc(sizeof(spl_ptr_heap_element), PTR_HEAP_BLOCK_SIZE, 0);
00232        heap->max_size = PTR_HEAP_BLOCK_SIZE;
00233        heap->count    = 0;
00234        heap->flags    = 0;
00235 
00236        return heap;
00237 }
00238 /* }}} */
00239 
00240 static void spl_ptr_heap_insert(spl_ptr_heap *heap, spl_ptr_heap_element elem, void *cmp_userdata TSRMLS_DC) { /* {{{ */
00241        int i;
00242 
00243        if (heap->count+1 > heap->max_size) {
00244               /* we need to allocate more memory */
00245               heap->elements  = (void **) safe_erealloc(heap->elements, sizeof(spl_ptr_heap_element), (heap->max_size), (sizeof(spl_ptr_heap_element) * (heap->max_size)));
00246               heap->max_size *= 2;
00247        }
00248 
00249        heap->ctor(elem TSRMLS_CC);
00250 
00251        /* sifting up */
00252        for(i = heap->count++; i > 0 && heap->cmp(heap->elements[(i-1)/2], elem, cmp_userdata TSRMLS_CC) < 0; i = (i-1)/2) {
00253               heap->elements[i] = heap->elements[(i-1)/2];
00254        }
00255 
00256        if (EG(exception)) {
00257               /* exception thrown during comparison */
00258               heap->flags |= SPL_HEAP_CORRUPTED;
00259        }
00260 
00261        heap->elements[i] = elem;
00262 
00263 }
00264 /* }}} */
00265 
00266 static spl_ptr_heap_element spl_ptr_heap_top(spl_ptr_heap *heap) { /* {{{ */
00267        if (heap->count == 0) {
00268               return NULL;
00269        }
00270 
00271        return heap->elements[0];
00272 }
00273 /* }}} */
00274 
00275 static spl_ptr_heap_element spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *cmp_userdata TSRMLS_DC) { /* {{{ */
00276        int i, j;
00277        const int limit = (heap->count-1)/2;
00278        spl_ptr_heap_element top;
00279        spl_ptr_heap_element bottom;
00280 
00281        if (heap->count == 0) {
00282               return NULL;
00283        }
00284 
00285        top    = heap->elements[0];
00286        bottom = heap->elements[--heap->count];
00287 
00288        for( i = 0; i < limit; i = j)
00289        {
00290               /* Find smaller child */
00291               j = i*2+1;
00292               if(j != heap->count && heap->cmp(heap->elements[j+1], heap->elements[j], cmp_userdata TSRMLS_CC) > 0) {
00293                      j++; /* next child is bigger */
00294               }
00295 
00296               /* swap elements between two levels */
00297               if(heap->cmp(bottom, heap->elements[j], cmp_userdata TSRMLS_CC) < 0) {
00298                      heap->elements[i] = heap->elements[j];
00299               } else {
00300                      break;
00301               }
00302        }
00303 
00304        if (EG(exception)) {
00305               /* exception thrown during comparison */
00306               heap->flags |= SPL_HEAP_CORRUPTED;
00307        }
00308 
00309        heap->elements[i] = bottom;
00310        heap->dtor(top TSRMLS_CC);
00311        return top;
00312 }
00313 /* }}} */
00314 
00315 static spl_ptr_heap *spl_ptr_heap_clone(spl_ptr_heap *from TSRMLS_DC) { /* {{{ */
00316        int i;
00317 
00318        spl_ptr_heap *heap = emalloc(sizeof(spl_ptr_heap));
00319 
00320        heap->dtor     = from->dtor;
00321        heap->ctor     = from->ctor;
00322        heap->cmp      = from->cmp;
00323        heap->max_size = from->max_size;
00324        heap->count    = from->count;
00325        heap->flags    = from->flags;
00326 
00327        heap->elements = safe_emalloc(sizeof(spl_ptr_heap_element),from->max_size,0);
00328        memcpy(heap->elements, from->elements, sizeof(spl_ptr_heap_element)*from->max_size);
00329 
00330        for (i=0; i < heap->count; ++i) {
00331               heap->ctor(heap->elements[i] TSRMLS_CC);
00332        }
00333 
00334        return heap;
00335 }
00336 /* }}} */
00337 
00338 static void spl_ptr_heap_destroy(spl_ptr_heap *heap TSRMLS_DC) { /* {{{ */
00339        int i;
00340 
00341        for (i=0; i < heap->count; ++i) {
00342               heap->dtor(heap->elements[i] TSRMLS_CC);
00343        }
00344 
00345        efree(heap->elements);
00346        efree(heap);
00347 }
00348 /* }}} */
00349 
00350 static int spl_ptr_heap_count(spl_ptr_heap *heap) { /* {{{ */
00351        return heap->count;
00352 }
00353 /* }}} */
00354 /* }}} */
00355 
00356 zend_object_iterator *spl_heap_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC);
00357 
00358 static void spl_heap_object_free_storage(void *object TSRMLS_DC) /* {{{ */
00359 {
00360        int i;
00361        spl_heap_object *intern = (spl_heap_object *)object;
00362 
00363        zend_object_std_dtor(&intern->std TSRMLS_CC);
00364 
00365        for (i = 0; i < intern->heap->count; ++i) {
00366               if (intern->heap->elements[i]) {
00367                      zval_ptr_dtor((zval **)&intern->heap->elements[i]);
00368               }
00369        }
00370 
00371        spl_ptr_heap_destroy(intern->heap TSRMLS_CC);
00372 
00373        zval_ptr_dtor(&intern->retval);
00374 
00375        if (intern->debug_info != NULL) {
00376               zend_hash_destroy(intern->debug_info);
00377               efree(intern->debug_info);
00378        }
00379 
00380        efree(object);
00381 }
00382 /* }}} */
00383 
00384 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) /* {{{ */
00385 {
00386        zend_object_value  retval;
00387        spl_heap_object   *intern;
00388        zval              *tmp;
00389        zend_class_entry  *parent = class_type;
00390        int                inherited = 0;
00391 
00392        intern = ecalloc(1, sizeof(spl_heap_object));
00393        *obj = intern;
00394        ALLOC_INIT_ZVAL(intern->retval);
00395 
00396        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
00397        zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
00398 
00399        intern->flags      = 0;
00400        intern->fptr_cmp   = NULL;
00401        intern->debug_info = NULL;
00402 
00403        if (orig) {
00404               spl_heap_object *other = (spl_heap_object*)zend_object_store_get_object(orig TSRMLS_CC);
00405               intern->ce_get_iterator = other->ce_get_iterator;
00406 
00407               if (clone_orig) {
00408                      int i;
00409                      intern->heap = spl_ptr_heap_clone(other->heap TSRMLS_CC);
00410                      for (i = 0; i < intern->heap->count; ++i) {
00411                             if (intern->heap->elements[i]) {
00412                                    Z_ADDREF_P((zval *)intern->heap->elements[i]);
00413                             }
00414                      }
00415               } else {
00416                      intern->heap = other->heap;
00417               }
00418 
00419               intern->flags = other->flags;
00420        } else {
00421               intern->heap = spl_ptr_heap_init(spl_ptr_heap_zval_max_cmp, spl_ptr_heap_zval_ctor, spl_ptr_heap_zval_dtor);
00422        }
00423 
00424        retval.handlers = &spl_handler_SplHeap;
00425 
00426        while (parent) {
00427               if (parent == spl_ce_SplPriorityQueue) {
00428                      intern->heap->cmp = spl_ptr_pqueue_zval_cmp;
00429                      intern->flags     = SPL_PQUEUE_EXTR_DATA;
00430                      retval.handlers   = &spl_handler_SplPriorityQueue;
00431                      break;
00432               }
00433 
00434               if (parent == spl_ce_SplMinHeap) {
00435                      intern->heap->cmp = spl_ptr_heap_zval_min_cmp;
00436                      break;
00437               }
00438 
00439               if (parent == spl_ce_SplMaxHeap) {
00440                      intern->heap->cmp = spl_ptr_heap_zval_max_cmp;
00441                      break;
00442               }
00443 
00444               if (parent == spl_ce_SplHeap) {
00445                      break;
00446               }
00447 
00448               parent = parent->parent;
00449               inherited = 1;
00450        }
00451 
00452        retval.handle   = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, spl_heap_object_free_storage, NULL TSRMLS_CC);
00453 
00454        if (!parent) { /* this must never happen */
00455               php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplHeap");
00456        }
00457 
00458        if (inherited) {
00459               zend_hash_find(&class_type->function_table, "compare",    sizeof("compare"),    (void **) &intern->fptr_cmp);
00460               if (intern->fptr_cmp->common.scope == parent) {
00461                      intern->fptr_cmp = NULL;
00462               }
00463               zend_hash_find(&class_type->function_table, "count",        sizeof("count"),        (void **) &intern->fptr_count);
00464               if (intern->fptr_count->common.scope == parent) {
00465                      intern->fptr_count = NULL;
00466               }
00467        }
00468 
00469        return retval;
00470 }
00471 /* }}} */
00472 
00473 static zend_object_value spl_heap_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
00474 {
00475        spl_heap_object *tmp;
00476        return spl_heap_object_new_ex(class_type, &tmp, NULL, 0 TSRMLS_CC);
00477 }
00478 /* }}} */
00479 
00480 static zend_object_value spl_heap_object_clone(zval *zobject TSRMLS_DC) /* {{{ */
00481 {
00482        zend_object_value   new_obj_val;
00483        zend_object        *old_object;
00484        zend_object        *new_object;
00485        zend_object_handle  handle = Z_OBJ_HANDLE_P(zobject);
00486        spl_heap_object    *intern;
00487 
00488        old_object  = zend_objects_get_address(zobject TSRMLS_CC);
00489        new_obj_val = spl_heap_object_new_ex(old_object->ce, &intern, zobject, 1 TSRMLS_CC);
00490        new_object  = &intern->std;
00491 
00492        zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
00493 
00494        return new_obj_val;
00495 }
00496 /* }}} */
00497 
00498 static int spl_heap_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
00499 {
00500        spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(object TSRMLS_CC);
00501 
00502        if (intern->fptr_count) {
00503               zval *rv;
00504               zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_count, "count", &rv);
00505               if (rv) {
00506                      zval_ptr_dtor(&intern->retval);
00507                      MAKE_STD_ZVAL(intern->retval);
00508                      ZVAL_ZVAL(intern->retval, rv, 1, 1);
00509                      convert_to_long(intern->retval);
00510                      *count = (long) Z_LVAL_P(intern->retval);
00511                      return SUCCESS;
00512               }
00513               *count = 0;
00514               return FAILURE;
00515        }
00516        
00517        *count = spl_ptr_heap_count(intern->heap);
00518 
00519        return SUCCESS;
00520 } 
00521 /* }}} */
00522 
00523 static HashTable* spl_heap_object_get_debug_info_helper(zend_class_entry *ce, zval *obj, int *is_temp TSRMLS_DC) { /* {{{ */
00524        spl_heap_object *intern  = (spl_heap_object*)zend_object_store_get_object(obj TSRMLS_CC);
00525        zval *tmp, zrv, *heap_array;
00526        char *pnstr;
00527        int  pnlen;
00528        int  i;
00529 
00530        *is_temp = 0;
00531 
00532        if (intern->debug_info == NULL) {
00533               ALLOC_HASHTABLE(intern->debug_info);
00534               ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
00535        }
00536 
00537        if (intern->debug_info->nApplyCount == 0) {
00538               INIT_PZVAL(&zrv);
00539               Z_ARRVAL(zrv) = intern->debug_info;
00540 
00541               zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
00542 
00543               pnstr = spl_gen_private_prop_name(ce, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
00544               add_assoc_long_ex(&zrv, pnstr, pnlen+1, intern->flags);
00545               efree(pnstr);
00546 
00547               pnstr = spl_gen_private_prop_name(ce, "isCorrupted", sizeof("isCorrupted")-1, &pnlen TSRMLS_CC);
00548               add_assoc_bool_ex(&zrv, pnstr, pnlen+1, intern->heap->flags&SPL_HEAP_CORRUPTED);
00549               efree(pnstr);
00550 
00551               ALLOC_INIT_ZVAL(heap_array);
00552               array_init(heap_array);
00553 
00554               for (i = 0; i < intern->heap->count; ++i) {
00555                      add_index_zval(heap_array, i, (zval *)intern->heap->elements[i]);
00556                      Z_ADDREF_P(intern->heap->elements[i]);
00557               }
00558 
00559               pnstr = spl_gen_private_prop_name(ce, "heap", sizeof("heap")-1, &pnlen TSRMLS_CC);
00560               add_assoc_zval_ex(&zrv, pnstr, pnlen+1, heap_array);
00561               efree(pnstr);
00562        }
00563 
00564        return intern->debug_info;
00565 }
00566 /* }}} */
00567 
00568 static HashTable* spl_heap_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */
00569 {
00570        return spl_heap_object_get_debug_info_helper(spl_ce_SplHeap, obj, is_temp TSRMLS_CC);
00571 }
00572 /* }}} */
00573 
00574 static HashTable* spl_pqueue_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */
00575 {
00576        return spl_heap_object_get_debug_info_helper(spl_ce_SplPriorityQueue, obj, is_temp TSRMLS_CC);
00577 }
00578 /* }}} */
00579 
00580 /* {{{ proto int SplHeap::count() U
00581  Return the number of elements in the heap. */
00582 SPL_METHOD(SplHeap, count)
00583 {
00584        long count;
00585        spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00586 
00587        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
00588               return;
00589        }
00590 
00591        count = spl_ptr_heap_count(intern->heap);
00592        RETURN_LONG(count);
00593 }
00594 /* }}} */
00595 
00596 /* {{{ proto int SplHeap::isEmpty() U
00597  Return true if the heap is empty. */
00598 SPL_METHOD(SplHeap, isEmpty)
00599 {
00600        spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00601 
00602        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
00603               return;
00604        }
00605 
00606        RETURN_BOOL(spl_ptr_heap_count(intern->heap)==0);
00607 }
00608 /* }}} */
00609 
00610 /* {{{ proto bool SplHeap::insert(mixed $value) U
00611           Push $value on the heap */
00612 SPL_METHOD(SplHeap, insert)
00613 {
00614        zval *value;
00615        spl_heap_object *intern;
00616 
00617        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
00618               return;
00619        }
00620 
00621        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00622 
00623        if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
00624               zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
00625               return;
00626        }
00627 
00628        SEPARATE_ARG_IF_REF(value);
00629 
00630        spl_ptr_heap_insert(intern->heap, value, getThis() TSRMLS_CC);
00631 
00632        RETURN_TRUE;
00633 } 
00634 /* }}} */
00635 
00636 /* {{{ proto mixed SplHeap::extract() U
00637           extract the element out of the top of the heap */
00638 SPL_METHOD(SplHeap, extract)
00639 {
00640        zval *value;
00641        spl_heap_object *intern;
00642 
00643        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
00644               return;
00645        }
00646 
00647        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00648 
00649        if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
00650               zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
00651               return;
00652        }
00653 
00654        value  = (zval *)spl_ptr_heap_delete_top(intern->heap, getThis() TSRMLS_CC);
00655 
00656        if (!value) {
00657               zend_throw_exception(spl_ce_RuntimeException, "Can't extract from an empty heap", 0 TSRMLS_CC);
00658               return;
00659        }
00660 
00661        RETURN_ZVAL(value, 1, 1);
00662 } 
00663 /* }}} */
00664 
00665 /* {{{ proto bool SplPriorityQueue::insert(mixed $value, mixed $priority) U
00666           Push $value with the priority $priodiry on the priorityqueue */
00667 SPL_METHOD(SplPriorityQueue, insert)
00668 {
00669        zval *data, *priority, *elem;
00670        spl_heap_object *intern;
00671 
00672        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &data, &priority) == FAILURE) {
00673               return;
00674        }
00675 
00676        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00677 
00678        if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
00679               zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
00680               return;
00681        }
00682 
00683        SEPARATE_ARG_IF_REF(data);
00684        SEPARATE_ARG_IF_REF(priority);
00685 
00686        ALLOC_INIT_ZVAL(elem);
00687 
00688        array_init(elem);
00689        add_assoc_zval_ex(elem, "data",     sizeof("data"),     data);
00690        add_assoc_zval_ex(elem, "priority", sizeof("priority"), priority);
00691 
00692        spl_ptr_heap_insert(intern->heap, elem, getThis() TSRMLS_CC);
00693 
00694        RETURN_TRUE;
00695 } 
00696 /* }}} */
00697 
00698 /* {{{ proto mixed SplPriorityQueue::extract() U
00699           extract the element out of the top of the priority queue */
00700 SPL_METHOD(SplPriorityQueue, extract)
00701 {
00702        zval *value, *value_out, **value_out_pp;
00703        spl_heap_object *intern;
00704 
00705        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
00706               return;
00707        }
00708 
00709        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00710 
00711        if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
00712               zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
00713               return;
00714        }
00715 
00716        value  = (zval *)spl_ptr_heap_delete_top(intern->heap, getThis() TSRMLS_CC);
00717 
00718        if (!value) {
00719               zend_throw_exception(spl_ce_RuntimeException, "Can't extract from an empty heap", 0 TSRMLS_CC);
00720               return;
00721        }
00722 
00723        value_out_pp = spl_pqueue_extract_helper(&value, intern->flags);
00724 
00725 
00726        if (!value_out_pp) {
00727               zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node");
00728               zval_ptr_dtor(&value);
00729               return;
00730        }
00731 
00732        value_out = *value_out_pp;
00733 
00734        Z_ADDREF_P(value_out);
00735        zval_ptr_dtor(&value);
00736 
00737        RETURN_ZVAL(value_out, 1, 1);
00738 } 
00739 /* }}} */
00740 
00741 /* {{{ proto mixed SplPriorityQueue::top() U
00742           Peek at the top element of the priority queue */
00743 SPL_METHOD(SplPriorityQueue, top)
00744 {
00745        zval *value, **value_out;
00746        spl_heap_object *intern;
00747 
00748        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
00749               return;
00750        }
00751 
00752        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00753 
00754        if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
00755               zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
00756               return;
00757        }
00758 
00759        value  = (zval *)spl_ptr_heap_top(intern->heap);
00760 
00761        if (!value) {
00762               zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty heap", 0 TSRMLS_CC);
00763               return;
00764        }
00765 
00766        value_out = spl_pqueue_extract_helper(&value, intern->flags);
00767 
00768        if (!value_out) {
00769               zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node");
00770               return;
00771        }
00772 
00773        RETURN_ZVAL(*value_out, 1, 0);
00774 }
00775 /* }}} */
00776 
00777 /* {{{ proto int SplPriorityQueue::setIteratorMode($flags) U
00778  Set the flags of extraction*/
00779 SPL_METHOD(SplPriorityQueue, setExtractFlags)
00780 {
00781        long value;
00782        spl_heap_object *intern;
00783 
00784        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) == FAILURE) {
00785               return;
00786        }
00787 
00788        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00789 
00790        intern->flags = value & SPL_PQUEUE_EXTR_MASK;
00791 
00792        RETURN_LONG(intern->flags);
00793 }
00794 /* }}} */
00795 
00796 /* {{{ proto int SplHeap::recoverFromCorruption() U
00797  Recover from a corrupted state*/
00798 SPL_METHOD(SplHeap, recoverFromCorruption)
00799 {
00800        spl_heap_object *intern;
00801 
00802        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
00803               return;
00804        }
00805 
00806        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00807 
00808        intern->heap->flags = intern->heap->flags & ~SPL_HEAP_CORRUPTED;
00809 
00810        RETURN_TRUE;
00811 }
00812 /* }}} */
00813 
00814 /* {{{ proto bool SplPriorityQueue::compare(mixed $a, mixed $b) U
00815           compare the priorities */
00816 SPL_METHOD(SplPriorityQueue, compare)
00817 {
00818        zval *a, *b;
00819 
00820        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a, &b) == FAILURE) {
00821               return;
00822        }
00823 
00824        RETURN_LONG(spl_ptr_heap_zval_max_cmp(a, b, NULL TSRMLS_CC));
00825 } 
00826 /* }}} */
00827 
00828 /* {{{ proto mixed SplHeap::top() U
00829           Peek at the top element of the heap */
00830 SPL_METHOD(SplHeap, top)
00831 {
00832        zval *value;
00833        spl_heap_object *intern;
00834 
00835        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
00836               return;
00837        }
00838 
00839        intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00840 
00841        if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
00842               zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
00843               return;
00844        }
00845 
00846        value  = (zval *)spl_ptr_heap_top(intern->heap);
00847 
00848        if (!value) {
00849               zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty heap", 0 TSRMLS_CC);
00850               return;
00851        }
00852 
00853        RETURN_ZVAL(value, 1, 0);
00854 }
00855 /* }}} */
00856 
00857 /* {{{ proto bool SplMinHeap::compare(mixed $a, mixed $b) U
00858           compare the values */
00859 SPL_METHOD(SplMinHeap, compare)
00860 {
00861        zval *a, *b;
00862 
00863        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a, &b) == FAILURE) {
00864               return;
00865        }
00866 
00867        RETURN_LONG(spl_ptr_heap_zval_min_cmp(a, b, NULL TSRMLS_CC));
00868 } 
00869 /* }}} */
00870 
00871 /* {{{ proto bool SplMaxHeap::compare(mixed $a, mixed $b) U
00872           compare the values */
00873 SPL_METHOD(SplMaxHeap, compare)
00874 {
00875        zval *a, *b;
00876 
00877        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a, &b) == FAILURE) {
00878               return;
00879        }
00880 
00881        RETURN_LONG(spl_ptr_heap_zval_max_cmp(a, b, NULL TSRMLS_CC));
00882 } 
00883 /* }}} */
00884 
00885 static void spl_heap_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
00886 {
00887        spl_heap_it *iterator = (spl_heap_it *)iter;
00888 
00889        zend_user_it_invalidate_current(iter TSRMLS_CC);
00890        zval_ptr_dtor((zval**)&iterator->intern.it.data);
00891 
00892        efree(iterator);
00893 }
00894 /* }}} */
00895 
00896 static void spl_heap_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
00897 {
00898        /* do nothing, the iterator always points to the top element */
00899 }
00900 /* }}} */
00901 
00902 static int spl_heap_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
00903 {
00904        spl_heap_it         *iterator = (spl_heap_it *)iter;
00905 
00906        return (iterator->object->heap->count != 0 ? SUCCESS : FAILURE);
00907 }
00908 /* }}} */
00909 
00910 static void spl_heap_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
00911 {
00912        spl_heap_it  *iterator = (spl_heap_it *)iter;
00913        zval        **element  = (zval **)&iterator->object->heap->elements[0];
00914 
00915        if (iterator->object->heap->flags & SPL_HEAP_CORRUPTED) {
00916               zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
00917               return;
00918        }
00919 
00920        if (iterator->object->heap->count == 0 || !*element) {
00921               *data = NULL;
00922        } else {
00923               *data = element;
00924        }
00925 }
00926 /* }}} */
00927 
00928 static void spl_pqueue_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
00929 {
00930        spl_heap_it  *iterator = (spl_heap_it *)iter;
00931        zval        **element  = (zval **)&iterator->object->heap->elements[0];
00932 
00933        if (iterator->object->heap->flags & SPL_HEAP_CORRUPTED) {
00934               zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
00935               return;
00936        }
00937 
00938        if (iterator->object->heap->count == 0 || !*element) {
00939               *data = NULL;
00940        } else {
00941               *data = spl_pqueue_extract_helper(element, iterator->object->flags);
00942               if (!*data) {
00943                      zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node");
00944               }
00945        }
00946 }
00947 /* }}} */
00948 
00949 static int spl_heap_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
00950 {
00951        spl_heap_it *iterator = (spl_heap_it *)iter;
00952 
00953        *int_key = (ulong) iterator->object->heap->count;
00954        return HASH_KEY_IS_LONG;
00955 }
00956 /* }}} */
00957 
00958 static void spl_heap_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
00959 {
00960        zval                 *object   = (zval*)((zend_user_iterator *)iter)->it.data;
00961        spl_heap_it          *iterator = (spl_heap_it *)iter;
00962        spl_ptr_heap_element elem;
00963 
00964        if (iterator->object->heap->flags & SPL_HEAP_CORRUPTED) {
00965               zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
00966               return;
00967        }
00968 
00969        elem = spl_ptr_heap_delete_top(iterator->object->heap, object TSRMLS_CC);
00970 
00971        if (elem != NULL) {
00972               zval_ptr_dtor((zval **)&elem);
00973        }
00974 
00975        zend_user_it_invalidate_current(iter TSRMLS_CC);
00976 }
00977 /* }}} */
00978 
00979 /* {{{  proto int SplHeap::key() U
00980    Return current array key */
00981 SPL_METHOD(SplHeap, key)
00982 {
00983        spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00984        
00985        if (zend_parse_parameters_none() == FAILURE) {
00986               return;
00987        }             
00988        
00989        RETURN_LONG(intern->heap->count - 1);
00990 }
00991 /* }}} */
00992 
00993 /* {{{ proto void SplHeap::next() U
00994    Move to next entry */
00995 SPL_METHOD(SplHeap, next)
00996 {
00997        spl_heap_object      *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00998        spl_ptr_heap_element  elem   = spl_ptr_heap_delete_top(intern->heap, getThis() TSRMLS_CC);
00999        
01000        if (zend_parse_parameters_none() == FAILURE) {
01001               return;
01002        }
01003 
01004        if (elem != NULL) {
01005               zval_ptr_dtor((zval **)&elem);
01006        }
01007 }
01008 /* }}} */
01009 
01010 /* {{{ proto bool SplHeap::valid() U
01011    Check whether the datastructure contains more entries */
01012 SPL_METHOD(SplHeap, valid)
01013 {
01014        spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
01015        
01016        if (zend_parse_parameters_none() == FAILURE) {
01017               return;
01018        }
01019 
01020        RETURN_BOOL(intern->heap->count != 0);
01021 }
01022 /* }}} */
01023 
01024 /* {{{ proto void SplHeap::rewind() U
01025    Rewind the datastructure back to the start */
01026 SPL_METHOD(SplHeap, rewind)
01027 {
01028        if (zend_parse_parameters_none() == FAILURE) {
01029               return;
01030        }
01031        /* do nothing, the iterator always points to the top element */
01032 }
01033 /* }}} */
01034 
01035 /* {{{ proto mixed|NULL SplHeap::current() U
01036    Return current datastructure entry */
01037 SPL_METHOD(SplHeap, current)
01038 {
01039        spl_heap_object *intern  = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
01040        zval            *element = (zval *)intern->heap->elements[0];
01041        
01042        if (zend_parse_parameters_none() == FAILURE) {
01043               return;
01044        }
01045 
01046        if (!intern->heap->count || !element) {
01047               RETURN_NULL();
01048        } else {
01049               RETURN_ZVAL(element, 1, 0);
01050        }
01051 }
01052 /* }}} */
01053 
01054 /* {{{ proto mixed|NULL SplPriorityQueue::current() U
01055    Return current datastructure entry */
01056 SPL_METHOD(SplPriorityQueue, current)
01057 {
01058        spl_heap_object  *intern  = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
01059        zval            **element = (zval **)&intern->heap->elements[0];
01060        
01061        if (zend_parse_parameters_none() == FAILURE) {
01062               return;
01063        }
01064 
01065        if (!intern->heap->count || !*element) {
01066               RETURN_NULL();
01067        } else {
01068               zval **data = spl_pqueue_extract_helper(element, intern->flags);
01069 
01070               if (!data) {
01071                      zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node");
01072                      RETURN_NULL();
01073               }
01074 
01075               RETURN_ZVAL(*data, 1, 0);
01076        }
01077 }
01078 /* }}} */
01079 
01080 /* iterator handler table */
01081 zend_object_iterator_funcs spl_heap_it_funcs = {
01082        spl_heap_it_dtor,
01083        spl_heap_it_valid,
01084        spl_heap_it_get_current_data,
01085        spl_heap_it_get_current_key,
01086        spl_heap_it_move_forward,
01087        spl_heap_it_rewind
01088 };
01089 
01090 zend_object_iterator_funcs spl_pqueue_it_funcs = {
01091        spl_heap_it_dtor,
01092        spl_heap_it_valid,
01093        spl_pqueue_it_get_current_data,
01094        spl_heap_it_get_current_key,
01095        spl_heap_it_move_forward,
01096        spl_heap_it_rewind
01097 };
01098 
01099 zend_object_iterator *spl_heap_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
01100 {
01101        spl_heap_it     *iterator;
01102        spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object(object TSRMLS_CC);
01103 
01104        if (by_ref) {
01105               zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC);
01106               return NULL;
01107        }
01108 
01109        Z_ADDREF_P(object);
01110 
01111        iterator                  = emalloc(sizeof(spl_heap_it));
01112        iterator->intern.it.data  = (void*)object;
01113        iterator->intern.it.funcs = &spl_heap_it_funcs;
01114        iterator->intern.ce       = ce;
01115        iterator->intern.value    = NULL;
01116        iterator->flags           = heap_object->flags;
01117        iterator->object          = heap_object;
01118 
01119        return (zend_object_iterator*)iterator;
01120 }
01121 /* }}} */
01122 
01123 zend_object_iterator *spl_pqueue_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
01124 {
01125        spl_heap_it     *iterator;
01126        spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object(object TSRMLS_CC);
01127 
01128        if (by_ref) {
01129               zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC);
01130               return NULL;
01131        }
01132 
01133        Z_ADDREF_P(object);
01134 
01135        iterator                  = emalloc(sizeof(spl_heap_it));
01136        iterator->intern.it.data  = (void*)object;
01137        iterator->intern.it.funcs = &spl_pqueue_it_funcs;
01138        iterator->intern.ce       = ce;
01139        iterator->intern.value    = NULL;
01140        iterator->flags           = heap_object->flags;
01141        iterator->object          = heap_object;
01142 
01143        return (zend_object_iterator*)iterator;
01144 }
01145 /* }}} */
01146 
01147 ZEND_BEGIN_ARG_INFO(arginfo_heap_insert, 0)
01148        ZEND_ARG_INFO(0, value)
01149 ZEND_END_ARG_INFO()
01150 
01151 ZEND_BEGIN_ARG_INFO(arginfo_heap_compare, 0)
01152        ZEND_ARG_INFO(0, a)
01153        ZEND_ARG_INFO(0, b)
01154 ZEND_END_ARG_INFO()
01155 
01156 ZEND_BEGIN_ARG_INFO(arginfo_pqueue_insert, 0)
01157        ZEND_ARG_INFO(0, value)
01158        ZEND_ARG_INFO(0, priority)
01159 ZEND_END_ARG_INFO()
01160 
01161 ZEND_BEGIN_ARG_INFO(arginfo_pqueue_setflags, 0)
01162        ZEND_ARG_INFO(0, flags)
01163 ZEND_END_ARG_INFO()
01164 
01165 ZEND_BEGIN_ARG_INFO(arginfo_splheap_void, 0)
01166 ZEND_END_ARG_INFO()
01167 
01168 static const zend_function_entry spl_funcs_SplMinHeap[] = {
01169        SPL_ME(SplMinHeap, compare, arginfo_heap_compare, ZEND_ACC_PROTECTED)
01170        {NULL, NULL, NULL}
01171 };
01172 static const zend_function_entry spl_funcs_SplMaxHeap[] = {
01173        SPL_ME(SplMaxHeap, compare, arginfo_heap_compare, ZEND_ACC_PROTECTED)
01174        {NULL, NULL, NULL}
01175 };
01176 
01177 static const zend_function_entry spl_funcs_SplPriorityQueue[] = {
01178        SPL_ME(SplPriorityQueue, compare,               arginfo_heap_compare,    ZEND_ACC_PUBLIC)
01179        SPL_ME(SplPriorityQueue, insert,                arginfo_pqueue_insert,   ZEND_ACC_PUBLIC)
01180        SPL_ME(SplPriorityQueue, setExtractFlags,       arginfo_pqueue_setflags, ZEND_ACC_PUBLIC)
01181        SPL_ME(SplPriorityQueue, top,                   arginfo_splheap_void,    ZEND_ACC_PUBLIC)
01182        SPL_ME(SplPriorityQueue, extract,               arginfo_splheap_void,    ZEND_ACC_PUBLIC)
01183        SPL_ME(SplHeap,          count,                 arginfo_splheap_void,    ZEND_ACC_PUBLIC)
01184        SPL_ME(SplHeap,          isEmpty,               arginfo_splheap_void,    ZEND_ACC_PUBLIC)
01185        SPL_ME(SplHeap,          rewind,                arginfo_splheap_void,    ZEND_ACC_PUBLIC)
01186        SPL_ME(SplPriorityQueue, current,               arginfo_splheap_void,    ZEND_ACC_PUBLIC)
01187        SPL_ME(SplHeap,          key,                   arginfo_splheap_void,    ZEND_ACC_PUBLIC)
01188        SPL_ME(SplHeap,          next,                  arginfo_splheap_void,    ZEND_ACC_PUBLIC)
01189        SPL_ME(SplHeap,          valid,                 arginfo_splheap_void,    ZEND_ACC_PUBLIC)
01190        SPL_ME(SplHeap,          recoverFromCorruption, arginfo_splheap_void,    ZEND_ACC_PUBLIC)
01191        {NULL, NULL, NULL}
01192 };
01193 
01194 static const zend_function_entry spl_funcs_SplHeap[] = {
01195        SPL_ME(SplHeap, extract,               arginfo_splheap_void, ZEND_ACC_PUBLIC)
01196        SPL_ME(SplHeap, insert,                arginfo_heap_insert, ZEND_ACC_PUBLIC)
01197        SPL_ME(SplHeap, top,                   arginfo_splheap_void, ZEND_ACC_PUBLIC)
01198        SPL_ME(SplHeap, count,                 arginfo_splheap_void, ZEND_ACC_PUBLIC)
01199        SPL_ME(SplHeap, isEmpty,               arginfo_splheap_void, ZEND_ACC_PUBLIC)
01200        SPL_ME(SplHeap, rewind,                arginfo_splheap_void, ZEND_ACC_PUBLIC)
01201        SPL_ME(SplHeap, current,               arginfo_splheap_void, ZEND_ACC_PUBLIC)
01202        SPL_ME(SplHeap, key,                   arginfo_splheap_void, ZEND_ACC_PUBLIC)
01203        SPL_ME(SplHeap, next,                  arginfo_splheap_void, ZEND_ACC_PUBLIC)
01204        SPL_ME(SplHeap, valid,                 arginfo_splheap_void, ZEND_ACC_PUBLIC)
01205        SPL_ME(SplHeap, recoverFromCorruption, arginfo_splheap_void, ZEND_ACC_PUBLIC)
01206        ZEND_FENTRY(compare, NULL, NULL, ZEND_ACC_PROTECTED|ZEND_ACC_ABSTRACT)
01207        {NULL, NULL, NULL}
01208 };
01209 /* }}} */
01210 
01211 PHP_MINIT_FUNCTION(spl_heap) /* {{{ */
01212 {
01213        REGISTER_SPL_STD_CLASS_EX(SplHeap, spl_heap_object_new, spl_funcs_SplHeap);
01214        memcpy(&spl_handler_SplHeap, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
01215 
01216        spl_handler_SplHeap.clone_obj      = spl_heap_object_clone;
01217        spl_handler_SplHeap.count_elements = spl_heap_object_count_elements;
01218        spl_handler_SplHeap.get_debug_info = spl_heap_object_get_debug_info;
01219 
01220        REGISTER_SPL_IMPLEMENTS(SplHeap, Iterator);
01221        REGISTER_SPL_IMPLEMENTS(SplHeap, Countable);
01222 
01223        spl_ce_SplHeap->get_iterator = spl_heap_get_iterator;
01224 
01225        REGISTER_SPL_SUB_CLASS_EX(SplMinHeap,           SplHeap,        spl_heap_object_new, spl_funcs_SplMinHeap);
01226        REGISTER_SPL_SUB_CLASS_EX(SplMaxHeap,           SplHeap,        spl_heap_object_new, spl_funcs_SplMaxHeap);
01227 
01228        spl_ce_SplMaxHeap->get_iterator = spl_heap_get_iterator;
01229        spl_ce_SplMinHeap->get_iterator = spl_heap_get_iterator;
01230 
01231        REGISTER_SPL_STD_CLASS_EX(SplPriorityQueue, spl_heap_object_new, spl_funcs_SplPriorityQueue);
01232        memcpy(&spl_handler_SplPriorityQueue, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
01233 
01234        spl_handler_SplPriorityQueue.clone_obj      = spl_heap_object_clone;
01235        spl_handler_SplPriorityQueue.count_elements = spl_heap_object_count_elements;
01236        spl_handler_SplPriorityQueue.get_debug_info = spl_pqueue_object_get_debug_info;
01237 
01238        REGISTER_SPL_IMPLEMENTS(SplPriorityQueue, Iterator);
01239        REGISTER_SPL_IMPLEMENTS(SplPriorityQueue, Countable);
01240 
01241        spl_ce_SplPriorityQueue->get_iterator = spl_pqueue_get_iterator;
01242 
01243        REGISTER_SPL_CLASS_CONST_LONG(SplPriorityQueue, "EXTR_BOTH",      SPL_PQUEUE_EXTR_BOTH);
01244        REGISTER_SPL_CLASS_CONST_LONG(SplPriorityQueue, "EXTR_PRIORITY",  SPL_PQUEUE_EXTR_PRIORITY);
01245        REGISTER_SPL_CLASS_CONST_LONG(SplPriorityQueue, "EXTR_DATA",      SPL_PQUEUE_EXTR_DATA);
01246 
01247        return SUCCESS;
01248 }
01249 /* }}} */
01250 
01251 /*
01252  * Local variables:
01253  * tab-width: 4
01254  * c-basic-offset: 4
01255  * End:
01256  * vim600: fdm=marker
01257  * vim: noet sw=4 ts=4
01258  */
01259