]> granicus.if.org Git - php/commitdiff
- Implemented basic collation support. For some reason "new Collator" gives segfaults...
authorDerick Rethans <derick@php.net>
Sun, 26 Mar 2006 11:06:24 +0000 (11:06 +0000)
committerDerick Rethans <derick@php.net>
Sun, 26 Mar 2006 11:06:24 +0000 (11:06 +0000)
- The following example shows what is implemented:

<?php
$orig = $strings = array(
    'côte',
    'cote',
    'côté',
    'coté',
    'fluÃ\9fe',
    'flüÃ\9fe',
);

echo "German phonebook:\n";
$c = collator_create( "de@collation=phonebook" );
foreach($c->sort($strings) as $string) {
    echo $string, "\n";
}
echo $c->getAttribute(Collator::FRENCH_COLLATION) == Collator::ON
    ? "With" : "Without", " french accent sorting order\n";

echo "\nFrench with options:\n";
$c = collator_create( "fr" );
$c->setAttribute(Collator::CASE_FIRST, Collator::UPPER_FIRST);
$c->setAttribute(Collator::CASE_LEVEL, Collator::ON);
$c->setStrength(Collator::SECONDARY);
foreach($c->sort($strings) as $string) {
    echo $string, "\n";
}
echo $c->getAttribute(Collator::FRENCH_COLLATION) == Collator::ON
    ? "With" : "Without", " french accent sorting order\n";
?>

ext/standard/array.c
ext/standard/php_array.h
ext/unicode/collator.c [new file with mode: 0644]
ext/unicode/config.m4
ext/unicode/config.w32
ext/unicode/php_unicode.h
ext/unicode/unicode.c

index 3ae61a4973723eaeb30f8f8a0cb485b6c3d42413..72f2f508736fc22f7ba67fbe508aa2f4bf46bdcf 100644 (file)
 
 #define EXTR_REFS                              0x100
 
-#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
 
@@ -139,7 +134,7 @@ PHP_MSHUTDOWN_FUNCTION(array)
        return SUCCESS;
 }
 
