From 0d16b1516b6b9ef0c2696bc19069e4cda5aee0ea Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Mon, 7 Jul 2008 22:51:04 +0000 Subject: [PATCH] Merge intl extension into core --- ext/intl/CREDITS | 2 + ext/intl/TODO | 5 + ext/intl/collator/collator.c | 96 + ext/intl/collator/collator.h | 29 + ext/intl/collator/collator_attr.c | 157 ++ ext/intl/collator/collator_attr.h | 28 + ext/intl/collator/collator_class.c | 197 ++ ext/intl/collator/collator_class.h | 71 + ext/intl/collator/collator_compare.c | 119 ++ ext/intl/collator/collator_compare.h | 25 + ext/intl/collator/collator_convert.c | 482 +++++ ext/intl/collator/collator_convert.h | 38 + ext/intl/collator/collator_create.c | 135 ++ ext/intl/collator/collator_create.h | 27 + ext/intl/collator/collator_error.c | 94 + ext/intl/collator/collator_error.h | 26 + ext/intl/collator/collator_is_numeric.c | 305 +++ ext/intl/collator/collator_is_numeric.h | 26 + ext/intl/collator/collator_locale.c | 71 + ext/intl/collator/collator_locale.h | 25 + ext/intl/collator/collator_sort.c | 532 +++++ ext/intl/collator/collator_sort.h | 29 + ext/intl/common/common_error.c | 266 +++ ext/intl/common/common_error.h | 30 + ext/intl/config.m4 | 66 + ext/intl/config.w32 | 71 + ext/intl/doc/Tutorial.txt | 239 +++ ext/intl/doc/collator_api.php | 398 ++++ ext/intl/doc/common_api.php | 58 + ext/intl/doc/datefmt_api.php | 439 +++++ ext/intl/doc/formatter_api.php | 502 +++++ ext/intl/doc/grapheme_api.php | 132 ++ ext/intl/doc/locale_api.php | 432 ++++ ext/intl/doc/msgfmt_api.php | 209 ++ ext/intl/doc/normalizer_api.php | 92 + ext/intl/formatter/formatter.c | 152 ++ ext/intl/formatter/formatter.h | 24 + ext/intl/formatter/formatter_attr.c | 443 +++++ ext/intl/formatter/formatter_attr.h | 32 + ext/intl/formatter/formatter_class.c | 147 ++ ext/intl/formatter/formatter_class.h | 41 + ext/intl/formatter/formatter_data.c | 72 + ext/intl/formatter/formatter_data.h | 38 + ext/intl/formatter/formatter_format.c | 207 ++ ext/intl/formatter/formatter_format.h | 31 + ext/intl/formatter/formatter_main.c | 220 +++ ext/intl/formatter/formatter_main.h | 27 + ext/intl/formatter/formatter_parse.c | 173 ++ ext/intl/formatter/formatter_parse.h | 25 + ext/intl/grapheme/grapheme.h | 37 + ext/intl/grapheme/grapheme_string.c | 913 +++++++++ ext/intl/grapheme/grapheme_util.c | 619 ++++++ ext/intl/grapheme/grapheme_util.h | 59 + ext/intl/intl_common.h | 44 + ext/intl/intl_convert.c | 154 ++ ext/intl/intl_convert.h | 33 + ext/intl/intl_data.h | 87 + ext/intl/intl_error.c | 215 ++ ext/intl/intl_error.h | 46 + ext/intl/locale/locale.c | 70 + ext/intl/locale/locale.h | 36 + ext/intl/locale/locale_class.c | 126 ++ ext/intl/locale/locale_class.h | 46 + ext/intl/locale/locale_methods.c | 1732 +++++++++++++++++ ext/intl/locale/locale_methods.h | 47 + ext/intl/msgformat/msgformat.c | 256 +++ ext/intl/msgformat/msgformat.h | 27 + ext/intl/msgformat/msgformat_attr.c | 144 ++ ext/intl/msgformat/msgformat_attr.h | 26 + ext/intl/msgformat/msgformat_class.c | 127 ++ ext/intl/msgformat/msgformat_class.h | 41 + ext/intl/msgformat/msgformat_data.c | 98 + ext/intl/msgformat/msgformat_data.h | 41 + ext/intl/msgformat/msgformat_format.c | 184 ++ ext/intl/msgformat/msgformat_format.h | 25 + ext/intl/msgformat/msgformat_helpers.cpp | 211 ++ ext/intl/msgformat/msgformat_helpers.h | 25 + ext/intl/msgformat/msgformat_parse.c | 157 ++ ext/intl/msgformat/msgformat_parse.h | 25 + ext/intl/normalizer/normalizer.c | 68 + ext/intl/normalizer/normalizer.h | 37 + ext/intl/normalizer/normalizer_class.c | 82 + ext/intl/normalizer/normalizer_class.h | 52 + ext/intl/normalizer/normalizer_normalize.c | 256 +++ ext/intl/normalizer/normalizer_normalize.h | 25 + ext/intl/php_intl.c | 490 +++++ ext/intl/php_intl.h | 76 + ext/intl/tests/bug12887.phpt | 29 + ext/intl/tests/collation_customization.phpt | 70 + ext/intl/tests/collator_asort.phpt | 242 +++ ext/intl/tests/collator_compare.phpt | 134 ++ ext/intl/tests/collator_create.phpt | 81 + ext/intl/tests/collator_get_error_code.phpt | 47 + .../tests/collator_get_error_message.phpt | 36 + ext/intl/tests/collator_get_locale.phpt | 52 + .../tests/collator_get_set_attribute.phpt | 41 + ext/intl/tests/collator_get_set_strength.phpt | 41 + ext/intl/tests/collator_sort.phpt | 247 +++ .../tests/collator_sort_with_sort_keys.phpt | 189 ++ ext/intl/tests/dateformat_format.phpt | 297 +++ ext/intl/tests/dateformat_format_parse.phpt | 307 +++ ext/intl/tests/dateformat_get_datetype.phpt | 57 + ext/intl/tests/dateformat_get_locale.phpt | 53 + .../tests/dateformat_get_set_calendar.phpt | 60 + .../tests/dateformat_get_set_pattern.phpt | 84 + ext/intl/tests/dateformat_get_timetype.phpt | 57 + .../tests/dateformat_get_timezone_id.phpt | 49 + ext/intl/tests/dateformat_is_set_lenient.phpt | 88 + ext/intl/tests/dateformat_localtime.phpt | 133 ++ ext/intl/tests/dateformat_parse.phpt | 82 + .../dateformat_parse_localtime_parsepos.phpt | 119 ++ .../dateformat_parse_timestamp_parsepos.phpt | 137 ++ .../tests/dateformat_set_timezone_id.phpt | 75 + ext/intl/tests/formatter_fail.phpt | 79 + ext/intl/tests/formatter_format.phpt | 108 + ext/intl/tests/formatter_format_conv.phpt | 24 + ext/intl/tests/formatter_format_currency.phpt | 45 + ext/intl/tests/formatter_get_error.phpt | 31 + ext/intl/tests/formatter_get_locale.phpt | 49 + .../tests/formatter_get_set_attribute.phpt | 193 ++ ext/intl/tests/formatter_get_set_pattern.phpt | 52 + ext/intl/tests/formatter_get_set_symbol.phpt | 184 ++ .../formatter_get_set_text_attribute.phpt | 121 ++ ext/intl/tests/formatter_parse.phpt | 42 + ext/intl/tests/formatter_parse_currency.phpt | 37 + ext/intl/tests/grapheme.phpt | 1187 +++++++++++ ext/intl/tests/intl_error_name.phpt | 25 + ext/intl/tests/intl_get_error_code.phpt | 24 + ext/intl/tests/intl_get_error_message.phpt | 21 + ext/intl/tests/intl_is_failure.phpt | 25 + ext/intl/tests/locale_compose_locale.phpt | 197 ++ ext/intl/tests/locale_filter_matches.phpt | 365 ++++ ext/intl/tests/locale_get_all_variants.phpt | 62 + ext/intl/tests/locale_get_default.phpt | 46 + .../tests/locale_get_display_language.phpt | 280 +++ ext/intl/tests/locale_get_display_name.phpt | 340 ++++ ext/intl/tests/locale_get_display_region.phpt | 274 +++ ext/intl/tests/locale_get_display_script.phpt | 274 +++ .../tests/locale_get_display_variant.phpt | 274 +++ ext/intl/tests/locale_get_keywords.phpt | 139 ++ .../tests/locale_get_primary_language.phpt | 121 ++ ext/intl/tests/locale_get_region.phpt | 123 ++ ext/intl/tests/locale_get_script.phpt | 122 ++ ext/intl/tests/locale_lookup.phpt | 99 + ext/intl/tests/locale_parse_locale.phpt | 201 ++ ext/intl/tests/locale_set_default.phpt | 133 ++ ext/intl/tests/msgfmt_fail.phpt | 101 + ext/intl/tests/msgfmt_format.phpt | 70 + ext/intl/tests/msgfmt_get_error.phpt | 29 + ext/intl/tests/msgfmt_get_locale.phpt | 40 + ext/intl/tests/msgfmt_get_set_pattern.phpt | 53 + ext/intl/tests/msgfmt_parse.phpt | 114 ++ ext/intl/tests/normalizer_normalize.phpt | 160 ++ ext/intl/tests/regression_sort_and_cow.phpt | 85 + ext/intl/tests/regression_sort_eq.phpt | 51 + .../tests/regression_sortwsk_and_cow.phpt | 86 + ext/intl/tests/regression_sortwsk_eq.phpt | 51 + ext/intl/tests/ut_common.inc | 385 ++++ 158 files changed, 23151 insertions(+) create mode 100755 ext/intl/CREDITS create mode 100755 ext/intl/TODO create mode 100755 ext/intl/collator/collator.c create mode 100755 ext/intl/collator/collator.h create mode 100755 ext/intl/collator/collator_attr.c create mode 100755 ext/intl/collator/collator_attr.h create mode 100755 ext/intl/collator/collator_class.c create mode 100755 ext/intl/collator/collator_class.h create mode 100755 ext/intl/collator/collator_compare.c create mode 100755 ext/intl/collator/collator_compare.h create mode 100755 ext/intl/collator/collator_convert.c create mode 100755 ext/intl/collator/collator_convert.h create mode 100755 ext/intl/collator/collator_create.c create mode 100755 ext/intl/collator/collator_create.h create mode 100755 ext/intl/collator/collator_error.c create mode 100755 ext/intl/collator/collator_error.h create mode 100755 ext/intl/collator/collator_is_numeric.c create mode 100755 ext/intl/collator/collator_is_numeric.h create mode 100755 ext/intl/collator/collator_locale.c create mode 100755 ext/intl/collator/collator_locale.h create mode 100755 ext/intl/collator/collator_sort.c create mode 100755 ext/intl/collator/collator_sort.h create mode 100755 ext/intl/common/common_error.c create mode 100755 ext/intl/common/common_error.h create mode 100755 ext/intl/config.m4 create mode 100755 ext/intl/config.w32 create mode 100755 ext/intl/doc/Tutorial.txt create mode 100755 ext/intl/doc/collator_api.php create mode 100755 ext/intl/doc/common_api.php create mode 100755 ext/intl/doc/datefmt_api.php create mode 100755 ext/intl/doc/formatter_api.php create mode 100755 ext/intl/doc/grapheme_api.php create mode 100755 ext/intl/doc/locale_api.php create mode 100755 ext/intl/doc/msgfmt_api.php create mode 100755 ext/intl/doc/normalizer_api.php create mode 100755 ext/intl/formatter/formatter.c create mode 100755 ext/intl/formatter/formatter.h create mode 100755 ext/intl/formatter/formatter_attr.c create mode 100755 ext/intl/formatter/formatter_attr.h create mode 100755 ext/intl/formatter/formatter_class.c create mode 100755 ext/intl/formatter/formatter_class.h create mode 100755 ext/intl/formatter/formatter_data.c create mode 100755 ext/intl/formatter/formatter_data.h create mode 100755 ext/intl/formatter/formatter_format.c create mode 100755 ext/intl/formatter/formatter_format.h create mode 100755 ext/intl/formatter/formatter_main.c create mode 100755 ext/intl/formatter/formatter_main.h create mode 100755 ext/intl/formatter/formatter_parse.c create mode 100755 ext/intl/formatter/formatter_parse.h create mode 100755 ext/intl/grapheme/grapheme.h create mode 100755 ext/intl/grapheme/grapheme_string.c create mode 100755 ext/intl/grapheme/grapheme_util.c create mode 100755 ext/intl/grapheme/grapheme_util.h create mode 100755 ext/intl/intl_common.h create mode 100755 ext/intl/intl_convert.c create mode 100755 ext/intl/intl_convert.h create mode 100755 ext/intl/intl_data.h create mode 100755 ext/intl/intl_error.c create mode 100755 ext/intl/intl_error.h create mode 100755 ext/intl/locale/locale.c create mode 100755 ext/intl/locale/locale.h create mode 100755 ext/intl/locale/locale_class.c create mode 100755 ext/intl/locale/locale_class.h create mode 100755 ext/intl/locale/locale_methods.c create mode 100755 ext/intl/locale/locale_methods.h create mode 100755 ext/intl/msgformat/msgformat.c create mode 100755 ext/intl/msgformat/msgformat.h create mode 100755 ext/intl/msgformat/msgformat_attr.c create mode 100755 ext/intl/msgformat/msgformat_attr.h create mode 100755 ext/intl/msgformat/msgformat_class.c create mode 100755 ext/intl/msgformat/msgformat_class.h create mode 100755 ext/intl/msgformat/msgformat_data.c create mode 100755 ext/intl/msgformat/msgformat_data.h create mode 100755 ext/intl/msgformat/msgformat_format.c create mode 100755 ext/intl/msgformat/msgformat_format.h create mode 100755 ext/intl/msgformat/msgformat_helpers.cpp create mode 100755 ext/intl/msgformat/msgformat_helpers.h create mode 100755 ext/intl/msgformat/msgformat_parse.c create mode 100755 ext/intl/msgformat/msgformat_parse.h create mode 100755 ext/intl/normalizer/normalizer.c create mode 100755 ext/intl/normalizer/normalizer.h create mode 100755 ext/intl/normalizer/normalizer_class.c create mode 100755 ext/intl/normalizer/normalizer_class.h create mode 100755 ext/intl/normalizer/normalizer_normalize.c create mode 100755 ext/intl/normalizer/normalizer_normalize.h create mode 100755 ext/intl/php_intl.c create mode 100755 ext/intl/php_intl.h create mode 100755 ext/intl/tests/bug12887.phpt create mode 100755 ext/intl/tests/collation_customization.phpt create mode 100755 ext/intl/tests/collator_asort.phpt create mode 100755 ext/intl/tests/collator_compare.phpt create mode 100755 ext/intl/tests/collator_create.phpt create mode 100755 ext/intl/tests/collator_get_error_code.phpt create mode 100755 ext/intl/tests/collator_get_error_message.phpt create mode 100755 ext/intl/tests/collator_get_locale.phpt create mode 100755 ext/intl/tests/collator_get_set_attribute.phpt create mode 100755 ext/intl/tests/collator_get_set_strength.phpt create mode 100755 ext/intl/tests/collator_sort.phpt create mode 100755 ext/intl/tests/collator_sort_with_sort_keys.phpt create mode 100755 ext/intl/tests/dateformat_format.phpt create mode 100755 ext/intl/tests/dateformat_format_parse.phpt create mode 100755 ext/intl/tests/dateformat_get_datetype.phpt create mode 100755 ext/intl/tests/dateformat_get_locale.phpt create mode 100755 ext/intl/tests/dateformat_get_set_calendar.phpt create mode 100755 ext/intl/tests/dateformat_get_set_pattern.phpt create mode 100755 ext/intl/tests/dateformat_get_timetype.phpt create mode 100755 ext/intl/tests/dateformat_get_timezone_id.phpt create mode 100755 ext/intl/tests/dateformat_is_set_lenient.phpt create mode 100755 ext/intl/tests/dateformat_localtime.phpt create mode 100755 ext/intl/tests/dateformat_parse.phpt create mode 100755 ext/intl/tests/dateformat_parse_localtime_parsepos.phpt create mode 100755 ext/intl/tests/dateformat_parse_timestamp_parsepos.phpt create mode 100755 ext/intl/tests/dateformat_set_timezone_id.phpt create mode 100755 ext/intl/tests/formatter_fail.phpt create mode 100755 ext/intl/tests/formatter_format.phpt create mode 100755 ext/intl/tests/formatter_format_conv.phpt create mode 100755 ext/intl/tests/formatter_format_currency.phpt create mode 100755 ext/intl/tests/formatter_get_error.phpt create mode 100755 ext/intl/tests/formatter_get_locale.phpt create mode 100755 ext/intl/tests/formatter_get_set_attribute.phpt create mode 100755 ext/intl/tests/formatter_get_set_pattern.phpt create mode 100755 ext/intl/tests/formatter_get_set_symbol.phpt create mode 100755 ext/intl/tests/formatter_get_set_text_attribute.phpt create mode 100755 ext/intl/tests/formatter_parse.phpt create mode 100755 ext/intl/tests/formatter_parse_currency.phpt create mode 100755 ext/intl/tests/grapheme.phpt create mode 100755 ext/intl/tests/intl_error_name.phpt create mode 100755 ext/intl/tests/intl_get_error_code.phpt create mode 100755 ext/intl/tests/intl_get_error_message.phpt create mode 100755 ext/intl/tests/intl_is_failure.phpt create mode 100755 ext/intl/tests/locale_compose_locale.phpt create mode 100755 ext/intl/tests/locale_filter_matches.phpt create mode 100755 ext/intl/tests/locale_get_all_variants.phpt create mode 100755 ext/intl/tests/locale_get_default.phpt create mode 100755 ext/intl/tests/locale_get_display_language.phpt create mode 100755 ext/intl/tests/locale_get_display_name.phpt create mode 100755 ext/intl/tests/locale_get_display_region.phpt create mode 100755 ext/intl/tests/locale_get_display_script.phpt create mode 100755 ext/intl/tests/locale_get_display_variant.phpt create mode 100755 ext/intl/tests/locale_get_keywords.phpt create mode 100755 ext/intl/tests/locale_get_primary_language.phpt create mode 100755 ext/intl/tests/locale_get_region.phpt create mode 100755 ext/intl/tests/locale_get_script.phpt create mode 100755 ext/intl/tests/locale_lookup.phpt create mode 100755 ext/intl/tests/locale_parse_locale.phpt create mode 100755 ext/intl/tests/locale_set_default.phpt create mode 100755 ext/intl/tests/msgfmt_fail.phpt create mode 100755 ext/intl/tests/msgfmt_format.phpt create mode 100755 ext/intl/tests/msgfmt_get_error.phpt create mode 100755 ext/intl/tests/msgfmt_get_locale.phpt create mode 100755 ext/intl/tests/msgfmt_get_set_pattern.phpt create mode 100755 ext/intl/tests/msgfmt_parse.phpt create mode 100755 ext/intl/tests/normalizer_normalize.phpt create mode 100755 ext/intl/tests/regression_sort_and_cow.phpt create mode 100755 ext/intl/tests/regression_sort_eq.phpt create mode 100755 ext/intl/tests/regression_sortwsk_and_cow.phpt create mode 100755 ext/intl/tests/regression_sortwsk_eq.phpt create mode 100755 ext/intl/tests/ut_common.inc diff --git a/ext/intl/CREDITS b/ext/intl/CREDITS new file mode 100755 index 0000000000..3c54042507 --- /dev/null +++ b/ext/intl/CREDITS @@ -0,0 +1,2 @@ +Internationalization +Ed Batutis, Vladimir Iordanov, Dmitry Lakhtyuk, Stanislav Malyshev, Vadim Savchuk, Kirti Velankar diff --git a/ext/intl/TODO b/ext/intl/TODO new file mode 100755 index 0000000000..a388c954e7 --- /dev/null +++ b/ext/intl/TODO @@ -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 + diff --git a/ext/intl/collator/collator.c b/ext/intl/collator/collator.c new file mode 100755 index 0000000000..4c1bbc7797 --- /dev/null +++ b/ext/intl/collator/collator.c @@ -0,0 +1,96 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "collator_class.h" +#include "collator.h" + +#include +#include +#include + +/* {{{ collator_register_constants + * Register constants common for the both (OO and procedural) + * APIs. + */ +void collator_register_constants( INIT_FUNC_ARGS ) +{ + if( !Collator_ce_ptr ) + { + zend_error( E_ERROR, "Collator class not defined" ); + return; + } + + #define COLLATOR_EXPOSE_CONST(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS) + #define COLLATOR_EXPOSE_CLASS_CONST(x) zend_declare_class_constant_long( Collator_ce_ptr, ZEND_STRS( #x ) - 1, UCOL_##x TSRMLS_CC ); + #define COLLATOR_EXPOSE_CUSTOM_CLASS_CONST(name, value) zend_declare_class_constant_long( Collator_ce_ptr, ZEND_STRS( name ) - 1, value TSRMLS_CC ); + + // UColAttributeValue constants + COLLATOR_EXPOSE_CUSTOM_CLASS_CONST( "DEFAULT_VALUE", UCOL_DEFAULT ); + + COLLATOR_EXPOSE_CLASS_CONST( PRIMARY ); + COLLATOR_EXPOSE_CLASS_CONST( SECONDARY ); + COLLATOR_EXPOSE_CLASS_CONST( TERTIARY ); + COLLATOR_EXPOSE_CLASS_CONST( DEFAULT_STRENGTH ); + COLLATOR_EXPOSE_CLASS_CONST( QUATERNARY ); + COLLATOR_EXPOSE_CLASS_CONST( IDENTICAL ); + + COLLATOR_EXPOSE_CLASS_CONST( OFF ); + COLLATOR_EXPOSE_CLASS_CONST( ON ); + + COLLATOR_EXPOSE_CLASS_CONST( SHIFTED ); + COLLATOR_EXPOSE_CLASS_CONST( NON_IGNORABLE ); + + COLLATOR_EXPOSE_CLASS_CONST( LOWER_FIRST ); + COLLATOR_EXPOSE_CLASS_CONST( UPPER_FIRST ); + + // UColAttribute constants + COLLATOR_EXPOSE_CLASS_CONST( FRENCH_COLLATION ); + COLLATOR_EXPOSE_CLASS_CONST( ALTERNATE_HANDLING ); + COLLATOR_EXPOSE_CLASS_CONST( CASE_FIRST ); + COLLATOR_EXPOSE_CLASS_CONST( CASE_LEVEL ); + COLLATOR_EXPOSE_CLASS_CONST( NORMALIZATION_MODE ); + COLLATOR_EXPOSE_CLASS_CONST( STRENGTH ); + COLLATOR_EXPOSE_CLASS_CONST( HIRAGANA_QUATERNARY_MODE ); + COLLATOR_EXPOSE_CLASS_CONST( NUMERIC_COLLATION ); + + // ULocDataLocaleType constants + COLLATOR_EXPOSE_CONST( ULOC_ACTUAL_LOCALE ); + COLLATOR_EXPOSE_CONST( ULOC_VALID_LOCALE ); + + // sort flags + COLLATOR_EXPOSE_CUSTOM_CLASS_CONST( "SORT_REGULAR", COLLATOR_SORT_REGULAR ); + COLLATOR_EXPOSE_CUSTOM_CLASS_CONST( "SORT_STRING", COLLATOR_SORT_STRING ); + COLLATOR_EXPOSE_CUSTOM_CLASS_CONST( "SORT_NUMERIC", COLLATOR_SORT_NUMERIC ); + + #undef COLLATOR_EXPOSE_CUSTOM_CLASS_CONST + #undef COLLATOR_EXPOSE_CLASS_CONST + #undef COLLATOR_EXPOSE_CONST +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/collator/collator.h b/ext/intl/collator/collator.h new file mode 100755 index 0000000000..96e7aa097b --- /dev/null +++ b/ext/intl/collator/collator.h @@ -0,0 +1,29 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifndef COLLATOR_COLLATOR_H +#define CCOLLATOR_COLLATOR_H + +#include + +#define COLLATOR_SORT_REGULAR 0 +#define COLLATOR_SORT_STRING 1 +#define COLLATOR_SORT_NUMERIC 2 + +void collator_register_constants( INIT_FUNC_ARGS ); + +#endif // COLLATOR_COLLATOR_H diff --git a/ext/intl/collator/collator_attr.c b/ext/intl/collator/collator_attr.c new file mode 100755 index 0000000000..b4fe0a4e14 --- /dev/null +++ b/ext/intl/collator/collator_attr.c @@ -0,0 +1,157 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#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 + +/* {{{ proto int Collator::getAttribute( int $attr ) + * Get collation attribute value. }}} */ +/* {{{ proto int collator_get_attribute( Collator $coll, int $attr ) + * Get collation attribute value. + */ +PHP_FUNCTION( collator_get_attribute ) +{ + long attribute, value; + + COLLATOR_METHOD_INIT_VARS + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", + &object, Collator_ce_ptr, &attribute ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "collator_get_attribute: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + // Fetch the object. + COLLATOR_METHOD_FETCH_OBJECT; + + value = ucol_getAttribute( co->ucoll, attribute, COLLATOR_ERROR_CODE_P( co ) ); + COLLATOR_CHECK_STATUS( co, "Error getting attribute value" ); + + RETURN_LONG( value ); +} +/* }}} */ + +/* {{{ proto bool Collator::getAttribute( int $attr ) + * Get collation attribute value. }}} */ +/* {{{ proto bool collator_set_attribute( Collator $coll, int $attr, int $val ) + * Set collation attribute. + */ +PHP_FUNCTION( collator_set_attribute ) +{ + long attribute, value; + COLLATOR_METHOD_INIT_VARS + + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll", + &object, Collator_ce_ptr, &attribute, &value ) == FAILURE) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "collator_set_attribute: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + // Fetch the object. + COLLATOR_METHOD_FETCH_OBJECT; + + // Set new value for the given attribute. + ucol_setAttribute( co->ucoll, attribute, value, COLLATOR_ERROR_CODE_P( co ) ); + COLLATOR_CHECK_STATUS( co, "Error setting attribute value" ); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto int Collator::getStrength() + * Returns the current collation strength. }}} */ +/* {{{ proto int collator_get_strength(Collator coll) + * Returns the current collation strength. + */ +PHP_FUNCTION( collator_get_strength ) +{ + COLLATOR_METHOD_INIT_VARS + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, Collator_ce_ptr ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "collator_get_strength: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + // Fetch the object. + COLLATOR_METHOD_FETCH_OBJECT; + + // Get current strength and return it. + RETURN_LONG( ucol_getStrength( co->ucoll ) ); +} +/* }}} */ + +/* {{{ proto bool Collator::setStrength(int strength) + * Set the collation strength. }}} */ +/* {{{ proto bool collator_set_strength(Collator coll, int strength) + * Set the collation strength. + */ +PHP_FUNCTION( collator_set_strength ) +{ + long strength; + + COLLATOR_METHOD_INIT_VARS + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", + &object, Collator_ce_ptr, &strength ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "collator_set_strength: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + // Fetch the object. + COLLATOR_METHOD_FETCH_OBJECT; + + // Set given strength. + ucol_setStrength( co->ucoll, strength ); + + RETURN_TRUE; +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/collator/collator_attr.h b/ext/intl/collator/collator_attr.h new file mode 100755 index 0000000000..85636cc486 --- /dev/null +++ b/ext/intl/collator/collator_attr.h @@ -0,0 +1,28 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifndef COLLATOR_ATTR_H +#define CCOLLATOR_ATTR_H + +#include + +PHP_FUNCTION( collator_get_attribute ); +PHP_FUNCTION( collator_set_attribute ); +PHP_FUNCTION( collator_get_strength ); +PHP_FUNCTION( collator_set_strength ); + +#endif // COLLATOR_ATTR_H diff --git a/ext/intl/collator/collator_class.c b/ext/intl/collator/collator_class.c new file mode 100755 index 0000000000..1d75f71f64 --- /dev/null +++ b/ext/intl/collator/collator_class.c @@ -0,0 +1,197 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#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 + +zend_class_entry *Collator_ce_ptr = NULL; + +///////////////////////////////////////////////////////////////////////////// +// Auxiliary functions needed by objects of 'Collator' class +///////////////////////////////////////////////////////////////////////////// + +/* {{{ Collator_objects_dtor */ +static void Collator_objects_dtor( + void *object, + zend_object_handle handle TSRMLS_DC ) +{ + zend_objects_destroy_object( object, handle TSRMLS_CC ); +} +/* }}} */ + +/* {{{ Collator_objects_free */ +void Collator_objects_free( zend_object *object TSRMLS_DC ) +{ + Collator_object* co = (Collator_object*)object; + + zend_object_std_dtor( &co->zo TSRMLS_CC ); + + collator_object_destroy( co TSRMLS_CC ); + + efree( co ); +} +/* }}} */ + +/* {{{ Collator_object_create */ +zend_object_value Collator_object_create( + zend_class_entry *ce TSRMLS_DC ) +{ + zend_object_value retval; + Collator_object* intern; + + intern = ecalloc( 1, sizeof(Collator_object) ); + intl_error_init( COLLATOR_ERROR_P( intern ) TSRMLS_CC ); + zend_object_std_init( &intern->zo, ce TSRMLS_CC ); + + retval.handle = zend_objects_store_put( + intern, + Collator_objects_dtor, + (zend_objects_free_object_storage_t)Collator_objects_free, + NULL TSRMLS_CC ); + + retval.handlers = zend_get_std_object_handlers(); + + return retval; +} +/* }}} */ + +///////////////////////////////////////////////////////////////////////////// +// 'Collator' class registration structures & functions +///////////////////////////////////////////////////////////////////////////// + +/* {{{ Collator methods arguments info */ +// NOTE: modifying 'collator_XX_args' do not forget to +// modify approptiate 'collator_XX_args' for +// the procedural API. + +static +ZEND_BEGIN_ARG_INFO_EX( collator_0_args, 0, 0, 0 ) +ZEND_END_ARG_INFO() + +static +ZEND_BEGIN_ARG_INFO_EX( collator_1_arg, 0, 0, 1 ) + ZEND_ARG_INFO( 0, arg1 ) +ZEND_END_ARG_INFO() + +static +ZEND_BEGIN_ARG_INFO_EX( collator_2_args, 0, 0, 2 ) + ZEND_ARG_INFO( 0, arg1 ) + ZEND_ARG_INFO( 0, arg2 ) +ZEND_END_ARG_INFO() + +static +ZEND_BEGIN_ARG_INFO_EX( collator_sort_args, 0, 0, 1 ) + ZEND_ARG_ARRAY_INFO( 1, arr, 0 ) + ZEND_ARG_INFO( 0, flags ) +ZEND_END_ARG_INFO() + +/* }}} */ + +/* {{{ Collator_class_functions + * Every 'Collator' class method has an entry in this table + */ + +function_entry Collator_class_functions[] = { + PHP_ME( Collator, __construct, collator_1_arg, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR ) + ZEND_FENTRY( create, ZEND_FN( collator_create ), collator_1_arg, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC ) + PHP_NAMED_FE( compare, ZEND_FN( collator_compare ), collator_2_args ) + PHP_NAMED_FE( sort, ZEND_FN( collator_sort ), collator_sort_args ) + PHP_NAMED_FE( sortWithSortKeys, ZEND_FN( collator_sort_with_sort_keys ), collator_sort_args ) + PHP_NAMED_FE( asort, ZEND_FN( collator_asort ), collator_sort_args ) + PHP_NAMED_FE( getAttribute, ZEND_FN( collator_get_attribute ), collator_1_arg ) + PHP_NAMED_FE( setAttribute, ZEND_FN( collator_set_attribute ), collator_2_args ) + PHP_NAMED_FE( getStrength, ZEND_FN( collator_get_strength ), collator_0_args ) + PHP_NAMED_FE( setStrength, ZEND_FN( collator_set_strength ), collator_1_arg ) + PHP_NAMED_FE( getLocale, ZEND_FN( collator_get_locale ), collator_1_arg ) + PHP_NAMED_FE( getErrorCode, ZEND_FN( collator_get_error_code ), collator_0_args ) + PHP_NAMED_FE( getErrorMessage, ZEND_FN( collator_get_error_message ), collator_0_args ) + { NULL, NULL, NULL } +}; +/* }}} */ + +/* {{{ collator_register_Collator_class + * Initialize 'Collator' class + */ +void collator_register_Collator_class( TSRMLS_D ) +{ + zend_class_entry ce; + + // Create and register 'Collator' class. + INIT_CLASS_ENTRY( ce, "Collator", Collator_class_functions ); + ce.create_object = Collator_object_create; + Collator_ce_ptr = zend_register_internal_class( &ce TSRMLS_CC ); + + // Declare 'Collator' class properties. + if( !Collator_ce_ptr ) + { + zend_error( E_ERROR, + "Collator: attempt to create properties " + "on a non-registered class." ); + return; + } +} +/* }}} */ + +/* {{{ void collator_object_init( Collator_object* co ) + * Initialize internals of Collator_object. + * Must be called before any other call to 'collator_object_...' functions. + */ +void collator_object_init( Collator_object* co TSRMLS_DC ) +{ + if( !co ) + return; + + intl_error_init( COLLATOR_ERROR_P( co ) TSRMLS_CC ); +} +/* }}} */ + +/* {{{ void collator_object_destroy( Collator_object* co ) + * Clean up mem allocted by internals of Collator_object + */ +void collator_object_destroy( Collator_object* co TSRMLS_DC ) +{ + if( !co ) + return; + + if( co->ucoll ) + { + ucol_close( co->ucoll ); + co->ucoll = NULL; + } + + intl_error_reset( COLLATOR_ERROR_P( co ) TSRMLS_CC ); +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/collator/collator_class.h b/ext/intl/collator/collator_class.h new file mode 100755 index 0000000000..8d4c9d97f4 --- /dev/null +++ b/ext/intl/collator/collator_class.h @@ -0,0 +1,71 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifndef COLLATOR_CLASS_H +#define COLLATOR_CLASS_H + +#include + +#include "intl_common.h" +#include "intl_error.h" + +#include + +typedef struct { + zend_object zo; + + // ICU collator + UCollator* ucoll; + + // error handling + intl_error err; + +} Collator_object; + +#define COLLATOR_ERROR(co) (co)->err +#define COLLATOR_ERROR_P(co) &(COLLATOR_ERROR(co)) + +#define COLLATOR_ERROR_CODE(co) INTL_ERROR_CODE(COLLATOR_ERROR(co)) +#define COLLATOR_ERROR_CODE_P(co) &(INTL_ERROR_CODE(COLLATOR_ERROR(co))) + +void collator_register_Collator_class( TSRMLS_D ); +void collator_object_init( Collator_object* co TSRMLS_DC ); +void collator_object_destroy( Collator_object* co TSRMLS_DC ); + +extern zend_class_entry *Collator_ce_ptr; + +/* Auxiliary macros */ + +#define COLLATOR_METHOD_INIT_VARS \ + zval* object = NULL; \ + Collator_object* co = NULL; \ + intl_error_reset( NULL TSRMLS_CC ); \ + +#define COLLATOR_METHOD_FETCH_OBJECT \ + co = (Collator_object *) zend_object_store_get_object( object TSRMLS_CC ); \ + intl_error_reset( COLLATOR_ERROR_P( co ) TSRMLS_CC ); \ + +// Macro to check return value of a ucol_* function call. +#define COLLATOR_CHECK_STATUS( co, msg ) \ + intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) TSRMLS_CC ); \ + if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) \ + { \ + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), msg, 0 TSRMLS_CC ); \ + RETURN_FALSE; \ + } \ + +#endif // #ifndef COLLATOR_CLASS_H diff --git a/ext/intl/collator/collator_compare.c b/ext/intl/collator/collator_compare.c new file mode 100755 index 0000000000..e6029e7920 --- /dev/null +++ b/ext/intl/collator/collator_compare.c @@ -0,0 +1,119 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php_intl.h" +#include "collator_class.h" +#include "collator_compare.h" +#include "intl_convert.h" + +/* {{{ proto int Collator::compare( string $str1, string $str2 ) + * Compare two strings. }}} */ +/* {{{ proto int collator_compare( Collator $coll, string $str1, string $str2 ) + * Compare two strings. + */ +PHP_FUNCTION( collator_compare ) +{ + char* str1 = NULL; + char* str2 = NULL; + int str1_len = 0; + int str2_len = 0; + + UChar* ustr1 = NULL; + UChar* ustr2 = NULL; + int ustr1_len = 0; + int ustr2_len = 0; + + UCollationResult result; + + COLLATOR_METHOD_INIT_VARS + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oss", + &object, Collator_ce_ptr, &str1, &str1_len, &str2, &str2_len ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "collator_compare: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + // Fetch the object. + COLLATOR_METHOD_FETCH_OBJECT; + + + /* + * Compare given strings (converting them to UTF-16 first). + */ + + // First convert the strings to UTF-16. + intl_convert_utf8_to_utf16( + &ustr1, &ustr1_len, str1, str1_len, COLLATOR_ERROR_CODE_P( co ) ); + if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) + { + // Set global error code. + intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) TSRMLS_CC ); + + // Set error messages. + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), + "Error converting first argument to UTF-16", 0 TSRMLS_CC ); + efree( ustr1 ); + RETURN_FALSE; + } + + intl_convert_utf8_to_utf16( + &ustr2, &ustr2_len, str2, str2_len, COLLATOR_ERROR_CODE_P( co ) ); + if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) + { + // Set global error code. + intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) TSRMLS_CC ); + + // Set error messages. + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), + "Error converting second argument to UTF-16", 0 TSRMLS_CC ); + efree( ustr1 ); + efree( ustr2 ); + RETURN_FALSE; + } + + // Then compare them. + result = ucol_strcoll( + co->ucoll, + ustr1, ustr1_len, + ustr2, ustr2_len ); + + if( ustr1 ) + efree( ustr1 ); + if( ustr2 ) + efree( ustr2 ); + + // Return result of the comparison. + RETURN_LONG( result ); +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/collator/collator_compare.h b/ext/intl/collator/collator_compare.h new file mode 100755 index 0000000000..4e38b79309 --- /dev/null +++ b/ext/intl/collator/collator_compare.h @@ -0,0 +1,25 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifndef COLLATOR_COMPARE_H +#define COLLATOR_COMPARE_H + +#include + +PHP_FUNCTION( collator_compare ); + +#endif // COLLATOR_COMPARE_H diff --git a/ext/intl/collator/collator_convert.c b/ext/intl/collator/collator_convert.c new file mode 100755 index 0000000000..7bb48ebb4b --- /dev/null +++ b/ext/intl/collator/collator_convert.c @@ -0,0 +1,482 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#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 +#include + +#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION <= 1) +#define CAST_OBJECT_SHOULD_FREE ,0 +#else +#define CAST_OBJECT_SHOULD_FREE +#endif + +#define COLLATOR_CONVERT_RETURN_FAILED(retval) { \ + zval_add_ref( &retval ); \ + return retval; \ + } + +/* {{{ collator_convert_hash_item_from_utf8_to_utf16 */ +static void collator_convert_hash_item_from_utf8_to_utf16( + HashTable* hash, int hashKeyType, char* hashKey, ulong hashIndex, + UErrorCode* status ) +{ + const char* old_val; + int old_val_len; + UChar* new_val = NULL; + int new_val_len = 0; + zval** hashData = NULL; + zval* znew_val = NULL; + + // Get current hash item. + zend_hash_get_current_data( hash, (void**) &hashData ); + + // Process string values only. + if( Z_TYPE_P( *hashData ) != IS_STRING ) + return; + + old_val = Z_STRVAL_P( *hashData ); + old_val_len = Z_STRLEN_P( *hashData ); + + // Convert it from UTF-8 to UTF-16LE and save the result to new_val[_len]. + intl_convert_utf8_to_utf16( &new_val, &new_val_len, old_val, old_val_len, status ); + if( U_FAILURE( *status ) ) + return; + + // Update current hash item with the converted value. + MAKE_STD_ZVAL( znew_val ); + ZVAL_STRINGL( znew_val, (char*)new_val, UBYTES(new_val_len), FALSE ); + + if( hashKeyType == HASH_KEY_IS_STRING ) + { + zend_hash_update( hash, hashKey, strlen( hashKey ) + 1, + (void*) &znew_val, sizeof(zval*), NULL ); + } + else // hashKeyType == HASH_KEY_IS_LONG + { + zend_hash_index_update( hash, hashIndex, + (void*) &znew_val, sizeof(zval*), NULL ); + } +} +/* }}} */ + +/* {{{ collator_convert_hash_item_from_utf16_to_utf8 */ +static void collator_convert_hash_item_from_utf16_to_utf8( + HashTable* hash, int hashKeyType, char* hashKey, ulong hashIndex, + UErrorCode* status ) +{ + const char* old_val; + int old_val_len; + char* new_val = NULL; + int new_val_len = 0; + zval** hashData = NULL; + zval* znew_val = NULL; + + // Get current hash item. + zend_hash_get_current_data( hash, (void**) &hashData ); + + // Process string values only. + if( Z_TYPE_P( *hashData ) != IS_STRING ) + return; + + old_val = Z_STRVAL_P( *hashData ); + old_val_len = Z_STRLEN_P( *hashData ); + + // Convert it from UTF-16LE to UTF-8 and save the result to new_val[_len]. + intl_convert_utf16_to_utf8( &new_val, &new_val_len, + (UChar*)old_val, UCHARS(old_val_len), status ); + if( U_FAILURE( *status ) ) + return; + + // Update current hash item with the converted value. + MAKE_STD_ZVAL( znew_val ); + ZVAL_STRINGL( znew_val, (char*)new_val, new_val_len, FALSE ); + + if( hashKeyType == HASH_KEY_IS_STRING ) + { + zend_hash_update( hash, hashKey, strlen( hashKey ) + 1, + (void*) &znew_val, sizeof(zval*), NULL ); + } + else // hashKeyType == HASH_KEY_IS_LONG + { + zend_hash_index_update( hash, hashIndex, + (void*) &znew_val, sizeof(zval*), NULL ); + } +} +/* }}} */ + +/* {{{ collator_convert_hash_from_utf8_to_utf16 + * Convert values of the given hash from UTF-8 encoding to UTF-16LE. + */ +void collator_convert_hash_from_utf8_to_utf16( HashTable* hash, UErrorCode* status ) +{ + ulong hashIndex = 0; + char* hashKey = NULL; + int hashKeyType = 0; + + zend_hash_internal_pointer_reset( hash ); + while( ( hashKeyType = zend_hash_get_current_key( hash, &hashKey, &hashIndex, 0 ) ) + != HASH_KEY_NON_EXISTANT ) + { + // Convert current hash item from UTF-8 to UTF-16LE. + collator_convert_hash_item_from_utf8_to_utf16( + hash, hashKeyType, hashKey, hashIndex, status ); + if( U_FAILURE( *status ) ) + return; + + // Proceed to the next item. + zend_hash_move_forward( hash ); + } +} +/* }}} */ + +/* {{{ collator_convert_hash_from_utf16_to_utf8 + * Convert values of the given hash from UTF-16LE encoding to UTF-8. + */ +void collator_convert_hash_from_utf16_to_utf8( HashTable* hash, UErrorCode* status ) +{ + ulong hashIndex = 0; + char* hashKey = NULL; + int hashKeyType = 0; + + zend_hash_internal_pointer_reset( hash ); + while( ( hashKeyType = zend_hash_get_current_key( hash, &hashKey, &hashIndex, 0 ) ) + != HASH_KEY_NON_EXISTANT ) + { + // Convert current hash item from UTF-16LE to UTF-8. + collator_convert_hash_item_from_utf16_to_utf8( + hash, hashKeyType, hashKey, hashIndex, status ); + if( U_FAILURE( *status ) ) + return; + + // Proceed to the next item. + zend_hash_move_forward( hash ); + } +} +/* }}} */ + +/* {{{ collator_convert_zstr_utf16_to_utf8 + * + * Convert string from utf16 to utf8. + * + * @param zval* utf16_zval String to convert. + * + * @return zval* Converted string. + */ +zval* collator_convert_zstr_utf16_to_utf8( zval* utf16_zval ) +{ + zval* utf8_zval = NULL; + char* str = NULL; + int str_len = 0; + UErrorCode status = U_ZERO_ERROR; + + // Convert to utf8 then. + intl_convert_utf16_to_utf8( &str, &str_len, + (UChar*) Z_STRVAL_P(utf16_zval), UCHARS( Z_STRLEN_P(utf16_zval) ), &status ); + if( U_FAILURE( status ) ) + php_error( E_WARNING, "Error converting utf16 to utf8 in collator_convert_zval_utf16_to_utf8()" ); + + ALLOC_INIT_ZVAL( utf8_zval ); + ZVAL_STRINGL( utf8_zval, str, str_len, FALSE ); + + return utf8_zval; +} +/* }}} */ + +/* {{{ collator_convert_zstr_utf8_to_utf16 + * + * Convert string from utf8 to utf16. + * + * @param zval* utf8_zval String to convert. + * + * @return zval* Converted string. + */ +zval* collator_convert_zstr_utf8_to_utf16( zval* utf8_zval ) +{ + zval* zstr = NULL; + UChar* ustr = NULL; + int ustr_len = 0; + UErrorCode status = U_ZERO_ERROR; + + // Convert the string to UTF-16. + intl_convert_utf8_to_utf16( + &ustr, &ustr_len, + Z_STRVAL_P( utf8_zval ), Z_STRLEN_P( utf8_zval ), + &status ); + if( U_FAILURE( status ) ) + php_error( E_WARNING, "Error casting object to string in collator_convert_zstr_utf8_to_utf16()" ); + + // Set string. + ALLOC_INIT_ZVAL( zstr ); + ZVAL_STRINGL( zstr, (char*)ustr, UBYTES(ustr_len), FALSE ); + + return zstr; +} +/* }}} */ + +/* {{{ collator_convert_object_to_string + * Convert object to UTF16-encoded string. + */ +zval* collator_convert_object_to_string( zval* obj TSRMLS_DC ) +{ + zval* zstr = NULL; + UErrorCode status = U_ZERO_ERROR; + UChar* ustr = NULL; + int ustr_len = 0; + + // Bail out if it's not an object. + if( Z_TYPE_P( obj ) != IS_OBJECT ) + { + COLLATOR_CONVERT_RETURN_FAILED( obj ); + } + + // Try object's handlers. + if( Z_OBJ_HT_P(obj)->get ) + { + zstr = Z_OBJ_HT_P(obj)->get( obj TSRMLS_CC ); + + switch( Z_TYPE_P( zstr ) ) + { + case IS_OBJECT: + { + // Bail out. + zval_ptr_dtor( &zstr ); + COLLATOR_CONVERT_RETURN_FAILED( obj ); + } break; + + case IS_STRING: + break; + + default: + { + convert_to_string( zstr ); + } break; + } + } + else if( Z_OBJ_HT_P(obj)->cast_object ) + { + ALLOC_INIT_ZVAL( zstr ); + + if( Z_OBJ_HT_P(obj)->cast_object( obj, zstr, IS_STRING CAST_OBJECT_SHOULD_FREE TSRMLS_CC ) == FAILURE ) + { + // cast_object failed => bail out. + zval_ptr_dtor( &zstr ); + COLLATOR_CONVERT_RETURN_FAILED( obj ); + } + } + + // Object wasn't successfuly converted => bail out. + if( zstr == NULL ) + { + COLLATOR_CONVERT_RETURN_FAILED( obj ); + } + + // Convert the string to UTF-16. + intl_convert_utf8_to_utf16( + &ustr, &ustr_len, + Z_STRVAL_P( zstr ), Z_STRLEN_P( zstr ), + &status ); + if( U_FAILURE( status ) ) + php_error( E_WARNING, "Error casting object to string in collator_convert_object_to_string()" ); + + // Cleanup zstr to hold utf16 string. + zval_dtor( zstr ); + + // Set string. + ZVAL_STRINGL( zstr, (char*)ustr, UBYTES(ustr_len), FALSE ); + + // Don't free ustr cause it's set in zstr without copy. + // efree( ustr ); + + return zstr; +} +/* }}} */ + +/* {{{ collator_convert_string_to_number + * + * Convert string to number. + * + * @param zval* str String to convert. + * + * @return zval* Number. If str is not numeric string return number zero. + */ +zval* collator_convert_string_to_number( zval* str ) +{ + zval* num = collator_convert_string_to_number_if_possible( str ); + if( num == str ) + { + // String wasn't converted => return zero. + zval_ptr_dtor( &num ); + + ALLOC_INIT_ZVAL( num ); + ZVAL_LONG( num, 0 ); + } + + return num; +} +/* }}} */ + +/* {{{ collator_convert_string_to_double + * + * Convert string to double. + * + * @param zval* str String to convert. + * + * @return zval* Number. If str is not numeric string return number zero. + */ +zval* collator_convert_string_to_double( zval* str ) +{ + zval* num = collator_convert_string_to_number( str ); + if( Z_TYPE_P(num) == IS_LONG ) + { + ZVAL_DOUBLE( num, Z_LVAL_P( num ) ); + } + + return num; +} +/* }}} */ + +/* {{{ collator_convert_string_to_number_if_possible + * + * Convert string to numer. + * + * @param zval* str String to convert. + * + * @return zval* Number if str is numeric string. Otherwise + * original str param. + */ +zval* collator_convert_string_to_number_if_possible( zval* str ) +{ + zval* num = NULL; + int is_numeric = 0; + long lval = 0; + double dval = 0; + + if( Z_TYPE_P( str ) != IS_STRING ) + { + COLLATOR_CONVERT_RETURN_FAILED( str ); + } + + if( ( is_numeric = collator_is_numeric( (UChar*) Z_STRVAL_P(str), UCHARS( Z_STRLEN_P(str) ), &lval, &dval, 1 ) ) ) + { + ALLOC_INIT_ZVAL( num ); + + if( is_numeric == IS_LONG ) + Z_LVAL_P(num) = lval; + if( is_numeric == IS_DOUBLE ) + Z_DVAL_P(num) = dval; + + Z_TYPE_P(num) = is_numeric; + } + else + { + COLLATOR_CONVERT_RETURN_FAILED( str ); + } + + return num; +} +/* }}} */ + +/* {{{ collator_make_printable_zval + * + * Returns string from input zval. + * + * @param zval* arg zval to get string from + * + * @return zval* UTF16 string. + */ +zval* collator_make_printable_zval( zval* arg ) +{ + zval arg_copy; + int use_copy = 0; + zval* str = NULL; + + if( Z_TYPE_P(arg) != IS_STRING ) + { + zend_make_printable_zval(arg, &arg_copy, &use_copy); + + if( use_copy ) + { + str = collator_convert_zstr_utf8_to_utf16( &arg_copy ); + zval_dtor( &arg_copy ); + } + else + { + str = collator_convert_zstr_utf8_to_utf16( arg ); + } + } + else + { + COLLATOR_CONVERT_RETURN_FAILED( arg ); + } + + return str; +} +/* }}} */ + +/* {{{ collator_normalize_sort_argument + * + * Normalize argument to use in sort's compare function. + * + * @param zval* arg Sort's argument to normalize. + * + * @return zval* Normalized copy of arg or unmodified arg + * if normalization is not needed. + */ +zval* collator_normalize_sort_argument( zval* arg ) +{ + zval* n_arg = NULL; + + if( Z_TYPE_P( arg ) != IS_STRING ) + { + // If its not a string then nothing to do. + // Return original arg. + COLLATOR_CONVERT_RETURN_FAILED( arg ); + } + + // Try convert to number. + n_arg = collator_convert_string_to_number_if_possible( arg ); + + if( n_arg == arg ) + { + // Conversion to number failed. + zval_ptr_dtor( &n_arg ); + + // Convert string to utf8. + n_arg = collator_convert_zstr_utf16_to_utf8( arg ); + } + + return n_arg; +} +/* }}} */ +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/collator/collator_convert.h b/ext/intl/collator/collator_convert.h new file mode 100755 index 0000000000..8322ea998b --- /dev/null +++ b/ext/intl/collator/collator_convert.h @@ -0,0 +1,38 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifndef COLLATOR_CONVERT_H +#define COLLATOR_CONVERT_H + +#include +#include + +void collator_convert_hash_from_utf8_to_utf16( HashTable* hash, UErrorCode* status ); +void collator_convert_hash_from_utf16_to_utf8( HashTable* hash, UErrorCode* status ); + +zval* collator_convert_zstr_utf16_to_utf8( zval* utf16_zval ); +zval* collator_convert_zstr_utf8_to_utf16( zval* utf8_zval ); + +zval* collator_normalize_sort_argument( zval* arg ); +zval* collator_convert_object_to_string( zval* obj TSRMLS_DC ); +zval* collator_convert_string_to_number( zval* arg ); +zval* collator_convert_string_to_number_if_possible( zval* str ); +zval* collator_convert_string_to_double( zval* str ); + +zval* collator_make_printable_zval( zval* arg ); + +#endif // COLLATOR_CONVERT_H diff --git a/ext/intl/collator/collator_create.c b/ext/intl/collator/collator_create.c new file mode 100755 index 0000000000..6fbb3da8b3 --- /dev/null +++ b/ext/intl/collator/collator_create.c @@ -0,0 +1,135 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php_intl.h" +#include "collator_class.h" +#include "collator_create.h" +#include "intl_data.h" + +/* {{{ proto Collator collator_create( string $locale ) + * Create collator. + */ +PHP_FUNCTION( collator_create ) +{ + char* locale; + int locale_len = 0; + zval* object; + Collator_object* co; + + intl_error_reset( NULL TSRMLS_CC ); + + // Parse parameters. + if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s", + &locale, &locale_len ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "collator_create: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_NULL(); + } + + INTL_CHECK_LOCALE_LEN(locale_len); + // Create a Collator object and save the ICU collator into it. + if( ( object = getThis() ) == NULL ) + object = return_value; + + if( Z_TYPE_P( object ) != IS_OBJECT ) + object_init_ex( object, Collator_ce_ptr ); + + co = (Collator_object *) zend_object_store_get_object( object TSRMLS_CC ); + + intl_error_reset( COLLATOR_ERROR_P( co ) TSRMLS_CC ); + + if(locale_len == 0) { + locale = INTL_G(default_locale); + } + + // Open ICU collator. + co->ucoll = ucol_open( locale, COLLATOR_ERROR_CODE_P( co ) ); + + if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) || co->ucoll == NULL ) + { + intl_error_set( NULL, COLLATOR_ERROR_CODE( co ), + "collator_create: unable to open ICU collator", 0 TSRMLS_CC ); + + // Collator creation failed. + RETURN_NULL(); + } +} +/* }}} */ + +/* {{{ proto Collator Collator::__construct( string $locale ) + * Collator object constructor. + */ +PHP_METHOD( Collator, __construct ) +{ + char* locale = NULL; + int locale_len = 0; + + COLLATOR_METHOD_INIT_VARS + + object = getThis(); + // Parse parameters. + if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s", + &locale, &locale_len ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "__construct: unable to parse input params", 0 TSRMLS_CC ); + + zval_dtor(object); + ZVAL_NULL(object); + RETURN_NULL(); + } + + INTL_CHECK_LOCALE_LEN_OBJ(locale_len, object); + /* Fetch the object. */ + co = (Collator_object*) zend_object_store_get_object( object TSRMLS_CC ); + + intl_error_reset( COLLATOR_ERROR_P( co ) TSRMLS_CC ); + + if(locale_len == 0) { + locale = INTL_G(default_locale); + } + + // Open ICU collator. + co->ucoll = ucol_open( locale, COLLATOR_ERROR_CODE_P( co ) ); + + if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) || co->ucoll == NULL ) + { + intl_error_set( NULL, COLLATOR_ERROR_CODE( co ), + "__construct: unable to open ICU collator", 0 TSRMLS_CC ); + + zval_dtor(object); + ZVAL_NULL(object); + RETURN_NULL(); + } + +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/collator/collator_create.h b/ext/intl/collator/collator_create.h new file mode 100755 index 0000000000..b740e82d68 --- /dev/null +++ b/ext/intl/collator/collator_create.h @@ -0,0 +1,27 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifndef COLLATOR_CREATE_H +#define COLLATOR_CREATE_H + +#include + +PHP_FUNCTION( collator_create ); + +PHP_METHOD( Collator, __construct ); + +#endif // COLLATOR_CREATE_H diff --git a/ext/intl/collator/collator_error.c b/ext/intl/collator/collator_error.c new file mode 100755 index 0000000000..55e366ccba --- /dev/null +++ b/ext/intl/collator/collator_error.c @@ -0,0 +1,94 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php_intl.h" +#include "collator_class.h" +#include "collator_error.h" + +/* {{{ proto int Collator::getErrorCode( Collator $coll ) + * Get collator's last error code. }}} */ +/* {{{ proto int collator_get_error_code( Collator $coll ) + * Get collator's last error code. + */ +PHP_FUNCTION( collator_get_error_code ) +{ + COLLATOR_METHOD_INIT_VARS + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, Collator_ce_ptr ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "collator_get_error_code: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + // Fetch the object (without resetting its last error code). + co = (Collator_object *) zend_object_store_get_object(object TSRMLS_CC); + if( co == NULL ) + RETURN_FALSE; + + // Return collator's last error code. + RETURN_LONG( COLLATOR_ERROR_CODE( co ) ); +} +/* }}} */ + +/* {{{ proto string Collator::getErrorMessage( Collator $coll ) + * Get text description for collator's last error code. }}} */ +/* {{{ proto string collator_get_error_message( Collator $coll ) + * Get text description for collator's last error code. + */ +PHP_FUNCTION( collator_get_error_message ) +{ + const char* message = NULL; + + COLLATOR_METHOD_INIT_VARS + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, Collator_ce_ptr ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "collator_get_error_message: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + // Fetch the object (without resetting its last error code). + co = (Collator_object *) zend_object_store_get_object( object TSRMLS_CC ); + if( co == NULL ) + RETURN_FALSE; + + // Return last error message. + message = intl_error_get_message( COLLATOR_ERROR_P( co ) TSRMLS_CC ); + RETURN_STRING( (char*)message, FALSE ); +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/collator/collator_error.h b/ext/intl/collator/collator_error.h new file mode 100755 index 0000000000..b2f44ea2a3 --- /dev/null +++ b/ext/intl/collator/collator_error.h @@ -0,0 +1,26 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifndef COLLATOR_ERROR_H +#define COLLATOR_ERROR_H + +#include + +PHP_FUNCTION( collator_get_error_code ); +PHP_FUNCTION( collator_get_error_message ); + +#endif // COLLATOR_ERROR_H diff --git a/ext/intl/collator/collator_is_numeric.c b/ext/intl/collator/collator_is_numeric.c new file mode 100755 index 0000000000..a8abfac12b --- /dev/null +++ b/ext/intl/collator/collator_is_numeric.c @@ -0,0 +1,305 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#include "collator_is_numeric.h" + +#if ZEND_MODULE_API_NO < 20071006 +/* not 5.3 */ +#ifndef ALLOCA_FLAG +#define ALLOCA_FLAG(use_heap) +#endif +#define _do_alloca(x, y) do_alloca((x)) +#define _free_alloca(x, y) free_alloca((x)) +#else +#define _do_alloca do_alloca +#define _free_alloca free_alloca +#endif +/* {{{ collator_u_strtod + * Taken from PHP6:zend_u_strtod() + */ +static double collator_u_strtod(const UChar *nptr, UChar **endptr) /* {{{ */ +{ + const UChar *u = nptr, *nstart; + UChar c = *u; + int any = 0; + ALLOCA_FLAG(use_heap); + + while (u_isspace(c)) { + c = *++u; + } + nstart = u; + + if (c == 0x2D /*'-'*/ || c == 0x2B /*'+'*/) { + c = *++u; + } + + while (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) { + any = 1; + c = *++u; + } + + if (c == 0x2E /*'.'*/) { + c = *++u; + while (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) { + any = 1; + c = *++u; + } + } + + if ((c == 0x65 /*'e'*/ || c == 0x45 /*'E'*/) && any) { + const UChar *e = u; + int any_exp = 0; + + c = *++u; + if (c == 0x2D /*'-'*/ || c == 0x2B /*'+'*/) { + c = *++u; + } + + while (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) { + any_exp = 1; + c = *++u; + } + + if (!any_exp) { + u = e; + } + } + + if (any) { + char buf[64], *numbuf, *bufpos; + int length = u - nstart; + double value; + + if (length < sizeof(buf)) { + numbuf = buf; + } else { + numbuf = (char *) _do_alloca(length + 1, use_heap); + } + + bufpos = numbuf; + + while (nstart < u) { + *bufpos++ = (char) *nstart++; + } + + *bufpos = '\0'; + value = zend_strtod(numbuf, NULL); + + if (numbuf != buf) { + _free_alloca(numbuf, use_heap); + } + + if (endptr != NULL) { + *endptr = (UChar *)u; + } + + return value; + } + + if (endptr != NULL) { + *endptr = (UChar *)nptr; + } + + return 0; +} +/* }}} */ + +/* {{{ collator_u_strtol + * Taken from PHP6:zend_u_strtol() + * + * Convert a Unicode string to a long integer. + * + * Ignores `locale' stuff. + */ +static long collator_u_strtol(nptr, endptr, base) + const UChar *nptr; + UChar **endptr; + register int base; +{ + register const UChar *s = nptr; + register unsigned long acc; + register UChar c; + register unsigned long cutoff; + register int neg = 0, any, cutlim; + + if (s == NULL) { + errno = ERANGE; + if (endptr != NULL) { + *endptr = NULL; + } + return 0; + } + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + do { + c = *s++; + } while (u_isspace(c)); + if (c == 0x2D /*'-'*/) { + neg = 1; + c = *s++; + } else if (c == 0x2B /*'+'*/) + c = *s++; + if ((base == 0 || base == 16) && + (c == 0x30 /*'0'*/) + && (*s == 0x78 /*'x'*/ || *s == 0x58 /*'X'*/)) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = (c == 0x30 /*'0'*/) ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; + cutlim = cutoff % (unsigned long)base; + cutoff /= (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) { + if (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) + c -= 0x30 /*'0'*/; + else if (c >= 0x41 /*'A'*/ && c <= 0x5A /*'Z'*/) + c -= 0x41 /*'A'*/ - 10; + else if (c >= 0x61 /*'a'*/ && c <= 0x7A /*'z'*/) + c -= 0x61 /*'a'*/ - 10; + else + break; + if (c >= base) + break; + + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? LONG_MIN : LONG_MAX; + errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != NULL) + *endptr = (UChar *)(any ? s - 1 : nptr); + return (acc); +} +/* }}} */ + + +/* {{{ collator_is_numeric] + * Taken from PHP6:is_numeric_unicode() + */ +zend_uchar collator_is_numeric( UChar *str, int length, long *lval, double *dval, int allow_errors ) +{ + long local_lval; + double local_dval; + UChar *end_ptr_long, *end_ptr_double; + int conv_base=10; + + if (!length) { + return 0; + } + + /* handle hex numbers */ + if (length>=2 && str[0]=='0' && (str[1]=='x' || str[1]=='X')) { + conv_base=16; + } + + errno=0; + local_lval = collator_u_strtol(str, &end_ptr_long, conv_base); + if (errno != ERANGE) { + if (end_ptr_long == str+length) { /* integer string */ + if (lval) { + *lval = local_lval; + } + return IS_LONG; + } else if (end_ptr_long == str && *end_ptr_long != '\0' && *str != '.' && *str != '-') { /* ignore partial string matches */ + return 0; + } + } else { + end_ptr_long = NULL; + } + + if (conv_base == 16) { /* hex string, under UNIX strtod() messes it up */ + /* UTODO: keep compatibility with is_numeric_string() here? */ + return 0; + } + + local_dval = collator_u_strtod(str, &end_ptr_double); + if (local_dval == 0 && end_ptr_double == str) { + end_ptr_double = NULL; + } else { + if (end_ptr_double == str+length) { /* floating point string */ + if (!zend_finite(local_dval)) { + /* "inf","nan" and maybe other weird ones */ + return 0; + } + + if (dval) { + *dval = local_dval; + } + return IS_DOUBLE; + } + } + + if (!allow_errors) { + return 0; + } + if (allow_errors == -1) { + zend_error(E_NOTICE, "A non well formed numeric value encountered"); + } + + if (allow_errors) { + if (end_ptr_double > end_ptr_long && dval) { + *dval = local_dval; + return IS_DOUBLE; + } else if (end_ptr_long && lval) { + *lval = local_lval; + return IS_LONG; + } + } + return 0; +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/collator/collator_is_numeric.h b/ext/intl/collator/collator_is_numeric.h new file mode 100755 index 0000000000..585d58917a --- /dev/null +++ b/ext/intl/collator/collator_is_numeric.h @@ -0,0 +1,26 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifndef COLLATOR_IS_NUMERIC_H +#define COLLATOR_IS_NUMERIC_H + +#include +#include + +zend_uchar collator_is_numeric( UChar *str, int length, long *lval, double *dval, int allow_errors ); + +#endif // COLLATOR_IS_NUMERIC_H diff --git a/ext/intl/collator/collator_locale.c b/ext/intl/collator/collator_locale.c new file mode 100755 index 0000000000..838c50be80 --- /dev/null +++ b/ext/intl/collator/collator_locale.c @@ -0,0 +1,71 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#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 + +/* {{{ proto string Collator::getLocale( int $type ) + * Gets the locale name of the collator. }}} */ +/* {{{ proto string collator_get_locale( Collator $coll, int $type ) + * Gets the locale name of the collator. + */ +PHP_FUNCTION( collator_get_locale ) +{ + int type = 0; + char* locale_name = NULL; + + COLLATOR_METHOD_INIT_VARS + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", + &object, Collator_ce_ptr, &type ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "collator_get_locale: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + // Fetch the object. + COLLATOR_METHOD_FETCH_OBJECT; + + // Get locale by specified type. + locale_name = (char*) ucol_getLocaleByType( + co->ucoll, type, COLLATOR_ERROR_CODE_P( co ) ); + COLLATOR_CHECK_STATUS( co, "Error getting locale by type" ); + + // Return it. + RETVAL_STRINGL( locale_name, strlen(locale_name), TRUE ); +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/collator/collator_locale.h b/ext/intl/collator/collator_locale.h new file mode 100755 index 0000000000..bda90cd3b9 --- /dev/null +++ b/ext/intl/collator/collator_locale.h @@ -0,0 +1,25 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifndef COLLATOR_LOCALE_H +#define COLLATOR_LOCALE_H + +#include + +PHP_FUNCTION( collator_get_locale ); + +#endif // COLLATOR_LOCALE_H diff --git a/ext/intl/collator/collator_sort.c b/ext/intl/collator/collator_sort.c new file mode 100755 index 0000000000..db014428ad --- /dev/null +++ b/ext/intl/collator/collator_sort.c @@ -0,0 +1,532 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php_intl.h" +#include "collator.h" +#include "collator_class.h" +#include "collator_sort.h" +#include "collator_convert.h" +#include "intl_convert.h" + +#if !defined(HAVE_PTRDIFF_T) && !defined(_PTRDIFF_T_DEFINED) +typedef long ptrdiff_t; +#endif + +/** + * Declare 'index' which will point to sort key in sort key + * buffer. + */ +typedef struct _collator_sort_key_index { + char* key; // pointer to sort key + zval** zstr; // pointer to original string(hash-item) +} collator_sort_key_index_t; + +ZEND_EXTERN_MODULE_GLOBALS( intl ) + +static const size_t DEF_SORT_KEYS_BUF_SIZE = 1048576; +static const size_t DEF_SORT_KEYS_BUF_INCREMENT = 1048576; + +static const size_t DEF_SORT_KEYS_INDX_BUF_SIZE = 1048576; +static const size_t DEF_SORT_KEYS_INDX_BUF_INCREMENT = 1048576; + +static const size_t DEF_UTF16_BUF_SIZE = 1024; + +/* {{{ collator_regular_compare_function */ +static int collator_regular_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) +{ + Collator_object* co = NULL; + + int rc = SUCCESS; + + zval* str1 = collator_convert_object_to_string( op1 TSRMLS_CC ); + zval* str2 = collator_convert_object_to_string( op2 TSRMLS_CC ); + + zval* num1 = NULL; + zval* num2 = NULL; + zval* norm1 = NULL; + zval* norm2 = NULL; + + // If both args are strings AND either of args is not numeric string + // then use ICU-compare. Otherwise PHP-compare. + if( Z_TYPE_P(str1) == IS_STRING && Z_TYPE_P(str2) == IS_STRING && + ( str1 == ( num1 = collator_convert_string_to_number_if_possible( str1 ) ) || + str2 == ( num2 = collator_convert_string_to_number_if_possible( str2 ) ) ) ) + { + // Fetch collator object. + co = (Collator_object *) zend_object_store_get_object( INTL_G(current_collator) TSRMLS_CC ); + + // Compare the strings using ICU. + result->value.lval = ucol_strcoll( + co->ucoll, + INTL_Z_STRVAL_P(str1), INTL_Z_STRLEN_P(str1), + INTL_Z_STRVAL_P(str2), INTL_Z_STRLEN_P(str2) ); + result->type = IS_LONG; + } + else + { + // num1 is set if str1 and str2 are strings. + if( num1 ) + { + if( num1 == str1 ) + { + // str1 is string but not numeric string + // just convert it to utf8. + norm1 = collator_convert_zstr_utf16_to_utf8( str1 ); + + // num2 is not set but str2 is string => do normalization. + norm2 = collator_normalize_sort_argument( str2 ); + } + else + { + // str1 is numeric strings => passthru to PHP-compare. + zval_add_ref( &num1 ); + norm1 = num1; + + // str2 is numeric strings => passthru to PHP-compare. + zval_add_ref( &num2 ); + norm2 = num2; + } + } + else + { + // num1 is not set if str1 or str2 is not a string => do normalization. + norm1 = collator_normalize_sort_argument( str1 ); + + // if num1 is not set then num2 is not set as well => do normalization. + norm2 = collator_normalize_sort_argument( str2 ); + } + + rc = compare_function( result, norm1, norm2 TSRMLS_CC ); + + zval_ptr_dtor( &norm1 ); + zval_ptr_dtor( &norm2 ); + } + + if( num1 ) + zval_ptr_dtor( &num1 ); + + if( num2 ) + zval_ptr_dtor( &num2 ); + + zval_ptr_dtor( &str1 ); + zval_ptr_dtor( &str2 ); + + return rc; +} +/* }}} */ + +/* {{{ collator_numeric_compare_function + * Convert input args to double and compare it. + */ +static int collator_numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) +{ + int rc = SUCCESS; + zval* num1 = NULL; + zval* num2 = NULL; + + if( Z_TYPE_P(op1) == IS_STRING ) + { + num1 = collator_convert_string_to_double( op1 ); + op1 = num1; + } + + if( Z_TYPE_P(op2) == IS_STRING ) + { + num2 = collator_convert_string_to_double( op2 ); + op2 = num2; + } + + rc = numeric_compare_function( result, op1, op2 TSRMLS_CC); + + if( num1 ) + zval_ptr_dtor( &num1 ); + if( num2 ) + zval_ptr_dtor( &num2 ); + + return rc; +} +/* }}} */ + +/* {{{ collator_icu_compare_function + * Direct use of ucol_strcoll. +*/ +static int collator_icu_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) +{ + int rc = SUCCESS; + Collator_object* co = NULL; + zval* str1 = NULL; + zval* str2 = NULL; + + str1 = collator_make_printable_zval( op1 ); + str2 = collator_make_printable_zval( op2 ); + + // Fetch collator object. + co = (Collator_object *) zend_object_store_get_object( INTL_G(current_collator) TSRMLS_CC ); + + // Compare the strings using ICU. + result->value.lval = ucol_strcoll( + co->ucoll, + INTL_Z_STRVAL_P(str1), INTL_Z_STRLEN_P(str1), + INTL_Z_STRVAL_P(str2), INTL_Z_STRLEN_P(str2) ); + result->type = IS_LONG; + + zval_ptr_dtor( &str1 ); + zval_ptr_dtor( &str2 ); + + return rc; +} +/* }}} */ + +/* {{{ collator_compare_func + * Taken from PHP5 source (array_data_compare). + */ +static int collator_compare_func( const void* a, const void* b TSRMLS_DC ) +{ + Bucket *f; + Bucket *s; + zval result; + zval *first; + zval *second; + + f = *((Bucket **) a); + s = *((Bucket **) b); + + first = *((zval **) f->pData); + second = *((zval **) s->pData); + + if( INTL_G(compare_func)( &result, first, second TSRMLS_CC) == FAILURE ) + return 0; + + if( Z_TYPE(result) == IS_DOUBLE ) + { + if( Z_DVAL(result) < 0 ) + return -1; + else if( Z_DVAL(result) > 0 ) + return 1; + else + return 0; + } + + convert_to_long(&result); + + if( Z_LVAL(result) < 0 ) + return -1; + else if( Z_LVAL(result) > 0 ) + return 1; + + return 0; +} +/* }}} */ + +/* {{{ collator_cmp_sort_keys + * Compare sort keys + */ +static int collator_cmp_sort_keys( const void *p1, const void *p2 TSRMLS_DC ) +{ + char* key1 = ((collator_sort_key_index_t*)p1)->key; + char* key2 = ((collator_sort_key_index_t*)p2)->key; + + return strcmp( key1, key2 ); +} +/* }}} */ + +/* {{{ collator_get_compare_function + * Choose compare function according to sort flags. + */ +static collator_compare_func_t collator_get_compare_function( const long sort_flags ) +{ + collator_compare_func_t func; + + switch( sort_flags ) + { + case COLLATOR_SORT_NUMERIC: + func = collator_numeric_compare_function; + break; + + case COLLATOR_SORT_STRING: + func = collator_icu_compare_function; + break; + + case COLLATOR_SORT_REGULAR: + default: + func = collator_regular_compare_function; + break; + } + + return func; +} +/* }}} */ + +/* {{{ collator_sort_internal + * Common code shared by collator_sort() and collator_asort() API functions. + */ +static void collator_sort_internal( int renumber, INTERNAL_FUNCTION_PARAMETERS ) +{ + zval* array = NULL; + HashTable* hash = NULL; + zval* saved_collator = NULL; + long sort_flags = COLLATOR_SORT_REGULAR; + + COLLATOR_METHOD_INIT_VARS + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oa|l", + &object, Collator_ce_ptr, &array, &sort_flags ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "collator_sort_internal: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + // Fetch the object. + COLLATOR_METHOD_FETCH_OBJECT; + + // Set 'compare function' according to sort flags. + INTL_G(compare_func) = collator_get_compare_function( sort_flags ); + + hash = HASH_OF( array ); + + // Convert strings in the specified array from UTF-8 to UTF-16. + collator_convert_hash_from_utf8_to_utf16( hash, COLLATOR_ERROR_CODE_P( co ) ); + COLLATOR_CHECK_STATUS( co, "Error converting hash from UTF-8 to UTF-16" ); + + // Save specified collator in the request-global (?) variable. + saved_collator = INTL_G( current_collator ); + INTL_G( current_collator ) = object; + + // Sort specified array. + zend_hash_sort( hash, zend_qsort, collator_compare_func, renumber TSRMLS_CC ); + + // Restore saved collator. + INTL_G( current_collator ) = saved_collator; + + // Convert strings in the specified array back to UTF-8. + collator_convert_hash_from_utf16_to_utf8( hash, COLLATOR_ERROR_CODE_P( co ) ); + COLLATOR_CHECK_STATUS( co, "Error converting hash from UTF-16 to UTF-8" ); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto bool Collator::sort( Collator $coll, array(string) $arr [, int $sort_flags] ) + * Sort array using specified collator. }}} */ +/* {{{ proto bool collator_sort( Collator $coll, array(string) $arr [, int $sort_flags] ) + * Sort array using specified collator. + */ +PHP_FUNCTION( collator_sort ) +{ + collator_sort_internal( TRUE, INTERNAL_FUNCTION_PARAM_PASSTHRU ); +} +/* }}} */ + +/* {{{ proto bool Collator::sortWithSortKeys( Collator $coll, array(string) $arr ) + * Equivalent to standard PHP sort using Collator. + * Uses ICU ucol_getSortKey for performance. }}} */ +/* {{{ proto bool collator_sort_with_sort_keys( Collator $coll, array(string) $arr ) + * Equivalent to standard PHP sort using Collator. + * Uses ICU ucol_getSortKey for performance. + */ +PHP_FUNCTION( collator_sort_with_sort_keys ) +{ + zval* array = NULL; + HashTable* hash = NULL; + zval** hashData = NULL; // currently processed item of input hash + + char* sortKeyBuf = NULL; // buffer to store sort keys + uint32_t sortKeyBufSize = DEF_SORT_KEYS_BUF_SIZE; // buffer size + ptrdiff_t sortKeyBufOffset = 0; // pos in buffer to store sort key + int32_t sortKeyLen = 0; // the length of currently processing key + uint32_t bufLeft = 0; + uint32_t bufIncrement = 0; + + collator_sort_key_index_t* sortKeyIndxBuf = NULL; // buffer to store 'indexes' which will be passed to 'qsort' + uint32_t sortKeyIndxBufSize = DEF_SORT_KEYS_INDX_BUF_SIZE; + uint32_t sortKeyIndxSize = sizeof( collator_sort_key_index_t ); + + uint32_t sortKeyCount = 0; + uint32_t j = 0; + + UChar* utf16_buf = NULL; // tmp buffer to hold current processing string in utf-16 + int utf16_buf_size = DEF_UTF16_BUF_SIZE; // the length of utf16_buf + int utf16_len = 0; // length of converted string + + HashTable* sortedHash = NULL; + + COLLATOR_METHOD_INIT_VARS + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oa", + &object, Collator_ce_ptr, &array ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "collator_sort_with_sort_keys: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + // Fetch the object. + COLLATOR_METHOD_FETCH_OBJECT; + + + /* + * Sort specified array. + */ + hash = HASH_OF( array ); + + if( !hash || zend_hash_num_elements( hash ) == 0 ) + RETURN_TRUE; + + // Create bufers + sortKeyBuf = ecalloc( sortKeyBufSize, sizeof( char ) ); + sortKeyIndxBuf = ecalloc( sortKeyIndxBufSize, sizeof( uint8_t ) ); + utf16_buf = eumalloc( utf16_buf_size ); + + // Iterate through input hash and create a sort key for each value. + zend_hash_internal_pointer_reset( hash ); + while( zend_hash_get_current_data( hash, (void**) &hashData ) == SUCCESS ) + { + // Convert current hash item from UTF-8 to UTF-16LE and save the result to utf16_buf. + + utf16_len = utf16_buf_size; + + // Process string values only. + if( Z_TYPE_PP( hashData ) == IS_STRING ) + { + intl_convert_utf8_to_utf16( &utf16_buf, &utf16_len, Z_STRVAL_PP( hashData ), Z_STRLEN_PP( hashData ), COLLATOR_ERROR_CODE_P( co ) ); + + if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) + { + intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) TSRMLS_CC ); + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Sort with sort keys failed", 0 TSRMLS_CC ); + + if( utf16_buf ) + efree( utf16_buf ); + + efree( sortKeyIndxBuf ); + efree( sortKeyBuf ); + + RETURN_FALSE; + } + } + else + { + // Set empty string + utf16_len = 0; + utf16_buf[utf16_len] = 0; + } + + if( (utf16_len + 1) > utf16_buf_size ) + utf16_buf_size = utf16_len + 1; + + // Get sort key, reallocating the buffer if needed. + bufLeft = sortKeyBufSize - sortKeyBufOffset; + + sortKeyLen = ucol_getSortKey( co->ucoll, + utf16_buf, + utf16_len, + (uint8_t*)sortKeyBuf + sortKeyBufOffset, + bufLeft ); + + // check for sortKeyBuf overflow, increasing its size of the buffer if needed + if( sortKeyLen > bufLeft ) + { + bufIncrement = ( sortKeyLen > DEF_SORT_KEYS_BUF_INCREMENT ) ? sortKeyLen : DEF_SORT_KEYS_BUF_INCREMENT; + + sortKeyBufSize += bufIncrement; + bufLeft += bufIncrement; + + sortKeyBuf = erealloc( sortKeyBuf, sortKeyBufSize ); + + sortKeyLen = ucol_getSortKey( co->ucoll, utf16_buf, utf16_len, (uint8_t*)sortKeyBuf + sortKeyBufOffset, bufLeft ); + } + + // check sortKeyIndxBuf overflow, increasing its size of the buffer if needed + if( ( sortKeyCount + 1 ) * sortKeyIndxSize > sortKeyIndxBufSize ) + { + bufIncrement = ( sortKeyIndxSize > DEF_SORT_KEYS_INDX_BUF_INCREMENT ) ? sortKeyIndxSize : DEF_SORT_KEYS_INDX_BUF_INCREMENT; + + sortKeyIndxBufSize += bufIncrement; + + sortKeyIndxBuf = erealloc( sortKeyIndxBuf, sortKeyIndxBufSize ); + } + + sortKeyIndxBuf[sortKeyCount].key = (char*)sortKeyBufOffset; // remeber just offset, cause address + // of 'sortKeyBuf' may be changed due to realloc. + sortKeyIndxBuf[sortKeyCount].zstr = hashData; + + sortKeyBufOffset += sortKeyLen; + ++sortKeyCount; + + zend_hash_move_forward( hash ); + } + + // update ptrs to point to valid keys. + for( j = 0; j < sortKeyCount; j++ ) + sortKeyIndxBuf[j].key = sortKeyBuf + (ptrdiff_t)sortKeyIndxBuf[j].key; + + // sort it + zend_qsort( sortKeyIndxBuf, sortKeyCount, sortKeyIndxSize, collator_cmp_sort_keys TSRMLS_CC ); + + // for resulting hash we'll assign new hash keys rather then reordering + ALLOC_HASHTABLE( sortedHash ); + zend_hash_init( sortedHash, 0, NULL, ZVAL_PTR_DTOR, 0 ); + + for( j = 0; j < sortKeyCount; j++ ) + { + zval_add_ref( sortKeyIndxBuf[j].zstr ); + zend_hash_next_index_insert( sortedHash, sortKeyIndxBuf[j].zstr, sizeof(zval **), NULL ); + } + + // Save sorted hash into return variable. + zval_dtor( array ); + (array)->value.ht = sortedHash; + (array)->type = IS_ARRAY; + + if( utf16_buf ) + efree( utf16_buf ); + + efree( sortKeyIndxBuf ); + efree( sortKeyBuf ); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto bool Collator::asort( Collator $coll, array(string) $arr ) + * Sort array using specified collator, maintaining index association. }}} */ +/* {{{ proto bool collator_asort( Collator $coll, array(string) $arr ) + * Sort array using specified collator, maintaining index association. + */ +PHP_FUNCTION( collator_asort ) +{ + collator_sort_internal( FALSE, INTERNAL_FUNCTION_PARAM_PASSTHRU ); +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/collator/collator_sort.h b/ext/intl/collator/collator_sort.h new file mode 100755 index 0000000000..0fafb9f35a --- /dev/null +++ b/ext/intl/collator/collator_sort.h @@ -0,0 +1,29 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifndef COLLATOR_SORT_H +#define COLLATOR_SORT_H + +#include + +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 diff --git a/ext/intl/common/common_error.c b/ext/intl/common/common_error.c new file mode 100755 index 0000000000..3468cd520e --- /dev/null +++ b/ext/intl/common/common_error.c @@ -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 | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#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 + */ diff --git a/ext/intl/common/common_error.h b/ext/intl/common/common_error.h new file mode 100755 index 0000000000..8716222124 --- /dev/null +++ b/ext/intl/common/common_error.h @@ -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 | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifndef INTL_COMMON_ERROR_H +#define INTL_COMMON_ERROR_H + +#include + +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 diff --git a/ext/intl/config.m4 b/ext/intl/config.m4 new file mode 100755 index 0000000000..9a6296f672 --- /dev/null +++ b/ext/intl/config.m4 @@ -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 diff --git a/ext/intl/config.w32 b/ext/intl/config.w32 new file mode 100755 index 0000000000..e793cd8cf8 --- /dev/null +++ b/ext/intl/config.w32 @@ -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"); + } +} diff --git a/ext/intl/doc/Tutorial.txt b/ext/intl/doc/Tutorial.txt new file mode 100755 index 0000000000..4a66dc1844 --- /dev/null +++ b/ext/intl/doc/Tutorial.txt @@ -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, _