mirror of
https://github.com/php/php-src.git
synced 2024-09-22 02:17:32 +00:00
Merge intl extension into core
This commit is contained in:
parent
3bab7c18ac
commit
0d16b1516b
2
ext/intl/CREDITS
Executable file
2
ext/intl/CREDITS
Executable file
@ -0,0 +1,2 @@
|
||||
Internationalization
|
||||
Ed Batutis, Vladimir Iordanov, Dmitry Lakhtyuk, Stanislav Malyshev, Vadim Savchuk, Kirti Velankar
|
5
ext/intl/TODO
Executable file
5
ext/intl/TODO
Executable file
@ -0,0 +1,5 @@
|
||||
- Document U_* error constants
|
||||
- For IntlDateFormatter
|
||||
-- Accept and produce DateTime objects in 5.3 and 6
|
||||
-- Create convertor from ICU pattern to PHP pattern
|
||||
|
96
ext/intl/collator/collator.c
Executable file
96
ext/intl/collator/collator.c
Executable file
@ -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
|
||||
*/
|
29
ext/intl/collator/collator.h
Executable file
29
ext/intl/collator/collator.h
Executable file
@ -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
|
157
ext/intl/collator/collator_attr.c
Executable file
157
ext/intl/collator/collator_attr.c
Executable file
@ -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
|
||||
*/
|
28
ext/intl/collator/collator_attr.h
Executable file
28
ext/intl/collator/collator_attr.h
Executable file
@ -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
|
197
ext/intl/collator/collator_class.c
Executable file
197
ext/intl/collator/collator_class.c
Executable file
@ -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
|
||||
*/
|
71
ext/intl/collator/collator_class.h
Executable file
71
ext/intl/collator/collator_class.h
Executable file
@ -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
|
119
ext/intl/collator/collator_compare.c
Executable file
119
ext/intl/collator/collator_compare.c
Executable file
@ -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
|
||||
*/
|
25
ext/intl/collator/collator_compare.h
Executable file
25
ext/intl/collator/collator_compare.h
Executable file
@ -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
|
482
ext/intl/collator/collator_convert.c
Executable file
482
ext/intl/collator/collator_convert.c
Executable file
@ -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
|
||||
*/
|
38
ext/intl/collator/collator_convert.h
Executable file
38
ext/intl/collator/collator_convert.h
Executable file
@ -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
|
135
ext/intl/collator/collator_create.c
Executable file
135
ext/intl/collator/collator_create.c
Executable file
@ -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
|
||||
*/
|
27
ext/intl/collator/collator_create.h
Executable file
27
ext/intl/collator/collator_create.h
Executable file
@ -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
|
94
ext/intl/collator/collator_error.c
Executable file
94
ext/intl/collator/collator_error.c
Executable file
@ -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
|
||||
*/
|
26
ext/intl/collator/collator_error.h
Executable file
26
ext/intl/collator/collator_error.h
Executable file
@ -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
|
305
ext/intl/collator/collator_is_numeric.c
Executable file
305
ext/intl/collator/collator_is_numeric.c
Executable file
@ -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
|
||||
*/
|
26
ext/intl/collator/collator_is_numeric.h
Executable file
26
ext/intl/collator/collator_is_numeric.h
Executable file
@ -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
|
71
ext/intl/collator/collator_locale.c
Executable file
71
ext/intl/collator/collator_locale.c
Executable file
@ -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
|
||||
*/
|
25
ext/intl/collator/collator_locale.h
Executable file
25
ext/intl/collator/collator_locale.h
Executable file
@ -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
|
532
ext/intl/collator/collator_sort.c
Executable file
532
ext/intl/collator/collator_sort.c
Executable file
@ -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
|
||||
*/
|
29
ext/intl/collator/collator_sort.h
Executable file
29
ext/intl/collator/collator_sort.h
Executable file
@ -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
|
266
ext/intl/common/common_error.c
Executable file
266
ext/intl/common/common_error.c
Executable file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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 "intl_error.h"
|
||||
#include "common_error.h"
|
||||
|
||||
/* {{{ proto int intl_get_error_code()
|
||||
* Get code of the last occured error.
|
||||
*/
|
||||
PHP_FUNCTION( intl_get_error_code )
|
||||
{
|
||||
RETURN_LONG( intl_error_get_code( NULL TSRMLS_CC ) );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string intl_get_error_message()
|
||||
* Get text description of the last occured error.
|
||||
*/
|
||||
PHP_FUNCTION( intl_get_error_message )
|
||||
{
|
||||
char* message = intl_error_get_message( NULL TSRMLS_CC );
|
||||
RETURN_STRING( message, FALSE );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool intl_is_failure()
|
||||
* Check whether the given error code indicates a failure.
|
||||
* Returns true if it does, and false if the code
|
||||
* indicates success or a warning.
|
||||
*/
|
||||
PHP_FUNCTION( intl_is_failure )
|
||||
{
|
||||
long err_code;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "l",
|
||||
&err_code ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"intl_is_failure: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
RETURN_BOOL( U_FAILURE( err_code ) );
|
||||
}
|
||||
|
||||
/* {{{ proto string intl_error_name()
|
||||
* Return a string for a given error code.
|
||||
* The string will be the same as the name of the error code constant.
|
||||
*/
|
||||
PHP_FUNCTION( intl_error_name )
|
||||
{
|
||||
long err_code;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "l",
|
||||
&err_code ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"intl_error_name: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
RETURN_STRING( (char*)u_errorName( err_code ), 1 );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ intl_expose_icu_error_codes
|
||||
* Expose ICU error codes
|
||||
*/
|
||||
void intl_expose_icu_error_codes( INIT_FUNC_ARGS )
|
||||
{
|
||||
#define INTL_EXPOSE_CONST(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS)
|
||||
|
||||
// Warnings
|
||||
INTL_EXPOSE_CONST( U_USING_FALLBACK_WARNING );
|
||||
INTL_EXPOSE_CONST( U_ERROR_WARNING_START );
|
||||
INTL_EXPOSE_CONST( U_USING_DEFAULT_WARNING );
|
||||
INTL_EXPOSE_CONST( U_SAFECLONE_ALLOCATED_WARNING );
|
||||
INTL_EXPOSE_CONST( U_STATE_OLD_WARNING );
|
||||
INTL_EXPOSE_CONST( U_STRING_NOT_TERMINATED_WARNING );
|
||||
INTL_EXPOSE_CONST( U_SORT_KEY_TOO_SHORT_WARNING );
|
||||
INTL_EXPOSE_CONST( U_AMBIGUOUS_ALIAS_WARNING );
|
||||
INTL_EXPOSE_CONST( U_DIFFERENT_UCA_VERSION );
|
||||
INTL_EXPOSE_CONST( U_ERROR_WARNING_LIMIT );
|
||||
|
||||
// Standard errors
|
||||
INTL_EXPOSE_CONST( U_ZERO_ERROR );
|
||||
INTL_EXPOSE_CONST( U_ILLEGAL_ARGUMENT_ERROR );
|
||||
INTL_EXPOSE_CONST( U_MISSING_RESOURCE_ERROR );
|
||||
INTL_EXPOSE_CONST( U_INVALID_FORMAT_ERROR );
|
||||
INTL_EXPOSE_CONST( U_FILE_ACCESS_ERROR );
|
||||
INTL_EXPOSE_CONST( U_INTERNAL_PROGRAM_ERROR );
|
||||
INTL_EXPOSE_CONST( U_MESSAGE_PARSE_ERROR );
|
||||
INTL_EXPOSE_CONST( U_MEMORY_ALLOCATION_ERROR );
|
||||
INTL_EXPOSE_CONST( U_INDEX_OUTOFBOUNDS_ERROR );
|
||||
INTL_EXPOSE_CONST( U_PARSE_ERROR );
|
||||
INTL_EXPOSE_CONST( U_INVALID_CHAR_FOUND );
|
||||
INTL_EXPOSE_CONST( U_TRUNCATED_CHAR_FOUND );
|
||||
INTL_EXPOSE_CONST( U_ILLEGAL_CHAR_FOUND );
|
||||
INTL_EXPOSE_CONST( U_INVALID_TABLE_FORMAT );
|
||||
INTL_EXPOSE_CONST( U_INVALID_TABLE_FILE );
|
||||
INTL_EXPOSE_CONST( U_BUFFER_OVERFLOW_ERROR );
|
||||
INTL_EXPOSE_CONST( U_UNSUPPORTED_ERROR );
|
||||
INTL_EXPOSE_CONST( U_RESOURCE_TYPE_MISMATCH );
|
||||
INTL_EXPOSE_CONST( U_ILLEGAL_ESCAPE_SEQUENCE );
|
||||
INTL_EXPOSE_CONST( U_UNSUPPORTED_ESCAPE_SEQUENCE );
|
||||
INTL_EXPOSE_CONST( U_NO_SPACE_AVAILABLE );
|
||||
INTL_EXPOSE_CONST( U_CE_NOT_FOUND_ERROR );
|
||||
INTL_EXPOSE_CONST( U_PRIMARY_TOO_LONG_ERROR );
|
||||
INTL_EXPOSE_CONST( U_STATE_TOO_OLD_ERROR );
|
||||
INTL_EXPOSE_CONST( U_TOO_MANY_ALIASES_ERROR );
|
||||
INTL_EXPOSE_CONST( U_ENUM_OUT_OF_SYNC_ERROR );
|
||||
INTL_EXPOSE_CONST( U_INVARIANT_CONVERSION_ERROR );
|
||||
INTL_EXPOSE_CONST( U_INVALID_STATE_ERROR );
|
||||
INTL_EXPOSE_CONST( U_COLLATOR_VERSION_MISMATCH );
|
||||
INTL_EXPOSE_CONST( U_USELESS_COLLATOR_ERROR );
|
||||
INTL_EXPOSE_CONST( U_NO_WRITE_PERMISSION );
|
||||
INTL_EXPOSE_CONST( U_STANDARD_ERROR_LIMIT );
|
||||
|
||||
// The error code range 0x10000 0x10100 are reserved for Transliterator
|
||||
INTL_EXPOSE_CONST( U_BAD_VARIABLE_DEFINITION );
|
||||
INTL_EXPOSE_CONST( U_PARSE_ERROR_START );
|
||||
INTL_EXPOSE_CONST( U_MALFORMED_RULE );
|
||||
INTL_EXPOSE_CONST( U_MALFORMED_SET );
|
||||
INTL_EXPOSE_CONST( U_MALFORMED_SYMBOL_REFERENCE );
|
||||
INTL_EXPOSE_CONST( U_MALFORMED_UNICODE_ESCAPE );
|
||||
INTL_EXPOSE_CONST( U_MALFORMED_VARIABLE_DEFINITION );
|
||||
INTL_EXPOSE_CONST( U_MALFORMED_VARIABLE_REFERENCE );
|
||||
INTL_EXPOSE_CONST( U_MISMATCHED_SEGMENT_DELIMITERS );
|
||||
INTL_EXPOSE_CONST( U_MISPLACED_ANCHOR_START );
|
||||
INTL_EXPOSE_CONST( U_MISPLACED_CURSOR_OFFSET );
|
||||
INTL_EXPOSE_CONST( U_MISPLACED_QUANTIFIER );
|
||||
INTL_EXPOSE_CONST( U_MISSING_OPERATOR );
|
||||
INTL_EXPOSE_CONST( U_MISSING_SEGMENT_CLOSE );
|
||||
INTL_EXPOSE_CONST( U_MULTIPLE_ANTE_CONTEXTS );
|
||||
INTL_EXPOSE_CONST( U_MULTIPLE_CURSORS );
|
||||
INTL_EXPOSE_CONST( U_MULTIPLE_POST_CONTEXTS );
|
||||
INTL_EXPOSE_CONST( U_TRAILING_BACKSLASH );
|
||||
INTL_EXPOSE_CONST( U_UNDEFINED_SEGMENT_REFERENCE );
|
||||
INTL_EXPOSE_CONST( U_UNDEFINED_VARIABLE );
|
||||
INTL_EXPOSE_CONST( U_UNQUOTED_SPECIAL );
|
||||
INTL_EXPOSE_CONST( U_UNTERMINATED_QUOTE );
|
||||
INTL_EXPOSE_CONST( U_RULE_MASK_ERROR );
|
||||
INTL_EXPOSE_CONST( U_MISPLACED_COMPOUND_FILTER );
|
||||
INTL_EXPOSE_CONST( U_MULTIPLE_COMPOUND_FILTERS );
|
||||
INTL_EXPOSE_CONST( U_INVALID_RBT_SYNTAX );
|
||||
INTL_EXPOSE_CONST( U_INVALID_PROPERTY_PATTERN );
|
||||
INTL_EXPOSE_CONST( U_MALFORMED_PRAGMA );
|
||||
INTL_EXPOSE_CONST( U_UNCLOSED_SEGMENT );
|
||||
INTL_EXPOSE_CONST( U_ILLEGAL_CHAR_IN_SEGMENT );
|
||||
INTL_EXPOSE_CONST( U_VARIABLE_RANGE_EXHAUSTED );
|
||||
INTL_EXPOSE_CONST( U_VARIABLE_RANGE_OVERLAP );
|
||||
INTL_EXPOSE_CONST( U_ILLEGAL_CHARACTER );
|
||||
INTL_EXPOSE_CONST( U_INTERNAL_TRANSLITERATOR_ERROR );
|
||||
INTL_EXPOSE_CONST( U_INVALID_ID );
|
||||
INTL_EXPOSE_CONST( U_INVALID_FUNCTION );
|
||||
INTL_EXPOSE_CONST( U_PARSE_ERROR_LIMIT );
|
||||
|
||||
// The error code range 0x10100 0x10200 are reserved for formatting API parsing error
|
||||
INTL_EXPOSE_CONST( U_UNEXPECTED_TOKEN );
|
||||
INTL_EXPOSE_CONST( U_FMT_PARSE_ERROR_START );
|
||||
INTL_EXPOSE_CONST( U_MULTIPLE_DECIMAL_SEPARATORS );
|
||||
INTL_EXPOSE_CONST( U_MULTIPLE_DECIMAL_SEPERATORS ); // Typo: kept for backward compatibility. Use U_MULTIPLE_DECIMAL_SEPARATORS
|
||||
INTL_EXPOSE_CONST( U_MULTIPLE_EXPONENTIAL_SYMBOLS );
|
||||
INTL_EXPOSE_CONST( U_MALFORMED_EXPONENTIAL_PATTERN );
|
||||
INTL_EXPOSE_CONST( U_MULTIPLE_PERCENT_SYMBOLS );
|
||||
INTL_EXPOSE_CONST( U_MULTIPLE_PERMILL_SYMBOLS );
|
||||
INTL_EXPOSE_CONST( U_MULTIPLE_PAD_SPECIFIERS );
|
||||
INTL_EXPOSE_CONST( U_PATTERN_SYNTAX_ERROR );
|
||||
INTL_EXPOSE_CONST( U_ILLEGAL_PAD_POSITION );
|
||||
INTL_EXPOSE_CONST( U_UNMATCHED_BRACES );
|
||||
INTL_EXPOSE_CONST( U_UNSUPPORTED_PROPERTY );
|
||||
INTL_EXPOSE_CONST( U_UNSUPPORTED_ATTRIBUTE );
|
||||
INTL_EXPOSE_CONST( U_FMT_PARSE_ERROR_LIMIT );
|
||||
|
||||
// The error code range 0x10200 0x102ff are reserved for Break Iterator related error
|
||||
INTL_EXPOSE_CONST( U_BRK_INTERNAL_ERROR );
|
||||
INTL_EXPOSE_CONST( U_BRK_ERROR_START );
|
||||
INTL_EXPOSE_CONST( U_BRK_HEX_DIGITS_EXPECTED );
|
||||
INTL_EXPOSE_CONST( U_BRK_SEMICOLON_EXPECTED );
|
||||
INTL_EXPOSE_CONST( U_BRK_RULE_SYNTAX );
|
||||
INTL_EXPOSE_CONST( U_BRK_UNCLOSED_SET );
|
||||
INTL_EXPOSE_CONST( U_BRK_ASSIGN_ERROR );
|
||||
INTL_EXPOSE_CONST( U_BRK_VARIABLE_REDFINITION );
|
||||
INTL_EXPOSE_CONST( U_BRK_MISMATCHED_PAREN );
|
||||
INTL_EXPOSE_CONST( U_BRK_NEW_LINE_IN_QUOTED_STRING );
|
||||
INTL_EXPOSE_CONST( U_BRK_UNDEFINED_VARIABLE );
|
||||
INTL_EXPOSE_CONST( U_BRK_INIT_ERROR );
|
||||
INTL_EXPOSE_CONST( U_BRK_RULE_EMPTY_SET );
|
||||
INTL_EXPOSE_CONST( U_BRK_UNRECOGNIZED_OPTION );
|
||||
INTL_EXPOSE_CONST( U_BRK_MALFORMED_RULE_TAG );
|
||||
INTL_EXPOSE_CONST( U_BRK_ERROR_LIMIT );
|
||||
|
||||
// The error codes in the range 0x10300-0x103ff are reserved for regular expression related errrs
|
||||
INTL_EXPOSE_CONST( U_REGEX_INTERNAL_ERROR );
|
||||
INTL_EXPOSE_CONST( U_REGEX_ERROR_START );
|
||||
INTL_EXPOSE_CONST( U_REGEX_RULE_SYNTAX );
|
||||
INTL_EXPOSE_CONST( U_REGEX_INVALID_STATE );
|
||||
INTL_EXPOSE_CONST( U_REGEX_BAD_ESCAPE_SEQUENCE );
|
||||
INTL_EXPOSE_CONST( U_REGEX_PROPERTY_SYNTAX );
|
||||
INTL_EXPOSE_CONST( U_REGEX_UNIMPLEMENTED );
|
||||
INTL_EXPOSE_CONST( U_REGEX_MISMATCHED_PAREN );
|
||||
INTL_EXPOSE_CONST( U_REGEX_NUMBER_TOO_BIG );
|
||||
INTL_EXPOSE_CONST( U_REGEX_BAD_INTERVAL );
|
||||
INTL_EXPOSE_CONST( U_REGEX_MAX_LT_MIN );
|
||||
INTL_EXPOSE_CONST( U_REGEX_INVALID_BACK_REF );
|
||||
INTL_EXPOSE_CONST( U_REGEX_INVALID_FLAG );
|
||||
INTL_EXPOSE_CONST( U_REGEX_LOOK_BEHIND_LIMIT );
|
||||
INTL_EXPOSE_CONST( U_REGEX_SET_CONTAINS_STRING );
|
||||
INTL_EXPOSE_CONST( U_REGEX_ERROR_LIMIT );
|
||||
|
||||
// The error code in the range 0x10400-0x104ff are reserved for IDNA related error codes
|
||||
#if defined(U_IDNA_PROHIBITED_ERROR)
|
||||
INTL_EXPOSE_CONST( U_IDNA_PROHIBITED_ERROR );
|
||||
INTL_EXPOSE_CONST( U_IDNA_ERROR_START );
|
||||
INTL_EXPOSE_CONST( U_IDNA_UNASSIGNED_ERROR );
|
||||
INTL_EXPOSE_CONST( U_IDNA_CHECK_BIDI_ERROR );
|
||||
INTL_EXPOSE_CONST( U_IDNA_STD3_ASCII_RULES_ERROR );
|
||||
INTL_EXPOSE_CONST( U_IDNA_ACE_PREFIX_ERROR );
|
||||
INTL_EXPOSE_CONST( U_IDNA_VERIFICATION_ERROR );
|
||||
INTL_EXPOSE_CONST( U_IDNA_LABEL_TOO_LONG_ERROR );
|
||||
INTL_EXPOSE_CONST( U_IDNA_ZERO_LENGTH_LABEL_ERROR );
|
||||
INTL_EXPOSE_CONST( U_IDNA_ERROR_LIMIT );
|
||||
#endif
|
||||
|
||||
// Aliases for StringPrep
|
||||
INTL_EXPOSE_CONST( U_STRINGPREP_PROHIBITED_ERROR );
|
||||
INTL_EXPOSE_CONST( U_STRINGPREP_UNASSIGNED_ERROR );
|
||||
INTL_EXPOSE_CONST( U_STRINGPREP_CHECK_BIDI_ERROR );
|
||||
|
||||
INTL_EXPOSE_CONST( U_ERROR_LIMIT );
|
||||
|
||||
#undef INTL_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
|
||||
*/
|
30
ext/intl/common/common_error.h
Executable file
30
ext/intl/common/common_error.h
Executable file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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 INTL_COMMON_ERROR_H
|
||||
#define INTL_COMMON_ERROR_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
PHP_FUNCTION( intl_get_error_code );
|
||||
PHP_FUNCTION( intl_get_error_message );
|
||||
PHP_FUNCTION( intl_is_failure );
|
||||
PHP_FUNCTION( intl_error_name );
|
||||
|
||||
void intl_expose_icu_error_codes( INIT_FUNC_ARGS );
|
||||
|
||||
#endif // INTL_COMMON_ERROR_H
|
66
ext/intl/config.m4
Executable file
66
ext/intl/config.m4
Executable file
@ -0,0 +1,66 @@
|
||||
dnl config.m4 for extension intl
|
||||
|
||||
dnl ##########################################################################
|
||||
dnl Initialize the extension
|
||||
PHP_ARG_ENABLE(intl, whether to enable internationalization support,
|
||||
[ --enable-intl Enable internationalization support])
|
||||
|
||||
if test "$PHP_INTL" != "no"; then
|
||||
PHP_SETUP_ICU(INTL_SHARED_LIBADD)
|
||||
PHP_SUBST(INTL_SHARED_LIBADD)
|
||||
PHP_REQUIRE_CXX()
|
||||
|
||||
PHP_NEW_EXTENSION(intl,
|
||||
php_intl.c \
|
||||
intl_error.c \
|
||||
intl_convert.c \
|
||||
collator/collator.c \
|
||||
collator/collator_class.c \
|
||||
collator/collator_sort.c \
|
||||
collator/collator_convert.c \
|
||||
collator/collator_locale.c \
|
||||
collator/collator_compare.c \
|
||||
collator/collator_attr.c \
|
||||
collator/collator_create.c \
|
||||
collator/collator_is_numeric.c \
|
||||
collator/collator_error.c \
|
||||
common/common_error.c \
|
||||
formatter/formatter.c \
|
||||
formatter/formatter_main.c \
|
||||
formatter/formatter_class.c \
|
||||
formatter/formatter_attr.c \
|
||||
formatter/formatter_data.c \
|
||||
formatter/formatter_format.c \
|
||||
formatter/formatter_parse.c \
|
||||
normalizer/normalizer.c \
|
||||
normalizer/normalizer_class.c \
|
||||
normalizer/normalizer_normalize.c \
|
||||
locale/locale.c \
|
||||
locale/locale_class.c \
|
||||
locale/locale_methods.c \
|
||||
dateformat/dateformat.c \
|
||||
dateformat/dateformat_class.c \
|
||||
dateformat/dateformat_attr.c \
|
||||
dateformat/dateformat_data.c \
|
||||
dateformat/dateformat_format.c \
|
||||
dateformat/dateformat_parse.c \
|
||||
msgformat/msgformat.c \
|
||||
msgformat/msgformat_attr.c \
|
||||
msgformat/msgformat_class.c \
|
||||
msgformat/msgformat_data.c \
|
||||
msgformat/msgformat_format.c \
|
||||
msgformat/msgformat_helpers.cpp \
|
||||
msgformat/msgformat_parse.c \
|
||||
grapheme/grapheme_string.c \
|
||||
grapheme/grapheme_util.c \
|
||||
,$ext_shared,,$ICU_INCS)
|
||||
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/collator)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/common)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/formatter)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/normalizer)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/dateformat)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/locale)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/msgformat)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/grapheme)
|
||||
fi
|
71
ext/intl/config.w32
Executable file
71
ext/intl/config.w32
Executable file
@ -0,0 +1,71 @@
|
||||
// $Id$
|
||||
// vim:ft=javascript
|
||||
|
||||
ARG_ENABLE("intl", "Enable internationalization support", "no");
|
||||
|
||||
if (PHP_INTL != "no") {
|
||||
if (CHECK_LIB("icuuc.lib", "intl", PHP_INTL) &&
|
||||
CHECK_HEADER_ADD_INCLUDE("unicode/utf.h", "CFLAGS_INTL")) {
|
||||
// always build as shared - zend_strtod.c/ICU type conflict
|
||||
EXTENSION("intl", "php_intl.c intl_convert.c intl_error.c ", true,
|
||||
"/I \"" + configure_module_dirname + "\"");
|
||||
ADD_SOURCES(configure_module_dirname + "/collator", "\
|
||||
collator.c \
|
||||
collator_attr.c \
|
||||
collator_class.c \
|
||||
collator_compare.c \
|
||||
collator_convert.c \
|
||||
collator_create.c \
|
||||
collator_error.c \
|
||||
collator_is_numeric.c \
|
||||
collator_locale.c \
|
||||
collator_sort.c \
|
||||
", "intl");
|
||||
ADD_SOURCES(configure_module_dirname + "/common", "\
|
||||
common_error.c \
|
||||
", "intl");
|
||||
ADD_SOURCES(configure_module_dirname + "/formatter", "\
|
||||
formatter.c \
|
||||
formatter_attr.c \
|
||||
formatter_class.c \
|
||||
formatter_data.c \
|
||||
formatter_format.c \
|
||||
formatter_main.c \
|
||||
formatter_parse.c \
|
||||
", "intl");
|
||||
ADD_SOURCES(configure_module_dirname + "/locale", "\
|
||||
locale.c \
|
||||
locale_class.c \
|
||||
locale_methods.c \
|
||||
", "intl");
|
||||
ADD_SOURCES(configure_module_dirname + "/msgformat", "\
|
||||
msgformat.c \
|
||||
msgformat_attr.c \
|
||||
msgformat_class.c \
|
||||
msgformat_data.c \
|
||||
msgformat_format.c \
|
||||
msgformat_helpers.cpp \
|
||||
msgformat_parse.c \
|
||||
", "intl");
|
||||
ADD_SOURCES(configure_module_dirname + "/grapheme", "\
|
||||
grapheme_string.c grapheme_util.c \
|
||||
", "intl");
|
||||
ADD_SOURCES(configure_module_dirname + "/normalizer", "\
|
||||
normalizer.c \
|
||||
normalizer_class.c \
|
||||
normalizer_normalize.c \
|
||||
", "intl");
|
||||
ADD_SOURCES(configure_module_dirname + "/dateformat", "\
|
||||
dateformat.c \
|
||||
dateformat_class.c \
|
||||
dateformat_attr.c \
|
||||
dateformat_format.c \
|
||||
dateformat_parse.c \
|
||||
dateformat_data.c \
|
||||
", "intl");
|
||||
ADD_FLAG("LIBS_INTL", "icudt.lib icuin.lib icuio.lib icule.lib iculx.lib");
|
||||
AC_DEFINE("HAVE_INTL", 1, "Internationalization support enabled");
|
||||
} else {
|
||||
WARNING("intl not enabled; libraries and/or headers not found");
|
||||
}
|
||||
}
|
239
ext/intl/doc/Tutorial.txt
Executable file
239
ext/intl/doc/Tutorial.txt
Executable file
@ -0,0 +1,239 @@
|
||||
1. Collator::getAvailableLocales().
|
||||
Return the locales available at the time of the call, including registered locales.
|
||||
If a sever error occurs (such as out of memory condition) this will return null.
|
||||
If there is no locale data, an empty enumeration will be returned.
|
||||
Returned locales list is a strings in format of RFC4646 standart (see http://www.rfc-editor.org/rfc/rfc4646.txt).
|
||||
Examle of locales format: 'en_US', 'ru_UA', 'ua_UA' (see http://demo.icu-project.org/icu-bin/locexp).
|
||||
|
||||
|
||||
2. Collator::getDisplayName( $obj_locale, $disp_locale ).
|
||||
Get name of the object for the desired Locale, in the desired langauge. Both arguments
|
||||
must be from getAvailableLocales method.
|
||||
|
||||
@param string $obj_locale Locale to get display name for.
|
||||
@param string $disp_locale Specifies the desired locale for output
|
||||
|
||||
Both parameters are case insensitive.
|
||||
For locale format see RFC4647 standart in ftp://ftp.rfc-editor.org/in-notes/rfc4647.txt
|
||||
|
||||
3. Collator::getLocaleByType( $type ).
|
||||
Allow user to select whether she wants information on requested, valid or actual locale.
|
||||
Returned locale tag is a string formatted to a RFC4646 standart and normalize to normal form -
|
||||
value is a string from
|
||||
For example, a collator for "en_US_CALIFORNIA" was requested. In the current state of ICU (2.0),
|
||||
the requested locale is "en_US_CALIFORNIA", the valid locale is "en_US" (most specific locale
|
||||
supported by ICU) and the actual locale is "root" (the collation data comes unmodified from the UCA)
|
||||
The locale is considered supported by ICU if there is a core ICU bundle for that locale (although
|
||||
it may be empty).
|
||||
|
||||
|
||||
4. VariableTop
|
||||
The Variable_Top attribute is only meaningful if the Alternate attribute is not set to NonIgnorable.
|
||||
In such a case, it controls which characters count as ignorable. The string value specifies
|
||||
the "highest" character (in UCA order) weight that is to be considered ignorable.
|
||||
Thus, for example, if a user wanted whitespace to be ignorable, but not any visible characters,
|
||||
then s/he would use the value Variable_Top="\u0020" (space). The string should only be a
|
||||
single character. All characters of the same primary weight are equivalent, so
|
||||
Variable_Top="\u3000" (ideographic space) has the same effect as Variable_Top="\u0020".
|
||||
This setting (alone) has little impact on string comparison performance; setting it lower or higher
|
||||
will make sort keys slightly shorter or longer respectively.
|
||||
|
||||
|
||||
5. Strength
|
||||
The ICU Collation Service supports many levels of comparison (named "Levels", but also
|
||||
known as "Strengths"). Having these categories enables ICU to sort strings precisely
|
||||
according to local conventions. However, by allowing the levels to be selectively
|
||||
employed, searching for a string in text can be performed with various matching
|
||||
conditions.
|
||||
Performance optimizations have been made for ICU collation with the default level
|
||||
settings. Performance specific impacts are discussed in the Performance section below.
|
||||
Following is a list of the names for each level and an example usage:
|
||||
|
||||
1. Primary Level: Typically, this is used to denote differences between base characters
|
||||
(for example, "a" < "b"). It is the strongest difference. For example, dictionaries are
|
||||
divided into different sections by base character. This is also called the level1
|
||||
strength.
|
||||
|
||||
2. Secondary Level: Accents in the characters are considered secondary differences (for
|
||||
example, "as" < "as" < "at"). Other differences between letters can also be considered
|
||||
secondary differences, depending on the language. A secondary difference is ignored
|
||||
when there is a primary difference anywhere in the strings. This is also called the
|
||||
level2 strength.
|
||||
Note: In some languages (such as Danish), certain accented letters are considered to
|
||||
be separate base characters. In most languages, however, an accented letter only has a
|
||||
secondary difference from the unaccented version of that letter.
|
||||
|
||||
3. Tertiary Level: Upper and lower case differences in characters are distinguished at the
|
||||
tertiary level (for example, "ao" < "Ao" < "ao"). In addition, a variant of a letter differs
|
||||
from the base form on the tertiary level (such as "A" and " "). Another ? example is the
|
||||
difference between large and small Kana. A tertiary difference is ignored when there is
|
||||
a primary or secondary difference anywhere in the strings. This is also called the level3
|
||||
strength.
|
||||
|
||||
4. Quaternary Level: When punctuation is ignored (see Ignoring Punctuations ) at level
|
||||
13, an additional level can be used to distinguish words with and without punctuation
|
||||
(for example, "ab" < "a-b" < "aB"). This difference is ignored when there is a primary,
|
||||
secondary or tertiary difference. This is also known as the level4 strength. The
|
||||
quaternary level should only be used if ignoring punctuation is required or when
|
||||
processing Japanese text (see Hiragana processing).
|
||||
|
||||
5. Identical Level: When all other levels are equal, the identical level is used as a
|
||||
tiebreaker. The Unicode code point values of the NFD form of each string are
|
||||
compared at this level, just in case there is no difference at levels 14
|
||||
. For example, Hebrew cantillation marks are only distinguished at this level. This level should be
|
||||
used sparingly, as only code point values differences between two strings is an
|
||||
extremely rare occurrence. Using this level substantially decreases the performance for
|
||||
both incremental comparison and sort key generation (as well as increasing the sort
|
||||
key length). It is also known as level 5 strength.
|
||||
|
||||
For example, people may choose to ignore accents or ignore accents and case when searching
|
||||
for text. Almost all characters are distinguished by the first three levels, and in most
|
||||
locales the default value is thus Tertiary. However, if Alternate is set to be Shifted,
|
||||
then the Quaternary strength can be used to break ties among whitespace, punctuation, and
|
||||
symbols that would otherwise be ignored. If very fine distinctions among characters are required,
|
||||
then the Identical strength can be used (for example, Identical Strength distinguishes
|
||||
between the Mathematical Bold Small A and the Mathematical Italic Small A.). However, using
|
||||
levels higher than Tertiary the Identical strength result in significantly longer sort
|
||||
keys, and slower string comparison performance for equal strings.
|
||||
|
||||
|
||||
|
||||
6. Collator::__construct( $locale ).
|
||||
The Locale attribute is typically the most important attribute for correct sorting and matching,
|
||||
according to the user expectations in different countries and regions. The default UCA
|
||||
ordering will only sort a few languages such as Dutch and Portuguese correctly ("correctly"
|
||||
meaning according to the normal expectations for users of the languages).
|
||||
Otherwise, you need to supply the locale to UCA in order to properly collate text for a
|
||||
given language. Thus a locale needs to be supplied so as to choose a collator that is correctly
|
||||
tailored for that locale. The choice of a locale will automatically preset the values for
|
||||
all of the attributes to something that is reasonable for that locale. Thus most of the time the
|
||||
other attributes do not need to be explicitly set. In some cases, the choice of locale will make a
|
||||
difference in string comparison performance and/or sort key length.
|
||||
In short attribute names, <language>_<script>_<region>_<keyword>.
|
||||
Not all the elements are required. Valid values for locale elements are general valid values
|
||||
for RFC4646 locale naming, and RFC 4647 lookup algorithm.
|
||||
Example:
|
||||
Locale="sv" (Swedish) "Kypper" < "Kopfe"
|
||||
Locale="de" (German) "Kopfe" < "Kypper"
|
||||
|
||||
|
||||
7. Collator::get/setAttribute.
|
||||
ICU uses UCA as a default starting point for ordering. Not all languages have sorting sequences
|
||||
that correspond with the UCA because UCA cannot simultaneously encompass the specifics of all
|
||||
the languages currently in use. Therefore, ICU provides a data-driven, flexible, and run-time
|
||||
customizable mechanism called "tailoring". Tailoring overrides the default order of code points
|
||||
and the values of the ICU Collation Service attributes.
|
||||
Collator have followed attributes:
|
||||
- FRENCH_COLLATION, possible values are:
|
||||
ON
|
||||
OFF (default)
|
||||
DEFAULT
|
||||
|
||||
- CASE_FIRST, possible values are:
|
||||
OFF (default)
|
||||
LOWER_FIRST
|
||||
UPPER_FIRST
|
||||
DEFAULT
|
||||
|
||||
- CASE_LEVEL, possible values are:
|
||||
OFF (default)
|
||||
ON
|
||||
DEFAULT
|
||||
|
||||
- NORMALIZATION_MODE, possible values are:
|
||||
OFF (default)
|
||||
ON
|
||||
DEFAULT
|
||||
|
||||
- STRENGTH, possible values are:
|
||||
PRIMARY
|
||||
SECONDARY
|
||||
TERTIARY (default)
|
||||
QUATERNARY
|
||||
IDENTICAL
|
||||
DEFAULT
|
||||
|
||||
- ALTERNATE_HANDLING, possible values are:
|
||||
NON_IGNORABLE (default)
|
||||
SHIFTED
|
||||
DEFAULT
|
||||
|
||||
- HIRAGANA_QUATERNARY_MODE, possible values are:
|
||||
ON
|
||||
OFF (default)
|
||||
DEFAULT
|
||||
|
||||
- NUMERIC_COLLATION, possible values are:
|
||||
ON
|
||||
OFF (default)
|
||||
DEFAULT
|
||||
|
||||
Description of all of this attributes:
|
||||
|
||||
FRENCH_COLLATION - Sort strings with different accents from the back of the string. This attribute
|
||||
is automatically set to On for the French locales and a few others. Users normally would
|
||||
not need to explicitly set this attribute. There is a string comparison performance cost when
|
||||
it is set On, but sort key length is unaffected.
|
||||
Example:
|
||||
F=X cote < cote < cote < cote
|
||||
F=O cote < cote < cote < cote
|
||||
|
||||
CASE_FIRST - The Case_First attribute is used to control whether uppercase letters come before
|
||||
lowercase letters or vice versa, in the absence of other differences in the strings. The possible
|
||||
values are Uppercase_First (U) and Lowercase_First (L), plus the standard Default and Off.
|
||||
There is almost no difference between the Off and Lowercase_First options in terms of results,
|
||||
so typically users will not use Lowercase_First: only Off or Uppercase_First. (People interested
|
||||
in the detailed differences between X and L should consult the Collation Customization).
|
||||
Specifying either L or U won't affect string comparison performance, but will affect the sort key
|
||||
length.
|
||||
Example:
|
||||
C=X or C=L "china" < "China" < "denmark" <
|
||||
"Denmark"
|
||||
C=U "China" < "china" < "Denmark" < "denmark"
|
||||
|
||||
CASE_LEVEL - The Case_Level attribute is used when ignoring accents but not case. In such a situation,
|
||||
set Strength to be Primary, and Case_Level to be On. In most locales, this setting is Off by default.
|
||||
There is a small string comparison performance and sort key impact if this attribute is set to be On.
|
||||
Example:
|
||||
S=1, E=X role = Role = role
|
||||
S=1, E=O role = role < Role
|
||||
|
||||
NORMALIZATION_MODE - The Normalization setting determines whether text is thoroughly normalized
|
||||
or not in comparison. Even if the setting is off (which is the default for many locales), text as
|
||||
represented in common usage will compare correctly (for details, see UTN #5). Only if the accent
|
||||
marks are in noncanonical order will there be a problem. If the setting is On, then the best
|
||||
results are guaranteed for all possible text input. There is a medium string comparison performance
|
||||
cost if this attribute is On, depending on the frequency of sequences that require normalization.
|
||||
There is no significant effect on sort key length. If the input text is known to be in NFD or NFKD
|
||||
normalization forms, there is no need to enable this Normalization option.
|
||||
|
||||
STRENGTH - see Collator::setStrength chapter.
|
||||
|
||||
ALTERNATE_HANDLING - The Alternate attribute is used to control the handling of the socalled
|
||||
variable characters in the UCA: whitespace, punctuation and symbols. If Alternate is set to
|
||||
NonIgnorable (N), then differences among these characters are of the same importance as
|
||||
differences among letters. If Alternate is set to Shifted (S), then these characters are of only
|
||||
minor importance. The Shifted value is often used in combination with Strength set to Quaternary.
|
||||
In such a case, whitespace, punctuation, and symbols are considered when comparing strings,
|
||||
but only if all other aspects of the strings (base letters, accents, and case) are identical.
|
||||
If Alternate is not set to Shifted, then there is no difference between a Strength of 3 and
|
||||
a Strength of 4. For more information and examples, see
|
||||
Variable_Weighting in the UCA (http://www.unicode.org/reports/tr10/#Variable_Weighting).
|
||||
The reason the Alternate values are not simply On and Off is that additional Alternate values
|
||||
may be added in the future. The UCA option Blanked is expressed with Strength set to 3,
|
||||
and Alternate set to Shifted. The default for most locales is NonIgnorable. If Shifted is selected,
|
||||
it may be slower if there are many strings that are the same except for punctuation;
|
||||
sort key length will not be affected unless the strength level is also increased.
|
||||
Example:
|
||||
S=3, A=N di Silva < Di Silva < diSilva < U.S.A. < USA
|
||||
S=3, A=S di Silva = diSilva < Di Silva < U.S.A. = USA
|
||||
S=4, A=S di Silva < diSilva < Di Silva < U.S.A. < USA
|
||||
|
||||
HIRAGANA_QUATERNARY_MODE - Compatibility with JIS x 4061 requires the introduction of an additional
|
||||
level to distinguish Hiragana and Katakana characters. If compatibility with that standard is required,
|
||||
then this attribute should be set On, and the strength set to Quaternary. This will affect sort key
|
||||
length and string comparison string comparison performance.
|
||||
|
||||
NUMERIC_COLLATION - When turned on, this attribute generates a collation key for the
|
||||
numeric value of substrings of digits. This is a way to get '100' to sort AFTER '2'.
|
||||
|
398
ext/intl/doc/collator_api.php
Executable file
398
ext/intl/doc/collator_api.php
Executable file
@ -0,0 +1,398 @@
|
||||
<?php
|
||||
#############################################################################
|
||||
# Object-oriented API
|
||||
#############################################################################
|
||||
|
||||
/**
|
||||
* Collator class.
|
||||
*
|
||||
* This is a wrapper around ICU Collator C API (declared in ucol.h).
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
*
|
||||
* </code>
|
||||
*
|
||||
* @see http://www.icu-project.org/apiref/icu4c/ucol_8h.html
|
||||
* @see http://www.icu-project.org/apiref/icu4c/classCollator.html
|
||||
*
|
||||
*/
|
||||
class Collator {
|
||||
#############################################################################
|
||||
# Common constants.
|
||||
#############################################################################
|
||||
|
||||
/**
|
||||
* Locale-related constants.
|
||||
*
|
||||
* These will be moved out of Collator when Locale class is created.
|
||||
*/
|
||||
const ULOC_ACTUAL_LOCALE = 0;
|
||||
const ULOC_VALID_LOCALE = 1;
|
||||
const ULOC_REQUESTED_LOCALE = 2;
|
||||
|
||||
/*
|
||||
* WARNING:
|
||||
* The values described here are NOT the actual values in PHP code.
|
||||
* They are references to the ICU C definitions, so the line
|
||||
* const DEFAULT_STRENGTH = 'UCOL_DEFAULT_STRENGTH';
|
||||
* actually means that Collator::DEFAULT_STRENGTH is the same as
|
||||
* UCOL_DEFAULT_STRENGTH constant in the ICU library.
|
||||
*/
|
||||
/**
|
||||
* Valid attribute values.
|
||||
*
|
||||
* @see Collator::setAttribute()
|
||||
* @see collator_set_attribute()
|
||||
*/
|
||||
const DEFAULT_VALUE = 'UCOL_DEFAULT';
|
||||
const PRIMARY = 'UCOL_PRIMARY';
|
||||
const SECONDARY = 'UCOL_SECONDARY';
|
||||
const TERTIARY = 'UCOL_TERTIARY';
|
||||
const DEFAULT_STRENGTH = 'UCOL_DEFAULT_STRENGTH';
|
||||
const QUATERNARY = 'UCOL_QUATERNARY';
|
||||
const IDENTICAL = 'UCOL_IDENTICAL';
|
||||
const OFF = 'UCOL_OFF';
|
||||
const ON = 'UCOL_ON';
|
||||
const SHIFTED = 'UCOL_SHIFTED';
|
||||
const NON_IGNORABLE = 'UCOL_NON_IGNORABLE';
|
||||
const LOWER_FIRST = 'UCOL_LOWER_FIRST';
|
||||
const UPPER_FIRST = 'UCOL_UPPER_FIRST';
|
||||
|
||||
/**
|
||||
* Valid attribute names.
|
||||
*
|
||||
* @see Collator::setAttribute()
|
||||
* @see collator_set_attribute()
|
||||
*/
|
||||
const FRENCH_COLLATION = 'UCOL_FRENCH_COLLATION';
|
||||
const ALTERNATE_HANDLING = 'UCOL_ALTERNATE_HANDLING';
|
||||
const CASE_FIRST = 'UCOL_CASE_FIRST';
|
||||
const CASE_LEVEL = 'UCOL_CASE_LEVEL';
|
||||
const NORMALIZATION_MODE = 'UCOL_NORMALIZATION_MODE';
|
||||
const STRENGTH = 'UCOL_STRENGTH';
|
||||
const HIRAGANA_QUATERNARY_MODE = 'UCOL_HIRAGANA_QUATERNARY_MODE';
|
||||
const NUMERIC_COLLATION = 'UCOL_NUMERIC_COLLATION';
|
||||
|
||||
/**
|
||||
* Create a collator
|
||||
*
|
||||
* @param string $locale The locale whose collation rules
|
||||
* should be used. Special values for
|
||||
* locales can be passed in - if null is
|
||||
* passed for the locale, the default
|
||||
* locale collation rules will be used. If
|
||||
* empty string ("") or "root" are passed,
|
||||
* UCA rules will be used.
|
||||
*
|
||||
* @return Collator New instance of Collator object.
|
||||
*/
|
||||
public function __construct( $locale ) {}
|
||||
|
||||
/**
|
||||
* Create a collator
|
||||
*
|
||||
* Creates a new instance of Collator.
|
||||
*
|
||||
* This method is useful when you prefer just to get null on error,
|
||||
* as if you called collator_create().
|
||||
*
|
||||
* @return Collator Newly created Collator instance,
|
||||
* or null on error.
|
||||
*
|
||||
* @see __construct()
|
||||
* @see collator_create()
|
||||
*/
|
||||
public static function create( $locale ) {}
|
||||
|
||||
/**
|
||||
* Get collator's last error code.
|
||||
*
|
||||
* @return int Error code returned by the last
|
||||
* Collator method call.
|
||||
*/
|
||||
public function getErrorCode() {}
|
||||
|
||||
/**
|
||||
* Return error text for the last ICU operation.
|
||||
*
|
||||
* @return string Description of an error occured in the last
|
||||
* Collator method call.
|
||||
*/
|
||||
public function getErrorMessage() {}
|
||||
|
||||
/**
|
||||
* Compare two strings using PHP strcmp() semantics.
|
||||
*
|
||||
* Wrapper around ICU ucol_strcoll().
|
||||
*
|
||||
* @param string $str1 First string to compare.
|
||||
* @param string $str2 Second string to compare.
|
||||
*
|
||||
* @return int 1 if $str1 is greater than $str2;
|
||||
* 0 if $str1 is equal to $str2;
|
||||
* -1 if $str1 is less than $str2.
|
||||
* On error false is returned.
|
||||
*/
|
||||
public function compare( $str1, $str2 ) {}
|
||||
|
||||
/**
|
||||
* Equivalent to standard PHP sort() using Collator.
|
||||
*
|
||||
* @param array $arr Array of strings to sort
|
||||
* @param int $sort_flags Optional sorting type, one of the following:
|
||||
* - SORT_REGULAR - compare items normally (don't change types)
|
||||
* - SORT_NUMERIC - compare items numerically
|
||||
* - SORT_STRING - compare items as strings
|
||||
* Default sorting type is SORT_REGULAR.
|
||||
*
|
||||
* @return bool true on success or false on failure.
|
||||
*/
|
||||
public function sort( $arr, $sort_flags ) {}
|
||||
|
||||
/**
|
||||
* Sort array maintaining index association.
|
||||
*
|
||||
* Equivalent to standard PHP asort() using Collator.
|
||||
*
|
||||
* @param array $arr Array of strings to sort
|
||||
* @param int $sort_flags Optional sorting type
|
||||
*
|
||||
* @return bool true on success or false on failure.
|
||||
*
|
||||
* @see Collator::sort()
|
||||
*/
|
||||
public function asort( $arr, $sort_flags ) {}
|
||||
|
||||
/**
|
||||
* Equivalent to standard PHP sort() using Collator.
|
||||
*
|
||||
* Similar to Collator::sort().
|
||||
* Uses ICU ucol_getSortKey() to gain more speed on large arrays.
|
||||
*
|
||||
* @param array $arr Array of strings to sort
|
||||
*
|
||||
* @return bool true on success or false on failure.
|
||||
*/
|
||||
public function sortWithSortKeys( $arr ) {}
|
||||
|
||||
/**
|
||||
* @todo Do we want to support other standard PHP sort functions: ksort, rsort, asort?
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get collation attribute value.
|
||||
*
|
||||
* Wrapper around ICU ucol_getAttribute().
|
||||
*
|
||||
* @param int $attr Attribute to get value for.
|
||||
*
|
||||
* @return int Attribute value, or false on error.
|
||||
*/
|
||||
public function getAttribute( $attr ) {}
|
||||
|
||||
/**
|
||||
* Set collation attribute.
|
||||
*
|
||||
* Wrapper around ICU ucol_setAttribute().
|
||||
*
|
||||
* @param int $attr Attribute.
|
||||
* @param int $val Attribute value.
|
||||
*
|
||||
* @return bool true on success, false otherwise.
|
||||
*/
|
||||
public function setAttribute( $attr, $val ) {}
|
||||
|
||||
/**
|
||||
* Get current collation strength.
|
||||
*
|
||||
* Wrapper around ICU ucol_getStrength().
|
||||
*
|
||||
* @return int Current collation strength, or false on error.
|
||||
*/
|
||||
public function getStrength() {}
|
||||
|
||||
/**
|
||||
* Set collation strength.
|
||||
*
|
||||
* Wrapper around ICU ucol_setStrength().
|
||||
*
|
||||
* @param int $strength Strength to set.
|
||||
*
|
||||
* @return bool true on success, false otherwise.
|
||||
*/
|
||||
public function setStrength( $strength ) {}
|
||||
|
||||
/**
|
||||
* Get the locale name of the collator.
|
||||
*
|
||||
* Wrapper around ICU ucol_getLocaleByType().
|
||||
*
|
||||
* @param int $type You can choose between requested, valid
|
||||
* and actual locale
|
||||
* (ULOC_REQUESTED_LOCALE,
|
||||
* ULOC_VALID_LOCALE, ULOC_ACTUAL_LOCALE,
|
||||
* respectively).
|
||||
*
|
||||
* @return string Real locale name from which the
|
||||
* collation data comes. If the collator
|
||||
* was instantiated from rules or an error occured,
|
||||
* returns false.
|
||||
*/
|
||||
public function getLocale( $type ) {}
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
# Procedural API
|
||||
#############################################################################
|
||||
|
||||
/**
|
||||
* Create collator.
|
||||
*
|
||||
* @param string $locale The locale containing the required
|
||||
* collation rules. Special values for
|
||||
* locales can be passed in - if null is
|
||||
* passed for the locale, the default
|
||||
* locale collation rules will be used. If
|
||||
* empty string ("") or "root" are passed,
|
||||
* UCA rules will be used.
|
||||
*
|
||||
* @return Collator New instance of Collator object, or null on error.
|
||||
*/
|
||||
function collator_create( $locale ) {}
|
||||
|
||||
/**
|
||||
* Compare two strings.
|
||||
*
|
||||
* The strings will be compared using the options already
|
||||
* specified.
|
||||
*
|
||||
* @param Collator $coll Collator object.
|
||||
* @param string $str1 The first string to compare.
|
||||
* @param string $str2 The second string to compare.
|
||||
*
|
||||
* @return int 1 if $str1 is greater than $str2;
|
||||
* 0 if $str1 is equal to $str2;
|
||||
* -1 if $str1 is less than $str2.
|
||||
* On error false is returned.
|
||||
*
|
||||
*/
|
||||
function collator_compare( $coll, $str1, $str2 ) {}
|
||||
|
||||
/**
|
||||
* Sort array using specified collator.
|
||||
*
|
||||
* @param Collator $coll Collator object.
|
||||
* @param array $arr Array of strings to sort.
|
||||
* @param int $sort_flags Optional sorting type, one of the following:
|
||||
* - SORT_REGULAR - compare items normally (don't change types)
|
||||
* - SORT_NUMERIC - compare items numerically
|
||||
* - SORT_STRING - compare items as strings
|
||||
* Default sorting type is SORT_REGULAR.
|
||||
*
|
||||
* @return bool true on success or false on failure.
|
||||
*/
|
||||
function collator_sort( $coll, $arr, $sort_flags ) {}
|
||||
|
||||
/**
|
||||
* Sort array maintaining index association.
|
||||
*
|
||||
* @param Collator $coll Collator object.
|
||||
* @param array $arr Array of strings to sort.
|
||||
* @param int $sort_flags Optional sorting type.
|
||||
*
|
||||
* @return bool true on success or false on failure.
|
||||
*
|
||||
* @see collator_sort()
|
||||
*/
|
||||
function collator_asort( $coll, $arr, $sort_flags ) {}
|
||||
|
||||
/**
|
||||
* Sort array using specified collator.
|
||||
*
|
||||
* Similar to collator_sort().
|
||||
* Uses ICU ucol_getSortKey() to gain more speed on large arrays.
|
||||
*
|
||||
* @param Collator $coll Collator object.
|
||||
* @param array $arr Array of strings to sort
|
||||
*
|
||||
* @return bool true on success or false on failure.
|
||||
*/
|
||||
function collator_sort_with_sort_keys( $coll, $arr ) {}
|
||||
|
||||
/**
|
||||
* Get the locale name of the collator.
|
||||
*
|
||||
* @param Collator $coll Collator object.
|
||||
* @param int $type You can choose between valid and
|
||||
* actual locale
|
||||
* (ULOC_VALID_LOCALE, ULOC_ACTUAL_LOCALE
|
||||
* respectively).
|
||||
*
|
||||
* @return string Real locale name from which the
|
||||
* collation data comes. If the collator
|
||||
* was instantiated from rules or an error occured,
|
||||
* returns false.
|
||||
*/
|
||||
function collator_get_locale( $coll, $type ) {}
|
||||
|
||||
/**
|
||||
* Get collation attribute value.
|
||||
*
|
||||
* @param Collator $coll Collator object.
|
||||
* @param int $attr Attribute to get value for.
|
||||
*
|
||||
* @return int Attribute value, or false on error.
|
||||
*/
|
||||
function collator_get_attribute( $coll, $attr ) {}
|
||||
|
||||
/**
|
||||
* Get current collation strength.
|
||||
*
|
||||
* @param Collator $coll Collator object.
|
||||
*
|
||||
* @return int Current collation strength, or false on error.
|
||||
*/
|
||||
function collator_get_strength( $coll ) {}
|
||||
|
||||
/**
|
||||
* Set collation strength.
|
||||
*
|
||||
* @param Collator $coll Collator object.
|
||||
* @param int $strength Strength to set.
|
||||
*
|
||||
* @return bool true on success, false otherwise.
|
||||
*/
|
||||
function collator_set_strength( $coll, $strength ) {}
|
||||
|
||||
/**
|
||||
* Set collation attribute.
|
||||
*
|
||||
* @param Collator $coll Collator object.
|
||||
* @param int $attr Attribute.
|
||||
* @param int $val Attribute value.
|
||||
*
|
||||
* @return bool true on success, false otherwise.
|
||||
*/
|
||||
function collator_set_attribute( $coll, $attr, $val ) {}
|
||||
|
||||
/**
|
||||
* Get collator's last error code.
|
||||
*
|
||||
* @param Collator $coll Collator object.
|
||||
*
|
||||
* @return int Error code returned by the last
|
||||
* Collator API function call.
|
||||
*/
|
||||
function collator_get_error_code( $coll ) {}
|
||||
|
||||
/**
|
||||
* Get text for collator's last error code.
|
||||
*
|
||||
* @param Collator $coll Collator object.
|
||||
*
|
||||
* @return string Description of an error occured in the last
|
||||
* Collator API function call.
|
||||
*/
|
||||
function collator_get_error_message( $coll ) {}
|
||||
?>
|
58
ext/intl/doc/common_api.php
Executable file
58
ext/intl/doc/common_api.php
Executable file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Handling of errors occured in static methods
|
||||
* when there's no object to get error code/message from.
|
||||
*
|
||||
* Example #1:
|
||||
* <code>
|
||||
* $coll = collator_create( '<bad_param>' );
|
||||
* if( !$coll )
|
||||
* handle_error( intl_get_error_code() );
|
||||
* </code>
|
||||
*
|
||||
* Example #2:
|
||||
* <code>
|
||||
* if( Collator::getAvailableLocales() === false )
|
||||
* show_error( intl_get_error_message() );
|
||||
* </code>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the last error code.
|
||||
*
|
||||
* @return int Error code returned by the last
|
||||
* API function call.
|
||||
*/
|
||||
function intl_get_error_code() {}
|
||||
|
||||
/**
|
||||
* Get description of the last error.
|
||||
*
|
||||
* @return string Description of an error occured in the last
|
||||
* API function call.
|
||||
*/
|
||||
function intl_get_error_message() {}
|
||||
|
||||
/**
|
||||
* Check whether the given error code indicates failure.
|
||||
*
|
||||
* @param int $code ICU error code.
|
||||
*
|
||||
* @return bool true if it the code indicates some failure,
|
||||
* and false in case of success or a warning.
|
||||
*/
|
||||
function intl_is_failure($code) {}
|
||||
|
||||
/**
|
||||
* Get symbolic name for a given error code.
|
||||
*
|
||||
* The returned string will be the same as the name of the error code constant.
|
||||
*
|
||||
* @param int $code ICU error code.
|
||||
*
|
||||
* @return string Error code name.
|
||||
*/
|
||||
function intl_error_name($code) {}
|
||||
|
||||
?>
|
439
ext/intl/doc/datefmt_api.php
Executable file
439
ext/intl/doc/datefmt_api.php
Executable file
@ -0,0 +1,439 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Date Formatter class - locale-dependent formatting/parsing of dates using pattern strings and/or canned patterns.
|
||||
*
|
||||
* This class represents the ICU date formatting functionality. It allows users to
|
||||
* display dates in a localized format or to parse strings
|
||||
* into PHP date values using pattern strings and/or canned patterns.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $datefmt = new DateFormatter("de-DE", LONG, SHORT, date_default_timezone_get());
|
||||
* echo $formatter->format(time());
|
||||
* </code>
|
||||
*
|
||||
* <code>
|
||||
* $datefmt = new DateFormatter("de-DE", LONG, SHORT, date_default_timezone_get() , GREGORIAN , "yyyy-MM-dd HH:mm:ss z");
|
||||
* echo $formatter->format(time());
|
||||
* </code>
|
||||
*
|
||||
* @see http://www.icu-project.org/apiref/icu4c/udat_8h.html
|
||||
*
|
||||
*/
|
||||
class DateFormatter {
|
||||
|
||||
#############################################################################
|
||||
# Common constants.
|
||||
#############################################################################
|
||||
|
||||
/**
|
||||
* The following constants are used to specify different formats
|
||||
* in the constructor.
|
||||
*/
|
||||
const NONE = -1;
|
||||
const FULL = 0;
|
||||
const LONG = 1;
|
||||
const MEDIUM = 2;
|
||||
const SHORT = 3;
|
||||
|
||||
/**
|
||||
* The following int constants are used to specify the calendar.
|
||||
* These calendars are all based directly on the Gregorian calendar
|
||||
* Non-Gregorian calendars need to be specified in locale.
|
||||
* Examples might include locale="hi@calendar=BUDDHIST"
|
||||
*/
|
||||
const TRADITIONAL = 0; // non-Gregorian calendar that is locale-defined, required by ICU
|
||||
const GREGORIAN = 1 ;// Gregorian calendar
|
||||
|
||||
#############################################################################
|
||||
# Object-oriented API
|
||||
#############################################################################
|
||||
/**
|
||||
* Create a date formatter
|
||||
*
|
||||
* @param string $locale Locale to use when formatting or parsing
|
||||
* @param integer $datetype Date type to use (none, short, medium, long, full)
|
||||
* @param integer $timetype Time type to use (none, short, medium, long, full)
|
||||
* @param [String] $timezone Time zone ID ; default is system default
|
||||
* @param [integer] $calendar Calendar to use for formatting or parsing; default is
|
||||
* GREGORIAN
|
||||
* @param [string] $pattern Optional pattern to use when formatting or parsing
|
||||
* @return DateFormatter
|
||||
* @see __construct
|
||||
* @see datefmt_create
|
||||
*/
|
||||
public function __construct($locale, $datetype, $timetype, $timezone = null, $calendar= null , $pattern= null) {}
|
||||
|
||||
/**
|
||||
* Create a date formatter
|
||||
*
|
||||
* @param string $locale Locale to use when formatting or parsing
|
||||
* @param integer $datetype Date type to use (none, short, medium, long, full)
|
||||
* @param integer $timetype Time type to use (none, short, medium, long, full)
|
||||
* @param [string] $timezone Time zone ID ; default is system default
|
||||
* @param [integer] $calendar Calendar to use for formatting or parsing; default is
|
||||
* GREGORIAN
|
||||
* @param [string] $pattern Optional pattern to use when formatting or parsing
|
||||
* @return DateFormatter
|
||||
* @see __construct
|
||||
* @see datefmt_create
|
||||
*/
|
||||
public static function create($locale, $datetype, $timetype, $timezone = null, $calendar= null , $pattern= null) {}
|
||||
|
||||
/**
|
||||
* formats the time value as a string.
|
||||
* @param mixed $value - value to format
|
||||
* integer: a unix timestamp value (seconds since epoch, UTC)
|
||||
* array: a localtime array - uses 24 hour clock in tm_hour field
|
||||
* @return string a formatted string or, if an error occurred, 'null'.
|
||||
*/
|
||||
public function format($value) {}
|
||||
|
||||
|
||||
/**
|
||||
* converts string $value to an incremental time value, starting at
|
||||
* $parse_pos and consuming as much of the input value as possible
|
||||
* If no error occurs before $value is consumed, $parse_pos will contain -1
|
||||
* otherwise it will contain the position at which parsing ended (and the error
|
||||
* occurred).
|
||||
* @param string $value string to convert to a time
|
||||
* @param integer $parse_pos position at which to start the parsing in $value (zero-based)
|
||||
* This variable will contain the end position if the parse fails
|
||||
* If $parse_pos > strlen($value), the parse fails immediately.
|
||||
* @return integer timestamp parsed value
|
||||
*/
|
||||
public function parse($value, $parse_pos=0) {}
|
||||
|
||||
|
||||
/**
|
||||
* converts string $value to a field-based time value, starting at
|
||||
* $parse_pos and consuming as much of the input value as possible
|
||||
* If no error occurs before $value is consumed, $parse_pos will contain -1
|
||||
* otherwise it will contain the position at which parsing ended (and the error
|
||||
* occurred).
|
||||
* @param string $value string to convert to a time
|
||||
* @param integer $parse_pos position at which to start the parsing in $value (zero-based)
|
||||
* This variable will contain the end position if the parse fails
|
||||
* If $parse_pos > strlen($value), the parse fails immediately.
|
||||
* @return array localtime compatible array of integers - uses 24 hour clock in tm_hour field
|
||||
*/
|
||||
public function localtime($value, $parse_pos=0) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the datetype in use
|
||||
* @return integer the current 'datetype' value of the formatter
|
||||
*/
|
||||
public function getDateType() {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the timetype in use
|
||||
* @return integer the current 'timetype' value of the formatter
|
||||
*/
|
||||
public function getTimeType() {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the leniency in use
|
||||
* @return boolean 'true' if parser is lenient, 'false' if parser is strict
|
||||
* default value for parser is 'false'.
|
||||
*/
|
||||
public function isLenient() {}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the leniency to use
|
||||
* @param boolean $lenient sets whether the parser is lenient or not, default is 'false'
|
||||
* 'true' sets the parser to accept otherwise flawed date or
|
||||
* time patterns, parsing as much as possible to obtain a value.
|
||||
* 'false' sets the parser to strictly parse strings into dates.
|
||||
* Extra space, unrecognized tokens, or invalid values
|
||||
* ("Feburary 30th") are not accepted.
|
||||
*
|
||||
* @return boolean 'true' if successful; 'false' if an error occurred.
|
||||
*/
|
||||
public function setLenient($lenient) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the locale in use
|
||||
* @param [integer] which locale should be returned?
|
||||
* values may include ULOC_ACTUAL_LOCALE,
|
||||
* ULOC_VALID_LOCALE. By default the actual
|
||||
* locale is returned.
|
||||
* @return string the locale of this formatter or 'false' if error
|
||||
*/
|
||||
|
||||
public function getLocale($type = ULOC_ACTUAL_LOCALE) {}
|
||||
|
||||
|
||||
/**
|
||||
* @return string ID string for the time zone used by this formatter
|
||||
*/
|
||||
public function getTimeZoneId() {}
|
||||
|
||||
|
||||
/**
|
||||
* sets the time zone to use
|
||||
* @param string $zone zone ID string of the time zone to use.
|
||||
* if null or the empty string, the default time zone for
|
||||
* the runtime is used.
|
||||
* @return boolean 'true' on successful setting of the time zone, 'false'
|
||||
* if an error occurred (such as the time zone wasn't recognized).
|
||||
*/
|
||||
public function setTimeZoneId($zone) {}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the calendar used to the appropriate calendar, which must be
|
||||
* one of the constants defined above. Some examples include:
|
||||
* - Gregorian calendar
|
||||
* - Traditional
|
||||
* Default value is GREGORIAN
|
||||
* @param integer $which the calendar (an enumerated constant) to use.
|
||||
* @return boolean 'true' if successful, 'false' if an error occurred or if the calendar was not recognized
|
||||
*/
|
||||
public function setCalendar($which) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the Calendar in use
|
||||
* @return integer the calendar being used by the formatter
|
||||
*/
|
||||
public function getCalendar() {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the pattern in use
|
||||
* @return string the pattern string being used to format/parse
|
||||
*/
|
||||
public function getPattern() {}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the pattern to use
|
||||
* @param string $pattern new pattern string to use
|
||||
* @return boolean 'true' if successful, 'false' if an error occured. Bad format
|
||||
* strings are usually the cause of the latter.
|
||||
*/
|
||||
public function setPattern($pattern) {}
|
||||
|
||||
|
||||
/**
|
||||
* Get the error code from last operation
|
||||
*
|
||||
* Returns error code from the last number formatting operation.
|
||||
*
|
||||
* @return integer the error code, one of UErrorCode values. Initial value is U_ZERO_ERROR.
|
||||
*/
|
||||
public function getErrorCode() {}
|
||||
|
||||
|
||||
/**
|
||||
* Get the error text from the last operation.
|
||||
*
|
||||
* @return string Description of the last error.
|
||||
*/
|
||||
public function getErrorMessage() {}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
# Procedural API
|
||||
#############################################################################
|
||||
|
||||
|
||||
/**
|
||||
* Create a date formatter
|
||||
*
|
||||
* @param string $locale Locale to use when formatting or parsing
|
||||
* @param integer $datetype Date type to use (none, short, medium, long, full)
|
||||
* @param integer $timetype Time type to use (none, short, medium, long, full)
|
||||
* @param [string] $timezone Time zone ID ; default is system default
|
||||
* @param [integer] $calendar Calendar to use for formatting or parsing; default is
|
||||
* GREGORIAN
|
||||
* @param [string] $pattern Optional pattern to use when formatting or parsing
|
||||
* @return DateFormatter
|
||||
* @see datefmt_create
|
||||
*/
|
||||
function datefmt_create($locale, $datetype, $timetype, $timezone = null, $calendar= null ,$pattern=null ) {}
|
||||
|
||||
|
||||
/**
|
||||
* formats the time value as a string.
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* @param mixed $value - value to format
|
||||
* integer: a unix timestamp value (seconds since epoch, UTC)
|
||||
* array: a localtime array - uses 24 hour clock in tm_hour field
|
||||
* @return string a formatted string or, if an error occurred, 'null'.
|
||||
*/
|
||||
function datefmt_format($fmt , $value) {}
|
||||
|
||||
|
||||
/**
|
||||
* converts string $value to an incremental time value, starting at
|
||||
* $parse_pos and consuming as much of the input value as possible
|
||||
* If no error occurs before $value is consumed, $parse_pos will contain -1
|
||||
* otherwise it will contain the position at which parsing ended (and the error
|
||||
* occurred).
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* @param string $value string to convert to a time
|
||||
* @param integer $parse_pos position at which to start the parsing in $value (zero-based)
|
||||
* This variable will contain the end position if the parse fails
|
||||
* If $parse_pos > strlen($value), the parse fails immediately.
|
||||
* @return integer timestamp parsed value
|
||||
*/
|
||||
function datefmt_parse($fmt , $value, $parse_pos=0) {}
|
||||
|
||||
|
||||
/**
|
||||
* converts string $value to a field-based time value, starting at
|
||||
* $parse_pos and consuming as much of the input value as possible
|
||||
* If no error occurs before $value is consumed, $parse_pos will contain -1
|
||||
* otherwise it will contain the position at which parsing ended (and the error
|
||||
* occurred).
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* @param string $value string to convert to a time
|
||||
* @param integer $parse_pos position at which to start the parsing in $value (zero-based)
|
||||
* This variable will contain the end position if the parse fails
|
||||
* If $parse_pos > strlen($value), the parse fails immediately.
|
||||
* @return array localtime compatible array of integers - uses 24 hour clock in tm_hour field
|
||||
*/
|
||||
function datefmt_localtime($fmt , $value, $parse_pos=0) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the Datetype in use
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* @return integer the current 'datetype' value of the formatter
|
||||
*/
|
||||
function datefmt_get_datetype($fmt ) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the timetype in use
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* @return integer the current 'timetype' value of the formatter
|
||||
*/
|
||||
function datefmt_get_timetype($fmt) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the leniency of the formatter
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* @return boolean 'true' if parser is lenient, 'false' if parser is strict
|
||||
* default value for parser is 'false'.
|
||||
*/
|
||||
function datefmt_is_lenient($fmt) {}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the leniency of the formatter
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* @param boolean $lenient sets whether the parser is lenient or not, default is 'false'
|
||||
* 'true' sets the parser to accept otherwise flawed date or
|
||||
* time patterns, parsing as much as possible to obtain a value.
|
||||
* 'false' sets the parser to strictly parse strings into dates.
|
||||
* Extra space, unrecognized tokens, or invalid values
|
||||
* ("Feburary 30th") are not accepted.
|
||||
*
|
||||
* @return boolean 'true' if successful; 'false' if an error occurred.
|
||||
*/
|
||||
function datefmt_set_lenient($fmt , $lenient) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the locale in use
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* @param [integer] which locale should be returned?
|
||||
* values may include ULOC_ACTUAL_LOCALE,
|
||||
* ULOC_VALID_LOCALE. By default the actual
|
||||
* locale is returned.
|
||||
* @return string the locale of this formatter or 'false' if error
|
||||
*/
|
||||
function datefmt_get_locale($fmt , $type = ULOC_ACTUAL_LOCALE) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the time zone id in use
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* @return string ID string for the time zone used by this formatter
|
||||
*/
|
||||
function datefmt_get_timezone_id($fmt) {}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the time zone to use
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* @param string $zone zone ID string of the time zone to use.
|
||||
* if null or the empty string, the default time zone for
|
||||
* the runtime is used.
|
||||
* @return boolean 'true' on successful setting of the time zone, 'false'
|
||||
* if an error occurred (such as the time zone wasn't recognized).
|
||||
*/
|
||||
function datefmt_set_timezone_id($fmt , $zone) {}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the calendar used to the appropriate calendar, which must be
|
||||
* one of the constants defined above. Some examples include:
|
||||
* - Gregorian calendar
|
||||
* - Traditional
|
||||
* Default value is GREGORIAN
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* @param integer $which the calendar (an enumerated constant) to use.
|
||||
* @return boolean 'true' if successful, 'false' if an error occurred or if the calendar was not recognized
|
||||
*/
|
||||
function datefmt_set_calendar($fmt , $which) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the calendar in use
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* @return integer the calendar being used by the formatter
|
||||
*/
|
||||
function datefmt_get_calendar($fmt) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the pattern in use
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* @return string the pattern string being used to format/parse
|
||||
*/
|
||||
function datefmt_get_pattern($fmt) {}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the pattern to use
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* @param string $pattern new pattern string to use
|
||||
* @return boolean 'true' if successful, 'false' if an error occured. Bad format
|
||||
* strings are usually the cause of the latter.
|
||||
*/
|
||||
function datefmt_set_pattern($fmt , $pattern) {}
|
||||
|
||||
|
||||
/**
|
||||
* Get the error code from last operation
|
||||
*
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* Returns error code from the last number formatting operation.
|
||||
*
|
||||
* @return integer the error code, one of UErrorCode values. Initial value is U_ZERO_ERROR.
|
||||
*/
|
||||
function datefmt_get_error_code($fmt) {}
|
||||
|
||||
|
||||
/**
|
||||
* Get the error text from the last operation.
|
||||
*
|
||||
* @param DateFormatter $fmt The date formatter resource
|
||||
* @return string Description of the last error.
|
||||
*/
|
||||
function datefmt_get_error_message($fmt) {}
|
||||
|
||||
|
||||
?>
|
502
ext/intl/doc/formatter_api.php
Executable file
502
ext/intl/doc/formatter_api.php
Executable file
@ -0,0 +1,502 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Number formatter class - locale-dependent number formatting/parsing.
|
||||
*
|
||||
* This class represents the ICU number formatting functionality. It allows to display
|
||||
* number according to the localized format or given pattern or set of rules, and to
|
||||
* parse strings into numbers according to the above patterns.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $value = 1234567;
|
||||
* $formatter = new NumberFormatter("de_DE", NumberFormatter::DECIMAL);
|
||||
* echo $formatter->format($value);
|
||||
* </code>
|
||||
*
|
||||
* @see http://www.icu-project.org/apiref/icu4c/unum_8h.html
|
||||
* @see http://www.icu-project.org/apiref/icu4c/classNumberFormat.html
|
||||
*
|
||||
* The class would also contain all the constants listed in the following enums:
|
||||
* UNumberFormatStyle, UNumberFormatRoundingMode, UNumberFormatPadPosition,
|
||||
* UNumberFormatAttribute, UNumberFormatTextAttribute, UNumberFormatSymbol.
|
||||
*/
|
||||
class NumberFormatter {
|
||||
#############################################################################
|
||||
# Common constants.
|
||||
#############################################################################
|
||||
|
||||
/*
|
||||
* WARNING:
|
||||
* The values described here are NOT the actual values in PHP code.
|
||||
* They are references to the ICU C definitions, so the line
|
||||
* const PATTERN_DECIMAL = 'UNUM_PATTERN_DECIMAL';
|
||||
* actually means that NumberFormatter::PATTERN_DECIMAL is the same as
|
||||
* UNUM_PATTERN_DECIMAL constant in the ICU library.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These constants define formatter/parser argument type - integer, floating point or currency.
|
||||
*/
|
||||
const TYPE_DEFAULT = 'FORMAT_TYPE_DEFAULT';
|
||||
const TYPE_INT32 = 'FORMAT_TYPE_INT32';
|
||||
const TYPE_INT64 = 'FORMAT_TYPE_INT64';
|
||||
const TYPE_DOUBLE = 'FORMAT_TYPE_DOUBLE';
|
||||
const TYPE_CURRENCY = 'FORMAT_TYPE_CURRENCY';
|
||||
|
||||
/*
|
||||
* UNumberFormatStyle constants
|
||||
*/
|
||||
const PATTERN_DECIMAL = 'UNUM_PATTERN_DECIMAL';
|
||||
const DECIMAL = 'UNUM_DECIMAL';
|
||||
const CURRENCY = 'UNUM_CURRENCY';
|
||||
const PERCENT = 'UNUM_PERCENT';
|
||||
const SCIENTIFIC = 'UNUM_SCIENTIFIC';
|
||||
const SPELLOUT = 'UNUM_SPELLOUT';
|
||||
const ORDINAL = 'UNUM_ORDINAL';
|
||||
const DURATION = 'UNUM_DURATION';
|
||||
const PATTERN_RULEBASED = 'UNUM_PATTERN_RULEBASED';
|
||||
const DEFAULT = 'UNUM_DEFAULT';
|
||||
const IGNORE = 'UNUM_IGNORE';
|
||||
|
||||
/*
|
||||
* UNumberFormatRoundingMode
|
||||
*/
|
||||
const ROUND_CEILING = 'UNUM_ROUND_CEILING';
|
||||
const ROUND_FLOOR = 'UNUM_ROUND_FLOOR';
|
||||
const ROUND_DOWN = 'UNUM_ROUND_DOWN';
|
||||
const ROUND_UP = 'UNUM_ROUND_UP';
|
||||
const ROUND_HALFEVEN = 'UNUM_ROUND_HALFEVEN';
|
||||
const ROUND_HALFDOWN = 'UNUM_ROUND_HALFDOWN';
|
||||
const ROUND_HALFUP = 'UNUM_ROUND_HALFUP';
|
||||
|
||||
/*
|
||||
* UNumberFormatPadPosition
|
||||
*/
|
||||
const PAD_BEFORE_PREFIX = 'UNUM_PAD_BEFORE_PREFIX';
|
||||
const PAD_AFTER_PREFIX = 'UNUM_PAD_AFTER_PREFIX';
|
||||
const PAD_BEFORE_SUFFIX = 'UNUM_PAD_BEFORE_SUFFIX';
|
||||
const PAD_AFTER_SUFFIX = 'UNUM_PAD_AFTER_SUFFIX';
|
||||
|
||||
/*
|
||||
* UNumberFormatAttribute
|
||||
*/
|
||||
const PARSE_INT_ONLY = 'UNUM_PARSE_INT_ONLY';
|
||||
const GROUPING_USED = 'UNUM_GROUPING_USED';
|
||||
const DECIMAL_ALWAYS_SHOWN = 'UNUM_DECIMAL_ALWAYS_SHOWN';
|
||||
const MAX_INTEGER_DIGITS = 'UNUM_MAX_INTEGER_DIGITS';
|
||||
const MIN_INTEGER_DIGITS = 'UNUM_MIN_INTEGER_DIGITS';
|
||||
const INTEGER_DIGITS = 'UNUM_INTEGER_DIGITS';
|
||||
const MAX_FRACTION_DIGITS = 'UNUM_MAX_FRACTION_DIGITS';
|
||||
const MIN_FRACTION_DIGITS = 'UNUM_MIN_FRACTION_DIGITS';
|
||||
const FRACTION_DIGITS = 'UNUM_FRACTION_DIGITS';
|
||||
const MULTIPLIER = 'UNUM_MULTIPLIER';
|
||||
const GROUPING_SIZE = 'UNUM_GROUPING_SIZE';
|
||||
const ROUNDING_MODE = 'UNUM_ROUNDING_MODE';
|
||||
const ROUNDING_INCREMENT = 'UNUM_ROUNDING_INCREMENT';
|
||||
const FORMAT_WIDTH = 'UNUM_FORMAT_WIDTH';
|
||||
const PADDING_POSITION = 'UNUM_PADDING_POSITION';
|
||||
const SECONDARY_GROUPING_SIZE = 'UNUM_SECONDARY_GROUPING_SIZE';
|
||||
const SIGNIFICANT_DIGITS_USED = 'UNUM_SIGNIFICANT_DIGITS_USED';
|
||||
const MIN_SIGNIFICANT_DIGITS = 'UNUM_MIN_SIGNIFICANT_DIGITS';
|
||||
const MAX_SIGNIFICANT_DIGITS = 'UNUM_MAX_SIGNIFICANT_DIGITS';
|
||||
const LENIENT_PARSE = 'UNUM_LENIENT_PARSE';
|
||||
|
||||
/*
|
||||
* UNumberFormatTextAttribute
|
||||
*/
|
||||
const POSITIVE_PREFIX = 'UNUM_POSITIVE_PREFIX';
|
||||
const POSITIVE_SUFFIX = 'UNUM_POSITIVE_SUFFIX';
|
||||
const NEGATIVE_PREFIX = 'UNUM_NEGATIVE_PREFIX';
|
||||
const NEGATIVE_SUFFIX = 'UNUM_NEGATIVE_SUFFIX';
|
||||
const PADDING_CHARACTER = 'UNUM_PADDING_CHARACTER';
|
||||
const CURRENCY_CODE = 'UNUM_CURRENCY_CODE';
|
||||
const DEFAULT_RULESET = 'UNUM_DEFAULT_RULESET';
|
||||
const PUBLIC_RULESETS = 'UNUM_PUBLIC_RULESETS';
|
||||
|
||||
/*
|
||||
* UNumberFormatSymbol
|
||||
*/
|
||||
const DECIMAL_SEPARATOR_SYMBOL = 'UNUM_DECIMAL_SEPARATOR_SYMBOL';
|
||||
const GROUPING_SEPARATOR_SYMBOL = 'UNUM_GROUPING_SEPARATOR_SYMBOL';
|
||||
const PATTERN_SEPARATOR_SYMBOL = 'UNUM_PATTERN_SEPARATOR_SYMBOL';
|
||||
const PERCENT_SYMBOL = 'UNUM_PERCENT_SYMBOL';
|
||||
const ZERO_DIGIT_SYMBOL = 'UNUM_ZERO_DIGIT_SYMBOL';
|
||||
const DIGIT_SYMBOL = 'UNUM_DIGIT_SYMBOL';
|
||||
const MINUS_SIGN_SYMBOL = 'UNUM_MINUS_SIGN_SYMBOL';
|
||||
const PLUS_SIGN_SYMBOL = 'UNUM_PLUS_SIGN_SYMBOL';
|
||||
const CURRENCY_SYMBOL = 'UNUM_CURRENCY_SYMBOL';
|
||||
const INTL_CURRENCY_SYMBOL = 'UNUM_INTL_CURRENCY_SYMBOL';
|
||||
const MONETARY_SEPARATOR_SYMBOL = 'UNUM_MONETARY_SEPARATOR_SYMBOL';
|
||||
const EXPONENTIAL_SYMBOL = 'UNUM_EXPONENTIAL_SYMBOL';
|
||||
const PERMILL_SYMBOL = 'UNUM_PERMILL_SYMBOL';
|
||||
const PAD_ESCAPE_SYMBOL = 'UNUM_PAD_ESCAPE_SYMBOL';
|
||||
const INFINITY_SYMBOL = 'UNUM_INFINITY_SYMBOL';
|
||||
const NAN_SYMBOL = 'UNUM_NAN_SYMBOL';
|
||||
const SIGNIFICANT_DIGIT_SYMBOL = 'UNUM_SIGNIFICANT_DIGIT_SYMBOL';
|
||||
const MONETARY_GROUPING_SEPARATOR_SYMBOL = 'UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL';
|
||||
|
||||
/**
|
||||
* Create a number formatter
|
||||
*
|
||||
* Creates a number formatter from locale and pattern. This formatter would be used to
|
||||
* format or parse numbers.
|
||||
*
|
||||
* @param integer $style Style of the formatting, one of the UNumberFormatStyle constants
|
||||
* @param string $locale Locale in which the number would be formatted
|
||||
* @param [string] $pattern Pattern string in case chose style requires pattern
|
||||
* @return NumberFormatter
|
||||
*/
|
||||
public function __construct($locale, $style, $pattern = null) {}
|
||||
|
||||
/**
|
||||
* Create a number formatter
|
||||
*
|
||||
* Creates a number formatter from locale and pattern. This formatter would be used to
|
||||
* format or parse numbers.
|
||||
*
|
||||
* This method is useful when you prefer just to get null on error,
|
||||
* as if you called numfmt_create().
|
||||
*
|
||||
* @param integer $style Style of the formatting, one of the UNumberFormatStyle constants
|
||||
* @param string $locale Locale in which the number would be formatted
|
||||
* @param [string] $pattern Pattern string in case chose style requires pattern
|
||||
* @return NumberFormatter
|
||||
* @see __construct
|
||||
* @see numfmt_create
|
||||
*/
|
||||
public static function create($locale, $style, $pattern = null) {}
|
||||
|
||||
/**
|
||||
* Format a number according to current formatting rules.
|
||||
*
|
||||
* If the type is not specified, the type is derived from the $number parameter. I.e., if it's
|
||||
* integer then INT32 would be chosen on 32-bit, INT64 on 64-bit, if it's double, DOUBLE would be
|
||||
* chosen. It is possible to format 64-bit number on 32-bit machine by passing it as double and using
|
||||
* TYPE_INT64.
|
||||
* When formatting currency, default formatter's currency code is used.
|
||||
*
|
||||
* @param integer|double $number Number to format
|
||||
* @param [integer] $type Type of the formatting - one of TYPE constants. If not specified, default for the type.
|
||||
* @return string formatted number
|
||||
*/
|
||||
public function format($number, $type = 0) {}
|
||||
|
||||
/**
|
||||
* Parse a number according to current formatting rules.
|
||||
*
|
||||
* @param string $string String to parse
|
||||
* @param [integer] $type Type of the formatting - one of TYPE constants.
|
||||
* TYPE_DOUBLE is used by default.
|
||||
* @param [integer] $position On input, the position to start parsing, default is 0;
|
||||
* on output, moved to after the last successfully parse character;
|
||||
* on parse failure, does not change.
|
||||
* @return integer|double|false Parsed number, false if parsing failed
|
||||
*/
|
||||
public function parse($string, $type, &$position) {}
|
||||
|
||||
/**
|
||||
* Format number as currency.
|
||||
*
|
||||
* Uses user-defined currency string.
|
||||
*
|
||||
* @param double $number Number to format
|
||||
* @param string $currency 3-letter currency code (ISO 4217) to use in format
|
||||
*/
|
||||
public function formatCurrency($number, $currency) {}
|
||||
|
||||
/**
|
||||
* Parse currency string
|
||||
*
|
||||
* This parser would use parseCurrency API string to parse currency string. The format is defined by the
|
||||
* formatter, returns both number and currency code.
|
||||
*
|
||||
* @param string $string String to parse
|
||||
* @param string $currency Parameter to return parsed currency code
|
||||
* @param [integer] $position On input, the position within text to match, default is 0;
|
||||
* on output, the position after the last matched character;
|
||||
* on parse failure, does not change.
|
||||
* @return double currency number
|
||||
*/
|
||||
public function parseCurrency($string, &$currency, &$position) {}
|
||||
|
||||
/**
|
||||
* Set formatter attribute.
|
||||
*
|
||||
* This function is used to set any of the formatter attributes. Example:
|
||||
*
|
||||
* $formatter->setAttribute(NumberFormat::FORMAT_WIDTH, 10);
|
||||
*
|
||||
* @param integer $attr One of UNumberFormatAttribute constants
|
||||
* @param integer|double $value Value of the attribute
|
||||
* @return false if attribute is unknown or can not be set, true otherwise
|
||||
*/
|
||||
public function setAttribute($attr, $value) {}
|
||||
/**
|
||||
* Set formatter attribute.
|
||||
*
|
||||
* This function is used to set any of the formatter attributes. Example:
|
||||
*
|
||||
* $formatter->setTextAttribute(NumberFormat::POSITIVE_PREFIX, "+");
|
||||
*
|
||||
* @param integer $attr One of UNumberFormatTextAttribute constants
|
||||
* @param string $value Value of the attribute
|
||||
* @return false if attribute is unknown or can not be set, true otherwise
|
||||
*/
|
||||
public function setTextAttribute($attr, $value) {}
|
||||
/**
|
||||
* Set formatting symbol.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* $formatter->setSymbol(NumberFormat::EXPONENTIAL_SYMBOL, "E");
|
||||
*
|
||||
* @param integer|array $attr One of UNumberFormatSymbol constants or array of symbols, indexed by
|
||||
* these constants
|
||||
* @param string $value Value of the symbol
|
||||
*/
|
||||
public function setSymbol($attr, $value) {}
|
||||
/**
|
||||
* Set pattern used by the formatter
|
||||
*
|
||||
* Valid only if the formatter is using pattern and is not rule-based.
|
||||
* @see http://www.icu-project.org/apiref/icu4c/classDecimalFormat.html
|
||||
* Localized patterns are not currently supported.
|
||||
*
|
||||
* @param string $pattern The pattern to be used.
|
||||
* @return boolean false if formatter pattern could not be set, true otherwise
|
||||
*/
|
||||
public function setPattern($pattern) {}
|
||||
/**
|
||||
* Get value of the formatter attribute
|
||||
*
|
||||
* @param integer $attr One of UNumberFormatAttribute constants
|
||||
* @return integer|double value of the attribute or false if the value can not be obtained
|
||||
*/
|
||||
public function getAttribute($attr) {}
|
||||
/**
|
||||
* Get value of the formatter attribute
|
||||
*
|
||||
* @param integer $attr One of UNumberFormatTextAttribute constants
|
||||
* @return string value of the attribute or false if the value can not be obtained
|
||||
*/
|
||||
public function getTextAttribute($attr) {}
|
||||
/**
|
||||
* Get value of the formatter symbol
|
||||
*
|
||||
* @param integer $attr One of UNumberFormatSymbol constants specifying the symbol
|
||||
* @return string|false The symbol value, or false if the value can not be obtained
|
||||
*/
|
||||
public function getSymbol($attr) {}
|
||||
/**
|
||||
* Get pattern used by the formatter.
|
||||
*
|
||||
* Gets current state of the formatter as a pattern.
|
||||
* Localized patterns are not currently supported.
|
||||
*
|
||||
* Valid only if the formatter is UNUM_PATTERN_DECIMAL
|
||||
* @return string|false The pattern used by the formatter or false if formatter is of a type
|
||||
* that does not support patterns.
|
||||
*/
|
||||
public function getPattern() {}
|
||||
/**
|
||||
* Get the locale for which the formatter was created.
|
||||
*
|
||||
* @param [integer] $type One of ULocDataLocaleType values
|
||||
* @return string locale name
|
||||
*/
|
||||
public function getLocale($type = 0) {}
|
||||
/**
|
||||
* Get the error code from last operation
|
||||
*
|
||||
* Returns error code from the last number formatting operation.
|
||||
*
|
||||
* @return integer the error code, one of UErrorCode values. Initial value is U_ZERO_ERROR.
|
||||
*/
|
||||
public function getErrorCode() {}
|
||||
/**
|
||||
* Get the error text from the last operation.
|
||||
*
|
||||
* @return string Description of the last occured error.
|
||||
*/
|
||||
public public function getErrorMessage() {}
|
||||
|
||||
}
|
||||
|
||||
/** Now the same as procedural API */
|
||||
|
||||
/**
|
||||
* Create a number formatter
|
||||
*
|
||||
* Creates a number formatter from locale and pattern. This formatter would be used to
|
||||
* format or parse numbers.
|
||||
*
|
||||
* @param string $locale Locale in which the number would be formatted
|
||||
* @param integer $style Style of the formatting, one of the UNumberFormatStyle constants
|
||||
* @param [string] $pattern Pattern string in case chose style requires pattern
|
||||
* @return Numberformatter resource NumberFormatter
|
||||
*/
|
||||
function numfmt_create($locale, $style, $pattern = null) {}
|
||||
/**
|
||||
* Format a number according to current formatting rules.
|
||||
*
|
||||
* If the type is not specified, the type is derived from the $number parameter. I.e., if it's
|
||||
* integer then INT32 would be chosen on 32-bit, INT64 on 64-bit, if it's double, DOUBLE would be
|
||||
* chosen. It is possible to format 64-bit number on 32-bit machine by passing it as double and using
|
||||
* TYPE_INT64.
|
||||
*
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @param integer|double $number Number to format
|
||||
* @param [integer] $type Type of the formatting - one of TYPE constants. If not specified, default for the type.
|
||||
* @return string formatted number
|
||||
*/
|
||||
function numfmt_format($formatter, $number, $type = null) {}
|
||||
/**
|
||||
* Parse a number according to current formatting rules.
|
||||
*
|
||||
* This parser uses DOUBLE type by default. When parsing currency,
|
||||
* default currency definitions are used.
|
||||
*
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @param string $string String to parse
|
||||
* @param [integer] $type Type of the formatting - one of TYPE constants.
|
||||
* @param [integer] $position String position after the end of parsed data.
|
||||
* @return integer|double|false Parsed number, false if parsing failed
|
||||
*/
|
||||
function numfmt_parse($formatter, $string, $type, &$position) {}
|
||||
/**
|
||||
* Format number as currency.
|
||||
*
|
||||
* Uses user-defined currency string.
|
||||
*
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @param double $number Number to format
|
||||
* @param string $currency 3-letter currency code (ISO 4217) to use in format
|
||||
*/
|
||||
function numfmt_format_currency($formatter, $number, $currency) {}
|
||||
/**
|
||||
* Parse currency string
|
||||
*
|
||||
* This parser would use parseCurrency API string to parse currency string. The format is defined by the
|
||||
* formatter, returns both number and currency code.
|
||||
*
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @param string $string String to parse
|
||||
* @param string $currency Parameter to return parsed currency code
|
||||
* @param [integer] $position String position after the end of parsed data.
|
||||
* @return double currency number
|
||||
*/
|
||||
function numfmt_parse_currency($formatter, $string, &$currency, &$position) {}
|
||||
/**
|
||||
* Set formatter attribute.
|
||||
*
|
||||
* This function is used to set any of the formatter attributes. Example:
|
||||
*
|
||||
* numfmt_format_set_attribute($formatter, NumberFormat::FORMAT_WIDTH, 10);
|
||||
*
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @param integer $attr One of UNumberFormatAttribute constants
|
||||
* @param integer|double $value Value of the attribute
|
||||
* @return false if attribute is unknown or can not be set, true otherwise
|
||||
*/
|
||||
function numfmt_set_attribute($formatter, $attribute, $value) {}
|
||||
/**
|
||||
* Set formatter attribute.
|
||||
*
|
||||
* This function is used to set any of the formatter attributes. Example:
|
||||
*
|
||||
* numfmt_format_set_text_attribute($formatter, NumberFormat::POSITIVE_PREFIX, "+");
|
||||
*
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @param integer $attr One of UNumberFormatTextAttribute constants
|
||||
* @param string $value Value of the attribute
|
||||
* @return false if attribute is unknown or can not be set, true otherwise
|
||||
*/
|
||||
function numfmt_set_text_attribute($formatter, $attribute, $value) {}
|
||||
/**
|
||||
* Set formatting symbol.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* $formatter->setSymbol(NumberFormat::EXPONENTIAL_SYMBOL, "E");
|
||||
*
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @param integer|array $attr One of UNumberFormatSymbol constants or array of symbols,
|
||||
* indexed by these constants
|
||||
* @param string $value Value of the symbol
|
||||
*/
|
||||
function numfmt_set_symbol($formatter, $attribute, $value) {}
|
||||
/**
|
||||
* Set pattern used by the formatter
|
||||
*
|
||||
* Valid only if the formatter is using pattern and is not rule-based.
|
||||
* @see http://www.icu-project.org/apiref/icu4c/classDecimalFormat.html
|
||||
* Localized patterns are not currently supported.
|
||||
*
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @param string $pattern The pattern to be used.
|
||||
* @return boolean false if formatter pattern could not be set, true otherwise
|
||||
*/
|
||||
function numfmt_set_pattern($formatter, $pattern) {}
|
||||
/**
|
||||
* Get value of the formatter attribute
|
||||
*
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @param integer $attribute One of UNumberFormatAttribute constants
|
||||
* @return integer|double value of the attribute or false if the value can not be obtained
|
||||
*/
|
||||
function numfmt_get_attribute($formatter, $attribute) {}
|
||||
/**
|
||||
* Get value of the formatter attribute
|
||||
*
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @param integer $attribute One of UNumberFormatTextAttribute constants
|
||||
* @return string value of the attribute or false if the value can not be obtained
|
||||
*/
|
||||
function numfmt_get_text_attribute($formatter, $attribute) {}
|
||||
/**
|
||||
* Get value of the formatter symbol
|
||||
*
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @param integer $attribute One of UNumberFormatSymbol constants specifying the symbol
|
||||
* @return string|false The symbol value, or false if the value can not be obtained
|
||||
*/
|
||||
function numfmt_get_symbol($formatter, $attribute) {}
|
||||
/**
|
||||
* Get pattern used by the formatter.
|
||||
*
|
||||
* Gets current state of the formatter as a pattern.
|
||||
* Localized patterns are not currently supported.
|
||||
*
|
||||
* Valid only if the formatter is UNUM_PATTERN_DECIMAL
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @return string|false The pattern used by the formatter or false if formatter is of a type
|
||||
* that does not support patterns.
|
||||
*/
|
||||
function numfmt_get_pattern($formatter) {}
|
||||
/**
|
||||
* Get the locale for which the formatter was created.
|
||||
*
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @param [integer] $type One of ULocDataLocaleType values
|
||||
* @return string locale name
|
||||
*/
|
||||
function numfmt_get_locale($formatter, $type = 0) {}
|
||||
/**
|
||||
* Get the error code from last operation
|
||||
*
|
||||
* Returns error code from the last number formatting operation.
|
||||
*
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @return integer the error code, one of UErrorCode values. Initial value is U_ZERO_ERROR.
|
||||
*/
|
||||
function numfmt_get_error_code($formatter) {}
|
||||
/**
|
||||
* Get the error text from the last operation.
|
||||
*
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @return string Description of the last occured error.
|
||||
*/
|
||||
function numfmt_get_error_message($formatter) {}
|
||||
|
||||
?>
|
132
ext/intl/doc/grapheme_api.php
Executable file
132
ext/intl/doc/grapheme_api.php
Executable file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
#############################################################################
|
||||
# Grapheme constants.
|
||||
#############################################################################
|
||||
|
||||
/**
|
||||
* grapheme_extract extract_type
|
||||
*
|
||||
*/
|
||||
/** Extract the given number of whole grapheme clusters from the string: */
|
||||
define('GRAPHEME_EXTR_COUNT', 0);
|
||||
/** Extract as many whole grapheme clusters as will fit into the given number of bytes: */
|
||||
define('GRAPHEME_EXTR_MAXBYTES', 1);
|
||||
/** Extract whole grapheme clusters up to a maximum number of UTF-8 characters: */
|
||||
define('GRAPHEME_EXTR_MAXCHARS', 2);
|
||||
|
||||
|
||||
#############################################################################
|
||||
# Grapheme API
|
||||
#############################################################################
|
||||
|
||||
/**
|
||||
* Get string length in grapheme units
|
||||
* @param string $input The string being measured for length.
|
||||
* @return int The length of the string on success, and 0 if the string is empty.
|
||||
*/
|
||||
function grapheme_strlen($input) {}
|
||||
|
||||
/**
|
||||
* Find position (in grapheme units) of first occurrence of a string
|
||||
* @param string $haystack The string to look in
|
||||
* @param string $needle The string to look for
|
||||
* @param [int] $offset The optional offset parameter allows you to specify
|
||||
which character in haystack to start searching. The position
|
||||
returned is still relative to the beginning of haystack.
|
||||
* @return int Returns the position as an integer. If needle is not found, strpos() will return boolean FALSE.
|
||||
*/
|
||||
function grapheme_strpos($haystack, $needle, $offset = 0) {}
|
||||
|
||||
|
||||
/**
|
||||
* Find position (in grapheme units) of first occurrence of a case-insensitive string
|
||||
* @param string $haystack The string to look in
|
||||
* @param string $needle The string to look for
|
||||
* @param [int] $offset The optional offset parameter allows you to specify
|
||||
which character in haystack to start searching. The position
|
||||
returned is still relative to the beginning of haystack.
|
||||
* @return int Returns the position as an integer. If needle is not found, grapheme_stripos() will return boolean FALSE.
|
||||
*/
|
||||
function grapheme_stripos($haystack, $needle, $offset = 0) {}
|
||||
|
||||
|
||||
/**
|
||||
* Find position (in grapheme units) of last occurrence of a string
|
||||
* @param string $haystack The string to look in
|
||||
* @param string $needle The string to look for
|
||||
* @param [int] $offset The optional offset parameter allows you to specify
|
||||
which character in haystack to start searching. The position
|
||||
returned is still relative to the beginning of haystack.
|
||||
* @return int Returns the position as an integer. If needle is not found, grapheme_strrpos() will return boolean FALSE.
|
||||
*/
|
||||
function grapheme_strrpos($haystack, $needle, $offset = 0) {}
|
||||
|
||||
|
||||
/**
|
||||
* Find position (in grapheme units) of last occurrence of a case-insensitive string
|
||||
* @param string $haystack The string to look in
|
||||
* @param string $needle The string to look for
|
||||
* @param [int] $offset The optional offset parameter allows you to specify
|
||||
which character in haystack to start searching. The position
|
||||
returned is still relative to the beginning of haystack.
|
||||
* @return int Returns the position as an integer. If needle is not found, grapheme_strripos() will return boolean FALSE.
|
||||
*/
|
||||
function grapheme_strripos($haystack, $needle, $offset = 0) {}
|
||||
|
||||
|
||||
/**
|
||||
* Return part of a string
|
||||
* @param string $string The input string.
|
||||
* @param int $start If start is non-negative, the returned string will start at the
|
||||
start'th position in string, counting from zero. If start is negative,
|
||||
the returned string will start at the start'th character from the
|
||||
end of string.
|
||||
* @param [int] $length If length is given and is positive, the string returned will contain
|
||||
at most length characters beginning from start (depending on the
|
||||
length of string). If string is less than or equal to start characters
|
||||
long, FALSE will be returned. If length is given and is negative, then
|
||||
that many characters will be omitted from the end of string (after the
|
||||
start position has been calculated when a start is negative). If start
|
||||
denotes a position beyond this truncation, an empty string will be returned.
|
||||
* @return int Returns the extracted part of string.
|
||||
*/
|
||||
function grapheme_substr($string, $start, $length = -1) {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns part of haystack string from the first occurrence of needle to the end of haystack.
|
||||
* @param string $haystack The input string.
|
||||
* @param string $needle The string to look for.
|
||||
* @param [boolean] $before_needle If TRUE (the default is FALSE), grapheme_strstr() returns the part of the
|
||||
haystack before the first occurence of the needle.
|
||||
* @return string Returns the portion of string, or FALSE if needle is not found.
|
||||
*/
|
||||
function grapheme_strstr($haystack, $needle, $before_needle = FALSE) {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns part of haystack string from the first occurrence of case-insensitive needle to the end of haystack.
|
||||
* @param string $haystack The input string.
|
||||
* @param string $needle The string to look for.
|
||||
* @param [boolean] $before_needle If TRUE (the default is FALSE), grapheme_strstr() returns the part of the
|
||||
haystack before the first occurence of the needle.
|
||||
* @return string Returns the portion of string, or FALSE if needle is not found.
|
||||
*/
|
||||
function grapheme_stristr($haystack, $needle, $before_needle = FALSE) {}
|
||||
|
||||
|
||||
/**
|
||||
* Function to extract a sequence of default grapheme clusters from a text buffer, which must be encoded in UTF-8.
|
||||
* @param string $haystack string to search
|
||||
* @param int $size maximum number of units - based on the $extract_type - to return
|
||||
* @param [int] $extract_type one of GRAPHEME_EXTR_COUNT (default), GRAPHEME_EXTR_MAXBYTES, or GRAPHEME_EXTR_MAXCHARS
|
||||
* @param [int] $start starting position in $haystack in bytes
|
||||
* @param [&int] $next set to next starting position in bytes
|
||||
* @return string A string starting at offset $start containing no more than $size grapheme clusters
|
||||
and ending on a default grapheme cluster boundary.
|
||||
*/
|
||||
function grapheme_extract($haystack, $size, $extract_type = GRAPHEME_EXTR_COUNT, $start = 0, &$next) {}
|
||||
|
||||
?>
|
||||
|
||||
|
432
ext/intl/doc/locale_api.php
Executable file
432
ext/intl/doc/locale_api.php
Executable file
@ -0,0 +1,432 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* A "Locale" is an identifier used to get language, culture, or regionally-specific
|
||||
* behavior from an API. PHP locales are organized and identified the same
|
||||
* way that the CLDR locales used by ICU (and many vendors of Unix-like operating
|
||||
* systems, the Mac, Java, and so forth) use. Locales are identified using
|
||||
* RFC 4646 language tags (which use hyphen, not underscore) in addition to the
|
||||
* more traditional underscore-using identifiers. Unless otherwise noted
|
||||
* the functions in this class are tolerant of both formats.
|
||||
*
|
||||
* Examples of identifiers include:
|
||||
*
|
||||
* * en-US (English, United States)
|
||||
* * zh-Hant-TW (Chinese, Traditional Script, Taiwan)
|
||||
* * fr-CA, fr-FR (French for Canada and France respectively)
|
||||
*
|
||||
* The Locale class (and related procedural functions) are used to interact
|
||||
* with locale identifiers--to verify that an ID is well-formed, valid,
|
||||
* etc. The extensions used by CLDR in UAX #35 (and inherited by ICU) are
|
||||
* valid and used wherever they would be in ICU normally.
|
||||
*
|
||||
* Locales cannot be instantiated as objects. All of the functions/methods
|
||||
* provided are static.
|
||||
*
|
||||
* * The null or empty string obtains the "root" locale.
|
||||
* The "root" locale is equivalent to "en_US_POSIX" in CLDR.
|
||||
* * Language tags (and thus locale identifiers) are case insensitive. There
|
||||
* exists a canonicalization function to make case match the specification.
|
||||
*
|
||||
* @see http://www.icu-project.org/apiref/icu4c/uloc_8h.html
|
||||
* @see http://www.unicode.org/reports/tr35/
|
||||
*
|
||||
*/
|
||||
class Locale {
|
||||
|
||||
#############################################################################
|
||||
# Common constants.
|
||||
#############################################################################
|
||||
|
||||
/**
|
||||
* The following static members are used with the getLocale methods of
|
||||
* the various locale affected classes, such as numfmt.
|
||||
*/
|
||||
const DEFAULT_LOCALE = default_locale;
|
||||
|
||||
/**
|
||||
* identifiers for the actual locale, valid locale
|
||||
* WARNING:
|
||||
* The values described here are NOT the actual values in PHP code.
|
||||
* They are references to the ICU C definitions, so the line
|
||||
* const ACTUAL_LOCALE = 'ULOC_ACTUAL_LOCALE';
|
||||
* actually means that Locale::ACTUAL_LOCALE is the same as
|
||||
* ULOC_ACTUAL_LOCALE constant in the ICU library.
|
||||
*/
|
||||
const ACTUAL_LOCALE = 'ULOC_ACTUAL_LOCALE';
|
||||
const VALID_LOCALE = 'ULOC_VALID_LOCALE';
|
||||
|
||||
/**
|
||||
* Valid locale tag and subtag values
|
||||
*/
|
||||
LANG_TAG = "language";
|
||||
EXTLANG_TAG = "extlang";
|
||||
SCRIPT_TAG = "script";
|
||||
REGION_TAG = "region";
|
||||
VARIANT_TAG = "variant";
|
||||
GRANDFATHERED_LANG_TAG = "grandfathered";
|
||||
PRIVATE_TAG = "private";
|
||||
|
||||
|
||||
#############################################################################
|
||||
# Object-oriented API
|
||||
#############################################################################
|
||||
|
||||
/**
|
||||
* Gets the default locale value from the INTL global 'default_locale'
|
||||
* At the PHP initilaization (MINIT) this value is set to
|
||||
* 'intl.default_locale' value from php.ini if that value exists
|
||||
* or from ICU's function uloc_getDefault()
|
||||
* Then onwards picks up changes from setDefault() calls also
|
||||
*
|
||||
* @return string the current runtime locale
|
||||
*/
|
||||
public static function getDefault() {}
|
||||
|
||||
/**
|
||||
* sets the default runtime locale to $locale
|
||||
* This changes the value of INTL global 'default_locale'
|
||||
*
|
||||
* @param string $locale is a BCP 47 compliant language tag containing the
|
||||
* locale identifier. UAX #35 extensions are accepted.
|
||||
* @return boolean 'true' if okay, 'false' if an error
|
||||
*/
|
||||
public static function setDefault($locale) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the primary language for the input locale
|
||||
*
|
||||
* @param string $locale the locale to extract the primary language code from
|
||||
* @return string the language code associated with the language
|
||||
* or null in case of error.
|
||||
*/
|
||||
public static function getPrimaryLanguage($locale) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the script for the input locale
|
||||
*
|
||||
* @param string $locale the locale to extract the script code from
|
||||
* @return string the script subtag for the locale or null if not present
|
||||
*/
|
||||
public static function getScript($locale) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the region for the input locale
|
||||
*
|
||||
* @param string $locale the locale to extract the region code from
|
||||
* @return string the region subtag for the locale or null if not present
|
||||
*/
|
||||
public static function getRegion($locale) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the variants for the input locale
|
||||
*
|
||||
* @param string $locale the locale to extract the variants from
|
||||
* @return array the array containing the list of all variants
|
||||
* subtag for the locale or null if not present
|
||||
*/
|
||||
public static function getAllVariants($locale) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the keywords for the input locale
|
||||
*
|
||||
* @param string $locale the locale to extract the keywords from
|
||||
* @return array associative array containing the keyword-value pairs for this locale
|
||||
*/
|
||||
public static function getKeywords($locale) {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an appropriately localized display name for the input locale
|
||||
*
|
||||
* @param string $locale the locale to return a displayname for
|
||||
* @param [string] $in_locale optional format locale
|
||||
* If is 'null' then the default locale is used.
|
||||
* @return string display name of the locale in the format
|
||||
* appropriate for $in_locale.
|
||||
*/
|
||||
public static function getDisplayName($locale, $in_locale = null) {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an appropriately localized display name for language of the input locale
|
||||
*
|
||||
* @param string $locale the locale to return a display language for
|
||||
* @param [string] $in_locale optional format locale to use to display the language name
|
||||
* If is 'null' then the default locale is used.
|
||||
* @return string display name of the language for the $locale in the format
|
||||
* appropriate for $in_locale.
|
||||
*/
|
||||
public static function getDisplayLanguage($lang, $in_locale = null) {}
|
||||
|
||||
/**
|
||||
* Returns an appropriately localized display name for script of the input locale
|
||||
*
|
||||
* @param string $locale the locale to return a display script for
|
||||
* @param [string] $in_locale optional format locale to use to display the script name
|
||||
* If is 'null' then the default locale is used.
|
||||
* @return string display name of the script for the $locale in the format
|
||||
* appropriate for $in_locale.
|
||||
*/
|
||||
public static function getDisplayScript($script, $in_locale = null) {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an appropriately localized display name for region of the input locale
|
||||
*
|
||||
* @param string $locale the locale to return a display region for
|
||||
* @param [string] $in_locale optional format locale to use to display the region name
|
||||
* If is 'null' then the default locale is used.
|
||||
* @return string display name of the region for the $locale in the format
|
||||
* appropriate for $in_locale.
|
||||
*/
|
||||
public static function getDisplayRegion($region, $in_locale = null) {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an appropriately localized display name for variants of the input locale
|
||||
*
|
||||
* @param string $locale the locale to return a display variant for
|
||||
* @param [string] $in_locale optional format locale to use to display the variant name
|
||||
* If is 'null' then the default locale is used.
|
||||
* @return string display name of the variant for the $locale in the format
|
||||
* appropriate for $in_locale.
|
||||
*/
|
||||
public static function getDisplayVariant($variant, $in_locale = null) {}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a $langtag filter matches with $locale according to
|
||||
* RFC 4647's basic filtering algorithm
|
||||
*
|
||||
* @param string $langtag the language tag to check
|
||||
* @param string $locale the language range to check against
|
||||
* @return boolean 'true' if $locale matches $langtag 'false' otherwise
|
||||
*/
|
||||
public static function filterMatches($langtag, $locale) {}
|
||||
|
||||
/**
|
||||
* Searchs the items in $langtag for the best match to the language
|
||||
* range specified in $locale according to RFC 4647's lookup algorithm.
|
||||
*
|
||||
* @param array $langtag an array containing a list of language tags to compare
|
||||
* to $locale
|
||||
* @param string $locale the locale to use as the language range when matching
|
||||
* @param string $default the locale to use if no match is found
|
||||
* @return string closest matching language tag, $default,
|
||||
* or empty string
|
||||
*/
|
||||
public static function lookup(array $langtag, $locale, $default = null) {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a correctly ordered and delimited locale ID
|
||||
*
|
||||
* @param array $subtags an array containing a list of key-value pairs, where
|
||||
* the keys identify the particular locale ID subtags,
|
||||
* and the values are the associated subtag values.
|
||||
*
|
||||
* @return string the corresponding locale identifier.
|
||||
*/
|
||||
public static function composeLocale(array $subtags) {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a key-value array of locale ID subtag elements.
|
||||
*
|
||||
* @param string $locale the locale to extract the subtag array from
|
||||
*
|
||||
* @return array $subtags an array containing a list of key-value pairs, where
|
||||
* the keys identify the particular locale ID subtags,
|
||||
* and the values are the associated subtag values.
|
||||
*/
|
||||
public static function parseLocale($locale) {}
|
||||
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
# Procedural API
|
||||
#############################################################################
|
||||
|
||||
|
||||
/**
|
||||
* Gets the default locale value from the INTL global 'default_locale'
|
||||
* At the PHP initilaization (MINIT) this value is set to
|
||||
* 'intl.default_locale' value from php.ini if that value exists
|
||||
* or from ICU's function uloc_getDefault()
|
||||
* Then onwards picks up changes from setDefault() calls also
|
||||
*
|
||||
* @return string the current runtime locale
|
||||
*/
|
||||
public static function locale_get_default() {}
|
||||
|
||||
/**
|
||||
* sets the default runtime locale to $locale
|
||||
* This changes the value of INTL global 'default_locale'
|
||||
*
|
||||
* @param string $locale is a BCP 47 compliant language tag containing the
|
||||
* locale identifier. UAX #35 extensions are accepted.
|
||||
* @return boolean 'true' if okay, 'false' if an error
|
||||
*/
|
||||
public static function locale_set_default($locale) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the primary language for the input locale
|
||||
*
|
||||
* @param string $locale the locale to extract the primary language code from
|
||||
* @return string the language code associated with the language
|
||||
* or null in case of error.
|
||||
*/
|
||||
public static function locale_get_primary_language($locale) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the script for the input locale
|
||||
*
|
||||
* @param string $locale the locale to extract the script code from
|
||||
* @return string the script subtag for the locale or null if not present
|
||||
*/
|
||||
public static function locale_get_script($locale) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the region for the input locale
|
||||
*
|
||||
* @param string $locale the locale to extract the region code from
|
||||
* @return string the region subtag for the locale or null if not present
|
||||
*/
|
||||
public static function locale_get_region($locale) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the variants for the input locale
|
||||
*
|
||||
* @param string $locale the locale to extract the variants from
|
||||
* @return array the array containing the list of all variants
|
||||
* subtag for the locale or null if not present
|
||||
*/
|
||||
public static function locale_get_all_variants($locale) {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the keywords for the input locale
|
||||
*
|
||||
* @param string $locale the locale to extract the keywords from
|
||||
* @return array associative array containing the keyword-value pairs for this locale
|
||||
*/
|
||||
public static function locale_get_keywords($locale) {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an appropriately localized display name for the input locale
|
||||
*
|
||||
* @param string $locale the locale to return a displayname for
|
||||
* @param [string] $in_locale optional format locale
|
||||
* If is 'null' then the default locale is used.
|
||||
* @return string display name of the locale in the format
|
||||
* appropriate for $in_locale.
|
||||
*/
|
||||
public static function locale_get_display_name($locale, $in_locale = null) {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an appropriately localized display name for language of the input locale
|
||||
*
|
||||
* @param string $locale the locale to return a display language for
|
||||
* @param [string] $in_locale optional format locale to use to display the language name
|
||||
* If is 'null' then the default locale is used.
|
||||
* @return string display name of the language for the $locale in the format
|
||||
* appropriate for $in_locale.
|
||||
*/
|
||||
public static function locale_get_display_language($lang, $in_locale = null) {}
|
||||
|
||||
/**
|
||||
* Returns an appropriately localized display name for script of the input locale
|
||||
*
|
||||
* @param string $locale the locale to return a display script for
|
||||
* @param [string] $in_locale optional format locale to use to display the script name
|
||||
* If is 'null' then the default locale is used.
|
||||
* @return string display name of the script for the $locale in the format
|
||||
* appropriate for $in_locale.
|
||||
*/
|
||||
public static function locale_get_display_script($script, $in_locale = null) {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an appropriately localized display name for region of the input locale
|
||||
*
|
||||
* @param string $locale the locale to return a display region for
|
||||
* @param [string] $in_locale optional format locale to use to display the region name
|
||||
* If is 'null' then the default locale is used.
|
||||
* @return string display name of the region for the $locale in the format
|
||||
* appropriate for $in_locale.
|
||||
*/
|
||||
public static function locale_get_display_region($region, $in_locale = null) {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an appropriately localized display name for variants of the input locale
|
||||
*
|
||||
* @param string $locale the locale to return a display variant for
|
||||
* @param [string] $in_locale optional format locale to use to display the variant name
|
||||
* If is 'null' then the default locale is used.
|
||||
* @return string display name of the variant for the $locale in the format
|
||||
* appropriate for $in_locale.
|
||||
*/
|
||||
public static function locale_get_display_variant($variant, $in_locale = null) {}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a $langtag filter matches with $locale according to
|
||||
* RFC 4647's basic filtering algorithm
|
||||
*
|
||||
* @param string $langtag the language tag to check
|
||||
* @param string $locale the language range to check against
|
||||
* @return boolean 'true' if $locale matches $langtag 'false' otherwise
|
||||
*/
|
||||
public static function locale_filter_matches($langtag, $locale) {}
|
||||
|
||||
/**
|
||||
* Searchs the items in $langtag for the best match to the language
|
||||
* range specified in $locale according to RFC 4647's lookup algorithm.
|
||||
*
|
||||
* @param array $langtag an array containing a list of language tags to compare
|
||||
* to $locale
|
||||
* @param string $locale the locale to use as the language range when matching
|
||||
* @param string $default the locale to use if no match is found
|
||||
* @return string closest matching language tag, $default,
|
||||
* or empty string
|
||||
*/
|
||||
public static function locale_lookup(array $langtag, $locale, $default = null) {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a correctly ordered and delimited locale ID
|
||||
*
|
||||
* @param array $subtags an array containing a list of key-value pairs, where
|
||||
* the keys identify the particular locale ID subtags,
|
||||
* and the values are the associated subtag values.
|
||||
*
|
||||
* @return string the corresponding locale identifier.
|
||||
*/
|
||||
public static function locale_compose_locale(array $subtags) {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a key-value array of locale ID subtag elements.
|
||||
*
|
||||
* @param string $locale the locale to extract the subtag array from
|
||||
*
|
||||
* @return array $subtags an array containing a list of key-value pairs, where
|
||||
* the keys identify the particular locale ID subtags,
|
||||
* and the values are the associated subtag values.
|
||||
*/
|
||||
public static function locale_parse_locale($locale) {}
|
||||
|
||||
?>
|
209
ext/intl/doc/msgfmt_api.php
Executable file
209
ext/intl/doc/msgfmt_api.php
Executable file
@ -0,0 +1,209 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Message formatter class.
|
||||
*
|
||||
* Message Format provides for runtime formatting of messages in a manner
|
||||
* somewhat similar to sprintf. The pattern string has its component parts
|
||||
* replaced in a locale-sensitive manner using items in the arguments array.
|
||||
*
|
||||
* @see http://www.icu-project.org/apiref/icu4c/umsg_8h.html
|
||||
*
|
||||
*/
|
||||
class MessageFormatter {
|
||||
|
||||
/**
|
||||
* Constructs a new Message Formatter
|
||||
*
|
||||
* @param string $locale the locale to use when formatting arguments
|
||||
* @param string $pattern the pattern string to stick arguments into
|
||||
*/
|
||||
public function __construct($locale, $pattern) {}
|
||||
|
||||
/**
|
||||
* Constructs a new Message Formatter
|
||||
*
|
||||
* @param string $locale the locale to use when formatting arguments
|
||||
* @param string $pattern the pattern string to stick arguments into
|
||||
*/
|
||||
public static function create($locale, $pattern) {}
|
||||
|
||||
/**
|
||||
* Format the message
|
||||
* @param array $args arguments to insert into the pattern string
|
||||
* @return string the formatted string, or false if an error ocurred
|
||||
*/
|
||||
public function format($args) {}
|
||||
|
||||
/**
|
||||
* Parse input string and returns any extracted items as an array
|
||||
*
|
||||
* $error will contain any error code. If an error occurs, $parse_pos contains
|
||||
* the position of the error.
|
||||
*
|
||||
* @param string $value string to parse for items
|
||||
* @return array array containing items extracted
|
||||
*
|
||||
*/
|
||||
public function parse($value) {}
|
||||
|
||||
/**
|
||||
* Inserts the items in $args into $pattern, formatting them
|
||||
* according to $locale. This is the static implementation.
|
||||
*
|
||||
* @param string $locale the locale to use when formatting numbers and dates and suchlike
|
||||
* @param string $pattern the pattern string to insert things into
|
||||
* @param array $args the array of values to insert into $pattern
|
||||
* @return string the formatted pattern string or false if an error occured
|
||||
*/
|
||||
public static function formatMessage($locale, $pattern, $args) {}
|
||||
|
||||
/**
|
||||
* parses input string and returns any extracted items as an array
|
||||
*
|
||||
* $error will contain any error code. If an error occurs, $parse_pos contains
|
||||
* the position of the error.
|
||||
*
|
||||
* @param string $locale the locale to use when formatting numbers and dates and suchlike
|
||||
* @param string $value string to parse for items
|
||||
* @return array array containing items extracted
|
||||
*
|
||||
*/
|
||||
public static function parseMessage($locale, $value) {}
|
||||
|
||||
/**
|
||||
* Get the pattern used by the formatter
|
||||
*
|
||||
* @return string the pattern string for this message formatter
|
||||
*/
|
||||
public function getPattern() {}
|
||||
|
||||
/**
|
||||
* Set the pattern used by the formatter
|
||||
*
|
||||
* @param string $pattern the pattern string to use in this message formatter
|
||||
* @return boolean 'true' if successful, 'false' if an error
|
||||
*/
|
||||
public function setPattern($pattern) {}
|
||||
|
||||
/**
|
||||
* Get the error code from last operation
|
||||
*
|
||||
* Returns error code from the last number formatting operation.
|
||||
*
|
||||
* @return integer the error code, one of UErrorCode values. Initial value is U_ZERO_ERROR.
|
||||
*/
|
||||
public function getErrorCode() {}
|
||||
/**
|
||||
* Get the error text from the last operation.
|
||||
*
|
||||
* @return string Description of the last error.
|
||||
*/
|
||||
public function getErrorMessage() {}
|
||||
/**
|
||||
* Get the locale for which the formatter was created.
|
||||
*
|
||||
* @return string locale name
|
||||
*/
|
||||
public function getLocale() {}
|
||||
}
|
||||
|
||||
/** Now the same as procedural API */
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new Message Formatter
|
||||
*
|
||||
* @param string $locale the locale to use when formatting arguments
|
||||
* @param string $pattern the pattern string to stick arguments into
|
||||
* @return MessageFormatter formatter object
|
||||
*/
|
||||
function msgfmt_create($locale, $pattern) {}
|
||||
|
||||
/**
|
||||
* Format the message
|
||||
* @param MessageFormatter $fmt The message formatter
|
||||
* @param array $args arguments to insert into the pattern string
|
||||
* @return string the formatted string, or false if an error ocurred
|
||||
*/
|
||||
function msgfmt_format($fmt, $args) {}
|
||||
|
||||
/**
|
||||
* parses input string and returns any extracted items as an array
|
||||
*
|
||||
* $error will contain any error code. If an error occurs, $parse_pos contains
|
||||
* the position of the error.
|
||||
*
|
||||
* @param MessageFormatter $fmt The message formatter
|
||||
* @param string $value string to parse for items
|
||||
* @return array array containing items extracted
|
||||
*
|
||||
*/
|
||||
function msgfmt_parse($fmt, $value) {}
|
||||
|
||||
/**
|
||||
* Inserts the items in $args into $pattern, formatting them
|
||||
* according to $locale. This is the static implementation.
|
||||
*
|
||||
* @param string $locale the locale to use when formatting numbers and dates and suchlike
|
||||
* @param string $pattern the pattern string to insert things into
|
||||
* @param array $args the array of values to insert into $pattern
|
||||
* @return string the formatted pattern string or false if an error occured
|
||||
*/
|
||||
function msgfmt_format_message($locale, $pattern, $args) {}
|
||||
|
||||
/**
|
||||
* parses input string and returns any extracted items as an array
|
||||
*
|
||||
* $error will contain any error code. If an error occurs, $parse_pos contains
|
||||
* the position of the error.
|
||||
*
|
||||
* @param string $locale the locale to use when formatting numbers and dates and suchlike
|
||||
* @param string $value string to parse for items
|
||||
* @return array array containing items extracted
|
||||
*
|
||||
*/
|
||||
function msgfmt_parse_message($locale, $value) {}
|
||||
|
||||
/**
|
||||
* Get the pattern used by the formatter
|
||||
*
|
||||
* @param MessageFormatter $fmt The message formatter
|
||||
* @return string the pattern string for this message formatter
|
||||
*/
|
||||
function msgfmt_get_pattern($fmt) {}
|
||||
|
||||
/**
|
||||
* Set the pattern used by the formatter
|
||||
*
|
||||
* @param MessageFormatter $fmt The message formatter
|
||||
* @param string $pattern the pattern string to use in this message formatter
|
||||
* @return boolean 'true' if successful, 'false' if an error
|
||||
*/
|
||||
function msgfmt_set_pattern($fmt, $pattern) {}
|
||||
|
||||
/**
|
||||
* Get the error code from last operation
|
||||
*
|
||||
* Returns error code from the last number formatting operation.
|
||||
*
|
||||
* @param MessageFormatter $fmt The message formatter
|
||||
* @return integer the error code, one of UErrorCode values. Initial value is U_ZERO_ERROR.
|
||||
*/
|
||||
function msgfmt_get_error_code($fmt) {}
|
||||
/**
|
||||
* Get the error text from the last operation.
|
||||
*
|
||||
* @param MessageFormatter $fmt The message formatter
|
||||
* @return string Description of the last error.
|
||||
*/
|
||||
function msgfmt_get_error_message($fmt) {}
|
||||
|
||||
/**
|
||||
* Get the locale for which the formatter was created.
|
||||
*
|
||||
* @param NumberFormatter $formatter The formatter resource
|
||||
* @return string locale name
|
||||
*/
|
||||
function msgfmt_get_locale($formatter) {}
|
||||
?>
|
92
ext/intl/doc/normalizer_api.php
Executable file
92
ext/intl/doc/normalizer_api.php
Executable file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
#############################################################################
|
||||
# Object-oriented API
|
||||
#############################################################################
|
||||
|
||||
/**
|
||||
* Normalizer class.
|
||||
*
|
||||
* Normalizer provides access to Unicode normalization of strings. This class consists
|
||||
* only of static methods. The iterator interface to normalizer is rarely used, so is
|
||||
* not provided here.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
*
|
||||
* </code>
|
||||
*
|
||||
* @see http://www.icu-project.org/apiref/icu4c/unorm_8h.html
|
||||
* @see http://www.icu-project.org/apiref/icu4c/classNormalizer.html
|
||||
*
|
||||
*/
|
||||
class Normalizer {
|
||||
#############################################################################
|
||||
# Common constants.
|
||||
#############################################################################
|
||||
|
||||
/**
|
||||
* Valid normalization form values.
|
||||
*
|
||||
* @see Normalizer::normalize()
|
||||
* @see Normalizer::isNormalize()
|
||||
* @see normalizer_normalize()
|
||||
* @see normalizer_is_normalized()
|
||||
*/
|
||||
const NONE = 1;
|
||||
/** Canonical decomposition. */
|
||||
const NFD = 2;
|
||||
const FORM_D = NFD;
|
||||
/** Compatibility decomposition. */
|
||||
const NFKD = 3;
|
||||
const FORM_KD = NFKD;
|
||||
/** Canonical decomposition followed by canonical composition. */
|
||||
const NFC = 4;
|
||||
const FORM_C = NFC;
|
||||
/** Compatibility decomposition followed by canonical composition. */
|
||||
const NFKC =5;
|
||||
const FORM_KC = NFKC;
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes the input provided and returns the normalized string
|
||||
* @param string $input The input string to normalize
|
||||
* @param [int] $form One of the normalization forms
|
||||
* @return string The normalized string or null if an error occurred.
|
||||
*/
|
||||
public static function normalize($input, $form = Normalizer::FORM_C) {}
|
||||
|
||||
/**
|
||||
* Checks if the provided string is already in the specified normalization form.
|
||||
* @param string $input The input string to normalize
|
||||
* @param [int] $form One of the normalization forms
|
||||
* @return boolean True if normalized, false otherwise or if there is an error
|
||||
*/
|
||||
public static function isNormalized($input, $form = Normalizer::FORM_C) {}
|
||||
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
# Procedural API
|
||||
#############################################################################
|
||||
|
||||
/**
|
||||
* Normalizes the input provided and returns the normalized string
|
||||
* @param string $input The input string to normalize
|
||||
* @param [int] $form One of the normalization forms
|
||||
* @return string The normalized string or null if an error occurred.
|
||||
*/
|
||||
function normalizer_normalize($input, $form = Normalizer::FORM_C) {}
|
||||
|
||||
/**
|
||||
* Checks if the provided string is already in the specified normalization form.
|
||||
* @param string $input The input string to normalize
|
||||
* @param [int] $form One of the normalization forms
|
||||
* @return boolean True if normalized, false otherwise or if there an error
|
||||
*/
|
||||
function normalizer_is_normalized($input, $form = Normalizer::FORM_C) {}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
152
ext/intl/formatter/formatter.c
Executable file
152
ext/intl/formatter/formatter.c
Executable file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unicode/utypes.h>
|
||||
#include <unicode/unum.h>
|
||||
#include <unicode/ustring.h>
|
||||
|
||||
#include "php_intl.h"
|
||||
#include "formatter_class.h"
|
||||
#include "formatter_format.h"
|
||||
|
||||
#if U_ICU_VERSION_MAJOR_NUM == 3 && U_ICU_VERSION_MINOR_NUM <= 4
|
||||
#define UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL 17
|
||||
#endif
|
||||
|
||||
/* {{{ formatter_register_constants
|
||||
* Register constants common for the both (OO and procedural)
|
||||
* APIs.
|
||||
*/
|
||||
void formatter_register_constants( INIT_FUNC_ARGS )
|
||||
{
|
||||
if( NumberFormatter_ce_ptr == NULL) {
|
||||
zend_error(E_ERROR, "NumberFormatter class not defined");
|
||||
}
|
||||
|
||||
#define FORMATTER_EXPOSE_CONST(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS)
|
||||
#define FORMATTER_EXPOSE_CLASS_CONST(x) zend_declare_class_constant_long( NumberFormatter_ce_ptr, ZEND_STRS( #x ) - 1, UNUM_##x TSRMLS_CC );
|
||||
#define FORMATTER_EXPOSE_CUSTOM_CLASS_CONST(name, value) zend_declare_class_constant_long( NumberFormatter_ce_ptr, ZEND_STRS( name ) - 1, value TSRMLS_CC );
|
||||
|
||||
// UNumberFormatStyle constants
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PATTERN_DECIMAL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( DECIMAL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( CURRENCY );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PERCENT );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( SCIENTIFIC );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( SPELLOUT );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( ORDINAL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( DURATION );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PATTERN_RULEBASED );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( IGNORE );
|
||||
|
||||
FORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "DEFAULT_STYLE", UNUM_DEFAULT );
|
||||
|
||||
/* workaround for ICU bug */
|
||||
#if U_ICU_VERSION_MAJOR_NUM == 3 && U_ICU_VERSION_MINOR_NUM < 8
|
||||
#define UNUM_ROUND_HALFEVEN UNUM_FOUND_HALFEVEN
|
||||
#endif
|
||||
|
||||
// UNumberFormatRoundingMode
|
||||
FORMATTER_EXPOSE_CLASS_CONST( ROUND_CEILING );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( ROUND_FLOOR );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( ROUND_DOWN );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( ROUND_UP );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( ROUND_HALFEVEN );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( ROUND_HALFDOWN );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( ROUND_HALFUP );
|
||||
|
||||
// UNumberFormatPadPosition
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PAD_BEFORE_PREFIX );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PAD_AFTER_PREFIX );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PAD_BEFORE_SUFFIX );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PAD_AFTER_SUFFIX );
|
||||
|
||||
// UNumberFormatAttribute
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PARSE_INT_ONLY );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( GROUPING_USED );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( DECIMAL_ALWAYS_SHOWN );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( MAX_INTEGER_DIGITS );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( MIN_INTEGER_DIGITS );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( INTEGER_DIGITS );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( MAX_FRACTION_DIGITS );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( MIN_FRACTION_DIGITS );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( FRACTION_DIGITS );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( MULTIPLIER );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( GROUPING_SIZE );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( ROUNDING_MODE );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( ROUNDING_INCREMENT );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( FORMAT_WIDTH );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PADDING_POSITION );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( SECONDARY_GROUPING_SIZE );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( SIGNIFICANT_DIGITS_USED );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( MIN_SIGNIFICANT_DIGITS );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( MAX_SIGNIFICANT_DIGITS );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( LENIENT_PARSE );
|
||||
|
||||
// UNumberFormatTextAttribute
|
||||
FORMATTER_EXPOSE_CLASS_CONST( POSITIVE_PREFIX );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( POSITIVE_SUFFIX );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( NEGATIVE_PREFIX );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( NEGATIVE_SUFFIX );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PADDING_CHARACTER );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( CURRENCY_CODE );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( DEFAULT_RULESET );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PUBLIC_RULESETS );
|
||||
|
||||
// UNumberFormatSymbol
|
||||
FORMATTER_EXPOSE_CLASS_CONST( DECIMAL_SEPARATOR_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( GROUPING_SEPARATOR_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PATTERN_SEPARATOR_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PERCENT_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( ZERO_DIGIT_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( DIGIT_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( MINUS_SIGN_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PLUS_SIGN_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( CURRENCY_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( INTL_CURRENCY_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( MONETARY_SEPARATOR_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( EXPONENTIAL_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PERMILL_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( PAD_ESCAPE_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( INFINITY_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( NAN_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( SIGNIFICANT_DIGIT_SYMBOL );
|
||||
FORMATTER_EXPOSE_CLASS_CONST( MONETARY_GROUPING_SEPARATOR_SYMBOL );
|
||||
|
||||
FORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "TYPE_DEFAULT", FORMAT_TYPE_DEFAULT );
|
||||
FORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "TYPE_INT32", FORMAT_TYPE_INT32 );
|
||||
FORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "TYPE_INT64", FORMAT_TYPE_INT64 );
|
||||
FORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "TYPE_DOUBLE", FORMAT_TYPE_DOUBLE );
|
||||
FORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "TYPE_CURRENCY", FORMAT_TYPE_CURRENCY );
|
||||
|
||||
#undef FORMATTER_EXPOSE_CUSTOM_CLASS_CONST
|
||||
#undef FORMATTER_EXPOSE_CLASS_CONST
|
||||
#undef FORMATTER_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
|
||||
*/
|
24
ext/intl/formatter/formatter.h
Executable file
24
ext/intl/formatter/formatter.h
Executable file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef FORMATTER_FORMATTER_H
|
||||
#define FORMATTER_FORMATTER_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
void formatter_register_constants( INIT_FUNC_ARGS );
|
||||
|
||||
#endif // FORMATTER_FORMATTER_H
|
443
ext/intl/formatter/formatter_attr.c
Executable file
443
ext/intl/formatter/formatter_attr.c
Executable file
@ -0,0 +1,443 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "php_intl.h"
|
||||
#include "formatter_class.h"
|
||||
#include "formatter_attr.h"
|
||||
#include "intl_convert.h"
|
||||
|
||||
#include <unicode/ustring.h>
|
||||
|
||||
/* {{{ proto mixed NumberFormatter::getAttribute( int $attr )
|
||||
* Get formatter attribute value. }}} */
|
||||
/* {{{ proto mixed numfmt_get_attribute( NumberFormatter $nf, int $attr )
|
||||
* Get formatter attribute value.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_get_attribute )
|
||||
{
|
||||
long attribute, value;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol",
|
||||
&object, NumberFormatter_ce_ptr, &attribute ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"numfmt_get_attribute: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
switch(attribute) {
|
||||
case UNUM_PARSE_INT_ONLY:
|
||||
case UNUM_GROUPING_USED:
|
||||
case UNUM_DECIMAL_ALWAYS_SHOWN:
|
||||
case UNUM_MAX_INTEGER_DIGITS:
|
||||
case UNUM_MIN_INTEGER_DIGITS:
|
||||
case UNUM_INTEGER_DIGITS:
|
||||
case UNUM_MAX_FRACTION_DIGITS:
|
||||
case UNUM_MIN_FRACTION_DIGITS:
|
||||
case UNUM_FRACTION_DIGITS:
|
||||
case UNUM_MULTIPLIER:
|
||||
case UNUM_GROUPING_SIZE:
|
||||
case UNUM_ROUNDING_MODE:
|
||||
case UNUM_FORMAT_WIDTH:
|
||||
case UNUM_PADDING_POSITION:
|
||||
case UNUM_SECONDARY_GROUPING_SIZE:
|
||||
case UNUM_SIGNIFICANT_DIGITS_USED:
|
||||
case UNUM_MIN_SIGNIFICANT_DIGITS:
|
||||
case UNUM_MAX_SIGNIFICANT_DIGITS:
|
||||
case UNUM_LENIENT_PARSE:
|
||||
value = unum_getAttribute(FORMATTER_OBJECT(nfo), attribute);
|
||||
if(value == -1) {
|
||||
INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR;
|
||||
} else {
|
||||
RETVAL_LONG(value);
|
||||
}
|
||||
break;
|
||||
case UNUM_ROUNDING_INCREMENT:
|
||||
{
|
||||
double value = unum_getDoubleAttribute(FORMATTER_OBJECT(nfo), attribute);
|
||||
if(value == -1) {
|
||||
INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR;
|
||||
} else {
|
||||
RETVAL_DOUBLE(value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error getting attribute value" );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string NumberFormatter::getTextAttribute( int $attr )
|
||||
* Get formatter attribute value. }}} */
|
||||
/* {{{ proto string numfmt_get_text_attribute( NumberFormatter $nf, int $attr )
|
||||
* Get formatter attribute value.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_get_text_attribute )
|
||||
{
|
||||
long attribute;
|
||||
UChar value_buf[64];
|
||||
int value_buf_size = USIZE( value_buf );
|
||||
UChar* value = value_buf;
|
||||
int length = 0;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol",
|
||||
&object, NumberFormatter_ce_ptr, &attribute ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"numfmt_get_text_attribute: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
length = unum_getTextAttribute( FORMATTER_OBJECT(nfo), attribute, value, value_buf_size, &INTL_DATA_ERROR_CODE(nfo) );
|
||||
if(INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR && length >= value_buf_size) {
|
||||
++length; // to avoid U_STRING_NOT_TERMINATED_WARNING
|
||||
INTL_DATA_ERROR_CODE(nfo) = U_ZERO_ERROR;
|
||||
value = eumalloc(length);
|
||||
length = unum_getTextAttribute( FORMATTER_OBJECT(nfo), attribute, value, length, &INTL_DATA_ERROR_CODE(nfo) );
|
||||
if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) {
|
||||
efree(value);
|
||||
value = value_buf;
|
||||
}
|
||||
}
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error getting attribute value" );
|
||||
|
||||
INTL_METHOD_RETVAL_UTF8( nfo, value, length, ( value != value_buf ) );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool NumberFormatter::setAttribute( int $attr, mixed $value )
|
||||
* Get formatter attribute value. }}} */
|
||||
/* {{{ proto bool numfmt_set_attribute( NumberFormatter $nf, int $attr, mixed $value )
|
||||
* Get formatter attribute value.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_set_attribute )
|
||||
{
|
||||
long attribute;
|
||||
zval **value;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OlZ",
|
||||
&object, NumberFormatter_ce_ptr, &attribute, &value ) == FAILURE)
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"numfmt_set_attribute: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
switch(attribute) {
|
||||
case UNUM_PARSE_INT_ONLY:
|
||||
case UNUM_GROUPING_USED:
|
||||
case UNUM_DECIMAL_ALWAYS_SHOWN:
|
||||
case UNUM_MAX_INTEGER_DIGITS:
|
||||
case UNUM_MIN_INTEGER_DIGITS:
|
||||
case UNUM_INTEGER_DIGITS:
|
||||
case UNUM_MAX_FRACTION_DIGITS:
|
||||
case UNUM_MIN_FRACTION_DIGITS:
|
||||
case UNUM_FRACTION_DIGITS:
|
||||
case UNUM_MULTIPLIER:
|
||||
case UNUM_GROUPING_SIZE:
|
||||
case UNUM_ROUNDING_MODE:
|
||||
case UNUM_FORMAT_WIDTH:
|
||||
case UNUM_PADDING_POSITION:
|
||||
case UNUM_SECONDARY_GROUPING_SIZE:
|
||||
case UNUM_SIGNIFICANT_DIGITS_USED:
|
||||
case UNUM_MIN_SIGNIFICANT_DIGITS:
|
||||
case UNUM_MAX_SIGNIFICANT_DIGITS:
|
||||
case UNUM_LENIENT_PARSE:
|
||||
convert_to_long_ex(value);
|
||||
unum_setAttribute(FORMATTER_OBJECT(nfo), attribute, Z_LVAL_PP(value));
|
||||
break;
|
||||
case UNUM_ROUNDING_INCREMENT:
|
||||
convert_to_double_ex(value);
|
||||
unum_setDoubleAttribute(FORMATTER_OBJECT(nfo), attribute, Z_DVAL_PP(value));
|
||||
break;
|
||||
default:
|
||||
INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error setting attribute value" );
|
||||
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool NumberFormatter::setTextAttribute( int $attr, string $value )
|
||||
* Get formatter attribute value. }}} */
|
||||
/* {{{ proto bool numfmt_set_text_attribute( NumberFormatter $nf, int $attr, string $value )
|
||||
* Get formatter attribute value.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_set_text_attribute )
|
||||
{
|
||||
int slength = 0;
|
||||
UChar *svalue = NULL;
|
||||
long attribute;
|
||||
char *value;
|
||||
int len;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ols",
|
||||
&object, NumberFormatter_ce_ptr, &attribute, &value, &len ) == FAILURE)
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"numfmt_set_text_attribute: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
// Convert given attribute value to UTF-16.
|
||||
intl_convert_utf8_to_utf16(&svalue, &slength, value, len, &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error converting attribute value to UTF-16" );
|
||||
|
||||
// Actually set new attribute value.
|
||||
unum_setTextAttribute(FORMATTER_OBJECT(nfo), attribute, svalue, slength, &INTL_DATA_ERROR_CODE(nfo));
|
||||
efree(svalue);
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error setting text attribute" );
|
||||
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string NumberFormatter::getSymbol( int $attr )
|
||||
* Get formatter symbol value. }}} */
|
||||
/* {{{ proto string numfmt_get_symbol( NumberFormatter $nf, int $attr )
|
||||
* Get formatter symbol value.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_get_symbol )
|
||||
{
|
||||
long symbol;
|
||||
UChar value_buf[4];
|
||||
UChar *value = value_buf;
|
||||
int length = USIZE(value);
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol",
|
||||
&object, NumberFormatter_ce_ptr, &symbol ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"numfmt_get_symbol: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
length = unum_getSymbol(FORMATTER_OBJECT(nfo), symbol, value_buf, length, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if(INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR && length >= USIZE( value )) {
|
||||
++length; // to avoid U_STRING_NOT_TERMINATED_WARNING
|
||||
INTL_DATA_ERROR_CODE(nfo) = U_ZERO_ERROR;
|
||||
value = eumalloc(length);
|
||||
length = unum_getSymbol(FORMATTER_OBJECT(nfo), symbol, value, length, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) {
|
||||
efree(value);
|
||||
value = value_buf;
|
||||
}
|
||||
}
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error getting symbol value" );
|
||||
|
||||
INTL_METHOD_RETVAL_UTF8( nfo, value, length, ( value_buf != value ) );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool NumberFormatter::setSymbol( int $attr, string $symbol )
|
||||
* Set formatter symbol value. }}} */
|
||||
/* {{{ proto bool numfmt_set_symbol( NumberFormatter $nf, int $attr, string $symbol )
|
||||
* Set formatter symbol value.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_set_symbol )
|
||||
{
|
||||
long symbol;
|
||||
char* value = NULL;
|
||||
int value_len = 0;
|
||||
UChar* svalue = 0;
|
||||
int slength = 0;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ols",
|
||||
&object, NumberFormatter_ce_ptr, &symbol, &value, &value_len ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"numfmt_set_symbol: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
// Convert given symbol to UTF-16.
|
||||
intl_convert_utf8_to_utf16(&svalue, &slength, value, value_len, &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error converting symbol value to UTF-16" );
|
||||
|
||||
// Actually set the symbol.
|
||||
unum_setSymbol(FORMATTER_OBJECT(nfo), symbol, svalue, slength, &INTL_DATA_ERROR_CODE(nfo));
|
||||
efree(svalue);
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error setting symbol value" );
|
||||
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string NumberFormatter::getPattern( )
|
||||
* Get formatter pattern. }}} */
|
||||
/* {{{ proto string numfmt_get_pattern( NumberFormatter $nf )
|
||||
* Get formatter pattern.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_get_pattern )
|
||||
{
|
||||
UChar value_buf[64];
|
||||
int length = USIZE( value_buf );
|
||||
UChar* value = value_buf;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
|
||||
&object, NumberFormatter_ce_ptr ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"numfmt_get_pattern: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
length = unum_toPattern(FORMATTER_OBJECT(nfo), 0, value, length, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if(INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR && length >= USIZE( value_buf )) {
|
||||
++length; // to avoid U_STRING_NOT_TERMINATED_WARNING
|
||||
INTL_DATA_ERROR_CODE(nfo) = U_ZERO_ERROR;
|
||||
value = eumalloc(length);
|
||||
length = unum_toPattern( FORMATTER_OBJECT(nfo), 0, value, length, &INTL_DATA_ERROR_CODE(nfo) );
|
||||
if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) {
|
||||
efree(value);
|
||||
value = value_buf;
|
||||
}
|
||||
}
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error getting formatter pattern" );
|
||||
|
||||
INTL_METHOD_RETVAL_UTF8( nfo, value, length, ( value != value_buf ) );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool NumberFormatter::setPattern( string $pattern )
|
||||
* Set formatter pattern. }}} */
|
||||
/* {{{ proto bool numfmt_set_pattern( NumberFormatter $nf, string $pattern )
|
||||
* Set formatter pattern.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_set_pattern )
|
||||
{
|
||||
char* value = NULL;
|
||||
int value_len = 0;
|
||||
int slength = 0;
|
||||
UChar* svalue = NULL;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os",
|
||||
&object, NumberFormatter_ce_ptr, &value, &value_len ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"numfmt_set_pattern: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
// Convert given pattern to UTF-16.
|
||||
intl_convert_utf8_to_utf16(&svalue, &slength, value, value_len, &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error converting pattern to UTF-16" );
|
||||
|
||||
// TODO: add parse error information
|
||||
unum_applyPattern(FORMATTER_OBJECT(nfo), 0, svalue, slength, NULL, &INTL_DATA_ERROR_CODE(nfo));
|
||||
efree(svalue);
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error setting pattern value" );
|
||||
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string NumberFormatter::getLocale([int type])
|
||||
* Get formatter locale. }}} */
|
||||
/* {{{ proto string numfmt_get_locale( NumberFormatter $nf[, int type] )
|
||||
* Get formatter locale.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_get_locale )
|
||||
{
|
||||
long type = ULOC_ACTUAL_LOCALE;
|
||||
char* loc;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l",
|
||||
&object, NumberFormatter_ce_ptr, &type ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"numfmt_get_locale: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
loc = (char *)unum_getLocaleByType(FORMATTER_OBJECT(nfo), type, &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error getting locale" );
|
||||
RETURN_STRING(loc, 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
32
ext/intl/formatter/formatter_attr.h
Executable file
32
ext/intl/formatter/formatter_attr.h
Executable file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef FORMATTER_ATTR_H
|
||||
#define FORMATTER_ATTR_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
PHP_FUNCTION( numfmt_set_attribute );
|
||||
PHP_FUNCTION( numfmt_get_attribute );
|
||||
PHP_FUNCTION( numfmt_set_text_attribute );
|
||||
PHP_FUNCTION( numfmt_get_text_attribute );
|
||||
PHP_FUNCTION( numfmt_set_symbol );
|
||||
PHP_FUNCTION( numfmt_get_symbol );
|
||||
PHP_FUNCTION( numfmt_set_pattern );
|
||||
PHP_FUNCTION( numfmt_get_pattern );
|
||||
PHP_FUNCTION( numfmt_get_locale );
|
||||
|
||||
#endif // FORMATTER_ATTR_H
|
147
ext/intl/formatter/formatter_class.c
Executable file
147
ext/intl/formatter/formatter_class.c
Executable file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include <unicode/unum.h>
|
||||
|
||||
#include "formatter_class.h"
|
||||
#include "php_intl.h"
|
||||
#include "formatter_data.h"
|
||||
#include "formatter_format.h"
|
||||
#include "formatter_parse.h"
|
||||
#include "formatter_main.h"
|
||||
#include "formatter_attr.h"
|
||||
|
||||
zend_class_entry *NumberFormatter_ce_ptr = NULL;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Auxiliary functions needed by objects of 'NumberFormatter' class
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* {{{ NumberFormatter_objects_dtor */
|
||||
static void NumberFormatter_object_dtor(
|
||||
void *object,
|
||||
zend_object_handle handle TSRMLS_DC )
|
||||
{
|
||||
zend_objects_destroy_object( object, handle TSRMLS_CC );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ NumberFormatter_objects_free */
|
||||
void NumberFormatter_object_free( zend_object *object TSRMLS_DC )
|
||||
{
|
||||
NumberFormatter_object* nfo = (NumberFormatter_object*)object;
|
||||
|
||||
zend_object_std_dtor( &nfo->zo TSRMLS_CC );
|
||||
|
||||
formatter_data_free( &nfo->nf_data TSRMLS_CC );
|
||||
|
||||
efree( nfo );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ NumberFormatter_object_create */
|
||||
zend_object_value NumberFormatter_object_create(
|
||||
zend_class_entry *ce TSRMLS_DC )
|
||||
{
|
||||
zend_object_value retval;
|
||||
NumberFormatter_object* intern;
|
||||
|
||||
intern = ecalloc( 1, sizeof(NumberFormatter_object) );
|
||||
formatter_data_init( &intern->nf_data TSRMLS_CC );
|
||||
zend_object_std_init( &intern->zo, ce TSRMLS_CC );
|
||||
|
||||
retval.handle = zend_objects_store_put(
|
||||
intern,
|
||||
NumberFormatter_object_dtor,
|
||||
(zend_objects_free_object_storage_t)NumberFormatter_object_free,
|
||||
NULL TSRMLS_CC );
|
||||
|
||||
retval.handlers = zend_get_std_object_handlers();
|
||||
|
||||
return retval;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// 'NumberFormatter' class registration structures & functions
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* {{{ NumberFormatter_class_functions
|
||||
* Every 'NumberFormatter' class method has an entry in this table
|
||||
*/
|
||||
static ZEND_BEGIN_ARG_INFO_EX( number_parse_arginfo, 0, 0, 1 )
|
||||
ZEND_ARG_INFO( 0, string )
|
||||
ZEND_ARG_INFO( 0, type )
|
||||
ZEND_ARG_INFO( 1, position )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static ZEND_BEGIN_ARG_INFO_EX( number_parse_currency_arginfo, 0, 0, 2 )
|
||||
ZEND_ARG_INFO( 0, string )
|
||||
ZEND_ARG_INFO( 1, currency )
|
||||
ZEND_ARG_INFO( 1, position )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static function_entry NumberFormatter_class_functions[] = {
|
||||
PHP_ME( NumberFormatter, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR )
|
||||
ZEND_FENTRY( create, ZEND_FN( numfmt_create ), NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
PHP_NAMED_FE( format, ZEND_FN( numfmt_format ), NULL )
|
||||
PHP_NAMED_FE( parse, ZEND_FN( numfmt_parse ), number_parse_arginfo )
|
||||
PHP_NAMED_FE( formatCurrency, ZEND_FN( numfmt_format_currency ), NULL )
|
||||
PHP_NAMED_FE( parseCurrency, ZEND_FN( numfmt_parse_currency ), number_parse_currency_arginfo )
|
||||
PHP_NAMED_FE( setAttribute, ZEND_FN( numfmt_set_attribute ), NULL )
|
||||
PHP_NAMED_FE( getAttribute, ZEND_FN( numfmt_get_attribute ), NULL )
|
||||
PHP_NAMED_FE( setTextAttribute, ZEND_FN( numfmt_set_text_attribute ), NULL )
|
||||
PHP_NAMED_FE( getTextAttribute, ZEND_FN( numfmt_get_text_attribute ), NULL )
|
||||
PHP_NAMED_FE( setSymbol, ZEND_FN( numfmt_set_symbol ), NULL )
|
||||
PHP_NAMED_FE( getSymbol, ZEND_FN( numfmt_get_symbol ), NULL )
|
||||
PHP_NAMED_FE( setPattern, ZEND_FN( numfmt_set_pattern ), NULL )
|
||||
PHP_NAMED_FE( getPattern, ZEND_FN( numfmt_get_pattern ), NULL )
|
||||
PHP_NAMED_FE( getLocale, ZEND_FN( numfmt_get_locale ), NULL )
|
||||
PHP_NAMED_FE( getErrorCode, ZEND_FN( numfmt_get_error_code ), NULL )
|
||||
PHP_NAMED_FE( getErrorMessage, ZEND_FN( numfmt_get_error_message ), NULL )
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
/* {{{ formatter_register_class
|
||||
* Initialize 'NumberFormatter' class
|
||||
*/
|
||||
void formatter_register_class( TSRMLS_D )
|
||||
{
|
||||
zend_class_entry ce;
|
||||
|
||||
// Create and register 'NumberFormatter' class.
|
||||
INIT_CLASS_ENTRY( ce, "NumberFormatter", NumberFormatter_class_functions );
|
||||
ce.create_object = NumberFormatter_object_create;
|
||||
NumberFormatter_ce_ptr = zend_register_internal_class( &ce TSRMLS_CC );
|
||||
|
||||
// Declare 'NumberFormatter' class properties.
|
||||
if( !NumberFormatter_ce_ptr )
|
||||
{
|
||||
zend_error(E_ERROR, "Failed to register NumberFormatter class");
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
41
ext/intl/formatter/formatter_class.h
Executable file
41
ext/intl/formatter/formatter_class.h
Executable file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef FORMATTER_CLASS_H
|
||||
#define FORMATTER_CLASS_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
#include "intl_common.h"
|
||||
#include "intl_error.h"
|
||||
#include "intl_data.h"
|
||||
#include "formatter_data.h"
|
||||
|
||||
typedef struct {
|
||||
zend_object zo;
|
||||
formatter_data nf_data;
|
||||
} NumberFormatter_object;
|
||||
|
||||
void formatter_register_class( TSRMLS_D );
|
||||
extern zend_class_entry *NumberFormatter_ce_ptr;
|
||||
|
||||
/* Auxiliary macros */
|
||||
|
||||
#define FORMATTER_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(NumberFormatter, nfo)
|
||||
#define FORMATTER_METHOD_FETCH_OBJECT INTL_METHOD_FETCH_OBJECT(NumberFormatter, nfo)
|
||||
#define FORMATTER_OBJECT(nfo) (nfo)->nf_data.unum
|
||||
|
||||
#endif // #ifndef FORMATTER_CLASS_H
|
72
ext/intl/formatter/formatter_data.c
Executable file
72
ext/intl/formatter/formatter_data.c
Executable file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "formatter_data.h"
|
||||
|
||||
/* {{{ void formatter_data_init( formatter_data* nf_data )
|
||||
* Initialize internals of formatter_data.
|
||||
*/
|
||||
void formatter_data_init( formatter_data* nf_data TSRMLS_DC )
|
||||
{
|
||||
if( !nf_data )
|
||||
return;
|
||||
|
||||
nf_data->unum = NULL;
|
||||
intl_error_reset( &nf_data->error TSRMLS_CC );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void formatter_data_free( formatter_data* nf_data )
|
||||
* Clean up mem allocted by internals of formatter_data
|
||||
*/
|
||||
void formatter_data_free( formatter_data* nf_data TSRMLS_DC )
|
||||
{
|
||||
if( !nf_data )
|
||||
return;
|
||||
|
||||
if( nf_data->unum )
|
||||
unum_close( nf_data->unum );
|
||||
|
||||
nf_data->unum = NULL;
|
||||
intl_error_reset( &nf_data->error TSRMLS_CC );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ formatter_data* formatter_data_create()
|
||||
* Alloc mem for formatter_data and initialize it with default values.
|
||||
*/
|
||||
formatter_data* formatter_data_create( TSRMLS_D )
|
||||
{
|
||||
formatter_data* nf_data = ecalloc( 1, sizeof(formatter_data) );
|
||||
|
||||
formatter_data_init( nf_data TSRMLS_CC );
|
||||
|
||||
return nf_data;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
38
ext/intl/formatter/formatter_data.h
Executable file
38
ext/intl/formatter/formatter_data.h
Executable file
@ -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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef FORMATTER_DATA_H
|
||||
#define FORMATTER_DATA_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
#include <unicode/unum.h>
|
||||
|
||||
#include "intl_error.h"
|
||||
|
||||
typedef struct {
|
||||
// error hangling
|
||||
intl_error error;
|
||||
|
||||
// formatter handling
|
||||
UNumberFormat* unum;
|
||||
} formatter_data;
|
||||
|
||||
formatter_data* formatter_data_create( TSRMLS_D );
|
||||
void formatter_data_init( formatter_data* nf_data TSRMLS_DC );
|
||||
void formatter_data_free( formatter_data* nf_data TSRMLS_DC );
|
||||
|
||||
#endif // FORMATTER_DATA_H
|
207
ext/intl/formatter/formatter_format.c
Executable file
207
ext/intl/formatter/formatter_format.c
Executable file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unicode/ustring.h>
|
||||
|
||||
#include "php_intl.h"
|
||||
#include "formatter_class.h"
|
||||
#include "formatter_format.h"
|
||||
#include "intl_convert.h"
|
||||
|
||||
/* {{{ proto mixed NumberFormatter::format( mixed $num[, int $type] )
|
||||
* Format a number. }}} */
|
||||
/* {{{ proto mixed numfmt_format( NumberFormatter $nf, mixed $num[, int type] )
|
||||
* Format a number.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_format )
|
||||
{
|
||||
zval **number;
|
||||
long type = FORMAT_TYPE_DEFAULT;
|
||||
UChar format_buf[32];
|
||||
UChar* formatted = format_buf;
|
||||
int formatted_len = USIZE(format_buf);
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OZ|l",
|
||||
&object, NumberFormatter_ce_ptr, &number, &type ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"numfmt_format: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
if(type == FORMAT_TYPE_DEFAULT) {
|
||||
if(Z_TYPE_PP(number) == IS_STRING) {
|
||||
SEPARATE_ZVAL_IF_NOT_REF(number);
|
||||
if ((Z_TYPE_PP(number)=is_numeric_string(Z_STRVAL_PP(number), Z_STRLEN_PP(number),
|
||||
&Z_LVAL_PP(number), &Z_DVAL_PP(number), 1)) == 0) {
|
||||
ZVAL_LONG(*number, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(Z_TYPE_PP(number) == IS_LONG) {
|
||||
// take INT32 on 32-bit, int64 on 64-bit
|
||||
type = (sizeof(long) == 8)?FORMAT_TYPE_INT64:FORMAT_TYPE_INT32;
|
||||
} else if(Z_TYPE_PP(number) == IS_DOUBLE) {
|
||||
type = FORMAT_TYPE_DOUBLE;
|
||||
} else {
|
||||
type = FORMAT_TYPE_INT32;
|
||||
}
|
||||
}
|
||||
|
||||
if(Z_TYPE_PP(number) != IS_DOUBLE && Z_TYPE_PP(number) != IS_LONG) {
|
||||
SEPARATE_ZVAL_IF_NOT_REF(number);
|
||||
convert_scalar_to_number( *number TSRMLS_CC );
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
case FORMAT_TYPE_INT32:
|
||||
convert_to_long_ex(number);
|
||||
formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)Z_LVAL_PP(number),
|
||||
formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) {
|
||||
intl_error_reset(INTL_DATA_ERROR_P(nfo) TSRMLS_CC);
|
||||
formatted = eumalloc(formatted_len);
|
||||
formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)Z_LVAL_PP(number),
|
||||
formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) {
|
||||
efree(formatted);
|
||||
}
|
||||
}
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" );
|
||||
break;
|
||||
|
||||
case FORMAT_TYPE_INT64:
|
||||
{
|
||||
int64_t value = (Z_TYPE_PP(number) == IS_DOUBLE)?(int64_t)Z_DVAL_PP(number):Z_LVAL_PP(number);
|
||||
formatted_len = unum_formatInt64(FORMATTER_OBJECT(nfo), value, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) {
|
||||
intl_error_reset(INTL_DATA_ERROR_P(nfo) TSRMLS_CC);
|
||||
formatted = eumalloc(formatted_len);
|
||||
formatted_len = unum_formatInt64(FORMATTER_OBJECT(nfo), value, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) {
|
||||
efree(formatted);
|
||||
}
|
||||
}
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" );
|
||||
}
|
||||
break;
|
||||
|
||||
case FORMAT_TYPE_DOUBLE:
|
||||
convert_to_double_ex(number);
|
||||
formatted_len = unum_formatDouble(FORMATTER_OBJECT(nfo), Z_DVAL_PP(number), formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) {
|
||||
intl_error_reset(INTL_DATA_ERROR_P(nfo) TSRMLS_CC);
|
||||
formatted = eumalloc(formatted_len);
|
||||
unum_formatDouble(FORMATTER_OBJECT(nfo), Z_DVAL_PP(number), formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) {
|
||||
efree(formatted);
|
||||
}
|
||||
}
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" );
|
||||
break;
|
||||
|
||||
default:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported format type %ld", type);
|
||||
RETURN_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
INTL_METHOD_RETVAL_UTF8( nfo, formatted, formatted_len, ( formatted != format_buf ) );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto mixed NumberFormatter::formatCurrency( double $num, string $currency )
|
||||
* Format a number as currency. }}} */
|
||||
/* {{{ proto mixed numfmt_format_currency( NumberFormatter $nf, double $num, string $currency )
|
||||
* Format a number as currency.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_format_currency )
|
||||
{
|
||||
double number;
|
||||
UChar format_buf[32];
|
||||
UChar* formatted = format_buf;
|
||||
int formatted_len = USIZE(format_buf);
|
||||
char* currency = NULL;
|
||||
int currency_len = 0;
|
||||
UChar* scurrency = NULL;
|
||||
int scurrency_len = 0;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ods",
|
||||
&object, NumberFormatter_ce_ptr, &number, ¤cy, ¤cy_len ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"numfmt_format_currency: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
// Convert currency to UTF-16.
|
||||
intl_convert_utf8_to_utf16(&scurrency, &scurrency_len, currency, currency_len, &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Currency conversion to UTF-16 failed" );
|
||||
|
||||
// Format the number using a fixed-length buffer.
|
||||
formatted_len = unum_formatDoubleCurrency(FORMATTER_OBJECT(nfo), number, scurrency, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
|
||||
|
||||
// If the buffer turned out to be too small
|
||||
// then allocate another buffer dynamically
|
||||
// and use it to format the number.
|
||||
if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) {
|
||||
intl_error_reset(INTL_DATA_ERROR_P(nfo) TSRMLS_CC);
|
||||
formatted = eumalloc(formatted_len);
|
||||
unum_formatDoubleCurrency(FORMATTER_OBJECT(nfo), number, scurrency, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
|
||||
}
|
||||
|
||||
if( U_FAILURE( INTL_DATA_ERROR_CODE((nfo)) ) ) {
|
||||
intl_error_set_code( NULL, INTL_DATA_ERROR_CODE((nfo)) TSRMLS_CC );
|
||||
intl_errors_set_custom_msg( INTL_DATA_ERROR_P(nfo), "Number formatting failed", 0 TSRMLS_CC );
|
||||
RETVAL_FALSE;
|
||||
if (formatted != format_buf) {
|
||||
efree(formatted);
|
||||
}
|
||||
} else {
|
||||
INTL_METHOD_RETVAL_UTF8( nfo, formatted, formatted_len, ( formatted != format_buf ) );
|
||||
}
|
||||
|
||||
if(scurrency) {
|
||||
efree(scurrency);
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
31
ext/intl/formatter/formatter_format.h
Executable file
31
ext/intl/formatter/formatter_format.h
Executable file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef FORMATTER_FORMAT_H
|
||||
#define FORMATTER_FORMAT_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
PHP_FUNCTION( numfmt_format );
|
||||
PHP_FUNCTION( numfmt_format_currency );
|
||||
|
||||
#define FORMAT_TYPE_DEFAULT 0
|
||||
#define FORMAT_TYPE_INT32 1
|
||||
#define FORMAT_TYPE_INT64 2
|
||||
#define FORMAT_TYPE_DOUBLE 3
|
||||
#define FORMAT_TYPE_CURRENCY 4
|
||||
|
||||
#endif // FORMATTER_FORMAT_H
|
220
ext/intl/formatter/formatter_main.c
Executable file
220
ext/intl/formatter/formatter_main.c
Executable file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unicode/ustring.h>
|
||||
|
||||
#include "php_intl.h"
|
||||
#include "formatter_class.h"
|
||||
#include "intl_convert.h"
|
||||
|
||||
/* {{{ proto NumberFormatter NumberFormatter::create( string $locale, int style[, string $pattern ] )
|
||||
* Create formatter. }}} */
|
||||
/* {{{ proto NumberFormatter numfmt_create( string $locale, int style[, string $pattern ] )
|
||||
* Create formatter.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_create )
|
||||
{
|
||||
char* locale;
|
||||
char* pattern = NULL;
|
||||
int locale_len = 0, pattern_len = 0;
|
||||
long style;
|
||||
UChar* spattern = NULL;
|
||||
int spattern_len = 0;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "sl|s",
|
||||
&locale, &locale_len, &style, &pattern, &pattern_len ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"numfmt_create: unable to parse input parameters", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
INTL_CHECK_LOCALE_LEN(locale_len);
|
||||
// Create a NumberFormatter object and save the ICU formatter into it.
|
||||
if( ( object = getThis() ) == NULL )
|
||||
object = return_value;
|
||||
|
||||
if( Z_TYPE_P( object ) != IS_OBJECT )
|
||||
object_init_ex( object, NumberFormatter_ce_ptr );
|
||||
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
// Convert pattern (if specified) to UTF-16.
|
||||
if(pattern && pattern_len) {
|
||||
intl_convert_utf8_to_utf16(&spattern, &spattern_len, pattern, pattern_len, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if( U_FAILURE( INTL_DATA_ERROR_CODE((nfo)) ) )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"numfmt_create: error converting pattern to UTF-16", 0 TSRMLS_CC );
|
||||
zval_dtor(return_value);
|
||||
RETURN_NULL();
|
||||
}
|
||||
}
|
||||
|
||||
if(locale_len == 0) {
|
||||
locale = INTL_G(default_locale);
|
||||
}
|
||||
|
||||
// Create an ICU number formatter.
|
||||
FORMATTER_OBJECT(nfo) = unum_open(style, spattern, spattern_len, locale, NULL, &INTL_DATA_ERROR_CODE(nfo));
|
||||
|
||||
if(spattern) {
|
||||
efree(spattern);
|
||||
}
|
||||
|
||||
if( U_FAILURE( INTL_DATA_ERROR_CODE((nfo)) ) )
|
||||
{
|
||||
intl_error_set( NULL, INTL_DATA_ERROR_CODE( nfo ),
|
||||
"numfmt_create: number formatter creation failed", 0 TSRMLS_CC );
|
||||
zval_dtor(return_value);
|
||||
RETURN_NULL();
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto void NumberFormatter::__construct( string $locale, int style[, string $pattern ] )
|
||||
* NumberFormatter object constructor.
|
||||
*/
|
||||
PHP_METHOD( NumberFormatter, __construct )
|
||||
{
|
||||
char* locale;
|
||||
char* pattern = NULL;
|
||||
int locale_len = 0, pattern_len = 0;
|
||||
long style;
|
||||
UChar* spattern = NULL;
|
||||
int spattern_len = 0;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
object = getThis();
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "sl|s",
|
||||
&locale, &locale_len, &style, &pattern, &pattern_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);
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
// Convert pattern (if specified) to UTF-16.
|
||||
if(pattern && pattern_len) {
|
||||
intl_convert_utf8_to_utf16(&spattern, &spattern_len, pattern, pattern_len, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if( U_FAILURE( INTL_DATA_ERROR_CODE((nfo)) ) )
|
||||
{
|
||||
intl_error_set( NULL, INTL_DATA_ERROR_CODE( nfo ),
|
||||
"__construct: Error converting pattern to UTF-16", 0 TSRMLS_CC );
|
||||
zval_dtor(object);
|
||||
ZVAL_NULL(object);
|
||||
RETURN_NULL();
|
||||
}
|
||||
}
|
||||
|
||||
if(locale_len == 0) {
|
||||
locale = INTL_G(default_locale);
|
||||
}
|
||||
|
||||
// Create an ICU number formatter.
|
||||
FORMATTER_OBJECT(nfo) = unum_open(style, spattern, spattern_len, locale, NULL, &INTL_DATA_ERROR_CODE(nfo));
|
||||
|
||||
if(spattern) {
|
||||
efree(spattern);
|
||||
}
|
||||
|
||||
if( U_FAILURE( INTL_DATA_ERROR_CODE((nfo)) ) )
|
||||
{
|
||||
intl_error_set( NULL, INTL_DATA_ERROR_CODE( nfo ),
|
||||
"__construct: number formatter creation failed", 0 TSRMLS_CC );
|
||||
zval_dtor(object);
|
||||
ZVAL_NULL(object);
|
||||
RETURN_NULL();
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int NumberFormatter::getErrorCode()
|
||||
* Get formatter's last error code. }}} */
|
||||
/* {{{ proto int numfmt_get_error_code( NumberFormatter $nf )
|
||||
* Get formatter's last error code.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_get_error_code )
|
||||
{
|
||||
FORMATTER_METHOD_INIT_VARS
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
|
||||
&object, NumberFormatter_ce_ptr ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"numfmt_get_error_code: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
nfo = (NumberFormatter_object *) zend_object_store_get_object( object TSRMLS_CC );
|
||||
|
||||
// Return formatter's last error code.
|
||||
RETURN_LONG( INTL_DATA_ERROR_CODE(nfo) );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string NumberFormatter::getErrorMessage( )
|
||||
* Get text description for formatter's last error code. }}} */
|
||||
/* {{{ proto string numfmt_get_error_message( NumberFormatter $nf )
|
||||
* Get text description for formatter's last error code.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_get_error_message )
|
||||
{
|
||||
char* message = NULL;
|
||||
FORMATTER_METHOD_INIT_VARS
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
|
||||
&object, NumberFormatter_ce_ptr ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"numfmt_get_error_message: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
nfo = (NumberFormatter_object *) zend_object_store_get_object( object TSRMLS_CC );
|
||||
|
||||
// Return last error message.
|
||||
message = intl_error_get_message( &INTL_DATA_ERROR(nfo) TSRMLS_CC );
|
||||
RETURN_STRING( message, 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
|
||||
*/
|
27
ext/intl/formatter/formatter_main.h
Executable file
27
ext/intl/formatter/formatter_main.h
Executable file
@ -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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef FORMATTER_MAIN_H
|
||||
#define FORMATTER_MAIN_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
PHP_FUNCTION( numfmt_create );
|
||||
PHP_FUNCTION( numfmt_get_error_code );
|
||||
PHP_FUNCTION( numfmt_get_error_message );
|
||||
PHP_METHOD( NumberFormatter, __construct );
|
||||
|
||||
#endif // FORMATTER_FORMAT_H
|
173
ext/intl/formatter/formatter_parse.c
Executable file
173
ext/intl/formatter/formatter_parse.c
Executable file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unicode/ustring.h>
|
||||
|
||||
#include "php_intl.h"
|
||||
#include "formatter_class.h"
|
||||
#include "formatter_format.h"
|
||||
#include "formatter_parse.h"
|
||||
#include "intl_convert.h"
|
||||
|
||||
/* {{{ proto mixed NumberFormatter::parse( string $str[, int $type, int &$position ])
|
||||
* Parse a number. }}} */
|
||||
/* {{{ proto mixed numfmt_parse( NumberFormatter $nf, string $str[, int $type, int &$position ])
|
||||
* Parse a number.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_parse )
|
||||
{
|
||||
long type = FORMAT_TYPE_DOUBLE;
|
||||
UChar* sstr = NULL;
|
||||
int sstr_len = 0;
|
||||
char* str = NULL;
|
||||
int str_len;
|
||||
int32_t val32, position = 0;
|
||||
int64_t val64;
|
||||
double val_double;
|
||||
int32_t* position_p = NULL;
|
||||
zval *zposition = NULL;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|lz!",
|
||||
&object, NumberFormatter_ce_ptr, &str, &str_len, &type, &zposition ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"number_parse: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
// Convert given string to UTF-16.
|
||||
intl_convert_utf8_to_utf16(&sstr, &sstr_len, str, str_len, &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" );
|
||||
|
||||
if(zposition) {
|
||||
convert_to_long(zposition);
|
||||
position = (int32_t)Z_LVAL_P( zposition );
|
||||
position_p = &position;
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
case FORMAT_TYPE_INT32:
|
||||
val32 = unum_parse(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo));
|
||||
RETVAL_LONG(val32);
|
||||
break;
|
||||
case FORMAT_TYPE_INT64:
|
||||
val64 = unum_parseInt64(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if(val64 > LONG_MAX || val64 < -LONG_MAX) {
|
||||
RETVAL_DOUBLE(val64);
|
||||
} else {
|
||||
val32 = (int32_t)val64;
|
||||
RETVAL_LONG(val32);
|
||||
}
|
||||
break;
|
||||
case FORMAT_TYPE_DOUBLE:
|
||||
val_double = unum_parseDouble(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo));
|
||||
RETVAL_DOUBLE(val_double);
|
||||
break;
|
||||
default:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported format type %ld", type);
|
||||
RETVAL_FALSE;
|
||||
break;
|
||||
}
|
||||
if(zposition) {
|
||||
zval_dtor(zposition);
|
||||
ZVAL_LONG(zposition, position);
|
||||
}
|
||||
|
||||
efree(sstr);
|
||||
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Number parsing failed" );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto double NumberFormatter::parseCurrency( string $str, string $¤cy[, int $&position] )
|
||||
* Parse a number as currency. }}} */
|
||||
/* {{{ proto double numfmt_parse_currency( NumberFormatter $nf, string $str, string $¤cy[, int $&position] )
|
||||
* Parse a number as currency.
|
||||
*/
|
||||
PHP_FUNCTION( numfmt_parse_currency )
|
||||
{
|
||||
double number;
|
||||
UChar currency[5] = {0};
|
||||
UChar* sstr = NULL;
|
||||
int sstr_len = 0;
|
||||
char *currency_str = NULL;
|
||||
int currency_len = 0;
|
||||
char *str;
|
||||
int str_len;
|
||||
int32_t* position_p = NULL;
|
||||
int32_t position = 0;
|
||||
zval *zcurrency, *zposition = NULL;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Osz|z!",
|
||||
&object, NumberFormatter_ce_ptr, &str, &str_len, &zcurrency, &zposition ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"number_parse_currency: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
// Convert given string to UTF-16.
|
||||
intl_convert_utf8_to_utf16(&sstr, &sstr_len, str, str_len, &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" );
|
||||
|
||||
if(zposition) {
|
||||
convert_to_long(zposition);
|
||||
position = (int32_t)Z_LVAL_P( zposition );
|
||||
position_p = &position;
|
||||
}
|
||||
|
||||
number = unum_parseDoubleCurrency(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, currency, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if(zposition) {
|
||||
zval_dtor(zposition);
|
||||
ZVAL_LONG(zposition, position);
|
||||
}
|
||||
efree(sstr);
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Number parsing failed" );
|
||||
|
||||
// Convert parsed currency to UTF-8 and pass it back to caller.
|
||||
intl_convert_utf16_to_utf8(¤cy_str, ¤cy_len, currency, u_strlen(currency), &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Currency conversion to UTF-8 failed" );
|
||||
zval_dtor( zcurrency );
|
||||
ZVAL_STRINGL(zcurrency, currency_str, currency_len, 0);
|
||||
|
||||
RETVAL_DOUBLE( number );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
25
ext/intl/formatter/formatter_parse.h
Executable file
25
ext/intl/formatter/formatter_parse.h
Executable file
@ -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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef FORMATTER_PARSE_H
|
||||
#define FORMATTER_PARSE_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
PHP_FUNCTION( numfmt_parse );
|
||||
PHP_FUNCTION( numfmt_parse_currency );
|
||||
|
||||
#endif // FORMATTER_PARSE_H
|
37
ext/intl/grapheme/grapheme.h
Executable file
37
ext/intl/grapheme/grapheme.h
Executable file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Ed Batutis <ed@batutis.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef GRAPHEME_GRAPHEME_H
|
||||
#define GRAPHEME_GRAPHEME_H
|
||||
|
||||
#include <php.h>
|
||||
#include <unicode/utypes.h>
|
||||
#include <unicode/ubrk.h>
|
||||
|
||||
PHP_FUNCTION(grapheme_strlen);
|
||||
PHP_FUNCTION(grapheme_strpos);
|
||||
PHP_FUNCTION(grapheme_stripos);
|
||||
PHP_FUNCTION(grapheme_strrpos);
|
||||
PHP_FUNCTION(grapheme_strripos);
|
||||
PHP_FUNCTION(grapheme_substr);
|
||||
PHP_FUNCTION(grapheme_strstr);
|
||||
PHP_FUNCTION(grapheme_stristr);
|
||||
PHP_FUNCTION(grapheme_extract);
|
||||
|
||||
void grapheme_register_constants( INIT_FUNC_ARGS );
|
||||
void grapheme_close_global_iterator( TSRMLS_D );
|
||||
|
||||
#endif // GRAPHEME_GRAPHEME_H
|
913
ext/intl/grapheme/grapheme_string.c
Executable file
913
ext/intl/grapheme/grapheme_string.c
Executable file
@ -0,0 +1,913 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Ed Batutis <ed@batutis.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* {{{ includes */
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <php.h>
|
||||
#include "grapheme.h"
|
||||
#include "grapheme_util.h"
|
||||
|
||||
#include <unicode/utypes.h>
|
||||
#include <unicode/ucol.h>
|
||||
#include <unicode/ustring.h>
|
||||
#include <unicode/ubrk.h>
|
||||
|
||||
#include "ext/standard/php_string.h"
|
||||
|
||||
/* }}} */
|
||||
|
||||
#define GRAPHEME_EXTRACT_TYPE_COUNT 0
|
||||
#define GRAPHEME_EXTRACT_TYPE_MAXBYTES 1
|
||||
#define GRAPHEME_EXTRACT_TYPE_MAXCHARS 2
|
||||
#define GRAPHEME_EXTRACT_TYPE_MIN GRAPHEME_EXTRACT_TYPE_COUNT
|
||||
#define GRAPHEME_EXTRACT_TYPE_MAX GRAPHEME_EXTRACT_TYPE_MAXCHARS
|
||||
|
||||
|
||||
/* {{{ grapheme_register_constants
|
||||
* Register API constants
|
||||
*/
|
||||
void grapheme_register_constants( INIT_FUNC_ARGS )
|
||||
{
|
||||
REGISTER_LONG_CONSTANT("GRAPHEME_EXTR_COUNT", GRAPHEME_EXTRACT_TYPE_COUNT, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("GRAPHEME_EXTR_MAXBYTES", GRAPHEME_EXTRACT_TYPE_MAXBYTES, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("GRAPHEME_EXTR_MAXCHARS", GRAPHEME_EXTRACT_TYPE_MAXCHARS, CONST_CS | CONST_PERSISTENT);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int grapheme_strlen(string str)
|
||||
Get number of graphemes in a string */
|
||||
PHP_FUNCTION(grapheme_strlen)
|
||||
{
|
||||
unsigned char* string;
|
||||
int string_len;
|
||||
UChar* ustring = NULL;
|
||||
int ustring_len = 0;
|
||||
int ret_len;
|
||||
UErrorCode status;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", (char **)&string, &string_len) == FAILURE) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"grapheme_strlen: unable to parse input param", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
ret_len = grapheme_ascii_check(string, string_len);
|
||||
|
||||
if ( ret_len >= 0 )
|
||||
RETURN_LONG(ret_len);
|
||||
|
||||
/* convert the string to UTF-16. */
|
||||
status = U_ZERO_ERROR;
|
||||
intl_convert_utf8_to_utf16(&ustring, &ustring_len, (char*) string, string_len, &status );
|
||||
|
||||
if ( U_FAILURE( status ) ) {
|
||||
/* Set global error code. */
|
||||
intl_error_set_code( NULL, status TSRMLS_CC );
|
||||
|
||||
/* Set error messages. */
|
||||
intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 1 TSRMLS_CC );
|
||||
efree( ustring );
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
ret_len = grapheme_split_string(ustring, ustring_len, NULL, 0 TSRMLS_CC );
|
||||
|
||||
efree( ustring );
|
||||
|
||||
if (ret_len >= 0) {
|
||||
RETVAL_LONG(ret_len);
|
||||
} else {
|
||||
RETVAL_FALSE;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int grapheme_strpos(string haystack, string needle [, int offset ])
|
||||
Find position of first occurrence of a string within another */
|
||||
PHP_FUNCTION(grapheme_strpos)
|
||||
{
|
||||
unsigned char *haystack, *needle;
|
||||
int haystack_len, needle_len;
|
||||
unsigned char *found;
|
||||
long loffset = 0;
|
||||
int32_t offset = 0;
|
||||
int ret_pos, uchar_pos;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", (char **)&haystack, &haystack_len, (char **)&needle, &needle_len, &loffset) == FAILURE) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"grapheme_strpos: unable to parse input param", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if ( OUTSIDE_STRING(loffset, haystack_len) ) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_strpos: Offset not contained in string", 1 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* we checked that it will fit: */
|
||||
offset = (int32_t) loffset;
|
||||
|
||||
/* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */
|
||||
|
||||
if (needle_len == 0) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_strpos: Empty delimiter", 1 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* quick check to see if the string might be there
|
||||
* I realize that 'offset' is 'grapheme count offset' but will work in spite of that
|
||||
*/
|
||||
found = (unsigned char *)php_memnstr((char *)haystack + offset, (char *)needle, needle_len, (char *)haystack + haystack_len);
|
||||
|
||||
/* if it isn't there the we are done */
|
||||
if (!found) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* if it is there, and if the haystack is ascii, we are all done */
|
||||
if ( grapheme_ascii_check(haystack, haystack_len) >= 0 ) {
|
||||
|
||||
RETURN_LONG(found - haystack);
|
||||
}
|
||||
|
||||
/* do utf16 part of the strpos */
|
||||
ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, &uchar_pos, 0 /* fIgnoreCase */ TSRMLS_CC );
|
||||
|
||||
if ( ret_pos >= 0 ) {
|
||||
RETURN_LONG(ret_pos + offset);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int grapheme_stripos(string haystack, string needle [, int offset ])
|
||||
Find position of first occurrence of a string within another, ignoring case differences */
|
||||
PHP_FUNCTION(grapheme_stripos)
|
||||
{
|
||||
unsigned char *haystack, *needle, *haystack_dup, *needle_dup;
|
||||
int haystack_len, needle_len;
|
||||
unsigned char *found;
|
||||
long loffset = 0;
|
||||
int32_t offset = 0;
|
||||
int ret_pos, uchar_pos;
|
||||
int is_ascii;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", (char **)&haystack, &haystack_len, (char **)&needle, &needle_len, &loffset) == FAILURE) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"grapheme_stripos: unable to parse input param", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if ( OUTSIDE_STRING(loffset, haystack_len) ) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_stripos: Offset not contained in string", 1 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* we checked that it will fit: */
|
||||
offset = (int32_t) loffset;
|
||||
|
||||
/* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */
|
||||
|
||||
if (needle_len == 0) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_stripos: Empty delimiter", 1 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
is_ascii = ( grapheme_ascii_check(haystack, haystack_len) >= 0 );
|
||||
|
||||
if ( is_ascii ) {
|
||||
needle_dup = (unsigned char *)estrndup((char *)needle, needle_len);
|
||||
php_strtolower((char *)needle_dup, needle_len);
|
||||
haystack_dup = (unsigned char *)estrndup((char *)haystack, haystack_len);
|
||||
php_strtolower((char *)haystack_dup, haystack_len);
|
||||
|
||||
found = (unsigned char*) php_memnstr((char *)haystack_dup + offset, (char *)needle_dup, needle_len, (char *)haystack_dup + haystack_len);
|
||||
|
||||
efree(haystack_dup);
|
||||
efree(needle_dup);
|
||||
|
||||
if (found) {
|
||||
RETURN_LONG(found - haystack_dup);
|
||||
}
|
||||
|
||||
/* if needle was ascii too, we are all done, otherwise we need to try using Unicode to see what we get */
|
||||
if ( grapheme_ascii_check(needle, needle_len) >= 0 ) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* do utf16 part of the strpos */
|
||||
ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, &uchar_pos, 1 /* fIgnoreCase */ TSRMLS_CC );
|
||||
|
||||
if ( ret_pos >= 0 ) {
|
||||
RETURN_LONG(ret_pos + offset);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int grapheme_strrpos(string haystack, string needle [, int offset])
|
||||
Find position of last occurrence of a string within another */
|
||||
PHP_FUNCTION(grapheme_strrpos)
|
||||
{
|
||||
unsigned char *haystack, *needle;
|
||||
int haystack_len, needle_len;
|
||||
long loffset = 0;
|
||||
int32_t offset = 0;
|
||||
int32_t ret_pos;
|
||||
int is_ascii;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", (char **)&haystack, &haystack_len, (char **)&needle, &needle_len, &loffset) == FAILURE) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"grapheme_strrpos: unable to parse input param", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if ( OUTSIDE_STRING(loffset, haystack_len) ) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_strpos: Offset not contained in string", 1 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* we checked that it will fit: */
|
||||
offset = (int32_t) loffset;
|
||||
|
||||
/* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */
|
||||
|
||||
if (needle_len == 0) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_strpos: Empty delimiter", 1 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
is_ascii = grapheme_ascii_check(haystack, haystack_len) >= 0;
|
||||
|
||||
if ( is_ascii ) {
|
||||
|
||||
ret_pos = grapheme_strrpos_ascii(haystack, haystack_len, needle, needle_len, offset);
|
||||
|
||||
|
||||
if ( ret_pos >= 0 ) {
|
||||
RETURN_LONG(ret_pos);
|
||||
}
|
||||
|
||||
/* if the needle was ascii too, we are done */
|
||||
|
||||
if ( grapheme_ascii_check(needle, needle_len) >= 0 ) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* else we need to continue via utf16 */
|
||||
}
|
||||
|
||||
ret_pos = grapheme_strrpos_utf16(haystack, haystack_len, needle, needle_len, offset, 0 /* f_ignore_case */ TSRMLS_CC);
|
||||
|
||||
if ( ret_pos >= 0 ) {
|
||||
RETURN_LONG(ret_pos);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int grapheme_strripos(string haystack, string needle [, int offset])
|
||||
Find position of last occurrence of a string within another, ignoring case */
|
||||
PHP_FUNCTION(grapheme_strripos)
|
||||
{
|
||||
unsigned char *haystack, *needle;
|
||||
int haystack_len, needle_len;
|
||||
long loffset = 0;
|
||||
int32_t offset = 0;
|
||||
int32_t ret_pos;
|
||||
int is_ascii;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", (char **)&haystack, &haystack_len, (char **)&needle, &needle_len, &loffset) == FAILURE) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"grapheme_strrpos: unable to parse input param", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if ( OUTSIDE_STRING(loffset, haystack_len) ) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_strpos: Offset not contained in string", 1 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* we checked that it will fit: */
|
||||
offset = (int32_t) loffset;
|
||||
|
||||
/* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */
|
||||
|
||||
if (needle_len == 0) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_strpos: Empty delimiter", 1 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
is_ascii = grapheme_ascii_check(haystack, haystack_len) >= 0;
|
||||
|
||||
if ( is_ascii ) {
|
||||
unsigned char *needle_dup, *haystack_dup;
|
||||
|
||||
needle_dup = (unsigned char *)estrndup((char *)needle, needle_len);
|
||||
php_strtolower((char *)needle_dup, needle_len);
|
||||
haystack_dup = (unsigned char *)estrndup((char *)haystack, haystack_len);
|
||||
php_strtolower((char *)haystack_dup, haystack_len);
|
||||
|
||||
ret_pos = grapheme_strrpos_ascii(haystack_dup, haystack_len, needle_dup, needle_len, offset);
|
||||
|
||||
efree(haystack_dup);
|
||||
efree(needle_dup);
|
||||
|
||||
if ( ret_pos >= 0 ) {
|
||||
RETURN_LONG(ret_pos);
|
||||
}
|
||||
|
||||
/* if the needle was ascii too, we are done */
|
||||
|
||||
if ( grapheme_ascii_check(needle, needle_len) >= 0 ) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* else we need to continue via utf16 */
|
||||
}
|
||||
|
||||
ret_pos = grapheme_strrpos_utf16(haystack, haystack_len, needle, needle_len, offset, 1 /* f_ignore_case */ TSRMLS_CC);
|
||||
|
||||
if ( ret_pos >= 0 ) {
|
||||
RETURN_LONG(ret_pos);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string grapheme_substr(string str, int start [, int length])
|
||||
Returns part of a string */
|
||||
PHP_FUNCTION(grapheme_substr)
|
||||
{
|
||||
unsigned char *str, *sub_str;
|
||||
UChar *ustr;
|
||||
int str_len, sub_str_len, ustr_len;
|
||||
long lstart = 0, length = 0;
|
||||
int32_t start = 0;
|
||||
int iter_val;
|
||||
UErrorCode status;
|
||||
unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE];
|
||||
UBreakIterator* bi = NULL;
|
||||
int sub_str_start_pos, sub_str_end_pos;
|
||||
int32_t (*iter_func)(UBreakIterator *);
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|l", (char **)&str, &str_len, &lstart, &length) == FAILURE) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"grapheme_substr: unable to parse input param", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if ( OUTSIDE_STRING(lstart, str_len) ) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_substr: start not contained in string", 1 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* we checked that it will fit: */
|
||||
start = (int32_t) lstart;
|
||||
|
||||
/* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */
|
||||
|
||||
if ( grapheme_ascii_check(str, str_len) >= 0 ) {
|
||||
grapheme_substr_ascii((char *)str, str_len, start, length, ZEND_NUM_ARGS(), (char **) &sub_str, &sub_str_len);
|
||||
|
||||
if ( NULL == sub_str ) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
RETURN_STRINGL(((char *)sub_str), sub_str_len, 1);
|
||||
}
|
||||
|
||||
ustr = NULL;
|
||||
ustr_len = 0;
|
||||
status = U_ZERO_ERROR;
|
||||
intl_convert_utf8_to_utf16(&ustr, &ustr_len, (char *)str, str_len, &status);
|
||||
|
||||
if ( U_FAILURE( status ) ) {
|
||||
/* Set global error code. */
|
||||
intl_error_set_code( NULL, status TSRMLS_CC );
|
||||
|
||||
/* Set error messages. */
|
||||
intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 1 TSRMLS_CC );
|
||||
efree( ustr );
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
bi = grapheme_get_break_iterator((void*)u_break_iterator_buffer, &status TSRMLS_CC );
|
||||
|
||||
if( U_FAILURE(status) ) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
ubrk_setText(bi, ustr, ustr_len, &status);
|
||||
|
||||
if ( start < 0 ) {
|
||||
iter_func = ubrk_previous;
|
||||
ubrk_last(bi);
|
||||
iter_val = 1;
|
||||
}
|
||||
else {
|
||||
iter_func = ubrk_next;
|
||||
iter_val = -1;
|
||||
}
|
||||
|
||||
sub_str_start_pos = 0;
|
||||
|
||||
while ( start ) {
|
||||
sub_str_start_pos = iter_func(bi);
|
||||
|
||||
if ( UBRK_DONE == sub_str_start_pos ) {
|
||||
break;
|
||||
}
|
||||
|
||||
start += iter_val;
|
||||
}
|
||||
|
||||
if ( 0 != start || sub_str_start_pos >= ustr_len ) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_substr: start not contained in string", 1 TSRMLS_CC );
|
||||
|
||||
efree(ustr);
|
||||
ubrk_close(bi);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (ZEND_NUM_ARGS() <= 2) {
|
||||
|
||||
/* no length supplied, return the rest of the string */
|
||||
|
||||
sub_str = NULL;
|
||||
sub_str_len = 0;
|
||||
status = U_ZERO_ERROR;
|
||||
intl_convert_utf16_to_utf8((char **)&sub_str, &sub_str_len, ustr + sub_str_start_pos, ustr_len - sub_str_start_pos, &status);
|
||||
|
||||
efree( ustr );
|
||||
ubrk_close( bi );
|
||||
|
||||
if ( U_FAILURE( status ) ) {
|
||||
/* Set global error code. */
|
||||
intl_error_set_code( NULL, status TSRMLS_CC );
|
||||
|
||||
/* Set error messages. */
|
||||
intl_error_set_custom_msg( NULL, "Error converting output string to UTF-8", 1 TSRMLS_CC );
|
||||
|
||||
efree( sub_str );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* return the allocated string, not a duplicate */
|
||||
RETURN_STRINGL(((char *)sub_str), sub_str_len, 0);
|
||||
}
|
||||
|
||||
/* find the end point of the string to return */
|
||||
|
||||
if ( length < 0 ) {
|
||||
iter_func = ubrk_previous;
|
||||
ubrk_last(bi);
|
||||
iter_val = 1;
|
||||
}
|
||||
else {
|
||||
iter_func = ubrk_next;
|
||||
iter_val = -1;
|
||||
}
|
||||
|
||||
sub_str_end_pos = 0;
|
||||
|
||||
while ( length ) {
|
||||
sub_str_end_pos = iter_func(bi);
|
||||
|
||||
if ( UBRK_DONE == sub_str_end_pos ) {
|
||||
break;
|
||||
}
|
||||
|
||||
length += iter_val;
|
||||
}
|
||||
|
||||
if ( UBRK_DONE == sub_str_end_pos ) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_substr: length not contained in string", 1 TSRMLS_CC );
|
||||
|
||||
efree(ustr);
|
||||
ubrk_close(bi);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
sub_str = NULL;
|
||||
status = U_ZERO_ERROR;
|
||||
intl_convert_utf16_to_utf8((char **)&sub_str, &sub_str_len, ustr + sub_str_start_pos, ( sub_str_end_pos - sub_str_start_pos ), &status);
|
||||
|
||||
efree( ustr );
|
||||
ubrk_close( bi );
|
||||
|
||||
if ( U_FAILURE( status ) ) {
|
||||
/* Set global error code. */
|
||||
intl_error_set_code( NULL, status TSRMLS_CC );
|
||||
|
||||
/* Set error messages. */
|
||||
intl_error_set_custom_msg( NULL, "Error converting output string to UTF-8", 1 TSRMLS_CC );
|
||||
|
||||
if ( NULL != sub_str )
|
||||
efree( sub_str );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* return the allocated string, not a duplicate */
|
||||
RETURN_STRINGL(((char *)sub_str), sub_str_len, 0);
|
||||
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ strstr_common_handler */
|
||||
static void strstr_common_handler(INTERNAL_FUNCTION_PARAMETERS, int f_ignore_case)
|
||||
{
|
||||
unsigned char *haystack, *needle, *found;
|
||||
int haystack_len, needle_len;
|
||||
int ret_pos, uchar_pos;
|
||||
zend_bool part = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", (char **)&haystack, &haystack_len, (char **)&needle, &needle_len, &part) == FAILURE) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"grapheme_strstr: unable to parse input param", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (needle_len == 0) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_strpos: Empty delimiter", 1 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
if ( !f_ignore_case ) {
|
||||
|
||||
/* ASCII optimization: quick check to see if the string might be there
|
||||
* I realize that 'offset' is 'grapheme count offset' but will work in spite of that
|
||||
*/
|
||||
found = (unsigned char *)php_memnstr((char *)haystack, (char *)needle, needle_len, (char *)haystack + haystack_len);
|
||||
|
||||
/* if it isn't there the we are done */
|
||||
if ( !found ) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* if it is there, and if the haystack is ascii, we are all done */
|
||||
if ( grapheme_ascii_check(haystack, haystack_len) >= 0 ) {
|
||||
size_t found_offset = found - haystack;
|
||||
|
||||
if (part) {
|
||||
RETURN_STRINGL(((char *)haystack) , found_offset, 1);
|
||||
} else {
|
||||
RETURN_STRINGL(((char *)found), haystack_len - found_offset, 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* need to work in utf16 */
|
||||
ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, 0, &uchar_pos, f_ignore_case TSRMLS_CC );
|
||||
|
||||
if ( ret_pos < 0 ) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* uchar_pos is the 'nth' Unicode character position of the needle */
|
||||
|
||||
ret_pos = 0;
|
||||
U8_FWD_N(haystack, ret_pos, haystack_len, uchar_pos);
|
||||
|
||||
if (part) {
|
||||
RETURN_STRINGL(((char *)haystack), ret_pos, 1);
|
||||
}
|
||||
else {
|
||||
RETURN_STRINGL(((char *)haystack) + ret_pos, haystack_len - ret_pos, 1);
|
||||
}
|
||||
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string grapheme_strstr(string haystack, string needle[, bool part])
|
||||
Finds first occurrence of a string within another */
|
||||
PHP_FUNCTION(grapheme_strstr)
|
||||
{
|
||||
strstr_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0 /* f_ignore_case */);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string grapheme_stristr(string haystack, string needle[, bool part])
|
||||
Finds first occurrence of a string within another */
|
||||
PHP_FUNCTION(grapheme_stristr)
|
||||
{
|
||||
strstr_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1 /* f_ignore_case */);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_extract_charcount_iter - grapheme iterator for grapheme_extract MAXCHARS */
|
||||
inline int32_t
|
||||
grapheme_extract_charcount_iter(UBreakIterator *bi, int32_t csize, unsigned char *pstr, int32_t str_len)
|
||||
{
|
||||
int pos = 0, prev_pos = 0;
|
||||
int ret_pos = 0, prev_ret_pos = 0;
|
||||
|
||||
while ( 1 ) {
|
||||
pos = ubrk_next(bi);
|
||||
|
||||
if ( UBRK_DONE == pos ) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* if we are beyond our limit, then the loop is done */
|
||||
if ( pos > csize ) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* update our pointer in the original UTF-8 buffer by as many characters
|
||||
as ubrk_next iterated over */
|
||||
|
||||
prev_ret_pos = ret_pos;
|
||||
U8_FWD_N(pstr, ret_pos, str_len, pos - prev_pos);
|
||||
|
||||
if ( prev_ret_pos == ret_pos ) {
|
||||
/* something wrong - malformed utf8? */
|
||||
break;
|
||||
}
|
||||
|
||||
prev_pos = pos;
|
||||
}
|
||||
|
||||
return ret_pos;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_extract_bytecount_iter - grapheme iterator for grapheme_extract MAXBYTES */
|
||||
inline int32_t
|
||||
grapheme_extract_bytecount_iter(UBreakIterator *bi, int32_t bsize, unsigned char *pstr, int32_t str_len)
|
||||
{
|
||||
int pos = 0, prev_pos = 0;
|
||||
int ret_pos = 0, prev_ret_pos = 0;
|
||||
|
||||
while ( 1 ) {
|
||||
pos = ubrk_next(bi);
|
||||
|
||||
if ( UBRK_DONE == pos ) {
|
||||
break;
|
||||
}
|
||||
|
||||
prev_ret_pos = ret_pos;
|
||||
U8_FWD_N(pstr, ret_pos, str_len, pos - prev_pos);
|
||||
|
||||
if ( ret_pos > bsize ) {
|
||||
ret_pos = prev_ret_pos;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( prev_ret_pos == ret_pos ) {
|
||||
/* something wrong - malformed utf8? */
|
||||
break;
|
||||
}
|
||||
|
||||
prev_pos = pos;
|
||||
}
|
||||
|
||||
return ret_pos;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_extract_count_iter - grapheme iterator for grapheme_extract COUNT */
|
||||
inline int32_t
|
||||
grapheme_extract_count_iter(UBreakIterator *bi, int32_t size, unsigned char *pstr, int32_t str_len)
|
||||
{
|
||||
int pos = 0, next_pos = 0;
|
||||
int ret_pos = 0;
|
||||
|
||||
while ( size ) {
|
||||
next_pos = ubrk_next(bi);
|
||||
|
||||
if ( UBRK_DONE == next_pos ) {
|
||||
break;
|
||||
}
|
||||
pos = next_pos;
|
||||
size--;
|
||||
}
|
||||
|
||||
/* pos is one past the last UChar - and represent the number of code units to
|
||||
advance in the utf-8 buffer
|
||||
*/
|
||||
|
||||
U8_FWD_N(pstr, ret_pos, str_len, pos);
|
||||
|
||||
return ret_pos;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme extract iter function pointer array */
|
||||
typedef int32_t (*grapheme_extract_iter)(UBreakIterator * /*bi*/, int32_t /*size*/, unsigned char * /*pstr*/, int32_t /*str_len*/);
|
||||
|
||||
static grapheme_extract_iter grapheme_extract_iters[] = {
|
||||
&grapheme_extract_count_iter,
|
||||
&grapheme_extract_bytecount_iter,
|
||||
&grapheme_extract_charcount_iter,
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string grapheme_extract(string str, int size[, int extract_type[, int start[, int next]]])
|
||||
Function to extract a sequence of default grapheme clusters */
|
||||
PHP_FUNCTION(grapheme_extract)
|
||||
{
|
||||
unsigned char *str, *pstr;
|
||||
UChar *ustr;
|
||||
int str_len, ustr_len;
|
||||
long size; /* maximum number of grapheme clusters, bytes, or characters (based on extract_type) to return */
|
||||
long lstart = 0; /* starting position in str in bytes */
|
||||
int32_t start = 0;
|
||||
long extract_type = GRAPHEME_EXTRACT_TYPE_COUNT;
|
||||
UErrorCode status;
|
||||
unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE];
|
||||
UBreakIterator* bi = NULL;
|
||||
int ret_pos;
|
||||
zval *next = NULL; // return offset of next part of the string
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|llz", (char **)&str, &str_len, &size, &extract_type, &lstart, &next) == FAILURE) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"grapheme_extract: unable to parse input param", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if ( NULL != next ) {
|
||||
if ( !PZVAL_IS_REF(next) ) {
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"grapheme_extract: 'next' was not passed by reference", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
else {
|
||||
/* initialize next */
|
||||
ZVAL_LONG(next, start);
|
||||
}
|
||||
}
|
||||
|
||||
if ( extract_type < GRAPHEME_EXTRACT_TYPE_MIN || extract_type > GRAPHEME_EXTRACT_TYPE_MAX ) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"grapheme_extract: unknown extract type param", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if ( lstart > INT32_MAX || lstart < 0 || lstart >= str_len ) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_extract: start not contained in string", 1 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* we checked that it will fit: */
|
||||
start = (int32_t) lstart;
|
||||
|
||||
pstr = str + start;
|
||||
|
||||
/* just in case pstr points in the middle of a character, move forward to the start of the next char */
|
||||
if ( !UTF8_IS_SINGLE(*pstr) && !U8_IS_LEAD(*pstr) ) {
|
||||
unsigned char *str_end = str + str_len;
|
||||
|
||||
while ( !UTF8_IS_SINGLE(*pstr) && !U8_IS_LEAD(*pstr) ) {
|
||||
pstr++;
|
||||
if ( pstr >= str_end ) {
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"grapheme_extract: invalid input string", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
str_len -= (pstr - str);
|
||||
|
||||
/* if the string is all ASCII up to size+1 - or str_len whichever is first - then we are done.
|
||||
(size + 1 because the size-th character might be the beginning of a grapheme cluster)
|
||||
*/
|
||||
|
||||
if ( -1 != grapheme_ascii_check(pstr, size + 1 < str_len ? size + 1 : str_len ) ) {
|
||||
if ( NULL != next ) {
|
||||
ZVAL_LONG(next, start+size);
|
||||
}
|
||||
RETURN_STRINGL(((char *)pstr), size, 1);
|
||||
}
|
||||
|
||||
/* convert the strings to UTF-16. */
|
||||
ustr = NULL;
|
||||
ustr_len = 0;
|
||||
status = U_ZERO_ERROR;
|
||||
intl_convert_utf8_to_utf16(&ustr, &ustr_len, (char *)pstr, str_len, &status );
|
||||
|
||||
if ( U_FAILURE( status ) ) {
|
||||
/* Set global error code. */
|
||||
intl_error_set_code( NULL, status TSRMLS_CC );
|
||||
|
||||
/* Set error messages. */
|
||||
intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 1 TSRMLS_CC );
|
||||
|
||||
if ( NULL != ustr )
|
||||
efree( ustr );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
bi = NULL;
|
||||
status = U_ZERO_ERROR;
|
||||
bi = grapheme_get_break_iterator(u_break_iterator_buffer, &status TSRMLS_CC );
|
||||
|
||||
ubrk_setText(bi, ustr, ustr_len, &status);
|
||||
|
||||
/* if the caller put us in the middle of a grapheme, we can't detect it in all cases since we
|
||||
can't back up. So, we will not do anything. */
|
||||
|
||||
/* now we need to find the end of the chunk the user wants us to return */
|
||||
|
||||
ret_pos = (*grapheme_extract_iters[extract_type])(bi, size, pstr, str_len);
|
||||
|
||||
efree(ustr);
|
||||
ubrk_close(bi);
|
||||
|
||||
if ( NULL != next ) {
|
||||
ZVAL_LONG(next, start+ret_pos);
|
||||
}
|
||||
|
||||
RETURN_STRINGL(((char *)pstr), ret_pos, 1);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: fdm=marker
|
||||
* vim: noet sw=4 ts=4
|
||||
*/
|
||||
|
619
ext/intl/grapheme/grapheme_util.c
Executable file
619
ext/intl/grapheme/grapheme_util.c
Executable file
@ -0,0 +1,619 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Ed Batutis <ed@batutis.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* {{{ includes */
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <php.h>
|
||||
#include "grapheme.h"
|
||||
#include "grapheme_util.h"
|
||||
#include "intl_common.h"
|
||||
|
||||
#include <unicode/utypes.h>
|
||||
#include <unicode/ucol.h>
|
||||
#include <unicode/ustring.h>
|
||||
#include <unicode/ubrk.h>
|
||||
|
||||
#include "ext/standard/php_string.h"
|
||||
|
||||
ZEND_EXTERN_MODULE_GLOBALS( intl )
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_close_global_iterator - clean up */
|
||||
void
|
||||
grapheme_close_global_iterator( TSRMLS_D )
|
||||
{
|
||||
UBreakIterator *global_break_iterator = INTL_G( grapheme_iterator );
|
||||
|
||||
if ( NULL != global_break_iterator ) {
|
||||
ubrk_close(global_break_iterator);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_intl_case_fold: convert string to lowercase */
|
||||
void
|
||||
grapheme_intl_case_fold(UChar** ptr_to_free, UChar **str, int32_t *str_len, UErrorCode *pstatus )
|
||||
{
|
||||
UChar *dest;
|
||||
int32_t dest_len, size_required;
|
||||
|
||||
/* allocate a destination string that is a bit larger than the src, hoping that is enough */
|
||||
dest_len = (*str_len) + ( *str_len / 10 );
|
||||
dest = (UChar*) eumalloc(dest_len);
|
||||
|
||||
*pstatus = U_ZERO_ERROR;
|
||||
size_required = u_strFoldCase(dest, dest_len, *str, *str_len, U_FOLD_CASE_DEFAULT, pstatus);
|
||||
|
||||
dest_len = size_required;
|
||||
|
||||
if ( U_BUFFER_OVERFLOW_ERROR == *pstatus ) {
|
||||
|
||||
dest = (UChar*) eurealloc(dest, dest_len);
|
||||
|
||||
*pstatus = U_ZERO_ERROR;
|
||||
size_required = u_strFoldCase(dest, dest_len, *str, *str_len, U_FOLD_CASE_DEFAULT, pstatus);
|
||||
}
|
||||
|
||||
if ( U_FAILURE(*pstatus) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( NULL != ptr_to_free) {
|
||||
efree(*ptr_to_free);
|
||||
*ptr_to_free = dest;
|
||||
}
|
||||
|
||||
*str = dest;
|
||||
*str_len = dest_len;
|
||||
|
||||
return;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_substr_ascii f='from' - starting point, l='length' */
|
||||
void
|
||||
grapheme_substr_ascii(char *str, int str_len, int f, int l, int argc, char **sub_str, int *sub_str_len)
|
||||
{
|
||||
*sub_str = NULL;
|
||||
|
||||
if (argc > 2) {
|
||||
if ((l < 0 && -l > str_len)) {
|
||||
return;
|
||||
} else if (l > str_len) {
|
||||
l = str_len;
|
||||
}
|
||||
} else {
|
||||
l = str_len;
|
||||
}
|
||||
|
||||
if (f > str_len || (f < 0 && -f > str_len)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (l < 0 && (l + str_len - f) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* if "from" position is negative, count start position from the end
|
||||
* of the string
|
||||
*/
|
||||
if (f < 0) {
|
||||
f = str_len + f;
|
||||
if (f < 0) {
|
||||
f = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* if "length" position is negative, set it to the length
|
||||
* needed to stop that many chars from the end of the string
|
||||
*/
|
||||
if (l < 0) {
|
||||
l = (str_len - f) + l;
|
||||
if (l < 0) {
|
||||
l = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (f >= str_len) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((f + l) > str_len) {
|
||||
l = str_len - f;
|
||||
}
|
||||
|
||||
*sub_str = str + f;
|
||||
*sub_str_len = l;
|
||||
|
||||
return;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_strrpos_utf16 - strrpos using utf16 */
|
||||
int
|
||||
grapheme_strrpos_utf16(unsigned char *haystack, int32_t haystack_len, unsigned char*needle, int32_t needle_len, int32_t offset, int f_ignore_case TSRMLS_DC)
|
||||
{
|
||||
UChar *uhaystack, *puhaystack, *uhaystack_end, *uneedle;
|
||||
int32_t uhaystack_len, uneedle_len;
|
||||
UErrorCode status;
|
||||
unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE];
|
||||
UBreakIterator* bi = NULL;
|
||||
int ret_pos, pos;
|
||||
|
||||
/* convert the strings to UTF-16. */
|
||||
uhaystack = NULL;
|
||||
uhaystack_len = 0;
|
||||
status = U_ZERO_ERROR;
|
||||
intl_convert_utf8_to_utf16(&uhaystack, &uhaystack_len, (char *) haystack, haystack_len, &status );
|
||||
|
||||
if ( U_FAILURE( status ) ) {
|
||||
/* Set global error code. */
|
||||
intl_error_set_code( NULL, status TSRMLS_CC );
|
||||
|
||||
/* Set error messages. */
|
||||
intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 1 TSRMLS_CC );
|
||||
efree( uhaystack );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( f_ignore_case ) {
|
||||
grapheme_intl_case_fold(&uhaystack, &uhaystack, &uhaystack_len, &status );
|
||||
}
|
||||
|
||||
/* get a pointer to the haystack taking into account the offset */
|
||||
bi = NULL;
|
||||
status = U_ZERO_ERROR;
|
||||
bi = grapheme_get_break_iterator(u_break_iterator_buffer, &status TSRMLS_CC );
|
||||
|
||||
puhaystack = grapheme_get_haystack_offset(bi, uhaystack, uhaystack_len, offset);
|
||||
|
||||
if ( NULL == puhaystack ) {
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_strpos: Offset not contained in string", 1 TSRMLS_CC );
|
||||
efree( uhaystack );
|
||||
ubrk_close (bi);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uneedle = NULL;
|
||||
uneedle_len = 0;
|
||||
status = U_ZERO_ERROR;
|
||||
intl_convert_utf8_to_utf16(&uneedle, &uneedle_len, (char *) needle, needle_len, &status );
|
||||
|
||||
if ( U_FAILURE( status ) ) {
|
||||
/* Set global error code. */
|
||||
intl_error_set_code( NULL, status TSRMLS_CC );
|
||||
|
||||
/* Set error messages. */
|
||||
intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 1 TSRMLS_CC );
|
||||
efree( uhaystack );
|
||||
efree( uneedle );
|
||||
ubrk_close (bi);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( f_ignore_case ) {
|
||||
grapheme_intl_case_fold(&uneedle, &uneedle, &uneedle_len, &status );
|
||||
}
|
||||
|
||||
ret_pos = -1; /* -1 represents 'not found' */
|
||||
|
||||
/* back up until there's needle_len characters to compare */
|
||||
|
||||
uhaystack_end = uhaystack + uhaystack_len;
|
||||
pos = ubrk_last(bi);
|
||||
puhaystack = uhaystack + pos;
|
||||
|
||||
while ( uhaystack_end - puhaystack < uneedle_len ) {
|
||||
|
||||
pos = ubrk_previous(bi);
|
||||
|
||||
if ( UBRK_DONE == pos ) {
|
||||
break;
|
||||
}
|
||||
|
||||
puhaystack = uhaystack + pos;
|
||||
}
|
||||
|
||||
/* is there enough haystack left to hold the needle? */
|
||||
if ( ( uhaystack_end - puhaystack ) < uneedle_len ) {
|
||||
/* not enough, not found */
|
||||
goto exit;
|
||||
}
|
||||
|
||||
while ( UBRK_DONE != pos ) {
|
||||
|
||||
if (!u_memcmp(uneedle, puhaystack, uneedle_len)) { /* needle_len - 1 in zend memnstr? */
|
||||
|
||||
/* does the grapheme in the haystack end at the same place as the last grapheme in the needle? */
|
||||
|
||||
if ( ubrk_isBoundary(bi, pos + uneedle_len) ) {
|
||||
|
||||
/* found it, get grapheme count offset */
|
||||
ret_pos = grapheme_count_graphemes(bi, uhaystack, pos);
|
||||
break;
|
||||
}
|
||||
|
||||
/* set position back */
|
||||
ubrk_isBoundary(bi, pos);
|
||||
}
|
||||
|
||||
pos = ubrk_previous(bi);
|
||||
puhaystack = uhaystack + pos;
|
||||
}
|
||||
|
||||
exit:
|
||||
efree( uhaystack );
|
||||
efree( uneedle );
|
||||
ubrk_close (bi);
|
||||
|
||||
return ret_pos;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_strpos_utf16 - strrpos using utf16*/
|
||||
int
|
||||
grapheme_strpos_utf16(unsigned char *haystack, int32_t haystack_len, unsigned char*needle, int32_t needle_len, int32_t offset, int32_t *puchar_pos, int f_ignore_case TSRMLS_DC)
|
||||
{
|
||||
UChar *uhaystack, *puhaystack, *uneedle;
|
||||
int32_t uhaystack_len, uneedle_len;
|
||||
int ret_pos;
|
||||
unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE];
|
||||
UBreakIterator* bi;
|
||||
UErrorCode status;
|
||||
|
||||
*puchar_pos = -1;
|
||||
|
||||
/* convert the strings to UTF-16. */
|
||||
|
||||
uhaystack = NULL;
|
||||
uhaystack_len = 0;
|
||||
status = U_ZERO_ERROR;
|
||||
intl_convert_utf8_to_utf16(&uhaystack, &uhaystack_len, (char *) haystack, haystack_len, &status );
|
||||
|
||||
if ( U_FAILURE( status ) ) {
|
||||
/* Set global error code. */
|
||||
intl_error_set_code( NULL, status TSRMLS_CC );
|
||||
|
||||
/* Set error messages. */
|
||||
intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 1 TSRMLS_CC );
|
||||
efree( uhaystack );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* get a pointer to the haystack taking into account the offset */
|
||||
bi = NULL;
|
||||
status = U_ZERO_ERROR;
|
||||
bi = grapheme_get_break_iterator(u_break_iterator_buffer, &status TSRMLS_CC );
|
||||
|
||||
puhaystack = grapheme_get_haystack_offset(bi, uhaystack, uhaystack_len, offset);
|
||||
uhaystack_len = (uhaystack_len - ( puhaystack - uhaystack));
|
||||
|
||||
if ( NULL == puhaystack ) {
|
||||
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_strpos: Offset not contained in string", 1 TSRMLS_CC );
|
||||
|
||||
efree( uhaystack );
|
||||
ubrk_close (bi);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( f_ignore_case ) {
|
||||
grapheme_intl_case_fold(&uhaystack, &puhaystack, &uhaystack_len, &status );
|
||||
}
|
||||
|
||||
uneedle = NULL;
|
||||
uneedle_len = 0;
|
||||
status = U_ZERO_ERROR;
|
||||
intl_convert_utf8_to_utf16(&uneedle, &uneedle_len, (char *) needle, needle_len, &status );
|
||||
|
||||
if ( U_FAILURE( status ) ) {
|
||||
/* Set global error code. */
|
||||
intl_error_set_code( NULL, status TSRMLS_CC );
|
||||
|
||||
/* Set error messages. */
|
||||
intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 1 TSRMLS_CC );
|
||||
efree( uhaystack );
|
||||
efree( uneedle );
|
||||
ubrk_close (bi);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( f_ignore_case ) {
|
||||
grapheme_intl_case_fold(&uneedle, &uneedle, &uneedle_len, &status );
|
||||
}
|
||||
|
||||
ret_pos = grapheme_memnstr_grapheme(bi, puhaystack, uneedle, uneedle_len, puhaystack + uhaystack_len );
|
||||
|
||||
*puchar_pos = ubrk_current(bi);
|
||||
|
||||
efree( uhaystack );
|
||||
efree( uneedle );
|
||||
ubrk_close (bi);
|
||||
|
||||
return ret_pos;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_ascii_check: ASCII check */
|
||||
int grapheme_ascii_check(const unsigned char *day, int32_t len)
|
||||
{
|
||||
int ret_len = len;
|
||||
while ( len-- ) {
|
||||
if ( *day++ > 0x7f )
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret_len;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_split_string: find and optionally return grapheme boundaries */
|
||||
int grapheme_split_string(const UChar *text, int32_t text_length, int boundary_array[], int boundary_array_len TSRMLS_DC )
|
||||
{
|
||||
unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE];
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int ret_len, pos;
|
||||
UBreakIterator* bi;
|
||||
|
||||
bi = grapheme_get_break_iterator((void*)u_break_iterator_buffer, &status TSRMLS_CC );
|
||||
|
||||
if( U_FAILURE(status) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ubrk_setText(bi, text, text_length, &status);
|
||||
|
||||
pos = 0;
|
||||
|
||||
for ( ret_len = 0; pos != UBRK_DONE; ) {
|
||||
|
||||
pos = ubrk_next(bi);
|
||||
|
||||
if ( pos != UBRK_DONE ) {
|
||||
|
||||
if ( NULL != boundary_array && ret_len < boundary_array_len ) {
|
||||
boundary_array[ret_len] = pos;
|
||||
}
|
||||
|
||||
ret_len++;
|
||||
}
|
||||
}
|
||||
|
||||
ubrk_close(bi);
|
||||
|
||||
return ret_len;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_count_graphemes */
|
||||
inline int32_t
|
||||
grapheme_count_graphemes(UBreakIterator *bi, UChar *string, int32_t string_len)
|
||||
{
|
||||
int ret_len = 0;
|
||||
int pos = 0;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
ubrk_setText(bi, string, string_len, &status);
|
||||
|
||||
do {
|
||||
|
||||
pos = ubrk_next(bi);
|
||||
|
||||
if ( UBRK_DONE != pos ) {
|
||||
ret_len++;
|
||||
}
|
||||
|
||||
} while ( UBRK_DONE != pos );
|
||||
|
||||
return ret_len;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_memnstr_grapheme: find needle in haystack using grapheme boundaries */
|
||||
inline int32_t
|
||||
grapheme_memnstr_grapheme(UBreakIterator *bi, UChar *haystack, UChar *needle, int32_t needle_len, UChar *end)
|
||||
{
|
||||
UChar *p = haystack;
|
||||
UChar ne = needle[needle_len-1];
|
||||
UErrorCode status;
|
||||
int32_t grapheme_offset;
|
||||
|
||||
end -= needle_len;
|
||||
|
||||
while (p <= end) {
|
||||
|
||||
if ((p = u_memchr(p, *needle, (end-p+1))) && ne == p[needle_len-1]) {
|
||||
|
||||
if (!u_memcmp(needle, p, needle_len - 1)) { /* needle_len - 1 works because if needle_len is 1, we've already tested the char */
|
||||
|
||||
/* does the grapheme end here? */
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
ubrk_setText (bi, haystack, (end - haystack) + needle_len, &status);
|
||||
|
||||
if ( ubrk_isBoundary (bi, (p - haystack) + needle_len) ) {
|
||||
|
||||
/* found it, get grapheme count offset */
|
||||
grapheme_offset = grapheme_count_graphemes(bi, haystack, (p - haystack));
|
||||
|
||||
return grapheme_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_memrstr_grapheme: reverse find needle in haystack using grapheme boundaries */
|
||||
inline void *grapheme_memrchr_grapheme(const void *s, int c, int32_t n)
|
||||
{
|
||||
register unsigned char *e;
|
||||
|
||||
if (n <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (e = (unsigned char *)s + n - 1; e >= (unsigned char *)s; e--) {
|
||||
if (*e == (unsigned char)c) {
|
||||
return (void *)e;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_get_haystack_offset - bump the haystack pointer based on the grapheme count offset */
|
||||
UChar *
|
||||
grapheme_get_haystack_offset(UBreakIterator* bi, UChar *uhaystack, int32_t uhaystack_len, int32_t offset)
|
||||
{
|
||||
UErrorCode status;
|
||||
int32_t pos;
|
||||
int32_t (*iter_op)(UBreakIterator* bi);
|
||||
int iter_incr;
|
||||
|
||||
if ( NULL != bi ) {
|
||||
status = U_ZERO_ERROR;
|
||||
ubrk_setText (bi, uhaystack, uhaystack_len, &status);
|
||||
}
|
||||
|
||||
if ( 0 == offset ) {
|
||||
return uhaystack;
|
||||
}
|
||||
|
||||
if ( offset < 0 ) {
|
||||
iter_op = ubrk_previous;
|
||||
ubrk_last(bi); /* one past the end */
|
||||
iter_incr = 1;
|
||||
}
|
||||
else {
|
||||
iter_op = ubrk_next;
|
||||
iter_incr = -1;
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
|
||||
while ( pos != UBRK_DONE && offset != 0 ) {
|
||||
|
||||
pos = iter_op(bi);
|
||||
|
||||
if ( UBRK_DONE != pos ) {
|
||||
offset += iter_incr;
|
||||
}
|
||||
}
|
||||
|
||||
if ( offset != 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return uhaystack + pos;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_strrpos_ascii: borrowed from the php ext/standard/string.c */
|
||||
int32_t
|
||||
grapheme_strrpos_ascii(unsigned char *haystack, int32_t haystack_len, unsigned char *needle, int32_t needle_len, int32_t offset)
|
||||
{
|
||||
unsigned char *p, *e;
|
||||
|
||||
if (offset >= 0) {
|
||||
p = haystack + offset;
|
||||
e = haystack + haystack_len - needle_len;
|
||||
} else {
|
||||
p = haystack;
|
||||
if (needle_len > -offset) {
|
||||
e = haystack + haystack_len - needle_len;
|
||||
} else {
|
||||
e = haystack + haystack_len + offset;
|
||||
}
|
||||
}
|
||||
|
||||
if (needle_len == 1) {
|
||||
/* Single character search can shortcut memcmps */
|
||||
while (e >= p) {
|
||||
if (*e == *needle) {
|
||||
return (e - p + (offset > 0 ? offset : 0));
|
||||
}
|
||||
e--;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (e >= p) {
|
||||
if (memcmp(e, needle, needle_len) == 0) {
|
||||
return (e - p + (offset > 0 ? offset : 0));
|
||||
}
|
||||
e--;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ grapheme_get_break_iterator: get a clone of the global character break iterator */
|
||||
UBreakIterator*
|
||||
grapheme_get_break_iterator(void *stack_buffer, UErrorCode *status TSRMLS_DC )
|
||||
{
|
||||
int32_t buffer_size;
|
||||
|
||||
UBreakIterator *global_break_iterator = INTL_G( grapheme_iterator );
|
||||
|
||||
if ( NULL == global_break_iterator ) {
|
||||
|
||||
global_break_iterator = ubrk_open(UBRK_CHARACTER,
|
||||
NULL, /* icu default locale - locale has no effect on this iterator */
|
||||
NULL, /* text not set in global iterator */
|
||||
0, /* text length = 0 */
|
||||
status);
|
||||
|
||||
INTL_G(grapheme_iterator) = global_break_iterator;
|
||||
}
|
||||
|
||||
buffer_size = U_BRK_SAFECLONE_BUFFERSIZE;
|
||||
|
||||
return ubrk_safeClone(global_break_iterator, stack_buffer, &buffer_size, status);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: fdm=marker
|
||||
* vim: noet sw=4 ts=4
|
||||
*/
|
||||
|
59
ext/intl/grapheme/grapheme_util.h
Executable file
59
ext/intl/grapheme/grapheme_util.h
Executable file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Ed Batutis <ed@batutis.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef GRAPHEME_GRAPHEME_UTIL_H
|
||||
#define GRAPHEME_GRAPHEME_UTIL_H
|
||||
|
||||
#include "php_intl.h"
|
||||
#include "intl_convert.h"
|
||||
|
||||
/* get_break_interator: get a break iterator from the global structure */
|
||||
UBreakIterator* grapheme_get_break_iterator(void *stack_buffer, UErrorCode *status TSRMLS_DC );
|
||||
|
||||
void
|
||||
grapheme_substr_ascii(char *str, int32_t str_len, int32_t f, int32_t l, int argc, char **sub_str, int *sub_str_len);
|
||||
|
||||
int
|
||||
grapheme_strrpos_utf16(unsigned char *haystack, int32_t haystack_len, unsigned char*needle, int32_t needle_len, int32_t offset, int f_ignore_case TSRMLS_DC);
|
||||
|
||||
int
|
||||
grapheme_strpos_utf16(unsigned char *haystack, int32_t haystack_len, unsigned char*needle, int32_t needle_len, int32_t offset, int *puchar_pos, int f_ignore_case TSRMLS_DC);
|
||||
|
||||
int grapheme_ascii_check(const unsigned char *day, int32_t len);
|
||||
|
||||
int grapheme_split_string(const UChar *text, int32_t text_length, int boundary_array[], int boundary_array_len TSRMLS_DC );
|
||||
|
||||
inline int32_t
|
||||
grapheme_count_graphemes(UBreakIterator *bi, UChar *string, int32_t string_len);
|
||||
|
||||
inline int32_t
|
||||
grapheme_memnstr_grapheme(UBreakIterator *bi, UChar *haystack, UChar *needle, int32_t needle_len, UChar *end);
|
||||
|
||||
inline void *grapheme_memrchr_grapheme(const void *s, int c, int32_t n);
|
||||
|
||||
UChar *
|
||||
grapheme_get_haystack_offset(UBreakIterator* bi, UChar *uhaystack, int32_t uhaystack_len, int32_t offset);
|
||||
|
||||
int32_t
|
||||
grapheme_strrpos_ascii(unsigned char *haystack, int32_t haystack_len, unsigned char *needle, int32_t needle_len, int32_t offset);
|
||||
|
||||
UBreakIterator*
|
||||
grapheme_get_break_iterator(void *stack_buffer, UErrorCode *status TSRMLS_DC );
|
||||
|
||||
/* OUTSIDE_STRING: check if (possibly negative) long offset is outside the string with int32_t length */
|
||||
#define OUTSIDE_STRING(offset, max_len) ( offset < INT32_MIN || offset > INT32_MAX || (offset < 0 ? -offset > (long) max_len : offset >= (long) max_len) )
|
||||
|
||||
#endif // GRAPHEME_GRAPHEME_UTIL_H
|
44
ext/intl/intl_common.h
Executable file
44
ext/intl/intl_common.h
Executable file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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> |
|
||||
| Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef INTL_COMMON_H
|
||||
#define INTL_COMMON_H
|
||||
/* Auxiliary macros */
|
||||
|
||||
#include <php.h>
|
||||
#include <unicode/utypes.h>
|
||||
|
||||
#ifndef UBYTES
|
||||
# define UBYTES(len) ((len) * sizeof(UChar))
|
||||
#endif
|
||||
|
||||
#ifndef eumalloc
|
||||
# define eumalloc(size) (UChar*)safe_emalloc(size, sizeof(UChar), 0)
|
||||
#endif
|
||||
|
||||
#ifndef eurealloc
|
||||
# define eurealloc(ptr, size) (UChar*)erealloc((ptr), size * sizeof(UChar))
|
||||
#endif
|
||||
|
||||
#define USIZE(data) sizeof((data))/sizeof(UChar)
|
||||
#define UCHARS(len) ((len) / sizeof(UChar))
|
||||
|
||||
#define INTL_Z_STRVAL_P(str) (UChar*) Z_STRVAL_P(str)
|
||||
#define INTL_Z_STRLEN_P(str) UCHARS( Z_STRLEN_P(str) )
|
||||
|
||||
#endif /* INTL_COMMON_H */
|
154
ext/intl/intl_convert.c
Executable file
154
ext/intl/intl_convert.c
Executable file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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.h>
|
||||
|
||||
#include "intl_common.h"
|
||||
#include "intl_convert.h"
|
||||
|
||||
/* {{{ intl_convert_utf8_to_utf16
|
||||
* Convert given string from UTF-8 to UTF-16 to *target buffer.
|
||||
*
|
||||
* It *target is NULL then we allocate a large enough buffer,
|
||||
* store the converted string into it, and make target point to it.
|
||||
*
|
||||
* Otherwise, if *target is non-NULL, we assume that it points to a
|
||||
* dynamically allocated buffer of *target_len bytes length.
|
||||
* In this case the buffer will be used to store the converted string to,
|
||||
* and may be resized (made larger) if needed.
|
||||
*
|
||||
* @param target Where to place the result.
|
||||
* @param target_len Result length.
|
||||
* @param source String to convert.
|
||||
* @param source_len Length of the source string.
|
||||
* @param status Conversion status.
|
||||
*
|
||||
* @return void This function does not return anything.
|
||||
*/
|
||||
void intl_convert_utf8_to_utf16(
|
||||
UChar** target, int* target_len,
|
||||
const char* src, int src_len,
|
||||
UErrorCode* status )
|
||||
{
|
||||
UChar* dst_buf = NULL;
|
||||
int32_t dst_len = 0;
|
||||
|
||||
// If *target is NULL determine required destination buffer size (pre-flighting).
|
||||
// Otherwise, attempt to convert source string; if *target buffer is not large enough
|
||||
// it will be resized appropriately.
|
||||
*status = U_ZERO_ERROR;
|
||||
|
||||
u_strFromUTF8( *target, *target_len, &dst_len, src, src_len, status );
|
||||
|
||||
if( *status == U_ZERO_ERROR )
|
||||
{
|
||||
// String is converted successfuly
|
||||
(*target)[dst_len] = 0;
|
||||
*target_len = dst_len;
|
||||
return;
|
||||
}
|
||||
|
||||
// Bail out if an unexpected error occured.
|
||||
// (U_BUFFER_OVERFLOW_ERROR means that *target buffer is not large enough).
|
||||
// (U_STRING_NOT_TERMINATED_WARNING usually means that the input string is empty).
|
||||
if( *status != U_BUFFER_OVERFLOW_ERROR && *status != U_STRING_NOT_TERMINATED_WARNING )
|
||||
return;
|
||||
|
||||
// Allocate memory for the destination buffer (it will be zero-terminated).
|
||||
dst_buf = eumalloc( dst_len + 1 );
|
||||
|
||||
// Convert source string from UTF-8 to UTF-16.
|
||||
*status = U_ZERO_ERROR;
|
||||
u_strFromUTF8( dst_buf, dst_len+1, NULL, src, src_len, status );
|
||||
if( U_FAILURE( *status ) )
|
||||
{
|
||||
efree( dst_buf );
|
||||
return;
|
||||
}
|
||||
|
||||
dst_buf[dst_len] = 0;
|
||||
|
||||
if( *target )
|
||||
efree( *target );
|
||||
|
||||
*target = dst_buf;
|
||||
*target_len = dst_len;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ intl_convert_utf16_to_utf8
|
||||
* Convert given string from UTF-16 to UTF-8.
|
||||
*
|
||||
* @param target Where to place the result.
|
||||
* @param target_len Result length.
|
||||
* @param source String to convert.
|
||||
* @param source_len Length of the source string.
|
||||
* @param status Conversion status.
|
||||
*
|
||||
* @return void This function does not return anything.
|
||||
*/
|
||||
void intl_convert_utf16_to_utf8(
|
||||
char** target, int* target_len,
|
||||
const UChar* src, int src_len,
|
||||
UErrorCode* status )
|
||||
{
|
||||
char* dst_buf = NULL;
|
||||
int32_t dst_len;
|
||||
|
||||
// Determine required destination buffer size (pre-flighting).
|
||||
*status = U_ZERO_ERROR;
|
||||
u_strToUTF8( NULL, 0, &dst_len, src, src_len, status );
|
||||
|
||||
// Bail out if an unexpected error occured.
|
||||
// (U_BUFFER_OVERFLOW_ERROR means that *target buffer is not large enough).
|
||||
// (U_STRING_NOT_TERMINATED_WARNING usually means that the input string is empty).
|
||||
if( *status != U_BUFFER_OVERFLOW_ERROR && *status != U_STRING_NOT_TERMINATED_WARNING )
|
||||
return;
|
||||
|
||||
// Allocate memory for the destination buffer (it will be zero-terminated).
|
||||
dst_buf = emalloc( dst_len+1 );
|
||||
|
||||
// Convert source string from UTF-8 to UTF-16.
|
||||
*status = U_ZERO_ERROR;
|
||||
u_strToUTF8( dst_buf, dst_len, NULL, src, src_len, status );
|
||||
if( U_FAILURE( *status ) )
|
||||
{
|
||||
efree( dst_buf );
|
||||
return;
|
||||
}
|
||||
|
||||
// U_STRING_NOT_TERMINATED_WARNING is OK for us => reset 'status'.
|
||||
*status = U_ZERO_ERROR;
|
||||
|
||||
dst_buf[dst_len] = 0;
|
||||
*target = dst_buf;
|
||||
*target_len = dst_len;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
33
ext/intl/intl_convert.h
Executable file
33
ext/intl/intl_convert.h
Executable file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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 INTL_CONVERT_H
|
||||
#define INTL_CONVERT_H
|
||||
|
||||
#include <unicode/ustring.h>
|
||||
|
||||
void intl_convert_utf8_to_utf16(
|
||||
UChar** target, int* target_len,
|
||||
const char* src, int src_len,
|
||||
UErrorCode* status );
|
||||
|
||||
void intl_convert_utf16_to_utf8(
|
||||
char** target, int* target_len,
|
||||
const UChar* src, int src_len,
|
||||
UErrorCode* status );
|
||||
|
||||
#endif // INTL_CONVERT_H
|
87
ext/intl/intl_data.h
Executable file
87
ext/intl/intl_data.h
Executable file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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> |
|
||||
| Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef INTL_DATA_H
|
||||
#define INTL_DATA_H
|
||||
|
||||
#include <unicode/utypes.h>
|
||||
|
||||
#include "intl_error.h"
|
||||
|
||||
/* Mock object to generalize error handling in sub-modules.
|
||||
Sub-module data structures should always have error as first element
|
||||
for this to work!
|
||||
*/
|
||||
typedef struct _intl_data {
|
||||
zend_object zo;
|
||||
intl_error error;
|
||||
} intl_object;
|
||||
|
||||
#define INTL_METHOD_INIT_VARS(oclass, obj) \
|
||||
zval* object = NULL; \
|
||||
oclass##_object* obj = NULL; \
|
||||
intl_error_reset( NULL TSRMLS_CC );
|
||||
|
||||
#define INTL_DATA_ERROR(obj) (((intl_object *)(obj))->error)
|
||||
#define INTL_DATA_ERROR_P(obj) (&(INTL_DATA_ERROR((obj))))
|
||||
#define INTL_DATA_ERROR_CODE(obj) INTL_ERROR_CODE(INTL_DATA_ERROR((obj)))
|
||||
|
||||
#define INTL_METHOD_FETCH_OBJECT(oclass, obj) \
|
||||
obj = (oclass##_object *) zend_object_store_get_object( object TSRMLS_CC ); \
|
||||
intl_error_reset( INTL_DATA_ERROR_P(obj) TSRMLS_CC ); \
|
||||
|
||||
#define INTL_METHOD_CHECK_STATUS(obj, msg) \
|
||||
intl_error_set_code( NULL, INTL_DATA_ERROR_CODE((obj)) TSRMLS_CC ); \
|
||||
if( U_FAILURE( INTL_DATA_ERROR_CODE((obj)) ) ) \
|
||||
{ \
|
||||
intl_errors_set_custom_msg( INTL_DATA_ERROR_P((obj)), msg, 0 TSRMLS_CC ); \
|
||||
RETURN_FALSE; \
|
||||
}
|
||||
|
||||
#define INTL_METHOD_RETVAL_UTF8(obj, ustring, ulen, free_it) \
|
||||
{ \
|
||||
char *u8value; \
|
||||
int u8len; \
|
||||
intl_convert_utf16_to_utf8(&u8value, &u8len, ustring, ulen, &INTL_DATA_ERROR_CODE((obj))); \
|
||||
if((free_it)) { \
|
||||
efree(ustring); \
|
||||
} \
|
||||
INTL_METHOD_CHECK_STATUS((obj), "Error converting value to UTF-8"); \
|
||||
RETVAL_STRINGL(u8value, u8len, 0); \
|
||||
}
|
||||
|
||||
#define INTL_MAX_LOCALE_LEN 64
|
||||
|
||||
#define INTL_CHECK_LOCALE_LEN(locale_len) \
|
||||
if((locale_len) > INTL_MAX_LOCALE_LEN) { \
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, \
|
||||
"Locale string too long, should be no longer than 64 characters", 0 TSRMLS_CC ); \
|
||||
RETURN_NULL(); \
|
||||
}
|
||||
|
||||
#define INTL_CHECK_LOCALE_LEN_OBJ(locale_len, object) \
|
||||
if((locale_len) > INTL_MAX_LOCALE_LEN) { \
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, \
|
||||
"Locale string too long, should be no longer than 64 characters", 0 TSRMLS_CC ); \
|
||||
zval_dtor(object); \
|
||||
ZVAL_NULL(object); \
|
||||
RETURN_NULL(); \
|
||||
}
|
||||
|
||||
|
||||
#endif // INTL_DATA_H
|
215
ext/intl/intl_error.c
Executable file
215
ext/intl/intl_error.c
Executable file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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> |
|
||||
| Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <php.h>
|
||||
|
||||
#include "php_intl.h"
|
||||
#include "intl_error.h"
|
||||
|
||||
ZEND_EXTERN_MODULE_GLOBALS( intl )
|
||||
|
||||
/* {{{ intl_error* intl_g_error_get()
|
||||
* Return global error structure.
|
||||
*/
|
||||
static intl_error* intl_g_error_get( TSRMLS_D )
|
||||
{
|
||||
return &INTL_G( g_error );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void intl_free_custom_error_msg( intl_error* err )
|
||||
* Free mem.
|
||||
*/
|
||||
static void intl_free_custom_error_msg( intl_error* err TSRMLS_DC )
|
||||
{
|
||||
if( !err && !( err = intl_g_error_get( TSRMLS_C ) ) )
|
||||
return;
|
||||
|
||||
if( !err->free_custom_error_message )
|
||||
return;
|
||||
|
||||
efree( err->custom_error_message );
|
||||
|
||||
err->custom_error_message = NULL;
|
||||
err->free_custom_error_message = 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ intl_error* intl_error_create()
|
||||
* Create and initialize internals of 'intl_error'.
|
||||
*/
|
||||
intl_error* intl_error_create( TSRMLS_D )
|
||||
{
|
||||
intl_error* err = ecalloc( 1, sizeof( intl_error ) );
|
||||
|
||||
intl_error_init( err TSRMLS_CC );
|
||||
|
||||
return err;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void intl_error_init( intl_error* coll_error )
|
||||
* Initialize internals of 'intl_error'.
|
||||
*/
|
||||
void intl_error_init( intl_error* err TSRMLS_DC )
|
||||
{
|
||||
if( !err && !( err = intl_g_error_get( TSRMLS_C ) ) )
|
||||
return;
|
||||
|
||||
err->code = U_ZERO_ERROR;
|
||||
err->custom_error_message = NULL;
|
||||
err->free_custom_error_message = 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void intl_error_reset( intl_error* err )
|
||||
* Set last error code to 0 and unset last error message
|
||||
*/
|
||||
void intl_error_reset( intl_error* err TSRMLS_DC )
|
||||
{
|
||||
if( !err && !( err = intl_g_error_get( TSRMLS_C ) ) )
|
||||
return;
|
||||
|
||||
err->code = U_ZERO_ERROR;
|
||||
|
||||
intl_free_custom_error_msg( err TSRMLS_CC );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void intl_error_set_custom_msg( intl_error* err, char* msg, int copyMsg )
|
||||
* Set last error message to msg copying it if needed.
|
||||
*/
|
||||
void intl_error_set_custom_msg( intl_error* err, char* msg, int copyMsg TSRMLS_DC )
|
||||
{
|
||||
if( !msg )
|
||||
return;
|
||||
|
||||
if( !err && !( err = intl_g_error_get( TSRMLS_C ) ) )
|
||||
return;
|
||||
|
||||
// Free previous message if any
|
||||
intl_free_custom_error_msg( err TSRMLS_CC );
|
||||
|
||||
// Mark message copied if any
|
||||
err->free_custom_error_message = copyMsg;
|
||||
|
||||
// Set user's error text message
|
||||
err->custom_error_message = copyMsg ? estrdup( msg ) : msg;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ const char* intl_error_get_message( intl_error* err )
|
||||
* Create output message in format "<intl_error_text>: <extra_user_error_text>".
|
||||
*/
|
||||
char* intl_error_get_message( intl_error* err TSRMLS_DC )
|
||||
{
|
||||
const char* uErrorName = NULL;
|
||||
char* errMessage = 0;
|
||||
|
||||
if( !err && !( err = intl_g_error_get( TSRMLS_C ) ) )
|
||||
return estrdup( "" );
|
||||
|
||||
uErrorName = u_errorName( err->code );
|
||||
|
||||
// Format output string
|
||||
if( err->custom_error_message )
|
||||
{
|
||||
spprintf( &errMessage, 0, "%s: %s", err->custom_error_message, uErrorName );
|
||||
}
|
||||
else
|
||||
{
|
||||
spprintf( &errMessage, 0, "%s", uErrorName );
|
||||
}
|
||||
|
||||
return errMessage;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void intl_error_set_code( intl_error* err, UErrorCode err_code )
|
||||
* Set last error code.
|
||||
*/
|
||||
void intl_error_set_code( intl_error* err, UErrorCode err_code TSRMLS_DC )
|
||||
{
|
||||
if( !err && !( err = intl_g_error_get( TSRMLS_C ) ) )
|
||||
return;
|
||||
|
||||
err->code = err_code;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void intl_error_get_code( intl_error* err )
|
||||
* Return last error code.
|
||||
*/
|
||||
UErrorCode intl_error_get_code( intl_error* err TSRMLS_DC )
|
||||
{
|
||||
if( !err && !( err = intl_g_error_get( TSRMLS_C ) ) )
|
||||
return U_ZERO_ERROR;
|
||||
|
||||
return err->code;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void intl_error_set( intl_error* err, UErrorCode code, char* msg, int copyMsg )
|
||||
* Set error code and message.
|
||||
*/
|
||||
void intl_error_set( intl_error* err, UErrorCode code, char* msg, int copyMsg TSRMLS_DC )
|
||||
{
|
||||
intl_error_set_code( err, code TSRMLS_CC );
|
||||
intl_error_set_custom_msg( err, msg, copyMsg TSRMLS_CC );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void intl_errors_reset( intl_error* err )
|
||||
*/
|
||||
void intl_errors_reset( intl_error* err TSRMLS_DC )
|
||||
{
|
||||
intl_error_reset( err TSRMLS_CC );
|
||||
intl_error_reset( NULL TSRMLS_CC );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void intl_errors_set_custom_msg( intl_error* err, char* msg, int copyMsg )
|
||||
*/
|
||||
void intl_errors_set_custom_msg( intl_error* err, char* msg, int copyMsg TSRMLS_DC )
|
||||
{
|
||||
intl_error_set_custom_msg( err, msg, copyMsg TSRMLS_CC );
|
||||
intl_error_set_custom_msg( NULL, msg, copyMsg TSRMLS_CC );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ intl_errors_set_code( intl_error* err, UErrorCode err_code )
|
||||
*/
|
||||
void intl_errors_set_code( intl_error* err, UErrorCode err_code TSRMLS_DC )
|
||||
{
|
||||
intl_error_set_code( err, err_code TSRMLS_CC );
|
||||
intl_error_set_code( NULL, err_code 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
|
||||
*/
|
46
ext/intl/intl_error.h
Executable file
46
ext/intl/intl_error.h
Executable file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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> |
|
||||
| Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef INTL_ERROR_H
|
||||
#define INTL_ERROR_H
|
||||
|
||||
#include <unicode/utypes.h>
|
||||
|
||||
#define INTL_ERROR_CODE(e) (e).code
|
||||
|
||||
typedef struct _intl_error {
|
||||
UErrorCode code;
|
||||
char* custom_error_message;
|
||||
int free_custom_error_message;
|
||||
} intl_error;
|
||||
|
||||
intl_error* intl_error_create( TSRMLS_D );
|
||||
void intl_error_init( intl_error* err TSRMLS_DC );
|
||||
void intl_error_reset( intl_error* err TSRMLS_DC );
|
||||
void intl_error_set_code( intl_error* err, UErrorCode err_code TSRMLS_DC );
|
||||
void intl_error_set_custom_msg( intl_error* err, char* msg, int copyMsg TSRMLS_DC );
|
||||
void intl_error_set( intl_error* err, UErrorCode code, char* msg, int copyMsg TSRMLS_DC );
|
||||
UErrorCode intl_error_get_code( intl_error* err TSRMLS_DC );
|
||||
char* intl_error_get_message( intl_error* err TSRMLS_DC );
|
||||
|
||||
// Wrappers to synchonize object's and global error structures.
|
||||
void intl_errors_reset( intl_error* err TSRMLS_DC );
|
||||
void intl_errors_set_custom_msg( intl_error* err, char* msg, int copyMsg TSRMLS_DC );
|
||||
void intl_errors_set_code( intl_error* err, UErrorCode err_code TSRMLS_DC );
|
||||
|
||||
#endif // INTL_ERROR_H
|
70
ext/intl/locale/locale.c
Executable file
70
ext/intl/locale/locale.c
Executable file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Kirti Velankar <kirtig@yahoo-inc.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "locale_class.h"
|
||||
#include "locale.h"
|
||||
|
||||
#include <unicode/utypes.h>
|
||||
#include <unicode/uloc.h>
|
||||
#include <unicode/ustring.h>
|
||||
|
||||
/* {{{ locale_register_constants
|
||||
* Register constants common for the both (OO and procedural)
|
||||
* APIs.
|
||||
*/
|
||||
void locale_register_constants( INIT_FUNC_ARGS )
|
||||
{
|
||||
if( !Locale_ce_ptr )
|
||||
{
|
||||
zend_error( E_ERROR, "Locale class not defined" );
|
||||
return;
|
||||
}
|
||||
|
||||
#define LOCALE_EXPOSE_CONST(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS)
|
||||
#define LOCALE_EXPOSE_CLASS_CONST(x) zend_declare_class_constant_long( Locale_ce_ptr, ZEND_STRS( #x ) - 1, ULOC_##x TSRMLS_CC );
|
||||
#define LOCALE_EXPOSE_CUSTOM_CLASS_CONST_STR(name, value) zend_declare_class_constant_string( Locale_ce_ptr, ZEND_STRS( name ) - 1, value TSRMLS_CC );
|
||||
|
||||
LOCALE_EXPOSE_CLASS_CONST( ACTUAL_LOCALE );
|
||||
LOCALE_EXPOSE_CLASS_CONST( VALID_LOCALE );
|
||||
|
||||
zend_declare_class_constant_null(Locale_ce_ptr, ZEND_STRS("DEFAULT_LOCALE") - 1 TSRMLS_CC);
|
||||
|
||||
LOCALE_EXPOSE_CUSTOM_CLASS_CONST_STR( "LANG_TAG", LOC_LANG_TAG);
|
||||
LOCALE_EXPOSE_CUSTOM_CLASS_CONST_STR( "EXTLANG_TAG", LOC_EXTLANG_TAG);
|
||||
LOCALE_EXPOSE_CUSTOM_CLASS_CONST_STR( "SCRIPT_TAG", LOC_SCRIPT_TAG);
|
||||
LOCALE_EXPOSE_CUSTOM_CLASS_CONST_STR( "REGION_TAG", LOC_REGION_TAG);
|
||||
LOCALE_EXPOSE_CUSTOM_CLASS_CONST_STR( "VARIANT_TAG",LOC_VARIANT_TAG);
|
||||
LOCALE_EXPOSE_CUSTOM_CLASS_CONST_STR( "GRANDFATHERED_LANG_TAG",LOC_GRANDFATHERED_LANG_TAG);
|
||||
LOCALE_EXPOSE_CUSTOM_CLASS_CONST_STR( "PRIVATE_TAG",LOC_PRIVATE_TAG);
|
||||
|
||||
#undef LOCALE_EXPOSE_CUSTOM_CLASS_CONST_STR
|
||||
#undef LOCALE_EXPOSE_CLASS_CONST
|
||||
#undef LOCALE_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
|
||||
*/
|
36
ext/intl/locale/locale.h
Executable file
36
ext/intl/locale/locale.h
Executable file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Kirti Velankar <kirtig@yahoo-inc.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef LOCALE_LOCALE_H
|
||||
#define LOCALE_LOCALE_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
void locale_register_constants( INIT_FUNC_ARGS );
|
||||
|
||||
#define OPTION_DEFAULT NULL
|
||||
#define LOC_LANG_TAG "language"
|
||||
#define LOC_SCRIPT_TAG "script"
|
||||
#define LOC_REGION_TAG "region"
|
||||
#define LOC_VARIANT_TAG "variant"
|
||||
#define LOC_EXTLANG_TAG "extlang"
|
||||
#define LOC_GRANDFATHERED_LANG_TAG "grandfathered"
|
||||
#define LOC_PRIVATE_TAG "private"
|
||||
#define LOC_CANONICALIZE_TAG "canonicalize"
|
||||
|
||||
#define LOCALE_INI_NAME "intl.default_locale"
|
||||
|
||||
#endif // LOCALE_LOCALE_H
|
126
ext/intl/locale/locale_class.c
Executable file
126
ext/intl/locale/locale_class.c
Executable file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Kirti Velankar <kirtig@yahoo-inc.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include <unicode/uloc.h>
|
||||
|
||||
#include "php_intl.h"
|
||||
|
||||
#include "intl_error.h"
|
||||
#include "locale_class.h"
|
||||
#include "locale_methods.h"
|
||||
#include "locale.h"
|
||||
|
||||
zend_class_entry *Locale_ce_ptr = NULL;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// 'Locale' class registration structures & functions
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* {{{ Locale methods arguments info */
|
||||
// NOTE: modifying 'locale_XX_args' do not forget to
|
||||
// modify approptiate 'locale_XX_args' for
|
||||
// the procedural API.
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( locale_0_args, 0, 0, 0 )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( locale_1_arg, 0, 0, 1 )
|
||||
ZEND_ARG_INFO( 0, arg1 )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( locale_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( locale_3_args, 0, 0, 3 )
|
||||
ZEND_ARG_INFO( 0, arg1 )
|
||||
ZEND_ARG_INFO( 0, arg2 )
|
||||
ZEND_ARG_INFO( 0, arg3 )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( locale_4_args, 0, 0, 4 )
|
||||
ZEND_ARG_INFO( 0, arg1 )
|
||||
ZEND_ARG_INFO( 0, arg2 )
|
||||
ZEND_ARG_INFO( 0, arg3 )
|
||||
ZEND_ARG_INFO( 0, arg4 )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Locale_class_functions
|
||||
* Every 'Locale' class method has an entry in this table
|
||||
*/
|
||||
|
||||
function_entry Locale_class_functions[] = {
|
||||
ZEND_FENTRY( getDefault, zif_locale_get_default , locale_0_args , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( setDefault, zif_locale_set_default , locale_1_arg , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( getPrimaryLanguage, ZEND_FN( locale_get_primary_language ), locale_1_arg , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( getScript, ZEND_FN( locale_get_script ), locale_1_arg , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( getRegion, ZEND_FN( locale_get_region ), locale_1_arg , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( getKeywords, ZEND_FN( locale_get_keywords ), locale_1_arg , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( getDisplayScript, ZEND_FN( locale_get_display_script ), locale_2_args , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( getDisplayRegion, ZEND_FN( locale_get_display_region ), locale_2_args , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( getDisplayName, ZEND_FN( locale_get_display_name ), locale_2_args , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( getDisplayLanguage, ZEND_FN( locale_get_display_language ), locale_2_args , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( getDisplayVariant, ZEND_FN( locale_get_display_variant ), locale_2_args , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( composeLocale, ZEND_FN( locale_compose ), locale_1_arg , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( parseLocale, ZEND_FN( locale_parse ), locale_1_arg , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( getAllVariants, ZEND_FN( locale_get_all_variants ), locale_1_arg , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( filterMatches, ZEND_FN( locale_filter_matches ), locale_3_args, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( lookup, ZEND_FN( locale_lookup ), locale_4_args, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( canonicalize, ZEND_FN( locale_canonicalize ), locale_1_arg , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
/* {{{ locale_register_Locale_class
|
||||
* Initialize 'Locale' class
|
||||
*/
|
||||
void locale_register_Locale_class( TSRMLS_D )
|
||||
{
|
||||
zend_class_entry ce;
|
||||
|
||||
// Create and register 'Locale' class.
|
||||
INIT_CLASS_ENTRY( ce, "Locale", Locale_class_functions );
|
||||
ce.create_object = NULL;
|
||||
Locale_ce_ptr = zend_register_internal_class( &ce TSRMLS_CC );
|
||||
|
||||
// Declare 'Locale' class properties.
|
||||
if( !Locale_ce_ptr )
|
||||
{
|
||||
zend_error( E_ERROR,
|
||||
"Locale: Failed to register Locale class.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
46
ext/intl/locale/locale_class.h
Executable file
46
ext/intl/locale/locale_class.h
Executable file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Kirti Velankar <kirtig@yahoo-inc.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef LOCALE_CLASS_H
|
||||
#define LOCALE_CLASS_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
#include "intl_common.h"
|
||||
#include "intl_error.h"
|
||||
|
||||
#include <unicode/uloc.h>
|
||||
|
||||
typedef struct {
|
||||
zend_object zo;
|
||||
|
||||
// ICU locale
|
||||
char* uloc1;
|
||||
|
||||
} Locale_object;
|
||||
|
||||
|
||||
void locale_register_Locale_class( TSRMLS_D );
|
||||
|
||||
extern zend_class_entry *Locale_ce_ptr;
|
||||
|
||||
/* Auxiliary macros */
|
||||
|
||||
#define LOCALE_METHOD_INIT_VARS \
|
||||
zval* object = NULL; \
|
||||
intl_error_reset( NULL TSRMLS_CC ); \
|
||||
|
||||
#endif // #ifndef LOCALE_CLASS_H
|
1732
ext/intl/locale/locale_methods.c
Executable file
1732
ext/intl/locale/locale_methods.c
Executable file
File diff suppressed because it is too large
Load Diff
47
ext/intl/locale/locale_methods.h
Executable file
47
ext/intl/locale/locale_methods.h
Executable file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Kirti Velankar <kirtig@yahoo-inc.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef LOCALE_METHODS_H
|
||||
#define LOCALE_METHODS_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
|
||||
PHP_FUNCTION( locale_get_primary_language );
|
||||
PHP_FUNCTION( locale_get_script );
|
||||
PHP_FUNCTION( locale_get_region );
|
||||
PHP_FUNCTION( locale_get_all_variants);
|
||||
|
||||
PHP_NAMED_FUNCTION( zif_locale_get_default );
|
||||
PHP_NAMED_FUNCTION( zif_locale_set_default );
|
||||
|
||||
PHP_FUNCTION( locale_get_display_name );
|
||||
PHP_FUNCTION( locale_get_display_language );
|
||||
PHP_FUNCTION( locale_get_display_script );
|
||||
PHP_FUNCTION( locale_get_display_region );
|
||||
PHP_FUNCTION( locale_get_display_variant );
|
||||
|
||||
PHP_FUNCTION( locale_get_keywords );
|
||||
PHP_FUNCTION( locale_canonicalize);
|
||||
|
||||
PHP_FUNCTION( locale_compose);
|
||||
PHP_FUNCTION( locale_parse);
|
||||
|
||||
PHP_FUNCTION( locale_filter_matches);
|
||||
PHP_FUNCTION( locale_lookup);
|
||||
PHP_FUNCTION( locale_canonicalize);
|
||||
|
||||
#endif // LOCALE_METHODS_H
|
256
ext/intl/msgformat/msgformat.c
Executable file
256
ext/intl/msgformat/msgformat.c
Executable file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unicode/ustring.h>
|
||||
#include <unicode/umsg.h>
|
||||
|
||||
#include "php_intl.h"
|
||||
#include "msgformat_class.h"
|
||||
#include "intl_convert.h"
|
||||
|
||||
/* {{{ proto MessageFormatter MesssageFormatter::create( string $locale, string $pattern )
|
||||
* Create formatter. }}} */
|
||||
/* {{{ proto MessageFormatter msgfmt_create( string $locale, string $pattern )
|
||||
* Create formatter.
|
||||
*/
|
||||
PHP_FUNCTION( msgfmt_create )
|
||||
{
|
||||
char* locale;
|
||||
char* pattern;
|
||||
int locale_len = 0, pattern_len = 0;
|
||||
UChar* spattern = NULL;
|
||||
int spattern_len = 0;
|
||||
zval* object;
|
||||
MessageFormatter_object* mfo;
|
||||
|
||||
intl_error_reset( NULL TSRMLS_CC );
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "ss",
|
||||
&locale, &locale_len, &pattern, &pattern_len ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"msgfmt_create: unable to parse input parameters", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
INTL_CHECK_LOCALE_LEN(locale_len);
|
||||
// Create a MessageFormatter object and save the ICU formatter into it.
|
||||
if( ( object = getThis() ) == NULL )
|
||||
object = return_value;
|
||||
|
||||
if( Z_TYPE_P( object ) != IS_OBJECT )
|
||||
object_init_ex( object, MessageFormatter_ce_ptr );
|
||||
|
||||
MSG_FORMAT_METHOD_FETCH_OBJECT;
|
||||
|
||||
// Convert pattern (if specified) to UTF-16.
|
||||
if(pattern && pattern_len) {
|
||||
intl_convert_utf8_to_utf16(&spattern, &spattern_len, pattern, pattern_len, &INTL_DATA_ERROR_CODE(mfo));
|
||||
if( U_FAILURE( INTL_DATA_ERROR_CODE((mfo)) ) )
|
||||
{
|
||||
intl_error_set( NULL, INTL_DATA_ERROR_CODE( mfo ),
|
||||
"msgfmt_create: error converting pattern to UTF-16", 0 TSRMLS_CC );
|
||||
zval_dtor(return_value);
|
||||
RETURN_NULL();
|
||||
}
|
||||
} else {
|
||||
spattern_len = 0;
|
||||
spattern = NULL;
|
||||
}
|
||||
|
||||
if(locale_len == 0) {
|
||||
locale = INTL_G(default_locale);
|
||||
}
|
||||
|
||||
if(msfgotmat_fix_quotes(&spattern, &spattern_len, &INTL_DATA_ERROR_CODE(mfo)) != SUCCESS) {
|
||||
intl_error_set( NULL, U_INVALID_FORMAT_ERROR,
|
||||
"msgfmt_create: error converting pattern to quote-friendly format", 0 TSRMLS_CC );
|
||||
zval_dtor(return_value);
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
(mfo)->mf_data.orig_format = estrndup(pattern, pattern_len);
|
||||
(mfo)->mf_data.orig_format_len = pattern_len;
|
||||
|
||||
// Create an ICU message formatter.
|
||||
MSG_FORMAT_OBJECT(mfo) = umsg_open(spattern, spattern_len, locale, NULL, &INTL_DATA_ERROR_CODE(mfo));
|
||||
|
||||
if(spattern) {
|
||||
efree(spattern);
|
||||
}
|
||||
|
||||
if( U_FAILURE( INTL_DATA_ERROR_CODE((mfo)) ) )
|
||||
{
|
||||
intl_error_set( NULL, INTL_DATA_ERROR_CODE( mfo ),
|
||||
"msgfmt_create: message formatter creation failed", 0 TSRMLS_CC );
|
||||
zval_dtor(return_value);
|
||||
RETURN_NULL();
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto void MessageFormatter::__construct( string $locale, string $pattern )
|
||||
* MessageFormatter object constructor.
|
||||
*/
|
||||
PHP_METHOD( MessageFormatter, __construct )
|
||||
{
|
||||
char* locale;
|
||||
char* pattern;
|
||||
int locale_len, pattern_len = 0;
|
||||
UChar* spattern = NULL;
|
||||
int spattern_len = 0;
|
||||
zval* object;
|
||||
MessageFormatter_object* mfo;
|
||||
|
||||
intl_error_reset( NULL TSRMLS_CC );
|
||||
|
||||
object = getThis();
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "ss",
|
||||
&locale, &locale_len, &pattern, &pattern_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);
|
||||
mfo = (MessageFormatter_object *) zend_object_store_get_object( object TSRMLS_CC );
|
||||
|
||||
intl_error_reset( &mfo->mf_data.error TSRMLS_CC );
|
||||
|
||||
// Convert pattern to UTF-16.
|
||||
if(pattern && pattern_len) {
|
||||
intl_convert_utf8_to_utf16(&spattern, &spattern_len, pattern, pattern_len, &INTL_DATA_ERROR_CODE(mfo));
|
||||
if( U_FAILURE( INTL_DATA_ERROR_CODE((mfo)) ) )
|
||||
{
|
||||
intl_error_set( NULL, INTL_DATA_ERROR_CODE( mfo ),
|
||||
"__construct: Error converting pattern to UTF-16", 0 TSRMLS_CC );
|
||||
zval_dtor(object);
|
||||
ZVAL_NULL(object);
|
||||
RETURN_NULL();
|
||||
}
|
||||
} else {
|
||||
spattern_len = 0;
|
||||
spattern = NULL;
|
||||
}
|
||||
|
||||
if(locale_len == 0) {
|
||||
locale = INTL_G(default_locale);
|
||||
}
|
||||
|
||||
if(msfgotmat_fix_quotes(&spattern, &spattern_len, &INTL_DATA_ERROR_CODE(mfo)) != SUCCESS) {
|
||||
intl_error_set( NULL, U_INVALID_FORMAT_ERROR,
|
||||
"__construct: error converting pattern to quote-friendly format", 0 TSRMLS_CC );
|
||||
zval_dtor(object);
|
||||
ZVAL_NULL(object);
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
(mfo)->mf_data.orig_format = estrndup(pattern, pattern_len);
|
||||
(mfo)->mf_data.orig_format_len = pattern_len;
|
||||
|
||||
// Create an ICU message formatter.
|
||||
MSG_FORMAT_OBJECT(mfo) = umsg_open(spattern, spattern_len, locale, NULL, &INTL_DATA_ERROR_CODE(mfo));
|
||||
|
||||
if(spattern && spattern_len) {
|
||||
efree(spattern);
|
||||
}
|
||||
|
||||
if( U_FAILURE( INTL_DATA_ERROR_CODE((mfo)) ) )
|
||||
{
|
||||
intl_error_set( NULL, INTL_DATA_ERROR_CODE(mfo),
|
||||
"__construct: message formatter creation failed", 0 TSRMLS_CC );
|
||||
zval_dtor(object);
|
||||
ZVAL_NULL(object);
|
||||
RETURN_NULL();
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int MessageFormatter::getErrorCode()
|
||||
* Get formatter's last error code. }}} */
|
||||
/* {{{ proto int msgfmt_get_error_code( MessageFormatter $nf )
|
||||
* Get formatter's last error code.
|
||||
*/
|
||||
PHP_FUNCTION( msgfmt_get_error_code )
|
||||
{
|
||||
zval* object = NULL;
|
||||
MessageFormatter_object* mfo = NULL;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
|
||||
&object, MessageFormatter_ce_ptr ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"msgfmt_get_error_code: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
mfo = (MessageFormatter_object *) zend_object_store_get_object( object TSRMLS_CC );
|
||||
|
||||
// Return formatter's last error code.
|
||||
RETURN_LONG( INTL_DATA_ERROR_CODE(mfo) );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string MessageFormatter::getErrorMessage( )
|
||||
* Get text description for formatter's last error code. }}} */
|
||||
/* {{{ proto string msgfmt_get_error_message( MessageFormatter $coll )
|
||||
* Get text description for formatter's last error code.
|
||||
*/
|
||||
PHP_FUNCTION( msgfmt_get_error_message )
|
||||
{
|
||||
char* message = NULL;
|
||||
zval* object = NULL;
|
||||
MessageFormatter_object* mfo = NULL;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
|
||||
&object, MessageFormatter_ce_ptr ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"msgfmt_get_error_message: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
mfo = (MessageFormatter_object *) zend_object_store_get_object( object TSRMLS_CC );
|
||||
|
||||
// Return last error message.
|
||||
message = intl_error_get_message( &mfo->mf_data.error TSRMLS_CC );
|
||||
RETURN_STRING( message, 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
|
||||
*/
|
27
ext/intl/msgformat/msgformat.h
Executable file
27
ext/intl/msgformat/msgformat.h
Executable file
@ -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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef MSG_FORMATTER_H
|
||||
#define MSG_FORMATTER_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
PHP_FUNCTION( msgfmt_create );
|
||||
PHP_FUNCTION( msgfmt_get_error_code );
|
||||
PHP_FUNCTION( msgfmt_get_error_message );
|
||||
PHP_METHOD( MessageFormatter, __construct );
|
||||
|
||||
#endif // MSG_FORMAT_H
|
144
ext/intl/msgformat/msgformat_attr.c
Executable file
144
ext/intl/msgformat/msgformat_attr.c
Executable file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "php_intl.h"
|
||||
#include "msgformat_class.h"
|
||||
#include "msgformat_attr.h"
|
||||
#include "intl_convert.h"
|
||||
|
||||
#include <unicode/ustring.h>
|
||||
|
||||
|
||||
/* {{{ proto string MessageFormatter::getPattern( )
|
||||
* Get formatter pattern. }}} */
|
||||
/* {{{ proto string msgfmt_get_pattern( MessageFormatter $mf )
|
||||
* Get formatter pattern.
|
||||
*/
|
||||
PHP_FUNCTION( msgfmt_get_pattern )
|
||||
{
|
||||
UChar value_buf[64];
|
||||
int length = USIZE( value_buf );
|
||||
UChar* value = value_buf;
|
||||
MSG_FORMAT_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, MessageFormatter_ce_ptr ) == FAILURE )
|
||||
{
|
||||
intl_error_set( INTL_DATA_ERROR_P(mfo), U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"msgfmt_get_pattern: unable to parse input params", 0 TSRMLS_CC );
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
MSG_FORMAT_METHOD_FETCH_OBJECT;
|
||||
|
||||
if(mfo->mf_data.orig_format) {
|
||||
RETURN_STRINGL(mfo->mf_data.orig_format, mfo->mf_data.orig_format_len, 1);
|
||||
}
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool MessageFormatter::setPattern( string $pattern )
|
||||
* Set formatter pattern. }}} */
|
||||
/* {{{ proto bool msgfmt_set_pattern( MessageFormatter $mf, string $pattern )
|
||||
* Set formatter pattern.
|
||||
*/
|
||||
PHP_FUNCTION( msgfmt_set_pattern )
|
||||
{
|
||||
char* value = NULL;
|
||||
int value_len = 0;
|
||||
int spattern_len = 0;
|
||||
UChar* spattern = NULL;
|
||||
MSG_FORMAT_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os",
|
||||
&object, MessageFormatter_ce_ptr, &value, &value_len ) == FAILURE )
|
||||
{
|
||||
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"msgfmt_set_pattern: unable to parse input params", 0 TSRMLS_CC);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
MSG_FORMAT_METHOD_FETCH_OBJECT;
|
||||
|
||||
// Convert given pattern to UTF-16.
|
||||
intl_convert_utf8_to_utf16(&spattern, &spattern_len, value, value_len, &INTL_DATA_ERROR_CODE(mfo));
|
||||
INTL_METHOD_CHECK_STATUS(mfo, "Error converting pattern to UTF-16" );
|
||||
|
||||
if(msfgotmat_fix_quotes(&spattern, &spattern_len, &INTL_DATA_ERROR_CODE(mfo)) != SUCCESS) {
|
||||
intl_error_set( NULL, U_INVALID_FORMAT_ERROR,
|
||||
"msgfmt_set_pattern: error converting pattern to quote-friendly format", 0 TSRMLS_CC );
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// TODO: add parse error information
|
||||
umsg_applyPattern(MSG_FORMAT_OBJECT(mfo), spattern, spattern_len, NULL, &INTL_DATA_ERROR_CODE(mfo));
|
||||
efree(spattern);
|
||||
INTL_METHOD_CHECK_STATUS(mfo, "Error setting symbol value");
|
||||
|
||||
if(mfo->mf_data.orig_format) {
|
||||
efree(mfo->mf_data.orig_format);
|
||||
}
|
||||
mfo->mf_data.orig_format = estrndup(value, value_len);
|
||||
mfo->mf_data.orig_format_len = value_len;
|
||||
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string MessageFormatter::getLocale()
|
||||
* Get formatter locale. }}} */
|
||||
/* {{{ proto string msgfmt_get_locale(MessageFormatter $mf)
|
||||
* Get formatter locale.
|
||||
*/
|
||||
PHP_FUNCTION( msgfmt_get_locale )
|
||||
{
|
||||
char *loc;
|
||||
MSG_FORMAT_METHOD_INIT_VARS;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
|
||||
&object, MessageFormatter_ce_ptr ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"msgfmt_get_locale: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
MSG_FORMAT_METHOD_FETCH_OBJECT;
|
||||
|
||||
loc = (char *)umsg_getLocale(MSG_FORMAT_OBJECT(mfo));
|
||||
RETURN_STRING(loc, 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
26
ext/intl/msgformat/msgformat_attr.h
Executable file
26
ext/intl/msgformat/msgformat_attr.h
Executable file
@ -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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef MSG_FORMAT_ATTR_H
|
||||
#define MSG_FORMAT_ATTR_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
PHP_FUNCTION( msgfmt_set_pattern );
|
||||
PHP_FUNCTION( msgfmt_get_pattern );
|
||||
PHP_FUNCTION( msgfmt_get_locale );
|
||||
|
||||
#endif // MSG_FORMAT_ATTR_H
|
127
ext/intl/msgformat/msgformat_class.c
Executable file
127
ext/intl/msgformat/msgformat_class.c
Executable file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include <unicode/unum.h>
|
||||
|
||||
#include "msgformat_class.h"
|
||||
#include "php_intl.h"
|
||||
#include "msgformat_data.h"
|
||||
#include "msgformat_format.h"
|
||||
#include "msgformat_parse.h"
|
||||
#include "msgformat.h"
|
||||
#include "msgformat_attr.h"
|
||||
|
||||
zend_class_entry *MessageFormatter_ce_ptr = NULL;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Auxiliary functions needed by objects of 'MessageFormatter' class
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* {{{ MessageFormatter_objects_dtor */
|
||||
static void MessageFormatter_object_dtor(void *object, zend_object_handle handle TSRMLS_DC )
|
||||
{
|
||||
zend_objects_destroy_object( object, handle TSRMLS_CC );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ MessageFormatter_objects_free */
|
||||
void MessageFormatter_object_free( zend_object *object TSRMLS_DC )
|
||||
{
|
||||
MessageFormatter_object* mfo = (MessageFormatter_object*)object;
|
||||
|
||||
zend_object_std_dtor( &mfo->zo TSRMLS_CC );
|
||||
|
||||
msgformat_data_free( &mfo->mf_data TSRMLS_CC );
|
||||
|
||||
efree( mfo );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ MessageFormatter_object_create */
|
||||
zend_object_value MessageFormatter_object_create(zend_class_entry *ce TSRMLS_DC)
|
||||
{
|
||||
zend_object_value retval;
|
||||
MessageFormatter_object* intern;
|
||||
|
||||
intern = ecalloc( 1, sizeof(MessageFormatter_object) );
|
||||
msgformat_data_init( &intern->mf_data TSRMLS_CC );
|
||||
zend_object_std_init( &intern->zo, ce TSRMLS_CC );
|
||||
|
||||
retval.handle = zend_objects_store_put(
|
||||
intern,
|
||||
MessageFormatter_object_dtor,
|
||||
(zend_objects_free_object_storage_t)MessageFormatter_object_free,
|
||||
NULL TSRMLS_CC );
|
||||
|
||||
retval.handlers = zend_get_std_object_handlers();
|
||||
|
||||
return retval;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// 'MessageFormatter' class registration structures & functions
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* {{{ MessageFormatter_class_functions
|
||||
* Every 'MessageFormatter' class method has an entry in this table
|
||||
*/
|
||||
|
||||
static function_entry MessageFormatter_class_functions[] = {
|
||||
PHP_ME( MessageFormatter, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR )
|
||||
ZEND_FENTRY( create, ZEND_FN( msgfmt_create ), NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
PHP_NAMED_FE( format, ZEND_FN( msgfmt_format ), NULL )
|
||||
ZEND_FENTRY( formatMessage, ZEND_FN( msgfmt_format_message ), NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
PHP_NAMED_FE( parse, ZEND_FN( msgfmt_parse ), NULL )
|
||||
ZEND_FENTRY( parseMessage, ZEND_FN( msgfmt_parse_message ), NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
PHP_NAMED_FE( setPattern, ZEND_FN( msgfmt_set_pattern ), NULL )
|
||||
PHP_NAMED_FE( getPattern, ZEND_FN( msgfmt_get_pattern ), NULL )
|
||||
PHP_NAMED_FE( getLocale, ZEND_FN( msgfmt_get_locale ), NULL )
|
||||
PHP_NAMED_FE( getErrorCode, ZEND_FN( msgfmt_get_error_code ), NULL )
|
||||
PHP_NAMED_FE( getErrorMessage, ZEND_FN( msgfmt_get_error_message ), NULL )
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
/* {{{ msgformat_register_class
|
||||
* Initialize 'MessageFormatter' class
|
||||
*/
|
||||
void msgformat_register_class( TSRMLS_D )
|
||||
{
|
||||
zend_class_entry ce;
|
||||
|
||||
// Create and register 'MessageFormatter' class.
|
||||
INIT_CLASS_ENTRY( ce, "MessageFormatter", MessageFormatter_class_functions );
|
||||
ce.create_object = MessageFormatter_object_create;
|
||||
MessageFormatter_ce_ptr = zend_register_internal_class( &ce TSRMLS_CC );
|
||||
|
||||
// Declare 'MessageFormatter' class properties.
|
||||
if( !MessageFormatter_ce_ptr )
|
||||
{
|
||||
zend_error(E_ERROR, "Failed to register MessageFormatter class");
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
41
ext/intl/msgformat/msgformat_class.h
Executable file
41
ext/intl/msgformat/msgformat_class.h
Executable file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef MSG_FORMAT_CLASS_H
|
||||
#define MSG_FORMAT_CLASS_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
#include "intl_common.h"
|
||||
#include "intl_error.h"
|
||||
#include "intl_data.h"
|
||||
#include "msgformat_data.h"
|
||||
|
||||
typedef struct {
|
||||
zend_object zo;
|
||||
msgformat_data mf_data;
|
||||
} MessageFormatter_object;
|
||||
|
||||
void msgformat_register_class( TSRMLS_D );
|
||||
extern zend_class_entry *MessageFormatter_ce_ptr;
|
||||
|
||||
/* Auxiliary macros */
|
||||
|
||||
#define MSG_FORMAT_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(MessageFormatter, mfo)
|
||||
#define MSG_FORMAT_METHOD_FETCH_OBJECT INTL_METHOD_FETCH_OBJECT(MessageFormatter, mfo)
|
||||
#define MSG_FORMAT_OBJECT(mfo) (mfo)->mf_data.umsgf
|
||||
|
||||
#endif // #ifndef MSG_FORMAT_CLASS_H
|
98
ext/intl/msgformat/msgformat_data.c
Executable file
98
ext/intl/msgformat/msgformat_data.c
Executable file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unicode/ustring.h>
|
||||
#include "msgformat_data.h"
|
||||
|
||||
/* {{{ void msgformat_data_init( msgformat_data* mf_data )
|
||||
* Initialize internals of msgformat_data.
|
||||
*/
|
||||
void msgformat_data_init( msgformat_data* mf_data TSRMLS_DC )
|
||||
{
|
||||
if( !mf_data )
|
||||
return;
|
||||
|
||||
mf_data->umsgf = NULL;
|
||||
mf_data->orig_format = NULL;
|
||||
intl_error_reset( &mf_data->error TSRMLS_CC );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void msgformat_data_free( msgformat_data* mf_data )
|
||||
* Clean up memory allocated for msgformat_data
|
||||
*/
|
||||
void msgformat_data_free( msgformat_data* mf_data TSRMLS_DC )
|
||||
{
|
||||
if( !mf_data )
|
||||
return;
|
||||
|
||||
if( mf_data->umsgf )
|
||||
umsg_close( mf_data->umsgf );
|
||||
|
||||
if(mf_data->orig_format) {
|
||||
efree(mf_data->orig_format);
|
||||
mf_data->orig_format = NULL;
|
||||
}
|
||||
|
||||
mf_data->umsgf = NULL;
|
||||
intl_error_reset( &mf_data->error TSRMLS_CC );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ msgformat_data* msgformat_data_create()
|
||||
* Allocate memory for msgformat_data and initialize it with default values.
|
||||
*/
|
||||
msgformat_data* msgformat_data_create( TSRMLS_D )
|
||||
{
|
||||
msgformat_data* mf_data = ecalloc( 1, sizeof(msgformat_data) );
|
||||
|
||||
msgformat_data_init( mf_data TSRMLS_CC );
|
||||
|
||||
return mf_data;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int msfgotmat_fix_quotes(UChar **spattern, uint32_t *spattern_len, UErrorCode *ec)
|
||||
{
|
||||
if(*spattern && *spattern_len && u_strchr(*spattern, (UChar)'\'')) {
|
||||
UChar *npattern = emalloc(sizeof(UChar)*(2*(*spattern_len)+1));
|
||||
uint32_t npattern_len;
|
||||
npattern_len = umsg_autoQuoteApostrophe(*spattern, *spattern_len, npattern, 2*(*spattern_len)+1, ec);
|
||||
efree(*spattern);
|
||||
if( U_FAILURE(*ec) )
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
npattern = erealloc(npattern, sizeof(UChar)*(npattern_len+1));
|
||||
*spattern = npattern;
|
||||
*spattern_len = npattern_len;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
41
ext/intl/msgformat/msgformat_data.h
Executable file
41
ext/intl/msgformat/msgformat_data.h
Executable file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef MSG_FORMAT_DATA_H
|
||||
#define MSG_FORMAT_DATA_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
#include <unicode/umsg.h>
|
||||
|
||||
#include "intl_error.h"
|
||||
|
||||
typedef struct {
|
||||
// error hangling
|
||||
intl_error error;
|
||||
|
||||
// formatter handling
|
||||
UMessageFormat* umsgf;
|
||||
char* orig_format;
|
||||
ulong orig_format_len;
|
||||
} msgformat_data;
|
||||
|
||||
msgformat_data* msgformat_data_create( TSRMLS_D );
|
||||
void msgformat_data_init( msgformat_data* mf_data TSRMLS_DC );
|
||||
void msgformat_data_free( msgformat_data* mf_data TSRMLS_DC );
|
||||
int msfgotmat_fix_quotes(UChar **spattern, uint32_t *spattern_len, UErrorCode *ec);
|
||||
|
||||
#endif // MSG_FORMAT_DATA_H
|
184
ext/intl/msgformat/msgformat_format.c
Executable file
184
ext/intl/msgformat/msgformat_format.c
Executable file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unicode/ustring.h>
|
||||
|
||||
#include "php_intl.h"
|
||||
#include "msgformat_class.h"
|
||||
#include "msgformat_format.h"
|
||||
#include "msgformat_data.h"
|
||||
#include "msgformat_helpers.h"
|
||||
#include "intl_convert.h"
|
||||
|
||||
#ifndef Z_ADDREF_P
|
||||
#define Z_ADDREF_P(z) ((z)->refcount++)
|
||||
#endif
|
||||
|
||||
/* {{{ */
|
||||
static void msgfmt_do_format(MessageFormatter_object *mfo, zval *args, zval *return_value TSRMLS_DC)
|
||||
{
|
||||
zval **fargs;
|
||||
int count;
|
||||
UChar* formatted = NULL;
|
||||
int formatted_len = 0;
|
||||
HashPosition pos;
|
||||
int i;
|
||||
|
||||
count = zend_hash_num_elements(Z_ARRVAL_P(args));
|
||||
|
||||
if(count < umsg_format_arg_count(MSG_FORMAT_OBJECT(mfo))) {
|
||||
// Not enough aguments for format!
|
||||
intl_error_set( INTL_DATA_ERROR_P(mfo), U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"msgfmt_format: not enough parameters", 0 TSRMLS_CC );
|
||||
RETVAL_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
fargs = safe_emalloc(count, sizeof(zval *), 0);
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos);
|
||||
for(i=0;i<count;i++) {
|
||||
zval **val;
|
||||
zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void **)&val, &pos);
|
||||
fargs[i] = *val;
|
||||
Z_ADDREF_P(fargs[i]);
|
||||
/* TODO: needs refcount increase here? */
|
||||
zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos);
|
||||
}
|
||||
|
||||
umsg_format_helper(MSG_FORMAT_OBJECT(mfo), count, fargs, &formatted, &formatted_len, &INTL_DATA_ERROR_CODE(mfo) TSRMLS_CC);
|
||||
|
||||
for(i=0;i<count;i++) {
|
||||
zval_ptr_dtor(&fargs[i]);
|
||||
}
|
||||
|
||||
efree(fargs);
|
||||
|
||||
if (formatted && U_FAILURE( INTL_DATA_ERROR_CODE(mfo) ) ) {
|
||||
efree(formatted);
|
||||
}
|
||||
|
||||
INTL_METHOD_CHECK_STATUS( mfo, "Number formatting failed" );
|
||||
INTL_METHOD_RETVAL_UTF8( mfo, formatted, formatted_len, 1 );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto mixed MessageFormatter::format( array $args )
|
||||
* Format a message. }}} */
|
||||
/* {{{ proto mixed msgfmt_format( MessageFormatter $nf, array $args )
|
||||
* Format a message.
|
||||
*/
|
||||
PHP_FUNCTION( msgfmt_format )
|
||||
{
|
||||
zval *args;
|
||||
MSG_FORMAT_METHOD_INIT_VARS;
|
||||
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oa",
|
||||
&object, MessageFormatter_ce_ptr, &args ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"msgfmt_format: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
MSG_FORMAT_METHOD_FETCH_OBJECT;
|
||||
|
||||
msgfmt_do_format(mfo, args, return_value TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto mixed MessageFormatter::formatMessage( string $locale, string $pattern, array $args )
|
||||
* Format a message. }}} */
|
||||
/* {{{ proto mixed msgfmt_format_message( string $locale, string $pattern, array $args )
|
||||
* Format a message.
|
||||
*/
|
||||
PHP_FUNCTION( msgfmt_format_message )
|
||||
{
|
||||
zval *args;
|
||||
UChar *spattern = NULL;
|
||||
int spattern_len = 0;
|
||||
char *pattern = NULL;
|
||||
int pattern_len = 0;
|
||||
char *slocale = NULL;
|
||||
int slocale_len = 0;
|
||||
MessageFormatter_object mf = {0};
|
||||
MessageFormatter_object *mfo = &mf;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "ssa",
|
||||
&slocale, &slocale_len, &pattern, &pattern_len, &args ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"msgfmt_format_message: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
msgformat_data_init(&mfo->mf_data TSRMLS_CC);
|
||||
|
||||
if(pattern && pattern_len) {
|
||||
intl_convert_utf8_to_utf16(&spattern, &spattern_len, pattern, pattern_len, &INTL_DATA_ERROR_CODE(mfo));
|
||||
if( U_FAILURE(INTL_DATA_ERROR_CODE((mfo))) )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"msgfmt_format_message: error converting pattern to UTF-16", 0 TSRMLS_CC );
|
||||
RETURN_FALSE;
|
||||
}
|
||||
} else {
|
||||
spattern_len = 0;
|
||||
spattern = NULL;
|
||||
}
|
||||
|
||||
if(slocale_len == 0) {
|
||||
slocale = INTL_G(default_locale);
|
||||
}
|
||||
|
||||
if(msfgotmat_fix_quotes(&spattern, &spattern_len, &INTL_DATA_ERROR_CODE(mfo)) != SUCCESS) {
|
||||
intl_error_set( NULL, U_INVALID_FORMAT_ERROR,
|
||||
"msgfmt_format_message: error converting pattern to quote-friendly format", 0 TSRMLS_CC );
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Create an ICU message formatter.
|
||||
MSG_FORMAT_OBJECT(mfo) = umsg_open(spattern, spattern_len, slocale, NULL, &INTL_DATA_ERROR_CODE(mfo));
|
||||
if(spattern && spattern_len) {
|
||||
efree(spattern);
|
||||
}
|
||||
INTL_METHOD_CHECK_STATUS(mfo, "Creating message formatter failed");
|
||||
|
||||
msgfmt_do_format(mfo, args, return_value TSRMLS_CC);
|
||||
|
||||
// drop the temporary formatter
|
||||
msgformat_data_free(&mfo->mf_data 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
|
||||
*/
|
25
ext/intl/msgformat/msgformat_format.h
Executable file
25
ext/intl/msgformat/msgformat_format.h
Executable file
@ -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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef MSG_FORMAT_FORMAT_H
|
||||
#define MSG_FORMAT_FORMAT_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
PHP_FUNCTION( msgfmt_format );
|
||||
PHP_FUNCTION( msgfmt_format_message );
|
||||
|
||||
#endif // MSG_FORMAT_FORMAT_H
|
211
ext/intl/msgformat/msgformat_helpers.cpp
Executable file
211
ext/intl/msgformat/msgformat_helpers.cpp
Executable file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <unicode/msgfmt.h>
|
||||
|
||||
extern "C" {
|
||||
#include "php_intl.h"
|
||||
#include "msgformat_class.h"
|
||||
#include "msgformat_format.h"
|
||||
#include "msgformat_helpers.h"
|
||||
#include "intl_convert.h"
|
||||
}
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
/**
|
||||
* This class isolates our access to private internal methods of
|
||||
* MessageFormat. It is never instantiated; it exists only for C++
|
||||
* access management.
|
||||
*/
|
||||
class MessageFormatAdapter {
|
||||
public:
|
||||
static const Formattable::Type* getArgTypeList(const MessageFormat& m,
|
||||
int32_t& count);
|
||||
};
|
||||
const Formattable::Type*
|
||||
MessageFormatAdapter::getArgTypeList(const MessageFormat& m,
|
||||
int32_t& count) {
|
||||
return m.getArgTypeList(count);
|
||||
}
|
||||
U_NAMESPACE_END
|
||||
|
||||
U_CFUNC int32_t umsg_format_arg_count(UMessageFormat *fmt)
|
||||
{
|
||||
int32_t fmt_count = 0;
|
||||
MessageFormatAdapter::getArgTypeList(*(const MessageFormat*)fmt, fmt_count);
|
||||
return fmt_count;
|
||||
}
|
||||
|
||||
U_CFUNC void umsg_format_helper(UMessageFormat *fmt, int arg_count, zval **args, UChar **formatted, int *formatted_len, UErrorCode *status TSRMLS_DC)
|
||||
{
|
||||
int fmt_count = 0;
|
||||
const Formattable::Type* argTypes =
|
||||
MessageFormatAdapter::getArgTypeList(*(const MessageFormat*)fmt, fmt_count);
|
||||
Formattable* fargs = new Formattable[fmt_count ? fmt_count : 1];
|
||||
|
||||
for(int32_t i = 0; i < fmt_count; ++i) {
|
||||
UChar *stringVal = NULL;
|
||||
int stringLen = 0;
|
||||
int64_t tInt64 = 0;
|
||||
|
||||
switch(argTypes[i]) {
|
||||
case Formattable::kDate:
|
||||
convert_to_long_ex(&args[i]);
|
||||
fargs[i].setDate(U_MILLIS_PER_SECOND * (double)Z_LVAL_P(args[i]));
|
||||
break;
|
||||
|
||||
case Formattable::kDouble:
|
||||
convert_to_double_ex(&args[i]);
|
||||
fargs[i].setDouble(Z_DVAL_P(args[i]));
|
||||
break;
|
||||
|
||||
case Formattable::kLong:
|
||||
convert_to_long_ex(&args[i]);
|
||||
fargs[i].setLong(Z_LVAL_P(args[i]));
|
||||
break;
|
||||
|
||||
case Formattable::kInt64:
|
||||
if(Z_TYPE_P(args[i]) == IS_DOUBLE) {
|
||||
tInt64 = (int64_t)Z_DVAL_P(args[i]);
|
||||
} else if(Z_TYPE_P(args[i]) == IS_LONG) {
|
||||
tInt64 = (int64_t)Z_LVAL_P(args[i]);
|
||||
} else {
|
||||
SEPARATE_ZVAL_IF_NOT_REF(&args[i]);
|
||||
convert_scalar_to_number( args[i] TSRMLS_CC );
|
||||
tInt64 = (Z_TYPE_P(args[i]) == IS_DOUBLE)?(int64_t)Z_DVAL_P(args[i]):Z_LVAL_P(args[i]);
|
||||
}
|
||||
fargs[i].setInt64(tInt64);
|
||||
break;
|
||||
|
||||
case Formattable::kString:
|
||||
convert_to_string_ex(&args[i]);
|
||||
intl_convert_utf8_to_utf16(&stringVal, &stringLen, Z_STRVAL_P(args[i]), Z_STRLEN_P(args[i]), status);
|
||||
if(U_FAILURE(*status)){
|
||||
delete[] fargs;
|
||||
return;
|
||||
}
|
||||
fargs[i].setString(stringVal);
|
||||
efree(stringVal);
|
||||
break;
|
||||
|
||||
case Formattable::kArray:
|
||||
case Formattable::kObject:
|
||||
*status = U_UNSUPPORTED_ERROR;
|
||||
delete[] fargs;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UnicodeString resultStr;
|
||||
FieldPosition fieldPosition(0);
|
||||
|
||||
/* format the message */
|
||||
((const MessageFormat*)fmt)->format(fargs, fmt_count, resultStr, fieldPosition, *status);
|
||||
|
||||
delete[] fargs;
|
||||
|
||||
if(U_FAILURE(*status)){
|
||||
return;
|
||||
}
|
||||
|
||||
*formatted_len = resultStr.length();
|
||||
*formatted = eumalloc(*formatted_len+1);
|
||||
resultStr.extract(*formatted, *formatted_len+1, *status);
|
||||
}
|
||||
|
||||
#define cleanup_zvals() for(int j=i;j>=0;j--) { zval_ptr_dtor((*args)+i); }
|
||||
|
||||
U_CFUNC void umsg_parse_helper(UMessageFormat *fmt, int *count, zval ***args, UChar *source, int source_len, UErrorCode *status)
|
||||
{
|
||||
UnicodeString srcString(source, source_len);
|
||||
Formattable *fargs = ((const MessageFormat*)fmt)->parse(srcString, *count, *status);
|
||||
|
||||
if(U_FAILURE(*status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
*args = (zval **)safe_emalloc(*count, sizeof(zval *), 0);
|
||||
|
||||
// assign formattables to varargs
|
||||
for(int32_t i = 0; i < *count; i++) {
|
||||
int64_t aInt64;
|
||||
double aDate;
|
||||
UnicodeString temp;
|
||||
char *stmp;
|
||||
int stmp_len;
|
||||
|
||||
ALLOC_INIT_ZVAL((*args)[i]);
|
||||
|
||||
switch(fargs[i].getType()) {
|
||||
case Formattable::kDate:
|
||||
aDate = ((double)fargs[i].getDate())/U_MILLIS_PER_SECOND;
|
||||
if(aDate > LONG_MAX || aDate < -LONG_MAX) {
|
||||
ZVAL_DOUBLE((*args)[i], aDate<0?ceil(aDate):floor(aDate));
|
||||
} else {
|
||||
ZVAL_LONG((*args)[i], (long)aDate);
|
||||
}
|
||||
break;
|
||||
|
||||
case Formattable::kDouble:
|
||||
ZVAL_DOUBLE((*args)[i], (double)fargs[i].getDouble());
|
||||
break;
|
||||
|
||||
case Formattable::kLong:
|
||||
ZVAL_LONG((*args)[i], fargs[i].getLong());
|
||||
break;
|
||||
|
||||
case Formattable::kInt64:
|
||||
aInt64 = fargs[i].getInt64();
|
||||
if(aInt64 > LONG_MAX || aInt64 < -LONG_MAX) {
|
||||
ZVAL_DOUBLE((*args)[i], (double)aInt64);
|
||||
} else {
|
||||
ZVAL_LONG((*args)[i], (long)aInt64);
|
||||
}
|
||||
break;
|
||||
|
||||
case Formattable::kString:
|
||||
fargs[i].getString(temp);
|
||||
intl_convert_utf16_to_utf8(&stmp, &stmp_len, temp.getBuffer(), temp.length(), status);
|
||||
if(U_FAILURE(*status)) {
|
||||
cleanup_zvals();
|
||||
return;
|
||||
}
|
||||
ZVAL_STRINGL((*args)[i], stmp, stmp_len, 0);
|
||||
break;
|
||||
|
||||
case Formattable::kObject:
|
||||
case Formattable::kArray:
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
cleanup_zvals();
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete[] fargs;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
25
ext/intl/msgformat/msgformat_helpers.h
Executable file
25
ext/intl/msgformat/msgformat_helpers.h
Executable file
@ -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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef MSG_FORMAT_HELPERS_H
|
||||
#define MSG_FORMAT_HELPERS_H
|
||||
|
||||
int32_t umsg_format_arg_count(UMessageFormat *fmt);
|
||||
void umsg_format_helper(UMessageFormat *fmt, int arg_count, zval **args,
|
||||
UChar **formatted, int *formatted_len, UErrorCode *status TSRMLS_DC);
|
||||
void umsg_parse_helper(UMessageFormat *fmt, int *count, zval ***args,
|
||||
UChar *source, int source_len, UErrorCode *status);
|
||||
#endif // MSG_FORMAT_HELPERS_H
|
157
ext/intl/msgformat/msgformat_parse.c
Executable file
157
ext/intl/msgformat/msgformat_parse.c
Executable file
@ -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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unicode/ustring.h>
|
||||
|
||||
#include "php_intl.h"
|
||||
#include "msgformat_class.h"
|
||||
#include "msgformat_parse.h"
|
||||
#include "msgformat_data.h"
|
||||
#include "msgformat_helpers.h"
|
||||
#include "intl_convert.h"
|
||||
|
||||
/* {{{ */
|
||||
static void msgfmt_do_parse(MessageFormatter_object *mfo, char *source, int src_len, zval *return_value TSRMLS_DC)
|
||||
{
|
||||
zval **fargs;
|
||||
int count = 0;
|
||||
int i;
|
||||
UChar *usource = NULL;
|
||||
int usrc_len = 0;
|
||||
|
||||
intl_convert_utf8_to_utf16(&usource, &usrc_len, source, src_len, &INTL_DATA_ERROR_CODE(mfo));
|
||||
INTL_METHOD_CHECK_STATUS(mfo, "Converting parse string failed");
|
||||
|
||||
umsg_parse_helper(MSG_FORMAT_OBJECT(mfo), &count, &fargs, usource, usrc_len, &INTL_DATA_ERROR_CODE(mfo));
|
||||
efree(usource);
|
||||
INTL_METHOD_CHECK_STATUS(mfo, "Parsing failed");
|
||||
|
||||
array_init(return_value);
|
||||
for(i=0;i<count;i++) {
|
||||
add_next_index_zval(return_value, fargs[i]);
|
||||
}
|
||||
efree(fargs);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto array MessageFormatter::parse( string $source )
|
||||
* Parse a message }}} */
|
||||
/* {{{ proto array msgfmt_parse( MessageFormatter $nf, string $source )
|
||||
* Parse a message.
|
||||
*/
|
||||
PHP_FUNCTION( msgfmt_parse )
|
||||
{
|
||||
char *source;
|
||||
int source_len;
|
||||
MSG_FORMAT_METHOD_INIT_VARS;
|
||||
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os",
|
||||
&object, MessageFormatter_ce_ptr, &source, &source_len ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"msgfmt_parse: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Fetch the object.
|
||||
MSG_FORMAT_METHOD_FETCH_OBJECT;
|
||||
|
||||
msgfmt_do_parse(mfo, source, source_len, return_value TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto array MessageFormatter::formatMessage( string $locale, string $pattern, string $source )
|
||||
* Parse a message. }}} */
|
||||
/* {{{ proto array numfmt_parse_message( string $locale, string $pattern, string $source )
|
||||
* Parse a message.
|
||||
*/
|
||||
PHP_FUNCTION( msgfmt_parse_message )
|
||||
{
|
||||
UChar *spattern = NULL;
|
||||
int spattern_len = 0;
|
||||
char *pattern = NULL;
|
||||
int pattern_len = 0;
|
||||
char *slocale = NULL;
|
||||
int slocale_len = 0;
|
||||
char *source = NULL;
|
||||
int src_len = 0;
|
||||
MessageFormatter_object mf = {0};
|
||||
MessageFormatter_object *mfo = &mf;
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "sss",
|
||||
&slocale, &slocale_len, &pattern, &pattern_len, &source, &src_len ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"msgfmt_parse_message: unable to parse input params", 0 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
msgformat_data_init(&mfo->mf_data TSRMLS_CC);
|
||||
|
||||
if(pattern && pattern_len) {
|
||||
intl_convert_utf8_to_utf16(&spattern, &spattern_len, pattern, pattern_len, &INTL_DATA_ERROR_CODE(mfo));
|
||||
if( U_FAILURE(INTL_DATA_ERROR_CODE((mfo))) )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"msgfmt_parse_message: error converting pattern to UTF-16", 0 TSRMLS_CC );
|
||||
RETURN_FALSE;
|
||||
}
|
||||
} else {
|
||||
spattern_len = 0;
|
||||
spattern = NULL;
|
||||
}
|
||||
|
||||
if(slocale_len == 0) {
|
||||
slocale = INTL_G(default_locale);
|
||||
}
|
||||
|
||||
if(msfgotmat_fix_quotes(&spattern, &spattern_len, &INTL_DATA_ERROR_CODE(mfo)) != SUCCESS) {
|
||||
intl_error_set( NULL, U_INVALID_FORMAT_ERROR,
|
||||
"msgfmt_parse_message: error converting pattern to quote-friendly format", 0 TSRMLS_CC );
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Create an ICU message formatter.
|
||||
MSG_FORMAT_OBJECT(mfo) = umsg_open(spattern, spattern_len, slocale, NULL, &INTL_DATA_ERROR_CODE(mfo));
|
||||
if(spattern && spattern_len) {
|
||||
efree(spattern);
|
||||
}
|
||||
INTL_METHOD_CHECK_STATUS(mfo, "Creating message formatter failed");
|
||||
|
||||
msgfmt_do_parse(mfo, source, src_len, return_value TSRMLS_CC);
|
||||
|
||||
// drop the temporary formatter
|
||||
msgformat_data_free(&mfo->mf_data 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
|
||||
*/
|
25
ext/intl/msgformat/msgformat_parse.h
Executable file
25
ext/intl/msgformat/msgformat_parse.h
Executable file
@ -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: Stanislav Malyshev <stas@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef MSG_FORMAT_PARSE_H
|
||||
#define MSG_FORMAT_PARSE_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
PHP_FUNCTION( msgfmt_parse );
|
||||
PHP_FUNCTION( msgfmt_parse_message );
|
||||
|
||||
#endif // MSG_FORMAT_PARSE_H
|
68
ext/intl/normalizer/normalizer.c
Executable file
68
ext/intl/normalizer/normalizer.c
Executable file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Ed Batutis <ed@batutis.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "normalizer_class.h"
|
||||
#include "normalizer.h"
|
||||
|
||||
#include <unicode/utypes.h>
|
||||
#include <unicode/unorm.h>
|
||||
#include <unicode/ustring.h>
|
||||
|
||||
/* {{{ normalizer_register_constants
|
||||
* Register constants common for the both (OO and procedural)
|
||||
* APIs.
|
||||
*/
|
||||
void normalizer_register_constants( INIT_FUNC_ARGS )
|
||||
{
|
||||
if( !Normalizer_ce_ptr )
|
||||
{
|
||||
zend_error( E_ERROR, "Normalizer class not defined" );
|
||||
return;
|
||||
}
|
||||
|
||||
#define NORMALIZER_EXPOSE_CONST(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS)
|
||||
#define NORMALIZER_EXPOSE_CLASS_CONST(x) zend_declare_class_constant_long( Normalizer_ce_ptr, ZEND_STRS( #x ) - 1, NORMALIZER_##x TSRMLS_CC );
|
||||
#define NORMALIZER_EXPOSE_CUSTOM_CLASS_CONST(name, value) zend_declare_class_constant_long( Normalizer_ce_ptr, ZEND_STRS( name ) - 1, value TSRMLS_CC );
|
||||
|
||||
// Normalization form constants
|
||||
NORMALIZER_EXPOSE_CLASS_CONST( NONE );
|
||||
NORMALIZER_EXPOSE_CLASS_CONST( FORM_D );
|
||||
NORMALIZER_EXPOSE_CLASS_CONST( NFD );
|
||||
NORMALIZER_EXPOSE_CLASS_CONST( FORM_KD );
|
||||
NORMALIZER_EXPOSE_CLASS_CONST( NFKD );
|
||||
NORMALIZER_EXPOSE_CLASS_CONST( FORM_C );
|
||||
NORMALIZER_EXPOSE_CLASS_CONST( NFC );
|
||||
NORMALIZER_EXPOSE_CLASS_CONST( FORM_KC );
|
||||
NORMALIZER_EXPOSE_CLASS_CONST( NFKC );
|
||||
|
||||
#undef NORMALIZER_EXPOSE_CUSTOM_CLASS_CONST
|
||||
#undef NORMALIZER_EXPOSE_CLASS_CONST
|
||||
#undef NORMALIZER_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
|
||||
*/
|
37
ext/intl/normalizer/normalizer.h
Executable file
37
ext/intl/normalizer/normalizer.h
Executable file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Ed Batutis <ed@batutis.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef NORMALIZER_NORMALIZER_H
|
||||
#define NORMALIZER_NORMALIZER_H
|
||||
|
||||
#include <php.h>
|
||||
#include <unicode/utypes.h>
|
||||
#include <unicode/unorm.h>
|
||||
|
||||
#define NORMALIZER_NONE UNORM_NONE
|
||||
#define NORMALIZER_FORM_D UNORM_NFD
|
||||
#define NORMALIZER_NFD UNORM_NFD
|
||||
#define NORMALIZER_FORM_KD UNORM_NFKD
|
||||
#define NORMALIZER_NFKD UNORM_NFKD
|
||||
#define NORMALIZER_FORM_C UNORM_NFC
|
||||
#define NORMALIZER_NFC UNORM_NFC
|
||||
#define NORMALIZER_FORM_KC UNORM_NFKC
|
||||
#define NORMALIZER_NFKC UNORM_NFKC
|
||||
#define NORMALIZER_DEFAULT UNORM_DEFAULT
|
||||
|
||||
void normalizer_register_constants( INIT_FUNC_ARGS );
|
||||
|
||||
#endif // NORMALIZER_NORMALIZER_H
|
82
ext/intl/normalizer/normalizer_class.c
Executable file
82
ext/intl/normalizer/normalizer_class.c
Executable file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Ed Batutis <ed@batutis.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "normalizer_class.h"
|
||||
#include "php_intl.h"
|
||||
#include "normalizer_normalize.h"
|
||||
#include "intl_error.h"
|
||||
|
||||
#include <unicode/unorm.h>
|
||||
|
||||
zend_class_entry *Normalizer_ce_ptr = NULL;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// 'Normalizer' class registration structures & functions
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* {{{ Normalizer methods arguments info */
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( normalizer_3_args, 0, 0, 3 )
|
||||
ZEND_ARG_INFO( 0, arg1 )
|
||||
ZEND_ARG_INFO( 0, arg2 )
|
||||
ZEND_ARG_INFO( 0, arg3 )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Normalizer_class_functions
|
||||
* Every 'Normalizer' class method has an entry in this table
|
||||
*/
|
||||
|
||||
function_entry Normalizer_class_functions[] = {
|
||||
ZEND_FENTRY( normalize, ZEND_FN( normalizer_normalize ), normalizer_3_args, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
ZEND_FENTRY( isNormalized, ZEND_FN( normalizer_is_normalized ), normalizer_3_args, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
/* {{{ normalizer_register_Normalizer_class
|
||||
* Initialize 'Normalizer' class
|
||||
*/
|
||||
void normalizer_register_Normalizer_class( TSRMLS_D )
|
||||
{
|
||||
zend_class_entry ce;
|
||||
|
||||
// Create and register 'Normalizer' class.
|
||||
INIT_CLASS_ENTRY( ce, "Normalizer", Normalizer_class_functions );
|
||||
ce.create_object = NULL;
|
||||
Normalizer_ce_ptr = zend_register_internal_class( &ce TSRMLS_CC );
|
||||
|
||||
// Declare 'Normalizer' class properties.
|
||||
if( !Normalizer_ce_ptr )
|
||||
{
|
||||
zend_error( E_ERROR,
|
||||
"Normalizer: attempt to create properties "
|
||||
"on a non-registered class." );
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
52
ext/intl/normalizer/normalizer_class.h
Executable file
52
ext/intl/normalizer/normalizer_class.h
Executable file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Ed Batutis <ed@batutis.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef NORMALIZER_CLASS_H
|
||||
#define NORMALIZER_CLASS_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
#include "intl_common.h"
|
||||
#include "intl_error.h"
|
||||
|
||||
#include <unicode/unorm.h>
|
||||
|
||||
typedef struct {
|
||||
zend_object zo;
|
||||
|
||||
// error value not used currently
|
||||
intl_error err;
|
||||
|
||||
} Normalizer_object;
|
||||
|
||||
#define NORMALIZER_ERROR(co) (co)->err
|
||||
#define NORMALIZER_ERROR_P(co) &(NORMALIZER_ERROR(co))
|
||||
|
||||
#define NORMALIZER_ERROR_CODE(co) INTL_ERROR_CODE(NORMALIZER_ERROR(co))
|
||||
#define NORMALIZER_ERROR_CODE_P(co) &(INTL_ERROR_CODE(NORMALIZER_ERROR(co)))
|
||||
|
||||
void normalizer_register_Normalizer_class( TSRMLS_D );
|
||||
void normalizer_object_init( Normalizer_object* co TSRMLS_DC );
|
||||
void normalizer_object_destroy( Normalizer_object* co TSRMLS_DC );
|
||||
|
||||
extern zend_class_entry *Normalizer_ce_ptr;
|
||||
|
||||
/* Auxiliary macros */
|
||||
|
||||
#define NORMALIZER_METHOD_INIT_VARS \
|
||||
intl_error_reset( NULL TSRMLS_CC ); \
|
||||
|
||||
#endif // #ifndef NORMALIZER_CLASS_H
|
256
ext/intl/normalizer/normalizer_normalize.c
Executable file
256
ext/intl/normalizer/normalizer_normalize.c
Executable file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Ed Batutis <ed@batutis.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "php_intl.h"
|
||||
#include "unicode/unorm.h"
|
||||
#include "normalizer.h"
|
||||
#include "normalizer_class.h"
|
||||
#include "normalizer_normalize.h"
|
||||
#include "intl_convert.h"
|
||||
|
||||
/* {{{ proto string Normalizer::normalize( string $input [, string $form = FORM_C] )
|
||||
* Normalize a string. }}} */
|
||||
/* {{{ proto string normalizer_normalize( string $input [, string $form = FORM_C] )
|
||||
* Normalize a string.
|
||||
*/
|
||||
PHP_FUNCTION( normalizer_normalize )
|
||||
{
|
||||
char* input = NULL;
|
||||
// form is optional, defaults to FORM_C
|
||||
long form = NORMALIZER_DEFAULT;
|
||||
int input_len = 0;
|
||||
|
||||
UChar* uinput = NULL;
|
||||
int uinput_len = 0;
|
||||
int expansion_factor = 1;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
UChar* uret_buf = NULL;
|
||||
int uret_len = 0;
|
||||
|
||||
char* ret_buf = NULL;
|
||||
int32_t ret_len = 0;
|
||||
|
||||
int32_t size_needed;
|
||||
|
||||
NORMALIZER_METHOD_INIT_VARS
|
||||
|
||||
intl_error_reset( NULL TSRMLS_CC );
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "s|l",
|
||||
&input, &input_len, &form ) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"normalizer_normalize: unable to parse input params", 1 TSRMLS_CC );
|
||||
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
expansion_factor = 1;
|
||||
|
||||
switch(form) {
|
||||
case NORMALIZER_NONE:
|
||||
break;
|
||||
case NORMALIZER_FORM_D:
|
||||
expansion_factor = 3;
|
||||
break;
|
||||
case NORMALIZER_FORM_KD:
|
||||
expansion_factor = 3;
|
||||
break;
|
||||
case NORMALIZER_FORM_C:
|
||||
case NORMALIZER_FORM_KC:
|
||||
break;
|
||||
default:
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"normalizer_normalize: illegal normalization form", 1 TSRMLS_CC );
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
/*
|
||||
* Normalize string (converting it to UTF-16 first).
|
||||
*/
|
||||
|
||||
// First convert the string to UTF-16.
|
||||
intl_convert_utf8_to_utf16(&uinput, &uinput_len, input, input_len, &status );
|
||||
|
||||
if( U_FAILURE( status ) )
|
||||
{
|
||||
// Set global error code.
|
||||
intl_error_set_code( NULL, status TSRMLS_CC );
|
||||
|
||||
// Set error messages.
|
||||
intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 1 TSRMLS_CC );
|
||||
efree( uinput );
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
|
||||
// Allocate memory for the destination buffer for normalization
|
||||
uret_len = uinput_len * expansion_factor;
|
||||
uret_buf = eumalloc( uret_len + 1 );
|
||||
|
||||
// normalize
|
||||
size_needed = unorm_normalize( uinput, uinput_len, form, (int32_t) 0 /* options */, uret_buf, uret_len, &status);
|
||||
|
||||
// Bail out if an unexpected error occured.
|
||||
// (U_BUFFER_OVERFLOW_ERROR means that *target buffer is not large enough).
|
||||
// (U_STRING_NOT_TERMINATED_WARNING usually means that the input string is empty).
|
||||
if( U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR && status != U_STRING_NOT_TERMINATED_WARNING ) {
|
||||
efree( uret_buf );
|
||||
efree( uinput );
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
if ( size_needed > uret_len ) {
|
||||
// realloc does not seem to work properly - memory is corrupted
|
||||
// uret_buf = eurealloc(uret_buf, size_needed + 1);
|
||||
efree( uret_buf );
|
||||
uret_buf = eumalloc( size_needed + 1 );
|
||||
uret_len = size_needed;
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
|
||||
// try normalize again
|
||||
size_needed = unorm_normalize( uinput, uinput_len, form, (int32_t) 0 /* options */, uret_buf, uret_len, &status);
|
||||
|
||||
// Bail out if an unexpected error occured.
|
||||
if( U_FAILURE(status) ) {
|
||||
// Set error messages.
|
||||
intl_error_set_custom_msg( NULL,"Error normalizing string", 1 TSRMLS_CC );
|
||||
efree( uret_buf );
|
||||
efree( uinput );
|
||||
RETURN_NULL();
|
||||
}
|
||||
}
|
||||
|
||||
efree( uinput );
|
||||
|
||||
// the buffer we actually used
|
||||
uret_len = size_needed;
|
||||
|
||||
// Convert normalized string from UTF-16 to UTF-8.
|
||||
intl_convert_utf16_to_utf8( &ret_buf, &ret_len, uret_buf, uret_len, &status );
|
||||
efree( uret_buf );
|
||||
if( U_FAILURE( status ) )
|
||||
{
|
||||
intl_error_set( NULL, status,
|
||||
"normalizer_normalize: error converting normalized text UTF-8", 1 TSRMLS_CC );
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
// Return it.
|
||||
RETVAL_STRINGL( ret_buf, ret_len, FALSE );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool Normalizer::isNormalized( string $input [, string $form = FORM_C] )
|
||||
* Test if a string is in a given normalization form. }}} */
|
||||
/* {{{ proto bool normalizer_is_normalize( string $input [, string $form = FORM_C] )
|
||||
* Test if a string is in a given normalization form.
|
||||
*/
|
||||
PHP_FUNCTION( normalizer_is_normalized )
|
||||
{
|
||||
char* input = NULL;
|
||||
// form is optional, defaults to FORM_C
|
||||
long form = NORMALIZER_DEFAULT;
|
||||
int input_len = 0;
|
||||
|
||||
UChar* uinput = NULL;
|
||||
int uinput_len = 0;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
UBool uret = FALSE;
|
||||
|
||||
NORMALIZER_METHOD_INIT_VARS
|
||||
|
||||
intl_error_reset( NULL TSRMLS_CC );
|
||||
|
||||
// Parse parameters.
|
||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "s|l",
|
||||
&input, &input_len, &form) == FAILURE )
|
||||
{
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"normalizer_is_normalized: unable to parse input params", 1 TSRMLS_CC );
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
switch(form) {
|
||||
// case NORMALIZER_NONE: not allowed - doesn't make sense
|
||||
|
||||
case NORMALIZER_FORM_D:
|
||||
case NORMALIZER_FORM_KD:
|
||||
case NORMALIZER_FORM_C:
|
||||
case NORMALIZER_FORM_KC:
|
||||
break;
|
||||
default:
|
||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"normalizer_normalize: illegal normalization form", 1 TSRMLS_CC );
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Test normalization of string (converting it to UTF-16 first).
|
||||
*/
|
||||
|
||||
// First convert the string to UTF-16.
|
||||
intl_convert_utf8_to_utf16(&uinput, &uinput_len, input, input_len, &status );
|
||||
|
||||
if( U_FAILURE( status ) )
|
||||
{
|
||||
// Set global error code.
|
||||
intl_error_set_code( NULL, status TSRMLS_CC );
|
||||
|
||||
// Set error messages.
|
||||
intl_error_set_custom_msg( NULL, "Error converting string to UTF-16.", 1 TSRMLS_CC );
|
||||
efree( uinput );
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
// test string
|
||||
uret = unorm_isNormalizedWithOptions( uinput, uinput_len, form, (int32_t) 0 /* options */, &status);
|
||||
|
||||
efree( uinput );
|
||||
|
||||
// Bail out if an unexpected error occured.
|
||||
if( U_FAILURE(status) ) {
|
||||
// Set error messages.
|
||||
intl_error_set_custom_msg( NULL,"Error testing if string is the given normalization form.", 1 TSRMLS_CC );
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if ( uret )
|
||||
RETURN_TRUE;
|
||||
|
||||
RETURN_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
|
||||
*/
|
25
ext/intl/normalizer/normalizer_normalize.h
Executable file
25
ext/intl/normalizer/normalizer_normalize.h
Executable file
@ -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: Ed Batutis <ed@batutis.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef NORMALIZER_NORMALIZE_H
|
||||
#define NORMALIZER_NORMALIZE_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
PHP_FUNCTION( normalizer_normalize );
|
||||
PHP_FUNCTION( normalizer_is_normalized );
|
||||
|
||||
#endif // NORMALIZER_NORMALIZE_H
|
490
ext/intl/php_intl.c
Executable file
490
ext/intl/php_intl.c
Executable file
@ -0,0 +1,490 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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> |
|
||||
| Stanislav Malyshev <stas@zend.com> |
|
||||
| Kirti Velankar <kirtig@yahoo-inc.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include "php_intl.h"
|
||||
#include "intl_error.h"
|
||||
#include "collator/collator_class.h"
|
||||
#include "collator/collator.h"
|
||||
#include "collator/collator_attr.h"
|
||||
#include "collator/collator_compare.h"
|
||||
#include "collator/collator_sort.h"
|
||||
#include "collator/collator_convert.h"
|
||||
#include "collator/collator_locale.h"
|
||||
#include "collator/collator_create.h"
|
||||
#include "collator/collator_error.h"
|
||||
|
||||
#include "formatter/formatter.h"
|
||||
#include "formatter/formatter_class.h"
|
||||
#include "formatter/formatter_attr.h"
|
||||
#include "formatter/formatter_format.h"
|
||||
#include "formatter/formatter_main.h"
|
||||
#include "formatter/formatter_parse.h"
|
||||
|
||||
#include "msgformat/msgformat.h"
|
||||
#include "msgformat/msgformat_class.h"
|
||||
#include "msgformat/msgformat_attr.h"
|
||||
#include "msgformat/msgformat_format.h"
|
||||
#include "msgformat/msgformat_parse.h"
|
||||
|
||||
#include "normalizer/normalizer.h"
|
||||
#include "normalizer/normalizer_class.h"
|
||||
#include "normalizer/normalizer_normalize.h"
|
||||
|
||||
#include "locale/locale.h"
|
||||
#include "locale/locale_class.h"
|
||||
#include "locale/locale_methods.h"
|
||||
|
||||
#include "dateformat/dateformat.h"
|
||||
#include "dateformat/dateformat_class.h"
|
||||
#include "dateformat/dateformat_attr.h"
|
||||
#include "dateformat/dateformat_format.h"
|
||||
#include "dateformat/dateformat_parse.h"
|
||||
#include "dateformat/dateformat_data.h"
|
||||
|
||||
#include "msgformat/msgformat.h"
|
||||
#include "common/common_error.h"
|
||||
|
||||
#include <unicode/uloc.h>
|
||||
#include <ext/standard/info.h>
|
||||
|
||||
#include "php_ini.h"
|
||||
#define INTL_MODULE_VERSION PHP_INTL_VERSION
|
||||
|
||||
/*
|
||||
* locale_get_default has a conflict since ICU also has
|
||||
* a function with the same name
|
||||
* in fact ICU appends the version no. to it also
|
||||
* Hence the following undef for ICU version
|
||||
* Same true for the locale_set_default function
|
||||
*/
|
||||
#undef locale_get_default
|
||||
#undef locale_set_default
|
||||
|
||||
ZEND_DECLARE_MODULE_GLOBALS( intl )
|
||||
|
||||
/* {{{ Arguments info */
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( collator_static_0_args, 0, 0, 0 )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( collator_static_1_arg, 0, 0, 1 )
|
||||
ZEND_ARG_INFO( 0, arg1 )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( collator_static_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_0_args, 0, 0, 1 )
|
||||
ZEND_ARG_OBJ_INFO( 0, object, Collator, 0 )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( collator_1_arg, 0, 0, 2 )
|
||||
ZEND_ARG_OBJ_INFO( 0, object, Collator, 0 )
|
||||
ZEND_ARG_INFO( 0, arg1 )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( collator_2_args, 0, 0, 3 )
|
||||
ZEND_ARG_OBJ_INFO( 0, object, Collator, 0 )
|
||||
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, 2 )
|
||||
ZEND_ARG_OBJ_INFO( 0, object, Collator, 0 )
|
||||
ZEND_ARG_ARRAY_INFO( 1, arr, 0 )
|
||||
ZEND_ARG_INFO( 0, sort_flags )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX( numfmt_parse_arginfo, 0, 0, 2 )
|
||||
ZEND_ARG_INFO( 0, formatter )
|
||||
ZEND_ARG_INFO( 0, string )
|
||||
ZEND_ARG_INFO( 0, type )
|
||||
ZEND_ARG_INFO( 1, position )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX( numfmt_parse_currency_arginfo, 0, 0, 3 )
|
||||
ZEND_ARG_INFO( 0, formatter )
|
||||
ZEND_ARG_INFO( 0, string )
|
||||
ZEND_ARG_INFO( 1, currency )
|
||||
ZEND_ARG_INFO( 1, position )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( locale_0_args, 0, 0, 0 )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( locale_1_arg, 0, 0, 1 )
|
||||
ZEND_ARG_INFO( 0, arg1 )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( locale_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( locale_3_args, 0, 0, 3 )
|
||||
ZEND_ARG_INFO( 0, arg1 )
|
||||
ZEND_ARG_INFO( 0, arg2 )
|
||||
ZEND_ARG_INFO( 0, arg3 )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( locale_4_args, 0, 0, 4 )
|
||||
ZEND_ARG_INFO( 0, arg1 )
|
||||
ZEND_ARG_INFO( 0, arg2 )
|
||||
ZEND_ARG_INFO( 0, arg3 )
|
||||
ZEND_ARG_INFO( 0, arg4 )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define intl_0_args collator_static_0_args
|
||||
#define intl_1_arg collator_static_1_arg
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( normalizer_args, 0, 0, 1 )
|
||||
ZEND_ARG_INFO( 0, input )
|
||||
ZEND_ARG_INFO( 0, form )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( grapheme_1_arg, 0, 0, 1 )
|
||||
ZEND_ARG_INFO( 0, string )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( grapheme_search_args, 0, 0, 2 )
|
||||
ZEND_ARG_INFO( 0, haystack )
|
||||
ZEND_ARG_INFO( 0, needle )
|
||||
ZEND_ARG_INFO( 0, offset )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( grapheme_substr_args, 0, 0, 2 )
|
||||
ZEND_ARG_INFO( 0, string )
|
||||
ZEND_ARG_INFO( 0, start )
|
||||
ZEND_ARG_INFO( 0, length )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX( grapheme_strstr_args, 0, 0, 2 )
|
||||
ZEND_ARG_INFO( 0, haystack )
|
||||
ZEND_ARG_INFO( 0, needle )
|
||||
ZEND_ARG_INFO( 0, before_needle )
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX( grapheme_extract_args, 0, 0, 2 )
|
||||
ZEND_ARG_INFO( 0, arg1 )
|
||||
ZEND_ARG_INFO( 0, arg2 )
|
||||
ZEND_ARG_INFO( 0, arg3 )
|
||||
ZEND_ARG_INFO( 0, arg4 )
|
||||
ZEND_ARG_INFO( 1, arg5 ) /* 1 = pass by reference */
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ intl_functions
|
||||
*
|
||||
* Every user visible function must have an entry in intl_functions[].
|
||||
*/
|
||||
zend_function_entry intl_functions[] = {
|
||||
|
||||
// collator functions
|
||||
PHP_FE( collator_create, collator_static_1_arg )
|
||||
PHP_FE( collator_compare, collator_2_args )
|
||||
PHP_FE( collator_get_attribute, collator_1_arg )
|
||||
PHP_FE( collator_set_attribute, collator_2_args )
|
||||
PHP_FE( collator_get_strength, collator_0_args )
|
||||
PHP_FE( collator_set_strength, collator_1_arg )
|
||||
PHP_FE( collator_sort, collator_sort_args )
|
||||
PHP_FE( collator_sort_with_sort_keys, collator_sort_args )
|
||||
PHP_FE( collator_asort, collator_sort_args )
|
||||
PHP_FE( collator_get_locale, collator_1_arg )
|
||||
PHP_FE( collator_get_error_code, collator_0_args )
|
||||
PHP_FE( collator_get_error_message, collator_0_args )
|
||||
|
||||
// formatter functions
|
||||
PHP_FE( numfmt_create, NULL )
|
||||
PHP_FE( numfmt_format, NULL )
|
||||
PHP_FE( numfmt_parse, numfmt_parse_arginfo )
|
||||
PHP_FE( numfmt_format_currency, NULL )
|
||||
PHP_FE( numfmt_parse_currency, numfmt_parse_currency_arginfo )
|
||||
PHP_FE( numfmt_set_attribute, NULL )
|
||||
PHP_FE( numfmt_get_attribute, NULL )
|
||||
PHP_FE( numfmt_set_text_attribute, NULL )
|
||||
PHP_FE( numfmt_get_text_attribute, NULL )
|
||||
PHP_FE( numfmt_set_symbol, NULL )
|
||||
PHP_FE( numfmt_get_symbol, NULL )
|
||||
PHP_FE( numfmt_set_pattern, NULL )
|
||||
PHP_FE( numfmt_get_pattern, NULL )
|
||||
PHP_FE( numfmt_get_locale, NULL )
|
||||
PHP_FE( numfmt_get_error_code, NULL )
|
||||
PHP_FE( numfmt_get_error_message, NULL )
|
||||
|
||||
// normalizer functions
|
||||
PHP_FE( normalizer_normalize, normalizer_args )
|
||||
PHP_FE( normalizer_is_normalized, normalizer_args )
|
||||
|
||||
//Locale functions
|
||||
PHP_NAMED_FE( locale_get_default, zif_locale_get_default, locale_0_args )
|
||||
PHP_NAMED_FE( locale_set_default, zif_locale_set_default, locale_1_arg )
|
||||
PHP_FE( locale_get_primary_language, locale_1_arg )
|
||||
PHP_FE( locale_get_script, locale_1_arg )
|
||||
PHP_FE( locale_get_region, locale_1_arg )
|
||||
PHP_FE( locale_get_keywords, locale_1_arg )
|
||||
PHP_FE( locale_get_display_script, locale_2_args )
|
||||
PHP_FE( locale_get_display_region, locale_2_args )
|
||||
PHP_FE( locale_get_display_name, locale_2_args )
|
||||
PHP_FE( locale_get_display_language, locale_2_args)
|
||||
PHP_FE( locale_get_display_variant, locale_2_args )
|
||||
PHP_FE( locale_compose, locale_1_arg )
|
||||
PHP_FE( locale_parse, locale_1_arg )
|
||||
PHP_FE( locale_get_all_variants, locale_1_arg )
|
||||
PHP_FE( locale_filter_matches, locale_3_args )
|
||||
PHP_FE( locale_canonicalize, locale_1_arg )
|
||||
PHP_FE( locale_lookup, locale_4_args )
|
||||
|
||||
// MessageFormatter functions
|
||||
PHP_FE( msgfmt_create, NULL )
|
||||
PHP_FE( msgfmt_format, NULL )
|
||||
PHP_FE( msgfmt_format_message, NULL )
|
||||
PHP_FE( msgfmt_parse, NULL )
|
||||
PHP_FE( msgfmt_parse_message, NULL )
|
||||
PHP_FE( msgfmt_set_pattern, NULL )
|
||||
PHP_FE( msgfmt_get_pattern, NULL )
|
||||
PHP_FE( msgfmt_get_locale, NULL )
|
||||
PHP_FE( msgfmt_get_error_code, NULL )
|
||||
PHP_FE( msgfmt_get_error_message, NULL )
|
||||
|
||||
// IntlDateFormatter functions
|
||||
PHP_FE( datefmt_create, NULL )
|
||||
PHP_FE( datefmt_get_datetype, NULL )
|
||||
PHP_FE( datefmt_get_timetype, NULL )
|
||||
PHP_FE( datefmt_get_calendar, NULL )
|
||||
PHP_FE( datefmt_set_calendar, NULL )
|
||||
PHP_FE( datefmt_get_locale, NULL )
|
||||
PHP_FE( datefmt_get_timezone_id, NULL )
|
||||
PHP_FE( datefmt_set_timezone_id, NULL )
|
||||
PHP_FE( datefmt_get_pattern, NULL )
|
||||
PHP_FE( datefmt_set_pattern, NULL )
|
||||
PHP_FE( datefmt_is_lenient, NULL )
|
||||
PHP_FE( datefmt_set_lenient, NULL )
|
||||
PHP_FE( datefmt_format, NULL )
|
||||
PHP_FE( datefmt_parse, NULL )
|
||||
PHP_FE( datefmt_localtime , NULL )
|
||||
PHP_FE( datefmt_get_error_code, NULL )
|
||||
PHP_FE( datefmt_get_error_message, NULL )
|
||||
|
||||
// grapheme functions
|
||||
PHP_FE( grapheme_strlen, grapheme_1_arg )
|
||||
PHP_FE( grapheme_strpos, grapheme_search_args )
|
||||
PHP_FE( grapheme_stripos, grapheme_search_args )
|
||||
PHP_FE( grapheme_strrpos, grapheme_search_args )
|
||||
PHP_FE( grapheme_strripos, grapheme_search_args )
|
||||
PHP_FE( grapheme_substr, grapheme_substr_args )
|
||||
PHP_FE( grapheme_strstr, grapheme_strstr_args )
|
||||
PHP_FE( grapheme_stristr, grapheme_strstr_args )
|
||||
PHP_FE( grapheme_extract, grapheme_extract_args )
|
||||
|
||||
// common functions
|
||||
PHP_FE( intl_get_error_code, intl_0_args )
|
||||
PHP_FE( intl_get_error_message, intl_0_args )
|
||||
PHP_FE( intl_is_failure, intl_1_arg )
|
||||
PHP_FE( intl_error_name, intl_1_arg )
|
||||
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ INI Settings */
|
||||
PHP_INI_BEGIN()
|
||||
STD_PHP_INI_ENTRY(LOCALE_INI_NAME, NULL, PHP_INI_ALL, OnUpdateStringUnempty, default_locale, zend_intl_globals, intl_globals)
|
||||
|
||||
PHP_INI_END()
|
||||
/* }}} */
|
||||
|
||||
|
||||
static PHP_GINIT_FUNCTION(intl);
|
||||
|
||||
/* {{{ intl_module_entry */
|
||||
zend_module_entry intl_module_entry = {
|
||||
#if ZEND_MODULE_API_NO >= 20010901
|
||||
STANDARD_MODULE_HEADER,
|
||||
#endif
|
||||
"intl",
|
||||
intl_functions,
|
||||
PHP_MINIT( intl ),
|
||||
PHP_MSHUTDOWN( intl ),
|
||||
PHP_RINIT( intl ),
|
||||
PHP_RSHUTDOWN( intl ),
|
||||
PHP_MINFO( intl ),
|
||||
INTL_MODULE_VERSION,
|
||||
PHP_MODULE_GLOBALS(intl), /* globals descriptor */
|
||||
PHP_GINIT(intl), /* globals ctor */
|
||||
NULL, /* globals dtor */
|
||||
NULL, /* post deactivate */
|
||||
STANDARD_MODULE_PROPERTIES_EX
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
#ifdef COMPILE_DL_INTL
|
||||
ZEND_GET_MODULE( intl )
|
||||
#endif
|
||||
|
||||
/* {{{ intl_init_globals */
|
||||
static PHP_GINIT_FUNCTION(intl)
|
||||
{
|
||||
memset( intl_globals, 0, sizeof(zend_intl_globals) );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ PHP_MINIT_FUNCTION
|
||||
*/
|
||||
PHP_MINIT_FUNCTION( intl )
|
||||
{
|
||||
//For the default locale php.ini setting
|
||||
REGISTER_INI_ENTRIES();
|
||||
|
||||
REGISTER_LONG_CONSTANT("INTL_MAX_LOCALE_LEN", INTL_MAX_LOCALE_LEN, CONST_CS);
|
||||
|
||||
// Register 'Collator' PHP class
|
||||
collator_register_Collator_class( TSRMLS_C );
|
||||
|
||||
// Expose Collator constants to PHP scripts
|
||||
collator_register_constants( INIT_FUNC_ARGS_PASSTHRU );
|
||||
|
||||
// Register 'NumberFormatter' PHP class
|
||||
formatter_register_class( TSRMLS_C );
|
||||
|
||||
// Expose NumberFormatter constants to PHP scripts
|
||||
formatter_register_constants( INIT_FUNC_ARGS_PASSTHRU );
|
||||
|
||||
// Register 'Normalizer' PHP class
|
||||
normalizer_register_Normalizer_class( TSRMLS_C );
|
||||
|
||||
// Expose Normalizer constants to PHP scripts
|
||||
normalizer_register_constants( INIT_FUNC_ARGS_PASSTHRU );
|
||||
|
||||
// Register 'Locale' PHP class
|
||||
locale_register_Locale_class( TSRMLS_C );
|
||||
|
||||
// Expose Locale constants to PHP scripts
|
||||
locale_register_constants( INIT_FUNC_ARGS_PASSTHRU );
|
||||
|
||||
msgformat_register_class(TSRMLS_C);
|
||||
|
||||
grapheme_register_constants( INIT_FUNC_ARGS_PASSTHRU );
|
||||
|
||||
// Register 'DateFormat' PHP class
|
||||
dateformat_register_IntlDateFormatter_class( TSRMLS_C );
|
||||
|
||||
// Expose DateFormat constants to PHP scripts
|
||||
dateformat_register_constants( INIT_FUNC_ARGS_PASSTHRU );
|
||||
|
||||
// Expose ICU error codes to PHP scripts.
|
||||
intl_expose_icu_error_codes( INIT_FUNC_ARGS_PASSTHRU );
|
||||
|
||||
// Global error handling.
|
||||
intl_error_init( NULL TSRMLS_CC );
|
||||
|
||||
//Set the default_locale value
|
||||
if( INTL_G(default_locale) == NULL ) {
|
||||
INTL_G(default_locale) = pestrdup(uloc_getDefault(), 1) ;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ PHP_MSHUTDOWN_FUNCTION
|
||||
*/
|
||||
PHP_MSHUTDOWN_FUNCTION( intl )
|
||||
{
|
||||
//For the default locale php.ini setting
|
||||
UNREGISTER_INI_ENTRIES();
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ PHP_RINIT_FUNCTION
|
||||
*/
|
||||
PHP_RINIT_FUNCTION( intl )
|
||||
{
|
||||
//Set the default_locale value
|
||||
if( INTL_G(default_locale) == NULL ) {
|
||||
INTL_G(default_locale) = pestrdup(uloc_getDefault(), 1) ;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ PHP_RSHUTDOWN_FUNCTION
|
||||
*/
|
||||
PHP_RSHUTDOWN_FUNCTION( intl )
|
||||
{
|
||||
if(INTL_G(current_collator)) {
|
||||
INTL_G(current_collator) = NULL;
|
||||
}
|
||||
if (INTL_G(grapheme_iterator)) {
|
||||
grapheme_close_global_iterator( TSRMLS_C );
|
||||
INTL_G(grapheme_iterator) = NULL;
|
||||
}
|
||||
|
||||
intl_error_reset( NULL TSRMLS_CC);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ PHP_MINFO_FUNCTION
|
||||
*/
|
||||
PHP_MINFO_FUNCTION( intl )
|
||||
{
|
||||
php_info_print_table_start();
|
||||
php_info_print_table_header( 2, "Internationalization support", "enabled" );
|
||||
php_info_print_table_row( 2, "version", INTL_MODULE_VERSION );
|
||||
php_info_print_table_end();
|
||||
|
||||
//For the default locale php.ini setting
|
||||
DISPLAY_INI_ENTRIES() ;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
76
ext/intl/php_intl.h
Executable file
76
ext/intl/php_intl.h
Executable file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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> |
|
||||
| Stanislav Malyshev <stas@zend.com> |
|
||||
| Kirti Velankar <kirtig@yahoo-inc.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef PHP_INTL_H
|
||||
#define PHP_INTL_H
|
||||
|
||||
#include <php.h>
|
||||
|
||||
#include "collator/collator_sort.h"
|
||||
#include "grapheme/grapheme.h"
|
||||
#include "intl_error.h"
|
||||
|
||||
extern zend_module_entry intl_module_entry;
|
||||
#define phpext_intl_ptr &intl_module_entry
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
#define PHP_INTL_API __declspec(dllexport)
|
||||
#else
|
||||
#define PHP_INTL_API
|
||||
#endif
|
||||
|
||||
#ifdef ZTS
|
||||
#include "TSRM.h"
|
||||
#endif
|
||||
|
||||
ZEND_BEGIN_MODULE_GLOBALS(intl)
|
||||
zval* current_collator;
|
||||
char* default_locale;
|
||||
collator_compare_func_t compare_func;
|
||||
UBreakIterator* grapheme_iterator;
|
||||
intl_error g_error;
|
||||
ZEND_END_MODULE_GLOBALS(intl)
|
||||
|
||||
/* Macro to access request-wide global variables. */
|
||||
#ifdef ZTS
|
||||
#define INTL_G(v) TSRMG(intl_globals_id, zend_intl_globals *, v)
|
||||
#else
|
||||
#define INTL_G(v) (intl_globals.v)
|
||||
#endif
|
||||
|
||||
ZEND_EXTERN_MODULE_GLOBALS(intl)
|
||||
|
||||
PHP_MINIT_FUNCTION(intl);
|
||||
PHP_MSHUTDOWN_FUNCTION(intl);
|
||||
PHP_RINIT_FUNCTION(intl);
|
||||
PHP_RSHUTDOWN_FUNCTION(intl);
|
||||
PHP_MINFO_FUNCTION(intl);
|
||||
|
||||
#define PHP_INTL_VERSION "1.0.0"
|
||||
|
||||
#endif /* PHP_INTL_H */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
29
ext/intl/tests/bug12887.phpt
Executable file
29
ext/intl/tests/bug12887.phpt
Executable file
@ -0,0 +1,29 @@
|
||||
--TEST--
|
||||
locale_get_keywords() bug #12887
|
||||
--SKIPIF--
|
||||
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function ut_main()
|
||||
{
|
||||
$res_str = '';
|
||||
$keywords_arr = ut_loc_get_keywords( 'de_DE@currency=EUR;collation=PHONEBOOK;sort=PHONEBOOK' );
|
||||
if ($keywords_arr) {
|
||||
foreach( $keywords_arr as $key => $value){
|
||||
$res_str .= "$key = $value\n";
|
||||
}
|
||||
}
|
||||
$res_str .= "\n";
|
||||
return $res_str;
|
||||
|
||||
}
|
||||
|
||||
include_once( 'ut_common.inc' );
|
||||
ut_run();
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
collation = PHONEBOOK
|
||||
currency = EUR
|
||||
sort = PHONEBOOK
|
70
ext/intl/tests/collation_customization.phpt
Executable file
70
ext/intl/tests/collation_customization.phpt
Executable file
@ -0,0 +1,70 @@
|
||||
--TEST--
|
||||
Collation customization
|
||||
--SKIPIF--
|
||||
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Check effects of changing misc collattion options.
|
||||
*/
|
||||
|
||||
|
||||
function cmp_array( &$coll, $a )
|
||||
{
|
||||
$res = '';
|
||||
$prev = null;
|
||||
foreach( $a as $i )
|
||||
{
|
||||
if( is_null( $prev ) )
|
||||
$res .= "$i";
|
||||
else
|
||||
{
|
||||
$eqrc = ut_coll_compare( $coll, $prev, $i );
|
||||
$eq = $eqrc < 0 ? "<" : ( $eqrc > 0 ? ">" : "=" );
|
||||
$res .= " $eq $i";
|
||||
}
|
||||
|
||||
$prev = $i;
|
||||
}
|
||||
$res .= "\n";
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
function check_alternate_handling( &$coll )
|
||||
{
|
||||
$res = '';
|
||||
|
||||
ut_coll_set_strength( $coll, Collator::TERTIARY );
|
||||
ut_coll_set_attribute( $coll, Collator::ALTERNATE_HANDLING, Collator::NON_IGNORABLE );
|
||||
|
||||
$res .= cmp_array( $coll, array( 'di Silva', 'Di Silva', 'diSilva', 'U.S.A.', 'USA' ) );
|
||||
|
||||
ut_coll_set_attribute( $coll, Collator::ALTERNATE_HANDLING, Collator::SHIFTED );
|
||||
|
||||
$res .= cmp_array( $coll, array( 'di Silva', 'diSilva', 'Di Silva', 'U.S.A.', 'USA' ) );
|
||||
|
||||
ut_coll_set_strength( $coll, Collator::QUATERNARY );
|
||||
|
||||
$res .= cmp_array( $coll, array( 'di Silva', 'diSilva', 'Di Silva', 'U.S.A.', 'USA' ) );
|
||||
$res .= "\n";
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
function ut_main()
|
||||
{
|
||||
$coll = ut_coll_create( 'en_US' );
|
||||
|
||||
return
|
||||
check_alternate_handling( $coll );
|
||||
}
|
||||
|
||||
include_once( 'ut_common.inc' );
|
||||
ut_run();
|
||||
?>
|
||||
--EXPECT--
|
||||
di Silva < Di Silva < diSilva < U.S.A. < USA
|
||||
di Silva = diSilva < Di Silva < U.S.A. = USA
|
||||
di Silva < diSilva < Di Silva < U.S.A. < USA
|
242
ext/intl/tests/collator_asort.phpt
Executable file
242
ext/intl/tests/collator_asort.phpt
Executable file
@ -0,0 +1,242 @@
|
||||
--TEST--
|
||||
asort()
|
||||
--SKIPIF--
|
||||
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Sort associative arrays using various locales.
|
||||
*/
|
||||
|
||||
|
||||
$test_num = 1;
|
||||
|
||||
/*
|
||||
* Sort various arrays in specified locale.
|
||||
*/
|
||||
function sort_arrays( $locale, $test_arrays, $sort_flag = Collator::SORT_REGULAR )
|
||||
{
|
||||
$res_str = '';
|
||||
|
||||
$coll = ut_coll_create( $locale );
|
||||
|
||||
foreach( $test_arrays as $test_array )
|
||||
{
|
||||
// Try to sort test data.
|
||||
$res_val = ut_coll_asort( $coll, $test_array, $sort_flag );
|
||||
|
||||
// Return output data.
|
||||
$res_dump = "\n" . dump( $test_array ) .
|
||||
"\n Result: " . dump( $res_val );
|
||||
|
||||
// Preppend test signature to output string
|
||||
$md5 = md5( $res_dump );
|
||||
|
||||
global $test_num;
|
||||
|
||||
$res_str .= "\n\n".
|
||||
"Test $test_num.$md5:" .
|
||||
$res_dump;
|
||||
++$test_num;
|
||||
}
|
||||
|
||||
return $res_str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test main function.
|
||||
*/
|
||||
function ut_main()
|
||||
{
|
||||
global $test_num;
|
||||
$test_num = 1;
|
||||
$res_str = '';
|
||||
|
||||
// Sort an array in SORT_REGULAR mode using en_US locale.
|
||||
$test_params = array(
|
||||
array( 'd' => 'y' ,
|
||||
'c' => 'i' ,
|
||||
'a' => 'k' ),
|
||||
|
||||
array( 'a' => 'a' ,
|
||||
'b' => 'aaa',
|
||||
'c' => 'aa' ),
|
||||
|
||||
array( 'a' => 'a' ,
|
||||
'aaa'=> 'a' ,
|
||||
'aa' => 'a' ),
|
||||
|
||||
array( '1' => 'abc',
|
||||
'5' => '!' ,
|
||||
'2' => null ,
|
||||
'7' => '' ),
|
||||
|
||||
array( '1' => '100',
|
||||
'2' => '25' ,
|
||||
'3' => '36' ),
|
||||
|
||||
array( '1' => 5 ,
|
||||
'2' => '30' ,
|
||||
'3' => 2 )
|
||||
);
|
||||
|
||||
$res_str .= sort_arrays( 'en_US', $test_params );
|
||||
|
||||
// Sort an array in SORT_STRING mode using en_US locale.
|
||||
$test_params = array(
|
||||
array( '1' => '100',
|
||||
'2' => '25' ,
|
||||
'3' => '36' ),
|
||||
|
||||
array( '1' => 5 ,
|
||||
'2' => '30' ,
|
||||
'3' => 2 ),
|
||||
|
||||
array( '1' => 'd' ,
|
||||
'2' => '' ,
|
||||
'3' => ' a' ),
|
||||
|
||||
array( '1' => 'y' ,
|
||||
'2' => 'k' ,
|
||||
'3' => 'i' )
|
||||
);
|
||||
|
||||
$res_str .= sort_arrays( 'en_US', $test_params, Collator::SORT_STRING );
|
||||
|
||||
// Sort a non-ASCII array using ru_RU locale.
|
||||
$test_params = array(
|
||||
array( 'п' => 'у',
|
||||
'б' => 'в',
|
||||
'е' => 'а' ),
|
||||
|
||||
array( '1' => 'п',
|
||||
'4' => '',
|
||||
'7' => 'd',
|
||||
'2' => 'пп' )
|
||||
);
|
||||
|
||||
$res_str .= sort_arrays( 'ru_RU', $test_params );
|
||||
|
||||
|
||||
// Sort an array using Lithuanian locale.
|
||||
$test_params = array(
|
||||
array( 'd' => 'y',
|
||||
'c' => 'i',
|
||||
'a' => 'k' )
|
||||
);
|
||||
|
||||
$res_str .= sort_arrays( 'lt_LT', $test_params );
|
||||
|
||||
return $res_str . "\n";
|
||||
}
|
||||
|
||||
include_once( 'ut_common.inc' );
|
||||
ut_run();
|
||||
?>
|
||||
--EXPECT--
|
||||
Test 1.162b81ac12878b817fc39063097e45b5:
|
||||
array (
|
||||
'c' => 'i',
|
||||
'a' => 'k',
|
||||
'd' => 'y',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 2.93d96e22f692d8a281b0a389f01f8d1e:
|
||||
array (
|
||||
'a' => 'a',
|
||||
'c' => 'aa',
|
||||
'b' => 'aaa',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 3.9f25de4482bc7b58de508e278113317c:
|
||||
array (
|
||||
'aa' => 'a',
|
||||
'aaa' => 'a',
|
||||
'a' => 'a',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 4.a85a41ea78e45b651080cfd98c0b431d:
|
||||
array (
|
||||
7 => '',
|
||||
2 => NULL,
|
||||
5 => '!',
|
||||
1 => 'abc',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 5.99dc71f405b286e03d489061b36e6900:
|
||||
array (
|
||||
2 => '25',
|
||||
3 => '36',
|
||||
1 => '100',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 6.bf5bba243307c9d12934e756ad4be190:
|
||||
array (
|
||||
3 => 2,
|
||||
1 => 5,
|
||||
2 => '30',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 7.e4ee7024c61476e9e7a6c28b5e47df6f:
|
||||
array (
|
||||
1 => '100',
|
||||
2 => '25',
|
||||
3 => '36',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 8.5fa7033dd43784be0db1474eb48b83c8:
|
||||
array (
|
||||
3 => 2,
|
||||
2 => '30',
|
||||
1 => 5,
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 9.588cdf4692bc09aa92ffe7e48f9e4579:
|
||||
array (
|
||||
2 => '',
|
||||
3 => ' a',
|
||||
1 => 'd',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 10.be02641a47ebcccd23e4183ca3a415f7:
|
||||
array (
|
||||
3 => 'i',
|
||||
2 => 'k',
|
||||
1 => 'y',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 11.153d9b11d1e5936afc917a94a4e11f34:
|
||||
array (
|
||||
'е' => 'а',
|
||||
'б' => 'в',
|
||||
'п' => 'у',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 12.6eaea3fa21b3b7d006ca7dfa27d4e282:
|
||||
array (
|
||||
4 => '',
|
||||
7 => 'd',
|
||||
1 => 'п',
|
||||
2 => 'пп',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 13.8800d48abb960a59002eef77f1d73ae0:
|
||||
array (
|
||||
'c' => 'i',
|
||||
'd' => 'y',
|
||||
'a' => 'k',
|
||||
)
|
||||
Result: true
|
134
ext/intl/tests/collator_compare.phpt
Executable file
134
ext/intl/tests/collator_compare.phpt
Executable file
@ -0,0 +1,134 @@
|
||||
--TEST--
|
||||
compare()
|
||||
--SKIPIF--
|
||||
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Compare various string pairs using various locales.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Converts comparison result to a character.
|
||||
*/
|
||||
function cmp_to_char( $comp_res )
|
||||
{
|
||||
switch( $comp_res )
|
||||
{
|
||||
case 0: // UCOL_EQUAL
|
||||
return '=';
|
||||
case 1: // UCOL_GREATER
|
||||
return '>';
|
||||
case -1: // UCOL_LESS
|
||||
return '<';
|
||||
default:
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare string pairs in the given array
|
||||
* using specified locale.
|
||||
*/
|
||||
function compare_pairs( $locale, $test_array )
|
||||
{
|
||||
$res_str = '';
|
||||
|
||||
$coll = ut_coll_create( $locale );
|
||||
|
||||
foreach( $test_array as $test_strings )
|
||||
{
|
||||
list( $str1, $str2 ) = $test_strings;
|
||||
|
||||
// Compare strings.
|
||||
$res_val = cmp_to_char( ut_coll_compare( $coll, $str1, $str2 ) );
|
||||
|
||||
// Concatenate result strings.
|
||||
$res_str .= dump( $str1 ) .
|
||||
' ' . $res_val . ' ' .
|
||||
dump( $str2 ) . "\n";
|
||||
}
|
||||
|
||||
return $res_str;
|
||||
|
||||
}
|
||||
|
||||
function ut_main()
|
||||
{
|
||||
$res_str = '';
|
||||
|
||||
// Compare strings using en_US locale.
|
||||
$test_params = array(
|
||||
array( 'abc', 'abc' ),
|
||||
array( 'Abc', 'abc' ),
|
||||
array( 'a' , 'abc' ),
|
||||
array( 'a' , '' ),
|
||||
array( '' , '' ),
|
||||
array( 'a' , 'b' ),
|
||||
array( 'ab' , 'b' ),
|
||||
array( 'ab' , 'a' ),
|
||||
array( 123 , 'abc' ),
|
||||
array( 'ac' , null ),
|
||||
array( '.' , '.' ),
|
||||
// Try to compare long strings.
|
||||
array( 'abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcde',
|
||||
'abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdea'),
|
||||
array( null , null )
|
||||
);
|
||||
|
||||
$res_str .= compare_pairs( 'en_US', $test_params );
|
||||
|
||||
|
||||
// Compare strings using ru_RU locale.
|
||||
$test_params = array(
|
||||
array( 'а', 'б' ),
|
||||
array( 'а', 'аа' ),
|
||||
array( 'аб', 'ба' ),
|
||||
array( 'а', ',' ),
|
||||
array( 'а', 'b' ),
|
||||
array( 'а', 'bb' ),
|
||||
array( 'а', 'ab' ),
|
||||
array( 'а', null )
|
||||
);
|
||||
|
||||
$res_str .= compare_pairs( 'ru_RU', $test_params );
|
||||
|
||||
|
||||
// Compare strings using lt_LT locale.
|
||||
$test_params = array(
|
||||
array( 'y', 'k' )
|
||||
);
|
||||
|
||||
$res_str .= compare_pairs( 'lt_LT', $test_params );
|
||||
|
||||
return $res_str;
|
||||
}
|
||||
|
||||
include_once( 'ut_common.inc' );
|
||||
ut_run();
|
||||
?>
|
||||
--EXPECT--
|
||||
'abc' = 'abc'
|
||||
'Abc' > 'abc'
|
||||
'a' < 'abc'
|
||||
'a' > ''
|
||||
'' = ''
|
||||
'a' < 'b'
|
||||
'ab' < 'b'
|
||||
'ab' > 'a'
|
||||
123 < 'abc'
|
||||
'ac' > NULL
|
||||
'.' = '.'
|
||||
'abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcde' < 'abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdea'
|
||||
NULL = NULL
|
||||
'а' < 'б'
|
||||
'а' < 'аа'
|
||||
'аб' < 'ба'
|
||||
'а' > ','
|
||||
'а' > 'b'
|
||||
'а' > 'bb'
|
||||
'а' > 'ab'
|
||||
'а' > NULL
|
||||
'y' < 'k'
|
81
ext/intl/tests/collator_create.phpt
Executable file
81
ext/intl/tests/collator_create.phpt
Executable file
@ -0,0 +1,81 @@
|
||||
--TEST--
|
||||
create()
|
||||
--SKIPIF--
|
||||
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Try creating collator with different locales
|
||||
* with Procedural and Object methods.
|
||||
*/
|
||||
|
||||
function ut_main()
|
||||
{
|
||||
$res_str = '';
|
||||
|
||||
$locales = array(
|
||||
'EN-US-ODESSA',
|
||||
'UK_UA_ODESSA',
|
||||
'uk-ua_CALIFORNIA@currency=;currency=GRN',
|
||||
'',
|
||||
'root',
|
||||
'uk@currency=EURO',
|
||||
'1234567891113151719212325272931333537394143454749515357596163656769717375777981838587899193959799'
|
||||
);
|
||||
|
||||
foreach( $locales as $locale )
|
||||
{
|
||||
// Create Collator with the current locale.
|
||||
$coll = ut_coll_create( $locale );
|
||||
if( !is_object($coll) )
|
||||
{
|
||||
$res_str .= "Error creating collator with '$locale' locale: " .
|
||||
intl_get_error_message() . "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the requested, valid and actual locales.
|
||||
$vloc = ut_coll_get_locale( $coll, Locale::VALID_LOCALE );
|
||||
$aloc = ut_coll_get_locale( $coll, Locale::ACTUAL_LOCALE );
|
||||
|
||||
// Show them.
|
||||
$res_str .= "Locale: '$locale'\n" .
|
||||
" ULOC_REQUESTED_LOCALE = '$locale'\n" .
|
||||
" ULOC_VALID_LOCALE = '$vloc'\n" .
|
||||
" ULOC_ACTUAL_LOCALE = '$aloc'\n";
|
||||
}
|
||||
|
||||
return $res_str;
|
||||
}
|
||||
|
||||
include_once( 'ut_common.inc' );
|
||||
ut_run();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Locale: 'EN-US-ODESSA'
|
||||
ULOC_REQUESTED_LOCALE = 'EN-US-ODESSA'
|
||||
ULOC_VALID_LOCALE = 'en_US'
|
||||
ULOC_ACTUAL_LOCALE = 'en'
|
||||
Locale: 'UK_UA_ODESSA'
|
||||
ULOC_REQUESTED_LOCALE = 'UK_UA_ODESSA'
|
||||
ULOC_VALID_LOCALE = 'uk_UA'
|
||||
ULOC_ACTUAL_LOCALE = 'uk'
|
||||
Locale: 'uk-ua_CALIFORNIA@currency=;currency=GRN'
|
||||
ULOC_REQUESTED_LOCALE = 'uk-ua_CALIFORNIA@currency=;currency=GRN'
|
||||
ULOC_VALID_LOCALE = 'uk_UA'
|
||||
ULOC_ACTUAL_LOCALE = 'uk'
|
||||
Locale: ''
|
||||
ULOC_REQUESTED_LOCALE = ''
|
||||
ULOC_VALID_LOCALE = '%s'
|
||||
ULOC_ACTUAL_LOCALE = '%s'
|
||||
Locale: 'root'
|
||||
ULOC_REQUESTED_LOCALE = 'root'
|
||||
ULOC_VALID_LOCALE = 'root'
|
||||
ULOC_ACTUAL_LOCALE = 'root'
|
||||
Locale: 'uk@currency=EURO'
|
||||
ULOC_REQUESTED_LOCALE = 'uk@currency=EURO'
|
||||
ULOC_VALID_LOCALE = 'uk'
|
||||
ULOC_ACTUAL_LOCALE = 'uk'
|
||||
Error creating collator with '1234567891113151719212325272931333537394143454749515357596163656769717375777981838587899193959799' locale: Locale string too long, should be no longer than 64 characters: U_ILLEGAL_ARGUMENT_ERROR
|
47
ext/intl/tests/collator_get_error_code.phpt
Executable file
47
ext/intl/tests/collator_get_error_code.phpt
Executable file
@ -0,0 +1,47 @@
|
||||
--TEST--
|
||||
get_error_code()
|
||||
--SKIPIF--
|
||||
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Retreive error code.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Check if error code equals to expected one.
|
||||
*/
|
||||
function check_rc( $rc, $expected )
|
||||
{
|
||||
return ( $rc === $expected ? "ok" : "failed" ) . "\n";
|
||||
}
|
||||
|
||||
function ut_main()
|
||||
{
|
||||
$res = '';
|
||||
$coll = ut_coll_create( 'ru_RU' );
|
||||
|
||||
// Try specifying a correct attribute.
|
||||
ut_coll_get_attribute( $coll, Collator::NORMALIZATION_MODE );
|
||||
$status = ut_coll_get_error_code( $coll );
|
||||
$res .= check_rc( $status, U_ZERO_ERROR );
|
||||
|
||||
// Try specifying an incorrect attribute.
|
||||
ut_coll_get_attribute( $coll, 12345 );
|
||||
$status = ut_coll_get_error_code( $coll );
|
||||
$res .= check_rc( $status, U_ILLEGAL_ARGUMENT_ERROR );
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
# Suppress warning messages.
|
||||
error_reporting( E_ERROR );
|
||||
|
||||
include_once( 'ut_common.inc' );
|
||||
ut_run();
|
||||
?>
|
||||
--EXPECT--
|
||||
ok
|
||||
ok
|
36
ext/intl/tests/collator_get_error_message.phpt
Executable file
36
ext/intl/tests/collator_get_error_message.phpt
Executable file
@ -0,0 +1,36 @@
|
||||
--TEST--
|
||||
get_error_message()
|
||||
--SKIPIF--
|
||||
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Retreive error message.
|
||||
*/
|
||||
|
||||
|
||||
function ut_main()
|
||||
{
|
||||
$res = '';
|
||||
$coll = ut_coll_create( 'ru_RU' );
|
||||
|
||||
// Try specifying a correct attribute.
|
||||
ut_coll_get_attribute( $coll, Collator::NORMALIZATION_MODE );
|
||||
$status = ut_coll_get_error_message( $coll );
|
||||
$res .= $status . "\n";
|
||||
|
||||
// Try specifying an incorrect attribute.
|
||||
ut_coll_get_attribute( $coll, 12345 );
|
||||
$status = ut_coll_get_error_message( $coll );
|
||||
$res .= $status . "\n";
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
include_once( 'ut_common.inc' );
|
||||
ut_run();
|
||||
?>
|
||||
--EXPECT--
|
||||
U_ZERO_ERROR
|
||||
Error getting attribute value: U_ILLEGAL_ARGUMENT_ERROR
|
52
ext/intl/tests/collator_get_locale.phpt
Executable file
52
ext/intl/tests/collator_get_locale.phpt
Executable file
@ -0,0 +1,52 @@
|
||||
--TEST--
|
||||
get_locale()
|
||||
--SKIPIF--
|
||||
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Try to specify valid and invalid locale types when getting locale.
|
||||
*/
|
||||
|
||||
function ut_main()
|
||||
{
|
||||
$locales = array(
|
||||
Locale::VALID_LOCALE,
|
||||
Locale::ACTUAL_LOCALE,
|
||||
100,
|
||||
-100,
|
||||
-9999999999999,
|
||||
9999999999999,
|
||||
1.2,
|
||||
9999999999999999999999999999999999999999999999
|
||||
);
|
||||
|
||||
$coll = ut_coll_create( 'en_US' );
|
||||
$res_str = '';
|
||||
|
||||
foreach( $locales as $locale )
|
||||
{
|
||||
$rc = ut_coll_get_locale( $coll, $locale );
|
||||
|
||||
$res_str .= sprintf(
|
||||
"Locale of type %s is %s\n",
|
||||
dump( $locale ),
|
||||
dump( $rc ) );
|
||||
}
|
||||
|
||||
return $res_str . "\n";
|
||||
}
|
||||
|
||||
include_once( 'ut_common.inc' );
|
||||
ut_run();
|
||||
?>
|
||||
--EXPECT--
|
||||
Locale of type 1 is 'en_US'
|
||||
Locale of type 0 is 'en'
|
||||
Locale of type 100 is false
|
||||
Locale of type -100 is false
|
||||
Locale of type -9999999999999 is false
|
||||
Locale of type 9999999999999 is false
|
||||
Locale of type 1.2 is 'en_US'
|
||||
Locale of type 1.0E+46 is false
|
41
ext/intl/tests/collator_get_set_attribute.phpt
Executable file
41
ext/intl/tests/collator_get_set_attribute.phpt
Executable file
@ -0,0 +1,41 @@
|
||||
--TEST--
|
||||
get/set_attribute()
|
||||
--SKIPIF--
|
||||
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Try to set/get a collation attribute.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Return current normalication mode.
|
||||
*/
|
||||
function check_val( $coll )
|
||||
{
|
||||
$val = ut_coll_get_attribute( $coll, Collator::NORMALIZATION_MODE );
|
||||
return sprintf( "%s\n", ( $val == Collator::OFF ? "off" : "on" ) );
|
||||
}
|
||||
|
||||
function ut_main()
|
||||
{
|
||||
$res = '';
|
||||
$coll = ut_coll_create( 'en_US' );
|
||||
|
||||
ut_coll_set_attribute( $coll, Collator::NORMALIZATION_MODE, Collator::OFF );
|
||||
$res .= check_val( $coll );
|
||||
|
||||
ut_coll_set_attribute( $coll, Collator::NORMALIZATION_MODE, Collator::ON );
|
||||
$res .= check_val( $coll );
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
include( 'ut_common.inc' );
|
||||
ut_run();
|
||||
?>
|
||||
--EXPECT--
|
||||
off
|
||||
on
|
41
ext/intl/tests/collator_get_set_strength.phpt
Executable file
41
ext/intl/tests/collator_get_set_strength.phpt
Executable file
@ -0,0 +1,41 @@
|
||||
--TEST--
|
||||
get/set_strength()
|
||||
--SKIPIF--
|
||||
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Try to set/get collation strength.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set given collation strength, then get it back
|
||||
* and check if it's the same.
|
||||
*/
|
||||
function check_set_strength( $coll, $val )
|
||||
{
|
||||
ut_coll_set_strength( $coll, $val );
|
||||
$new_val = ut_coll_get_strength( $coll );
|
||||
return ( $new_val == $val ? "ok" : "failed" ) . "\n";
|
||||
}
|
||||
|
||||
function ut_main()
|
||||
{
|
||||
$res = '';
|
||||
$coll = ut_coll_create( 'en_US' );
|
||||
|
||||
$res .= check_set_strength( $coll, Collator::PRIMARY );
|
||||
$res .= check_set_strength( $coll, Collator::SECONDARY );
|
||||
$res .= check_set_strength( $coll, Collator::TERTIARY );
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
include_once( 'ut_common.inc' );
|
||||
ut_run();
|
||||
?>
|
||||
--EXPECT--
|
||||
ok
|
||||
ok
|
||||
ok
|
247
ext/intl/tests/collator_sort.phpt
Executable file
247
ext/intl/tests/collator_sort.phpt
Executable file
@ -0,0 +1,247 @@
|
||||
--TEST--
|
||||
sort()
|
||||
--SKIPIF--
|
||||
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Sort arrays using various locales.
|
||||
*/
|
||||
|
||||
|
||||
$test_num = 1;
|
||||
|
||||
/*
|
||||
* Sort arrays in the given list using specified locale.
|
||||
*/
|
||||
function sort_arrays( $locale, $arrays, $sort_flag = Collator::SORT_REGULAR )
|
||||
{
|
||||
$res_str = '';
|
||||
|
||||
$coll = ut_coll_create( $locale );
|
||||
|
||||
foreach( $arrays as $array )
|
||||
{
|
||||
// Sort array values
|
||||
$res_val = ut_coll_sort( $coll, $array, $sort_flag );
|
||||
|
||||
// Concatenate the sorted array and function result
|
||||
// with output string.
|
||||
$res_dump = "\n" . dump( $array ) .
|
||||
"\n Result: " . dump( $res_val );
|
||||
|
||||
// Preppend test signature to output string
|
||||
$md5 = md5( $res_dump );
|
||||
|
||||
global $test_num;
|
||||
|
||||
$res_str .= "\n\n".
|
||||
"Test $test_num.$md5:" .
|
||||
$res_dump;
|
||||
++$test_num;
|
||||
}
|
||||
|
||||
return $res_str;
|
||||
}
|
||||
|
||||
function ut_main()
|
||||
{
|
||||
global $test_num;
|
||||
$test_num = 1;
|
||||
$res_str = '';
|
||||
|
||||
// Sort an array in SORT_REGULAR mode using en_US locale.
|
||||
$test_params = array(
|
||||
array( 'abc', 'abd', 'aaa' ),
|
||||
array( 'm' , '1' , '_' ),
|
||||
array( 'a' , 'aaa', 'aa' ),
|
||||
array( 'ba' , 'b' , 'ab' ),
|
||||
array( 'e' , 'c' , 'a' ),
|
||||
array( '100', '25' , '36' ),
|
||||
array( 5 , '30' , 2 ),
|
||||
array( 'd' , '' , ' a' ),
|
||||
array( 'd ' , 'f ' , ' a' ),
|
||||
array( 'a' , null , '3' ),
|
||||
array( 'y' , 'k' , 'i' )
|
||||
);
|
||||
|
||||
$res_str .= sort_arrays( 'en_US', $test_params );
|
||||
|
||||
$test_params = array(
|
||||
array( '100', '25' , '36' ),
|
||||
array( 5 , '30' , 2 ),
|
||||
array( 'd' , '' , ' a' ),
|
||||
array( 'y' , 'k' , 'i' )
|
||||
);
|
||||
|
||||
// Sort in en_US locale with SORT_STRING flag
|
||||
$res_str .= sort_arrays( 'en_US', $test_params, Collator::SORT_STRING );
|
||||
|
||||
|
||||
// Sort a non-ASCII array using ru_RU locale.
|
||||
$test_params = array(
|
||||
array( 'абг', 'абв', 'ааа', 'abc' ),
|
||||
array( 'аа', 'ааа' , 'а' )
|
||||
);
|
||||
|
||||
$res_str .= sort_arrays( 'ru_RU', $test_params );
|
||||
|
||||
// Sort an array using Lithuanian locale.
|
||||
$test_params = array(
|
||||
array( 'y' , 'k' , 'i' )
|
||||
);
|
||||
|
||||
$res_str .= sort_arrays( 'lt_LT', $test_params );
|
||||
|
||||
return $res_str;
|
||||
}
|
||||
|
||||
include_once( 'ut_common.inc' );
|
||||
ut_run();
|
||||
?>
|
||||
--EXPECT--
|
||||
Test 1.e8f1cd28133d79ecd660002f1c660d0e:
|
||||
array (
|
||||
0 => 'aaa',
|
||||
1 => 'abc',
|
||||
2 => 'abd',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 2.c2ded12173dd2996927378cae37eb275:
|
||||
array (
|
||||
0 => '_',
|
||||
1 => '1',
|
||||
2 => 'm',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 3.54071c968d71cb98c5d379145f8d7d38:
|
||||
array (
|
||||
0 => 'a',
|
||||
1 => 'aa',
|
||||
2 => 'aaa',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 4.19abe63d6f6dfef65b0e3c9ab4826b07:
|
||||
array (
|
||||
0 => 'ab',
|
||||
1 => 'b',
|
||||
2 => 'ba',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 5.9a8dc0a9bc771368c2f1fc3d02754610:
|
||||
array (
|
||||
0 => 'a',
|
||||
1 => 'c',
|
||||
2 => 'e',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 6.ab530b060e5e54a65bfb8b9f8fc61870:
|
||||
array (
|
||||
0 => '25',
|
||||
1 => '36',
|
||||
2 => '100',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 7.0718dd838509017bded2ed307a6e785f:
|
||||
array (
|
||||
0 => 2,
|
||||
1 => 5,
|
||||
2 => '30',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 8.923d65739c5219c634616ffd100a50e4:
|
||||
array (
|
||||
0 => '',
|
||||
1 => ' a',
|
||||
2 => 'd',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 9.289bc2f28e87d3201ec9d7e8477ae1b0:
|
||||
array (
|
||||
0 => ' a',
|
||||
1 => 'd ',
|
||||
2 => 'f ',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 10.de0fd958484f2377a645835d7fbcf124:
|
||||
array (
|
||||
0 => NULL,
|
||||
1 => '3',
|
||||
2 => 'a',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 11.dd2b8f0adb37c45d528cad1a0cc0f361:
|
||||
array (
|
||||
0 => 'i',
|
||||
1 => 'k',
|
||||
2 => 'y',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 12.1e6b4d6f7df9d4580317634ea46d8208:
|
||||
array (
|
||||
0 => '100',
|
||||
1 => '25',
|
||||
2 => '36',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 13.cec115dc9850b98dfbdf102efa09e61b:
|
||||
array (
|
||||
0 => 2,
|
||||
1 => '30',
|
||||
2 => 5,
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 14.923d65739c5219c634616ffd100a50e4:
|
||||
array (
|
||||
0 => '',
|
||||
1 => ' a',
|
||||
2 => 'd',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 15.dd2b8f0adb37c45d528cad1a0cc0f361:
|
||||
array (
|
||||
0 => 'i',
|
||||
1 => 'k',
|
||||
2 => 'y',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 16.ca0e38a2e3147dd97070f2128f140934:
|
||||
array (
|
||||
0 => 'abc',
|
||||
1 => 'ааа',
|
||||
2 => 'абв',
|
||||
3 => 'абг',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 17.91480b10473a0c96a4cd6d88c23c577a:
|
||||
array (
|
||||
0 => 'а',
|
||||
1 => 'аа',
|
||||
2 => 'ааа',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 18.fdd3fe3981476039164aa000bf9177f2:
|
||||
array (
|
||||
0 => 'i',
|
||||
1 => 'y',
|
||||
2 => 'k',
|
||||
)
|
||||
Result: true
|
189
ext/intl/tests/collator_sort_with_sort_keys.phpt
Executable file
189
ext/intl/tests/collator_sort_with_sort_keys.phpt
Executable file
@ -0,0 +1,189 @@
|
||||
--TEST--
|
||||
sort_with_sort_keys()
|
||||
--SKIPIF--
|
||||
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Sort arrays using various locales.
|
||||
*/
|
||||
|
||||
|
||||
$test_num = 1;
|
||||
|
||||
/*
|
||||
* Sort arrays in the given list using specified locale.
|
||||
*/
|
||||
function sort_arrays( $locale, $arrays )
|
||||
{
|
||||
$res_str = '';
|
||||
|
||||
$coll = ut_coll_create( $locale );
|
||||
|
||||
foreach( $arrays as $array )
|
||||
{
|
||||
// Sort array values
|
||||
$res_val = ut_coll_sort_with_sort_keys( $coll, $array );
|
||||
|
||||
// Concatenate the sorted array and function result
|
||||
// with output string.
|
||||
$res_dump = "\n" . dump( $array ) .
|
||||
"\n Result: " . dump( $res_val );
|
||||
|
||||
|
||||
// Preppend test signature to output string
|
||||
$md5 = md5( $res_dump );
|
||||
|
||||
global $test_num;
|
||||
|
||||
$res_str .= "\n\n".
|
||||
"Test $test_num.$md5:" .
|
||||
$res_dump;
|
||||
++$test_num;
|
||||
}
|
||||
|
||||
return $res_str;
|
||||
}
|
||||
|
||||
|
||||
function ut_main()
|
||||
{
|
||||
global $test_num;
|
||||
$test_num = 1;
|
||||
$res_str = '';
|
||||
|
||||
// Sort an array in SORT_REGULAR mode using en_US locale.
|
||||
$test_params = array(
|
||||
array( 'abc', 'abd', 'aaa' ),
|
||||
array( 'm' , '1' , '_' ),
|
||||
array( 'a' , 'aaa', 'aa' ),
|
||||
array( 'ba' , 'b' , 'ab' ),
|
||||
array( 'e' , 'c' , 'a' ),
|
||||
array( 'd' , '' , ' a' ),
|
||||
array( 'd ' , 'f ' , ' a' ),
|
||||
array( 'a' , null , '3' ),
|
||||
array( 'y' , 'i' , 'k' )
|
||||
);
|
||||
|
||||
$res_str .= sort_arrays( 'en_US', $test_params );
|
||||
|
||||
// Sort a non-ASCII array using ru_RU locale.
|
||||
$test_params = array(
|
||||
array( 'абг', 'абв', 'ааа', 'abc' ),
|
||||
array( 'аа', 'ааа', 'а' )
|
||||
);
|
||||
|
||||
$res_str .= sort_arrays( 'ru_RU', $test_params );
|
||||
|
||||
// Array with data for sorting.
|
||||
$test_params = array(
|
||||
array( 'y' , 'i' , 'k' )
|
||||
);
|
||||
|
||||
// Sort an array using Lithuanian locale.
|
||||
$res_str .= sort_arrays( 'lt_LT', $test_params );
|
||||
|
||||
return $res_str . "\n";
|
||||
}
|
||||
|
||||
include_once( 'ut_common.inc' );
|
||||
ut_run();
|
||||
?>
|
||||
--EXPECT--
|
||||
Test 1.e8f1cd28133d79ecd660002f1c660d0e:
|
||||
array (
|
||||
0 => 'aaa',
|
||||
1 => 'abc',
|
||||
2 => 'abd',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 2.c2ded12173dd2996927378cae37eb275:
|
||||
array (
|
||||
0 => '_',
|
||||
1 => '1',
|
||||
2 => 'm',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 3.54071c968d71cb98c5d379145f8d7d38:
|
||||
array (
|
||||
0 => 'a',
|
||||
1 => 'aa',
|
||||
2 => 'aaa',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 4.19abe63d6f6dfef65b0e3c9ab4826b07:
|
||||
array (
|
||||
0 => 'ab',
|
||||
1 => 'b',
|
||||
2 => 'ba',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 5.9a8dc0a9bc771368c2f1fc3d02754610:
|
||||
array (
|
||||
0 => 'a',
|
||||
1 => 'c',
|
||||
2 => 'e',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 6.923d65739c5219c634616ffd100a50e4:
|
||||
array (
|
||||
0 => '',
|
||||
1 => ' a',
|
||||
2 => 'd',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 7.289bc2f28e87d3201ec9d7e8477ae1b0:
|
||||
array (
|
||||
0 => ' a',
|
||||
1 => 'd ',
|
||||
2 => 'f ',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 8.de0fd958484f2377a645835d7fbcf124:
|
||||
array (
|
||||
0 => NULL,
|
||||
1 => '3',
|
||||
2 => 'a',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 9.dd2b8f0adb37c45d528cad1a0cc0f361:
|
||||
array (
|
||||
0 => 'i',
|
||||
1 => 'k',
|
||||
2 => 'y',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 10.ca0e38a2e3147dd97070f2128f140934:
|
||||
array (
|
||||
0 => 'abc',
|
||||
1 => 'ааа',
|
||||
2 => 'абв',
|
||||
3 => 'абг',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 11.91480b10473a0c96a4cd6d88c23c577a:
|
||||
array (
|
||||
0 => 'а',
|
||||
1 => 'аа',
|
||||
2 => 'ааа',
|
||||
)
|
||||
Result: true
|
||||
|
||||
Test 12.fdd3fe3981476039164aa000bf9177f2:
|
||||
array (
|
||||
0 => 'i',
|
||||
1 => 'y',
|
||||
2 => 'k',
|
||||
)
|
||||
Result: true
|
297
ext/intl/tests/dateformat_format.phpt
Executable file
297
ext/intl/tests/dateformat_format.phpt
Executable file
@ -0,0 +1,297 @@
|
||||
--TEST--
|
||||
datefmt_format_code()
|
||||
--SKIPIF--
|
||||
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Test for the datefmt_format function
|
||||
*/
|
||||
|
||||
|
||||
function ut_main()
|
||||
{
|
||||
$locale_arr = array (
|
||||
'en_US'
|
||||
);
|
||||
|
||||
$datetype_arr = array (
|
||||
IntlDateFormatter::FULL,
|
||||
IntlDateFormatter::LONG,
|
||||
IntlDateFormatter::MEDIUM,
|
||||
IntlDateFormatter::SHORT,
|
||||
IntlDateFormatter::NONE
|
||||
);
|
||||
|
||||
$res_str = '';
|
||||
|
||||
|
||||
$time_arr = array (
|
||||
0,
|
||||
-1200000,
|
||||
1200000,
|
||||
2200000000,
|
||||
-2200000000,
|
||||
90099999,
|
||||
3600,
|
||||
-3600
|
||||
);
|
||||
|
||||
$localtime_arr1 = array (
|
||||
'tm_sec' => 24 ,
|
||||
'tm_min' => 3,
|
||||
'tm_hour' => 19,
|
||||
'tm_mday' => 3,
|
||||
'tm_mon' => 3,
|
||||
'tm_year' => 105,
|
||||
'tm_wday' => 0,
|
||||
'tm_yday' => 93,
|
||||
'tm_isdst' => 1
|
||||
);
|
||||
$localtime_arr2 = array (
|
||||
'tm_sec' => 24 ,
|
||||
'tm_min' => 3,
|
||||
'tm_hour' => 3,
|
||||
'tm_mday' => 3,
|
||||
'tm_mon' => 3,
|
||||
'tm_year' => 205,
|
||||
'tm_wday' => 5,
|
||||
'tm_yday' => 93,
|
||||
'tm_isdst' => 1
|
||||
);
|
||||
$localtime_arr3 = array (
|
||||
'tm_sec' => 24 ,
|
||||
'tm_min' => 3,
|
||||
'tm_hour' => 3,
|
||||
'tm_mday' => 3,
|
||||
'tm_mon' => 3,
|
||||
'tm_year' => -5,
|
||||
'tm_wday' => 3,
|
||||
'tm_yday' => 93,
|
||||
'tm_isdst' => 1
|
||||
);
|
||||
|
||||
$localtime_arr = array (
|
||||
$localtime_arr1,
|
||||
$localtime_arr2,
|
||||
$localtime_arr3
|
||||
);
|
||||
|
||||
//Test format with input as a timestamp : integer
|
||||
foreach( $time_arr as $timestamp_entry){
|
||||
$res_str .= "\n------------\n";
|
||||
$res_str .= "\nInput timestamp is : $timestamp_entry";
|
||||
$res_str .= "\n------------\n";
|
||||
foreach( $locale_arr as $locale_entry ){
|
||||
foreach( $datetype_arr as $datetype_entry )
|
||||
{
|
||||
$res_str .= "\nIntlDateFormatter locale= $locale_entry ,datetype = $datetype_entry ,timetype =$datetype_entry ";
|
||||
//$fmt = ut_datefmt_create( $locale_entry , $datetype_entry ,$datetype_entry,'America/Los_Angeles', IntlDateFormatter::GREGORIAN ,"dd/mm/yyyy");
|
||||
$fmt = ut_datefmt_create( $locale_entry , $datetype_entry ,$datetype_entry,'America/Los_Angeles', IntlDateFormatter::GREGORIAN );
|
||||
//$fmt = ut_datefmt_create( $locale_entry , $datetype_entry ,$datetype_entry);
|
||||
$formatted = ut_datefmt_format( $fmt , $timestamp_entry);
|
||||
$res_str .= "\nFormatted timestamp is : $formatted";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Test format with input as a localtime :array
|
||||
foreach( $localtime_arr as $localtime_entry){
|
||||
$res_str .= "\n------------\n";
|
||||
$res_str .= "\nInput localtime is : ";
|
||||
foreach( $localtime_entry as $key => $value){
|
||||
$res_str .= "$key : '$value' , ";
|
||||
}
|
||||
|
||||
$res_str .= "\n------------\n";
|
||||
foreach( $locale_arr as $locale_entry ){
|
||||
foreach( $datetype_arr as $datetype_entry )
|
||||
{
|
||||
$res_str .= "\nIntlDateFormatter locale= $locale_entry ,datetype = $datetype_entry ,timetype =$datetype_entry ";
|
||||
$fmt = ut_datefmt_create( $locale_entry , $datetype_entry ,$datetype_entry);
|
||||
$formatted1 = ut_datefmt_format( $fmt , $localtime_entry);
|
||||
if( intl_get_error_code() == U_ZERO_ERROR){
|
||||
$res_str .= "\nFormatted localtime_array is : $formatted1";
|
||||
}else{
|
||||
$res_str .= "\nError while formatting as: '".intl_get_error_message()."'";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $res_str;
|
||||
|
||||
}
|
||||
|
||||
include_once( 'ut_common.inc' );
|
||||
|
||||
// Run the test
|
||||
ut_run();
|
||||
?>
|
||||
--EXPECT--
|
||||
------------
|
||||
|
||||
Input timestamp is : 0
|
||||
------------
|
||||
|
||||
IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0
|
||||
Formatted timestamp is : Wednesday, December 31, 1969 4:00:00 PM PT
|
||||
IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1
|
||||
Formatted timestamp is : December 31, 1969 4:00:00 PM PST
|
||||
IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2
|
||||
Formatted timestamp is : Dec 31, 1969 4:00:00 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = 3 ,timetype =3
|
||||
Formatted timestamp is : 12/31/69 4:00 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = -1 ,timetype =-1
|
||||
Formatted timestamp is : 19691231 04:00 PM
|
||||
------------
|
||||
|
||||
Input timestamp is : -1200000
|
||||
------------
|
||||
|
||||
IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0
|
||||
Formatted timestamp is : Wednesday, December 17, 1969 6:40:00 PM PT
|
||||
IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1
|
||||
Formatted timestamp is : December 17, 1969 6:40:00 PM PST
|
||||
IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2
|
||||
Formatted timestamp is : Dec 17, 1969 6:40:00 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = 3 ,timetype =3
|
||||
Formatted timestamp is : 12/17/69 6:40 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = -1 ,timetype =-1
|
||||
Formatted timestamp is : 19691217 06:40 PM
|
||||
------------
|
||||
|
||||
Input timestamp is : 1200000
|
||||
------------
|
||||
|
||||
IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0
|
||||
Formatted timestamp is : Wednesday, January 14, 1970 1:20:00 PM PT
|
||||
IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1
|
||||
Formatted timestamp is : January 14, 1970 1:20:00 PM PST
|
||||
IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2
|
||||
Formatted timestamp is : Jan 14, 1970 1:20:00 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = 3 ,timetype =3
|
||||
Formatted timestamp is : 1/14/70 1:20 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = -1 ,timetype =-1
|
||||
Formatted timestamp is : 19700114 01:20 PM
|
||||
------------
|
||||
|
||||
Input timestamp is : 2200000000
|
||||
------------
|
||||
|
||||
IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0
|
||||
Formatted timestamp is : Sunday, September 18, 2039 4:06:40 PM PT
|
||||
IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1
|
||||
Formatted timestamp is : September 18, 2039 4:06:40 PM PDT
|
||||
IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2
|
||||
Formatted timestamp is : Sep 18, 2039 4:06:40 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = 3 ,timetype =3
|
||||
Formatted timestamp is : 9/18/39 4:06 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = -1 ,timetype =-1
|
||||
Formatted timestamp is : 20390918 04:06 PM
|
||||
------------
|
||||
|
||||
Input timestamp is : -2200000000
|
||||
------------
|
||||
|
||||
IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0
|
||||
Formatted timestamp is : Saturday, April 14, 1900 5:53:20 PM PT
|
||||
IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1
|
||||
Formatted timestamp is : April 14, 1900 5:53:20 PM PDT
|
||||
IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2
|
||||
Formatted timestamp is : Apr 14, 1900 5:53:20 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = 3 ,timetype =3
|
||||
Formatted timestamp is : 4/14/00 5:53 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = -1 ,timetype =-1
|
||||
Formatted timestamp is : 19000414 05:53 PM
|
||||
------------
|
||||
|
||||
Input timestamp is : 90099999
|
||||
------------
|
||||
|
||||
IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0
|
||||
Formatted timestamp is : Wednesday, November 8, 1972 11:46:39 AM PT
|
||||
IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1
|
||||
Formatted timestamp is : November 8, 1972 11:46:39 AM PST
|
||||
IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2
|
||||
Formatted timestamp is : Nov 8, 1972 11:46:39 AM
|
||||
IntlDateFormatter locale= en_US ,datetype = 3 ,timetype =3
|
||||
Formatted timestamp is : 11/8/72 11:46 AM
|
||||
IntlDateFormatter locale= en_US ,datetype = -1 ,timetype =-1
|
||||
Formatted timestamp is : 19721108 11:46 AM
|
||||
------------
|
||||
|
||||
Input timestamp is : 3600
|
||||
------------
|
||||
|
||||
IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0
|
||||
Formatted timestamp is : Wednesday, December 31, 1969 5:00:00 PM PT
|
||||
IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1
|
||||
Formatted timestamp is : December 31, 1969 5:00:00 PM PST
|
||||
IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2
|
||||
Formatted timestamp is : Dec 31, 1969 5:00:00 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = 3 ,timetype =3
|
||||
Formatted timestamp is : 12/31/69 5:00 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = -1 ,timetype =-1
|
||||
Formatted timestamp is : 19691231 05:00 PM
|
||||
------------
|
||||
|
||||
Input timestamp is : -3600
|
||||
------------
|
||||
|
||||
IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0
|
||||
Formatted timestamp is : Wednesday, December 31, 1969 3:00:00 PM PT
|
||||
IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1
|
||||
Formatted timestamp is : December 31, 1969 3:00:00 PM PST
|
||||
IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2
|
||||
Formatted timestamp is : Dec 31, 1969 3:00:00 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = 3 ,timetype =3
|
||||
Formatted timestamp is : 12/31/69 3:00 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = -1 ,timetype =-1
|
||||
Formatted timestamp is : 19691231 03:00 PM
|
||||
------------
|
||||
|
||||
Input localtime is : tm_sec : '24' , tm_min : '3' , tm_hour : '19' , tm_mday : '3' , tm_mon : '3' , tm_year : '105' , tm_wday : '0' , tm_yday : '93' , tm_isdst : '1' ,
|
||||
------------
|
||||
|
||||
IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0
|
||||
Formatted localtime_array is : Sunday, April 3, 2005 7:03:24 PM PT
|
||||
IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1
|
||||
Formatted localtime_array is : April 3, 2005 7:03:24 PM PDT
|
||||
IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2
|
||||
Formatted localtime_array is : Apr 3, 2005 7:03:24 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = 3 ,timetype =3
|
||||
Formatted localtime_array is : 4/3/05 7:03 PM
|
||||
IntlDateFormatter locale= en_US ,datetype = -1 ,timetype =-1
|
||||
Formatted localtime_array is : 20050403 07:03 PM
|
||||
------------
|
||||
|
||||
Input localtime is : tm_sec : '24' , tm_min : '3' , tm_hour : '3' , tm_mday : '3' , tm_mon : '3' , tm_year : '205' , tm_wday : '5' , tm_yday : '93' , tm_isdst : '1' ,
|
||||
------------
|
||||
|
||||
IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0
|
||||
Formatted localtime_array is : Friday, April 3, 2105 3:03:24 AM PT
|
||||
IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1
|
||||
Formatted localtime_array is : April 3, 2105 3:03:24 AM PDT
|
||||
IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2
|
||||
Formatted localtime_array is : Apr 3, 2105 3:03:24 AM
|
||||
IntlDateFormatter locale= en_US ,datetype = 3 ,timetype =3
|
||||
Formatted localtime_array is : 4/3/05 3:03 AM
|
||||
IntlDateFormatter locale= en_US ,datetype = -1 ,timetype =-1
|
||||
Formatted localtime_array is : 21050403 03:03 AM
|
||||
------------
|
||||
|
||||
Input localtime is : tm_sec : '24' , tm_min : '3' , tm_hour : '3' , tm_mday : '3' , tm_mon : '3' , tm_year : '-5' , tm_wday : '3' , tm_yday : '93' , tm_isdst : '1' ,
|
||||
------------
|
||||
|
||||
IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0
|
||||
Formatted localtime_array is : Wednesday, April 3, 1895 3:03:24 AM PT
|
||||
IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1
|
||||
Formatted localtime_array is : April 3, 1895 3:03:24 AM PDT
|
||||
IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2
|
||||
Formatted localtime_array is : Apr 3, 1895 3:03:24 AM
|
||||
IntlDateFormatter locale= en_US ,datetype = 3 ,timetype =3
|
||||
Formatted localtime_array is : 4/3/95 3:03 AM
|
||||
IntlDateFormatter locale= en_US ,datetype = -1 ,timetype =-1
|
||||
Formatted localtime_array is : 18950403 03:03 AM
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user