--- embedaddon/php/ext/spl/spl_dllist.c 2012/02/21 23:48:01 1.1 +++ embedaddon/php/ext/spl/spl_dllist.c 2014/06/15 20:03:55 1.1.1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2012 The PHP Group | + | Copyright (c) 1997-2014 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: spl_dllist.c,v 1.1 2012/02/21 23:48:01 misho Exp $ */ +/* $Id: spl_dllist.c,v 1.1.1.5 2014/06/15 20:03:55 misho Exp $ */ #ifdef HAVE_CONFIG_H # include "config.h" @@ -27,6 +27,9 @@ #include "zend_hash.h" #include "php_spl.h" +#include "ext/standard/info.h" +#include "ext/standard/php_var.h" +#include "ext/standard/php_smart_str.h" #include "spl_functions.h" #include "spl_engine.h" #include "spl_iterators.h" @@ -365,9 +368,8 @@ zend_object_iterator *spl_dllist_get_iterator(zend_cla static zend_object_value spl_dllist_object_new_ex(zend_class_entry *class_type, spl_dllist_object **obj, zval *orig, int clone_orig TSRMLS_DC) /* {{{ */ { - zend_object_value retval; + zend_object_value retval = {0}; spl_dllist_object *intern; - zval *tmp; zend_class_entry *parent = class_type; int inherited = 0; @@ -376,7 +378,7 @@ static zend_object_value spl_dllist_object_new_ex(zend ALLOC_INIT_ZVAL(intern->retval); zend_object_std_init(&intern->std, class_type TSRMLS_CC); - zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + object_properties_init(&intern->std, class_type); intern->flags = 0; intern->traverse_position = 0; @@ -523,6 +525,9 @@ static HashTable* spl_dllist_object_get_debug_info(zva INIT_PZVAL(&zrv); Z_ARRVAL(zrv) = intern->debug_info; + if (!intern->std.properties) { + rebuild_object_properties(&intern->std); + } zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC); @@ -875,7 +880,7 @@ SPL_METHOD(SplDoublyLinkedList, offsetUnset) } intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - index = (int)spl_offset_convert_to_long(zindex TSRMLS_CC); + index = spl_offset_convert_to_long(zindex TSRMLS_CC); llist = intern->llist; if (index < 0 || index >= intern->llist->count) { @@ -1127,7 +1132,109 @@ SPL_METHOD(SplDoublyLinkedList, current) } } /* }}} */ +/* {{{ proto string SplDoublyLinkedList::serialize() + Serializes storage */ +SPL_METHOD(SplDoublyLinkedList, serialize) +{ + spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + smart_str buf = {0}; + spl_ptr_llist_element *current = intern->llist->head, *next; + zval *flags; + php_serialize_data_t var_hash; + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + PHP_VAR_SERIALIZE_INIT(var_hash); + + /* flags */ + MAKE_STD_ZVAL(flags); + ZVAL_LONG(flags, intern->flags); + php_var_serialize(&buf, &flags, &var_hash TSRMLS_CC); + zval_ptr_dtor(&flags); + + /* elements */ + while (current) { + smart_str_appendc(&buf, ':'); + next = current->next; + + php_var_serialize(&buf, (zval **)¤t->data, &var_hash TSRMLS_CC); + + current = next; + } + + smart_str_0(&buf); + + /* done */ + PHP_VAR_SERIALIZE_DESTROY(var_hash); + + if (buf.c) { + RETURN_STRINGL(buf.c, buf.len, 0); + } else { + RETURN_NULL(); + } + +} /* }}} */ + +/* {{{ proto void SplDoublyLinkedList::unserialize(string serialized) + Unserializes storage */ +SPL_METHOD(SplDoublyLinkedList, unserialize) +{ + spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + zval *flags, *elem; + char *buf; + int buf_len; + const unsigned char *p, *s; + php_unserialize_data_t var_hash; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) { + return; + } + + if (buf_len == 0) { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Serialized string cannot be empty"); + return; + } + + s = p = (const unsigned char*)buf; + PHP_VAR_UNSERIALIZE_INIT(var_hash); + + /* flags */ + ALLOC_INIT_ZVAL(flags); + if (!php_var_unserialize(&flags, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(flags) != IS_LONG) { + zval_ptr_dtor(&flags); + goto error; + } + intern->flags = Z_LVAL_P(flags); + zval_ptr_dtor(&flags); + + /* elements */ + while(*p == ':') { + ++p; + ALLOC_INIT_ZVAL(elem); + if (!php_var_unserialize(&elem, &p, s + buf_len, &var_hash TSRMLS_CC)) { + zval_ptr_dtor(&elem); + goto error; + } + + spl_ptr_llist_push(intern->llist, elem TSRMLS_CC); + } + + 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 TSRMLS_CC, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len); + return; + +} /* }}} */ + /* iterator handler table */ zend_object_iterator_funcs spl_dllist_it_funcs = { spl_dllist_it_dtor, @@ -1188,6 +1295,10 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_dllist_void, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO(arginfo_dllist_serialized, 0) + ZEND_ARG_INFO(0, serialized) +ZEND_END_ARG_INFO(); + static const zend_function_entry spl_funcs_SplQueue[] = { SPL_MA(SplQueue, enqueue, SplDoublyLinkedList, push, arginfo_dllist_push, ZEND_ACC_PUBLIC) SPL_MA(SplQueue, dequeue, SplDoublyLinkedList, shift, arginfo_dllist_void, ZEND_ACC_PUBLIC) @@ -1201,20 +1312,26 @@ static const zend_function_entry spl_funcs_SplDoublyLi SPL_ME(SplDoublyLinkedList, unshift, arginfo_dllist_push, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, top, arginfo_dllist_void, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, bottom, arginfo_dllist_void, ZEND_ACC_PUBLIC) - SPL_ME(SplDoublyLinkedList, count, arginfo_dllist_void, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, isEmpty, arginfo_dllist_void, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, setIteratorMode, arginfo_dllist_setiteratormode, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, getIteratorMode, arginfo_dllist_void, ZEND_ACC_PUBLIC) + /* Countable */ + SPL_ME(SplDoublyLinkedList, count, arginfo_dllist_void, ZEND_ACC_PUBLIC) + /* ArrayAccess */ SPL_ME(SplDoublyLinkedList, offsetExists, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, offsetGet, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, offsetSet, arginfo_dllist_offsetSet, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, offsetUnset, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC) + /* Iterator */ SPL_ME(SplDoublyLinkedList, rewind, arginfo_dllist_void, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, current, arginfo_dllist_void, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, key, arginfo_dllist_void, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, next, arginfo_dllist_void, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, prev, arginfo_dllist_void, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, valid, arginfo_dllist_void, ZEND_ACC_PUBLIC) + /* Serializable */ + SPL_ME(SplDoublyLinkedList, unserialize, arginfo_dllist_serialized, ZEND_ACC_PUBLIC) + SPL_ME(SplDoublyLinkedList, serialize, arginfo_dllist_void, ZEND_ACC_PUBLIC) PHP_FE_END }; /* }}} */ @@ -1236,6 +1353,7 @@ PHP_MINIT_FUNCTION(spl_dllist) /* {{{ */ REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Iterator); REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Countable); REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, ArrayAccess); + REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Serializable); spl_ce_SplDoublyLinkedList->get_iterator = spl_dllist_get_iterator;