--- embedaddon/php/ext/standard/array.c 2012/02/21 23:48:02 1.1.1.1 +++ embedaddon/php/ext/standard/array.c 2013/07/22 01:32:04 1.1.1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2012 The PHP Group | + | Copyright (c) 1997-2013 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 | @@ -21,7 +21,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: array.c,v 1.1.1.1 2012/02/21 23:48:02 misho Exp $ */ +/* $Id: array.c,v 1.1.1.3 2013/07/22 01:32:04 misho Exp $ */ #include "php.h" #include "php_ini.h" @@ -118,6 +118,8 @@ PHP_MINIT_FUNCTION(array) /* {{{ */ REGISTER_LONG_CONSTANT("SORT_NUMERIC", PHP_SORT_NUMERIC, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SORT_STRING", PHP_SORT_STRING, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SORT_LOCALE_STRING", PHP_SORT_LOCALE_STRING, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SORT_NATURAL", PHP_SORT_NATURAL, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SORT_FLAG_CASE", PHP_SORT_FLAG_CASE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CASE_LOWER", CASE_LOWER, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CASE_UPPER", CASE_UPPER, CONST_CS | CONST_PERSISTENT); @@ -141,15 +143,19 @@ PHP_MSHUTDOWN_FUNCTION(array) /* {{{ */ static void php_set_compare_func(int sort_type TSRMLS_DC) /* {{{ */ { - switch (sort_type) { + switch (sort_type & ~PHP_SORT_FLAG_CASE) { case PHP_SORT_NUMERIC: ARRAYG(compare_func) = numeric_compare_function; break; case PHP_SORT_STRING: - ARRAYG(compare_func) = string_compare_function; + ARRAYG(compare_func) = sort_type & PHP_SORT_FLAG_CASE ? string_case_compare_function : string_compare_function; break; + case PHP_SORT_NATURAL: + ARRAYG(compare_func) = sort_type & PHP_SORT_FLAG_CASE ? string_natural_case_compare_function : string_natural_compare_function; + break; + #if HAVE_STRCOLL case PHP_SORT_LOCALE_STRING: ARRAYG(compare_func) = string_locale_compare_function; @@ -180,7 +186,7 @@ static int php_array_key_compare(const void *a, const Z_LVAL(first) = f->h; } else { Z_TYPE(first) = IS_STRING; - Z_STRVAL(first) = f->arKey; + Z_STRVAL(first) = (char*)f->arKey; Z_STRLEN(first) = f->nKeyLength - 1; } @@ -189,7 +195,7 @@ static int php_array_key_compare(const void *a, const Z_LVAL(second) = s->h; } else { Z_TYPE(second) = IS_STRING; - Z_STRVAL(second) = s->arKey; + Z_STRVAL(second) = (char*)s->arKey; Z_STRLEN(second) = s->nKeyLength - 1; } @@ -629,7 +635,7 @@ static int php_array_user_compare(const void *a, const PHP_FUNCTION(usort) { zval *array; - int refcount; + unsigned int refcount; PHP_ARRAY_CMP_FUNC_VARS; PHP_ARRAY_CMP_FUNC_BACKUP(); @@ -672,7 +678,7 @@ PHP_FUNCTION(usort) PHP_FUNCTION(uasort) { zval *array; - int refcount; + unsigned int refcount; PHP_ARRAY_CMP_FUNC_VARS; PHP_ARRAY_CMP_FUNC_BACKUP(); @@ -768,7 +774,7 @@ static int php_array_user_key_compare(const void *a, c PHP_FUNCTION(uksort) { zval *array; - int refcount; + unsigned int refcount; PHP_ARRAY_CMP_FUNC_VARS; PHP_ARRAY_CMP_FUNC_BACKUP(); @@ -1044,7 +1050,7 @@ PHP_FUNCTION(max) } /* }}} */ -static int php_array_walk(HashTable *target_hash, zval **userdata, int recursive TSRMLS_DC) /* {{{ */ +static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive TSRMLS_DC) /* {{{ */ { zval **args[3], /* Arguments to userland function */ *retval_ptr, /* Return value - unused */ @@ -1052,24 +1058,22 @@ static int php_array_walk(HashTable *target_hash, zval char *string_key; uint string_key_len; ulong num_key; - HashPosition pos; /* Set up known arguments */ args[1] = &key; - args[2] = userdata; + args[2] = &userdata; if (userdata) { - Z_ADDREF_PP(userdata); + Z_ADDREF_P(userdata); } - zend_hash_internal_pointer_reset_ex(target_hash, &pos); - BG(array_walk_fci).retval_ptr_ptr = &retval_ptr; BG(array_walk_fci).param_count = userdata ? 3 : 2; BG(array_walk_fci).params = args; BG(array_walk_fci).no_separation = 0; - + /* Iterate through hash */ - while (!EG(exception) && zend_hash_get_current_data_ex(target_hash, (void **)&args[0], &pos) == SUCCESS) { + zend_hash_internal_pointer_reset(target_hash); + while (!EG(exception) && zend_hash_get_current_data(target_hash, (void **)&args[0]) == SUCCESS) { if (recursive && Z_TYPE_PP(args[0]) == IS_ARRAY) { HashTable *thash; zend_fcall_info orig_array_walk_fci; @@ -1080,7 +1084,7 @@ static int php_array_walk(HashTable *target_hash, zval if (thash->nApplyCount > 1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected"); if (userdata) { - zval_ptr_dtor(userdata); + zval_ptr_dtor(&userdata); } return 0; } @@ -1101,7 +1105,7 @@ static int php_array_walk(HashTable *target_hash, zval MAKE_STD_ZVAL(key); /* Set up the key */ - switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_key_len, &num_key, 0, &pos)) { + switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_key_len, &num_key, 0, NULL)) { case HASH_KEY_IS_LONG: Z_TYPE_P(key) = IS_LONG; Z_LVAL_P(key) = num_key; @@ -1129,11 +1133,11 @@ static int php_array_walk(HashTable *target_hash, zval zval_ptr_dtor(&key); key = NULL; } - zend_hash_move_forward_ex(target_hash, &pos); + zend_hash_move_forward(target_hash); } if (userdata) { - zval_ptr_dtor(userdata); + zval_ptr_dtor(&userdata); } return 0; } @@ -1157,7 +1161,7 @@ PHP_FUNCTION(array_walk) return; } - php_array_walk(array, userdata ? &userdata : NULL, 0 TSRMLS_CC); + php_array_walk(array, userdata, 0 TSRMLS_CC); BG(array_walk_fci) = orig_array_walk_fci; BG(array_walk_fci_cache) = orig_array_walk_fci_cache; RETURN_TRUE; @@ -1182,7 +1186,7 @@ PHP_FUNCTION(array_walk_recursive) return; } - php_array_walk(array, userdata ? &userdata : NULL, 1 TSRMLS_CC); + php_array_walk(array, userdata, 1 TSRMLS_CC); BG(array_walk_fci) = orig_array_walk_fci; BG(array_walk_fci_cache) = orig_array_walk_fci_cache; RETURN_TRUE; @@ -1557,12 +1561,17 @@ PHP_FUNCTION(array_fill) array_init_size(return_value, num); num--; - zval_add_ref(&val); zend_hash_index_update(Z_ARRVAL_P(return_value), start_key, &val, sizeof(zval *), NULL); + zval_add_ref(&val); while (num--) { - zval_add_ref(&val); - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &val, sizeof(zval *), NULL); + if (zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &val, sizeof(zval *), NULL) == SUCCESS) { + zval_add_ref(&val); + } else { + zval_dtor(return_value); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add element to the array as the next element is already occupied"); + RETURN_FALSE; + } } } /* }}} */ @@ -1662,24 +1671,28 @@ PHP_FUNCTION(range) high = (unsigned char *)Z_STRVAL_P(zhigh); if (*low > *high) { /* Negative Steps */ + unsigned char ch = *low; + if (lstep <= 0) { err = 1; goto err; } - for (; *low >= *high; (*low) -= (unsigned int)lstep) { - add_next_index_stringl(return_value, (const char *)low, 1, 1); - if (((signed int)*low - lstep) < 0) { + for (; ch >= *high; ch -= (unsigned int)lstep) { + add_next_index_stringl(return_value, (const char *)&ch, 1, 1); + if (((signed int)ch - lstep) < 0) { break; } } } else if (*high > *low) { /* Positive Steps */ + unsigned char ch = *low; + if (lstep <= 0) { err = 1; goto err; } - for (; *low <= *high; (*low) += (unsigned int)lstep) { - add_next_index_stringl(return_value, (const char *)low, 1, 1); - if (((signed int)*low + lstep) > 255) { + for (; ch <= *high; ch += (unsigned int)lstep) { + add_next_index_stringl(return_value, (const char *)&ch, 1, 1); + if (((signed int)ch + lstep) > 255) { break; } } @@ -3758,7 +3771,7 @@ PHPAPI int php_multisort_compare(const void *a, const efree(args); \ RETURN_FALSE; -/* {{{ proto bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...]) +/* {{{ proto bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...]) Sort multiple arrays at once similar to how ORDER BY clause works in SQL */ PHP_FUNCTION(array_multisort) { @@ -3808,7 +3821,7 @@ PHP_FUNCTION(array_multisort) parse_state[k] = 1; } } else if (Z_TYPE_PP(args[i]) == IS_LONG) { - switch (Z_LVAL_PP(args[i])) { + switch (Z_LVAL_PP(args[i]) & ~PHP_SORT_FLAG_CASE) { case PHP_SORT_ASC: case PHP_SORT_DESC: /* flag allowed here */ @@ -3825,6 +3838,7 @@ PHP_FUNCTION(array_multisort) case PHP_SORT_REGULAR: case PHP_SORT_NUMERIC: case PHP_SORT_STRING: + case PHP_SORT_NATURAL: #if HAVE_STRCOLL case PHP_SORT_LOCALE_STRING: #endif @@ -4481,12 +4495,11 @@ PHP_FUNCTION(array_combine) RETURN_FALSE; } + array_init_size(return_value, num_keys); + if (!num_keys) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Both parameters should have at least 1 element"); - RETURN_FALSE; + return; } - - array_init_size(return_value, num_keys); zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(keys), &pos_keys); zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos_values);