-static void set_compare_func(int sort_type TSRMLS_DC)
+PHPAPI void php_set_compare_func(int sort_type TSRMLS_DC)
 {
        switch (sort_type) {
                case SORT_NUMERIC:
@@ -241,7 +236,7 @@ PHP_FUNCTION(krsort)
        }
        
        target_hash = HASH_OF(array);
-       set_compare_func(sort_type TSRMLS_CC);
+       php_set_compare_func(sort_type TSRMLS_CC);
        
        if (zend_hash_sort(target_hash, zend_qsort, array_reverse_key_compare, 0 TSRMLS_CC) == FAILURE) {
                RETURN_FALSE;
@@ -263,7 +258,7 @@ PHP_FUNCTION(ksort)
        }
 
        target_hash = HASH_OF(array);
-       set_compare_func(sort_type TSRMLS_CC);
+       php_set_compare_func(sort_type TSRMLS_CC);
        
        if (zend_hash_sort(target_hash, zend_qsort, array_key_compare, 0 TSRMLS_CC) == FAILURE) {
                RETURN_FALSE;
@@ -346,7 +341,7 @@ PHP_FUNCTION(count)
  *
  * This is not correct any more, depends on what compare_func is set to.
  */
-static int array_data_compare(const void *a, const void *b TSRMLS_DC)
+PHPAPI int php_array_data_compare(const void *a, const void *b TSRMLS_DC)
 {
        Bucket *f;
        Bucket *s;
@@ -387,7 +382,7 @@ static int array_data_compare(const void *a, const void *b TSRMLS_DC)
 
 static int array_reverse_data_compare(const void *a, const void *b TSRMLS_DC)
 {
-       return array_data_compare(a, b TSRMLS_CC)*-1;
+       return php_array_data_compare(a, b TSRMLS_CC)*-1;
 }
 
 static int array_natural_general_compare(const void *a, const void *b, int fold_case)
@@ -493,9 +488,9 @@ PHP_FUNCTION(asort)
        }
        
        target_hash = HASH_OF(array);
-       set_compare_func(sort_type TSRMLS_CC);
+       php_set_compare_func(sort_type TSRMLS_CC);
        
-       if (zend_hash_sort(target_hash, zend_qsort, array_data_compare, 0 TSRMLS_CC) == FAILURE) {
+       if (zend_hash_sort(target_hash, zend_qsort, php_array_data_compare, 0 TSRMLS_CC) == FAILURE) {
                RETURN_FALSE;
        }
        RETURN_TRUE;
@@ -515,7 +510,7 @@ PHP_FUNCTION(arsort)
        }
        
        target_hash = HASH_OF(array);
-       set_compare_func(sort_type TSRMLS_CC);
+       php_set_compare_func(sort_type TSRMLS_CC);
        
        if (zend_hash_sort(target_hash, zend_qsort, array_reverse_data_compare, 0 TSRMLS_CC) == FAILURE) {
                RETURN_FALSE;
@@ -537,9 +532,9 @@ PHP_FUNCTION(sort)
        }
        
        target_hash = HASH_OF(array);
-       set_compare_func(sort_type TSRMLS_CC);
+       php_set_compare_func(sort_type TSRMLS_CC);
        
-       if (zend_hash_sort(target_hash, zend_qsort, array_data_compare, 1 TSRMLS_CC) == FAILURE) {
+       if (zend_hash_sort(target_hash, zend_qsort, php_array_data_compare, 1 TSRMLS_CC) == FAILURE) {
                RETURN_FALSE;
        }
        RETURN_TRUE;
@@ -559,7 +554,7 @@ PHP_FUNCTION(rsort)
        }
        
        target_hash = HASH_OF(array);
-       set_compare_func(sort_type TSRMLS_CC);
+       php_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;
@@ -968,14 +963,14 @@ PHP_FUNCTION(min)
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Atleast one value should be passed");
                RETURN_NULL();
        }
-       set_compare_func(SORT_REGULAR TSRMLS_CC);
+       php_set_compare_func(SORT_REGULAR TSRMLS_CC);
        if (argc == 1) {
                zval **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) {
+               if (zend_hash_minmax(Z_ARRVAL_PP(arr), php_array_data_compare, 0, (void **) &result TSRMLS_CC) == SUCCESS) {
                        RETVAL_ZVAL(*result, 1, 0);
                } else {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array must contain atleast one element");
@@ -1018,14 +1013,14 @@ PHP_FUNCTION(max)
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Atleast one value should be passed");
                RETURN_NULL();
        }
-       set_compare_func(SORT_REGULAR TSRMLS_CC);
+       php_set_compare_func(SORT_REGULAR TSRMLS_CC);
        if (argc == 1) {
                zval **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) {
+               if (zend_hash_minmax(Z_ARRVAL_PP(arr), php_array_data_compare, 1, (void **) &result TSRMLS_CC) == SUCCESS) {
                        RETVAL_ZVAL(*result, 1, 0);
                } else {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array must contain atleast one element");
@@ -3026,13 +3021,13 @@ PHP_FUNCTION(array_unique)
                arTmp[i].i = i;
        }
        arTmp[i].b = NULL;
-       set_compare_func(SORT_STRING TSRMLS_CC);
-       zend_qsort((void *) arTmp, i, sizeof(struct bucketindex), array_data_compare TSRMLS_CC);
+       php_set_compare_func(SORT_STRING TSRMLS_CC);
+       zend_qsort((void *) arTmp, i, sizeof(struct bucketindex), php_array_data_compare TSRMLS_CC);
 
        /* go through the sorted array and delete duplicates from the copy */
        lastkept = arTmp;
        for (cmpdata = arTmp + 1; cmpdata->b; cmpdata++) {
-               if (array_data_compare(lastkept, cmpdata TSRMLS_CC)) {
+               if (php_array_data_compare(lastkept, cmpdata TSRMLS_CC)) {
                        lastkept = cmpdata;
                } else {
                        if (lastkept->i > cmpdata->i) {
@@ -3091,7 +3086,7 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int
                                WRONG_PARAM_COUNT;
                        }
                        arr_argc = argc;
-                       intersect_data_compare_func = array_data_compare;
+                       intersect_data_compare_func = php_array_data_compare;
                } else if (data_compare_type == INTERSECT_COMP_DATA_USER) {
                        /* array_uintersect() */
                        if (argc < 3) {
@@ -3130,7 +3125,7 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int
                        }
                        arr_argc = argc;
                        intersect_key_compare_func = array_key_compare;
-                       intersect_data_compare_func = array_data_compare;
+                       intersect_data_compare_func = php_array_data_compare;
                } else if (data_compare_type == INTERSECT_COMP_DATA_USER 
                                &&
                                key_compare_type == INTERSECT_COMP_KEY_INTERNAL) {
@@ -3168,7 +3163,7 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int
                                }
                                zval_dtor(&callback_name);
                                intersect_key_compare_func = array_user_key_compare;
-                               intersect_data_compare_func = array_data_compare;
+                               intersect_data_compare_func = php_array_data_compare;
                                BG(user_compare_func_name) = args[arr_argc];
                } else if (data_compare_type == INTERSECT_COMP_DATA_USER
                                &&
@@ -3210,7 +3205,7 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int
        /* for each argument, create and sort list with pointers to the hash buckets */
        lists = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);
        ptrs = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);
-       set_compare_func(SORT_STRING TSRMLS_CC);
+       php_set_compare_func(SORT_STRING TSRMLS_CC);
        for (i = 0; i < arr_argc; i++) {
                if (Z_TYPE_PP(args[i]) != IS_ARRAY) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i+1);
@@ -3476,7 +3471,7 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_
                                WRONG_PARAM_COUNT;
                        }
                        arr_argc = argc;
-                       diff_data_compare_func = array_data_compare;
+                       diff_data_compare_func = php_array_data_compare;
                } else if (data_compare_type == DIFF_COMP_DATA_USER) {
                        /* array_udiff */
                        if (argc < 3) {
@@ -3515,7 +3510,7 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_
                        }
                        arr_argc = argc;
                        diff_key_compare_func = array_key_compare;
-                       diff_data_compare_func = array_data_compare;
+                       diff_data_compare_func = php_array_data_compare;
                } else if (data_compare_type == DIFF_COMP_DATA_USER 
                                && 
                        key_compare_type == DIFF_COMP_KEY_INTERNAL) {
@@ -3553,7 +3548,7 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_
                        }
                        zval_dtor(&callback_name);
                        diff_key_compare_func = array_user_key_compare;
-                       diff_data_compare_func = array_data_compare;
+                       diff_data_compare_func = php_array_data_compare;
                        BG(user_compare_func_name) = args[arr_argc];
                } else if (data_compare_type == DIFF_COMP_DATA_USER 
                                && 
@@ -3595,7 +3590,7 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_
        /* for each argument, create and sort list with pointers to the hash buckets */
        lists = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);
        ptrs = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);
