diff options
-rw-r--r-- | ext/standard/array.c | 123 | ||||
-rw-r--r-- | ext/standard/php_array.h | 3 |
2 files changed, 101 insertions, 25 deletions
diff --git a/ext/standard/array.c b/ext/standard/array.c index 82a6dc448f..a76163dcf7 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -56,6 +56,10 @@ php_array_globals array_globals; #define SORT_DESC -1 #define SORT_ASC 1 +#define SORT_REGULAR 0 +#define SORT_NUMERIC 1 +#define SORT_STRING 2 + PHP_MINIT_FUNCTION(array) { #ifdef ZTS @@ -70,6 +74,10 @@ PHP_MINIT_FUNCTION(array) REGISTER_LONG_CONSTANT("SORT_ASC", SORT_ASC, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SORT_DESC", SORT_DESC, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SORT_REGULAR", SORT_REGULAR, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SORT_NUMERIC", SORT_NUMERIC, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SORT_STRING", SORT_STRING, CONST_CS | CONST_PERSISTENT); + return SUCCESS; } @@ -82,6 +90,26 @@ PHP_MSHUTDOWN_FUNCTION(array) return SUCCESS; } +static void set_compare_func(int sort_type) +{ + ARRAYLS_FETCH(); + + switch (sort_type) { + case SORT_NUMERIC: + ARRAYG(compare_func) = numeric_compare_function; + break; + + case SORT_STRING: + ARRAYG(compare_func) = string_compare_function; + break; + + case SORT_REGULAR: + default: + ARRAYG(compare_func) = compare_function; + break; + } +} + static int array_key_compare(const void *a, const void *b) { Bucket *f; @@ -89,6 +117,7 @@ static int array_key_compare(const void *a, const void *b) pval result; pval first; pval second; + ARRAYLS_FETCH(); f = *((Bucket **) a); s = *((Bucket **) b); @@ -111,7 +140,7 @@ static int array_key_compare(const void *a, const void *b) second.value.str.len = s->nKeyLength; } - if (compare_function(&result, &first, &second) == FAILURE) { + if (ARRAYG(compare_func)(&result, &first, &second) == FAILURE) { return 0; } @@ -145,10 +174,12 @@ static int array_reverse_key_compare(const void *a, const void *b) Sort an array reverse by key */ PHP_FUNCTION(krsort) { - pval **array; + zval **array, **sort_type; + int sort_type_val = SORT_REGULAR; HashTable *target_hash; - if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { + if (ARG_COUNT(ht) < 1 || ARG_COUNT(ht) > 2 || + zend_get_parameters_ex(ARG_COUNT(ht), &array, &sort_type) == FAILURE) { WRONG_PARAM_COUNT; } target_hash = HASH_OF(*array); @@ -156,6 +187,11 @@ PHP_FUNCTION(krsort) php_error(E_WARNING, "Wrong datatype in krsort() call"); return; } + if (ARG_COUNT(ht) == 2) { + convert_to_long_ex(sort_type); + sort_type_val = Z_LVAL_PP(sort_type); + } + set_compare_func(sort_type_val); if (zend_hash_sort(target_hash, qsort, array_reverse_key_compare, 0) == FAILURE) { return; } @@ -167,10 +203,12 @@ PHP_FUNCTION(krsort) Sort an array by key */ PHP_FUNCTION(ksort) { - pval **array; + zval **array, **sort_type; + int sort_type_val = SORT_REGULAR; HashTable *target_hash; - if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { + if (ARG_COUNT(ht) < 1 || ARG_COUNT(ht) > 2 || + zend_get_parameters_ex(ARG_COUNT(ht), &array, &sort_type) == FAILURE) { WRONG_PARAM_COUNT; } target_hash = HASH_OF(*array); @@ -178,6 +216,11 @@ PHP_FUNCTION(ksort) php_error(E_WARNING, "Wrong datatype in ksort() call"); return; } + if (ARG_COUNT(ht) == 2) { + convert_to_long_ex(sort_type); + sort_type_val = Z_LVAL_PP(sort_type); + } + set_compare_func(sort_type_val); if (zend_hash_sort(target_hash, qsort, array_key_compare,0) == FAILURE) { return; } @@ -218,6 +261,7 @@ static int array_data_compare(const void *a, const void *b) pval result; pval *first; pval *second; + ARRAYLS_FETCH(); f = *((Bucket **) a); s = *((Bucket **) b); @@ -225,7 +269,7 @@ static int array_data_compare(const void *a, const void *b) first = *((pval **) f->pData); second = *((pval **) s->pData); - if (compare_function(&result, first, second) == FAILURE) { + if (ARRAYG(compare_func)(&result, first, second) == FAILURE) { return 0; } @@ -351,10 +395,12 @@ PHP_FUNCTION(natcasesort) Sort an array and maintain index association */ PHP_FUNCTION(asort) { - pval **array; + zval **array, **sort_type; + int sort_type_val = SORT_REGULAR; HashTable *target_hash; - if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { + if (ARG_COUNT(ht) < 1 || ARG_COUNT(ht) > 2 || + zend_get_parameters_ex(ARG_COUNT(ht), &array, &sort_type) == FAILURE) { WRONG_PARAM_COUNT; } target_hash = HASH_OF(*array); @@ -362,6 +408,11 @@ PHP_FUNCTION(asort) php_error(E_WARNING, "Wrong datatype in asort() call"); return; } + if (ARG_COUNT(ht) == 2) { + convert_to_long_ex(sort_type); + sort_type_val = Z_LVAL_PP(sort_type); + } + set_compare_func(sort_type_val); if (zend_hash_sort(target_hash, qsort, array_data_compare,0) == FAILURE) { return; } @@ -373,10 +424,12 @@ PHP_FUNCTION(asort) Sort an array in reverse order and maintain index association */ PHP_FUNCTION(arsort) { - pval **array; + zval **array, **sort_type; + int sort_type_val = SORT_REGULAR; HashTable *target_hash; - if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { + if (ARG_COUNT(ht) < 1 || ARG_COUNT(ht) > 2 || + zend_get_parameters_ex(ARG_COUNT(ht), &array, &sort_type) == FAILURE) { WRONG_PARAM_COUNT; } target_hash = HASH_OF(*array); @@ -384,6 +437,11 @@ PHP_FUNCTION(arsort) php_error(E_WARNING, "Wrong datatype in arsort() call"); RETURN_FALSE; } + if (ARG_COUNT(ht) == 2) { + convert_to_long_ex(sort_type); + sort_type_val = Z_LVAL_PP(sort_type); + } + set_compare_func(sort_type_val); if (zend_hash_sort(target_hash, qsort, array_reverse_data_compare,0) == FAILURE) { RETURN_FALSE; } @@ -395,10 +453,12 @@ PHP_FUNCTION(arsort) Sort an array */ PHP_FUNCTION(sort) { - pval **array; + zval **array, **sort_type; + int sort_type_val = SORT_REGULAR; HashTable *target_hash; - if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { + if (ARG_COUNT(ht) < 1 || ARG_COUNT(ht) > 2 || + zend_get_parameters_ex(ARG_COUNT(ht), &array, &sort_type) == FAILURE) { WRONG_PARAM_COUNT; } target_hash = HASH_OF(*array); @@ -406,6 +466,11 @@ PHP_FUNCTION(sort) php_error(E_WARNING, "Wrong datatype in sort() call"); RETURN_FALSE; } + if (ARG_COUNT(ht) == 2) { + convert_to_long_ex(sort_type); + sort_type_val = Z_LVAL_PP(sort_type); + } + set_compare_func(sort_type_val); if (zend_hash_sort(target_hash, qsort, array_data_compare,1) == FAILURE) { RETURN_FALSE; } @@ -417,10 +482,12 @@ PHP_FUNCTION(sort) Sort an array in reverse order */ PHP_FUNCTION(rsort) { - pval **array; + zval **array, **sort_type; + int sort_type_val = SORT_REGULAR; HashTable *target_hash; - if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { + if (ARG_COUNT(ht) < 1 || ARG_COUNT(ht) > 2 || + zend_get_parameters_ex(ARG_COUNT(ht), &array, &sort_type) == FAILURE) { WRONG_PARAM_COUNT; } target_hash = HASH_OF(*array); @@ -428,6 +495,11 @@ PHP_FUNCTION(rsort) php_error(E_WARNING, "Wrong datatype in rsort() call"); RETURN_FALSE; } + if (ARG_COUNT(ht) == 2) { + convert_to_long_ex(sort_type); + sort_type_val = Z_LVAL_PP(sort_type); + } + set_compare_func(sort_type_val); if (zend_hash_sort(target_hash, qsort, array_reverse_data_compare,1) == FAILURE) { RETURN_FALSE; } @@ -1248,10 +1320,10 @@ PHP_FUNCTION(shuffle) /* }}} */ -/* HashTable* _phpi_splice(HashTable *in_hash, int offset, int length, - zval ***list, int list_count, HashTable **removed) */ -HashTable* _phpi_splice(HashTable *in_hash, int offset, int length, - zval ***list, int list_count, HashTable **removed) +/* HashTable* php_splice(HashTable *in_hash, int offset, int length, + zval ***list, int list_count, HashTable **removed) */ +HashTable* php_splice(HashTable *in_hash, int offset, int length, + zval ***list, int list_count, HashTable **removed) { HashTable *out_hash = NULL; /* Output hashtable */ int num_in, /* Number of entries in the input hashtable */ @@ -1416,7 +1488,7 @@ static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end) INIT_PZVAL(return_value); /* Delete the first or last value */ - new_hash = _phpi_splice((*stack)->value.ht, (off_the_end) ? -1 : 0, 1, NULL, 0, NULL); + new_hash = php_splice((*stack)->value.ht, (off_the_end) ? -1 : 0, 1, NULL, 0, NULL); zend_hash_destroy((*stack)->value.ht); efree((*stack)->value.ht); (*stack)->value.ht = new_hash; @@ -1474,7 +1546,7 @@ PHP_FUNCTION(array_unshift) /* Use splice to insert the elements at the beginning. Destroy old hashtable and replace it with new one */ - new_hash = _phpi_splice(stack->value.ht, 0, 0, &args[1], argc-1, NULL); + new_hash = php_splice(stack->value.ht, 0, 0, &args[1], argc-1, NULL); zend_hash_destroy(stack->value.ht); efree(stack->value.ht); stack->value.ht = new_hash; @@ -1548,7 +1620,7 @@ PHP_FUNCTION(array_splice) array_init(return_value); /* Perform splice */ - new_hash = _phpi_splice(array->value.ht, offset, length, + new_hash = php_splice(array->value.ht, offset, length, repl, repl_num, &return_value->value.ht); @@ -1974,9 +2046,9 @@ PHP_FUNCTION(array_pad) /* Pad on the right or on the left */ if ((*pad_size)->value.lval > 0) - new_hash = _phpi_splice(return_value->value.ht, input_size, 0, pads, num_pads, NULL); + new_hash = php_splice(return_value->value.ht, input_size, 0, pads, num_pads, NULL); else - new_hash = _phpi_splice(return_value->value.ht, 0, 0, pads, num_pads, NULL); + new_hash = php_splice(return_value->value.ht, 0, 0, pads, num_pads, NULL); /* Copy the result hash into return value */ @@ -2050,7 +2122,7 @@ int multisort_compare(const void *a, const void *b) r = 0; do { - compare_function(&temp, *((zval **)ab[r]->pData), *((zval **)bb[r]->pData)); + ARRAYG(compare_func)(&temp, *((zval **)ab[r]->pData), *((zval **)bb[r]->pData)); result = ARRAYG(multisort_flags)[r] * temp.value.lval; if (result != 0) return result; @@ -2180,6 +2252,9 @@ PHP_FUNCTION(array_multisort) for (k = 0; k < array_size; k++) indirect[k][num_arrays] = NULL; + /* For now, assume it's always regular sort. */ + set_compare_func(SORT_REGULAR); + /* Do the actual sort magic - bada-bim, bada-boom */ qsort(indirect, array_size, sizeof(Bucket **), multisort_compare); diff --git a/ext/standard/php_array.h b/ext/standard/php_array.h index 519b4b33af..2d9d6607e0 100644 --- a/ext/standard/php_array.h +++ b/ext/standard/php_array.h @@ -69,11 +69,12 @@ PHP_FUNCTION(array_pad); PHP_FUNCTION(array_flip); PHP_FUNCTION(array_rand); -HashTable* _phpi_splice(HashTable *, int, int, zval ***, int, HashTable **); +HashTable* php_splice(HashTable *, int, int, zval ***, int, HashTable **); int multisort_compare(const void *a, const void *b); typedef struct { int *multisort_flags; + int (*compare_func)(zval *result, zval *op1, zval *op2); } php_array_globals; #ifdef ZTS |