com php-src: ICU < 4.8 compat in MessageFormatter: ext/intl/msg format/msgformat_helpers.cpp ext/intl/tests/msgfmt_form at_error1.phpt
ext/intl/tests/msgfmt_format_error 2.phpt ext/intl/tests/msgfmt_format_error3.phpt ext/intl/tests/msgfmt_format_error4.phpt ext/intl/
tests/msgfmt_format_error5.phpt ext/intl/tests/msgfmt _format_error6.phpt ext/intl/tests/msgfmt_format_ mixed_params.phpt
ext/intl/tests/msgfmt_format_simple _types_numeric_strings.phpt ex
| From: | Gustavo André dos Santos Lopes | Date: | Sun, 13 May 2012 19:55:02 +0000 |
| Subject: | com php-src: ICU < 4.8 compat in MessageFormatter: ext/intl/msg format/msgformat_helpers.cpp ext/intl/tests/msgfmt_form at_error1.phpt ext/intl/tests/msgfmt_format_error 2.phpt ext/intl/tests/msgfmt_format_error3.phpt ext/intl/tests/msgfmt_format_error4.phpt ext/intl/ tests/msgfmt_format_error5.phpt ext/intl/tests/msgfmt _format_error6.phpt ext/intl/tests/msgfmt_format_ mixed_params.phpt ext/intl/tests/msgfmt_format_simple _types_numeric_strings.phpt ex |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-69049@lists.php.net to get a copy of this message | ||
Commit: 53860672f3636049e5fbc29d49eb017893fa6808
Author: Gustavo André dos Santos Lopes <cataphract@php.net> Sun, 13 May 2012
20:14:14 +0200
Parents: 43ff66e0953e3664de11ffa7af27c695057cc4d6
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=53860672f3636049e5fbc29d49eb017893fa6808
Log:
ICU < 4.8 compat in MessageFormatter
Restricted support for named arguments to ICU 4..8+.
Also added bound checks when converting arguments to Formattables..
Changed paths:
M ext/intl/msgformat/msgformat_helpers.cpp
M ext/intl/tests/msgfmt_format_error1.phpt
M ext/intl/tests/msgfmt_format_error2.phpt
M ext/intl/tests/msgfmt_format_error3.phpt
M ext/intl/tests/msgfmt_format_error4.phpt
M ext/intl/tests/msgfmt_format_error5.phpt
M ext/intl/tests/msgfmt_format_error6.phpt
M ext/intl/tests/msgfmt_format_mixed_params.phpt
M ext/intl/tests/msgfmt_format_simple_types_numeric_strings.phpt
M ext/intl/tests/msgfmt_format_subpatterns.phpt
M ext/intl/tests/msgfmt_format_subpatterns_named.phpt
D ext/intl/tests/msgfmt_get_error.phpt
diff --git a/ext/intl/msgformat/msgformat_helpers.cpp b/ext/intl/msgformat/msgformat_helpers.cpp index b13c4c4..42c5466 100755 --- a/ext/intl/msgformat/msgformat_helpers.cpp +++ b/ext/intl/msgformat/msgformat_helpers.cpp @@ -25,7 +25,6 @@ #include <limits.h> #include <unicode/msgfmt.h> #include <unicode/chariter.h> -#include <unicode/messagepattern.h> #include <unicode/ustdio.h> #include <vector> @@ -51,6 +50,10 @@ extern "C" { #define NAN (INFINITY-INFINITY) #endif +#if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 48 +#define HAS_MESSAGE_PATTERN 1 +#endif + U_NAMESPACE_BEGIN /** * This class isolates our access to private internal methods of @@ -61,17 +64,23 @@ class MessageFormatAdapter { public: static const Formattable::Type* getArgTypeList(const MessageFormat& m, int32_t& count); +#ifdef HAS_MESSAGE_PATTERN static const MessagePattern getMessagePattern(MessageFormat* m); +#endif }; + const Formattable::Type* MessageFormatAdapter::getArgTypeList(const MessageFormat& m, int32_t& count) { return m.getArgTypeList(count); } + +#ifdef HAS_MESSAGE_PATTERN const MessagePattern MessageFormatAdapter::getMessagePattern(MessageFormat* m) { return m->msgPattern; } +#endif U_NAMESPACE_END U_CFUNC int32_t umsg_format_arg_count(UMessageFormat *fmt) @@ -133,6 +142,52 @@ static double umsg_helper_zval_to_millis(zval *z, UErrorCode *status TSRMLS_DC) return rv; } +static HashTable *umsg_get_numeric_types(MessageFormatter_object *mfo, + intl_error& err TSRMLS_DC) +{ + HashTable *ret; + int32_t parts_count; + + if (U_FAILURE(err.code)) { + return NULL; + } + + if (mfo->mf_data.arg_types) { + /* already cached */ + return mfo->mf_data.arg_types; + } + + const Formattable::Type *types = MessageFormatAdapter::getArgTypeList( + *(MessageFormat*)mfo->mf_data.umsgf, parts_count); + + /* Hash table will store Formattable::Type objects directly, + * so no need for destructor */ + ALLOC_HASHTABLE(ret); + zend_hash_init(ret, parts_count, NULL, NULL, 0); + + for (int i = 0; i < parts_count; i++) { + const Formattable::Type t = types[i]; + if (zend_hash_index_update(ret, (ulong)i, (void*)&t, sizeof(t), NULL) + == FAILURE) { + intl_errors_set(&err, U_MEMORY_ALLOCATION_ERROR, + "Write to argument types hash table failed", 0 TSRMLS_CC); + break; + } + } + + if (U_FAILURE(err.code)) { + zend_hash_destroy(ret); + efree(ret); + + return NULL; + } + + mfo->mf_data.arg_types = ret; + + return ret; +} + +#ifdef HAS_MESSAGE_PATTERN static HashTable *umsg_parse_format(MessageFormatter_object *mfo, const MessagePattern& mp, intl_error& err TSRMLS_DC) @@ -144,6 +199,10 @@ static HashTable *umsg_parse_format(MessageFormatter_object *mfo, return NULL; } + if (!((MessageFormat *)mfo->mf_data.umsgf)->usesNamedArguments()) { + return umsg_get_numeric_types(mfo, err TSRMLS_CC); + } + if (mfo->mf_data.arg_types) { /* already cached */ return mfo->mf_data.arg_types; @@ -287,6 +346,27 @@ static HashTable *umsg_parse_format(MessageFormatter_object *mfo, return ret; } +#endif + +static HashTable *umsg_get_types(MessageFormatter_object *mfo, + intl_error& err TSRMLS_DC) +{ + MessageFormat *mf = (MessageFormat *)mfo->mf_data.umsgf; + +#ifdef HAS_MESSAGE_PATTERN + const MessagePattern mp = MessageFormatAdapter::getMessagePattern(mf); + + return umsg_parse_format(mfo, mp, err TSRMLS_CC); +#else + if (mf->usesNamedArguments()) { + intl_errors_set(&err, U_UNSUPPORTED_ERROR, + "This extension supports named arguments only on ICU 4.8+", + 0 TSRMLS_CC); + return NULL; + } + return umsg_get_numeric_types(mfo, err TSRMLS_CC); +#endif +} U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, HashTable *args, @@ -297,7 +377,6 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, std::vector<Formattable> fargs; std::vector<UnicodeString> farg_names; MessageFormat *mf = (MessageFormat *)mfo->mf_data.umsgf; - const MessagePattern mp = MessageFormatAdapter::getMessagePattern(mf); HashTable *types; intl_error& err = INTL_DATA_ERROR(mfo); @@ -305,11 +384,11 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, return; } + types = umsg_get_types(mfo, err TSRMLS_CC); + fargs.resize(arg_count); farg_names.resize(arg_count); - types = umsg_parse_format(mfo, mp, err TSRMLS_CC); - int argNum = 0; HashPosition pos; zval **elem; @@ -414,19 +493,56 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, formattable.setDouble(d); break; } + case Formattable::kLong: + { + int32_t tInt32; +retry_klong: + if (Z_TYPE_PP(elem) == IS_DOUBLE) { + if (Z_DVAL_PP(elem) > (double)INT32_MAX || + Z_DVAL_PP(elem) < (double)INT32_MIN) { + intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, + "Found PHP float with absolute value too large for " + "32 bit integer argument", 0 TSRMLS_CC); + } else { + tInt32 = (int32_t)Z_DVAL_PP(elem); + } + } else if (Z_TYPE_PP(elem) == IS_LONG) { + if (Z_LVAL_PP(elem) > INT32_MAX || + Z_LVAL_PP(elem) < INT32_MIN) { + intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, + "Found PHP integer with absolute value too large " + "for 32 bit integer argument", 0 TSRMLS_CC); + } else { + tInt32 = (int32_t)Z_LVAL_PP(elem); + } + } else { + SEPARATE_ZVAL_IF_NOT_REF(elem); + convert_scalar_to_number(*elem TSRMLS_CC); + goto retry_klong; + } + formattable.setLong(tInt32); + break; + } case Formattable::kInt64: { int64_t tInt64; +retry_kint64: if (Z_TYPE_PP(elem) == IS_DOUBLE) { - tInt64 = (int64_t)Z_DVAL_PP(elem); + if (Z_DVAL_PP(elem) > (double)U_INT64_MAX || + Z_DVAL_PP(elem) < (double)U_INT64_MIN) { + intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, + "Found PHP float with absolute value too large for " + "64 bit integer argument", 0 TSRMLS_CC); + } else { + tInt64 = (int64_t)Z_DVAL_PP(elem); + } } else if (Z_TYPE_PP(elem) == IS_LONG) { + /* assume long is not wider than 64 bits */ tInt64 = (int64_t)Z_LVAL_PP(elem); } else { SEPARATE_ZVAL_IF_NOT_REF(elem); convert_scalar_to_number(*elem TSRMLS_CC); - tInt64 = (Z_TYPE_PP(elem) == IS_DOUBLE) - ? (int64_t)Z_DVAL_PP(elem) - : Z_LVAL_PP(elem); + goto retry_kint64; } formattable.setInt64(tInt64); break; @@ -451,6 +567,10 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, formattable.setDate(dd); break; } + default: + intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, + "Found unsupported argument type", 0 TSRMLS_CC); + break; } } else { /* We couldn't find any information about the argument in the pattern, this diff --git a/ext/intl/tests/msgfmt_format_error1.phpt b/ext/intl/tests/msgfmt_format_error1.phpt index 09d022b..684b059 100644 --- a/ext/intl/tests/msgfmt_format_error1.phpt +++ b/ext/intl/tests/msgfmt_format_error1.phpt @@ -16,6 +16,4 @@ $mf = new MessageFormatter('en_US', $fmt); var_dump($mf->format(array(7))); --EXPECTF-- - -Warning: MessageFormatter::format(): msgfmt_format: not enough parameters in %s on line %d -bool(false) +string(5) "7 {1}" diff --git a/ext/intl/tests/msgfmt_format_error2.phpt b/ext/intl/tests/msgfmt_format_error2.phpt index 00b8542..85d1b1c 100644 --- a/ext/intl/tests/msgfmt_format_error2.phpt +++ b/ext/intl/tests/msgfmt_format_error2.phpt @@ -4,6 +4,8 @@ MessageFormatter::format() inconsistent types in named argument <?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php ini_set("intl.error_level", E_WARNING); diff --git a/ext/intl/tests/msgfmt_format_error3.phpt b/ext/intl/tests/msgfmt_format_error3.phpt index 98eebd7..6dfbee3 100644 --- a/ext/intl/tests/msgfmt_format_error3.phpt +++ b/ext/intl/tests/msgfmt_format_error3.phpt @@ -4,6 +4,8 @@ MessageFormatter::format() given negative arg key <?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php ini_set("intl.error_level", E_WARNING); diff --git a/ext/intl/tests/msgfmt_format_error4.phpt b/ext/intl/tests/msgfmt_format_error4.phpt index 5f4d006..3b92b48 100644 --- a/ext/intl/tests/msgfmt_format_error4.phpt +++ b/ext/intl/tests/msgfmt_format_error4.phpt @@ -4,6 +4,8 @@ MessageFormatter::format() invalid UTF-8 for arg key or value <?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php ini_set("intl.error_level", E_WARNING); diff --git a/ext/intl/tests/msgfmt_format_error5.phpt b/ext/intl/tests/msgfmt_format_error5.phpt index 951cd3f..0ea5169 100644 --- a/ext/intl/tests/msgfmt_format_error5.phpt +++ b/ext/intl/tests/msgfmt_format_error5.phpt @@ -4,6 +4,8 @@ MessageFormatter::format() invalid date/time argument <?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php ini_set("intl.error_level", E_WARNING); diff --git a/ext/intl/tests/msgfmt_format_error6.phpt b/ext/intl/tests/msgfmt_format_error6.phpt index aefed90..b07d2ab 100644 --- a/ext/intl/tests/msgfmt_format_error6.phpt +++ b/ext/intl/tests/msgfmt_format_error6.phpt @@ -4,6 +4,8 @@ MessageFormatter::format() invalid type for key not in pattern <?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php ini_set("intl.error_level", E_WARNING); diff --git a/ext/intl/tests/msgfmt_format_mixed_params.phpt b/ext/intl/tests/msgfmt_format_mixed_params.phpt index 3ab7688..93412f4 100644 --- a/ext/intl/tests/msgfmt_format_mixed_params.phpt +++ b/ext/intl/tests/msgfmt_format_mixed_params.phpt @@ -4,6 +4,8 @@ MessageFormatter::format(): mixed named and numeric parameters <?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php ini_set("intl.error_level", E_WARNING); diff --git a/ext/intl/tests/msgfmt_format_simple_types_numeric_strings.phpt b/ext/intl/tests/msgfmt_format_simple_types_numeric_strings.phpt index 39cf815..c52c359 100644 --- a/ext/intl/tests/msgfmt_format_simple_types_numeric_strings.phpt +++ b/ext/intl/tests/msgfmt_format_simple_types_numeric_strings.phpt @@ -4,6 +4,8 @@ MessageFormatter::format(): simple types handling with numeric strings <?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php ini_set("intl.error_level", E_WARNING); diff --git a/ext/intl/tests/msgfmt_format_subpatterns.phpt b/ext/intl/tests/msgfmt_format_subpatterns.phpt index ec7443f..9f11e3e 100644 --- a/ext/intl/tests/msgfmt_format_subpatterns.phpt +++ b/ext/intl/tests/msgfmt_format_subpatterns.phpt @@ -1,7 +1,11 @@ --TEST-- msgfmt_format() with subpatterns --SKIPIF-- -<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +<?php +if (!extension_loaded('intl')) + die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php @@ -45,7 +49,7 @@ $str_res = ''; $fmt = ut_msgfmt_create( 'en_US', $pattern ); if(!$fmt) { $str_res .= dump(intl_get_error_message())."\n"; - continue; + return $str_res; } foreach ($args as $arg) { $str_res .= dump( ut_msgfmt_format($fmt, $arg) ). "\n"; diff --git a/ext/intl/tests/msgfmt_format_subpatterns_named.phpt b/ext/intl/tests/msgfmt_format_subpatterns_named.phpt index 98a6e01..f6af025 100644 --- a/ext/intl/tests/msgfmt_format_subpatterns_named.phpt +++ b/ext/intl/tests/msgfmt_format_subpatterns_named.phpt @@ -1,7 +1,11 @@ --TEST-- msgfmt_format() with named subpatterns --SKIPIF-- -<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +<?php +if (!extension_loaded('intl')) + die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php @@ -45,7 +49,7 @@ $str_res = ''; $fmt = ut_msgfmt_create( 'en_US', $pattern ); if(!$fmt) { $str_res .= dump(intl_get_error_message())."\n"; - continue; + return $str_res; } foreach ($args as $arg) { $str_res .= dump( ut_msgfmt_format($fmt, $arg) ). "\n"; diff --git a/ext/intl/tests/msgfmt_get_error.phpt b/ext/intl/tests/msgfmt_get_error.phpt deleted file mode 100755 index 015c50d..0000000 --- a/ext/intl/tests/msgfmt_get_error.phpt +++ /dev/null @@ -1,29 +0,0 @@ ---TEST-- -msgmfmt_get_error_message/code() ---SKIPIF-- -<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> ---FILE-- -<?php - -/* - * Error handling. - */ - - -function ut_main() -{ - $fmt = ut_msgfmt_create( "en_US", "{0, number} monkeys on {1, number} trees" ); - $num = ut_msgfmt_format( $fmt, array()); - if( $num === false ) - return $fmt->getErrorMessage() . " (" . $fmt->getErrorCode() . ")\n"; - else - return "Ooops, an error should have occured."; -} - -include_once( 'ut_common.inc' ); - -// Run the test -ut_run(); -?> ---EXPECT-- -msgfmt_format: not enough parameters: U_ILLEGAL_ARGUMENT_ERROR (1)
diff --git a/ext/intl/msgformat/msgformat_helpers.cpp b/ext/intl/msgformat/msgformat_helpers.cpp index b13c4c4..42c5466 100755 --- a/ext/intl/msgformat/msgformat_helpers.cpp +++ b/ext/intl/msgformat/msgformat_helpers.cpp @@ -25,7 +25,6 @@ #include <limits.h> #include <unicode/msgfmt.h> #include <unicode/chariter.h> -#include <unicode/messagepattern.h> #include <unicode/ustdio.h> #include <vector> @@ -51,6 +50,10 @@ extern "C" { #define NAN (INFINITY-INFINITY) #endif +#if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 48 +#define HAS_MESSAGE_PATTERN 1 +#endif + U_NAMESPACE_BEGIN /** * This class isolates our access to private internal methods of @@ -61,17 +64,23 @@ class MessageFormatAdapter { public: static const Formattable::Type* getArgTypeList(const MessageFormat& m, int32_t& count); +#ifdef HAS_MESSAGE_PATTERN static const MessagePattern getMessagePattern(MessageFormat* m); +#endif }; + const Formattable::Type* MessageFormatAdapter::getArgTypeList(const MessageFormat& m, int32_t& count) { return m.getArgTypeList(count); } + +#ifdef HAS_MESSAGE_PATTERN const MessagePattern MessageFormatAdapter::getMessagePattern(MessageFormat* m) { return m->msgPattern; } +#endif U_NAMESPACE_END U_CFUNC int32_t umsg_format_arg_count(UMessageFormat *fmt) @@ -133,6 +142,52 @@ static double umsg_helper_zval_to_millis(zval *z, UErrorCode *status TSRMLS_DC) return rv; } +static HashTable *umsg_get_numeric_types(MessageFormatter_object *mfo, + intl_error& err TSRMLS_DC) +{ + HashTable *ret; + int32_t parts_count; + + if (U_FAILURE(err.code)) { + return NULL; + } + + if (mfo->mf_data.arg_types) { + /* already cached */ + return mfo->mf_data.arg_types; + } + + const Formattable::Type *types = MessageFormatAdapter::getArgTypeList( + *(MessageFormat*)mfo->mf_data.umsgf, parts_count); + + /* Hash table will store Formattable::Type objects directly, + * so no need for destructor */ + ALLOC_HASHTABLE(ret); + zend_hash_init(ret, parts_count, NULL, NULL, 0); + + for (int i = 0; i < parts_count; i++) { + const Formattable::Type t = types[i]; + if (zend_hash_index_update(ret, (ulong)i, (void*)&t, sizeof(t), NULL) + == FAILURE) { + intl_errors_set(&err, U_MEMORY_ALLOCATION_ERROR, + "Write to argument types hash table failed", 0 TSRMLS_CC); + break; + } + } + + if (U_FAILURE(err.code)) { + zend_hash_destroy(ret); + efree(ret); + + return NULL; + } + + mfo->mf_data.arg_types = ret; + + return ret; +} + +#ifdef HAS_MESSAGE_PATTERN static HashTable *umsg_parse_format(MessageFormatter_object *mfo, const MessagePattern& mp, intl_error& err TSRMLS_DC) @@ -144,6 +199,10 @@ static HashTable *umsg_parse_format(MessageFormatter_object *mfo, return NULL; } + if (!((MessageFormat *)mfo->mf_data.umsgf)->usesNamedArguments()) { + return umsg_get_numeric_types(mfo, err TSRMLS_CC); + } + if (mfo->mf_data.arg_types) { /* already cached */ return mfo->mf_data.arg_types; @@ -287,6 +346,27 @@ static HashTable *umsg_parse_format(MessageFormatter_object *mfo, return ret; } +#endif + +static HashTable *umsg_get_types(MessageFormatter_object *mfo, + intl_error& err TSRMLS_DC) +{ + MessageFormat *mf = (MessageFormat *)mfo->mf_data.umsgf; + +#ifdef HAS_MESSAGE_PATTERN + const MessagePattern mp = MessageFormatAdapter::getMessagePattern(mf); + + return umsg_parse_format(mfo, mp, err TSRMLS_CC); +#else + if (mf->usesNamedArguments()) { + intl_errors_set(&err, U_UNSUPPORTED_ERROR, + "This extension supports named arguments only on ICU 4.8+", + 0 TSRMLS_CC); + return NULL; + } + return umsg_get_numeric_types(mfo, err TSRMLS_CC); +#endif +} U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, HashTable *args, @@ -297,7 +377,6 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, std::vector<Formattable> fargs; std::vector<UnicodeString> farg_names; MessageFormat *mf = (MessageFormat *)mfo->mf_data.umsgf; - const MessagePattern mp = MessageFormatAdapter::getMessagePattern(mf); HashTable *types; intl_error& err = INTL_DATA_ERROR(mfo); @@ -305,11 +384,11 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, return; } + types = umsg_get_types(mfo, err TSRMLS_CC); + fargs.resize(arg_count); farg_names.resize(arg_count); - types = umsg_parse_format(mfo, mp, err TSRMLS_CC); - int argNum = 0; HashPosition pos; zval **elem; @@ -414,19 +493,56 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, formattable.setDouble(d); break; } + case Formattable::kLong: + { + int32_t tInt32; +retry_klong: + if (Z_TYPE_PP(elem) == IS_DOUBLE) { + if (Z_DVAL_PP(elem) > (double)INT32_MAX || + Z_DVAL_PP(elem) < (double)INT32_MIN) { + intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, + "Found PHP float with absolute value too large for " + "32 bit integer argument", 0 TSRMLS_CC); + } else { + tInt32 = (int32_t)Z_DVAL_PP(elem); + } + } else if (Z_TYPE_PP(elem) == IS_LONG) { + if (Z_LVAL_PP(elem) > INT32_MAX || + Z_LVAL_PP(elem) < INT32_MIN) { + intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, + "Found PHP integer with absolute value too large " + "for 32 bit integer argument", 0 TSRMLS_CC); + } else { + tInt32 = (int32_t)Z_LVAL_PP(elem); + } + } else { + SEPARATE_ZVAL_IF_NOT_REF(elem); + convert_scalar_to_number(*elem TSRMLS_CC); + goto retry_klong; + } + formattable.setLong(tInt32); + break; + } case Formattable::kInt64: { int64_t tInt64; +retry_kint64: if (Z_TYPE_PP(elem) == IS_DOUBLE) { - tInt64 = (int64_t)Z_DVAL_PP(elem); + if (Z_DVAL_PP(elem) > (double)U_INT64_MAX || + Z_DVAL_PP(elem) < (double)U_INT64_MIN) { + intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, + "Found PHP float with absolute value too large for " + "64 bit integer argument", 0 TSRMLS_CC); + } else { + tInt64 = (int64_t)Z_DVAL_PP(elem); + } } else if (Z_TYPE_PP(elem) == IS_LONG) { + /* assume long is not wider than 64 bits */ tInt64 = (int64_t)Z_LVAL_PP(elem); } else { SEPARATE_ZVAL_IF_NOT_REF(elem); convert_scalar_to_number(*elem TSRMLS_CC); - tInt64 = (Z_TYPE_PP(elem) == IS_DOUBLE) - ? (int64_t)Z_DVAL_PP(elem) - : Z_LVAL_PP(elem); + goto retry_kint64; } formattable.setInt64(tInt64); break; @@ -451,6 +567,10 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, formattable.setDate(dd); break; } + default: + intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, + "Found unsupported argument type", 0 TSRMLS_CC); + break; } } else { /* We couldn't find any information about the argument in the pattern, this diff --git a/ext/intl/tests/msgfmt_format_error1.phpt b/ext/intl/tests/msgfmt_format_error1.phpt index 09d022b..684b059 100644 --- a/ext/intl/tests/msgfmt_format_error1.phpt +++ b/ext/intl/tests/msgfmt_format_error1.phpt @@ -16,6 +16,4 @@ $mf = new MessageFormatter('en_US', $fmt); var_dump($mf->format(array(7))); --EXPECTF-- - -Warning: MessageFormatter::format(): msgfmt_format: not enough parameters in %s on line %d -bool(false) +string(5) "7 {1}" diff --git a/ext/intl/tests/msgfmt_format_error2.phpt b/ext/intl/tests/msgfmt_format_error2.phpt index 00b8542..85d1b1c 100644 --- a/ext/intl/tests/msgfmt_format_error2.phpt +++ b/ext/intl/tests/msgfmt_format_error2.phpt @@ -4,6 +4,8 @@ MessageFormatter::format() inconsistent types in named argument <?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php ini_set("intl.error_level", E_WARNING); diff --git a/ext/intl/tests/msgfmt_format_error3.phpt b/ext/intl/tests/msgfmt_format_error3.phpt index 98eebd7..6dfbee3 100644 --- a/ext/intl/tests/msgfmt_format_error3.phpt +++ b/ext/intl/tests/msgfmt_format_error3.phpt @@ -4,6 +4,8 @@ MessageFormatter::format() given negative arg key <?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php ini_set("intl.error_level", E_WARNING); diff --git a/ext/intl/tests/msgfmt_format_error4.phpt b/ext/intl/tests/msgfmt_format_error4.phpt index 5f4d006..3b92b48 100644 --- a/ext/intl/tests/msgfmt_format_error4.phpt +++ b/ext/intl/tests/msgfmt_format_error4.phpt @@ -4,6 +4,8 @@ MessageFormatter::format() invalid UTF-8 for arg key or value <?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php ini_set("intl.error_level", E_WARNING); diff --git a/ext/intl/tests/msgfmt_format_error5.phpt b/ext/intl/tests/msgfmt_format_error5.phpt index 951cd3f..0ea5169 100644 --- a/ext/intl/tests/msgfmt_format_error5.phpt +++ b/ext/intl/tests/msgfmt_format_error5.phpt @@ -4,6 +4,8 @@ MessageFormatter::format() invalid date/time argument <?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php ini_set("intl.error_level", E_WARNING); diff --git a/ext/intl/tests/msgfmt_format_error6.phpt b/ext/intl/tests/msgfmt_format_error6.phpt index aefed90..b07d2ab 100644 --- a/ext/intl/tests/msgfmt_format_error6.phpt +++ b/ext/intl/tests/msgfmt_format_error6.phpt @@ -4,6 +4,8 @@ MessageFormatter::format() invalid type for key not in pattern <?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php ini_set("intl.error_level", E_WARNING); diff --git a/ext/intl/tests/msgfmt_format_mixed_params.phpt b/ext/intl/tests/msgfmt_format_mixed_params.phpt index 3ab7688..93412f4 100644 --- a/ext/intl/tests/msgfmt_format_mixed_params.phpt +++ b/ext/intl/tests/msgfmt_format_mixed_params.phpt @@ -4,6 +4,8 @@ MessageFormatter::format(): mixed named and numeric parameters <?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php ini_set("intl.error_level", E_WARNING); diff --git a/ext/intl/tests/msgfmt_format_simple_types_numeric_strings.phpt b/ext/intl/tests/msgfmt_format_simple_types_numeric_strings.phpt index 39cf815..c52c359 100644 --- a/ext/intl/tests/msgfmt_format_simple_types_numeric_strings.phpt +++ b/ext/intl/tests/msgfmt_format_simple_types_numeric_strings.phpt @@ -4,6 +4,8 @@ MessageFormatter::format(): simple types handling with numeric strings <?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php ini_set("intl.error_level", E_WARNING); diff --git a/ext/intl/tests/msgfmt_format_subpatterns.phpt b/ext/intl/tests/msgfmt_format_subpatterns.phpt index ec7443f..9f11e3e 100644 --- a/ext/intl/tests/msgfmt_format_subpatterns.phpt +++ b/ext/intl/tests/msgfmt_format_subpatterns.phpt @@ -1,7 +1,11 @@ --TEST-- msgfmt_format() with subpatterns --SKIPIF-- -<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +<?php +if (!extension_loaded('intl')) + die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php @@ -45,7 +49,7 @@ $str_res = ''; $fmt = ut_msgfmt_create( 'en_US', $pattern ); if(!$fmt) { $str_res .= dump(intl_get_error_message())."\n"; - continue; + return $str_res; } foreach ($args as $arg) { $str_res .= dump( ut_msgfmt_format($fmt, $arg) ). "\n"; diff --git a/ext/intl/tests/msgfmt_format_subpatterns_named.phpt b/ext/intl/tests/msgfmt_format_subpatterns_named.phpt index 98a6e01..f6af025 100644 --- a/ext/intl/tests/msgfmt_format_subpatterns_named.phpt +++ b/ext/intl/tests/msgfmt_format_subpatterns_named.phpt @@ -1,7 +1,11 @@ --TEST-- msgfmt_format() with named subpatterns --SKIPIF-- -<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +<?php +if (!extension_loaded('intl')) + die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '4.8') < 0) + die('skip for ICU 4.8+'); --FILE-- <?php @@ -45,7 +49,7 @@ $str_res = ''; $fmt = ut_msgfmt_create( 'en_US', $pattern ); if(!$fmt) { $str_res .= dump(intl_get_error_message())."\n"; - continue; + return $str_res; } foreach ($args as $arg) { $str_res .= dump( ut_msgfmt_format($fmt, $arg) ). "\n"; diff --git a/ext/intl/tests/msgfmt_get_error.phpt b/ext/intl/tests/msgfmt_get_error.phpt deleted file mode 100755 index 015c50d..0000000 --- a/ext/intl/tests/msgfmt_get_error.phpt +++ /dev/null @@ -1,29 +0,0 @@ ---TEST-- -msgmfmt_get_error_message/code() ---SKIPIF-- -<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> ---FILE-- -<?php - -/* - * Error handling. - */ - - -function ut_main() -{ - $fmt = ut_msgfmt_create( "en_US", "{0, number} monkeys on {1, number} trees" ); - $num = ut_msgfmt_format( $fmt, array()); - if( $num === false ) - return $fmt->getErrorMessage() . " (" . $fmt->getErrorCode() . ")\n"; - else - return "Ooops, an error should have occured."; -} - -include_once( 'ut_common.inc' ); - -// Run the test -ut_run(); -?> ---EXPECT-- -msgfmt_format: not enough parameters: U_ILLEGAL_ARGUMENT_ERROR (1)