-       set_compare_func(SORT_STRING TSRMLS_CC);
+       php_set_compare_func(SORT_STRING TSRMLS_CC);
        for (i = 0; i < arr_argc; i++) {
                if (Z_TYPE_PP(args[i]) != IS_ARRAY) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1);
@@ -3841,7 +3836,7 @@ int multisort_compare(const void *a, const void *b TSRMLS_DC)
        
        r = 0;
        do {
-               set_compare_func(ARRAYG(multisort_flags)[MULTISORT_TYPE][r] TSRMLS_CC);
+               php_set_compare_func(ARRAYG(multisort_flags)[MULTISORT_TYPE][r] TSRMLS_CC);
 
                ARRAYG(compare_func)(&temp, *((zval **)ab[r]->pData), *((zval **)bb[r]->pData) TSRMLS_CC);
                result = ARRAYG(multisort_flags)[MULTISORT_ORDER][r] * Z_LVAL(temp);
index 6d80348871c19468bc120c454a41d2a9b64b55cc..076a82ffd3ebe4dc128657599f604cb58e5ac523 100644 (file)
@@ -102,6 +102,14 @@ PHP_FUNCTION(array_combine);
 HashTable* php_splice(HashTable *, int, int, zval ***, int, HashTable **);
 PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS_DC);
 int multisort_compare(const void *a, const void *b TSRMLS_DC);
