Beispiel #1
0
/* {{{ proto void SplDoublyLinkedList::__unserialize(array serialized) */
SPL_METHOD(SplDoublyLinkedList, __unserialize) {
	spl_dllist_object *intern = Z_SPLDLLIST_P(ZEND_THIS);
	HashTable *data;
	zval *flags_zv, *storage_zv, *members_zv, *elem;

	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "h", &data) == FAILURE) {
		return;
	}

	flags_zv = zend_hash_index_find(data, 0);
	storage_zv = zend_hash_index_find(data, 1);
	members_zv = zend_hash_index_find(data, 2);
	if (!flags_zv || !storage_zv || !members_zv ||
			Z_TYPE_P(flags_zv) != IS_LONG || Z_TYPE_P(storage_zv) != IS_ARRAY ||
			Z_TYPE_P(members_zv) != IS_ARRAY) {
		zend_throw_exception(spl_ce_UnexpectedValueException,
			"Incomplete or ill-typed serialization data", 0);
		return;
	}

	intern->flags = (int) Z_LVAL_P(flags_zv);

	ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(storage_zv), elem) {
		spl_ptr_llist_push(intern->llist, elem);
	} ZEND_HASH_FOREACH_END();
Beispiel #2
0
/* {{{ proto void SplDoublyLinkedList::unserialize(string serialized)
 Unserializes storage */
SPL_METHOD(SplDoublyLinkedList, unserialize)
{
	spl_dllist_object *intern = Z_SPLDLLIST_P(getThis());
	zval flags, elem;
	char *buf;
	size_t buf_len;
	const unsigned char *p, *s;
	php_unserialize_data_t var_hash;
	
	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &buf, &buf_len) == FAILURE) {
		return;
	}

	if (buf_len == 0) {
		return;
	}

	s = p = (const unsigned char*)buf;
	PHP_VAR_UNSERIALIZE_INIT(var_hash);

	/* flags */
	if (!php_var_unserialize(&flags, &p, s + buf_len, &var_hash)) {
		goto error;
	}

	if (Z_TYPE(flags) != IS_LONG) {
		zval_ptr_dtor(&flags);
		goto error;
	}

	intern->flags = (int)Z_LVAL(flags);
	zval_ptr_dtor(&flags);

	/* elements */
	while(*p == ':') {
		++p;
		if (!php_var_unserialize(&elem, &p, s + buf_len, &var_hash)) {
			goto error;
		}

		spl_ptr_llist_push(intern->llist, &elem);
		zval_ptr_dtor(&elem);
	}

	if (*p != '\0') {
		goto error;
	}

	PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
	return;

error:
	PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
	zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Error at offset %pd of %d bytes", (zend_long)((char*)p - buf), buf_len);
	return;

} /* }}} */
Beispiel #3
0
/* {{{ proto void SplDoublyLinkedList::add(mixed $index, mixed $newval)
 Inserts a new entry before the specified $index consisting of $newval. */
SPL_METHOD(SplDoublyLinkedList, add)
{
	zval                  *zindex, *value;
	spl_dllist_object     *intern;
	spl_ptr_llist_element *element;
	zend_long                  index;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &zindex, &value) == FAILURE) {
		return;
	}

	intern = Z_SPLDLLIST_P(getThis());
	index  = spl_offset_convert_to_long(zindex);

	if (index < 0 || index > intern->llist->count) {
		zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0);
		return;
	}

	if (Z_REFCOUNTED_P(value)) {
		Z_ADDREF_P(value);
	}
	if (index == intern->llist->count) {
		/* If index is the last entry+1 then we do a push because we're not inserting before any entry */
		spl_ptr_llist_push(intern->llist, value);
	} else {
		/* Create the new element we want to insert */
		spl_ptr_llist_element *elem = emalloc(sizeof(spl_ptr_llist_element));

		/* Get the element we want to insert before */
		element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);

		ZVAL_COPY_VALUE(&elem->data, value);
		elem->rc   = 1;
		/* connect to the neighbours */
		elem->next = element;
		elem->prev = element->prev;

		/* connect the neighbours to this new element */
		if (elem->prev == NULL) {
			intern->llist->head = elem;
		} else {
			element->prev->next = elem;
		}
		element->prev = elem;

		intern->llist->count++;

		if (intern->llist->ctor) {
			intern->llist->ctor(elem);
		}
	}
} /* }}} */
Beispiel #4
0
/* {{{ proto void SplDoublyLinkedList::offsetSet(mixed $index, mixed $newval)
 Sets the value at the specified $index to $newval. */
SPL_METHOD(SplDoublyLinkedList, offsetSet)
{
	zval                  *zindex, *value;
	spl_dllist_object     *intern;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &zindex, &value) == FAILURE) {
		return;
	}

	intern = Z_SPLDLLIST_P(getThis());

	if (Z_TYPE_P(zindex) == IS_NULL) {
		/* $obj[] = ... */
		spl_ptr_llist_push(intern->llist, value);
	} else {
		/* $obj[$foo] = ... */
		zend_long                   index;
		spl_ptr_llist_element *element;

		index = spl_offset_convert_to_long(zindex);

		if (index < 0 || index >= intern->llist->count) {
			zval_ptr_dtor(value);
			zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0);
			return;
		}

		element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);

		if (element != NULL) {
			/* call dtor on the old element as in spl_ptr_llist_pop */
			if (intern->llist->dtor) {
				intern->llist->dtor(element);
			}

			/* the element is replaced, delref the old one as in
			 * SplDoublyLinkedList::pop() */
			zval_ptr_dtor(&element->data);
			ZVAL_COPY_VALUE(&element->data, value);

			/* new element, call ctor as in spl_ptr_llist_push */
			if (intern->llist->ctor) {
				intern->llist->ctor(element);
			}
		} else {
			zval_ptr_dtor(value);
			zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0);
			return;
		}
	}
} /* }}} */
Beispiel #5
0
/* {{{ proto bool SplDoublyLinkedList::push(mixed value)
	   Push $value on the SplDoublyLinkedList */
SPL_METHOD(SplDoublyLinkedList, push)
{
	zval *value;
	spl_dllist_object *intern;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &value) == FAILURE) {
		return;
	}

	intern = Z_SPLDLLIST_P(ZEND_THIS);
	spl_ptr_llist_push(intern->llist, value);

	RETURN_TRUE;
}
Beispiel #6
0
static void spl_ptr_llist_copy(spl_ptr_llist *from, spl_ptr_llist *to) /* {{{ */
{
	spl_ptr_llist_element *current = from->head, *next;
//???	spl_ptr_llist_ctor_func ctor = from->ctor;

	while (current) {
		next = current->next;

		/*??? FIXME
		if (ctor) {
			ctor(current);
		}
		*/

		spl_ptr_llist_push(to, &current->data);
		current = next;
	}

}