From 20dd5ccf19916a290973a2e25de4eed59b169093 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Sun, 6 May 2012 16:31:52 +0200 Subject: [PATCH] Cache arguments type info in MessageFormatter. --- ext/intl/msgformat/msgformat_attr.c | 6 +++++ ext/intl/msgformat/msgformat_data.c | 19 ++++++++++----- ext/intl/msgformat/msgformat_data.h | 1 + ext/intl/msgformat/msgformat_format.c | 2 +- ext/intl/msgformat/msgformat_helpers.cpp | 20 ++++++++++------ ext/intl/msgformat/msgformat_helpers.h | 2 +- ext/intl/tests/msgfmt_setPattern_cache.phpt | 26 +++++++++++++++++++++ 7 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 ext/intl/tests/msgfmt_setPattern_cache.phpt diff --git a/ext/intl/msgformat/msgformat_attr.c b/ext/intl/msgformat/msgformat_attr.c index cf34665142..c7a4d1c8cd 100755 --- a/ext/intl/msgformat/msgformat_attr.c +++ b/ext/intl/msgformat/msgformat_attr.c @@ -100,6 +100,12 @@ PHP_FUNCTION( msgfmt_set_pattern ) } mfo->mf_data.orig_format = estrndup(value, value_len); mfo->mf_data.orig_format_len = value_len; + /* invalidate cached format types */ + if (mfo->mf_data.arg_types) { + zend_hash_destroy(mfo->mf_data.arg_types); + efree(mfo->mf_data.arg_types); + mfo->mf_data.arg_types = NULL; + } RETURN_TRUE; } diff --git a/ext/intl/msgformat/msgformat_data.c b/ext/intl/msgformat/msgformat_data.c index 95e81d3ea7..9ed129f058 100755 --- a/ext/intl/msgformat/msgformat_data.c +++ b/ext/intl/msgformat/msgformat_data.c @@ -31,6 +31,7 @@ void msgformat_data_init( msgformat_data* mf_data TSRMLS_DC ) mf_data->umsgf = NULL; mf_data->orig_format = NULL; + mf_data->arg_types = NULL; intl_error_reset( &mf_data->error TSRMLS_CC ); } /* }}} */ @@ -38,21 +39,27 @@ void msgformat_data_init( msgformat_data* mf_data TSRMLS_DC ) /* {{{ void msgformat_data_free( msgformat_data* mf_data ) * Clean up memory allocated for msgformat_data */ -void msgformat_data_free( msgformat_data* mf_data TSRMLS_DC ) +void msgformat_data_free(msgformat_data* mf_data TSRMLS_DC) { - if( !mf_data ) + if (!mf_data) return; - if( mf_data->umsgf ) - umsg_close( mf_data->umsgf ); + if (mf_data->umsgf) + umsg_close(mf_data->umsgf); - if(mf_data->orig_format) { + if (mf_data->orig_format) { efree(mf_data->orig_format); mf_data->orig_format = NULL; } + if (mf_data->arg_types) { + zend_hash_destroy(mf_data->arg_types); + efree(mf_data->arg_types); + mf_data->arg_types = NULL; + } + mf_data->umsgf = NULL; - intl_error_reset( &mf_data->error TSRMLS_CC ); + intl_error_reset(&mf_data->error TSRMLS_CC); } /* }}} */ diff --git a/ext/intl/msgformat/msgformat_data.h b/ext/intl/msgformat/msgformat_data.h index 44001753b3..5a82003240 100755 --- a/ext/intl/msgformat/msgformat_data.h +++ b/ext/intl/msgformat/msgformat_data.h @@ -31,6 +31,7 @@ typedef struct { UMessageFormat* umsgf; char* orig_format; ulong orig_format_len; + HashTable* arg_types; } msgformat_data; msgformat_data* msgformat_data_create( TSRMLS_D ); diff --git a/ext/intl/msgformat/msgformat_format.c b/ext/intl/msgformat/msgformat_format.c index 099dbcb4b6..412a5f7b29 100755 --- a/ext/intl/msgformat/msgformat_format.c +++ b/ext/intl/msgformat/msgformat_format.c @@ -57,7 +57,7 @@ static void msgfmt_do_format(MessageFormatter_object *mfo, zval *args, zval *ret zend_hash_copy(args_copy, Z_ARRVAL_P(args), (copy_ctor_func_t)zval_add_ref, NULL, sizeof(zval*)); - umsg_format_helper(MSG_FORMAT_OBJECT(mfo), args_copy, + umsg_format_helper(mfo, args_copy, &formatted, &formatted_len, &INTL_DATA_ERROR_CODE(mfo) TSRMLS_CC); zend_hash_destroy(args_copy); diff --git a/ext/intl/msgformat/msgformat_helpers.cpp b/ext/intl/msgformat/msgformat_helpers.cpp index 503dca9ad9..1a7dc89c87 100755 --- a/ext/intl/msgformat/msgformat_helpers.cpp +++ b/ext/intl/msgformat/msgformat_helpers.cpp @@ -100,7 +100,9 @@ double umsg_helper_zval_to_millis(zval *z, UErrorCode *status TSRMLS_DC) { return rv; } -static HashTable *umsg_parse_format(const MessagePattern& mp, UErrorCode& uec) +static HashTable *umsg_parse_format(MessageFormatter_object *mfo, + const MessagePattern& mp, + UErrorCode& uec) { HashTable *ret; int32_t parts_count; @@ -109,6 +111,11 @@ static HashTable *umsg_parse_format(const MessagePattern& mp, UErrorCode& uec) return NULL; } + if (mfo->mf_data.arg_types) { + /* already cached */ + return mfo->mf_data.arg_types; + } + /* Hash table will store Formattable::Type objects directly, * so no need for destructor */ ALLOC_HASHTABLE(ret); @@ -235,22 +242,24 @@ static HashTable *umsg_parse_format(const MessagePattern& mp, UErrorCode& uec) return NULL; } + mfo->mf_data.arg_types = ret; + return ret; } -U_CFUNC void umsg_format_helper(UMessageFormat *fmt, HashTable *args, UChar **formatted, int *formatted_len, UErrorCode *status TSRMLS_DC) +U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, HashTable *args, UChar **formatted, int *formatted_len, UErrorCode *status TSRMLS_DC) { int arg_count = zend_hash_num_elements(args); std::vector fargs; std::vector farg_names; - MessageFormat *mf = (MessageFormat *) fmt; + MessageFormat *mf = (MessageFormat *)mfo->mf_data.umsgf; const MessagePattern mp = MessageFormatAdapter::getMessagePattern(mf); HashTable *types; fargs.resize(arg_count); farg_names.resize(arg_count); - types = umsg_parse_format(mp, *status); + types = umsg_parse_format(mfo, mp, *status); if (U_FAILURE(*status)) { return; } @@ -391,9 +400,6 @@ string_arg: //XXX: make function } } // visiting each argument - zend_hash_destroy(types); - efree(types); - if (U_FAILURE(*status)){ return; } diff --git a/ext/intl/msgformat/msgformat_helpers.h b/ext/intl/msgformat/msgformat_helpers.h index 4e10471e36..7a042480bf 100755 --- a/ext/intl/msgformat/msgformat_helpers.h +++ b/ext/intl/msgformat/msgformat_helpers.h @@ -18,7 +18,7 @@ #define MSG_FORMAT_HELPERS_H int32_t umsg_format_arg_count(UMessageFormat *fmt); -void umsg_format_helper(UMessageFormat *fmt, HashTable *args, +void umsg_format_helper(MessageFormatter_object *mfo, HashTable *args, UChar **formatted, int *formatted_len, UErrorCode *status TSRMLS_DC); void umsg_parse_helper(UMessageFormat *fmt, int *count, zval ***args, UChar *source, int source_len, UErrorCode *status); diff --git a/ext/intl/tests/msgfmt_setPattern_cache.phpt b/ext/intl/tests/msgfmt_setPattern_cache.phpt new file mode 100644 index 0000000000..35ec463c2a --- /dev/null +++ b/ext/intl/tests/msgfmt_setPattern_cache.phpt @@ -0,0 +1,26 @@ +--TEST-- +MessageFormatter::setPattern() invalidates arg types cache +--SKIPIF-- +format(array(1.3, 1.3))); +var_dump($mf->format(array(1.3, 1.3))); +$mf->setPattern("{0,ordinal} -- {1,number}"); +var_dump($mf->format(array(1.3, 1.3))); + +?> +==DONE== +--EXPECT-- +string(10) "1.3 -- 1st" +string(10) "1.3 -- 1st" +string(10) "1st -- 1.3" +==DONE== \ No newline at end of file -- 2.40.0