Skip to content

Commit 7d3a0e1

Browse files
committed
Imlement clone for formatters that support it
# also some test fixes, more to follow
1 parent b059dfa commit 7d3a0e1

12 files changed

+190
-19
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
(Felipe)
3939
. Fixed bug #53612 (Segmentation fault when using cloned several intl
4040
objects). (Gustavo)
41+
. Implemented clone functionality for number, date & message formatters.
42+
(Stas).
4143

4244
- MySQL Improved extension:
4345
. Fixed bug #53503 (mysqli::query returns false after successful LOAD DATA

ext/intl/collator/collator_class.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,9 @@ void collator_register_Collator_class( TSRMLS_D )
145145

146146
memcpy(&Collator_handlers, zend_get_std_object_handlers(),
147147
sizeof Collator_handlers);
148-
Collator_handlers.clone_obj = NULL;
148+
/* Collator has no usable clone semantics - ucol_cloneBinary/ucol_openBinary require binary buffer
149+
for which we don't have the place to keep */
150+
Collator_handlers.clone_obj = NULL;
149151

150152
/* Declare 'Collator' class properties. */
151153
if( !Collator_ce_ptr )

ext/intl/dateformat/dateformat_class.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,30 @@ zend_object_value IntlDateFormatter_object_create(zend_class_entry *ce TSRMLS_DC
8080
}
8181
/* }}} */
8282

83+
/* {{{ IntlDateFormatter_object_clone */
84+
zend_object_value IntlDateFormatter_object_clone(zval *object TSRMLS_DC)
85+
{
86+
zend_object_value new_obj_val;
87+
zend_object_handle handle = Z_OBJ_HANDLE_P(object);
88+
IntlDateFormatter_object *dfo, *new_dfo;
89+
90+
DATE_FORMAT_METHOD_FETCH_OBJECT;
91+
new_obj_val = IntlDateFormatter_ce_ptr->create_object(IntlDateFormatter_ce_ptr TSRMLS_CC);
92+
new_dfo = (IntlDateFormatter_object *)zend_object_store_get_object_by_handle(new_obj_val.handle TSRMLS_CC);
93+
/* clone standard parts */
94+
zend_objects_clone_members(&new_dfo->zo, new_obj_val, &dfo->zo, handle TSRMLS_CC);
95+
/* clone formatter object */
96+
DATE_FORMAT_OBJECT(new_dfo) = udat_clone(DATE_FORMAT_OBJECT(dfo), &INTL_DATA_ERROR_CODE(new_dfo));
97+
if(U_FAILURE(INTL_DATA_ERROR_CODE(new_dfo))) {
98+
/* set up error in case error handler is interested */
99+
intl_error_set( NULL, INTL_DATA_ERROR_CODE(new_dfo), "Failed to clone IntlDateFormatter object", 0 TSRMLS_CC );
100+
IntlDateFormatter_object_dtor(new_dfo, new_obj_val.handle TSRMLS_CC); /* free new object */
101+
zend_error(E_ERROR, "Failed to clone IntlDateFormatter object");
102+
}
103+
return new_obj_val;
104+
}
105+
/* }}} */
106+
83107
/*
84108
* 'IntlDateFormatter' class registration structures & functions
85109
*/
@@ -164,7 +188,7 @@ void dateformat_register_IntlDateFormatter_class( TSRMLS_D )
164188

165189
memcpy(&IntlDateFormatter_handlers, zend_get_std_object_handlers(),
166190
sizeof IntlDateFormatter_handlers);
167-
IntlDateFormatter_handlers.clone_obj = NULL;
191+
IntlDateFormatter_handlers.clone_obj = IntlDateFormatter_object_clone;
168192

169193
/* Declare 'IntlDateFormatter' class properties. */
170194
if( !IntlDateFormatter_ce_ptr )

ext/intl/formatter/formatter_class.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ void NumberFormatter_object_free( zend_object *object TSRMLS_DC )
5454
/* }}} */
5555

