📄 array.c
字号:
/* }}} *//* {{{ proto bool sort(array array_arg [, int sort_flags]) Sort an array */PHP_FUNCTION(sort){ zval *array; long sort_type = SORT_REGULAR; HashTable *target_hash; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) { RETURN_FALSE; } target_hash = HASH_OF(array); set_compare_func(sort_type TSRMLS_CC); if (zend_hash_sort(target_hash, zend_qsort, array_data_compare, 1 TSRMLS_CC) == FAILURE) { RETURN_FALSE; } RETURN_TRUE;}/* }}} *//* {{{ proto bool rsort(array array_arg [, int sort_flags]) Sort an array in reverse order */PHP_FUNCTION(rsort){ zval *array; long sort_type = SORT_REGULAR; HashTable *target_hash; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) { RETURN_FALSE; } target_hash = HASH_OF(array); set_compare_func(sort_type TSRMLS_CC); if (zend_hash_sort(target_hash, zend_qsort, array_reverse_data_compare, 1 TSRMLS_CC) == FAILURE) { RETURN_FALSE; } RETURN_TRUE;}/* }}} */static int array_user_compare(const void *a, const void *b TSRMLS_DC){ Bucket *f; Bucket *s; zval **args[2]; zval *retval_ptr; f = *((Bucket **) a); s = *((Bucket **) b); args[0] = (zval **) f->pData; args[1] = (zval **) s->pData; if (call_user_function_ex(EG(function_table), NULL, *BG(user_compare_func_name), &retval_ptr, 2, args, 0, NULL TSRMLS_CC)==SUCCESS && retval_ptr) { long retval; convert_to_long_ex(&retval_ptr); retval = Z_LVAL_P(retval_ptr); zval_ptr_dtor(&retval_ptr); return retval; } else { return 0; }}/* check is comparison function is valid */#define PHP_ARRAY_CMP_FUNC_CHECK(func_name) \ if (!zend_is_callable(*func_name, 0, NULL)) { \ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid comparison function."); \ BG(user_compare_func_name) = old_compare_func; \ RETURN_FALSE; \ } \/* {{{ proto bool usort(array array_arg, string cmp_function) Sort an array by values using a user-defined comparison function */PHP_FUNCTION(usort){ zval **array; zval **old_compare_func; HashTable *target_hash; old_compare_func = BG(user_compare_func_name); if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &array, &BG(user_compare_func_name)) == FAILURE) { BG(user_compare_func_name) = old_compare_func; WRONG_PARAM_COUNT; } target_hash = HASH_OF(*array); if (!target_hash) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); BG(user_compare_func_name) = old_compare_func; RETURN_FALSE; } PHP_ARRAY_CMP_FUNC_CHECK(BG(user_compare_func_name)) if (zend_hash_sort(target_hash, zend_qsort, array_user_compare, 1 TSRMLS_CC) == FAILURE) { BG(user_compare_func_name) = old_compare_func; RETURN_FALSE; } BG(user_compare_func_name) = old_compare_func; RETURN_TRUE;}/* }}} *//* {{{ proto bool uasort(array array_arg, string cmp_function) Sort an array with a user-defined comparison function and maintain index association */PHP_FUNCTION(uasort){ zval **array; zval **old_compare_func; HashTable *target_hash; old_compare_func = BG(user_compare_func_name); if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &array, &BG(user_compare_func_name)) == FAILURE) { BG(user_compare_func_name) = old_compare_func; WRONG_PARAM_COUNT; } target_hash = HASH_OF(*array); if (!target_hash) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); BG(user_compare_func_name) = old_compare_func; RETURN_FALSE; } PHP_ARRAY_CMP_FUNC_CHECK(BG(user_compare_func_name)) if (zend_hash_sort(target_hash, zend_qsort, array_user_compare, 0 TSRMLS_CC) == FAILURE) { BG(user_compare_func_name) = old_compare_func; RETURN_FALSE; } BG(user_compare_func_name) = old_compare_func; RETURN_TRUE;}/* }}} */static int array_user_key_compare(const void *a, const void *b TSRMLS_DC){ Bucket *f; Bucket *s; zval *key1, *key2; zval *args[2]; zval retval; int status; ALLOC_INIT_ZVAL(key1); ALLOC_INIT_ZVAL(key2); args[0] = key1; args[1] = key2; f = *((Bucket **) a); s = *((Bucket **) b); if (f->nKeyLength) { Z_STRVAL_P(key1) = estrndup(f->arKey, f->nKeyLength-1); Z_STRLEN_P(key1) = f->nKeyLength-1; Z_TYPE_P(key1) = IS_STRING; } else { Z_LVAL_P(key1) = f->h; Z_TYPE_P(key1) = IS_LONG; } if (s->nKeyLength) { Z_STRVAL_P(key2) = estrndup(s->arKey, s->nKeyLength-1); Z_STRLEN_P(key2) = s->nKeyLength-1; Z_TYPE_P(key2) = IS_STRING; } else { Z_LVAL_P(key2) = s->h; Z_TYPE_P(key2) = IS_LONG; } status = call_user_function(EG(function_table), NULL, *BG(user_compare_func_name), &retval, 2, args TSRMLS_CC); zval_ptr_dtor(&key1); zval_ptr_dtor(&key2); if (status == SUCCESS) { convert_to_long(&retval); return Z_LVAL(retval); } else { return 0; }}/* {{{ proto bool uksort(array array_arg, string cmp_function) Sort an array by keys using a user-defined comparison function */PHP_FUNCTION(uksort){ zval **array; zval **old_compare_func; HashTable *target_hash; old_compare_func = BG(user_compare_func_name); if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &array, &BG(user_compare_func_name)) == FAILURE) { BG(user_compare_func_name) = old_compare_func; WRONG_PARAM_COUNT; } target_hash = HASH_OF(*array); if (!target_hash) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); BG(user_compare_func_name) = old_compare_func; RETURN_FALSE; } PHP_ARRAY_CMP_FUNC_CHECK(BG(user_compare_func_name)) if (zend_hash_sort(target_hash, zend_qsort, array_user_key_compare, 0 TSRMLS_CC) == FAILURE) { BG(user_compare_func_name) = old_compare_func; RETURN_FALSE; } BG(user_compare_func_name) = old_compare_func; RETURN_TRUE;}/* }}} *//* {{{ proto mixed end(array array_arg) Advances array argument's internal pointer to the last element and return it */PHP_FUNCTION(end){ pval **array, **entry; HashTable *target_hash; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { WRONG_PARAM_COUNT; } target_hash = HASH_OF(*array); if (!target_hash) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passed variable is not an array or object"); RETURN_FALSE; } zend_hash_internal_pointer_end(target_hash); if (return_value_used) { if (zend_hash_get_current_data(target_hash, (void **) &entry) == FAILURE) { RETURN_FALSE; } *return_value = **entry; zval_copy_ctor(return_value); }}/* }}} *//* {{{ proto mixed prev(array array_arg) Move array argument's internal pointer to the previous element and return it */PHP_FUNCTION(prev){ pval **array, **entry; HashTable *target_hash; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { WRONG_PARAM_COUNT; } target_hash = HASH_OF(*array); if (!target_hash) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passed variable is not an array or object"); RETURN_FALSE; } zend_hash_move_backwards(target_hash); if (return_value_used) { if (zend_hash_get_current_data(target_hash, (void **) &entry) == FAILURE) { RETURN_FALSE; } *return_value = **entry; zval_copy_ctor(return_value); }}/* }}} *//* {{{ proto mixed next(array array_arg) Move array argument's internal pointer to the next element and return it */PHP_FUNCTION(next){ pval **array, **entry; HashTable *target_hash; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { WRONG_PARAM_COUNT; } target_hash = HASH_OF(*array); if (!target_hash) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passed variable is not an array or object"); RETURN_FALSE; } zend_hash_move_forward(target_hash); if (return_value_used) { if (zend_hash_get_current_data(target_hash, (void **) &entry) == FAILURE) { RETURN_FALSE; } *return_value = **entry; zval_copy_ctor(return_value); }}/* }}} *//* {{{ proto mixed reset(array array_arg) Set array argument's internal pointer to the first element and return it */ PHP_FUNCTION(reset){ pval **array, **entry; HashTable *target_hash; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { WRONG_PARAM_COUNT; } target_hash = HASH_OF(*array); if (!target_hash) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passed variable is not an array or object"); RETURN_FALSE; } zend_hash_internal_pointer_reset(target_hash); if (return_value_used) { if (zend_hash_get_current_data(target_hash, (void **) &entry) == FAILURE) { RETURN_FALSE; } *return_value = **entry; zval_copy_ctor(return_value); }}/* }}} *//* {{{ proto mixed current(array array_arg) Return the element currently pointed to by the internal array pointer */PHP_FUNCTION(current){ pval **array, **entry; HashTable *target_hash; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { WRONG_PARAM_COUNT; } target_hash = HASH_OF(*array); if (!target_hash) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passed variable is not an array or object"); RETURN_FALSE; } if (zend_hash_get_current_data(target_hash, (void **) &entry) == FAILURE) { RETURN_FALSE; } *return_value = **entry; zval_copy_ctor(return_value);}/* }}} *//* {{{ proto mixed key(array array_arg) Return the key of the element currently pointed to by the internal array pointer */PHP_FUNCTION(key){ pval **array; char *string_key; uint string_length; ulong num_key; HashTable *target_hash; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &array) == FAILURE) { WRONG_PARAM_COUNT; } target_hash = HASH_OF(*array); if (!target_hash) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passed variable is not an array or object"); RETURN_FALSE; } switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_length, &num_key, 0, NULL)) { case HASH_KEY_IS_STRING: RETVAL_STRINGL(string_key, string_length - 1, 1); break; case HASH_KEY_IS_LONG: RETVAL_LONG(num_key); break; case HASH_KEY_NON_EXISTANT: return; }}/* }}} *//* {{{ proto mixed min(mixed arg1 [, mixed arg2 [, mixed ...]]) Return the lowest value in an array or a series of arguments */PHP_FUNCTION(min){ int argc=ZEND_NUM_ARGS(); pval **result; if (argc<=0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Atleast one value should be passed"); RETURN_NULL(); } set_compare_func(SORT_REGULAR TSRMLS_CC); if (argc == 1) { pval **arr; if (zend_get_parameters_ex(1, &arr) == FAILURE || Z_TYPE_PP(arr) != IS_ARRAY) { WRONG_PARAM_COUNT; } if (zend_hash_minmax(Z_ARRVAL_PP(arr), array_data_compare, 0, (void **) &result TSRMLS_CC) == SUCCESS) { *return_value = **result; zval_copy_ctor(return_value); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array must contain atleast one element"); RETURN_FALSE; } } else { pval ***args = (pval ***) safe_emalloc(sizeof(pval **), ZEND_NUM_ARGS(), 0); pval **min, result; int i; if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args)==FAILURE) { efree(args); WRONG_PARAM_COUNT; } min = args[0]; for (i=1; i<ZEND_NUM_ARGS(); i++) { is_smaller_function(&result, *args[i], *min TSRMLS_CC); if (Z_LVAL(result) == 1) { min = args[i]; } } *return_value = **min; zval_copy_ctor(return_value); efree(args); }}/* }}} *//* {{{ proto mixed max(mixed arg1 [, mixed arg2 [, mixed ...]]) Return the highest value in an array or a series of arguments */PHP_FUNCTION(max){ int argc=ZEND_NUM_ARGS(); pval **result; if (argc<=0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Atleast one value should be passed"); RETURN_NULL(); } set_compare_func(SORT_REGULAR TSRMLS_CC); if (argc == 1) { pval **arr; if (zend_get_parameters_ex(1, &arr) == FAILURE || Z_TYPE_PP(arr) != IS_ARRAY) { WRONG_PARAM_COUNT; } if (zend_hash_minmax(Z_ARRVAL_PP(arr), array_data_compare, 1, (void **) &result TSRMLS_CC) == SUCCESS) { *return_value = **result; zval_copy_ctor(return_value); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array must contain atleast one element"); RETURN_FALSE; } } else { pval ***args = (pval ***) safe_emalloc(sizeof(pval **), ZEND_NUM_ARGS(), 0); pval **max, result; int i; if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) { efree(args); WRONG_PARAM_COUNT; } max = args[0]; for (i=1; i<ZEND_NUM_ARGS(); i++) { is_smaller_or_equal_function(&result, *args[i], *max TSRMLS_CC); if (Z_LVAL(result) == 0) { max = args[i]; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -