summaryrefslogtreecommitdiff
path: root/ext/intl/collator
diff options
context:
space:
mode:
authorStanislav Malyshev <stas@php.net>2008-07-07 22:51:04 +0000
committerStanislav Malyshev <stas@php.net>2008-07-07 22:51:04 +0000
commit0d16b1516b6b9ef0c2696bc19069e4cda5aee0ea (patch)
treedf4e6a46dea0afafdbc912919b32c2806841a4eb /ext/intl/collator
parent3bab7c18ac205863af3df740144be23c18cf7a72 (diff)
downloadphp-git-0d16b1516b6b9ef0c2696bc19069e4cda5aee0ea.tar.gz
Merge intl extension into core
Diffstat (limited to 'ext/intl/collator')
-rwxr-xr-xext/intl/collator/collator.c96
-rwxr-xr-xext/intl/collator/collator.h29
-rwxr-xr-xext/intl/collator/collator_attr.c157
-rwxr-xr-xext/intl/collator/collator_attr.h28
-rwxr-xr-xext/intl/collator/collator_class.c197
-rwxr-xr-xext/intl/collator/collator_class.h71
-rwxr-xr-xext/intl/collator/collator_compare.c119
-rwxr-xr-xext/intl/collator/collator_compare.h25
-rwxr-xr-xext/intl/collator/collator_convert.c482
-rwxr-xr-xext/intl/collator/collator_convert.h38
-rwxr-xr-xext/intl/collator/collator_create.c135
-rwxr-xr-xext/intl/collator/collator_create.h27
-rwxr-xr-xext/intl/collator/collator_error.c94
-rwxr-xr-xext/intl/collator/collator_error.h26
-rwxr-xr-xext/intl/collator/collator_is_numeric.c305
-rwxr-xr-xext/intl/collator/collator_is_numeric.h26
-rwxr-xr-xext/intl/collator/collator_locale.c71
-rwxr-xr-xext/intl/collator/collator_locale.h25
-rwxr-xr-xext/intl/collator/collator_sort.c532
-rwxr-xr-xext/intl/collator/collator_sort.h29
20 files changed, 2512 insertions, 0 deletions
diff --git a/ext/intl/collator/collator.c b/ext/intl/collator/collator.c
new file mode 100755
index 0000000000..4c1bbc7797
--- /dev/null
+++ b/ext/intl/collator/collator.c
@@ -0,0 +1,96 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "collator_class.h"
+#include "collator.h"
+
+#include <unicode/utypes.h>
+#include <unicode/ucol.h>
+#include <unicode/ustring.h>
+
+/* {{{ collator_register_constants
+ * Register constants common for the both (OO and procedural)
+ * APIs.
+ */
+void collator_register_constants( INIT_FUNC_ARGS )
+{
+ if( !Collator_ce_ptr )
+ {
+ zend_error( E_ERROR, "Collator class not defined" );
+ return;
+ }
+
+ #define COLLATOR_EXPOSE_CONST(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS)
+ #define COLLATOR_EXPOSE_CLASS_CONST(x) zend_declare_class_constant_long( Collator_ce_ptr, ZEND_STRS( #x ) - 1, UCOL_##x TSRMLS_CC );
+ #define COLLATOR_EXPOSE_CUSTOM_CLASS_CONST(name, value) zend_declare_class_constant_long( Collator_ce_ptr, ZEND_STRS( name ) - 1, value TSRMLS_CC );
+
+ // UColAttributeValue constants
+ COLLATOR_EXPOSE_CUSTOM_CLASS_CONST( "DEFAULT_VALUE", UCOL_DEFAULT );
+
+ COLLATOR_EXPOSE_CLASS_CONST( PRIMARY );
+ COLLATOR_EXPOSE_CLASS_CONST( SECONDARY );
+ COLLATOR_EXPOSE_CLASS_CONST( TERTIARY );
+ COLLATOR_EXPOSE_CLASS_CONST( DEFAULT_STRENGTH );
+ COLLATOR_EXPOSE_CLASS_CONST( QUATERNARY );
+ COLLATOR_EXPOSE_CLASS_CONST( IDENTICAL );
+
+ COLLATOR_EXPOSE_CLASS_CONST( OFF );
+ COLLATOR_EXPOSE_CLASS_CONST( ON );
+
+ COLLATOR_EXPOSE_CLASS_CONST( SHIFTED );
+ COLLATOR_EXPOSE_CLASS_CONST( NON_IGNORABLE );
+
+ COLLATOR_EXPOSE_CLASS_CONST( LOWER_FIRST );
+ COLLATOR_EXPOSE_CLASS_CONST( UPPER_FIRST );
+
+ // UColAttribute constants
+ COLLATOR_EXPOSE_CLASS_CONST( FRENCH_COLLATION );
+ COLLATOR_EXPOSE_CLASS_CONST( ALTERNATE_HANDLING );
+ COLLATOR_EXPOSE_CLASS_CONST( CASE_FIRST );
+ COLLATOR_EXPOSE_CLASS_CONST( CASE_LEVEL );
+ COLLATOR_EXPOSE_CLASS_CONST( NORMALIZATION_MODE );
+ COLLATOR_EXPOSE_CLASS_CONST( STRENGTH );
+ COLLATOR_EXPOSE_CLASS_CONST( HIRAGANA_QUATERNARY_MODE );
+ COLLATOR_EXPOSE_CLASS_CONST( NUMERIC_COLLATION );
+
+ // ULocDataLocaleType constants
+ COLLATOR_EXPOSE_CONST( ULOC_ACTUAL_LOCALE );
+ COLLATOR_EXPOSE_CONST( ULOC_VALID_LOCALE );
+
+ // sort flags
+ COLLATOR_EXPOSE_CUSTOM_CLASS_CONST( "SORT_REGULAR", COLLATOR_SORT_REGULAR );
+ COLLATOR_EXPOSE_CUSTOM_CLASS_CONST( "SORT_STRING", COLLATOR_SORT_STRING );
+ COLLATOR_EXPOSE_CUSTOM_CLASS_CONST( "SORT_NUMERIC", COLLATOR_SORT_NUMERIC );
+
+ #undef COLLATOR_EXPOSE_CUSTOM_CLASS_CONST
+ #undef COLLATOR_EXPOSE_CLASS_CONST
+ #undef COLLATOR_EXPOSE_CONST
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/collator/collator.h b/ext/intl/collator/collator.h
new file mode 100755
index 0000000000..96e7aa097b
--- /dev/null
+++ b/ext/intl/collator/collator.h
@@ -0,0 +1,29 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef COLLATOR_COLLATOR_H
+#define CCOLLATOR_COLLATOR_H
+
+#include <php.h>
+
+#define COLLATOR_SORT_REGULAR 0
+#define COLLATOR_SORT_STRING 1
+#define COLLATOR_SORT_NUMERIC 2
+
+void collator_register_constants( INIT_FUNC_ARGS );
+
+#endif // COLLATOR_COLLATOR_H
diff --git a/ext/intl/collator/collator_attr.c b/ext/intl/collator/collator_attr.c
new file mode 100755
index 0000000000..b4fe0a4e14
--- /dev/null
+++ b/ext/intl/collator/collator_attr.c
@@ -0,0 +1,157 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php_intl.h"
+#include "collator_class.h"
+#include "collator_convert.h"
+#include "collator_attr.h"
+
+#include <unicode/ustring.h>
+
+/* {{{ proto int Collator::getAttribute( int $attr )
+ * Get collation attribute value. }}} */
+/* {{{ proto int collator_get_attribute( Collator $coll, int $attr )
+ * Get collation attribute value.
+ */
+PHP_FUNCTION( collator_get_attribute )
+{
+ long attribute, value;
+
+ COLLATOR_METHOD_INIT_VARS
+
+ // Parse parameters.
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol",
+ &object, Collator_ce_ptr, &attribute ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "collator_get_attribute: unable to parse input params", 0 TSRMLS_CC );
+
+ RETURN_FALSE;
+ }
+
+ // Fetch the object.
+ COLLATOR_METHOD_FETCH_OBJECT;
+
+ value = ucol_getAttribute( co->ucoll, attribute, COLLATOR_ERROR_CODE_P( co ) );
+ COLLATOR_CHECK_STATUS( co, "Error getting attribute value" );
+
+ RETURN_LONG( value );
+}
+/* }}} */
+
+/* {{{ proto bool Collator::getAttribute( int $attr )
+ * Get collation attribute value. }}} */
+/* {{{ proto bool collator_set_attribute( Collator $coll, int $attr, int $val )
+ * Set collation attribute.
+ */
+PHP_FUNCTION( collator_set_attribute )
+{
+ long attribute, value;
+ COLLATOR_METHOD_INIT_VARS
+
+
+ // Parse parameters.
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll",
+ &object, Collator_ce_ptr, &attribute, &value ) == FAILURE)
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "collator_set_attribute: unable to parse input params", 0 TSRMLS_CC );
+
+ RETURN_FALSE;
+ }
+
+ // Fetch the object.
+ COLLATOR_METHOD_FETCH_OBJECT;
+
+ // Set new value for the given attribute.
+ ucol_setAttribute( co->ucoll, attribute, value, COLLATOR_ERROR_CODE_P( co ) );
+ COLLATOR_CHECK_STATUS( co, "Error setting attribute value" );
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int Collator::getStrength()
+ * Returns the current collation strength. }}} */
+/* {{{ proto int collator_get_strength(Collator coll)
+ * Returns the current collation strength.
+ */
+PHP_FUNCTION( collator_get_strength )
+{
+ COLLATOR_METHOD_INIT_VARS
+
+ // Parse parameters.
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
+ &object, Collator_ce_ptr ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "collator_get_strength: unable to parse input params", 0 TSRMLS_CC );
+
+ RETURN_FALSE;
+ }
+
+ // Fetch the object.
+ COLLATOR_METHOD_FETCH_OBJECT;
+
+ // Get current strength and return it.
+ RETURN_LONG( ucol_getStrength( co->ucoll ) );
+}
+/* }}} */
+
+/* {{{ proto bool Collator::setStrength(int strength)
+ * Set the collation strength. }}} */
+/* {{{ proto bool collator_set_strength(Collator coll, int strength)
+ * Set the collation strength.
+ */
+PHP_FUNCTION( collator_set_strength )
+{
+ long strength;
+
+ COLLATOR_METHOD_INIT_VARS
+
+ // Parse parameters.
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol",
+ &object, Collator_ce_ptr, &strength ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "collator_set_strength: unable to parse input params", 0 TSRMLS_CC );
+
+ RETURN_FALSE;
+ }
+
+ // Fetch the object.
+ COLLATOR_METHOD_FETCH_OBJECT;
+
+ // Set given strength.
+ ucol_setStrength( co->ucoll, strength );
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/collator/collator_attr.h b/ext/intl/collator/collator_attr.h
new file mode 100755
index 0000000000..85636cc486
--- /dev/null
+++ b/ext/intl/collator/collator_attr.h
@@ -0,0 +1,28 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef COLLATOR_ATTR_H
+#define CCOLLATOR_ATTR_H
+
+#include <php.h>
+
+PHP_FUNCTION( collator_get_attribute );
+PHP_FUNCTION( collator_set_attribute );
+PHP_FUNCTION( collator_get_strength );
+PHP_FUNCTION( collator_set_strength );
+
+#endif // COLLATOR_ATTR_H
diff --git a/ext/intl/collator/collator_class.c b/ext/intl/collator/collator_class.c
new file mode 100755
index 0000000000..1d75f71f64
--- /dev/null
+++ b/ext/intl/collator/collator_class.c
@@ -0,0 +1,197 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#include "collator_class.h"
+#include "php_intl.h"
+#include "collator_attr.h"
+#include "collator_compare.h"
+#include "collator_sort.h"
+#include "collator_convert.h"
+#include "collator_locale.h"
+#include "collator_create.h"
+#include "collator_error.h"
+#include "intl_error.h"
+
+#include <unicode/ucol.h>
+
+zend_class_entry *Collator_ce_ptr = NULL;
+
+/////////////////////////////////////////////////////////////////////////////
+// Auxiliary functions needed by objects of 'Collator' class
+/////////////////////////////////////////////////////////////////////////////
+
+/* {{{ Collator_objects_dtor */
+static void Collator_objects_dtor(
+ void *object,
+ zend_object_handle handle TSRMLS_DC )
+{
+ zend_objects_destroy_object( object, handle TSRMLS_CC );
+}
+/* }}} */
+
+/* {{{ Collator_objects_free */
+void Collator_objects_free( zend_object *object TSRMLS_DC )
+{
+ Collator_object* co = (Collator_object*)object;
+
+ zend_object_std_dtor( &co->zo TSRMLS_CC );
+
+ collator_object_destroy( co TSRMLS_CC );
+
+ efree( co );
+}
+/* }}} */
+
+/* {{{ Collator_object_create */
+zend_object_value Collator_object_create(
+ zend_class_entry *ce TSRMLS_DC )
+{
+ zend_object_value retval;
+ Collator_object* intern;
+
+ intern = ecalloc( 1, sizeof(Collator_object) );
+ intl_error_init( COLLATOR_ERROR_P( intern ) TSRMLS_CC );
+ zend_object_std_init( &intern->zo, ce TSRMLS_CC );
+
+ retval.handle = zend_objects_store_put(
+ intern,
+ Collator_objects_dtor,
+ (zend_objects_free_object_storage_t)Collator_objects_free,
+ NULL TSRMLS_CC );
+
+ retval.handlers = zend_get_std_object_handlers();
+
+ return retval;
+}
+/* }}} */
+
+/////////////////////////////////////////////////////////////////////////////
+// 'Collator' class registration structures & functions
+/////////////////////////////////////////////////////////////////////////////
+
+/* {{{ Collator methods arguments info */
+// NOTE: modifying 'collator_XX_args' do not forget to
+// modify approptiate 'collator_XX_args' for
+// the procedural API.
+
+static
+ZEND_BEGIN_ARG_INFO_EX( collator_0_args, 0, 0, 0 )
+ZEND_END_ARG_INFO()
+
+static
+ZEND_BEGIN_ARG_INFO_EX( collator_1_arg, 0, 0, 1 )
+ ZEND_ARG_INFO( 0, arg1 )
+ZEND_END_ARG_INFO()
+
+static
+ZEND_BEGIN_ARG_INFO_EX( collator_2_args, 0, 0, 2 )
+ ZEND_ARG_INFO( 0, arg1 )
+ ZEND_ARG_INFO( 0, arg2 )
+ZEND_END_ARG_INFO()
+
+static
+ZEND_BEGIN_ARG_INFO_EX( collator_sort_args, 0, 0, 1 )
+ ZEND_ARG_ARRAY_INFO( 1, arr, 0 )
+ ZEND_ARG_INFO( 0, flags )
+ZEND_END_ARG_INFO()
+
+/* }}} */
+
+/* {{{ Collator_class_functions
+ * Every 'Collator' class method has an entry in this table
+ */
+
+function_entry Collator_class_functions[] = {
+ PHP_ME( Collator, __construct, collator_1_arg, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR )
+ ZEND_FENTRY( create, ZEND_FN( collator_create ), collator_1_arg, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
+ PHP_NAMED_FE( compare, ZEND_FN( collator_compare ), collator_2_args )
+ PHP_NAMED_FE( sort, ZEND_FN( collator_sort ), collator_sort_args )
+ PHP_NAMED_FE( sortWithSortKeys, ZEND_FN( collator_sort_with_sort_keys ), collator_sort_args )
+ PHP_NAMED_FE( asort, ZEND_FN( collator_asort ), collator_sort_args )
+ PHP_NAMED_FE( getAttribute, ZEND_FN( collator_get_attribute ), collator_1_arg )
+ PHP_NAMED_FE( setAttribute, ZEND_FN( collator_set_attribute ), collator_2_args )
+ PHP_NAMED_FE( getStrength, ZEND_FN( collator_get_strength ), collator_0_args )
+ PHP_NAMED_FE( setStrength, ZEND_FN( collator_set_strength ), collator_1_arg )
+ PHP_NAMED_FE( getLocale, ZEND_FN( collator_get_locale ), collator_1_arg )
+ PHP_NAMED_FE( getErrorCode, ZEND_FN( collator_get_error_code ), collator_0_args )
+ PHP_NAMED_FE( getErrorMessage, ZEND_FN( collator_get_error_message ), collator_0_args )
+ { NULL, NULL, NULL }
+};
+/* }}} */
+
+/* {{{ collator_register_Collator_class
+ * Initialize 'Collator' class
+ */
+void collator_register_Collator_class( TSRMLS_D )
+{
+ zend_class_entry ce;
+
+ // Create and register 'Collator' class.
+ INIT_CLASS_ENTRY( ce, "Collator", Collator_class_functions );
+ ce.create_object = Collator_object_create;
+ Collator_ce_ptr = zend_register_internal_class( &ce TSRMLS_CC );
+
+ // Declare 'Collator' class properties.
+ if( !Collator_ce_ptr )
+ {
+ zend_error( E_ERROR,
+ "Collator: attempt to create properties "
+ "on a non-registered class." );
+ return;
+ }
+}
+/* }}} */
+
+/* {{{ void collator_object_init( Collator_object* co )
+ * Initialize internals of Collator_object.
+ * Must be called before any other call to 'collator_object_...' functions.
+ */
+void collator_object_init( Collator_object* co TSRMLS_DC )
+{
+ if( !co )
+ return;
+
+ intl_error_init( COLLATOR_ERROR_P( co ) TSRMLS_CC );
+}
+/* }}} */
+
+/* {{{ void collator_object_destroy( Collator_object* co )
+ * Clean up mem allocted by internals of Collator_object
+ */
+void collator_object_destroy( Collator_object* co TSRMLS_DC )
+{
+ if( !co )
+ return;
+
+ if( co->ucoll )
+ {
+ ucol_close( co->ucoll );
+ co->ucoll = NULL;
+ }
+
+ intl_error_reset( COLLATOR_ERROR_P( co ) TSRMLS_CC );
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/collator/collator_class.h b/ext/intl/collator/collator_class.h
new file mode 100755
index 0000000000..8d4c9d97f4
--- /dev/null
+++ b/ext/intl/collator/collator_class.h
@@ -0,0 +1,71 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef COLLATOR_CLASS_H
+#define COLLATOR_CLASS_H
+
+#include <php.h>
+
+#include "intl_common.h"
+#include "intl_error.h"
+
+#include <unicode/ucol.h>
+
+typedef struct {
+ zend_object zo;
+
+ // ICU collator
+ UCollator* ucoll;
+
+ // error handling
+ intl_error err;
+
+} Collator_object;
+
+#define COLLATOR_ERROR(co) (co)->err
+#define COLLATOR_ERROR_P(co) &(COLLATOR_ERROR(co))
+
+#define COLLATOR_ERROR_CODE(co) INTL_ERROR_CODE(COLLATOR_ERROR(co))
+#define COLLATOR_ERROR_CODE_P(co) &(INTL_ERROR_CODE(COLLATOR_ERROR(co)))
+
+void collator_register_Collator_class( TSRMLS_D );
+void collator_object_init( Collator_object* co TSRMLS_DC );
+void collator_object_destroy( Collator_object* co TSRMLS_DC );
+
+extern zend_class_entry *Collator_ce_ptr;
+
+/* Auxiliary macros */
+
+#define COLLATOR_METHOD_INIT_VARS \
+ zval* object = NULL; \
+ Collator_object* co = NULL; \
+ intl_error_reset( NULL TSRMLS_CC ); \
+
+#define COLLATOR_METHOD_FETCH_OBJECT \
+ co = (Collator_object *) zend_object_store_get_object( object TSRMLS_CC ); \
+ intl_error_reset( COLLATOR_ERROR_P( co ) TSRMLS_CC ); \
+
+// Macro to check return value of a ucol_* function call.
+#define COLLATOR_CHECK_STATUS( co, msg ) \
+ intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) TSRMLS_CC ); \
+ if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) \
+ { \
+ intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), msg, 0 TSRMLS_CC ); \
+ RETURN_FALSE; \
+ } \
+
+#endif // #ifndef COLLATOR_CLASS_H
diff --git a/ext/intl/collator/collator_compare.c b/ext/intl/collator/collator_compare.c
new file mode 100755
index 0000000000..e6029e7920
--- /dev/null
+++ b/ext/intl/collator/collator_compare.c
@@ -0,0 +1,119 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php_intl.h"
+#include "collator_class.h"
+#include "collator_compare.h"
+#include "intl_convert.h"
+
+/* {{{ proto int Collator::compare( string $str1, string $str2 )
+ * Compare two strings. }}} */
+/* {{{ proto int collator_compare( Collator $coll, string $str1, string $str2 )
+ * Compare two strings.
+ */
+PHP_FUNCTION( collator_compare )
+{
+ char* str1 = NULL;
+ char* str2 = NULL;
+ int str1_len = 0;
+ int str2_len = 0;
+
+ UChar* ustr1 = NULL;
+ UChar* ustr2 = NULL;
+ int ustr1_len = 0;
+ int ustr2_len = 0;
+
+ UCollationResult result;
+
+ COLLATOR_METHOD_INIT_VARS
+
+ // Parse parameters.
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oss",
+ &object, Collator_ce_ptr, &str1, &str1_len, &str2, &str2_len ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "collator_compare: unable to parse input params", 0 TSRMLS_CC );
+
+ RETURN_FALSE;
+ }
+
+ // Fetch the object.
+ COLLATOR_METHOD_FETCH_OBJECT;
+
+
+ /*
+ * Compare given strings (converting them to UTF-16 first).
+ */
+
+ // First convert the strings to UTF-16.
+ intl_convert_utf8_to_utf16(
+ &ustr1, &ustr1_len, str1, str1_len, COLLATOR_ERROR_CODE_P( co ) );
+ if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) )
+ {
+ // Set global error code.
+ intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) TSRMLS_CC );
+
+ // Set error messages.
+ intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ),
+ "Error converting first argument to UTF-16", 0 TSRMLS_CC );
+ efree( ustr1 );
+ RETURN_FALSE;
+ }
+
+ intl_convert_utf8_to_utf16(
+ &ustr2, &ustr2_len, str2, str2_len, COLLATOR_ERROR_CODE_P( co ) );
+ if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) )
+ {
+ // Set global error code.
+ intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) TSRMLS_CC );
+
+ // Set error messages.
+ intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ),
+ "Error converting second argument to UTF-16", 0 TSRMLS_CC );
+ efree( ustr1 );
+ efree( ustr2 );
+ RETURN_FALSE;
+ }
+
+ // Then compare them.
+ result = ucol_strcoll(
+ co->ucoll,
+ ustr1, ustr1_len,
+ ustr2, ustr2_len );
+
+ if( ustr1 )
+ efree( ustr1 );
+ if( ustr2 )
+ efree( ustr2 );
+
+ // Return result of the comparison.
+ RETURN_LONG( result );
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/collator/collator_compare.h b/ext/intl/collator/collator_compare.h
new file mode 100755
index 0000000000..4e38b79309
--- /dev/null
+++ b/ext/intl/collator/collator_compare.h
@@ -0,0 +1,25 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef COLLATOR_COMPARE_H
+#define COLLATOR_COMPARE_H
+
+#include <php.h>
+
+PHP_FUNCTION( collator_compare );
+
+#endif // COLLATOR_COMPARE_H
diff --git a/ext/intl/collator/collator_convert.c b/ext/intl/collator/collator_convert.c
new file mode 100755
index 0000000000..7bb48ebb4b
--- /dev/null
+++ b/ext/intl/collator/collator_convert.c
@@ -0,0 +1,482 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php_intl.h"
+#include "collator_class.h"
+#include "collator_is_numeric.h"
+#include "collator_convert.h"
+#include "intl_convert.h"
+
+#include <unicode/ustring.h>
+#include <php.h>
+
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION <= 1)
+#define CAST_OBJECT_SHOULD_FREE ,0
+#else
+#define CAST_OBJECT_SHOULD_FREE
+#endif
+
+#define COLLATOR_CONVERT_RETURN_FAILED(retval) { \
+ zval_add_ref( &retval ); \
+ return retval; \
+ }
+
+/* {{{ collator_convert_hash_item_from_utf8_to_utf16 */
+static void collator_convert_hash_item_from_utf8_to_utf16(
+ HashTable* hash, int hashKeyType, char* hashKey, ulong hashIndex,
+ UErrorCode* status )
+{
+ const char* old_val;
+ int old_val_len;
+ UChar* new_val = NULL;
+ int new_val_len = 0;
+ zval** hashData = NULL;
+ zval* znew_val = NULL;
+
+ // Get current hash item.
+ zend_hash_get_current_data( hash, (void**) &hashData );
+
+ // Process string values only.
+ if( Z_TYPE_P( *hashData ) != IS_STRING )
+ return;
+
+ old_val = Z_STRVAL_P( *hashData );
+ old_val_len = Z_STRLEN_P( *hashData );
+
+ // Convert it from UTF-8 to UTF-16LE and save the result to new_val[_len].
+ intl_convert_utf8_to_utf16( &new_val, &new_val_len, old_val, old_val_len, status );
+ if( U_FAILURE( *status ) )
+ return;
+
+ // Update current hash item with the converted value.
+ MAKE_STD_ZVAL( znew_val );
+ ZVAL_STRINGL( znew_val, (char*)new_val, UBYTES(new_val_len), FALSE );
+
+ if( hashKeyType == HASH_KEY_IS_STRING )
+ {
+ zend_hash_update( hash, hashKey, strlen( hashKey ) + 1,
+ (void*) &znew_val, sizeof(zval*), NULL );
+ }
+ else // hashKeyType == HASH_KEY_IS_LONG
+ {
+ zend_hash_index_update( hash, hashIndex,
+ (void*) &znew_val, sizeof(zval*), NULL );
+ }
+}
+/* }}} */
+
+/* {{{ collator_convert_hash_item_from_utf16_to_utf8 */
+static void collator_convert_hash_item_from_utf16_to_utf8(
+ HashTable* hash, int hashKeyType, char* hashKey, ulong hashIndex,
+ UErrorCode* status )
+{
+ const char* old_val;
+ int old_val_len;
+ char* new_val = NULL;
+ int new_val_len = 0;
+ zval** hashData = NULL;
+ zval* znew_val = NULL;
+
+ // Get current hash item.
+ zend_hash_get_current_data( hash, (void**) &hashData );
+
+ // Process string values only.
+ if( Z_TYPE_P( *hashData ) != IS_STRING )
+ return;
+
+ old_val = Z_STRVAL_P( *hashData );
+ old_val_len = Z_STRLEN_P( *hashData );
+
+ // Convert it from UTF-16LE to UTF-8 and save the result to new_val[_len].
+ intl_convert_utf16_to_utf8( &new_val, &new_val_len,
+ (UChar*)old_val, UCHARS(old_val_len), status );
+ if( U_FAILURE( *status ) )
+ return;
+
+ // Update current hash item with the converted value.
+ MAKE_STD_ZVAL( znew_val );
+ ZVAL_STRINGL( znew_val, (char*)new_val, new_val_len, FALSE );
+
+ if( hashKeyType == HASH_KEY_IS_STRING )
+ {
+ zend_hash_update( hash, hashKey, strlen( hashKey ) + 1,
+ (void*) &znew_val, sizeof(zval*), NULL );
+ }
+ else // hashKeyType == HASH_KEY_IS_LONG
+ {
+ zend_hash_index_update( hash, hashIndex,
+ (void*) &znew_val, sizeof(zval*), NULL );
+ }
+}
+/* }}} */
+
+/* {{{ collator_convert_hash_from_utf8_to_utf16
+ * Convert values of the given hash from UTF-8 encoding to UTF-16LE.
+ */
+void collator_convert_hash_from_utf8_to_utf16( HashTable* hash, UErrorCode* status )
+{
+ ulong hashIndex = 0;
+ char* hashKey = NULL;
+ int hashKeyType = 0;
+
+ zend_hash_internal_pointer_reset( hash );
+ while( ( hashKeyType = zend_hash_get_current_key( hash, &hashKey, &hashIndex, 0 ) )
+ != HASH_KEY_NON_EXISTANT )
+ {
+ // Convert current hash item from UTF-8 to UTF-16LE.
+ collator_convert_hash_item_from_utf8_to_utf16(
+ hash, hashKeyType, hashKey, hashIndex, status );
+ if( U_FAILURE( *status ) )
+ return;
+
+ // Proceed to the next item.
+ zend_hash_move_forward( hash );
+ }
+}
+/* }}} */
+
+/* {{{ collator_convert_hash_from_utf16_to_utf8
+ * Convert values of the given hash from UTF-16LE encoding to UTF-8.
+ */
+void collator_convert_hash_from_utf16_to_utf8( HashTable* hash, UErrorCode* status )
+{
+ ulong hashIndex = 0;
+ char* hashKey = NULL;
+ int hashKeyType = 0;
+
+ zend_hash_internal_pointer_reset( hash );
+ while( ( hashKeyType = zend_hash_get_current_key( hash, &hashKey, &hashIndex, 0 ) )
+ != HASH_KEY_NON_EXISTANT )
+ {
+ // Convert current hash item from UTF-16LE to UTF-8.
+ collator_convert_hash_item_from_utf16_to_utf8(
+ hash, hashKeyType, hashKey, hashIndex, status );
+ if( U_FAILURE( *status ) )
+ return;
+
+ // Proceed to the next item.
+ zend_hash_move_forward( hash );
+ }
+}
+/* }}} */
+
+/* {{{ collator_convert_zstr_utf16_to_utf8
+ *
+ * Convert string from utf16 to utf8.
+ *
+ * @param zval* utf16_zval String to convert.
+ *
+ * @return zval* Converted string.
+ */
+zval* collator_convert_zstr_utf16_to_utf8( zval* utf16_zval )
+{
+ zval* utf8_zval = NULL;
+ char* str = NULL;
+ int str_len = 0;
+ UErrorCode status = U_ZERO_ERROR;
+
+ // Convert to utf8 then.
+ intl_convert_utf16_to_utf8( &str, &str_len,
+ (UChar*) Z_STRVAL_P(utf16_zval), UCHARS( Z_STRLEN_P(utf16_zval) ), &status );
+ if( U_FAILURE( status ) )
+ php_error( E_WARNING, "Error converting utf16 to utf8 in collator_convert_zval_utf16_to_utf8()" );
+
+ ALLOC_INIT_ZVAL( utf8_zval );
+ ZVAL_STRINGL( utf8_zval, str, str_len, FALSE );
+
+ return utf8_zval;
+}
+/* }}} */
+
+/* {{{ collator_convert_zstr_utf8_to_utf16
+ *
+ * Convert string from utf8 to utf16.
+ *
+ * @param zval* utf8_zval String to convert.
+ *
+ * @return zval* Converted string.
+ */
+zval* collator_convert_zstr_utf8_to_utf16( zval* utf8_zval )
+{
+ zval* zstr = NULL;
+ UChar* ustr = NULL;
+ int ustr_len = 0;
+ UErrorCode status = U_ZERO_ERROR;
+
+ // Convert the string to UTF-16.
+ intl_convert_utf8_to_utf16(
+ &ustr, &ustr_len,
+ Z_STRVAL_P( utf8_zval ), Z_STRLEN_P( utf8_zval ),
+ &status );
+ if( U_FAILURE( status ) )
+ php_error( E_WARNING, "Error casting object to string in collator_convert_zstr_utf8_to_utf16()" );
+
+ // Set string.
+ ALLOC_INIT_ZVAL( zstr );
+ ZVAL_STRINGL( zstr, (char*)ustr, UBYTES(ustr_len), FALSE );
+
+ return zstr;
+}
+/* }}} */
+
+/* {{{ collator_convert_object_to_string
+ * Convert object to UTF16-encoded string.
+ */
+zval* collator_convert_object_to_string( zval* obj TSRMLS_DC )
+{
+ zval* zstr = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar* ustr = NULL;
+ int ustr_len = 0;
+
+ // Bail out if it's not an object.
+ if( Z_TYPE_P( obj ) != IS_OBJECT )
+ {
+ COLLATOR_CONVERT_RETURN_FAILED( obj );
+ }
+
+ // Try object's handlers.
+ if( Z_OBJ_HT_P(obj)->get )
+ {
+ zstr = Z_OBJ_HT_P(obj)->get( obj TSRMLS_CC );
+
+ switch( Z_TYPE_P( zstr ) )
+ {
+ case IS_OBJECT:
+ {
+ // Bail out.
+ zval_ptr_dtor( &zstr );
+ COLLATOR_CONVERT_RETURN_FAILED( obj );
+ } break;
+
+ case IS_STRING:
+ break;
+
+ default:
+ {
+ convert_to_string( zstr );
+ } break;
+ }
+ }
+ else if( Z_OBJ_HT_P(obj)->cast_object )
+ {
+ ALLOC_INIT_ZVAL( zstr );
+
+ if( Z_OBJ_HT_P(obj)->cast_object( obj, zstr, IS_STRING CAST_OBJECT_SHOULD_FREE TSRMLS_CC ) == FAILURE )
+ {
+ // cast_object failed => bail out.
+ zval_ptr_dtor( &zstr );
+ COLLATOR_CONVERT_RETURN_FAILED( obj );
+ }
+ }
+
+ // Object wasn't successfuly converted => bail out.
+ if( zstr == NULL )
+ {
+ COLLATOR_CONVERT_RETURN_FAILED( obj );
+ }
+
+ // Convert the string to UTF-16.
+ intl_convert_utf8_to_utf16(
+ &ustr, &ustr_len,
+ Z_STRVAL_P( zstr ), Z_STRLEN_P( zstr ),
+ &status );
+ if( U_FAILURE( status ) )
+ php_error( E_WARNING, "Error casting object to string in collator_convert_object_to_string()" );
+
+ // Cleanup zstr to hold utf16 string.
+ zval_dtor( zstr );
+
+ // Set string.
+ ZVAL_STRINGL( zstr, (char*)ustr, UBYTES(ustr_len), FALSE );
+
+ // Don't free ustr cause it's set in zstr without copy.
+ // efree( ustr );
+
+ return zstr;
+}
+/* }}} */
+
+/* {{{ collator_convert_string_to_number
+ *
+ * Convert string to number.
+ *
+ * @param zval* str String to convert.
+ *
+ * @return zval* Number. If str is not numeric string return number zero.
+ */
+zval* collator_convert_string_to_number( zval* str )
+{
+ zval* num = collator_convert_string_to_number_if_possible( str );
+ if( num == str )
+ {
+ // String wasn't converted => return zero.
+ zval_ptr_dtor( &num );
+
+ ALLOC_INIT_ZVAL( num );
+ ZVAL_LONG( num, 0 );
+ }
+
+ return num;
+}
+/* }}} */
+
+/* {{{ collator_convert_string_to_double
+ *
+ * Convert string to double.
+ *
+ * @param zval* str String to convert.
+ *
+ * @return zval* Number. If str is not numeric string return number zero.
+ */
+zval* collator_convert_string_to_double( zval* str )
+{
+ zval* num = collator_convert_string_to_number( str );
+ if( Z_TYPE_P(num) == IS_LONG )
+ {
+ ZVAL_DOUBLE( num, Z_LVAL_P( num ) );
+ }
+
+ return num;
+}
+/* }}} */
+
+/* {{{ collator_convert_string_to_number_if_possible
+ *
+ * Convert string to numer.
+ *
+ * @param zval* str String to convert.
+ *
+ * @return zval* Number if str is numeric string. Otherwise
+ * original str param.
+ */
+zval* collator_convert_string_to_number_if_possible( zval* str )
+{
+ zval* num = NULL;
+ int is_numeric = 0;
+ long lval = 0;
+ double dval = 0;
+
+ if( Z_TYPE_P( str ) != IS_STRING )
+ {
+ COLLATOR_CONVERT_RETURN_FAILED( str );
+ }
+
+ if( ( is_numeric = collator_is_numeric( (UChar*) Z_STRVAL_P(str), UCHARS( Z_STRLEN_P(str) ), &lval, &dval, 1 ) ) )
+ {
+ ALLOC_INIT_ZVAL( num );
+
+ if( is_numeric == IS_LONG )
+ Z_LVAL_P(num) = lval;
+ if( is_numeric == IS_DOUBLE )
+ Z_DVAL_P(num) = dval;
+
+ Z_TYPE_P(num) = is_numeric;
+ }
+ else
+ {
+ COLLATOR_CONVERT_RETURN_FAILED( str );
+ }
+
+ return num;
+}
+/* }}} */
+
+/* {{{ collator_make_printable_zval
+ *
+ * Returns string from input zval.
+ *
+ * @param zval* arg zval to get string from
+ *
+ * @return zval* UTF16 string.
+ */
+zval* collator_make_printable_zval( zval* arg )
+{
+ zval arg_copy;
+ int use_copy = 0;
+ zval* str = NULL;
+
+ if( Z_TYPE_P(arg) != IS_STRING )
+ {
+ zend_make_printable_zval(arg, &arg_copy, &use_copy);
+
+ if( use_copy )
+ {
+ str = collator_convert_zstr_utf8_to_utf16( &arg_copy );
+ zval_dtor( &arg_copy );
+ }
+ else
+ {
+ str = collator_convert_zstr_utf8_to_utf16( arg );
+ }
+ }
+ else
+ {
+ COLLATOR_CONVERT_RETURN_FAILED( arg );
+ }
+
+ return str;
+}
+/* }}} */
+
+/* {{{ collator_normalize_sort_argument
+ *
+ * Normalize argument to use in sort's compare function.
+ *
+ * @param zval* arg Sort's argument to normalize.
+ *
+ * @return zval* Normalized copy of arg or unmodified arg
+ * if normalization is not needed.
+ */
+zval* collator_normalize_sort_argument( zval* arg )
+{
+ zval* n_arg = NULL;
+
+ if( Z_TYPE_P( arg ) != IS_STRING )
+ {
+ // If its not a string then nothing to do.
+ // Return original arg.
+ COLLATOR_CONVERT_RETURN_FAILED( arg );
+ }
+
+ // Try convert to number.
+ n_arg = collator_convert_string_to_number_if_possible( arg );
+
+ if( n_arg == arg )
+ {
+ // Conversion to number failed.
+ zval_ptr_dtor( &n_arg );
+
+ // Convert string to utf8.
+ n_arg = collator_convert_zstr_utf16_to_utf8( arg );
+ }
+
+ return n_arg;
+}
+/* }}} */
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/collator/collator_convert.h b/ext/intl/collator/collator_convert.h
new file mode 100755
index 0000000000..8322ea998b
--- /dev/null
+++ b/ext/intl/collator/collator_convert.h
@@ -0,0 +1,38 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef COLLATOR_CONVERT_H
+#define COLLATOR_CONVERT_H
+
+#include <php.h>
+#include <unicode/utypes.h>
+
+void collator_convert_hash_from_utf8_to_utf16( HashTable* hash, UErrorCode* status );
+void collator_convert_hash_from_utf16_to_utf8( HashTable* hash, UErrorCode* status );
+
+zval* collator_convert_zstr_utf16_to_utf8( zval* utf16_zval );
+zval* collator_convert_zstr_utf8_to_utf16( zval* utf8_zval );
+
+zval* collator_normalize_sort_argument( zval* arg );
+zval* collator_convert_object_to_string( zval* obj TSRMLS_DC );
+zval* collator_convert_string_to_number( zval* arg );
+zval* collator_convert_string_to_number_if_possible( zval* str );
+zval* collator_convert_string_to_double( zval* str );
+
+zval* collator_make_printable_zval( zval* arg );
+
+#endif // COLLATOR_CONVERT_H
diff --git a/ext/intl/collator/collator_create.c b/ext/intl/collator/collator_create.c
new file mode 100755
index 0000000000..6fbb3da8b3
--- /dev/null
+++ b/ext/intl/collator/collator_create.c
@@ -0,0 +1,135 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php_intl.h"
+#include "collator_class.h"
+#include "collator_create.h"
+#include "intl_data.h"
+
+/* {{{ proto Collator collator_create( string $locale )
+ * Create collator.
+ */
+PHP_FUNCTION( collator_create )
+{
+ char* locale;
+ int locale_len = 0;
+ zval* object;
+ Collator_object* co;
+
+ intl_error_reset( NULL TSRMLS_CC );
+
+ // Parse parameters.
+ if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s",
+ &locale, &locale_len ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "collator_create: unable to parse input params", 0 TSRMLS_CC );
+
+ RETURN_NULL();
+ }
+
+ INTL_CHECK_LOCALE_LEN(locale_len);
+ // Create a Collator object and save the ICU collator into it.
+ if( ( object = getThis() ) == NULL )
+ object = return_value;
+
+ if( Z_TYPE_P( object ) != IS_OBJECT )
+ object_init_ex( object, Collator_ce_ptr );
+
+ co = (Collator_object *) zend_object_store_get_object( object TSRMLS_CC );
+
+ intl_error_reset( COLLATOR_ERROR_P( co ) TSRMLS_CC );
+
+ if(locale_len == 0) {
+ locale = INTL_G(default_locale);
+ }
+
+ // Open ICU collator.
+ co->ucoll = ucol_open( locale, COLLATOR_ERROR_CODE_P( co ) );
+
+ if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) || co->ucoll == NULL )
+ {
+ intl_error_set( NULL, COLLATOR_ERROR_CODE( co ),
+ "collator_create: unable to open ICU collator", 0 TSRMLS_CC );
+
+ // Collator creation failed.
+ RETURN_NULL();
+ }
+}
+/* }}} */
+
+/* {{{ proto Collator Collator::__construct( string $locale )
+ * Collator object constructor.
+ */
+PHP_METHOD( Collator, __construct )
+{
+ char* locale = NULL;
+ int locale_len = 0;
+
+ COLLATOR_METHOD_INIT_VARS
+
+ object = getThis();
+ // Parse parameters.
+ if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s",
+ &locale, &locale_len ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "__construct: unable to parse input params", 0 TSRMLS_CC );
+
+ zval_dtor(object);
+ ZVAL_NULL(object);
+ RETURN_NULL();
+ }
+
+ INTL_CHECK_LOCALE_LEN_OBJ(locale_len, object);
+ /* Fetch the object. */
+ co = (Collator_object*) zend_object_store_get_object( object TSRMLS_CC );
+
+ intl_error_reset( COLLATOR_ERROR_P( co ) TSRMLS_CC );
+
+ if(locale_len == 0) {
+ locale = INTL_G(default_locale);
+ }
+
+ // Open ICU collator.
+ co->ucoll = ucol_open( locale, COLLATOR_ERROR_CODE_P( co ) );
+
+ if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) || co->ucoll == NULL )
+ {
+ intl_error_set( NULL, COLLATOR_ERROR_CODE( co ),
+ "__construct: unable to open ICU collator", 0 TSRMLS_CC );
+
+ zval_dtor(object);
+ ZVAL_NULL(object);
+ RETURN_NULL();
+ }
+
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/collator/collator_create.h b/ext/intl/collator/collator_create.h
new file mode 100755
index 0000000000..b740e82d68
--- /dev/null
+++ b/ext/intl/collator/collator_create.h
@@ -0,0 +1,27 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef COLLATOR_CREATE_H
+#define COLLATOR_CREATE_H
+
+#include <php.h>
+
+PHP_FUNCTION( collator_create );
+
+PHP_METHOD( Collator, __construct );
+
+#endif // COLLATOR_CREATE_H
diff --git a/ext/intl/collator/collator_error.c b/ext/intl/collator/collator_error.c
new file mode 100755
index 0000000000..55e366ccba
--- /dev/null
+++ b/ext/intl/collator/collator_error.c
@@ -0,0 +1,94 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php_intl.h"
+#include "collator_class.h"
+#include "collator_error.h"
+
+/* {{{ proto int Collator::getErrorCode( Collator $coll )
+ * Get collator's last error code. }}} */
+/* {{{ proto int collator_get_error_code( Collator $coll )
+ * Get collator's last error code.
+ */
+PHP_FUNCTION( collator_get_error_code )
+{
+ COLLATOR_METHOD_INIT_VARS
+
+ // Parse parameters.
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
+ &object, Collator_ce_ptr ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "collator_get_error_code: unable to parse input params", 0 TSRMLS_CC );
+
+ RETURN_FALSE;
+ }
+
+ // Fetch the object (without resetting its last error code).
+ co = (Collator_object *) zend_object_store_get_object(object TSRMLS_CC);
+ if( co == NULL )
+ RETURN_FALSE;
+
+ // Return collator's last error code.
+ RETURN_LONG( COLLATOR_ERROR_CODE( co ) );
+}
+/* }}} */
+
+/* {{{ proto string Collator::getErrorMessage( Collator $coll )
+ * Get text description for collator's last error code. }}} */
+/* {{{ proto string collator_get_error_message( Collator $coll )
+ * Get text description for collator's last error code.
+ */
+PHP_FUNCTION( collator_get_error_message )
+{
+ const char* message = NULL;
+
+ COLLATOR_METHOD_INIT_VARS
+
+ // Parse parameters.
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
+ &object, Collator_ce_ptr ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "collator_get_error_message: unable to parse input params", 0 TSRMLS_CC );
+
+ RETURN_FALSE;
+ }
+
+ // Fetch the object (without resetting its last error code).
+ co = (Collator_object *) zend_object_store_get_object( object TSRMLS_CC );
+ if( co == NULL )
+ RETURN_FALSE;
+
+ // Return last error message.
+ message = intl_error_get_message( COLLATOR_ERROR_P( co ) TSRMLS_CC );
+ RETURN_STRING( (char*)message, FALSE );
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/collator/collator_error.h b/ext/intl/collator/collator_error.h
new file mode 100755
index 0000000000..b2f44ea2a3
--- /dev/null
+++ b/ext/intl/collator/collator_error.h
@@ -0,0 +1,26 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef COLLATOR_ERROR_H
+#define COLLATOR_ERROR_H
+
+#include <php.h>
+
+PHP_FUNCTION( collator_get_error_code );
+PHP_FUNCTION( collator_get_error_message );
+
+#endif // COLLATOR_ERROR_H
diff --git a/ext/intl/collator/collator_is_numeric.c b/ext/intl/collator/collator_is_numeric.c
new file mode 100755
index 0000000000..a8abfac12b
--- /dev/null
+++ b/ext/intl/collator/collator_is_numeric.c
@@ -0,0 +1,305 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#include "collator_is_numeric.h"
+
+#if ZEND_MODULE_API_NO < 20071006
+/* not 5.3 */
+#ifndef ALLOCA_FLAG
+#define ALLOCA_FLAG(use_heap)
+#endif
+#define _do_alloca(x, y) do_alloca((x))
+#define _free_alloca(x, y) free_alloca((x))
+#else
+#define _do_alloca do_alloca
+#define _free_alloca free_alloca
+#endif
+/* {{{ collator_u_strtod
+ * Taken from PHP6:zend_u_strtod()
+ */
+static double collator_u_strtod(const UChar *nptr, UChar **endptr) /* {{{ */
+{
+ const UChar *u = nptr, *nstart;
+ UChar c = *u;
+ int any = 0;
+ ALLOCA_FLAG(use_heap);
+
+ while (u_isspace(c)) {
+ c = *++u;
+ }
+ nstart = u;
+
+ if (c == 0x2D /*'-'*/ || c == 0x2B /*'+'*/) {
+ c = *++u;
+ }
+
+ while (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) {
+ any = 1;
+ c = *++u;
+ }
+
+ if (c == 0x2E /*'.'*/) {
+ c = *++u;
+ while (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) {
+ any = 1;
+ c = *++u;
+ }
+ }
+
+ if ((c == 0x65 /*'e'*/ || c == 0x45 /*'E'*/) && any) {
+ const UChar *e = u;
+ int any_exp = 0;
+
+ c = *++u;
+ if (c == 0x2D /*'-'*/ || c == 0x2B /*'+'*/) {
+ c = *++u;
+ }
+
+ while (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) {
+ any_exp = 1;
+ c = *++u;
+ }
+
+ if (!any_exp) {
+ u = e;
+ }
+ }
+
+ if (any) {
+ char buf[64], *numbuf, *bufpos;
+ int length = u - nstart;
+ double value;
+
+ if (length < sizeof(buf)) {
+ numbuf = buf;
+ } else {
+ numbuf = (char *) _do_alloca(length + 1, use_heap);
+ }
+
+ bufpos = numbuf;
+
+ while (nstart < u) {
+ *bufpos++ = (char) *nstart++;
+ }
+
+ *bufpos = '\0';
+ value = zend_strtod(numbuf, NULL);
+
+ if (numbuf != buf) {
+ _free_alloca(numbuf, use_heap);
+ }
+
+ if (endptr != NULL) {
+ *endptr = (UChar *)u;
+ }
+
+ return value;
+ }
+
+ if (endptr != NULL) {
+ *endptr = (UChar *)nptr;
+ }
+
+ return 0;
+}
+/* }}} */
+
+/* {{{ collator_u_strtol
+ * Taken from PHP6:zend_u_strtol()
+ *
+ * Convert a Unicode string to a long integer.
+ *
+ * Ignores `locale' stuff.
+ */
+static long collator_u_strtol(nptr, endptr, base)
+ const UChar *nptr;
+ UChar **endptr;
+ register int base;
+{
+ register const UChar *s = nptr;
+ register unsigned long acc;
+ register UChar c;
+ register unsigned long cutoff;
+ register int neg = 0, any, cutlim;
+
+ if (s == NULL) {
+ errno = ERANGE;
+ if (endptr != NULL) {
+ *endptr = NULL;
+ }
+ return 0;
+ }
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ do {
+ c = *s++;
+ } while (u_isspace(c));
+ if (c == 0x2D /*'-'*/) {
+ neg = 1;
+ c = *s++;
+ } else if (c == 0x2B /*'+'*/)
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ (c == 0x30 /*'0'*/)
+ && (*s == 0x78 /*'x'*/ || *s == 0x58 /*'X'*/)) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = (c == 0x30 /*'0'*/) ? 8 : 10;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+ cutlim = cutoff % (unsigned long)base;
+ cutoff /= (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/)
+ c -= 0x30 /*'0'*/;
+ else if (c >= 0x41 /*'A'*/ && c <= 0x5A /*'Z'*/)
+ c -= 0x41 /*'A'*/ - 10;
+ else if (c >= 0x61 /*'a'*/ && c <= 0x7A /*'z'*/)
+ c -= 0x61 /*'a'*/ - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_MIN : LONG_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != NULL)
+ *endptr = (UChar *)(any ? s - 1 : nptr);
+ return (acc);
+}
+/* }}} */
+
+
+/* {{{ collator_is_numeric]
+ * Taken from PHP6:is_numeric_unicode()
+ */
+zend_uchar collator_is_numeric( UChar *str, int length, long *lval, double *dval, int allow_errors )
+{
+ long local_lval;
+ double local_dval;
+ UChar *end_ptr_long, *end_ptr_double;
+ int conv_base=10;
+
+ if (!length) {
+ return 0;
+ }
+
+ /* handle hex numbers */
+ if (length>=2 && str[0]=='0' && (str[1]=='x' || str[1]=='X')) {
+ conv_base=16;
+ }
+
+ errno=0;
+ local_lval = collator_u_strtol(str, &end_ptr_long, conv_base);
+ if (errno != ERANGE) {
+ if (end_ptr_long == str+length) { /* integer string */
+ if (lval) {
+ *lval = local_lval;
+ }
+ return IS_LONG;
+ } else if (end_ptr_long == str && *end_ptr_long != '\0' && *str != '.' && *str != '-') { /* ignore partial string matches */
+ return 0;
+ }
+ } else {
+ end_ptr_long = NULL;
+ }
+
+ if (conv_base == 16) { /* hex string, under UNIX strtod() messes it up */
+ /* UTODO: keep compatibility with is_numeric_string() here? */
+ return 0;
+ }
+
+ local_dval = collator_u_strtod(str, &end_ptr_double);
+ if (local_dval == 0 && end_ptr_double == str) {
+ end_ptr_double = NULL;
+ } else {
+ if (end_ptr_double == str+length) { /* floating point string */
+ if (!zend_finite(local_dval)) {
+ /* "inf","nan" and maybe other weird ones */
+ return 0;
+ }
+
+ if (dval) {
+ *dval = local_dval;
+ }
+ return IS_DOUBLE;
+ }
+ }
+
+ if (!allow_errors) {
+ return 0;
+ }
+ if (allow_errors == -1) {
+ zend_error(E_NOTICE, "A non well formed numeric value encountered");
+ }
+
+ if (allow_errors) {
+ if (end_ptr_double > end_ptr_long && dval) {
+ *dval = local_dval;
+ return IS_DOUBLE;
+ } else if (end_ptr_long && lval) {
+ *lval = local_lval;
+ return IS_LONG;
+ }
+ }
+ return 0;
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/collator/collator_is_numeric.h b/ext/intl/collator/collator_is_numeric.h
new file mode 100755
index 0000000000..585d58917a
--- /dev/null
+++ b/ext/intl/collator/collator_is_numeric.h
@@ -0,0 +1,26 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef COLLATOR_IS_NUMERIC_H
+#define COLLATOR_IS_NUMERIC_H
+
+#include <php.h>
+#include <unicode/uchar.h>
+
+zend_uchar collator_is_numeric( UChar *str, int length, long *lval, double *dval, int allow_errors );
+
+#endif // COLLATOR_IS_NUMERIC_H
diff --git a/ext/intl/collator/collator_locale.c b/ext/intl/collator/collator_locale.c
new file mode 100755
index 0000000000..838c50be80
--- /dev/null
+++ b/ext/intl/collator/collator_locale.c
@@ -0,0 +1,71 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php_intl.h"
+#include "collator_class.h"
+#include "collator_locale.h"
+#include "intl_convert.h"
+
+#include <zend_API.h>
+
+/* {{{ proto string Collator::getLocale( int $type )
+ * Gets the locale name of the collator. }}} */
+/* {{{ proto string collator_get_locale( Collator $coll, int $type )
+ * Gets the locale name of the collator.
+ */
+PHP_FUNCTION( collator_get_locale )
+{
+ int type = 0;
+ char* locale_name = NULL;
+
+ COLLATOR_METHOD_INIT_VARS
+
+ // Parse parameters.
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol",
+ &object, Collator_ce_ptr, &type ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "collator_get_locale: unable to parse input params", 0 TSRMLS_CC );
+
+ RETURN_FALSE;
+ }
+
+ // Fetch the object.
+ COLLATOR_METHOD_FETCH_OBJECT;
+
+ // Get locale by specified type.
+ locale_name = (char*) ucol_getLocaleByType(
+ co->ucoll, type, COLLATOR_ERROR_CODE_P( co ) );
+ COLLATOR_CHECK_STATUS( co, "Error getting locale by type" );
+
+ // Return it.
+ RETVAL_STRINGL( locale_name, strlen(locale_name), TRUE );
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/collator/collator_locale.h b/ext/intl/collator/collator_locale.h
new file mode 100755
index 0000000000..bda90cd3b9
--- /dev/null
+++ b/ext/intl/collator/collator_locale.h
@@ -0,0 +1,25 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef COLLATOR_LOCALE_H
+#define COLLATOR_LOCALE_H
+
+#include <php.h>
+
+PHP_FUNCTION( collator_get_locale );
+
+#endif // COLLATOR_LOCALE_H
diff --git a/ext/intl/collator/collator_sort.c b/ext/intl/collator/collator_sort.c
new file mode 100755
index 0000000000..db014428ad
--- /dev/null
+++ b/ext/intl/collator/collator_sort.c
@@ -0,0 +1,532 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php_intl.h"
+#include "collator.h"
+#include "collator_class.h"
+#include "collator_sort.h"
+#include "collator_convert.h"
+#include "intl_convert.h"
+
+#if !defined(HAVE_PTRDIFF_T) && !defined(_PTRDIFF_T_DEFINED)
+typedef long ptrdiff_t;
+#endif
+
+/**
+ * Declare 'index' which will point to sort key in sort key
+ * buffer.
+ */
+typedef struct _collator_sort_key_index {
+ char* key; // pointer to sort key
+ zval** zstr; // pointer to original string(hash-item)
+} collator_sort_key_index_t;
+
+ZEND_EXTERN_MODULE_GLOBALS( intl )
+
+static const size_t DEF_SORT_KEYS_BUF_SIZE = 1048576;
+static const size_t DEF_SORT_KEYS_BUF_INCREMENT = 1048576;
+
+static const size_t DEF_SORT_KEYS_INDX_BUF_SIZE = 1048576;
+static const size_t DEF_SORT_KEYS_INDX_BUF_INCREMENT = 1048576;
+
+static const size_t DEF_UTF16_BUF_SIZE = 1024;
+
+/* {{{ collator_regular_compare_function */
+static int collator_regular_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
+{
+ Collator_object* co = NULL;
+
+ int rc = SUCCESS;
+
+ zval* str1 = collator_convert_object_to_string( op1 TSRMLS_CC );
+ zval* str2 = collator_convert_object_to_string( op2 TSRMLS_CC );
+
+ zval* num1 = NULL;
+ zval* num2 = NULL;
+ zval* norm1 = NULL;
+ zval* norm2 = NULL;
+
+ // If both args are strings AND either of args is not numeric string
+ // then use ICU-compare. Otherwise PHP-compare.
+ if( Z_TYPE_P(str1) == IS_STRING && Z_TYPE_P(str2) == IS_STRING &&
+ ( str1 == ( num1 = collator_convert_string_to_number_if_possible( str1 ) ) ||
+ str2 == ( num2 = collator_convert_string_to_number_if_possible( str2 ) ) ) )
+ {
+ // Fetch collator object.
+ co = (Collator_object *) zend_object_store_get_object( INTL_G(current_collator) TSRMLS_CC );
+
+ // Compare the strings using ICU.
+ result->value.lval = ucol_strcoll(
+ co->ucoll,
+ INTL_Z_STRVAL_P(str1), INTL_Z_STRLEN_P(str1),
+ INTL_Z_STRVAL_P(str2), INTL_Z_STRLEN_P(str2) );
+ result->type = IS_LONG;
+ }
+ else
+ {
+ // num1 is set if str1 and str2 are strings.
+ if( num1 )
+ {
+ if( num1 == str1 )
+ {
+ // str1 is string but not numeric string
+ // just convert it to utf8.
+ norm1 = collator_convert_zstr_utf16_to_utf8( str1 );
+
+ // num2 is not set but str2 is string => do normalization.
+ norm2 = collator_normalize_sort_argument( str2 );
+ }
+ else
+ {
+ // str1 is numeric strings => passthru to PHP-compare.
+ zval_add_ref( &num1 );
+ norm1 = num1;
+
+ // str2 is numeric strings => passthru to PHP-compare.
+ zval_add_ref( &num2 );
+ norm2 = num2;
+ }
+ }
+ else
+ {
+ // num1 is not set if str1 or str2 is not a string => do normalization.
+ norm1 = collator_normalize_sort_argument( str1 );
+
+ // if num1 is not set then num2 is not set as well => do normalization.
+ norm2 = collator_normalize_sort_argument( str2 );
+ }
+
+ rc = compare_function( result, norm1, norm2 TSRMLS_CC );
+
+ zval_ptr_dtor( &norm1 );
+ zval_ptr_dtor( &norm2 );
+ }
+
+ if( num1 )
+ zval_ptr_dtor( &num1 );
+
+ if( num2 )
+ zval_ptr_dtor( &num2 );
+
+ zval_ptr_dtor( &str1 );
+ zval_ptr_dtor( &str2 );
+
+ return rc;
+}
+/* }}} */
+
+/* {{{ collator_numeric_compare_function
+ * Convert input args to double and compare it.
+ */
+static int collator_numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
+{
+ int rc = SUCCESS;
+ zval* num1 = NULL;
+ zval* num2 = NULL;
+
+ if( Z_TYPE_P(op1) == IS_STRING )
+ {
+ num1 = collator_convert_string_to_double( op1 );
+ op1 = num1;
+ }
+
+ if( Z_TYPE_P(op2) == IS_STRING )
+ {
+ num2 = collator_convert_string_to_double( op2 );
+ op2 = num2;
+ }
+
+ rc = numeric_compare_function( result, op1, op2 TSRMLS_CC);
+
+ if( num1 )
+ zval_ptr_dtor( &num1 );
+ if( num2 )
+ zval_ptr_dtor( &num2 );
+
+ return rc;
+}
+/* }}} */
+
+/* {{{ collator_icu_compare_function
+ * Direct use of ucol_strcoll.
+*/
+static int collator_icu_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
+{
+ int rc = SUCCESS;
+ Collator_object* co = NULL;
+ zval* str1 = NULL;
+ zval* str2 = NULL;
+
+ str1 = collator_make_printable_zval( op1 );
+ str2 = collator_make_printable_zval( op2 );
+
+ // Fetch collator object.
+ co = (Collator_object *) zend_object_store_get_object( INTL_G(current_collator) TSRMLS_CC );
+
+ // Compare the strings using ICU.
+ result->value.lval = ucol_strcoll(
+ co->ucoll,
+ INTL_Z_STRVAL_P(str1), INTL_Z_STRLEN_P(str1),
+ INTL_Z_STRVAL_P(str2), INTL_Z_STRLEN_P(str2) );
+ result->type = IS_LONG;
+
+ zval_ptr_dtor( &str1 );
+ zval_ptr_dtor( &str2 );
+
+ return rc;
+}
+/* }}} */
+
+/* {{{ collator_compare_func
+ * Taken from PHP5 source (array_data_compare).
+ */
+static int collator_compare_func( const void* a, const void* b TSRMLS_DC )
+{
+ Bucket *f;
+ Bucket *s;
+ zval result;
+ zval *first;
+ zval *second;
+
+ f = *((Bucket **) a);
+ s = *((Bucket **) b);
+
+ first = *((zval **) f->pData);
+ second = *((zval **) s->pData);
+
+ if( INTL_G(compare_func)( &result, first, second TSRMLS_CC) == FAILURE )
+ return 0;
+
+ if( Z_TYPE(result) == IS_DOUBLE )
+ {
+ if( Z_DVAL(result) < 0 )
+ return -1;
+ else if( Z_DVAL(result) > 0 )
+ return 1;
+ else
+ return 0;
+ }
+
+ convert_to_long(&result);
+
+ if( Z_LVAL(result) < 0 )
+ return -1;
+ else if( Z_LVAL(result) > 0 )
+ return 1;
+
+ return 0;
+}
+/* }}} */
+
+/* {{{ collator_cmp_sort_keys
+ * Compare sort keys
+ */
+static int collator_cmp_sort_keys( const void *p1, const void *p2 TSRMLS_DC )
+{
+ char* key1 = ((collator_sort_key_index_t*)p1)->key;
+ char* key2 = ((collator_sort_key_index_t*)p2)->key;
+
+ return strcmp( key1, key2 );
+}
+/* }}} */
+
+/* {{{ collator_get_compare_function
+ * Choose compare function according to sort flags.
+ */
+static collator_compare_func_t collator_get_compare_function( const long sort_flags )
+{
+ collator_compare_func_t func;
+
+ switch( sort_flags )
+ {
+ case COLLATOR_SORT_NUMERIC:
+ func = collator_numeric_compare_function;
+ break;
+
+ case COLLATOR_SORT_STRING:
+ func = collator_icu_compare_function;
+ break;
+
+ case COLLATOR_SORT_REGULAR:
+ default:
+ func = collator_regular_compare_function;
+ break;
+ }
+
+ return func;
+}
+/* }}} */
+
+/* {{{ collator_sort_internal
+ * Common code shared by collator_sort() and collator_asort() API functions.
+ */
+static void collator_sort_internal( int renumber, INTERNAL_FUNCTION_PARAMETERS )
+{
+ zval* array = NULL;
+ HashTable* hash = NULL;
+ zval* saved_collator = NULL;
+ long sort_flags = COLLATOR_SORT_REGULAR;
+
+ COLLATOR_METHOD_INIT_VARS
+
+ // Parse parameters.
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oa|l",
+ &object, Collator_ce_ptr, &array, &sort_flags ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "collator_sort_internal: unable to parse input params", 0 TSRMLS_CC );
+
+ RETURN_FALSE;
+ }
+
+ // Fetch the object.
+ COLLATOR_METHOD_FETCH_OBJECT;
+
+ // Set 'compare function' according to sort flags.
+ INTL_G(compare_func) = collator_get_compare_function( sort_flags );
+
+ hash = HASH_OF( array );
+
+ // Convert strings in the specified array from UTF-8 to UTF-16.
+ collator_convert_hash_from_utf8_to_utf16( hash, COLLATOR_ERROR_CODE_P( co ) );
+ COLLATOR_CHECK_STATUS( co, "Error converting hash from UTF-8 to UTF-16" );
+
+ // Save specified collator in the request-global (?) variable.
+ saved_collator = INTL_G( current_collator );
+ INTL_G( current_collator ) = object;
+
+ // Sort specified array.
+ zend_hash_sort( hash, zend_qsort, collator_compare_func, renumber TSRMLS_CC );
+
+ // Restore saved collator.
+ INTL_G( current_collator ) = saved_collator;
+
+ // Convert strings in the specified array back to UTF-8.
+ collator_convert_hash_from_utf16_to_utf8( hash, COLLATOR_ERROR_CODE_P( co ) );
+ COLLATOR_CHECK_STATUS( co, "Error converting hash from UTF-16 to UTF-8" );
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool Collator::sort( Collator $coll, array(string) $arr [, int $sort_flags] )
+ * Sort array using specified collator. }}} */
+/* {{{ proto bool collator_sort( Collator $coll, array(string) $arr [, int $sort_flags] )
+ * Sort array using specified collator.
+ */
+PHP_FUNCTION( collator_sort )
+{
+ collator_sort_internal( TRUE, INTERNAL_FUNCTION_PARAM_PASSTHRU );
+}
+/* }}} */
+
+/* {{{ proto bool Collator::sortWithSortKeys( Collator $coll, array(string) $arr )
+ * Equivalent to standard PHP sort using Collator.
+ * Uses ICU ucol_getSortKey for performance. }}} */
+/* {{{ proto bool collator_sort_with_sort_keys( Collator $coll, array(string) $arr )
+ * Equivalent to standard PHP sort using Collator.
+ * Uses ICU ucol_getSortKey for performance.
+ */
+PHP_FUNCTION( collator_sort_with_sort_keys )
+{
+ zval* array = NULL;
+ HashTable* hash = NULL;
+ zval** hashData = NULL; // currently processed item of input hash
+
+ char* sortKeyBuf = NULL; // buffer to store sort keys
+ uint32_t sortKeyBufSize = DEF_SORT_KEYS_BUF_SIZE; // buffer size
+ ptrdiff_t sortKeyBufOffset = 0; // pos in buffer to store sort key
+ int32_t sortKeyLen = 0; // the length of currently processing key
+ uint32_t bufLeft = 0;
+ uint32_t bufIncrement = 0;
+
+ collator_sort_key_index_t* sortKeyIndxBuf = NULL; // buffer to store 'indexes' which will be passed to 'qsort'
+ uint32_t sortKeyIndxBufSize = DEF_SORT_KEYS_INDX_BUF_SIZE;
+ uint32_t sortKeyIndxSize = sizeof( collator_sort_key_index_t );
+
+ uint32_t sortKeyCount = 0;
+ uint32_t j = 0;
+
+ UChar* utf16_buf = NULL; // tmp buffer to hold current processing string in utf-16
+ int utf16_buf_size = DEF_UTF16_BUF_SIZE; // the length of utf16_buf
+ int utf16_len = 0; // length of converted string
+
+ HashTable* sortedHash = NULL;
+
+ COLLATOR_METHOD_INIT_VARS
+
+ // Parse parameters.
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oa",
+ &object, Collator_ce_ptr, &array ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "collator_sort_with_sort_keys: unable to parse input params", 0 TSRMLS_CC );
+
+ RETURN_FALSE;
+ }
+
+ // Fetch the object.
+ COLLATOR_METHOD_FETCH_OBJECT;
+
+
+ /*
+ * Sort specified array.
+ */
+ hash = HASH_OF( array );
+
+ if( !hash || zend_hash_num_elements( hash ) == 0 )
+ RETURN_TRUE;
+
+ // Create bufers
+ sortKeyBuf = ecalloc( sortKeyBufSize, sizeof( char ) );
+ sortKeyIndxBuf = ecalloc( sortKeyIndxBufSize, sizeof( uint8_t ) );
+ utf16_buf = eumalloc( utf16_buf_size );
+
+ // Iterate through input hash and create a sort key for each value.
+ zend_hash_internal_pointer_reset( hash );
+ while( zend_hash_get_current_data( hash, (void**) &hashData ) == SUCCESS )
+ {
+ // Convert current hash item from UTF-8 to UTF-16LE and save the result to utf16_buf.
+
+ utf16_len = utf16_buf_size;
+
+ // Process string values only.
+ if( Z_TYPE_PP( hashData ) == IS_STRING )
+ {
+ intl_convert_utf8_to_utf16( &utf16_buf, &utf16_len, Z_STRVAL_PP( hashData ), Z_STRLEN_PP( hashData ), COLLATOR_ERROR_CODE_P( co ) );
+
+ if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) )
+ {
+ intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) TSRMLS_CC );
+ intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Sort with sort keys failed", 0 TSRMLS_CC );
+
+ if( utf16_buf )
+ efree( utf16_buf );
+
+ efree( sortKeyIndxBuf );
+ efree( sortKeyBuf );
+
+ RETURN_FALSE;
+ }
+ }
+ else
+ {
+ // Set empty string
+ utf16_len = 0;
+ utf16_buf[utf16_len] = 0;
+ }
+
+ if( (utf16_len + 1) > utf16_buf_size )
+ utf16_buf_size = utf16_len + 1;
+
+ // Get sort key, reallocating the buffer if needed.
+ bufLeft = sortKeyBufSize - sortKeyBufOffset;
+
+ sortKeyLen = ucol_getSortKey( co->ucoll,
+ utf16_buf,
+ utf16_len,
+ (uint8_t*)sortKeyBuf + sortKeyBufOffset,
+ bufLeft );
+
+ // check for sortKeyBuf overflow, increasing its size of the buffer if needed
+ if( sortKeyLen > bufLeft )
+ {
+ bufIncrement = ( sortKeyLen > DEF_SORT_KEYS_BUF_INCREMENT ) ? sortKeyLen : DEF_SORT_KEYS_BUF_INCREMENT;
+
+ sortKeyBufSize += bufIncrement;
+ bufLeft += bufIncrement;
+
+ sortKeyBuf = erealloc( sortKeyBuf, sortKeyBufSize );
+
+ sortKeyLen = ucol_getSortKey( co->ucoll, utf16_buf, utf16_len, (uint8_t*)sortKeyBuf + sortKeyBufOffset, bufLeft );
+ }
+
+ // check sortKeyIndxBuf overflow, increasing its size of the buffer if needed
+ if( ( sortKeyCount + 1 ) * sortKeyIndxSize > sortKeyIndxBufSize )
+ {
+ bufIncrement = ( sortKeyIndxSize > DEF_SORT_KEYS_INDX_BUF_INCREMENT ) ? sortKeyIndxSize : DEF_SORT_KEYS_INDX_BUF_INCREMENT;
+
+ sortKeyIndxBufSize += bufIncrement;
+
+ sortKeyIndxBuf = erealloc( sortKeyIndxBuf, sortKeyIndxBufSize );
+ }
+
+ sortKeyIndxBuf[sortKeyCount].key = (char*)sortKeyBufOffset; // remeber just offset, cause address
+ // of 'sortKeyBuf' may be changed due to realloc.
+ sortKeyIndxBuf[sortKeyCount].zstr = hashData;
+
+ sortKeyBufOffset += sortKeyLen;
+ ++sortKeyCount;
+
+ zend_hash_move_forward( hash );
+ }
+
+ // update ptrs to point to valid keys.
+ for( j = 0; j < sortKeyCount; j++ )
+ sortKeyIndxBuf[j].key = sortKeyBuf + (ptrdiff_t)sortKeyIndxBuf[j].key;
+
+ // sort it
+ zend_qsort( sortKeyIndxBuf, sortKeyCount, sortKeyIndxSize, collator_cmp_sort_keys TSRMLS_CC );
+
+ // for resulting hash we'll assign new hash keys rather then reordering
+ ALLOC_HASHTABLE( sortedHash );
+ zend_hash_init( sortedHash, 0, NULL, ZVAL_PTR_DTOR, 0 );
+
+ for( j = 0; j < sortKeyCount; j++ )
+ {
+ zval_add_ref( sortKeyIndxBuf[j].zstr );
+ zend_hash_next_index_insert( sortedHash, sortKeyIndxBuf[j].zstr, sizeof(zval **), NULL );
+ }
+
+ // Save sorted hash into return variable.
+ zval_dtor( array );
+ (array)->value.ht = sortedHash;
+ (array)->type = IS_ARRAY;
+
+ if( utf16_buf )
+ efree( utf16_buf );
+
+ efree( sortKeyIndxBuf );
+ efree( sortKeyBuf );
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool Collator::asort( Collator $coll, array(string) $arr )
+ * Sort array using specified collator, maintaining index association. }}} */
+/* {{{ proto bool collator_asort( Collator $coll, array(string) $arr )
+ * Sort array using specified collator, maintaining index association.
+ */
+PHP_FUNCTION( collator_asort )
+{
+ collator_sort_internal( FALSE, INTERNAL_FUNCTION_PARAM_PASSTHRU );
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/collator/collator_sort.h b/ext/intl/collator/collator_sort.h
new file mode 100755
index 0000000000..0fafb9f35a
--- /dev/null
+++ b/ext/intl/collator/collator_sort.h
@@ -0,0 +1,29 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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: Vadim Savchuk <vsavchuk@productengine.com> |
+ | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef COLLATOR_SORT_H
+#define COLLATOR_SORT_H
+
+#include <php.h>
+
+typedef int (*collator_compare_func_t)( zval *result, zval *op1, zval *op2 TSRMLS_DC );
+
+PHP_FUNCTION( collator_sort );
+PHP_FUNCTION( collator_sort_with_sort_keys );
+PHP_FUNCTION( collator_asort );
+
+#endif // COLLATOR_SORT_H