5656
/* {{{ NumberFormatter_object_create */
57-
zend_object_value NumberFormatter_object_create(
58-
zend_class_entry *ce TSRMLS_DC )
57+
zend_object_value NumberFormatter_object_create(zend_class_entry *ce TSRMLS_DC)
5958
{
6059
zend_object_value retval;
6160
NumberFormatter_object* intern;
@@ -76,6 +75,30 @@ zend_object_value NumberFormatter_object_create(
7675
}
7776
/* }}} */
7877

78+
/* {{{ NumberFormatter_object_clone */
79+
zend_object_value NumberFormatter_object_clone(zval *object TSRMLS_DC)
80+
{
81+
zend_object_value new_obj_val;
82+
zend_object_handle handle = Z_OBJ_HANDLE_P(object);
83+
NumberFormatter_object *nfo, *new_nfo;
84+
85+
FORMATTER_METHOD_FETCH_OBJECT;
86+
new_obj_val = NumberFormatter_ce_ptr->create_object(NumberFormatter_ce_ptr TSRMLS_CC);
87+
new_nfo = (NumberFormatter_object *)zend_object_store_get_object_by_handle(new_obj_val.handle TSRMLS_CC);
88+
/* clone standard parts */
89+
zend_objects_clone_members(&new_nfo->zo, new_obj_val, &nfo->zo, handle TSRMLS_CC);
90+
/* clone formatter object */
91+
FORMATTER_OBJECT(new_nfo) = unum_clone(FORMATTER_OBJECT(nfo), &INTL_DATA_ERROR_CODE(new_nfo));
92+
if(U_FAILURE(INTL_DATA_ERROR_CODE(new_nfo))) {
93+
/* set up error in case error handler is interested */
94+
intl_error_set( NULL, INTL_DATA_ERROR_CODE(new_nfo), "Failed to clone NumberFormatter object", 0 TSRMLS_CC );
95+
NumberFormatter_object_dtor(new_nfo, new_obj_val.handle TSRMLS_CC); /* free new object */
96+
zend_error(E_ERROR, "Failed to clone NumberFormatter object");
97+
}
98+
return new_obj_val;
99+
}
100+
/* }}} */
101+
79102
/*
80103
* 'NumberFormatter' class registration structures & functions
81104
*/
@@ -173,8 +196,8 @@ void formatter_register_class( TSRMLS_D )
173196
NumberFormatter_ce_ptr = zend_register_internal_class( &ce TSRMLS_CC );
174197

175198
memcpy(&NumberFormatter_handlers, zend_get_std_object_handlers(),
176-
sizeof NumberFormatter_handlers);
177-
NumberFormatter_handlers.clone_obj = NULL;
199+
sizeof(NumberFormatter_handlers));
200+
NumberFormatter_handlers.clone_obj = NumberFormatter_object_clone;
178201

179202
/* Declare 'NumberFormatter' class properties. */
180203
if( !NumberFormatter_ce_ptr )

ext/intl/msgformat/msgformat_class.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,30 @@ zend_object_value MessageFormatter_object_create(zend_class_entry *ce TSRMLS_DC)
7373
}
7474
/* }}} */
7575

76+
/* {{{ MessageFormatter_object_clone */
77+
zend_object_value MessageFormatter_object_clone(zval *object TSRMLS_DC)
78+
{
79+
zend_object_value new_obj_val;
80+
zend_object_handle handle = Z_OBJ_HANDLE_P(object);
81+
MessageFormatter_object *mfo, *new_mfo;
82+
83+
MSG_FORMAT_METHOD_FETCH_OBJECT;
84+
new_obj_val = MessageFormatter_ce_ptr->create_object(MessageFormatter_ce_ptr TSRMLS_CC);
85+
new_mfo = (MessageFormatter_object *)zend_object_store_get_object_by_handle(new_obj_val.handle TSRMLS_CC);
86+
/* clone standard parts */
87+
zend_objects_clone_members(&new_mfo->zo, new_obj_val, &mfo->zo, handle TSRMLS_CC);
88+
/* clone formatter object */
89+
MSG_FORMAT_OBJECT(new_mfo) = umsg_clone(MSG_FORMAT_OBJECT(mfo), &INTL_DATA_ERROR_CODE(new_mfo));
90+
if(U_FAILURE(INTL_DATA_ERROR_CODE(new_mfo))) {
91+
/* set up error in case error handler is interested */
92+
intl_error_set( NULL, INTL_DATA_ERROR_CODE(new_mfo), "Failed to clone MessageFormatter object", 0 TSRMLS_CC );
93+
MessageFormatter_object_dtor(new_mfo, new_obj_val.handle TSRMLS_CC); /* free new object */
94+
zend_error(E_ERROR, "Failed to clone MessageFormatter object");
95+
}
96+
return new_obj_val;
97+
}
98+
/* }}} */
99+
76100
/*
77101
* 'MessageFormatter' class registration structures & functions
78102
*/
@@ -138,7 +162,7 @@ void msgformat_register_class( TSRMLS_D )
138162

