com php-src: Merge branch 'PHP-5.5' into PHP-5.6: NEWS UPGRADING.INTERNALS ext/phar/phar_object.c ext/spl/spl_observer.c ext/s tandard/array.c
ext/standard/php_array.h
| From: | Bob Weinand | Date: | Sun, 13 Apr 2014 22:08:36 +0000 |
| Subject: | com php-src: Merge branch 'PHP-5.5' into PHP-5.6: NEWS UPGRADING.INTERNALS ext/phar/phar_object.c ext/spl/spl_observer.c ext/s tandard/array.c ext/standard/php_array.h |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-76841@lists.php.net to get a copy of this message | ||
Commit: a93e734f8143815bcb4f675567146d4326c05fb9
Author: Bob Weinand <bobwei9@hotmail.com> Mon, 14 Apr 2014 00:08:36 +0200
Parents: 0e023e978445a7d2f723cabfd4a59d65886be72a bf3edbada68cb99f4c67f60fe113a6cf0b44e0fa
Branches: PHP-5.6
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=a93e734f8143815bcb4f675567146d4326c05fb9
Log:
Merge branch 'PHP-5.5' into PHP-5.6
Changed paths:
MM NEWS
MM UPGRADING.INTERNALS
MM ext/phar/phar_object.c
MM ext/spl/spl_observer.c
MM ext/standard/array.c
MM ext/standard/php_array..h
diff --cc NEWS index cd75dca,cb6c695..e4809ae --- a/NEWS +++ b/NEWS @@@ -1,21 -1,28 +1,23 @@@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? 2014, PHP 5.5.12 -- Core: - . Fixed bug #61019 (Out of memory on command stream_get_contents). (Mike) - . Fixed bug #64330 (stream_socket_server() creates wrong Abstract Namespace - UNIX sockets). (Mike) - . Fixed bug #66182 (exit in stream filter produces segfault). (Mike) - . Fixed bug #66736 (fpassthru broken). (Mike) - . Fixed bug #67043 (substr_compare broke by previous change) (Tjerk) - -- Embed: - . Fixed bug #65715 (php5embed.lib isn't provided anymore). (Anatol). +?? ??? 2014, PHP 5.6.0 Beta 2 -- Fileinfo: - . Fixed bug #66987 (Memory corruption in fileinfo ext / bigendian). - (Remi) +- Core: + . Fixed bug #66015 (Unexpected array indexing in class's static property). (Bob) + . Added (constant) string/array dereferencing to static scalar expressions + to complete the set; now possible thanks to bug #66015 being fixed. (Bob) + . Fixed bug #66568 (Update reflection information for unserialize() function). + (Ferenc) + . Fixed bug #66660 (Composer.phar install/update fails). (Ferenc) ++ . Fixed bug #67064 (Countable interface prevents using 2nd parameter ++ ($mode) of count() function). (Bob) -- mysqli: - . Fixed problem in mysqli_commit()/mysqli_rollback() with second parameter - (extra comma) and third parameters (lack of escaping). (Andrey) +- mysqlnd: + . Added a new fetching mode to mysqlnd. (Andrey) -- SimpleXML: - . Fixed bug #66084 (simplexml_load_string() mangles empty node name) - (Anatol) +- PDO: + . Fixed bug #66604 ('pdo/php_pdo_error.h' not copied to the include dir). + (Matteo) - SQLite: . Fixed bug #66967 (Updated bundled libsqlite to 3.8.4.3). (Anatol) diff --cc UPGRADING.INTERNALS index f3e7281,bdc2a43..1bc359b --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@@ -22,166 -18,96 +22,173 @@@ UPGRADE NOTES - PHP X. 1. Internal API changes ======================== - a. Executor changes - - * extensions can't override zend_execute() any more, they should override - zend_execute_ex() instead. The EG(current_execute_data) is already - initialized in zend_execute_ex(), so for compatibility extensions - may need to use EG(current_execute_data)->prev_execute_data instead. - * removed EG(arg_types_stack), EX(fbc), EX(called_scope), EX(current_object) - * added op_array->nested_calls. It's calculated at compile time. - * added EX(call_slots). It is an array to store information about syntaticaly - nested calls (e.g. foo(bar())). It's preallocated together with execute_data. - * added EX(call) - pointer to a current calling function. Actually an - element of EX(call_slots) - * opcodes INIT_METHOD_CALL, ZEND_INIT_STATIC_METHOD_CALL, - ZEND_INIT_FCALL_BY_NAME, ZEND_INIT_NS_FCALL_BY_NAME use result.num as - an index in EX(call_slots) - * opcode ZEND_NEW uses extended_vallue as an index in EX(call_slots) - * opcoes ZEND_DO_FCALL and ZEND_DO_FCALL_BY_NAME use op2.num as - an index in EX(call_slots) - * added op_array->used_stack. It's calculated at compile time and the - corresponding stack space is preallocated together with execute_data. - ZEND_SEND* and ZEND_DO_FCALL* don't need to check for stack overflow - anymore. - * Removed execute_data->Ts field. The VM temporary variables always allocated - immediately before execute_data structure. Now they are accessed by offset - from the execute_data base pointer (instead of execute_data->Ts). Compiler - stores new offsets in op_array->opcodes[*].op?.num. You can use macros - EX_TMP_VAR() and EX_TMP_VAR_NUM() to access temp_variable by offset or - number. You can convert number to offset using EX_TMP_VAR_NUM(0, num) or - offset to number (EX_TMP_VAR_NUM(0,0)-EX_TMP_VAR(0,offset)). - * Removed execute_data->CVs field. The VM compiled variables always allocated - immediately after execute_data structure. Now they are accessed by offset - from the execute_data base pointer (instead of execute_data->CVs). You can - use macros EX_CV_NUM() to access compiled variables by number. - - b. Streams pooling API - -The streams pooling API has been removed. The following functions no longer -exist: - -PHPAPI int php_stream_context_get_link(php_stream_context *context, - const char *hostent, php_stream **stream); -PHPAPI int php_stream_context_set_link(php_stream_context *context, - const char *hostent, php_stream *stream); -PHPAPI int php_stream_context_del_link(php_stream_context *context, - php_stream *stream); - - c. Lowercasing and locales - -The lowercasing functions in zend_operators.c were split into those that do -lowercasing according to locale rules and those that do ASCII lowercasing. -ASCII: - - zend_str_tolower_copy - zend_str_tolower_dup - zend_str_tolower - zend_binary_strcasecmp - zend_binary_strncasecmp - -Locale-based: - zend_binary_strncasecmp_l - zend_binary_strcasecmp_l - zend_binary_zval_strcasecmp - zend_binary_zval_strncasecmp - string_compare_function_ex - string_case_compare_function - -Internal engine lowercasing will be using ASCII-only rules. User-facing functions, -such as strcasecmp, will be using locale rules. - -Two new functions - zend_binary_strncasecmp_l and zend_binary_strcasecmp_l - added as -locale-based counterparts to zend_binary_strcasecmp and zend_binary_strncasecmp. - - d. zend_qsort_r - -Added the function zend_qsort_r(): - -typedef int (*compare_r_func_t)(const void *, const void * TSRMLS_DC, void *); -void zend_qsort_r(void *base, size_t nmemb, size_t siz, compare_r_func_t compare, void *arg TSRMLS_DC); - -The extra argument it has (relatively to zend_qsort()) is passed to the -comparison function. - - e. get_current_key - -The signature of the get_current_key iteration handler has been changed to: - -void (*get_current_key)(zend_object_iterator *iter, zval *key TSRMLS_DC); - -The key should be written into the zval* using the ZVAL_* macros. + a. Addition of do_operation and compare object handlers + + Two new object handlers have been added: + + do_operation: + typedef int (*zend_object_do_operation_t)( + zend_uchar opcode, zval *result, zval *op1, zval *op2 TSRMLS_DC + ); + + compare: + typedef int (*zend_object_compare_zvals_t)( + zval *result, zval *op1, zval *op2 TSRMLS_DC + ); + + The first handler is used to overload arithmetic operations. The first + argument specifies the opcode of the operator, result is the target zval, + op1 the first operand and op2 the second operand. For unary operations + op2 is NULL. If the handler returns FAILURE PHP falls back to the default + behavior for the operation. + + The second handler is used to perform comparison operations with + non-objects. The value written into result must be an IS_LONG with value + -1 (smaller), 0 (equal) or 1 (greater). The return value is a SUCCESS/FAILURE + return code. The difference between this handler and compare_objects is + that it will be triggered for comparisons with non-objects and objects of + different types. It takes precedence over compare_objects. + + Further docs in the RFC: https://wiki.php.net/rfc/operator_overloading_gmp + + b. return_value_ptr now always available, RETVAL_ZVAL_FAST macros + + The return_value_ptr argument to internal functions is now always set. + Previously it was only available for functions returning by-reference. + return_value_ptr can now be used to return zvals without copying them. + For this purpose two new macros are provided: + + RETVAL_ZVAL_FAST(zv); /* analog to RETVAL_ZVAL(zv, 1, 0) */ + RETURN_ZVAL_FAST(zv); /* analog to RETURN_ZVAL(zv, 1, 0) */ + + The macros behave similarly to the non-FAST variants with copy=1 and + dtor=0, but will try to return the zval without making a copy by utilizing + return_value_ptr. + + c. POST data handling + + The sapi_request_info's members post_data, post_data_len and raw_post_data as + well as raw_post_data_len have been replaced with a temp PHP stream + request_body. + + The recommended way to access raw POST data is to open and use a php://input + stream wrapper. It is safe to be used concurrently and more than once. + + d. Arginfo changes + + The pass_rest_by_reference argument of the ZEND_BEGIN_ARG_INFO and + ZEND_BEGIN_ARG_INFO_EX() is no longer used. The value passed to it is ignored. + + Instead a variadic argument is created using ZEND_ARG_VARIADIC_INFO(): + + ZEND_ARG_VARIADIC_INFO(0, name) /* pass rest by value */ + ZEND_ARG_VARIADIC_INFO(1, name) /* pass rest by reference */ + ZEND_ARG_VARIADIC_INFO(ZEND_SEND_PREFER_REF, name) + /* pass rest by prefer-ref */ + + ZEND_ARG_VARIADIC_INFO() should only be used for the last argument. + + The following changes were applied to the zend_arg_info struct: + + typedef struct _zend_arg_info { + const char *class_name; + zend_uint class_name_len; + zend_uchar type_hint; + + zend_uchar pass_by_reference; + zend_bool allow_null; + - zend_bool pass_by_reference; + + zend_bool is_variadic; + } zend_arg_info; + + The following changes were applied to the zend_internal_function_info struct: + + typedef struct _zend_internal_function_info { + zend_uint required_num_args; + zend_uchar _type_hint; + zend_bool return_reference; + - zend_bool pass_rest_by_reference; + + zend_bool _allow_null; + + zend_bool _is_variadic; + } zend_internal_function_info; + + The CHECK_ARG_SEND_TYPE(), ARG_MUST_BE_SENT_BY_REF(), + ARG_SHOULD_BE_SENT_BY_REF() and ARG_MAY_BE_SENT_BY_REF() macros now assume + that the argument passed to them is a zend_function* and that it is non-NULL. + + e. tsrm_virtual_cwd.h moved to zend_virtual_cwd.h + + Memory allocation is now managed by emalloc/efree instead of malloc/free. + + f. empty strings are interned + + String created using STR_EMPTY_ALLOC() are now interned. + convert_to_string use STR_EMPTY_ALLOC() for zval when IS_NULL. + str_efree() shoud be preferred as efree() on such strings can cause memory + corruption. + + g. Additional str_* APIs + + In addition to the previously existing str_free() and str_efree() macros, the + following macros have been introduced to simplify dealing with potentially + interned strings: + + str_efree_rel(str) - efree_rel() if not interned + str_erealloc(str, new_len) - erealloc() or emalloc+memcpy if interned + str_estrndup(str, len) - estrndup() if not interned + str_strndup(str, len) - zend_strndup() if not interned + str_hash(str, len) - INTERNED_HASH(str) if interned, + zend_hash_func(str, len+1) otherwise + + h. Addition of zend_hash_reindex + + A zend_hash_reindex() function with the following prototype has been added: + + void zend_hash_reindex(HashTable *ht, zend_bool only_integer_keys); + + If only_integer_keys==0, this function will change all keys to be continuous, + zero-based integers in hash order. If only_integer_keys==1 the same will be + done only for keys that were already integers previously, while leaving + string keys alone. + + i. Addition of zend_hash_splice + + A zend_hash_splice() macro with the following prototype has been added: + + void zend_hash_splice( + HashTable *ht, uint nDataSize, copy_ctor_func_t pCopyConstructor, + uint offset, uint length, + void **list, uint list_count, HashTable *removed + ); + + This function performs an in-place splice operation on a hashtable: + + The elements between offset and offset+length are removed and the elements in + list[list_count] are inserted in their place. The removed elements can be + optionally collected into a hashtable. + + This operation reindexes the hashtable, i.e. integer keys will be zero-based + and sequential, while string keys stay intact. The same applies to the + elements inserted into the removed HT. + + As a side-effect of this addition the signature of the php_splice() function + changed: + + void php_splice( + HashTable *ht, zend_uint offset, zend_uint length, + zval ***list, zend_uint list_count, HashTable *removed TSRMLS_DC + ) + + This function now directly forwards to zend_hash_splice(), resets the + IAP of ht (for compatibility with the previous implementation) and resets + CVs if the passed hashtable is the global symbol table. + ++ j. An additional parameter is sent to Countable::count() ++ ++ That parameter denotes the $mode passed to count; it shouldn't affect any ++ userland code, but any zend_parse_parameters() used with no arguments should ++ fail. Extensions which implement Countable internally, need to accept one ++ optional long as parameter. + ======================== 2. Build system changes ======================== diff --cc ext/phar/phar_object.c index 99907f8,7857fa7..407edda --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@@ -1934,10 -1934,10 +1934,12 @@@ PHP_METHOD(Phar, buildFromIterator */ PHP_METHOD(Phar, count) { ++ /* mode can be ignored, maximum depth is 1 */ ++ long mode; PHAR_ARCHIVE_OBJECT(); -- if (zend_parse_parameters_none() == FAILURE) { -- return; ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &mode) == FAILURE) { ++ RETURN_FALSE; } RETURN_LONG(zend_hash_num_elements(&phar_obj->arc.archive->manifest)); diff --cc ext/spl/spl_observer.c index 1a706f7,1a706f7..91830ab --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@@ -26,6 -26,6 +26,7 @@@ #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" ++#include "ext/standard/php_array.h" #include "ext/standard/php_var.h" #include "ext/standard/php_smart_str.h" #include "zend_interfaces.h" @@@ -621,11 -621,11 +622,27 @@@ SPL_METHOD(SplObjectStorage, contains SPL_METHOD(SplObjectStorage, count) { spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); -- -- if (zend_parse_parameters_none() == FAILURE) { ++ long mode = COUNT_NORMAL; ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &mode) == FAILURE) { return; } -- ++ ++ if (mode == COUNT_RECURSIVE) { ++ long ret = zend_hash_num_elements(&intern->storage); ++ HashPosition position; ++ zval *element; ++ ++ for (zend_hash_internal_pointer_reset_ex(&intern->storage, &position); ++ zend_hash_get_current_data_ex(&intern->storage, (void**) &element, &position) == SUCCESS; ++ zend_hash_move_forward_ex(&intern->storage, &position)) { ++ ret += php_count_recursive(element, mode TSRMLS_CC); ++ } ++ ++ RETURN_LONG(ret); ++ return; ++ } ++ RETURN_LONG(zend_hash_num_elements(&intern->storage)); } /* }}} */ diff --cc ext/standard/array.c index 34057e3,1a29afa..4f98331 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@@ -64,9 -64,9 +64,6 @@@ #define CASE_LOWER 0 #define CASE_UPPER 1 --#define COUNT_NORMAL 0 --#define COUNT_RECURSIVE 1 -- #define DIFF_NORMAL 1 #define DIFF_KEY 2 #define DIFF_ASSOC 6 @@@ -274,7 -271,7 +271,7 @@@ PHP_FUNCTION(ksort } /* }}} */ --static int php_count_recursive(zval *array, long mode TSRMLS_DC) /* {{{ */ ++PHPAPI int php_count_recursive(zval *array, long mode TSRMLS_DC) /* {{{ */ { long cnt = 0; zval **element; @@@ -336,15 -333,12 +333,17 @@@ PHP_FUNCTION(count #ifdef HAVE_SPL /* if not and the object implements Countable we call its count() method */ if (Z_OBJ_HT_P(array)->get_class_entry && instanceof_function(Z_OBJCE_P(array), spl_ce_Countable TSRMLS_CC)) { - zend_call_method_with_0_params(&array, NULL, NULL, "count", &retval); + zval *mode_zv; + MAKE_STD_ZVAL(mode_zv); - Z_LVAL_P(mode_zv) = mode; ++ ZVAL_LONG(mode_zv, mode); + zend_call_method_with_1_params(&array, NULL, NULL, "count", &retval, mode_zv); if (retval) { convert_to_long_ex(&retval); RETVAL_LONG(Z_LVAL_P(retval)); zval_ptr_dtor(&retval); } ++ zval_dtor(mode_zv); ++ efree(mode_zv); return; } #endif diff --cc ext/standard/php_array.h index deddeb4,e2af331..1b30e34 --- a/ext/standard/php_array.h +++ b/ext/standard/php_array.h @@@ -107,6 -107,6 +107,7 @@@ PHPAPI void php_splice(HashTable *ht, z PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS_DC); PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src TSRMLS_DC); PHPAPI int php_multisort_compare(const void *a, const void *b TSRMLS_DC); ++PHPAPI int php_count_recursive(zval *array, long mode TSRMLS_DC); #define PHP_SORT_REGULAR 0 #define PHP_SORT_NUMERIC 1 @@@ -117,9 -117,6 +118,12 @@@ #define PHP_SORT_NATURAL 6 #define PHP_SORT_FLAG_CASE 8 ++#define COUNT_NORMAL 0 ++#define COUNT_RECURSIVE 1 ++ +#define ARRAY_FILTER_USE_BOTH 1 +#define ARRAY_FILTER_USE_KEY 2 + ZEND_BEGIN_MODULE_GLOBALS(array) int *multisort_flags[2]; int (*compare_func)(zval *result, zval *op1, zval *op2 TSRMLS_DC);
diff --cc NEWS index cd75dca,cb6c695..e4809ae --- a/NEWS +++ b/NEWS @@@ -1,21 -1,28 +1,23 @@@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? 2014, PHP 5.5.12 -- Core: - . Fixed bug #61019 (Out of memory on command stream_get_contents). (Mike) - . Fixed bug #64330 (stream_socket_server() creates wrong Abstract Namespace - UNIX sockets). (Mike) - . Fixed bug #66182 (exit in stream filter produces segfault). (Mike) - . Fixed bug #66736 (fpassthru broken). (Mike) - . Fixed bug #67043 (substr_compare broke by previous change) (Tjerk) - -- Embed: - . Fixed bug #65715 (php5embed.lib isn't provided anymore). (Anatol). +?? ??? 2014, PHP 5.6.0 Beta 2 -- Fileinfo: - . Fixed bug #66987 (Memory corruption in fileinfo ext / bigendian). - (Remi) +- Core: + . Fixed bug #66015 (Unexpected array indexing in class's static property). (Bob) + . Added (constant) string/array dereferencing to static scalar expressions + to complete the set; now possible thanks to bug #66015 being fixed. (Bob) + . Fixed bug #66568 (Update reflection information for unserialize() function). + (Ferenc) + . Fixed bug #66660 (Composer.phar install/update fails). (Ferenc) ++ . Fixed bug #67064 (Countable interface prevents using 2nd parameter ++ ($mode) of count() function). (Bob) -- mysqli: - . Fixed problem in mysqli_commit()/mysqli_rollback() with second parameter - (extra comma) and third parameters (lack of escaping). (Andrey) +- mysqlnd: + . Added a new fetching mode to mysqlnd. (Andrey) -- SimpleXML: - . Fixed bug #66084 (simplexml_load_string() mangles empty node name) - (Anatol) +- PDO: + . Fixed bug #66604 ('pdo/php_pdo_error.h' not copied to the include dir). + (Matteo) - SQLite: . Fixed bug #66967 (Updated bundled libsqlite to 3.8.4.3). (Anatol) diff --cc UPGRADING.INTERNALS index f3e7281,bdc2a43..1bc359b --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@@ -22,166 -18,96 +22,173 @@@ UPGRADE NOTES - PHP X. 1. Internal API changes ======================== - a. Executor changes - - * extensions can't override zend_execute() any more, they should override - zend_execute_ex() instead. The EG(current_execute_data) is already - initialized in zend_execute_ex(), so for compatibility extensions - may need to use EG(current_execute_data)->prev_execute_data instead. - * removed EG(arg_types_stack), EX(fbc), EX(called_scope), EX(current_object) - * added op_array->nested_calls. It's calculated at compile time. - * added EX(call_slots). It is an array to store information about syntaticaly - nested calls (e.g. foo(bar())). It's preallocated together with execute_data. - * added EX(call) - pointer to a current calling function. Actually an - element of EX(call_slots) - * opcodes INIT_METHOD_CALL, ZEND_INIT_STATIC_METHOD_CALL, - ZEND_INIT_FCALL_BY_NAME, ZEND_INIT_NS_FCALL_BY_NAME use result.num as - an index in EX(call_slots) - * opcode ZEND_NEW uses extended_vallue as an index in EX(call_slots) - * opcoes ZEND_DO_FCALL and ZEND_DO_FCALL_BY_NAME use op2.num as - an index in EX(call_slots) - * added op_array->used_stack. It's calculated at compile time and the - corresponding stack space is preallocated together with execute_data. - ZEND_SEND* and ZEND_DO_FCALL* don't need to check for stack overflow - anymore. - * Removed execute_data->Ts field. The VM temporary variables always allocated - immediately before execute_data structure. Now they are accessed by offset - from the execute_data base pointer (instead of execute_data->Ts). Compiler - stores new offsets in op_array->opcodes[*].op?.num. You can use macros - EX_TMP_VAR() and EX_TMP_VAR_NUM() to access temp_variable by offset or - number. You can convert number to offset using EX_TMP_VAR_NUM(0, num) or - offset to number (EX_TMP_VAR_NUM(0,0)-EX_TMP_VAR(0,offset)). - * Removed execute_data->CVs field. The VM compiled variables always allocated - immediately after execute_data structure. Now they are accessed by offset - from the execute_data base pointer (instead of execute_data->CVs). You can - use macros EX_CV_NUM() to access compiled variables by number. - - b. Streams pooling API - -The streams pooling API has been removed. The following functions no longer -exist: - -PHPAPI int php_stream_context_get_link(php_stream_context *context, - const char *hostent, php_stream **stream); -PHPAPI int php_stream_context_set_link(php_stream_context *context, - const char *hostent, php_stream *stream); -PHPAPI int php_stream_context_del_link(php_stream_context *context, - php_stream *stream); - - c. Lowercasing and locales - -The lowercasing functions in zend_operators.c were split into those that do -lowercasing according to locale rules and those that do ASCII lowercasing. -ASCII: - - zend_str_tolower_copy - zend_str_tolower_dup - zend_str_tolower - zend_binary_strcasecmp - zend_binary_strncasecmp - -Locale-based: - zend_binary_strncasecmp_l - zend_binary_strcasecmp_l - zend_binary_zval_strcasecmp - zend_binary_zval_strncasecmp - string_compare_function_ex - string_case_compare_function - -Internal engine lowercasing will be using ASCII-only rules. User-facing functions, -such as strcasecmp, will be using locale rules. - -Two new functions - zend_binary_strncasecmp_l and zend_binary_strcasecmp_l - added as -locale-based counterparts to zend_binary_strcasecmp and zend_binary_strncasecmp. - - d. zend_qsort_r - -Added the function zend_qsort_r(): - -typedef int (*compare_r_func_t)(const void *, const void * TSRMLS_DC, void *); -void zend_qsort_r(void *base, size_t nmemb, size_t siz, compare_r_func_t compare, void *arg TSRMLS_DC); - -The extra argument it has (relatively to zend_qsort()) is passed to the -comparison function. - - e. get_current_key - -The signature of the get_current_key iteration handler has been changed to: - -void (*get_current_key)(zend_object_iterator *iter, zval *key TSRMLS_DC); - -The key should be written into the zval* using the ZVAL_* macros. + a. Addition of do_operation and compare object handlers + + Two new object handlers have been added: + + do_operation: + typedef int (*zend_object_do_operation_t)( + zend_uchar opcode, zval *result, zval *op1, zval *op2 TSRMLS_DC + ); + + compare: + typedef int (*zend_object_compare_zvals_t)( + zval *result, zval *op1, zval *op2 TSRMLS_DC + ); + + The first handler is used to overload arithmetic operations. The first + argument specifies the opcode of the operator, result is the target zval, + op1 the first operand and op2 the second operand. For unary operations + op2 is NULL. If the handler returns FAILURE PHP falls back to the default + behavior for the operation. + + The second handler is used to perform comparison operations with + non-objects. The value written into result must be an IS_LONG with value + -1 (smaller), 0 (equal) or 1 (greater). The return value is a SUCCESS/FAILURE + return code. The difference between this handler and compare_objects is + that it will be triggered for comparisons with non-objects and objects of + different types. It takes precedence over compare_objects. + + Further docs in the RFC: https://wiki.php.net/rfc/operator_overloading_gmp + + b. return_value_ptr now always available, RETVAL_ZVAL_FAST macros + + The return_value_ptr argument to internal functions is now always set. + Previously it was only available for functions returning by-reference. + return_value_ptr can now be used to return zvals without copying them. + For this purpose two new macros are provided: + + RETVAL_ZVAL_FAST(zv); /* analog to RETVAL_ZVAL(zv, 1, 0) */ + RETURN_ZVAL_FAST(zv); /* analog to RETURN_ZVAL(zv, 1, 0) */ + + The macros behave similarly to the non-FAST variants with copy=1 and + dtor=0, but will try to return the zval without making a copy by utilizing + return_value_ptr. + + c. POST data handling + + The sapi_request_info's members post_data, post_data_len and raw_post_data as + well as raw_post_data_len have been replaced with a temp PHP stream + request_body. + + The recommended way to access raw POST data is to open and use a php://input + stream wrapper. It is safe to be used concurrently and more than once. + + d. Arginfo changes + + The pass_rest_by_reference argument of the ZEND_BEGIN_ARG_INFO and + ZEND_BEGIN_ARG_INFO_EX() is no longer used. The value passed to it is ignored. + + Instead a variadic argument is created using ZEND_ARG_VARIADIC_INFO(): + + ZEND_ARG_VARIADIC_INFO(0, name) /* pass rest by value */ + ZEND_ARG_VARIADIC_INFO(1, name) /* pass rest by reference */ + ZEND_ARG_VARIADIC_INFO(ZEND_SEND_PREFER_REF, name) + /* pass rest by prefer-ref */ + + ZEND_ARG_VARIADIC_INFO() should only be used for the last argument. + + The following changes were applied to the zend_arg_info struct: + + typedef struct _zend_arg_info { + const char *class_name; + zend_uint class_name_len; + zend_uchar type_hint; + + zend_uchar pass_by_reference; + zend_bool allow_null; + - zend_bool pass_by_reference; + + zend_bool is_variadic; + } zend_arg_info; + + The following changes were applied to the zend_internal_function_info struct: + + typedef struct _zend_internal_function_info { + zend_uint required_num_args; + zend_uchar _type_hint; + zend_bool return_reference; + - zend_bool pass_rest_by_reference; + + zend_bool _allow_null; + + zend_bool _is_variadic; + } zend_internal_function_info; + + The CHECK_ARG_SEND_TYPE(), ARG_MUST_BE_SENT_BY_REF(), + ARG_SHOULD_BE_SENT_BY_REF() and ARG_MAY_BE_SENT_BY_REF() macros now assume + that the argument passed to them is a zend_function* and that it is non-NULL. + + e. tsrm_virtual_cwd.h moved to zend_virtual_cwd.h + + Memory allocation is now managed by emalloc/efree instead of malloc/free. + + f. empty strings are interned + + String created using STR_EMPTY_ALLOC() are now interned. + convert_to_string use STR_EMPTY_ALLOC() for zval when IS_NULL. + str_efree() shoud be preferred as efree() on such strings can cause memory + corruption. + + g. Additional str_* APIs + + In addition to the previously existing str_free() and str_efree() macros, the + following macros have been introduced to simplify dealing with potentially + interned strings: + + str_efree_rel(str) - efree_rel() if not interned + str_erealloc(str, new_len) - erealloc() or emalloc+memcpy if interned + str_estrndup(str, len) - estrndup() if not interned + str_strndup(str, len) - zend_strndup() if not interned + str_hash(str, len) - INTERNED_HASH(str) if interned, + zend_hash_func(str, len+1) otherwise + + h. Addition of zend_hash_reindex + + A zend_hash_reindex() function with the following prototype has been added: + + void zend_hash_reindex(HashTable *ht, zend_bool only_integer_keys); + + If only_integer_keys==0, this function will change all keys to be continuous, + zero-based integers in hash order. If only_integer_keys==1 the same will be + done only for keys that were already integers previously, while leaving + string keys alone. + + i. Addition of zend_hash_splice + + A zend_hash_splice() macro with the following prototype has been added: + + void zend_hash_splice( + HashTable *ht, uint nDataSize, copy_ctor_func_t pCopyConstructor, + uint offset, uint length, + void **list, uint list_count, HashTable *removed + ); + + This function performs an in-place splice operation on a hashtable: + + The elements between offset and offset+length are removed and the elements in + list[list_count] are inserted in their place. The removed elements can be + optionally collected into a hashtable. + + This operation reindexes the hashtable, i.e. integer keys will be zero-based + and sequential, while string keys stay intact. The same applies to the + elements inserted into the removed HT. + + As a side-effect of this addition the signature of the php_splice() function + changed: + + void php_splice( + HashTable *ht, zend_uint offset, zend_uint length, + zval ***list, zend_uint list_count, HashTable *removed TSRMLS_DC + ) + + This function now directly forwards to zend_hash_splice(), resets the + IAP of ht (for compatibility with the previous implementation) and resets + CVs if the passed hashtable is the global symbol table. + ++ j. An additional parameter is sent to Countable::count() ++ ++ That parameter denotes the $mode passed to count; it shouldn't affect any ++ userland code, but any zend_parse_parameters() used with no arguments should ++ fail. Extensions which implement Countable internally, need to accept one ++ optional long as parameter. + ======================== 2. Build system changes ======================== diff --cc ext/phar/phar_object.c index 99907f8,7857fa7..407edda --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@@ -1934,10 -1934,10 +1934,12 @@@ PHP_METHOD(Phar, buildFromIterator */ PHP_METHOD(Phar, count) { ++ /* mode can be ignored, maximum depth is 1 */ ++ long mode; PHAR_ARCHIVE_OBJECT(); -- if (zend_parse_parameters_none() == FAILURE) { -- return; ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &mode) == FAILURE) { ++ RETURN_FALSE; } RETURN_LONG(zend_hash_num_elements(&phar_obj->arc.archive->manifest)); diff --cc ext/spl/spl_observer.c index 1a706f7,1a706f7..91830ab --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@@ -26,6 -26,6 +26,7 @@@ #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" ++#include "ext/standard/php_array.h" #include "ext/standard/php_var.h" #include "ext/standard/php_smart_str.h" #include "zend_interfaces.h" @@@ -621,11 -621,11 +622,27 @@@ SPL_METHOD(SplObjectStorage, contains SPL_METHOD(SplObjectStorage, count) { spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); -- -- if (zend_parse_parameters_none() == FAILURE) { ++ long mode = COUNT_NORMAL; ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &mode) == FAILURE) { return; } -- ++ ++ if (mode == COUNT_RECURSIVE) { ++ long ret = zend_hash_num_elements(&intern->storage); ++ HashPosition position; ++ zval *element; ++ ++ for (zend_hash_internal_pointer_reset_ex(&intern->storage, &position); ++ zend_hash_get_current_data_ex(&intern->storage, (void**) &element, &position) == SUCCESS; ++ zend_hash_move_forward_ex(&intern->storage, &position)) { ++ ret += php_count_recursive(element, mode TSRMLS_CC); ++ } ++ ++ RETURN_LONG(ret); ++ return; ++ } ++ RETURN_LONG(zend_hash_num_elements(&intern->storage)); } /* }}} */ diff --cc ext/standard/array.c index 34057e3,1a29afa..4f98331 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@@ -64,9 -64,9 +64,6 @@@ #define CASE_LOWER 0 #define CASE_UPPER 1 --#define COUNT_NORMAL 0 --#define COUNT_RECURSIVE 1 -- #define DIFF_NORMAL 1 #define DIFF_KEY 2 #define DIFF_ASSOC 6 @@@ -274,7 -271,7 +271,7 @@@ PHP_FUNCTION(ksort } /* }}} */ --static int php_count_recursive(zval *array, long mode TSRMLS_DC) /* {{{ */ ++PHPAPI int php_count_recursive(zval *array, long mode TSRMLS_DC) /* {{{ */ { long cnt = 0; zval **element; @@@ -336,15 -333,12 +333,17 @@@ PHP_FUNCTION(count #ifdef HAVE_SPL /* if not and the object implements Countable we call its count() method */ if (Z_OBJ_HT_P(array)->get_class_entry && instanceof_function(Z_OBJCE_P(array), spl_ce_Countable TSRMLS_CC)) { - zend_call_method_with_0_params(&array, NULL, NULL, "count", &retval); + zval *mode_zv; + MAKE_STD_ZVAL(mode_zv); - Z_LVAL_P(mode_zv) = mode; ++ ZVAL_LONG(mode_zv, mode); + zend_call_method_with_1_params(&array, NULL, NULL, "count", &retval, mode_zv); if (retval) { convert_to_long_ex(&retval); RETVAL_LONG(Z_LVAL_P(retval)); zval_ptr_dtor(&retval); } ++ zval_dtor(mode_zv); ++ efree(mode_zv); return; } #endif diff --cc ext/standard/php_array.h index deddeb4,e2af331..1b30e34 --- a/ext/standard/php_array.h +++ b/ext/standard/php_array.h @@@ -107,6 -107,6 +107,7 @@@ PHPAPI void php_splice(HashTable *ht, z PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS_DC); PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src TSRMLS_DC); PHPAPI int php_multisort_compare(const void *a, const void *b TSRMLS_DC); ++PHPAPI int php_count_recursive(zval *array, long mode TSRMLS_DC); #define PHP_SORT_REGULAR 0 #define PHP_SORT_NUMERIC 1 @@@ -117,9 -117,6 +118,12 @@@ #define PHP_SORT_NATURAL 6 #define PHP_SORT_FLAG_CASE 8 ++#define COUNT_NORMAL 0 ++#define COUNT_RECURSIVE 1 ++ +#define ARRAY_FILTER_USE_BOTH 1 +#define ARRAY_FILTER_USE_KEY 2 + ZEND_BEGIN_MODULE_GLOBALS(array) int *multisort_flags[2]; int (*compare_func)(zval *result, zval *op1, zval *op2 TSRMLS_DC);