+PHPAPI int php_array_data_compare(const void *a, const void *b TSRMLS_DC);
+PHPAPI void php_set_compare_func(int sort_type TSRMLS_DC);
+
+#define SORT_REGULAR                   0
+#define SORT_NUMERIC                   1
+#define        SORT_STRING                             2
+#define        SORT_LOCALE_STRING      5
+
 
 ZEND_BEGIN_MODULE_GLOBALS(array) 
        int *multisort_flags[2];
diff --git a/ext/unicode/collator.c b/ext/unicode/collator.c
new file mode 100644 (file)
index 0000000..4131e21
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP Version 6                                                        |
+   +----------------------------------------------------------------------+
+   | 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        |
+   | available through the world-wide-web at the following url:           |
+   | http://www.php.net/license/3_01.txt                                  |
+   | If you did not receive a copy of the PHP license and are unable to   |
+   | obtain it through the world-wide-web, please send a note to          |
+   | license@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Authors: Derick Rethans <derick@php.net>                             |
+   +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include "php.h"
+#include "ext/standard/php_array.h"
+#include "zend_interfaces.h"
+#include "zend_exceptions.h"
+#include "php_unicode.h"
+#include <unicode/ucol.h>
+
+
+zend_function_entry collator_funcs_collator[] = {
+       ZEND_ME(collator, __construct, NULL, ZEND_ACC_PUBLIC)
+       ZEND_NAMED_FE(compare, ZEND_FN(collator_compare), NULL)
+       ZEND_NAMED_FE(setStrength, ZEND_FN(collator_set_strength), NULL)
+       ZEND_NAMED_FE(setAttribute, ZEND_FN(collator_set_attribute), NULL)
+       ZEND_NAMED_FE(getStrength, ZEND_FN(collator_get_strength), NULL)
+       ZEND_NAMED_FE(getAttribute, ZEND_FN(collator_get_attribute), NULL)
+       ZEND_NAMED_FE(sort, ZEND_FN(collator_sort), NULL)
+       {NULL, NULL, NULL}
+};
+
+zend_class_entry *unicode_ce_collator;
+
+static zend_object_handlers unicode_object_handlers_collator;
+
+typedef struct _php_collator_obj php_collator_obj;
+
+struct _php_collator_obj {
+       zend_object   std;
+       UCollator *col;
+};
+
+#define COLLATOR_SET_CONTEXT \
+       zval *object; \
+       object = getThis(); \
+   
+#define COLLATOR_FETCH_OBJECT  \
+       php_collator_obj *obj;  \
+       COLLATOR_SET_CONTEXT; \
+       if (object) {   \
+               if (ZEND_NUM_ARGS()) {  \
+                       WRONG_PARAM_COUNT;      \
+               }       \
+       } else {        \
+               if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, NULL, "O", &object, unicode_ce_collator) == FAILURE) {      \
+                       RETURN_FALSE;   \
+               }       \
+       }       \
+       obj = (php_collator_obj *) zend_object_store_get_object(object TSRMLS_CC);
+
+static zend_object_value collator_object_new(zend_class_entry *class_type TSRMLS_DC);
+static void collator_object_free_storage(void *object TSRMLS_DC);
+
+static void collator_register_class(TSRMLS_D)
+{
+       zend_class_entry ce_collator;
+
+       INIT_CLASS_ENTRY(ce_collator, "Collator", collator_funcs_collator);
+       ce_collator.create_object = collator_object_new;
+       unicode_ce_collator = zend_register_internal_class_ex(&ce_collator, NULL, NULL TSRMLS_CC);
+       memcpy(&unicode_object_handlers_collator, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+       unicode_object_handlers_collator.clone_obj = NULL;
+
+#define REGISTER_COLLATOR_CLASS_CONST_STRING(const_name, value) \
+       zend_declare_class_constant_stringl(unicode_ce_collator, const_name, sizeof(const_name)-1, value, sizeof(value)-1 TSRMLS_CC);
+#define REGISTER_COLLATOR_CLASS_CONST_LONG(const_name, value) \
+       zend_declare_class_constant_long(unicode_ce_collator, const_name, sizeof(const_name)-1, value TSRMLS_CC);
+
+       /* Attributes */
+       REGISTER_COLLATOR_CLASS_CONST_LONG("FRENCH_COLLATION", UCOL_FRENCH_COLLATION);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("ALTERNATE_HANDLING", UCOL_ALTERNATE_HANDLING);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("CASE_FIRST", UCOL_CASE_FIRST);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("CASE_LEVEL", UCOL_CASE_LEVEL);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("NORMALIZATION_MODE", UCOL_NORMALIZATION_MODE);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("STRENGTH", UCOL_STRENGTH);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("HIRAGANA_QUARTERNARY_MODE", UCOL_HIRAGANA_QUATERNARY_MODE);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("NUMERIC_COLLATION", UCOL_NUMERIC_COLLATION);
+
+       
+       /* Attribute value constants */
+       REGISTER_COLLATOR_CLASS_CONST_LONG("DEFAULT_VALUE", UCOL_DEFAULT);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("PRIMARY", UCOL_PRIMARY);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("SECONDARY", UCOL_SECONDARY);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("TERTIARY", UCOL_TERTIARY);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("DEFAULT_STRENGHT", UCOL_DEFAULT_STRENGTH);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("QUARTERNARY", UCOL_QUATERNARY);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("IDENTICAL", UCOL_IDENTICAL);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("ON", UCOL_ON);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("OFF", UCOL_OFF);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("SHIFTED", UCOL_SHIFTED);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("NON_IGNORABLE", UCOL_NON_IGNORABLE);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("LOWER_FIRST", UCOL_LOWER_FIRST);
+       REGISTER_COLLATOR_CLASS_CONST_LONG("UPPER_FIRST", UCOL_UPPER_FIRST);
+}
+
+
+void php_init_collation(TSRMLS_D)
+{
+       collator_register_class(TSRMLS_C);
+}
+
+
+static zend_object_value collator_object_new(zend_class_entry *class_type TSRMLS_DC)
+{
+       php_collator_obj *intern;
+       zend_object_value retval;
+       zval *tmp;
+
+       intern = emalloc(sizeof(php_collator_obj));
+       memset(intern, 0, sizeof(php_collator_obj));
+       intern->std.ce = class_type;
+       
+       ALLOC_HASHTABLE(intern->std.properties);
+       zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       
+       retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) collator_object_free_storage, NULL TSRMLS_CC);
+       retval.handlers = &unicode_object_handlers_collator;
+       
+       return retval;
+}
+
+static void collator_object_free_storage(void *object TSRMLS_DC)
+{
+       php_collator_obj *intern = (php_collator_obj *)object;
+
+       if (intern->col) {
+               ucol_close(intern->col);
+       }
+
+       if (intern->std.properties) {
+               zend_hash_destroy(intern->std.properties);
+               efree(intern->std.properties);
+               intern->std.properties = NULL;
+       }
+       
+       efree(object);
+}
+
+static zval* collator_instanciate(zend_class_entry *pce, zval *object TSRMLS_DC)
+{
+       if (!object) {
+               ALLOC_ZVAL(object);
+       }
+
+       Z_TYPE_P(object) = IS_OBJECT;
+       object_init_ex(object, pce);
+       object->refcount = 1;
+       object->is_ref = 1;
+       return object;
+}
+
+PHP_METHOD(collator, __construct)
+{
+       zif_collator_create(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+PHP_FUNCTION(collator_create)
+{
+       php_collator_obj *collatorobj;
+       UErrorCode        error;
+       char             *collator_name;
+       int               collator_name_len;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &collator_name, &collator_name_len) == FAILURE) {
+               RETURN_FALSE;
+       }
+
+       collator_instanciate(unicode_ce_collator, return_value TSRMLS_CC);
+       collatorobj = (php_collator_obj *) zend_object_store_get_object(return_value TSRMLS_CC);
+       error = U_ZERO_ERROR;
+       collatorobj->col = ucol_open(collator_name, &error);
+}
+
+PHP_FUNCTION(collator_compare)
+{
+       zval             *object;
+       php_collator_obj *collatorobj;
+       UChar            *string1, *string2;
+       int               string1_len, string2_len;
+
+       if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ouu", &object, unicode_ce_collator, &string1, &string1_len, &string2, &string2_len) == FAILURE) {
+               RETURN_FALSE;
+       }
+       collatorobj = (php_collator_obj *) zend_object_store_get_object(object TSRMLS_CC);
+       RETURN_LONG(ucol_strcoll(collatorobj->col, string1, string1_len, string2, string2_len));
+}
+
+PHP_FUNCTION(collator_sort)
+{
+       zval             *object;
+       php_collator_obj *collatorobj;
+       zval             *array;
+       HashTable        *target_hash;
+       UCollator        *orig_collator;
+
+       if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oa/", &object, unicode_ce_collator, &array) == FAILURE) {
+               RETURN_FALSE;
+       }
+       collatorobj = (php_collator_obj *) zend_object_store_get_object(object TSRMLS_CC);
+
+       target_hash = HASH_OF(array);
+       php_set_compare_func(SORT_LOCALE_STRING TSRMLS_CC);
+       orig_collator = UG(default_collator);
+       UG(default_collator) = collatorobj->col;
+       if (zend_hash_sort(target_hash, zend_qsort, php_array_data_compare, 1 TSRMLS_CC) == FAILURE) {
+               RETVAL_FALSE;
+       } else {
+               RETVAL_ZVAL(array, 1, 0);
+       }
+       UG(default_collator) = orig_collator;
+}
+
+PHP_FUNCTION(collator_set_strength)
+{
+       zval             *object;
+       php_collator_obj *collatorobj;
+       long              strength;
+
+       if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &object, unicode_ce_collator, &strength) == FAILURE) {
+               RETURN_FALSE;
+       }
+       collatorobj = (php_collator_obj *) zend_object_store_get_object(object TSRMLS_CC);
+       ucol_setStrength(collatorobj->col, strength);
+}
+
+PHP_FUNCTION(collator_get_strength)
+{
+       zval             *object;
+       php_collator_obj *collatorobj;
+
+       if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, unicode_ce_collator) == FAILURE) {
+               RETURN_FALSE;
+       }
+       collatorobj = (php_collator_obj *) zend_object_store_get_object(object TSRMLS_CC);
+       RETURN_LONG(ucol_getStrength(collatorobj->col));
+}
+
+PHP_FUNCTION(collator_set_attribute)
+{
+       zval             *object;
+       php_collator_obj *collatorobj;
+       long              attribute, value;
+       UErrorCode        error;
+
+       if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll", &object, unicode_ce_collator, &attribute, &value) == FAILURE) {
+               RETURN_FALSE;
+       }
+       collatorobj = (php_collator_obj *) zend_object_store_get_object(object TSRMLS_CC);
+       error = U_ZERO_ERROR;
+       ucol_setAttribute(collatorobj->col, attribute, value, &error);
+       RETURN_BOOL(error == U_ZERO_ERROR ? 1 : 0);
+}
+
+PHP_FUNCTION(collator_get_attribute)
+{
+       zval             *object;
+       php_collator_obj *collatorobj;
+       long              attribute, value;
+       UErrorCode        error;
+
+       if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &object, unicode_ce_collator, &attribute) == FAILURE) {
+               RETURN_FALSE;
+       }
+       collatorobj = (php_collator_obj *) zend_object_store_get_object(object TSRMLS_CC);
+       error = U_ZERO_ERROR;
+       value = ucol_getAttribute(collatorobj->col, attribute, &error);
+       if (error != U_ZERO_ERROR) {
+               RETURN_FALSE;
+       }
+       RETURN_LONG(value);
+}
index ae9ed568c3cb1c9c6491a52fdf41eb47ff0f7684..afa089613c4330eb968d346218c2c02c56049d07 100644 (file)
@@ -4,4 +4,4 @@ dnl
 
 PHP_SUBST(UNICODE_SHARED_LIBADD)
 AC_DEFINE(HAVE_UNICODE, 1, [ ])