139163
memcpy(&MessageFormatter_handlers, zend_get_std_object_handlers(),
140164
sizeof MessageFormatter_handlers);
141-
MessageFormatter_handlers.clone_obj = NULL;
165+
MessageFormatter_handlers.clone_obj = MessageFormatter_object_clone;
142166

143167
/* Declare 'MessageFormatter' class properties. */
144168
if( !MessageFormatter_ce_ptr )

ext/intl/resourcebundle/resourcebundle_class.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ static void resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS)
109109
if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING || INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) {
110110
intl_errors_set_code( NULL, INTL_DATA_ERROR_CODE(rb) TSRMLS_CC );
111111
spprintf( &pbuf, 0, "resourcebundle_ctor: Cannot load libICU resource '%s' without fallback from %s to %s",
112-
bundlename, locale, ures_getLocale( rb->me, &INTL_DATA_ERROR_CODE(rb)) );
112+
bundlename, locale, ures_getLocaleByType( rb->me, ULOC_ACTUAL_LOCALE, &INTL_DATA_ERROR_CODE(rb)) );
113113
intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 TSRMLS_CC );
114114
efree(pbuf);
115115
zval_dtor( return_value );
@@ -187,7 +187,7 @@ static void resourcebundle_array_fetch(zval *object, zval *offset, zval *return_
187187

188188
if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING || INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) {
189189
UErrorCode icuerror;
190-
const char * locale = ures_getLocale( rb->me, &icuerror );
190+
const char * locale = ures_getLocaleByType( rb->me, ULOC_ACTUAL_LOCALE, &icuerror );
191191
if (is_numeric) {
192192
spprintf( &pbuf, 0, "Cannot load element %d without fallback from to %s", meindex, locale );
193193
} else {
@@ -420,7 +420,7 @@ void resourcebundle_register_class( TSRMLS_D )
420420
}
421421

422422
ResourceBundle_object_handlers = std_object_handlers;
423-
ResourceBundle_object_handlers.clone_obj = NULL;
423+
ResourceBundle_object_handlers.clone_obj = NULL; /* ICU ResourceBundle has no clone implementation */
424424
ResourceBundle_object_handlers.read_dimension = resourcebundle_array_get;
425425
ResourceBundle_object_handlers.count_elements = resourcebundle_array_count;
426426
}

ext/intl/tests/dateformat_clone.phpt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
Cloning datefmt
3+
--SKIPIF--
4+
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
5+
--FILE--
6+
<?php
7+
include_once( 'ut_common.inc' );
8+
$GLOBALS['oo-mode'] = true;
9+
$res_str = '';
10+
/*
11+
* Clone
12+
*/
13+
$start_pattern = 'dd-MM-YY';
14+
$fmt = ut_datefmt_create( "en-US", IntlDateFormatter::FULL, IntlDateFormatter::FULL, 'America/New_York', IntlDateFormatter::GREGORIAN , $start_pattern );
15+
16+
$formatted = ut_datefmt_format($fmt,0);
17+
$res_str .= "\nResult of formatting timestamp=0 is : \n$formatted";
18+
19+
$fmt_clone = clone $fmt;
20+
ut_datefmt_set_pattern( $fmt , 'yyyy-DDD.hh:mm:ss z' );
21+
22+
$formatted = ut_datefmt_format($fmt,0);
23+
$res_str .= "\nResult of formatting timestamp=0 is : \n$formatted";
24+
$formatted = ut_datefmt_format($fmt_clone,0);
25+
$res_str .= "\nResult of clone formatting timestamp=0 is : \n$formatted";
26+
27+
echo $res_str;
28+
29+
?>
30+
--EXPECTF--
31+
Result of formatting timestamp=0 is :
32+
31-12-69
33+
Result of formatting timestamp=0 is :
34+
1969-365.07:00:00 EST
35+
Result of clone formatting timestamp=0 is :
36+
31-12-69

