Locale Based Array sorting
| From: | Derick Rethans | Date: | Fri, 10 Sep 2004 11:20:28 +0000 |
| Subject: | Locale Based Array sorting | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-12713@lists.php.net to get a copy of this message | ||
Hello,
the attached patch adds a flag (SORT_LOCALE_STRING) to our sort
functions that allows the sorting to be done based on the locale
settings. This is important for languages like Norwegian which adds æ, ø
and å to the end of the alphabet, while their iso-8859-1 (the "C"
locale) order is å æ ø.
The working is demonstrated as follows:
<?php
$a = array("ætte", "åtte", "øtte");
$d = $c = $b = $a;
setlocale(LC_ALL, 'C');
sort($a);
sort($b, SORT_LOCALE_STRING);
var_dump($b);
setlocale(LC_ALL, 'no_NO');
sort($c, SORT_LOCALE_STRING);
var_dump($c);
// Words in UTF-8
$d = array("åtte", "Þtte2", "Êtte4", "Þtte1",
"Êtte3");
setlocale(LC_ALL, 'no_NO.UTF-8');
sort($d, SORT_LOCALE_STRING);
var_dump($d);
?>
Output:
array(3) {
[0]=> string(4) "åtte"
[1]=> string(4) "ætte"
[2]=> string(4) "øtte"
}
array(3) {
[0]=> string(4) "ætte"
[1]=> string(4) "øtte"
[2]=> string(4) "åtte"
}
array(5) {
[0]=> string(6) "Êtte3"
[1]=> string(6) "Êtte4"
[2]=> string(6) "Þtte1"
[3]=> string(6) "Þtte2"
[4]=> string(5) "Ã¥tte"
}
(The funny chars are UTf8, but it is correct sorting)
I will be committing this patch later, if there are no objections.
Derick
--
Derick Rethans
http://derickrethans.nl | http://ez.no | http://xdebug.org
? Zend Index: ext/standard/array.c =================================================================== RCS file: /repository/php-src/ext/standard/array.c,v retrieving revision 1.266.2.2 diff -u -p -r1.266.2.2 array.c --- ext/standard/array.c 10 Aug 2004 06:01:20 -0000 1.266.2.2 +++ ext/standard/array.c 10 Sep 2004 10:46:27 -0000 @@ -65,6 +65,7 @@ php_array_globals array_globals; #define SORT_REGULAR 0 #define SORT_NUMERIC 1 #define SORT_STRING 2 +#define SORT_LOCALE_STRING 5 #define SORT_DESC 3 #define SORT_ASC 4 @@ -112,6 +113,8 @@ PHP_MINIT_FUNCTION(array) 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); + REGISTER_LONG_CONSTANT("SORT_LOCALE_STRING", SORT_LOCALE_STRING, 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,6 +144,10 @@ static void set_compare_func(int sort_ty ARRAYG(compare_func) = string_compare_function; break; + case SORT_LOCALE_STRING: + ARRAYG(compare_func) = string_locale_compare_function; + break; + case SORT_REGULAR: default: ARRAYG(compare_func) = compare_function; Index: Zend/zend_operators.c =================================================================== RCS file: /repository/ZendEngine2/zend_operators.c,v retrieving revision 1.193 diff -u -p -r1.193 zend_operators.c --- Zend/zend_operators.c 10 May 2004 14:56:21 -0000 1.193 +++ Zend/zend_operators.c 10 Sep 2004 10:49:08 -0000 @@ -1221,6 +1221,33 @@ ZEND_API int string_compare_function(zva return SUCCESS; } +ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) +{ + zval op1_copy, op2_copy; + int use_copy1, use_copy2; + + zend_make_printable_zval(op1, &op1_copy, &use_copy1); + zend_make_printable_zval(op2, &op2_copy, &use_copy2); + + if (use_copy1) { + op1 = &op1_copy; + } + if (use_copy2) { + op2 = &op2_copy; + } + + result->value.lval = strcoll(op1->value.str.val, op2->value.str.val); + result->type = IS_LONG; + + if (use_copy1) { + zval_dtor(op1); + } + if (use_copy2) { + zval_dtor(op2); + } + return SUCCESS; +} + ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) { zval op1_copy, op2_copy; Index: Zend/zend_operators.h =================================================================== RCS file: /repository/ZendEngine2/zend_operators.h,v retrieving revision 1.88.2.1 diff -u -p -r1.88.2.1 zend_operators.h --- Zend/zend_operators.h 16 Jul 2004 02:02:09 -0000 1.88.2.1 +++ Zend/zend_operators.h 10 Sep 2004 10:49:08 -0000 @@ -179,6 +179,7 @@ ZEND_API int zval_is_true(zval *op); ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); +ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); ZEND_API void zend_str_tolower(char *str, unsigned int length); ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length);
? Zend Index: ext/standard/array.c =================================================================== RCS file: /repository/php-src/ext/standard/array.c,v retrieving revision 1.266.2.2 diff -u -p -r1.266.2.2 array.c --- ext/standard/array.c 10 Aug 2004 06:01:20 -0000 1.266.2.2 +++ ext/standard/array.c 10 Sep 2004 10:46:27 -0000 @@ -65,6 +65,7 @@ php_array_globals array_globals; #define SORT_REGULAR 0 #define SORT_NUMERIC 1 #define SORT_STRING 2 +#define SORT_LOCALE_STRING 5 #define SORT_DESC 3 #define SORT_ASC 4 @@ -112,6 +113,8 @@ PHP_MINIT_FUNCTION(array) 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); + REGISTER_LONG_CONSTANT("SORT_LOCALE_STRING", SORT_LOCALE_STRING, 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,6 +144,10 @@ static void set_compare_func(int sort_ty ARRAYG(compare_func) = string_compare_function; break; + case SORT_LOCALE_STRING: + ARRAYG(compare_func) = string_locale_compare_function; + break; + case SORT_REGULAR: default: ARRAYG(compare_func) = compare_function; Index: Zend/zend_operators.c =================================================================== RCS file: /repository/ZendEngine2/zend_operators.c,v retrieving revision 1.193 diff -u -p -r1.193 zend_operators.c --- Zend/zend_operators.c 10 May 2004 14:56:21 -0000 1.193 +++ Zend/zend_operators.c 10 Sep 2004 10:49:08 -0000 @@ -1221,6 +1221,33 @@ ZEND_API int string_compare_function(zva return SUCCESS; } +ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) +{ + zval op1_copy, op2_copy; + int use_copy1, use_copy2; + + zend_make_printable_zval(op1, &op1_copy, &use_copy1); + zend_make_printable_zval(op2, &op2_copy, &use_copy2); + + if (use_copy1) { + op1 = &op1_copy; + } + if (use_copy2) { + op2 = &op2_copy; + } + + result->value.lval = strcoll(op1->value.str.val, op2->value.str.val); + result->type = IS_LONG; + + if (use_copy1) { + zval_dtor(op1); + } + if (use_copy2) { + zval_dtor(op2); + } + return SUCCESS; +} + ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) { zval op1_copy, op2_copy; Index: Zend/zend_operators.h =================================================================== RCS file: /repository/ZendEngine2/zend_operators.h,v retrieving revision 1.88.2.1 diff -u -p -r1.88.2.1 zend_operators.h --- Zend/zend_operators.h 16 Jul 2004 02:02:09 -0000 1.88.2.1 +++ Zend/zend_operators.h 10 Sep 2004 10:49:08 -0000 @@ -179,6 +179,7 @@ ZEND_API int zval_is_true(zval *op); ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); +ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); ZEND_API void zend_str_tolower(char *str, unsigned int length); ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length);