#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
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:
}
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;
}
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;
*
* 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;
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)
}
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;
}
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;
}
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;
}
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;
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");
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");
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) {
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) {
}
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) {
}
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
&&
/* 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);
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) {
}
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) {
}
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
&&
/* 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);
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);
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | 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);
+}