不是自定义的排序函数,而是自定义的比较函数,就是说让你自己写函数判断谁大谁小,排序还是他给你排 原文 uasort — Sort an array with a user-defined comparison function and maintain index association附5.2.10相关代码(偷懒没下最新的)/* {{{ 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; HashTable *target_hash; PHP_ARRAY_CMP_FUNC_VARS; PHP_ARRAY_CMP_FUNC_BACKUP(); if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &array, &BG(user_compare_func_name)) == FAILURE) { PHP_ARRAY_CMP_FUNC_RESTORE(); 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"); PHP_ARRAY_CMP_FUNC_RESTORE(); RETURN_FALSE; } PHP_ARRAY_CMP_FUNC_CHECK(BG(user_compare_func_name)) BG(user_compare_fci_cache).initialized = 0; if (zend_hash_sort(target_hash, zend_qsort, array_user_compare, 0 TSRMLS_CC) == FAILURE) { PHP_ARRAY_CMP_FUNC_RESTORE(); RETURN_FALSE; } PHP_ARRAY_CMP_FUNC_RESTORE(); RETURN_TRUE; } /* }}} */
ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func, compare_func_t compar, int renumber TSRMLS_DC) { Bucket **arTmp; Bucket *p; int i, j; IS_CONSISTENT(ht); if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */ return SUCCESS; } arTmp = (Bucket **) pemalloc(ht->nNumOfElements * sizeof(Bucket *), ht->persistent); if (!arTmp) { return FAILURE; } p = ht->pListHead; i = 0; while (p) { arTmp[i] = p; p = p->pListNext; i++; } (*sort_func)((void *) arTmp, i, sizeof(Bucket *), compar TSRMLS_CC); HANDLE_BLOCK_INTERRUPTIONS(); ht->pListHead = arTmp[0]; ht->pListTail = NULL; ht->pInternalPointer = ht->pListHead; arTmp[0]->pListLast = NULL; if (i > 1) { arTmp[0]->pListNext = arTmp[1]; for (j = 1; j < i-1; j++) { arTmp[j]->pListLast = arTmp[j-1]; arTmp[j]->pListNext = arTmp[j+1]; } arTmp[j]->pListLast = arTmp[j-1]; arTmp[j]->pListNext = NULL; } else { arTmp[0]->pListNext = NULL; } ht->pListTail = arTmp[i-1]; pefree(arTmp, ht->persistent); HANDLE_UNBLOCK_INTERRUPTIONS(); if (renumber) { p = ht->pListHead; i=0; while (p != NULL) { p->nKeyLength = 0; p->h = i++; p = p->pListNext; } ht->nNextFreeElement = i; zend_hash_rehash(ht); } return SUCCESS; }/* +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt. | | If you did not receive a copy of the Zend 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. | +----------------------------------------------------------------------+ | Authors: Sterling Hughes <[email protected]> | +----------------------------------------------------------------------+ *//* $Id: zend_qsort.c,v 1.8.2.1.2.3 2008/12/31 11:17:33 sebastian Exp $ */#include "zend.h"#include <limits.h>#define QSORT_STACK_SIZE (sizeof(size_t) * CHAR_BIT)static void _zend_qsort_swap(void *a, void *b, size_t siz) { register char *tmp_a_char; register char *tmp_b_char; register int *tmp_a_int; register int *tmp_b_int; register size_t i; int t_i; char t_c; tmp_a_int = (int *) a; tmp_b_int = (int *) b; for (i = sizeof(int); i <= siz; i += sizeof(int)) { t_i = *tmp_a_int; *tmp_a_int++ = *tmp_b_int; *tmp_b_int++ = t_i; } tmp_a_char = (char *) tmp_a_int; tmp_b_char = (char *) tmp_b_int; for (i = i - sizeof(int) + 1; i <= siz; ++i) { t_c = *tmp_a_char; *tmp_a_char++ = *tmp_b_char; *tmp_b_char++ = t_c; } }ZEND_API void zend_qsort(void *base, size_t nmemb, size_t siz, compare_func_t compare TSRMLS_DC) { void *begin_stack[QSORT_STACK_SIZE]; void *end_stack[QSORT_STACK_SIZE]; register char *begin; register char *end; register char *seg1; register char *seg2; register char *seg2p; register int loop; uint offset; begin_stack[0] = (char *) base; end_stack[0] = (char *) base + ((nmemb - 1) * siz); for (loop = 0; loop >= 0; --loop) { begin = begin_stack[loop]; end = end_stack[loop]; while (begin < end) { offset = (end - begin) >> 1; _zend_qsort_swap(begin, begin + (offset - (offset % siz)), siz); seg1 = begin + siz; seg2 = end; while (1) { for (; seg1 < seg2 && compare(begin, seg1 TSRMLS_CC) > 0; seg1 += siz); for (; seg2 >= seg1 && compare(seg2, begin TSRMLS_CC) > 0; seg2 -= siz);
原文 uasort — Sort an array with a user-defined comparison function and maintain index association附5.2.10相关代码(偷懒没下最新的)/* {{{ 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;
HashTable *target_hash;
PHP_ARRAY_CMP_FUNC_VARS; PHP_ARRAY_CMP_FUNC_BACKUP(); if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &array, &BG(user_compare_func_name)) == FAILURE) {
PHP_ARRAY_CMP_FUNC_RESTORE();
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");
PHP_ARRAY_CMP_FUNC_RESTORE();
RETURN_FALSE;
} PHP_ARRAY_CMP_FUNC_CHECK(BG(user_compare_func_name))
BG(user_compare_fci_cache).initialized = 0; if (zend_hash_sort(target_hash, zend_qsort, array_user_compare, 0 TSRMLS_CC) == FAILURE) {
PHP_ARRAY_CMP_FUNC_RESTORE();
RETURN_FALSE;
}
PHP_ARRAY_CMP_FUNC_RESTORE(); RETURN_TRUE;
}
/* }}} */
compare_func_t compar, int renumber TSRMLS_DC)
{
Bucket **arTmp;
Bucket *p;
int i, j; IS_CONSISTENT(ht); if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */
return SUCCESS;
}
arTmp = (Bucket **) pemalloc(ht->nNumOfElements * sizeof(Bucket *), ht->persistent);
if (!arTmp) {
return FAILURE;
}
p = ht->pListHead;
i = 0;
while (p) {
arTmp[i] = p;
p = p->pListNext;
i++;
} (*sort_func)((void *) arTmp, i, sizeof(Bucket *), compar TSRMLS_CC); HANDLE_BLOCK_INTERRUPTIONS();
ht->pListHead = arTmp[0];
ht->pListTail = NULL;
ht->pInternalPointer = ht->pListHead; arTmp[0]->pListLast = NULL;
if (i > 1) {
arTmp[0]->pListNext = arTmp[1];
for (j = 1; j < i-1; j++) {
arTmp[j]->pListLast = arTmp[j-1];
arTmp[j]->pListNext = arTmp[j+1];
}
arTmp[j]->pListLast = arTmp[j-1];
arTmp[j]->pListNext = NULL;
} else {
arTmp[0]->pListNext = NULL;
}
ht->pListTail = arTmp[i-1]; pefree(arTmp, ht->persistent);
HANDLE_UNBLOCK_INTERRUPTIONS(); if (renumber) {
p = ht->pListHead;
i=0;
while (p != NULL) {
p->nKeyLength = 0;
p->h = i++;
p = p->pListNext;
}
ht->nNextFreeElement = i;
zend_hash_rehash(ht);
}
return SUCCESS;
}/*
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
| Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend 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. |
+----------------------------------------------------------------------+
| Authors: Sterling Hughes <[email protected]> |
+----------------------------------------------------------------------+
*//* $Id: zend_qsort.c,v 1.8.2.1.2.3 2008/12/31 11:17:33 sebastian Exp $ */#include "zend.h"#include <limits.h>#define QSORT_STACK_SIZE (sizeof(size_t) * CHAR_BIT)static void _zend_qsort_swap(void *a, void *b, size_t siz)
{
register char *tmp_a_char;
register char *tmp_b_char;
register int *tmp_a_int;
register int *tmp_b_int;
register size_t i;
int t_i;
char t_c; tmp_a_int = (int *) a;
tmp_b_int = (int *) b; for (i = sizeof(int); i <= siz; i += sizeof(int)) {
t_i = *tmp_a_int;
*tmp_a_int++ = *tmp_b_int;
*tmp_b_int++ = t_i;
} tmp_a_char = (char *) tmp_a_int;
tmp_b_char = (char *) tmp_b_int; for (i = i - sizeof(int) + 1; i <= siz; ++i) {
t_c = *tmp_a_char;
*tmp_a_char++ = *tmp_b_char;
*tmp_b_char++ = t_c;
}
}ZEND_API void zend_qsort(void *base, size_t nmemb, size_t siz, compare_func_t compare TSRMLS_DC)
{
void *begin_stack[QSORT_STACK_SIZE];
void *end_stack[QSORT_STACK_SIZE];
register char *begin;
register char *end;
register char *seg1;
register char *seg2;
register char *seg2p;
register int loop;
uint offset; begin_stack[0] = (char *) base;
end_stack[0] = (char *) base + ((nmemb - 1) * siz); for (loop = 0; loop >= 0; --loop) {
begin = begin_stack[loop];
end = end_stack[loop]; while (begin < end) {
offset = (end - begin) >> 1;
_zend_qsort_swap(begin, begin + (offset - (offset % siz)), siz); seg1 = begin + siz;
seg2 = end; while (1) {
for (; seg1 < seg2 && compare(begin, seg1 TSRMLS_CC) > 0;
seg1 += siz); for (; seg2 >= seg1 && compare(seg2, begin TSRMLS_CC) > 0;
seg2 -= siz);
if (seg1 >= seg2)
break;
_zend_qsort_swap(seg1, seg2, siz); seg1 += siz;
seg2 -= siz;
} _zend_qsort_swap(begin, seg2, siz); seg2p = seg2;
if ((seg2p - begin) <= (end - seg2p)) {
if ((seg2p + siz) < end) {
begin_stack[loop] = seg2p + siz;
end_stack[loop++] = end;
}
end = seg2p - siz;
}
else {
if ((seg2p - siz) > begin) {
begin_stack[loop] = begin;
end_stack[loop++] = seg2p - siz;
}
begin = seg2p + siz;
}
}
}
}/*
* Local Variables:
* c-basic-offset: 4
* tab-width: 4
* End:
* vim600: fdm=er
* vim: noet sw=4 ts=4
*/