colder Fri Jun 6 23:53:10 2008 UTC Added files: /php-src/ext/spl spl_fastarray.c spl_fastarray.h /php-src/ext/spl/tests fastarray_001.phpt fastarray_002.phpt fastarray_003.phpt
Modified files: /php-src/ext/spl config.m4 config.w32 php_spl.c spl_engine.c spl_engine.h spl_dllist.c Log: Implements C arrays wrapper
http://cvs.php.net/viewvc.cgi/php-src/ext/spl/config.m4?r1=1.25&r2=1.26&diff_format=u Index: php-src/ext/spl/config.m4 diff -u php-src/ext/spl/config.m4:1.25 php-src/ext/spl/config.m4:1.26 --- php-src/ext/spl/config.m4:1.25 Wed Apr 9 21:47:29 2008 +++ php-src/ext/spl/config.m4 Fri Jun 6 23:53:10 2008 @@ -1,4 +1,4 @@ -dnl $Id: config.m4,v 1.25 2008/04/09 21:47:29 helly Exp $ +dnl $Id: config.m4,v 1.26 2008/06/06 23:53:10 colder Exp $ dnl config.m4 for extension SPL AC_MSG_CHECKING(whether zend_object_value is packed) @@ -25,6 +25,6 @@ PHP_INSTALL_HEADERS([ext/spl/]) AC_DEFINE_UNQUOTED(HAVE_PACKED_OBJECT_VALUE, $ac_result, [Whether struct _zend_object_value is packed]) AC_DEFINE(HAVE_SPL, 1, [Whether you want SPL (Standard PHP Library) support]) - PHP_NEW_EXTENSION(spl, php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_sxe.c spl_exceptions.c spl_observer.c spl_dllist.c spl_heap.c, no) - PHP_INSTALL_HEADERS([ext/spl], [php_spl.h spl_array.h spl_directory.h spl_engine.h spl_exceptions.h spl_functions.h spl_iterators.h spl_observer.h spl_sxe.h spl_dllist.h spl_heap.h]) + PHP_NEW_EXTENSION(spl, php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_sxe.c spl_exceptions.c spl_observer.c spl_dllist.c spl_heap.c spl_fastarray.c, no) + PHP_INSTALL_HEADERS([ext/spl], [php_spl.h spl_array.h spl_directory.h spl_engine.h spl_exceptions.h spl_functions.h spl_iterators.h spl_observer.h spl_sxe.h spl_dllist.h spl_heap.h spl_fastarray.h]) PHP_ADD_EXTENSION_DEP(spl, pcre, true) http://cvs.php.net/viewvc.cgi/php-src/ext/spl/config.w32?r1=1.10&r2=1.11&diff_format=u Index: php-src/ext/spl/config.w32 diff -u php-src/ext/spl/config.w32:1.10 php-src/ext/spl/config.w32:1.11 --- php-src/ext/spl/config.w32:1.10 Fri May 2 14:10:05 2008 +++ php-src/ext/spl/config.w32 Fri Jun 6 23:53:10 2008 @@ -1,5 +1,5 @@ -// $Id: config.w32,v 1.10 2008/05/02 14:10:05 auroraeosrose Exp $ +// $Id: config.w32,v 1.11 2008/06/06 23:53:10 colder Exp $ // vim:ft=javascript -EXTENSION("spl", "php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_sxe.c spl_exceptions.c spl_observer.c spl_dllist.c spl_heap.c", false /* never shared */); +EXTENSION("spl", "php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_sxe.c spl_exceptions.c spl_observer.c spl_dllist.c spl_heap.c spl_fastarray.c", false /* never shared */); AC_DEFINE('HAVE_SPL', 1); http://cvs.php.net/viewvc.cgi/php-src/ext/spl/php_spl.c?r1=1.131&r2=1.132&diff_format=u Index: php-src/ext/spl/php_spl.c diff -u php-src/ext/spl/php_spl.c:1.131 php-src/ext/spl/php_spl.c:1.132 --- php-src/ext/spl/php_spl.c:1.131 Sun May 25 12:23:22 2008 +++ php-src/ext/spl/php_spl.c Fri Jun 6 23:53:10 2008 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_spl.c,v 1.131 2008/05/25 12:23:22 colder Exp $ */ +/* $Id: php_spl.c,v 1.132 2008/06/06 23:53:10 colder Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -37,6 +37,7 @@ #include "spl_observer.h" #include "spl_dllist.h" #include "spl_heap.h" +#include "spl_fastarray.h" #include "zend_exceptions.h" #include "zend_interfaces.h" #include "ext/standard/md5.h" @@ -156,6 +157,7 @@ SPL_ADD_CLASS(SplMinHeap, z_list, sub, allow, ce_flags); \ SPL_ADD_CLASS(SplMaxHeap, z_list, sub, allow, ce_flags); \ SPL_ADD_CLASS(SplPriorityQueue, z_list, sub, allow, ce_flags); \ + SPL_ADD_CLASS(SplFastArray, z_list, sub, allow, ce_flags); \ SPL_ADD_CLASS(BadFunctionCallException, z_list, sub, allow, ce_flags); \ SPL_ADD_CLASS(BadMethodCallException, z_list, sub, allow, ce_flags); \ SPL_ADD_CLASS(CachingIterator, z_list, sub, allow, ce_flags); \ @@ -800,6 +802,7 @@ PHP_MINIT(spl_sxe)(INIT_FUNC_ARGS_PASSTHRU); PHP_MINIT(spl_dllist)(INIT_FUNC_ARGS_PASSTHRU); PHP_MINIT(spl_heap)(INIT_FUNC_ARGS_PASSTHRU); + PHP_MINIT(spl_fastarray)(INIT_FUNC_ARGS_PASSTHRU); PHP_MINIT(spl_observer)(INIT_FUNC_ARGS_PASSTHRU); return SUCCESS; http://cvs.php.net/viewvc.cgi/php-src/ext/spl/spl_engine.c?r1=1.26&r2=1.27&diff_format=u Index: php-src/ext/spl/spl_engine.c diff -u php-src/ext/spl/spl_engine.c:1.26 php-src/ext/spl/spl_engine.c:1.27 --- php-src/ext/spl/spl_engine.c:1.26 Mon Dec 31 07:12:15 2007 +++ php-src/ext/spl/spl_engine.c Fri Jun 6 23:53:10 2008 @@ -43,6 +43,29 @@ } /* }}} */ +PHPAPI long spl_offset_convert_to_long(zval *offset TSRMLS_DC) /* {{{ */ +{ + switch(Z_TYPE_P(offset)) { + case IS_STRING: + ZEND_HANDLE_NUMERIC(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, idx); + break; + case IS_UNICODE: + ZEND_HANDLE_U_NUMERIC(Z_USTRVAL_P(offset), Z_USTRLEN_P(offset)+1, idx); + break; + case IS_DOUBLE: + case IS_RESOURCE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + return (long)Z_DVAL_P(offset); + } else { + return Z_LVAL_P(offset); + } + } + return -1; +} +/* }}} */ + /* * Local variables: * tab-width: 4 http://cvs.php.net/viewvc.cgi/php-src/ext/spl/spl_engine.h?r1=1.26&r2=1.27&diff_format=u Index: php-src/ext/spl/spl_engine.h diff -u php-src/ext/spl/spl_engine.h:1.26 php-src/ext/spl/spl_engine.h:1.27 --- php-src/ext/spl/spl_engine.h:1.26 Mon Dec 31 07:12:15 2007 +++ php-src/ext/spl/spl_engine.h Fri Jun 6 23:53:10 2008 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: spl_engine.h,v 1.26 2007/12/31 07:12:15 sebastian Exp $ */ +/* $Id: spl_engine.h,v 1.27 2008/06/06 23:53:10 colder Exp $ */ #ifndef SPL_ENGINE_H #define SPL_ENGINE_H @@ -39,6 +39,8 @@ PHPAPI void spl_instantiate(zend_class_entry *pce, zval **object, int alloc TSRMLS_DC); +PHPAPI long spl_offset_convert_to_long(zval *offset TSRMLS_DC); + /* {{{ spl_instantiate_arg_ex1 */ static inline int spl_instantiate_arg_ex1(zend_class_entry *pce, zval **retval, int alloc, zval *arg1 TSRMLS_DC) { http://cvs.php.net/viewvc.cgi/php-src/ext/spl/spl_dllist.c?r1=1.11&r2=1.12&diff_format=u Index: php-src/ext/spl/spl_dllist.c diff -u php-src/ext/spl/spl_dllist.c:1.11 php-src/ext/spl/spl_dllist.c:1.12 --- php-src/ext/spl/spl_dllist.c:1.11 Thu Feb 28 14:16:14 2008 +++ php-src/ext/spl/spl_dllist.c Fri Jun 6 23:53:10 2008 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: spl_dllist.c,v 1.11 2008/02/28 14:16:14 felipe Exp $ */ +/* $Id: spl_dllist.c,v 1.12 2008/06/06 23:53:10 colder Exp $ */ #ifdef HAVE_CONFIG_H # include "config.h" @@ -721,29 +721,6 @@ } /* }}} */ -static long spl_dllist_offset_convert(zval *offset TSRMLS_DC) /* {{{ */ -{ - switch(Z_TYPE_P(offset)) { - case IS_STRING: - ZEND_HANDLE_NUMERIC(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, idx); - break; - case IS_UNICODE: - ZEND_HANDLE_U_NUMERIC(Z_USTRVAL_P(offset), Z_USTRLEN_P(offset)+1, idx); - break; - case IS_DOUBLE: - case IS_RESOURCE: - case IS_BOOL: - case IS_LONG: - if (Z_TYPE_P(offset) == IS_DOUBLE) { - return (long)Z_DVAL_P(offset); - } else { - return Z_LVAL_P(offset); - } - } - return -1; -} -/* }}} */ - /* {{{ proto bool SplDoublyLinkedList::offsetExists(mixed $index) U Returns whether the requested $index exists. */ SPL_METHOD(SplDoublyLinkedList, offsetExists) @@ -757,7 +734,7 @@ } intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - index = spl_dllist_offset_convert(zindex TSRMLS_CC); + index = spl_offset_convert_to_long(zindex TSRMLS_CC); RETURN_BOOL(index >= 0 && index < intern->llist->count); } /* }}} */ @@ -776,7 +753,7 @@ } intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - index = spl_dllist_offset_convert(zindex TSRMLS_CC); + index = spl_offset_convert_to_long(zindex TSRMLS_CC); if (index < 0 || index >= intern->llist->count) { zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC); @@ -816,7 +793,7 @@ long index; spl_ptr_llist_element *element; - index = spl_dllist_offset_convert(zindex TSRMLS_CC); + index = spl_offset_convert_to_long(zindex TSRMLS_CC); if (index < 0 || index >= intern->llist->count) { zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC); @@ -862,7 +839,7 @@ } intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - index = (int)spl_dllist_offset_convert(zindex TSRMLS_CC); + index = (int)spl_offset_convert_to_long(zindex TSRMLS_CC); llist = intern->llist; if (index < 0 || index >= intern->llist->count) { @@ -1194,6 +1171,9 @@ REGISTER_SPL_SUB_CLASS_EX(SplQueue, SplDoublyLinkedList, spl_dllist_object_new, spl_funcs_SplQueue); REGISTER_SPL_SUB_CLASS_EX(SplStack, SplDoublyLinkedList, spl_dllist_object_new, NULL); + spl_ce_SplQueue->get_iterator = spl_dllist_get_iterator; + spl_ce_SplStack->get_iterator = spl_dllist_get_iterator; + return SUCCESS; } /* }}} */ http://cvs.php.net/viewvc.cgi/php-src/ext/spl/spl_fastarray.c?view=markup&rev=1.1 Index: php-src/ext/spl/spl_fastarray.c +++ php-src/ext/spl/spl_fastarray.c /* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 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 | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | [EMAIL PROTECTED] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Antony Dovgal <[EMAIL PROTECTED]> | | Etienne Kneuss <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ /* $Id: spl_fastarray.c,v 1.1 2008/06/06 23:53:10 colder Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "zend_exceptions.h" #include "php_spl.h" #include "spl_functions.h" #include "spl_engine.h" #include "spl_fastarray.h" #include "spl_exceptions.h" #include "spl_iterators.h" zend_object_handlers spl_handler_SplFastArray; PHPAPI zend_class_entry *spl_ce_SplFastArray; #ifdef COMPILE_DL_SPL_FASTARRAY ZEND_GET_MODULE(spl_fastarray) #endif typedef struct _spl_fastarray { /* {{{ */ long size; zval **elements; } spl_fastarray; /* }}} */ typedef struct _spl_fastarray_object { /* {{{ */ zend_object std; spl_fastarray *array; zval *retval; zend_function *fptr_offset_get; zend_function *fptr_offset_set; zend_function *fptr_offset_has; zend_function *fptr_offset_del; zend_function *fptr_it_next; zend_function *fptr_it_rewind; zend_function *fptr_it_current; zend_function *fptr_it_key; zend_function *fptr_it_valid; int current; zend_class_entry *ce_get_iterator; } spl_fastarray_object; /* }}} */ typedef struct _spl_fastarray_it { /* {{{ */ zend_user_iterator intern; spl_fastarray_object *object; } spl_fastarray_it; /* }}} */ static void spl_fastarray_init(spl_fastarray *array, long size TSRMLS_DC) /* {{{ */ { if (size > 0) { array->elements = ecalloc(size, sizeof(zval *)); array->size = size; } else { array->elements = NULL; array->size = 0; } } /* }}} */ static void spl_fastarray_resize(spl_fastarray *array, long size TSRMLS_DC) /* {{{ */ { if (size == array->size) { /* nothing to do */ return; } /* first initialization */ if (array->size == 0) { spl_fastarray_init(array, size TSRMLS_CC); return; } /* clearing the array */ if (size == 0) { long i; for (i = 0; i < array->size; i++) { if (array->elements[i]) { zval_ptr_dtor(&(array->elements[i])); } } if (array->elements) { efree(array->elements); } } else if (size > array->size) { array->elements = erealloc(array->elements, sizeof(zval *) * size); memset(array->elements + array->size, '\0', sizeof(zval *) * (size - array->size)); } else { /* size < array->size */ long i; for (i = size; i < array->size; i++) { if (array->elements[i]) { zval_ptr_dtor(&(array->elements[i])); } } array->elements = erealloc(array->elements, sizeof(zval *) * size); } array->size = size; } /* }}} */ static void spl_fastarray_copy(spl_fastarray *to, spl_fastarray *from TSRMLS_DC) /* {{{ */ { int i; for (i = 0; i < from->size; i++) { if (from->elements[i]) { Z_ADDREF_P(from->elements[i]); to->elements[i] = from->elements[i]; } else { to->elements[i] = NULL; } } } /* }}} */ static void spl_fastarray_object_free_storage(void *object TSRMLS_DC) /* {{{ */ { spl_fastarray_object *intern = (spl_fastarray_object *)object; long i; for (i = 0; i < intern->array->size; i++) { if (intern->array->elements[i]) { zval_ptr_dtor(&(intern->array->elements[i])); } } if (intern->array->elements) { efree(intern->array->elements); } efree(intern->array); zend_object_std_dtor(&intern->std TSRMLS_CC); zval_ptr_dtor(&intern->retval); efree(object); } /* }}} */ zend_object_iterator *spl_fastarray_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC); static zend_object_value spl_fastarray_object_new_ex(zend_class_entry *class_type, spl_fastarray_object **obj, zval *orig, int clone_orig TSRMLS_DC) /* {{{ */ { zend_object_value retval; spl_fastarray_object *intern; zval *tmp; zend_class_entry *parent = class_type; int inherited = 0; intern = ecalloc(1, sizeof(spl_fastarray_object)); *obj = intern; 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 *)); intern->current = 0; if (orig && clone_orig) { spl_fastarray_object *other = (spl_fastarray_object*)zend_object_store_get_object(orig TSRMLS_CC); intern->ce_get_iterator = other->ce_get_iterator; intern->array = emalloc(sizeof(spl_fastarray)); spl_fastarray_init(intern->array, other->array->size TSRMLS_CC); spl_fastarray_copy(intern->array, other->array TSRMLS_CC); } while (parent) { if (parent == spl_ce_SplFastArray) { retval.handlers = &spl_handler_SplFastArray; break; } parent = parent->parent; inherited = 1; } retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, spl_fastarray_object_free_storage, NULL TSRMLS_CC); if (!parent) { /* this must never happen */ php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplFastArray"); } if (inherited) { zend_hash_find(&class_type->function_table, "offsetget", sizeof("offsetget"), (void **) &intern->fptr_offset_get); if (intern->fptr_offset_get->common.scope == parent) { intern->fptr_offset_get = NULL; } zend_hash_find(&class_type->function_table, "offsetset", sizeof("offsetset"), (void **) &intern->fptr_offset_set); if (intern->fptr_offset_set->common.scope == parent) { intern->fptr_offset_set = NULL; } zend_hash_find(&class_type->function_table, "offsetexists", sizeof("offsetexists"), (void **) &intern->fptr_offset_has); if (intern->fptr_offset_has->common.scope == parent) { intern->fptr_offset_has = NULL; } zend_hash_find(&class_type->function_table, "offsetunset", sizeof("offsetunset"), (void **) &intern->fptr_offset_del); if (intern->fptr_offset_del->common.scope == parent) { intern->fptr_offset_del = NULL; } zend_hash_find(&class_type->function_table, "next", sizeof("next"), (void **) &intern->fptr_it_next); if (intern->fptr_it_next->common.scope == parent) { intern->fptr_it_next = NULL; } zend_hash_find(&class_type->function_table, "rewind", sizeof("rewind"), (void **) &intern->fptr_it_rewind); if (intern->fptr_it_rewind->common.scope == parent) { intern->fptr_it_rewind = NULL; } zend_hash_find(&class_type->function_table, "current", sizeof("current"), (void **) &intern->fptr_it_current); if (intern->fptr_it_current->common.scope == parent) { intern->fptr_it_current = NULL; } zend_hash_find(&class_type->function_table, "key", sizeof("key"), (void **) &intern->fptr_it_key); if (intern->fptr_it_key->common.scope == parent) { intern->fptr_it_key = NULL; } zend_hash_find(&class_type->function_table, "valid", sizeof("valid"), (void **) &intern->fptr_it_valid); if (intern->fptr_it_valid->common.scope == parent) { intern->fptr_it_valid = NULL; } } return retval; } /* }}} */ static zend_object_value spl_fastarray_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ { spl_fastarray_object *tmp; return spl_fastarray_object_new_ex(class_type, &tmp, NULL, 0 TSRMLS_CC); } /* }}} */ static zend_object_value spl_fastarray_object_clone(zval *zobject TSRMLS_DC) /* {{{ */ { zend_object_value new_obj_val; zend_object *old_object; zend_object *new_object; zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); spl_fastarray_object *intern; old_object = zend_objects_get_address(zobject TSRMLS_CC); new_obj_val = spl_fastarray_object_new_ex(old_object->ce, &intern, zobject, 1 TSRMLS_CC); new_object = &intern->std; zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC); return new_obj_val; } /* }}} */ static inline zval **spl_fastarray_object_read_dimension_helper(spl_fastarray_object *intern, zval *offset TSRMLS_DC) /* {{{ */ { long index; zval **retval; index = spl_offset_convert_to_long(offset TSRMLS_CC); if (index < 0 || index >= intern->array->size) { zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0 TSRMLS_CC); return NULL; } else { retval = &intern->array->elements[index]; } return retval; } /* }}} */ static zval *spl_fastarray_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */ { zval **value_pp; spl_fastarray_object *intern; intern = (spl_fastarray_object *)zend_object_store_get_object(object TSRMLS_CC); if (intern->fptr_offset_get) { zval *rv; SEPARATE_ARG_IF_REF(offset); zend_call_method_with_1_params(&object, intern->std.ce, &intern->fptr_offset_get, "offsetGet", &rv, offset); zval_ptr_dtor(&offset); if (rv) { zval_ptr_dtor(&intern->retval); MAKE_STD_ZVAL(intern->retval); ZVAL_ZVAL(intern->retval, rv, 1, 1); return intern->retval; } return EG(uninitialized_zval_ptr); } value_pp = spl_fastarray_object_read_dimension_helper(intern, offset TSRMLS_CC); if (value_pp) { return *value_pp; } else { return EG(uninitialized_zval_ptr); } } /* }}} */ static inline void spl_fastarray_object_write_dimension_helper(spl_fastarray_object *intern, zval *offset, zval *value TSRMLS_DC) /* {{{ */ { long index; index = spl_offset_convert_to_long(offset TSRMLS_CC); if (index < 0 || index >= intern->array->size) { zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0 TSRMLS_CC); return; } else { if (intern->array->elements[index]) { zval_ptr_dtor(&(intern->array->elements[index])); } SEPARATE_ARG_IF_REF(value); intern->array->elements[index] = value; } } /* }}} */ static void spl_fastarray_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) /* {{{ */ { spl_fastarray_object *intern; intern = (spl_fastarray_object *)zend_object_store_get_object(object TSRMLS_CC); if (intern->fptr_offset_set) { SEPARATE_ARG_IF_REF(offset); SEPARATE_ARG_IF_REF(value); zend_call_method_with_2_params(&object, intern->std.ce, &intern->fptr_offset_set, "offsetSet", NULL, offset, value); zval_ptr_dtor(&value); zval_ptr_dtor(&offset); return; } spl_fastarray_object_write_dimension_helper(intern, offset, value TSRMLS_CC); } /* }}} */ static inline void spl_fastarray_object_unset_dimension_helper(spl_fastarray_object *intern, zval *offset TSRMLS_DC) /* {{{ */ { long index; index = spl_offset_convert_to_long(offset TSRMLS_CC); if (index < 0 || index >= intern->array->size) { zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0 TSRMLS_CC); return; } else { if (intern->array->elements[index]) { zval_ptr_dtor(&(intern->array->elements[index])); } intern->array->elements[index] = NULL; } } /* }}} */ static void spl_fastarray_object_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{{ */ { spl_fastarray_object *intern; intern = (spl_fastarray_object *)zend_object_store_get_object(object TSRMLS_CC); if (intern->fptr_offset_del) { SEPARATE_ARG_IF_REF(offset); zend_call_method_with_1_params(&object, intern->std.ce, &intern->fptr_offset_del, "offsetUnset", NULL, offset); zval_ptr_dtor(&offset); return; } spl_fastarray_object_unset_dimension_helper(intern, offset TSRMLS_CC); } /* }}} */ static inline int spl_fastarray_object_has_dimension_helper(spl_fastarray_object *intern, zval *offset, int check_empty TSRMLS_DC) /* {{{ */ { long index; int retval; index = spl_offset_convert_to_long(offset TSRMLS_CC); if (index < 0 || index >= intern->array->size) { retval = 0; } else { if (!intern->array->elements[index]) { retval = 0; } else if (check_empty) { if (zend_is_true(intern->array->elements[index])) { retval = 1; } else { retval = 0; } } else { /* != NULL and !check_empty */ retval = 1; } } return retval; } /* }}} */ static int spl_fastarray_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC) /* {{{ */ { spl_fastarray_object *intern; intern = (spl_fastarray_object *)zend_object_store_get_object(object TSRMLS_CC); if (intern->fptr_offset_get) { zval *rv; SEPARATE_ARG_IF_REF(offset); zend_call_method_with_1_params(&object, intern->std.ce, &intern->fptr_offset_has, "offsetExists", &rv, offset); zval_ptr_dtor(&offset); if (rv) { zval_ptr_dtor(&intern->retval); MAKE_STD_ZVAL(intern->retval); ZVAL_ZVAL(intern->retval, rv, 1, 1); return zend_is_true(intern->retval); } return 0; } return spl_fastarray_object_has_dimension_helper(intern, offset, check_empty TSRMLS_CC); } /* }}} */ static int spl_fastarray_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */ { spl_fastarray_object *intern; intern = (spl_fastarray_object *)zend_object_store_get_object(object TSRMLS_CC); *count = intern->array->size; return SUCCESS; } /* }}} */ /* {{{ proto void SplFastArray::__construct([int size]) */ SPL_METHOD(SplFastArray, __construct) { zval *object = getThis(); spl_fastarray_object *intern; long size = 0; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &size)) { return; } if (size < 0) { zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "array size cannot be less than zero"); return; } intern = (spl_fastarray_object *)zend_object_store_get_object(object TSRMLS_CC); if (intern->array) { /* called __construct() twice, bail out */ return; } intern->array = emalloc(sizeof(spl_fastarray)); spl_fastarray_init(intern->array, size TSRMLS_CC); } /* }}} */ /* {{{ proto int SplFastArray::count(void) */ SPL_METHOD(SplFastArray, count) { zval *object = getThis(); spl_fastarray_object *intern; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) { return; } intern = (spl_fastarray_object *)zend_object_store_get_object(object TSRMLS_CC); RETURN_LONG(intern->array->size); } /* }}} */ /* {{{ proto int SplFastArray::getSize(void) */ SPL_METHOD(SplFastArray, getSize) { zval *object = getThis(); spl_fastarray_object *intern; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) { return; } intern = (spl_fastarray_object *)zend_object_store_get_object(object TSRMLS_CC); RETURN_LONG(intern->array->size); } /* }}} */ /* {{{ proto bool SplFastArray::setSize(int size) */ SPL_METHOD(SplFastArray, setSize) { zval *object = getThis(); spl_fastarray_object *intern; long size; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &size)) { return; } if (size < 0) { zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "array size cannot be less than zero"); return; } intern = (spl_fastarray_object *)zend_object_store_get_object(object TSRMLS_CC); spl_fastarray_resize(intern->array, size TSRMLS_CC); RETURN_TRUE; } /* }}} */ /* {{{ proto bool SplFastArray::offsetExists(mixed $index) U Returns whether the requested $index exists. */ SPL_METHOD(SplFastArray, offsetExists) { zval *zindex; spl_fastarray_object *intern; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) { return; } intern = (spl_fastarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC); RETURN_BOOL(spl_fastarray_object_has_dimension_helper(intern, zindex, 0 TSRMLS_CC)); } /* }}} */ /* {{{ proto mixed SplFastArray::offsetGet(mixed $index) U Returns the value at the specified $index. */ SPL_METHOD(SplFastArray, offsetGet) { zval *zindex, **value_pp; spl_fastarray_object *intern; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) { return; } intern = (spl_fastarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC); value_pp = spl_fastarray_object_read_dimension_helper(intern, zindex TSRMLS_CC); if (value_pp) { RETURN_ZVAL(*value_pp, 1, 0); } } /* }}} */ /* {{{ proto void SplFastArray::offsetSet(mixed $index, mixed $newval) U Sets the value at the specified $index to $newval. */ SPL_METHOD(SplFastArray, offsetSet) { zval *zindex, *value; spl_fastarray_object *intern; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zindex, &value) == FAILURE) { return; } intern = (spl_fastarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC); spl_fastarray_object_write_dimension_helper(intern, zindex, value TSRMLS_CC); } /* }}} */ /* {{{ proto void SplFastArray::offsetUnset(mixed $index) U Unsets the value at the specified $index. */ SPL_METHOD(SplFastArray, offsetUnset) { zval *zindex; spl_fastarray_object *intern; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) { return; } intern = (spl_fastarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC); spl_fastarray_object_unset_dimension_helper(intern, zindex TSRMLS_CC); } /* }}} */ static void spl_fastarray_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ { spl_fastarray_it *iterator = (spl_fastarray_it *)iter; zend_user_it_invalidate_current(iter TSRMLS_CC); zval_ptr_dtor((zval**)&iterator->intern.it.data); efree(iterator); } /* }}} */ static void spl_fastarray_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ { spl_fastarray_it *iterator = (spl_fastarray_it *)iter; spl_fastarray_object *intern = iterator->object; zval *object = (zval *)&iterator->intern.it.data; if (intern->fptr_it_rewind) { zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_it_rewind, "rewind", NULL); } iterator->object->current = 0; } /* }}} */ static int spl_fastarray_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ { spl_fastarray_it *iterator = (spl_fastarray_it *)iter; spl_fastarray_object *intern = iterator->object; zval *object = (zval *)&iterator->intern.it.data; if (intern->fptr_it_valid) { zval *rv; zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_it_valid, "valid", &rv); if (rv) { zval_ptr_dtor(&intern->retval); MAKE_STD_ZVAL(intern->retval); ZVAL_ZVAL(intern->retval, rv, 1, 1); return zend_is_true(intern->retval) ? SUCCESS : FAILURE; } return FAILURE; } if (iterator->object->current >= 0 && iterator->object->current < iterator->object->array->size) { return SUCCESS; } return FAILURE; } /* }}} */ static void spl_fastarray_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */ { zval *zindex; spl_fastarray_it *iterator = (spl_fastarray_it *)iter; spl_fastarray_object *intern = iterator->object; zval *object = (zval *)&iterator->intern.it.data; if (intern->fptr_it_current) { zval *rv; zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_it_current, "current", &rv); if (rv) { zval_ptr_dtor(&intern->retval); MAKE_STD_ZVAL(intern->retval); ZVAL_ZVAL(intern->retval, rv, 1, 1); *data = &intern->retval; } return; } ALLOC_INIT_ZVAL(zindex); ZVAL_LONG(zindex, iterator->object->current); *data = spl_fastarray_object_read_dimension_helper(iterator->object, zindex TSRMLS_CC); zval_ptr_dtor(&zindex); } /* }}} */ static int spl_fastarray_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */ { spl_fastarray_it *iterator = (spl_fastarray_it *)iter; spl_fastarray_object *intern = iterator->object; zval *object = (zval *)&iterator->intern.it.data; if (intern->fptr_it_key) { zval *rv; zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_it_key, "key", &rv); if (rv) { zval_ptr_dtor(&intern->retval); MAKE_STD_ZVAL(intern->retval); ZVAL_ZVAL(intern->retval, rv, 1, 1); convert_to_long(intern->retval); *int_key = (ulong) Z_LVAL_P(intern->retval); } *int_key = (ulong) 0; } else { *int_key = (ulong) iterator->object->current; } return HASH_KEY_IS_LONG; } /* }}} */ static void spl_fastarray_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ { spl_fastarray_it *iterator = (spl_fastarray_it *)iter; spl_fastarray_object *intern = iterator->object; zval *object = (zval *)&iterator->intern.it.data; if (intern->fptr_it_next) { zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_it_next, "next", NULL); } zend_user_it_invalidate_current(iter TSRMLS_CC); iterator->object->current++; } /* }}} */ /* {{{ proto int SplFastArray::key() U Return current array key */ SPL_METHOD(SplFastArray, key) { spl_fastarray_object *intern = (spl_fastarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC); RETURN_LONG(intern->current); } /* }}} */ /* {{{ proto void SplFastArray::next() U Move to next entry */ SPL_METHOD(SplFastArray, next) { spl_fastarray_object *intern = (spl_fastarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC); intern->current++; } /* }}} */ /* {{{ proto bool SplFastArray::valid() U Check whether the datastructure contains more entries */ SPL_METHOD(SplFastArray, valid) { spl_fastarray_object *intern = (spl_fastarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC); RETURN_BOOL(intern->current >= 0 && intern->current < intern->array->size); } /* }}} */ /* {{{ proto void SplFastArray::rewind() U Rewind the datastructure back to the start */ SPL_METHOD(SplFastArray, rewind) { spl_fastarray_object *intern = (spl_fastarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC); intern->current = 0; } /* }}} */ /* {{{ proto mixed|NULL SplFastArray::current() U Return current datastructure entry */ SPL_METHOD(SplFastArray, current) { zval *zindex, **value_pp; spl_fastarray_object *intern = (spl_fastarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC); ALLOC_INIT_ZVAL(zindex); ZVAL_LONG(zindex, intern->current); value_pp = spl_fastarray_object_read_dimension_helper(intern, zindex TSRMLS_CC); zval_ptr_dtor(&zindex); if (value_pp) { RETURN_ZVAL(*value_pp, 1, 0); } } /* }}} */ /* iterator handler table */ zend_object_iterator_funcs spl_fastarray_it_funcs = { spl_fastarray_it_dtor, spl_fastarray_it_valid, spl_fastarray_it_get_current_data, spl_fastarray_it_get_current_key, spl_fastarray_it_move_forward, spl_fastarray_it_rewind }; zend_object_iterator *spl_fastarray_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */ { spl_fastarray_it *iterator; spl_fastarray_object *fastarray_object = (spl_fastarray_object*)zend_object_store_get_object(object TSRMLS_CC); if (by_ref) { zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC); return NULL; } Z_ADDREF_P(object); iterator = emalloc(sizeof(spl_fastarray_it)); iterator->intern.it.data = (void*)object; iterator->intern.it.funcs = &spl_fastarray_it_funcs; iterator->intern.ce = ce; iterator->intern.value = NULL; iterator->object = fastarray_object; return (zend_object_iterator*)iterator; } /* }}} */ static ZEND_BEGIN_ARG_INFO_EX(arginfo_fastarray_offsetGet, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() static ZEND_BEGIN_ARG_INFO_EX(arginfo_fastarray_offsetSet, 0, 0, 2) ZEND_ARG_INFO(0, index) ZEND_ARG_INFO(0, newval) ZEND_END_ARG_INFO() static ZEND_BEGIN_ARG_INFO(arginfo_fastarray_setSize, 0) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() static zend_function_entry spl_funcs_SplFastArray[] = { /* {{{ */ SPL_ME(SplFastArray, __construct, NULL, ZEND_ACC_PUBLIC) SPL_ME(SplFastArray, count, NULL, ZEND_ACC_PUBLIC) SPL_ME(SplFastArray, getSize, NULL, ZEND_ACC_PUBLIC) SPL_ME(SplFastArray, setSize, arginfo_fastarray_setSize, ZEND_ACC_PUBLIC) SPL_ME(SplFastArray, offsetExists, arginfo_fastarray_offsetGet, ZEND_ACC_PUBLIC) SPL_ME(SplFastArray, offsetGet, arginfo_fastarray_offsetGet, ZEND_ACC_PUBLIC) SPL_ME(SplFastArray, offsetSet, arginfo_fastarray_offsetSet, ZEND_ACC_PUBLIC) SPL_ME(SplFastArray, offsetUnset, arginfo_fastarray_offsetGet, ZEND_ACC_PUBLIC) SPL_ME(SplFastArray, rewind, NULL, ZEND_ACC_PUBLIC) SPL_ME(SplFastArray, current, NULL, ZEND_ACC_PUBLIC) SPL_ME(SplFastArray, key, NULL, ZEND_ACC_PUBLIC) SPL_ME(SplFastArray, next, NULL, ZEND_ACC_PUBLIC) SPL_ME(SplFastArray, valid, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; /* }}} */ /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(spl_fastarray) { REGISTER_SPL_STD_CLASS_EX(SplFastArray, spl_fastarray_new, spl_funcs_SplFastArray); memcpy(&spl_handler_SplFastArray, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); spl_handler_SplFastArray.clone_obj = spl_fastarray_object_clone; spl_handler_SplFastArray.count_elements = spl_fastarray_object_count_elements; spl_handler_SplFastArray.read_dimension = spl_fastarray_object_read_dimension; spl_handler_SplFastArray.write_dimension = spl_fastarray_object_write_dimension; spl_handler_SplFastArray.unset_dimension = spl_fastarray_object_unset_dimension; spl_handler_SplFastArray.has_dimension = spl_fastarray_object_has_dimension; spl_handler_SplFastArray.count_elements = spl_fastarray_object_count_elements; REGISTER_SPL_IMPLEMENTS(SplFastArray, Iterator); REGISTER_SPL_IMPLEMENTS(SplFastArray, ArrayAccess); REGISTER_SPL_IMPLEMENTS(SplFastArray, Countable); spl_ce_SplFastArray->get_iterator = spl_fastarray_get_iterator; return SUCCESS; } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ http://cvs.php.net/viewvc.cgi/php-src/ext/spl/spl_fastarray.h?view=markup&rev=1.1 Index: php-src/ext/spl/spl_fastarray.h +++ php-src/ext/spl/spl_fastarray.h /* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 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 | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | [EMAIL PROTECTED] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Antony Dovgal <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ /* $Id: spl_fastarray.h,v 1.1 2008/06/06 23:53:10 colder Exp $ */ #ifndef SPL_FASTARRAY_H #define SPL_FASTARRAY_H PHPAPI zend_class_entry *spl_ce_SplFastArray; PHP_MINIT_FUNCTION(spl_fastarray); #endif /* SPL_FASTARRAY_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ http://cvs.php.net/viewvc.cgi/php-src/ext/spl/tests/fastarray_001.phpt?view=markup&rev=1.1 Index: php-src/ext/spl/tests/fastarray_001.phpt +++ php-src/ext/spl/tests/fastarray_001.phpt --TEST-- SPL: FastArray: std operations --INI-- allow_call_time_pass_reference=1 --FILE-- <?php $a = new SplFastArray(0); // errors try { $a[0] = "value1"; } catch (RuntimeException $e) { echo "Exception: ".$e->getMessage()."\n"; } try { var_dump($a["asdf"]); } catch (RuntimeException $e) { echo "Exception: ".$e->getMessage()."\n"; } try { unset($a[-1]); } catch (RuntimeException $e) { echo "Exception: ".$e->getMessage()."\n"; } $a->setSize(10); $a[0] = "value0"; $a[1] = "value1"; $a[2] = "value2"; $a[3] = "value3"; $ref = "value4"; $ref2 =&$ref; $a[4] = $ref; $ref = "value5"; unset($a[1]); var_dump($a[0], $a[2], $a[3], $a[4]); // countable var_dump(count($a), $a->getSize(), count($a) == $a->getSize()); // clonable $b = clone $a; $a[0] = "valueNew"; var_dump($b[0]); ?> ===DONE=== --EXPECTF-- Exception: Index invalid or out of range Exception: Index invalid or out of range Exception: Index invalid or out of range unicode(6) "value0" unicode(6) "value2" unicode(6) "value3" unicode(6) "value4" int(10) int(10) bool(true) unicode(6) "value0" ===DONE=== http://cvs.php.net/viewvc.cgi/php-src/ext/spl/tests/fastarray_002.phpt?view=markup&rev=1.1 Index: php-src/ext/spl/tests/fastarray_002.phpt +++ php-src/ext/spl/tests/fastarray_002.phpt --TEST-- SPL: FastArray: overloading --INI-- allow_call_time_pass_reference=1 --FILE-- <?php class A extends SplFastArray { public function count() { return 2; } public function offsetGet($n) { echo "A::offsetGet\n"; return parent::offsetGet($n); } public function offsetSet($n, $v) { echo "A::offsetSet\n"; return parent::offsetSet($n, $v); } public function offsetUnset($n) { echo "A::offsetUnset\n"; return parent::offsetUnset($n); } public function offsetExists($n) { echo "A::offsetExists\n"; return parent::offsetExists($n); } } $a = new A; // errors try { $a[0] = "value1"; } catch (RuntimeException $e) { echo "Exception: ".$e->getMessage()."\n"; } try { var_dump($a["asdf"]); } catch (RuntimeException $e) { echo "Exception: ".$e->getMessage()."\n"; } try { unset($a[-1]); } catch (RuntimeException $e) { echo "Exception: ".$e->getMessage()."\n"; } $a->setSize(10); $a[0] = "value0"; $a[1] = "value1"; $a[2] = "value2"; $a[3] = "value3"; $ref = "value4"; $ref2 =&$ref; $a[4] = $ref; $ref = "value5"; unset($a[1]); var_dump(isset($a[1]), isset($a[2]), empty($a[1]), empty($a[2])); var_dump($a[0], $a[2], $a[3], $a[4]); // countable var_dump(count($a), $a->getSize(), count($a) == $a->getSize()); ?> ===DONE=== --EXPECTF-- A::offsetSet Exception: Index invalid or out of range A::offsetGet Exception: Index invalid or out of range A::offsetUnset Exception: Index invalid or out of range A::offsetSet A::offsetSet A::offsetSet A::offsetSet A::offsetSet A::offsetUnset A::offsetExists A::offsetExists A::offsetExists A::offsetExists bool(false) bool(true) bool(true) bool(false) A::offsetGet A::offsetGet A::offsetGet A::offsetGet unicode(6) "value0" unicode(6) "value2" unicode(6) "value3" unicode(6) "value4" int(2) int(10) bool(false) ===DONE=== http://cvs.php.net/viewvc.cgi/php-src/ext/spl/tests/fastarray_003.phpt?view=markup&rev=1.1 Index: php-src/ext/spl/tests/fastarray_003.phpt +++ php-src/ext/spl/tests/fastarray_003.phpt --TEST-- SPL: FastArray: Iterators --FILE-- <?php class A extends SplFastArray { public function current() { echo "A::current\n"; return parent::current(); } public function key() { echo "A::key\n"; return parent::key(); } public function rewind() { echo "A::rewind\n"; return parent::rewind(); } public function valid() { echo "A::valid\n"; return parent::valid(); } public function next() { echo "A::next\n"; return parent::next(); } } echo "==Direct instance==\n"; $a = new SplFastArray(5); $a[0] = "a"; $a[1] = "c"; $a[2] = "d"; $a[3] = "e"; $a[4] = "f"; foreach ($a as $k => $v) { echo "$k => $v\n"; } echo "==Child instance==\n"; $a = new A(5); $a[0] = "a"; $a[1] = "c"; $a[2] = "d"; $a[3] = "e"; $a[4] = "f"; foreach ($a as $k => $v) { echo "$k => $v\n"; } ?> ===DONE=== --EXPECTF-- ==Direct instance== 0 => a 1 => c 2 => d 3 => e 4 => f ==Child instance== A::rewind A::valid A::current A::key 0 => a A::next A::valid A::current A::key 1 => c A::next A::valid A::current A::key 2 => d A::next A::valid A::current A::key 3 => e A::next A::valid A::current A::key 4 => f A::next A::valid ===DONE===
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php