-PHP_NEW_EXTENSION(unicode, unicode.c locale.c unicode_filter.c unicode_iterators.c, $ext_shared)
+PHP_NEW_EXTENSION(unicode, unicode.c locale.c unicode_filter.c unicode_iterators.c collator.c, $ext_shared)
index 9fe1e3de8723c32ea88fb8feb7a8c5a1d1c6608b..5321397c1e4a589a5a58954a442dd7bc6cd58fcd 100644 (file)
@@ -1,5 +1,5 @@
 // $Id$
 // vim:ft=javascript
 
-EXTENSION("unicode", "unicode.c unicode_filter.c unicode_iterators.c locale.c");
+EXTENSION("unicode", "unicode.c unicode_filter.c unicode_iterators.c collator.c locale.c");
 AC_DEFINE('HAVE_UNICODE', 1, 'ICU API extension');
index d90d192d796828da4af7e4b854fbff996fa184d1..1de91686f3150a06a01c873390a4670e67bcc2a4 100644 (file)
@@ -57,7 +57,16 @@ PHP_MINFO_FUNCTION(unicode);
 
 PHP_FUNCTION(i18n_loc_get_default);
 PHP_FUNCTION(i18n_loc_set_default);
-
+PHP_FUNCTION(collator_create);
+PHP_FUNCTION(collator_compare);
+PHP_FUNCTION(collator_sort);
+PHP_FUNCTION(collator_set_strength);
+PHP_FUNCTION(collator_set_attribute);
+PHP_FUNCTION(collator_get_strength);
+PHP_FUNCTION(collator_get_attribute);
+PHP_METHOD(collator, __construct);
+
+void php_init_collation(TSRMLS_D);
 extern php_stream_filter_factory php_unicode_filter_factory;
 
 #ifdef  __cplusplus
index e019d245c616840a44e2856cc88d498a518bdedc..63511e79873f1d12cb856c17d6c0deb7fc7d9d5c 100644 (file)
@@ -184,6 +184,8 @@ zend_function_entry unicode_functions[] = {
        PHP_FE(unicode_encode, NULL)
        PHP_FE(unicode_set_error_mode, NULL)
        PHP_FE(unicode_set_subst_char, NULL)
+       PHP_FE(collator_create, NULL)
+       PHP_FE(collator_compare, NULL)
        { NULL, NULL, NULL }
 };
 /* }}} */
@@ -217,7 +219,8 @@ PHP_MINIT_FUNCTION(unicode)
        }
 
        php_register_unicode_iterators(TSRMLS_C);
-
+       php_init_collation(TSRMLS_C);
+       
        return SUCCESS;
 }
 /* }}} */