]> granicus.if.org Git - php/commitdiff
Imlement clone for formatters that support it
authorStanislav Malyshev <stas@php.net>
Mon, 3 Jan 2011 03:58:57 +0000 (03:58 +0000)
committerStanislav Malyshev <stas@php.net>
Mon, 3 Jan 2011 03:58:57 +0000 (03:58 +0000)
# also some test fixes, more to follow

12 files changed:
NEWS
ext/intl/collator/collator_class.c
ext/intl/dateformat/dateformat_class.c
ext/intl/formatter/formatter_class.c
ext/intl/msgformat/msgformat_class.c
ext/intl/resourcebundle/resourcebundle_class.c
ext/intl/tests/dateformat_clone.phpt [new file with mode: 0755]
ext/intl/tests/dateformat_get_set_pattern.phpt
ext/intl/tests/formatter_clone.phpt [new file with mode: 0755]
ext/intl/tests/formatter_get_set_attribute.phpt
ext/intl/tests/msgfmt_clone.phpt [new file with mode: 0755]
ext/intl/tests/msgfmt_get_set_pattern.phpt

diff --git a/NEWS b/NEWS
index 1e0e36a3473620fbfbefb6d1f394833503b0169b..67be574e399f24f2cd31b94e664f4fa749058165 100644 (file)
--- 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 
index 021099c15ee7dba3f3309248d24af7a6042bf66e..58a11fe46dd4877240ae18730a2e12776b0630ad 100755 (executable)
@@ -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 )
index ab9ad190cbee96e7c0a12cc6d8c75768d6da8653..74c193bc0e86c5dd70006cb312a4b1573c52dc7f 100755 (executable)
@@ -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 )
index 69f3b8871455b033e449a237934451590ed4b4ee..07d07b64c2889b88905405537e790373ab9ae183 100755 (executable)
@@ -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 )
index efa3a411a34e59d9cf3e1c8f183753bfa8fd296c..bd291291eedd19ad02172ba40d1e8f4691ccb555 100755 (executable)
@@ -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 )
index 9242b57f2ff92687a120f249c5a40b5775ce1658..a8a4bf1c86be0ab7bd2ed467d7e9e36d6b54d8b8 100644 (file)
@@ -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 (executable)
index 0000000..886a98f
--- /dev/null
@@ -0,0 +1,36 @@
+--TEST--
+Cloning datefmt
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+include_once( 'ut_common.inc' );
+$GLOBALS['oo-mode'] = true;
+$res_str = '';
+/*
+ * Clone
+ */
+$start_pattern = 'dd-MM-YY';
+$fmt = ut_datefmt_create( "en-US",  IntlDateFormatter::FULL, IntlDateFormatter::FULL, 'America/New_York', IntlDateFormatter::GREGORIAN , $start_pattern );
+
+$formatted = ut_datefmt_format($fmt,0);
+$res_str .= "\nResult of formatting timestamp=0 is :  \n$formatted";
+
+$fmt_clone = clone $fmt;
+ut_datefmt_set_pattern( $fmt , 'yyyy-DDD.hh:mm:ss z' );
+
+$formatted = ut_datefmt_format($fmt,0);
+$res_str .= "\nResult of formatting timestamp=0 is :  \n$formatted";
+$formatted = ut_datefmt_format($fmt_clone,0);
+$res_str .= "\nResult of clone formatting timestamp=0 is :  \n$formatted";
+
+echo $res_str;
+
+?>
+--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
index b0d02dc0b4596359c7fb9fb1efb80a1476425384..648923250905ec59c4de29c230be39589a8fd7d9 100755 (executable)
@@ -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 (executable)
index 0000000..4e8d096
--- /dev/null
@@ -0,0 +1,30 @@
+--TEST--
+Cloning numfmt
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+include_once( 'ut_common.inc' );
+$GLOBALS['oo-mode'] = true;
+$res_str = '';
+/*
+ * Clone
+ */
+$test_value = 12345.123456;
+$fmt = new NumberFormatter( "en_US", NumberFormatter::PATTERN_DECIMAL );
+$res_str .= "Formatted number: " . ut_nfmt_format( $fmt, $test_value ) . "\n";
+$fmt_clone = clone $fmt;
+
+$res = $fmt->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
index c52334684143654fe4e7ca4e99070438cb305c96..95a2643439b49e4645879915d6351e72918adcf7 100755 (executable)
@@ -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 (executable)
index 0000000..9d8ea64
--- /dev/null
@@ -0,0 +1,30 @@
+--TEST--
+Cloning msgfmt
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+include_once( 'ut_common.inc' );
+$GLOBALS['oo-mode'] = true;
+$res_str = '';
+/*
+ * Clone
+ */
+$fmt = ut_msgfmt_create( "en_US", "{0,number} monkeys on {1,number} trees" );
+
+// Get default patten.
+$res_str .= "Formatting result: " . ut_msgfmt_format( $fmt, array(123, 456) ) . "\n";
+$fmt_clone = clone $fmt;
+// Set a new pattern.
+$pattern = "{0,number} trees hosting {1,number} monkeys";
+$res = ut_msgfmt_set_pattern( $fmt, $pattern );
+$res_str .= "Formatting result: " . ut_msgfmt_format( $fmt, array(123, 456) ) . "\n";
+$res_str .= "Formatting clone result: " . ut_msgfmt_format( $fmt_clone, array(123, 456) ) . "\n";
+
+echo $res_str;
+
+?>
+--EXPECTF--
+Formatting result: 123 monkeys on 456 trees
+Formatting result: 123 trees hosting 456 monkeys
+Formatting clone result: 123 monkeys on 456 trees
index dd6fb5fa2ef7e6afa0f5e49bf411b01c44ec7bd8..67b1aca459856e1806e21e9367dcc41b5442a6ba 100755 (executable)
@@ -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