ext/intl/tests/dateformat_get_set_pattern.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@ ut_run();
5858
Creating IntlDateFormatter with pattern = dd-MM-YY
5959
After call to get_pattern : pattern= dd-MM-YY
6060
Result of formatting timestamp=0 is :
61-
31-12-70
61+
31-12-69
6262
-------------------
6363
Setting IntlDateFormatter with pattern = DD-MM-YYYY hh:mm:ss
6464
After call to get_pattern : pattern= DD-MM-YYYY hh:mm:ss
6565
Result of formatting timestamp=0 with the new pattern is :
66-
365-12-1970 07:00:00
66+
365-12-1969 07:00:00
6767

6868
-------------------
6969
Setting IntlDateFormatter with pattern = yyyy-DDD.hh:mm:ss z

ext/intl/tests/formatter_clone.phpt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
Cloning numfmt
3+
--SKIPIF--
4+
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
5+
--FILE--
6+
<?php
7+
include_once( 'ut_common.inc' );
8+
$GLOBALS['oo-mode'] = true;
9+
$res_str = '';
10+
/*
11+
* Clone
12+
*/
13+
$test_value = 12345.123456;
14+
$fmt = new NumberFormatter( "en_US", NumberFormatter::PATTERN_DECIMAL );
15+
$res_str .= "Formatted number: " . ut_nfmt_format( $fmt, $test_value ) . "\n";
16+
$fmt_clone = clone $fmt;
17+
18+
$res = $fmt->setPattern("0.0" );
19+
if( $res === false )
20+
$res_str .= ut_nfmt_get_error_message( $fmt ) . " (" . ut_nfmt_get_error_code( $fmt ) . ")\n";
21+
22+
$res_str .= "Formatted number: " . ut_nfmt_format( $fmt, $test_value ) . "\n";
23+
$res_str .= "Formatted(clone) number: " . ut_nfmt_format( $fmt_clone, $test_value ) . "\n";
24+
echo $res_str;
25+
26+
?>
27+
--EXPECTF--
28+
Formatted number: 12345.123456
29+
Formatted number: 12345.1
30+
Formatted(clone) number: 12345.123456

ext/intl/tests/formatter_get_set_attribute.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function ut_main()
2525
'FRACTION_DIGITS' => array( NumberFormatter::FRACTION_DIGITS, 5, 12345.123456 ),
2626
'MULTIPLIER' => array( NumberFormatter::MULTIPLIER, 2, 12345.123456 ),
2727
'GROUPING_SIZE' => array( NumberFormatter::GROUPING_SIZE, 2, 12345.123456 ),
28-
'ROUNDING_MODE' => array( NumberFormatter::ROUNDING_MODE, 7, 12345.123456 ),
28+
'ROUNDING_MODE' => array( NumberFormatter::ROUNDING_MODE, 1, 12345.123456 ),
2929
'ROUNDING_INCREMENT' => array( NumberFormatter::ROUNDING_INCREMENT, (float)2, 12345.123456 ),
3030
'FORMAT_WIDTH' => array( NumberFormatter::FORMAT_WIDTH, 27, 12345.123456 ),
3131
'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
155155
Attribute ROUNDING_MODE
156156
Old attribute value: 4 ; Format result: '0,012,345.12346' ; Parse result: 12345.12346
157157
Setting attribute: ok
158-
New attribute value: 7 ; Format result: '0,012,345.12346' ; Parse result: 12345.12346
158+
New attribute value: 1 ; Format result: '0,012,345.12345' ; Parse result: 12345.12345
159159

160160
Attribute ROUNDING_INCREMENT
161-
Old attribute value: 0 ; Format result: '0,012,345.12346' ; Parse result: 12345.12346
161+
Old attribute value: 1.0E-5 ; Format result: '0,012,345.12346' ; Parse result: 12345.12346
162162
Setting attribute: ok
163163
New attribute value: 2 ; Format result: '0,012,346.00000' ; Parse result: 12346
164164

0 commit comments

Comments
 (0)