typedef struct _spl_heap_it spl_heap_it;
struct _spl_heap_object {
- zend_object std;
spl_ptr_heap *heap;
zval retval;
int flags;
zend_function *fptr_cmp;
zend_function *fptr_count;
HashTable *debug_info;
+ zend_object std;
};
/* define an overloaded iterator structure */
int flags;
};
+static inline spl_heap_object *spl_heap_from_obj(zend_object *obj) /* {{{ */ {
+ return (spl_heap_object*)((char*)(obj) - XtOffsetOf(spl_heap_object, std));
+}
+/* }}} */
+
+#define Z_SPLHEAP_P(zv) spl_heap_from_obj(Z_OBJ_P((zv)))
+
static void spl_ptr_heap_zval_dtor(zval *elem TSRMLS_DC) { /* {{{ */
if (!ZVAL_IS_UNDEF(elem)) {
zval_ptr_dtor(elem);
}
if (object) {
- spl_heap_object *heap_object = (spl_heap_object*)Z_OBJ_P(object);
+ spl_heap_object *heap_object = Z_SPLHEAP_P(object);
if (heap_object->fptr_cmp) {
long lval = 0;
if (spl_ptr_heap_cmp_cb_helper(object, heap_object, a, b, &lval TSRMLS_CC) == FAILURE) {
}
/* }}} */
-static int spl_ptr_heap_zval_min_cmp(zval *a, zval *b, zval* object TSRMLS_DC) { /* {{{ */
+static int spl_ptr_heap_zval_min_cmp(zval *a, zval *b, zval *object TSRMLS_DC) { /* {{{ */
zval result;
if (EG(exception)) {
}
if (object) {
- spl_heap_object *heap_object = (spl_heap_object*)Z_OBJ_P(object);
+ spl_heap_object *heap_object = Z_SPLHEAP_P(object);
if (heap_object->fptr_cmp) {
long lval = 0;
- if (spl_ptr_heap_cmp_cb_helper((zval *)object, heap_object, (zval *)a, (zval *)b, &lval TSRMLS_CC) == FAILURE) {
+ if (spl_ptr_heap_cmp_cb_helper(object, heap_object, a, b, &lval TSRMLS_CC) == FAILURE) {
/* exception or call failure */
return 0;
}
}
if (object) {
- spl_heap_object *heap_object = (spl_heap_object*)Z_OBJ_P(object);
+ spl_heap_object *heap_object = Z_SPLHEAP_P(object);
if (heap_object->fptr_cmp) {
long lval = 0;
if (spl_ptr_heap_cmp_cb_helper((zval *)object, heap_object, a_priority_p, b_priority_p, &lval TSRMLS_CC) == FAILURE) {
}
ZVAL_COPY_VALUE(&heap->elements[i], elem);
-
}
/* }}} */
}
/* }}} */
-static zval *spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *cmp_userdata TSRMLS_DC) { /* {{{ */
+static void spl_ptr_heap_delete_top(spl_ptr_heap *heap, zval *elem, void *cmp_userdata TSRMLS_DC) { /* {{{ */
int i, j;
const int limit = (heap->count-1)/2;
- zval *top, *bottom;
+ zval *bottom;
if (heap->count == 0) {
- return NULL;
+ ZVAL_UNDEF(elem);
+ return;
}
- top = &heap->elements[0];
+ ZVAL_COPY_VALUE(elem, &heap->elements[0]);
bottom = &heap->elements[--heap->count];
for (i = 0; i < limit; i = j) {
}
ZVAL_COPY_VALUE(&heap->elements[i], bottom);
- heap->dtor(top TSRMLS_CC);
- return ZVAL_IS_UNDEF(top)? NULL : top;
+ heap->dtor(elem TSRMLS_CC);
}
/* }}} */
static void spl_heap_object_free_storage(zend_object *object TSRMLS_DC) /* {{{ */
{
int i;
- spl_heap_object *intern = (spl_heap_object *)object;
+ spl_heap_object *intern = spl_heap_from_obj(object);
zend_object_std_dtor(&intern->std TSRMLS_CC);
efree(intern->debug_info);
}
- efree(object);
+ efree(intern);
}
/* }}} */
zend_class_entry *parent = class_type;
int inherited = 0;
- intern = ecalloc(1, sizeof(spl_heap_object));
+ intern = ecalloc(1, sizeof(spl_heap_object) + sizeof(zval) * (parent->default_properties_count - 1));
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
object_properties_init(&intern->std, class_type);
intern->debug_info = NULL;
if (orig) {
- spl_heap_object *other = (spl_heap_object*)Z_OBJ_P(orig);
+ spl_heap_object *other = Z_SPLHEAP_P(orig);
intern->ce_get_iterator = other->ce_get_iterator;
if (clone_orig) {
static int spl_heap_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
{
- spl_heap_object *intern = (spl_heap_object*)Z_OBJ_P(object);
+ spl_heap_object *intern = Z_SPLHEAP_P(object);
if (intern->fptr_count) {
zval rv;
/* }}} */
static HashTable* spl_heap_object_get_debug_info_helper(zend_class_entry *ce, zval *obj, int *is_temp TSRMLS_DC) { /* {{{ */
- spl_heap_object *intern = (spl_heap_object*)Z_OBJ_P(obj);
+ spl_heap_object *intern = Z_SPLHEAP_P(obj);
zval tmp, heap_array;
zend_string *pnstr;
int i;
SPL_METHOD(SplHeap, count)
{
long count;
- spl_heap_object *intern = (spl_heap_object*)Z_OBJ_P(getThis());
+ spl_heap_object *intern = Z_SPLHEAP_P(getThis());
if (zend_parse_parameters_none() == FAILURE) {
return;
Return true if the heap is empty. */
SPL_METHOD(SplHeap, isEmpty)
{
- spl_heap_object *intern = (spl_heap_object*)Z_OBJ_P(getThis());
+ spl_heap_object *intern = Z_SPLHEAP_P(getThis());
if (zend_parse_parameters_none() == FAILURE) {
return;
return;
}
- intern = (spl_heap_object*)Z_OBJ_P(getThis());
+ intern = Z_SPLHEAP_P(getThis());
if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
}
SEPARATE_ARG_IF_REF(value);
-
spl_ptr_heap_insert(intern->heap, value, getThis() TSRMLS_CC);
RETURN_TRUE;
extract the element out of the top of the heap */
SPL_METHOD(SplHeap, extract)
{
- zval *value;
+ zval value;
spl_heap_object *intern;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
- intern = (spl_heap_object*)Z_OBJ_P(getThis());
+ intern = Z_SPLHEAP_P(getThis());
if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
return;
}
- value = (zval *)spl_ptr_heap_delete_top(intern->heap, getThis() TSRMLS_CC);
+ spl_ptr_heap_delete_top(intern->heap, &value, getThis() TSRMLS_CC);
- if (!value) {
+ if (ZVAL_IS_UNDEF(&value)) {
zend_throw_exception(spl_ce_RuntimeException, "Can't extract from an empty heap", 0 TSRMLS_CC);
return;
}
- RETURN_ZVAL(value, 1, 1);
+ RETURN_ZVAL(&value, 1, 1);
}
/* }}} */
return;
}
- intern = (spl_heap_object*)Z_OBJ_P(getThis());
+ intern = Z_SPLHEAP_P(getThis());
if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
extract the element out of the top of the priority queue */
SPL_METHOD(SplPriorityQueue, extract)
{
- zval *value, *value_out;
+ zval value, *value_out;
spl_heap_object *intern;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
- intern = (spl_heap_object*)Z_OBJ_P(getThis());
+ intern = Z_SPLHEAP_P(getThis());
if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
return;
}
- value = spl_ptr_heap_delete_top(intern->heap, getThis() TSRMLS_CC);
+ spl_ptr_heap_delete_top(intern->heap, &value, getThis() TSRMLS_CC);
- if (!value || ZVAL_IS_UNDEF(value)) {
+ if (ZVAL_IS_UNDEF(&value)) {
zend_throw_exception(spl_ce_RuntimeException, "Can't extract from an empty heap", 0 TSRMLS_CC);
return;
}
- value_out = spl_pqueue_extract_helper(value, intern->flags);
+ value_out = spl_pqueue_extract_helper(&value, intern->flags);
if (!value_out) {
zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node");
- zval_ptr_dtor(value);
+ zval_ptr_dtor(&value);
return;
}
if (Z_REFCOUNTED_P(value_out)) {
Z_ADDREF_P(value_out);
}
- zval_ptr_dtor(value);
+ zval_ptr_dtor(&value);
RETURN_ZVAL(value_out, 1, 1);
}
return;
}
- intern = (spl_heap_object*)Z_OBJ_P(getThis());
+ intern = Z_SPLHEAP_P(getThis());
if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
return;
}
- intern = (spl_heap_object*)Z_OBJ_P(getThis());
+ intern = Z_SPLHEAP_P(getThis());
intern->flags = value & SPL_PQUEUE_EXTR_MASK;
return;
}
- intern = (spl_heap_object*)Z_OBJ_P(getThis());
+ intern = Z_SPLHEAP_P(getThis());
intern->heap->flags = intern->heap->flags & ~SPL_HEAP_CORRUPTED;
return;
}
- intern = (spl_heap_object*)Z_OBJ_P(getThis());
+ intern = Z_SPLHEAP_P(getThis());
if (intern->heap->flags & SPL_HEAP_CORRUPTED) {
zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
static int spl_heap_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
{
- return (((spl_heap_object *)Z_OBJ(iter->data))->heap->count != 0 ? SUCCESS : FAILURE);
+ return ((Z_SPLHEAP_P(&iter->data))->heap->count != 0 ? SUCCESS : FAILURE);
}
/* }}} */
static zval *spl_heap_it_get_current_data(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
{
- spl_heap_object *object = (spl_heap_object*)Z_OBJ(iter->data);
+ spl_heap_object *object = Z_SPLHEAP_P(&iter->data);
zval *element = &object->heap->elements[0];
if (object->heap->flags & SPL_HEAP_CORRUPTED) {
static zval *spl_pqueue_it_get_current_data(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
{
- spl_heap_object *object = (spl_heap_object*)Z_OBJ(iter->data);
+ spl_heap_object *object = Z_SPLHEAP_P(&iter->data);
zval *element = &object->heap->elements[0];
if (object->heap->flags & SPL_HEAP_CORRUPTED) {
static void spl_heap_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */
{
- spl_heap_object *object = (spl_heap_object*)Z_OBJ(iter->data);
+ spl_heap_object *object = Z_SPLHEAP_P(&iter->data);
ZVAL_LONG(key, object->heap->count - 1);
}
static void spl_heap_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
{
- spl_heap_object *object = (spl_heap_object*)Z_OBJ(iter->data);
- zval *elem;
+ spl_heap_object *object = Z_SPLHEAP_P(&iter->data);
+ zval elem;
if (object->heap->flags & SPL_HEAP_CORRUPTED) {
zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC);
return;
}
- elem = spl_ptr_heap_delete_top(object->heap, &iter->data TSRMLS_CC);
+ spl_ptr_heap_delete_top(object->heap, &elem, &iter->data TSRMLS_CC);
- if (elem != NULL) {
- zval_ptr_dtor(elem);
- }
+ zval_ptr_dtor(&elem);
zend_user_it_invalidate_current(iter TSRMLS_CC);
}
Return current array key */
SPL_METHOD(SplHeap, key)
{
- spl_heap_object *intern = (spl_heap_object*)Z_OBJ_P(getThis());
+ spl_heap_object *intern = Z_SPLHEAP_P(getThis());
if (zend_parse_parameters_none() == FAILURE) {
return;
Move to next entry */
SPL_METHOD(SplHeap, next)
{
- spl_heap_object *intern = (spl_heap_object*)Z_OBJ_P(getThis());
- zval *elem = spl_ptr_heap_delete_top(intern->heap, getThis() TSRMLS_CC);
+ spl_heap_object *intern = Z_SPLHEAP_P(getThis());
+ zval elem;
+ spl_ptr_heap_delete_top(intern->heap, &elem, getThis() TSRMLS_CC);
if (zend_parse_parameters_none() == FAILURE) {
return;
}
- if (elem != NULL) {
- zval_ptr_dtor(elem);
- }
+ zval_ptr_dtor(&elem);
}
/* }}} */
Check whether the datastructure contains more entries */
SPL_METHOD(SplHeap, valid)
{
- spl_heap_object *intern = (spl_heap_object*)Z_OBJ_P(getThis());
+ spl_heap_object *intern = Z_SPLHEAP_P(getThis());
if (zend_parse_parameters_none() == FAILURE) {
return;
Return current datastructure entry */
SPL_METHOD(SplHeap, current)
{
- spl_heap_object *intern = (spl_heap_object*)Z_OBJ_P(getThis());
+ spl_heap_object *intern = Z_SPLHEAP_P(getThis());
zval *element = &intern->heap->elements[0];
if (zend_parse_parameters_none() == FAILURE) {
Return current datastructure entry */
SPL_METHOD(SplPriorityQueue, current)
{
- spl_heap_object *intern = (spl_heap_object*)Z_OBJ_P(getThis());
+ spl_heap_object *intern = Z_SPLHEAP_P(getThis());
zval *element = &intern->heap->elements[0];
if (zend_parse_parameters_none() == FAILURE) {
zend_object_iterator *spl_heap_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
{
spl_heap_it *iterator;
- spl_heap_object *heap_object = (spl_heap_object*)Z_OBJ_P(object);
+ spl_heap_object *heap_object = Z_SPLHEAP_P(object);
if (by_ref) {
zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC);
zend_object_iterator *spl_pqueue_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
{
spl_heap_it *iterator;
- spl_heap_object *heap_object = (spl_heap_object*)Z_OBJ_P(object);
+ spl_heap_object *heap_object = Z_SPLHEAP_P(object);
if (by_ref) {
zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC);