From 7d3a0e15f55e5e20b6dc3df76a4d9869756590d9 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Mon, 3 Jan 2011 03:58:57 +0000 Subject: [PATCH] Imlement clone for formatters that support it # also some test fixes, more to follow --- NEWS | 2 ++ ext/intl/collator/collator_class.c | 4 ++- ext/intl/dateformat/dateformat_class.c | 26 +++++++++++++- ext/intl/formatter/formatter_class.c | 31 +++++++++++++--- ext/intl/msgformat/msgformat_class.c | 26 +++++++++++++- .../resourcebundle/resourcebundle_class.c | 6 ++-- ext/intl/tests/dateformat_clone.phpt | 36 +++++++++++++++++++ .../tests/dateformat_get_set_pattern.phpt | 4 +-- ext/intl/tests/formatter_clone.phpt | 30 ++++++++++++++++ .../tests/formatter_get_set_attribute.phpt | 6 ++-- ext/intl/tests/msgfmt_clone.phpt | 30 ++++++++++++++++ ext/intl/tests/msgfmt_get_set_pattern.phpt | 8 ++--- 12 files changed, 190 insertions(+), 19 deletions(-) create mode 100755 ext/intl/tests/dateformat_clone.phpt create mode 100755 ext/intl/tests/formatter_clone.phpt create mode 100755 ext/intl/tests/msgfmt_clone.phpt diff --git a/NEWS b/NEWS index 1e0e36a347..67be574e39 100644 --- a/NEWS +++ b/NEWS @@ -38,6 +38,8 @@ (Felipe) . Fixed bug #53612 (Segmentation fault when using cloned several intl objects). (Gustavo) + . Implemented clone functionality for number, date & message formatters. + (Stas). - MySQL Improved extension: . Fixed bug #53503 (mysqli::query returns false after successful LOAD DATA diff --git a/ext/intl/collator/collator_class.c b/ext/intl/collator/collator_class.c index 021099c15e..58a11fe46d 100755 --- a/ext/intl/collator/collator_class.c +++ b/ext/intl/collator/collator_class.c @@ -145,7 +145,9 @@ void collator_register_Collator_class( TSRMLS_D ) memcpy(&Collator_handlers, zend_get_std_object_handlers(), sizeof Collator_handlers); - Collator_handlers.clone_obj = NULL; + /* Collator has no usable clone semantics - ucol_cloneBinary/ucol_openBinary require binary buffer + for which we don't have the place to keep */ + Collator_handlers.clone_obj = NULL; /* Declare 'Collator' class properties. */ if( !Collator_ce_ptr ) diff --git a/ext/intl/dateformat/dateformat_class.c b/ext/intl/dateformat/dateformat_class.c index ab9ad190cb..74c193bc0e 100755 --- a/ext/intl/dateformat/dateformat_class.c +++ b/ext/intl/dateformat/dateformat_class.c @@ -80,6 +80,30 @@ zend_object_value IntlDateFormatter_object_create(zend_class_entry *ce TSRMLS_DC } /* }}} */ +/* {{{ IntlDateFormatter_object_clone */ +zend_object_value IntlDateFormatter_object_clone(zval *object TSRMLS_DC) +{ + zend_object_value new_obj_val; + zend_object_handle handle = Z_OBJ_HANDLE_P(object); + IntlDateFormatter_object *dfo, *new_dfo; + + DATE_FORMAT_METHOD_FETCH_OBJECT; + new_obj_val = IntlDateFormatter_ce_ptr->create_object(IntlDateFormatter_ce_ptr TSRMLS_CC); + new_dfo = (IntlDateFormatter_object *)zend_object_store_get_object_by_handle(new_obj_val.handle TSRMLS_CC); + /* clone standard parts */ + zend_objects_clone_members(&new_dfo->zo, new_obj_val, &dfo->zo, handle TSRMLS_CC); + /* clone formatter object */ + DATE_FORMAT_OBJECT(new_dfo) = udat_clone(DATE_FORMAT_OBJECT(dfo), &INTL_DATA_ERROR_CODE(new_dfo)); + if(U_FAILURE(INTL_DATA_ERROR_CODE(new_dfo))) { + /* set up error in case error handler is interested */ + intl_error_set( NULL, INTL_DATA_ERROR_CODE(new_dfo), "Failed to clone IntlDateFormatter object", 0 TSRMLS_CC ); + IntlDateFormatter_object_dtor(new_dfo, new_obj_val.handle TSRMLS_CC); /* free new object */ + zend_error(E_ERROR, "Failed to clone IntlDateFormatter object"); + } + return new_obj_val; +} +/* }}} */ + /* * 'IntlDateFormatter' class registration structures & functions */ @@ -164,7 +188,7 @@ void dateformat_register_IntlDateFormatter_class( TSRMLS_D ) memcpy(&IntlDateFormatter_handlers, zend_get_std_object_handlers(), sizeof IntlDateFormatter_handlers); - IntlDateFormatter_handlers.clone_obj = NULL; + IntlDateFormatter_handlers.clone_obj = IntlDateFormatter_object_clone; /* Declare 'IntlDateFormatter' class properties. */ if( !IntlDateFormatter_ce_ptr ) diff --git a/ext/intl/formatter/formatter_class.c b/ext/intl/formatter/formatter_class.c index 69f3b88714..07d07b64c2 100755 --- a/ext/intl/formatter/formatter_class.c +++ b/ext/intl/formatter/formatter_class.c @@ -54,8 +54,7 @@ void NumberFormatter_object_free( zend_object *object TSRMLS_DC ) /* }}} */ /* {{{ NumberFormatter_object_create */ -zend_object_value NumberFormatter_object_create( - zend_class_entry *ce TSRMLS_DC ) +zend_object_value NumberFormatter_object_create(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; NumberFormatter_object* intern; @@ -76,6 +75,30 @@ zend_object_value NumberFormatter_object_create( } /* }}} */ +/* {{{ NumberFormatter_object_clone */ +zend_object_value NumberFormatter_object_clone(zval *object TSRMLS_DC) +{ + zend_object_value new_obj_val; + zend_object_handle handle = Z_OBJ_HANDLE_P(object); + NumberFormatter_object *nfo, *new_nfo; + + FORMATTER_METHOD_FETCH_OBJECT; + new_obj_val = NumberFormatter_ce_ptr->create_object(NumberFormatter_ce_ptr TSRMLS_CC); + new_nfo = (NumberFormatter_object *)zend_object_store_get_object_by_handle(new_obj_val.handle TSRMLS_CC); + /* clone standard parts */ + zend_objects_clone_members(&new_nfo->zo, new_obj_val, &nfo->zo, handle TSRMLS_CC); + /* clone formatter object */ + FORMATTER_OBJECT(new_nfo) = unum_clone(FORMATTER_OBJECT(nfo), &INTL_DATA_ERROR_CODE(new_nfo)); + if(U_FAILURE(INTL_DATA_ERROR_CODE(new_nfo))) { + /* set up error in case error handler is interested */ + intl_error_set( NULL, INTL_DATA_ERROR_CODE(new_nfo), "Failed to clone NumberFormatter object", 0 TSRMLS_CC ); + NumberFormatter_object_dtor(new_nfo, new_obj_val.handle TSRMLS_CC); /* free new object */ + zend_error(E_ERROR, "Failed to clone NumberFormatter object"); + } + return new_obj_val; +} +/* }}} */ + /* * 'NumberFormatter' class registration structures & functions */ @@ -173,8 +196,8 @@ void formatter_register_class( TSRMLS_D ) NumberFormatter_ce_ptr = zend_register_internal_class( &ce TSRMLS_CC ); memcpy(&NumberFormatter_handlers, zend_get_std_object_handlers(), - sizeof NumberFormatter_handlers); - NumberFormatter_handlers.clone_obj = NULL; + sizeof(NumberFormatter_handlers)); + NumberFormatter_handlers.clone_obj = NumberFormatter_object_clone; /* Declare 'NumberFormatter' class properties. */ if( !NumberFormatter_ce_ptr ) diff --git a/ext/intl/msgformat/msgformat_class.c b/ext/intl/msgformat/msgformat_class.c index efa3a411a3..bd291291ee 100755 --- a/ext/intl/msgformat/msgformat_class.c +++ b/ext/intl/msgformat/msgformat_class.c @@ -73,6 +73,30 @@ zend_object_value MessageFormatter_object_create(zend_class_entry *ce TSRMLS_DC) } /* }}} */ +/* {{{ MessageFormatter_object_clone */ +zend_object_value MessageFormatter_object_clone(zval *object TSRMLS_DC) +{ + zend_object_value new_obj_val; + zend_object_handle handle = Z_OBJ_HANDLE_P(object); + MessageFormatter_object *mfo, *new_mfo; + + MSG_FORMAT_METHOD_FETCH_OBJECT; + new_obj_val = MessageFormatter_ce_ptr->create_object(MessageFormatter_ce_ptr TSRMLS_CC); + new_mfo = (MessageFormatter_object *)zend_object_store_get_object_by_handle(new_obj_val.handle TSRMLS_CC); + /* clone standard parts */ + zend_objects_clone_members(&new_mfo->zo, new_obj_val, &mfo->zo, handle TSRMLS_CC); + /* clone formatter object */ + MSG_FORMAT_OBJECT(new_mfo) = umsg_clone(MSG_FORMAT_OBJECT(mfo), &INTL_DATA_ERROR_CODE(new_mfo)); + if(U_FAILURE(INTL_DATA_ERROR_CODE(new_mfo))) { + /* set up error in case error handler is interested */ + intl_error_set( NULL, INTL_DATA_ERROR_CODE(new_mfo), "Failed to clone MessageFormatter object", 0 TSRMLS_CC ); + MessageFormatter_object_dtor(new_mfo, new_obj_val.handle TSRMLS_CC); /* free new object */ + zend_error(E_ERROR, "Failed to clone MessageFormatter object"); + } + return new_obj_val; +} +/* }}} */ + /* * 'MessageFormatter' class registration structures & functions */ @@ -138,7 +162,7 @@ void msgformat_register_class( TSRMLS_D ) memcpy(&MessageFormatter_handlers, zend_get_std_object_handlers(), sizeof MessageFormatter_handlers); - MessageFormatter_handlers.clone_obj = NULL; + MessageFormatter_handlers.clone_obj = MessageFormatter_object_clone; /* Declare 'MessageFormatter' class properties. */ if( !MessageFormatter_ce_ptr ) diff --git a/ext/intl/resourcebundle/resourcebundle_class.c b/ext/intl/resourcebundle/resourcebundle_class.c index 9242b57f2f..a8a4bf1c86 100644 --- a/ext/intl/resourcebundle/resourcebundle_class.c +++ b/ext/intl/resourcebundle/resourcebundle_class.c @@ -109,7 +109,7 @@ static void resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS) if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING || INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) { intl_errors_set_code( NULL, INTL_DATA_ERROR_CODE(rb) TSRMLS_CC ); spprintf( &pbuf, 0, "resourcebundle_ctor: Cannot load libICU resource '%s' without fallback from %s to %s", - bundlename, locale, ures_getLocale( rb->me, &INTL_DATA_ERROR_CODE(rb)) ); + bundlename, locale, ures_getLocaleByType( rb->me, ULOC_ACTUAL_LOCALE, &INTL_DATA_ERROR_CODE(rb)) ); intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 TSRMLS_CC ); efree(pbuf); zval_dtor( return_value ); @@ -187,7 +187,7 @@ static void resourcebundle_array_fetch(zval *object, zval *offset, zval *return_ if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING || INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) { UErrorCode icuerror; - const char * locale = ures_getLocale( rb->me, &icuerror ); + const char * locale = ures_getLocaleByType( rb->me, ULOC_ACTUAL_LOCALE, &icuerror ); if (is_numeric) { spprintf( &pbuf, 0, "Cannot load element %d without fallback from to %s", meindex, locale ); } else { @@ -420,7 +420,7 @@ void resourcebundle_register_class( TSRMLS_D ) } ResourceBundle_object_handlers = std_object_handlers; - ResourceBundle_object_handlers.clone_obj = NULL; + ResourceBundle_object_handlers.clone_obj = NULL; /* ICU ResourceBundle has no clone implementation */ ResourceBundle_object_handlers.read_dimension = resourcebundle_array_get; ResourceBundle_object_handlers.count_elements = resourcebundle_array_count; } diff --git a/ext/intl/tests/dateformat_clone.phpt b/ext/intl/tests/dateformat_clone.phpt new file mode 100755 index 0000000000..886a98f17a --- /dev/null +++ b/ext/intl/tests/dateformat_clone.phpt @@ -0,0 +1,36 @@ +--TEST-- +Cloning datefmt +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Result of formatting timestamp=0 is : +31-12-69 +Result of formatting timestamp=0 is : +1969-365.07:00:00 EST +Result of clone formatting timestamp=0 is : +31-12-69 diff --git a/ext/intl/tests/dateformat_get_set_pattern.phpt b/ext/intl/tests/dateformat_get_set_pattern.phpt index b0d02dc0b4..6489232509 100755 --- a/ext/intl/tests/dateformat_get_set_pattern.phpt +++ b/ext/intl/tests/dateformat_get_set_pattern.phpt @@ -58,12 +58,12 @@ ut_run(); Creating IntlDateFormatter with pattern = dd-MM-YY After call to get_pattern : pattern= dd-MM-YY Result of formatting timestamp=0 is : -31-12-70 +31-12-69 ------------------- Setting IntlDateFormatter with pattern = DD-MM-YYYY hh:mm:ss After call to get_pattern : pattern= DD-MM-YYYY hh:mm:ss Result of formatting timestamp=0 with the new pattern is : -365-12-1970 07:00:00 +365-12-1969 07:00:00 ------------------- Setting IntlDateFormatter with pattern = yyyy-DDD.hh:mm:ss z diff --git a/ext/intl/tests/formatter_clone.phpt b/ext/intl/tests/formatter_clone.phpt new file mode 100755 index 0000000000..4e8d096244 --- /dev/null +++ b/ext/intl/tests/formatter_clone.phpt @@ -0,0 +1,30 @@ +--TEST-- +Cloning numfmt +--SKIPIF-- + +--FILE-- +setPattern("0.0" ); +if( $res === false ) + $res_str .= ut_nfmt_get_error_message( $fmt ) . " (" . ut_nfmt_get_error_code( $fmt ) . ")\n"; + +$res_str .= "Formatted number: " . ut_nfmt_format( $fmt, $test_value ) . "\n"; +$res_str .= "Formatted(clone) number: " . ut_nfmt_format( $fmt_clone, $test_value ) . "\n"; +echo $res_str; + +?> +--EXPECTF-- +Formatted number: 12345.123456 +Formatted number: 12345.1 +Formatted(clone) number: 12345.123456 diff --git a/ext/intl/tests/formatter_get_set_attribute.phpt b/ext/intl/tests/formatter_get_set_attribute.phpt index c523346841..95a2643439 100755 --- a/ext/intl/tests/formatter_get_set_attribute.phpt +++ b/ext/intl/tests/formatter_get_set_attribute.phpt @@ -25,7 +25,7 @@ function ut_main() 'FRACTION_DIGITS' => array( NumberFormatter::FRACTION_DIGITS, 5, 12345.123456 ), 'MULTIPLIER' => array( NumberFormatter::MULTIPLIER, 2, 12345.123456 ), 'GROUPING_SIZE' => array( NumberFormatter::GROUPING_SIZE, 2, 12345.123456 ), - 'ROUNDING_MODE' => array( NumberFormatter::ROUNDING_MODE, 7, 12345.123456 ), + 'ROUNDING_MODE' => array( NumberFormatter::ROUNDING_MODE, 1, 12345.123456 ), 'ROUNDING_INCREMENT' => array( NumberFormatter::ROUNDING_INCREMENT, (float)2, 12345.123456 ), 'FORMAT_WIDTH' => array( NumberFormatter::FORMAT_WIDTH, 27, 12345.123456 ), 'PADDING_POSITION' => array( NumberFormatter::PADDING_POSITION, 21, 12345.123456 ), @@ -155,10 +155,10 @@ New attribute value: 2 ; Format result: '0,01,23,45.12346' ; Parse result: 1234 Attribute ROUNDING_MODE Old attribute value: 4 ; Format result: '0,012,345.12346' ; Parse result: 12345.12346 Setting attribute: ok -New attribute value: 7 ; Format result: '0,012,345.12346' ; Parse result: 12345.12346 +New attribute value: 1 ; Format result: '0,012,345.12345' ; Parse result: 12345.12345 Attribute ROUNDING_INCREMENT -Old attribute value: 0 ; Format result: '0,012,345.12346' ; Parse result: 12345.12346 +Old attribute value: 1.0E-5 ; Format result: '0,012,345.12346' ; Parse result: 12345.12346 Setting attribute: ok New attribute value: 2 ; Format result: '0,012,346.00000' ; Parse result: 12346 diff --git a/ext/intl/tests/msgfmt_clone.phpt b/ext/intl/tests/msgfmt_clone.phpt new file mode 100755 index 0000000000..9d8ea64442 --- /dev/null +++ b/ext/intl/tests/msgfmt_clone.phpt @@ -0,0 +1,30 @@ +--TEST-- +Cloning msgfmt +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Formatting result: 123 monkeys on 456 trees +Formatting result: 123 trees hosting 456 monkeys +Formatting clone result: 123 monkeys on 456 trees diff --git a/ext/intl/tests/msgfmt_get_set_pattern.phpt b/ext/intl/tests/msgfmt_get_set_pattern.phpt index dd6fb5fa2e..67b1aca459 100755 --- a/ext/intl/tests/msgfmt_get_set_pattern.phpt +++ b/ext/intl/tests/msgfmt_get_set_pattern.phpt @@ -30,11 +30,11 @@ function ut_main() if( $res === false ) $res_str .= ut_msgfmt_get_error_message( $fmt ) . " (" . ut_msgfmt_get_error_code( $fmt ) . ")\n"; $res_str .= "New pattern: '" . ut_msgfmt_get_pattern( $fmt ) . "'\n"; - $res_str .= "Formatted number: " . ut_msgfmt_format( $fmt, array(123, 456) ) . "\n"; + $res_str .= "Formatted message: " . ut_msgfmt_format( $fmt, array(123, 456) ) . "\n"; ut_msgfmt_set_pattern($fmt, str_repeat($pattern, 10)); $res_str .= "New pattern: '" . ut_msgfmt_get_pattern( $fmt ) . "'\n"; - $res_str .= "Formatted number: " . ut_msgfmt_format( $fmt, array(123, 456) ) . "\n"; + $res_str .= "Formatted message: " . ut_msgfmt_format( $fmt, array(123, 456) ) . "\n"; return $res_str; @@ -48,6 +48,6 @@ ut_run(); Default pattern: '{0,number} monkeys on {1,number} trees' Formatting result: 123 monkeys on 456 trees New pattern: '{0,number} trees hosting {1,number} monkeys' -Formatted number: 123 trees hosting 456 monkeys +Formatted message: 123 trees hosting 456 monkeys New pattern: '{0,number} trees hosting {1,number} monkeys{0,number} trees hosting {1,number} monkeys{0,number} trees hosting {1,number} monkeys{0,number} trees hosting {1,number} monkeys{0,number} trees hosting {1,number} monkeys{0,number} trees hosting {1,number} monkeys{0,number} trees hosting {1,number} monkeys{0,number} trees hosting {1,number} monkeys{0,number} trees hosting {1,number} monkeys{0,number} trees hosting {1,number} monkeys' -Formatted number: 123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys +Formatted message: 123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys123 trees hosting 456 monkeys -- 2.40.0