diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2013-03-14 05:42:27 +0000 |
---|---|---|
committer | <> | 2013-04-03 16:25:08 +0000 |
commit | c4dd7a1a684490673e25aaf4fabec5df138854c4 (patch) | |
tree | 4d57c44caae4480efff02b90b9be86f44bf25409 /ext/intl/formatter | |
download | php2-master.tar.gz |
Imported from /home/lorry/working-area/delta_php2/php-5.4.13.tar.bz2.HEADphp-5.4.13master
Diffstat (limited to 'ext/intl/formatter')
-rw-r--r-- | ext/intl/formatter/formatter.c | 152 | ||||
-rw-r--r-- | ext/intl/formatter/formatter.h | 24 | ||||
-rw-r--r-- | ext/intl/formatter/formatter_attr.c | 459 | ||||
-rw-r--r-- | ext/intl/formatter/formatter_attr.h | 32 | ||||
-rw-r--r-- | ext/intl/formatter/formatter_class.c | 226 | ||||
-rw-r--r-- | ext/intl/formatter/formatter_class.h | 50 | ||||
-rw-r--r-- | ext/intl/formatter/formatter_data.c | 72 | ||||
-rw-r--r-- | ext/intl/formatter/formatter_data.h | 38 | ||||
-rw-r--r-- | ext/intl/formatter/formatter_format.c | 204 | ||||
-rw-r--r-- | ext/intl/formatter/formatter_format.h | 31 | ||||
-rw-r--r-- | ext/intl/formatter/formatter_main.c | 156 | ||||
-rw-r--r-- | ext/intl/formatter/formatter_main.h | 27 | ||||
-rw-r--r-- | ext/intl/formatter/formatter_parse.c | 187 | ||||
-rw-r--r-- | ext/intl/formatter/formatter_parse.h | 25 |
14 files changed, 1683 insertions, 0 deletions
diff --git a/ext/intl/formatter/formatter.c b/ext/intl/formatter/formatter.c new file mode 100644 index 0000000..1b7922c --- /dev/null +++ b/ext/intl/formatter/formatter.c @@ -0,0 +1,152 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Stanislav Malyshev <stas@zend.com> | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unicode/utypes.h> +#include <unicode/unum.h> +#include <unicode/ustring.h> + +#include "php_intl.h" +#include "formatter_class.h" +#include "formatter_format.h" + +#if U_ICU_VERSION_MAJOR_NUM == 3 && U_ICU_VERSION_MINOR_NUM <= 4 +#define UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL 17 +#endif + +/* {{{ formatter_register_constants + * Register constants common for the both (OO and procedural) + * APIs. + */ +void formatter_register_constants( INIT_FUNC_ARGS ) +{ + if( NumberFormatter_ce_ptr == NULL) { + zend_error(E_ERROR, "NumberFormatter class not defined"); + } + + #define FORMATTER_EXPOSE_CONST(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS) + #define FORMATTER_EXPOSE_CLASS_CONST(x) zend_declare_class_constant_long( NumberFormatter_ce_ptr, ZEND_STRS( #x ) - 1, UNUM_##x TSRMLS_CC ); + #define FORMATTER_EXPOSE_CUSTOM_CLASS_CONST(name, value) zend_declare_class_constant_long( NumberFormatter_ce_ptr, ZEND_STRS( name ) - 1, value TSRMLS_CC ); + + /* UNumberFormatStyle constants */ + FORMATTER_EXPOSE_CLASS_CONST( PATTERN_DECIMAL ); + FORMATTER_EXPOSE_CLASS_CONST( DECIMAL ); + FORMATTER_EXPOSE_CLASS_CONST( CURRENCY ); + FORMATTER_EXPOSE_CLASS_CONST( PERCENT ); + FORMATTER_EXPOSE_CLASS_CONST( SCIENTIFIC ); + FORMATTER_EXPOSE_CLASS_CONST( SPELLOUT ); + FORMATTER_EXPOSE_CLASS_CONST( ORDINAL ); + FORMATTER_EXPOSE_CLASS_CONST( DURATION ); + FORMATTER_EXPOSE_CLASS_CONST( PATTERN_RULEBASED ); + FORMATTER_EXPOSE_CLASS_CONST( IGNORE ); + + FORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "DEFAULT_STYLE", UNUM_DEFAULT ); + +/* workaround for ICU bug */ +#if U_ICU_VERSION_MAJOR_NUM == 3 && U_ICU_VERSION_MINOR_NUM < 8 +#define UNUM_ROUND_HALFEVEN UNUM_FOUND_HALFEVEN +#endif + + /* UNumberFormatRoundingMode */ + FORMATTER_EXPOSE_CLASS_CONST( ROUND_CEILING ); + FORMATTER_EXPOSE_CLASS_CONST( ROUND_FLOOR ); + FORMATTER_EXPOSE_CLASS_CONST( ROUND_DOWN ); + FORMATTER_EXPOSE_CLASS_CONST( ROUND_UP ); + FORMATTER_EXPOSE_CLASS_CONST( ROUND_HALFEVEN ); + FORMATTER_EXPOSE_CLASS_CONST( ROUND_HALFDOWN ); + FORMATTER_EXPOSE_CLASS_CONST( ROUND_HALFUP ); + + /* UNumberFormatPadPosition */ + FORMATTER_EXPOSE_CLASS_CONST( PAD_BEFORE_PREFIX ); + FORMATTER_EXPOSE_CLASS_CONST( PAD_AFTER_PREFIX ); + FORMATTER_EXPOSE_CLASS_CONST( PAD_BEFORE_SUFFIX ); + FORMATTER_EXPOSE_CLASS_CONST( PAD_AFTER_SUFFIX ); + + /* UNumberFormatAttribute */ + FORMATTER_EXPOSE_CLASS_CONST( PARSE_INT_ONLY ); + FORMATTER_EXPOSE_CLASS_CONST( GROUPING_USED ); + FORMATTER_EXPOSE_CLASS_CONST( DECIMAL_ALWAYS_SHOWN ); + FORMATTER_EXPOSE_CLASS_CONST( MAX_INTEGER_DIGITS ); + FORMATTER_EXPOSE_CLASS_CONST( MIN_INTEGER_DIGITS ); + FORMATTER_EXPOSE_CLASS_CONST( INTEGER_DIGITS ); + FORMATTER_EXPOSE_CLASS_CONST( MAX_FRACTION_DIGITS ); + FORMATTER_EXPOSE_CLASS_CONST( MIN_FRACTION_DIGITS ); + FORMATTER_EXPOSE_CLASS_CONST( FRACTION_DIGITS ); + FORMATTER_EXPOSE_CLASS_CONST( MULTIPLIER ); + FORMATTER_EXPOSE_CLASS_CONST( GROUPING_SIZE ); + FORMATTER_EXPOSE_CLASS_CONST( ROUNDING_MODE ); + FORMATTER_EXPOSE_CLASS_CONST( ROUNDING_INCREMENT ); + FORMATTER_EXPOSE_CLASS_CONST( FORMAT_WIDTH ); + FORMATTER_EXPOSE_CLASS_CONST( PADDING_POSITION ); + FORMATTER_EXPOSE_CLASS_CONST( SECONDARY_GROUPING_SIZE ); + FORMATTER_EXPOSE_CLASS_CONST( SIGNIFICANT_DIGITS_USED ); + FORMATTER_EXPOSE_CLASS_CONST( MIN_SIGNIFICANT_DIGITS ); + FORMATTER_EXPOSE_CLASS_CONST( MAX_SIGNIFICANT_DIGITS ); + FORMATTER_EXPOSE_CLASS_CONST( LENIENT_PARSE ); + + /* UNumberFormatTextAttribute */ + FORMATTER_EXPOSE_CLASS_CONST( POSITIVE_PREFIX ); + FORMATTER_EXPOSE_CLASS_CONST( POSITIVE_SUFFIX ); + FORMATTER_EXPOSE_CLASS_CONST( NEGATIVE_PREFIX ); + FORMATTER_EXPOSE_CLASS_CONST( NEGATIVE_SUFFIX ); + FORMATTER_EXPOSE_CLASS_CONST( PADDING_CHARACTER ); + FORMATTER_EXPOSE_CLASS_CONST( CURRENCY_CODE ); + FORMATTER_EXPOSE_CLASS_CONST( DEFAULT_RULESET ); + FORMATTER_EXPOSE_CLASS_CONST( PUBLIC_RULESETS ); + + /* UNumberFormatSymbol */ + FORMATTER_EXPOSE_CLASS_CONST( DECIMAL_SEPARATOR_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( GROUPING_SEPARATOR_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( PATTERN_SEPARATOR_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( PERCENT_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( ZERO_DIGIT_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( DIGIT_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( MINUS_SIGN_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( PLUS_SIGN_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( CURRENCY_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( INTL_CURRENCY_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( MONETARY_SEPARATOR_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( EXPONENTIAL_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( PERMILL_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( PAD_ESCAPE_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( INFINITY_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( NAN_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( SIGNIFICANT_DIGIT_SYMBOL ); + FORMATTER_EXPOSE_CLASS_CONST( MONETARY_GROUPING_SEPARATOR_SYMBOL ); + + FORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "TYPE_DEFAULT", FORMAT_TYPE_DEFAULT ); + FORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "TYPE_INT32", FORMAT_TYPE_INT32 ); + FORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "TYPE_INT64", FORMAT_TYPE_INT64 ); + FORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "TYPE_DOUBLE", FORMAT_TYPE_DOUBLE ); + FORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "TYPE_CURRENCY", FORMAT_TYPE_CURRENCY ); + + #undef FORMATTER_EXPOSE_CUSTOM_CLASS_CONST + #undef FORMATTER_EXPOSE_CLASS_CONST + #undef FORMATTER_EXPOSE_CONST +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/formatter/formatter.h b/ext/intl/formatter/formatter.h new file mode 100644 index 0000000..1f9ebea --- /dev/null +++ b/ext/intl/formatter/formatter.h @@ -0,0 +1,24 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Stanislav Malyshev <stas@zend.com> | + +----------------------------------------------------------------------+ + */ + +#ifndef FORMATTER_FORMATTER_H +#define FORMATTER_FORMATTER_H + +#include <php.h> + +void formatter_register_constants( INIT_FUNC_ARGS ); + +#endif // FORMATTER_FORMATTER_H diff --git a/ext/intl/formatter/formatter_attr.c b/ext/intl/formatter/formatter_attr.c new file mode 100644 index 0000000..448a9db --- /dev/null +++ b/ext/intl/formatter/formatter_attr.c @@ -0,0 +1,459 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Stanislav Malyshev <stas@zend.com> | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php_intl.h" +#include "formatter_class.h" +#include "formatter_attr.h" +#include "intl_convert.h" + +#include <unicode/ustring.h> + +/* {{{ proto mixed NumberFormatter::getAttribute( int $attr ) + * Get formatter attribute value. }}} */ +/* {{{ proto mixed numfmt_get_attribute( NumberFormatter $nf, int $attr ) + * Get formatter attribute value. + */ +PHP_FUNCTION( numfmt_get_attribute ) +{ + long attribute, value; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", + &object, NumberFormatter_ce_ptr, &attribute ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "numfmt_get_attribute: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + switch(attribute) { + case UNUM_PARSE_INT_ONLY: + case UNUM_GROUPING_USED: + case UNUM_DECIMAL_ALWAYS_SHOWN: + case UNUM_MAX_INTEGER_DIGITS: + case UNUM_MIN_INTEGER_DIGITS: + case UNUM_INTEGER_DIGITS: + case UNUM_MAX_FRACTION_DIGITS: + case UNUM_MIN_FRACTION_DIGITS: + case UNUM_FRACTION_DIGITS: + case UNUM_MULTIPLIER: + case UNUM_GROUPING_SIZE: + case UNUM_ROUNDING_MODE: + case UNUM_FORMAT_WIDTH: + case UNUM_PADDING_POSITION: + case UNUM_SECONDARY_GROUPING_SIZE: + case UNUM_SIGNIFICANT_DIGITS_USED: + case UNUM_MIN_SIGNIFICANT_DIGITS: + case UNUM_MAX_SIGNIFICANT_DIGITS: + case UNUM_LENIENT_PARSE: + value = unum_getAttribute(FORMATTER_OBJECT(nfo), attribute); + if(value == -1) { + INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR; + } else { + RETVAL_LONG(value); + } + break; + case UNUM_ROUNDING_INCREMENT: + { + double value_double = unum_getDoubleAttribute(FORMATTER_OBJECT(nfo), attribute); + if(value_double == -1) { + INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR; + } else { + RETVAL_DOUBLE(value_double); + } + } + break; + default: + INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR; + break; + } + + INTL_METHOD_CHECK_STATUS( nfo, "Error getting attribute value" ); +} +/* }}} */ + +/* {{{ proto string NumberFormatter::getTextAttribute( int $attr ) + * Get formatter attribute value. }}} */ +/* {{{ proto string numfmt_get_text_attribute( NumberFormatter $nf, int $attr ) + * Get formatter attribute value. + */ +PHP_FUNCTION( numfmt_get_text_attribute ) +{ + long attribute; + UChar value_buf[64]; + int value_buf_size = USIZE( value_buf ); + UChar* value = value_buf; + int length = 0; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", + &object, NumberFormatter_ce_ptr, &attribute ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "numfmt_get_text_attribute: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + length = unum_getTextAttribute( FORMATTER_OBJECT(nfo), attribute, value, value_buf_size, &INTL_DATA_ERROR_CODE(nfo) ); + if(INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR && length >= value_buf_size) { + ++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */ + INTL_DATA_ERROR_CODE(nfo) = U_ZERO_ERROR; + value = eumalloc(length); + length = unum_getTextAttribute( FORMATTER_OBJECT(nfo), attribute, value, length, &INTL_DATA_ERROR_CODE(nfo) ); + if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) { + efree(value); + value = value_buf; + } + } + INTL_METHOD_CHECK_STATUS( nfo, "Error getting attribute value" ); + + INTL_METHOD_RETVAL_UTF8( nfo, value, length, ( value != value_buf ) ); +} +/* }}} */ + +/* {{{ proto bool NumberFormatter::setAttribute( int $attr, mixed $value ) + * Get formatter attribute value. }}} */ +/* {{{ proto bool numfmt_set_attribute( NumberFormatter $nf, int $attr, mixed $value ) + * Get formatter attribute value. + */ +PHP_FUNCTION( numfmt_set_attribute ) +{ + long attribute; + zval **value; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OlZ", + &object, NumberFormatter_ce_ptr, &attribute, &value ) == FAILURE) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "numfmt_set_attribute: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + switch(attribute) { + case UNUM_PARSE_INT_ONLY: + case UNUM_GROUPING_USED: + case UNUM_DECIMAL_ALWAYS_SHOWN: + case UNUM_MAX_INTEGER_DIGITS: + case UNUM_MIN_INTEGER_DIGITS: + case UNUM_INTEGER_DIGITS: + case UNUM_MAX_FRACTION_DIGITS: + case UNUM_MIN_FRACTION_DIGITS: + case UNUM_FRACTION_DIGITS: + case UNUM_MULTIPLIER: + case UNUM_GROUPING_SIZE: + case UNUM_ROUNDING_MODE: + case UNUM_FORMAT_WIDTH: + case UNUM_PADDING_POSITION: + case UNUM_SECONDARY_GROUPING_SIZE: + case UNUM_SIGNIFICANT_DIGITS_USED: + case UNUM_MIN_SIGNIFICANT_DIGITS: + case UNUM_MAX_SIGNIFICANT_DIGITS: + case UNUM_LENIENT_PARSE: + convert_to_long_ex(value); + unum_setAttribute(FORMATTER_OBJECT(nfo), attribute, Z_LVAL_PP(value)); + break; + case UNUM_ROUNDING_INCREMENT: + convert_to_double_ex(value); + unum_setDoubleAttribute(FORMATTER_OBJECT(nfo), attribute, Z_DVAL_PP(value)); + break; + default: + INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR; + break; + } + + INTL_METHOD_CHECK_STATUS( nfo, "Error setting attribute value" ); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto bool NumberFormatter::setTextAttribute( int $attr, string $value ) + * Get formatter attribute value. }}} */ +/* {{{ proto bool numfmt_set_text_attribute( NumberFormatter $nf, int $attr, string $value ) + * Get formatter attribute value. + */ +PHP_FUNCTION( numfmt_set_text_attribute ) +{ + int slength = 0; + UChar *svalue = NULL; + long attribute; + char *value; + int len; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ols", + &object, NumberFormatter_ce_ptr, &attribute, &value, &len ) == FAILURE) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "numfmt_set_text_attribute: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + /* Convert given attribute value to UTF-16. */ + intl_convert_utf8_to_utf16(&svalue, &slength, value, len, &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "Error converting attribute value to UTF-16" ); + + /* Actually set new attribute value. */ + unum_setTextAttribute(FORMATTER_OBJECT(nfo), attribute, svalue, slength, &INTL_DATA_ERROR_CODE(nfo)); + if (svalue) { + efree(svalue); + } + INTL_METHOD_CHECK_STATUS( nfo, "Error setting text attribute" ); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto string NumberFormatter::getSymbol( int $attr ) + * Get formatter symbol value. }}} */ +/* {{{ proto string numfmt_get_symbol( NumberFormatter $nf, int $attr ) + * Get formatter symbol value. + */ +PHP_FUNCTION( numfmt_get_symbol ) +{ + long symbol; + UChar value_buf[4]; + UChar *value = value_buf; + int length = USIZE(value_buf); + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", + &object, NumberFormatter_ce_ptr, &symbol ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "numfmt_get_symbol: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + if(symbol >= UNUM_FORMAT_SYMBOL_COUNT || symbol < 0) { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "numfmt_get_symbol: invalid symbol value", 0 TSRMLS_CC ); + RETURN_FALSE; + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + length = unum_getSymbol(FORMATTER_OBJECT(nfo), symbol, value_buf, length, &INTL_DATA_ERROR_CODE(nfo)); + if(INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR && length >= USIZE( value_buf )) { + ++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */ + INTL_DATA_ERROR_CODE(nfo) = U_ZERO_ERROR; + value = eumalloc(length); + length = unum_getSymbol(FORMATTER_OBJECT(nfo), symbol, value, length, &INTL_DATA_ERROR_CODE(nfo)); + if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) { + efree(value); + value = value_buf; + } + } + INTL_METHOD_CHECK_STATUS( nfo, "Error getting symbol value" ); + + INTL_METHOD_RETVAL_UTF8( nfo, value, length, ( value_buf != value ) ); +} +/* }}} */ + +/* {{{ proto bool NumberFormatter::setSymbol( int $attr, string $symbol ) + * Set formatter symbol value. }}} */ +/* {{{ proto bool numfmt_set_symbol( NumberFormatter $nf, int $attr, string $symbol ) + * Set formatter symbol value. + */ +PHP_FUNCTION( numfmt_set_symbol ) +{ + long symbol; + char* value = NULL; + int value_len = 0; + UChar* svalue = 0; + int slength = 0; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ols", + &object, NumberFormatter_ce_ptr, &symbol, &value, &value_len ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "numfmt_set_symbol: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + if (symbol >= UNUM_FORMAT_SYMBOL_COUNT || symbol < 0) { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "numfmt_set_symbol: invalid symbol value", 0 TSRMLS_CC ); + RETURN_FALSE; + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + /* Convert given symbol to UTF-16. */ + intl_convert_utf8_to_utf16(&svalue, &slength, value, value_len, &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "Error converting symbol value to UTF-16" ); + + /* Actually set the symbol. */ + unum_setSymbol(FORMATTER_OBJECT(nfo), symbol, svalue, slength, &INTL_DATA_ERROR_CODE(nfo)); + if (svalue) { + efree(svalue); + } + INTL_METHOD_CHECK_STATUS( nfo, "Error setting symbol value" ); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto string NumberFormatter::getPattern( ) + * Get formatter pattern. }}} */ +/* {{{ proto string numfmt_get_pattern( NumberFormatter $nf ) + * Get formatter pattern. + */ +PHP_FUNCTION( numfmt_get_pattern ) +{ + UChar value_buf[64]; + int length = USIZE( value_buf ); + UChar* value = value_buf; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, NumberFormatter_ce_ptr ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "numfmt_get_pattern: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + length = unum_toPattern(FORMATTER_OBJECT(nfo), 0, value, length, &INTL_DATA_ERROR_CODE(nfo)); + if(INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR && length >= USIZE( value_buf )) { + ++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */ + INTL_DATA_ERROR_CODE(nfo) = U_ZERO_ERROR; + value = eumalloc(length); + length = unum_toPattern( FORMATTER_OBJECT(nfo), 0, value, length, &INTL_DATA_ERROR_CODE(nfo) ); + if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) { + efree(value); + value = value_buf; + } + } + INTL_METHOD_CHECK_STATUS( nfo, "Error getting formatter pattern" ); + + INTL_METHOD_RETVAL_UTF8( nfo, value, length, ( value != value_buf ) ); +} +/* }}} */ + +/* {{{ proto bool NumberFormatter::setPattern( string $pattern ) + * Set formatter pattern. }}} */ +/* {{{ proto bool numfmt_set_pattern( NumberFormatter $nf, string $pattern ) + * Set formatter pattern. + */ +PHP_FUNCTION( numfmt_set_pattern ) +{ + char* value = NULL; + int value_len = 0; + int slength = 0; + UChar* svalue = NULL; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", + &object, NumberFormatter_ce_ptr, &value, &value_len ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "numfmt_set_pattern: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + FORMATTER_METHOD_FETCH_OBJECT; + + /* Convert given pattern to UTF-16. */ + intl_convert_utf8_to_utf16(&svalue, &slength, value, value_len, &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "Error converting pattern to UTF-16" ); + + /* TODO: add parse error information */ + unum_applyPattern(FORMATTER_OBJECT(nfo), 0, svalue, slength, NULL, &INTL_DATA_ERROR_CODE(nfo)); + if (svalue) { + efree(svalue); + } + INTL_METHOD_CHECK_STATUS( nfo, "Error setting pattern value" ); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto string NumberFormatter::getLocale([int type]) + * Get formatter locale. }}} */ +/* {{{ proto string numfmt_get_locale( NumberFormatter $nf[, int type] ) + * Get formatter locale. + */ +PHP_FUNCTION( numfmt_get_locale ) +{ + long type = ULOC_ACTUAL_LOCALE; + char* loc; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l", + &object, NumberFormatter_ce_ptr, &type ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "numfmt_get_locale: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + loc = (char *)unum_getLocaleByType(FORMATTER_OBJECT(nfo), type, &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "Error getting locale" ); + RETURN_STRING(loc, 1); +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/formatter/formatter_attr.h b/ext/intl/formatter/formatter_attr.h new file mode 100644 index 0000000..c4bc94c --- /dev/null +++ b/ext/intl/formatter/formatter_attr.h @@ -0,0 +1,32 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Stanislav Malyshev <stas@zend.com> | + +----------------------------------------------------------------------+ + */ + +#ifndef FORMATTER_ATTR_H +#define FORMATTER_ATTR_H + +#include <php.h> + +PHP_FUNCTION( numfmt_set_attribute ); +PHP_FUNCTION( numfmt_get_attribute ); +PHP_FUNCTION( numfmt_set_text_attribute ); +PHP_FUNCTION( numfmt_get_text_attribute ); +PHP_FUNCTION( numfmt_set_symbol ); +PHP_FUNCTION( numfmt_get_symbol ); +PHP_FUNCTION( numfmt_set_pattern ); +PHP_FUNCTION( numfmt_get_pattern ); +PHP_FUNCTION( numfmt_get_locale ); + +#endif // FORMATTER_ATTR_H diff --git a/ext/intl/formatter/formatter_class.c b/ext/intl/formatter/formatter_class.c new file mode 100644 index 0000000..2246cd2 --- /dev/null +++ b/ext/intl/formatter/formatter_class.c @@ -0,0 +1,226 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Stanislav Malyshev <stas@zend.com> | + +----------------------------------------------------------------------+ + */ + +#include <unicode/unum.h> + +#include "formatter_class.h" +#include "php_intl.h" +#include "formatter_data.h" +#include "formatter_format.h" +#include "formatter_parse.h" +#include "formatter_main.h" +#include "formatter_attr.h" + +#include <zend_exceptions.h> + +zend_class_entry *NumberFormatter_ce_ptr = NULL; +static zend_object_handlers NumberFormatter_handlers; + +/* + * Auxiliary functions needed by objects of 'NumberFormatter' class + */ + +/* {{{ NumberFormatter_objects_dtor */ +static void NumberFormatter_object_dtor( + void *object, + zend_object_handle handle TSRMLS_DC ) +{ + zend_objects_destroy_object( object, handle TSRMLS_CC ); +} +/* }}} */ + +/* {{{ NumberFormatter_objects_free */ +void NumberFormatter_object_free( zend_object *object TSRMLS_DC ) +{ + NumberFormatter_object* nfo = (NumberFormatter_object*)object; + + zend_object_std_dtor( &nfo->zo TSRMLS_CC ); + + formatter_data_free( &nfo->nf_data TSRMLS_CC ); + + efree( nfo ); +} +/* }}} */ + +/* {{{ NumberFormatter_object_create */ +zend_object_value NumberFormatter_object_create(zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value retval; + NumberFormatter_object* intern; + + intern = ecalloc( 1, sizeof(NumberFormatter_object) ); + formatter_data_init( &intern->nf_data TSRMLS_CC ); + zend_object_std_init( &intern->zo, ce TSRMLS_CC ); + object_properties_init(&intern->zo, ce); + + retval.handle = zend_objects_store_put( + intern, + NumberFormatter_object_dtor, + (zend_objects_free_object_storage_t)NumberFormatter_object_free, + NULL TSRMLS_CC ); + + retval.handlers = &NumberFormatter_handlers; + + return retval; +} +/* }}} */ + +/* {{{ 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_NO_CHECK; + new_obj_val = NumberFormatter_ce_ptr->create_object(Z_OBJCE_P(object) 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. It may fail, the destruction code must handle this case */ + if (FORMATTER_OBJECT(nfo) != NULL) { + FORMATTER_OBJECT(new_nfo) = unum_clone(FORMATTER_OBJECT(nfo), + &INTL_DATA_ERROR_CODE(nfo)); + if (U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) { + /* set up error in case error handler is interested */ + intl_errors_set(INTL_DATA_ERROR_P(nfo), INTL_DATA_ERROR_CODE(nfo), + "Failed to clone NumberFormatter object", 0 TSRMLS_CC); + zend_throw_exception(NULL, "Failed to clone NumberFormatter object", 0 TSRMLS_CC); + } + } else { + zend_throw_exception(NULL, "Cannot clone unconstructed NumberFormatter", 0 TSRMLS_CC); + } + return new_obj_val; +} +/* }}} */ + +/* + * 'NumberFormatter' class registration structures & functions + */ + +/* {{{ arginfo */ +ZEND_BEGIN_ARG_INFO_EX(number_parse_arginfo, 0, 0, 1) + ZEND_ARG_INFO(0, string) + ZEND_ARG_INFO(0, type) + ZEND_ARG_INFO(1, position) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(number_parse_currency_arginfo, 0, 0, 2) + ZEND_ARG_INFO(0, string) + ZEND_ARG_INFO(1, currency) + ZEND_ARG_INFO(1, position) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_numberformatter_getattribute, 0, 0, 1) + ZEND_ARG_INFO(0, attr) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_numberformatter_setattribute, 0, 0, 2) + ZEND_ARG_INFO(0, attr) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_numberformatter_setsymbol, 0, 0, 2) + ZEND_ARG_INFO(0, attr) + ZEND_ARG_INFO(0, symbol) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_numberformatter_getpattern, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_numberformatter_setpattern, 0, 0, 1) + ZEND_ARG_INFO(0, pattern) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_numberformatter_getlocale, 0, 0, 0) + ZEND_ARG_INFO(0, type) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_numberformatter___construct, 0, 0, 2) + ZEND_ARG_INFO(0, locale) + ZEND_ARG_INFO(0, style) + ZEND_ARG_INFO(0, pattern) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_numberformatter_formatcurrency, 0, 0, 2) + ZEND_ARG_INFO(0, num) + ZEND_ARG_INFO(0, currency) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_numberformatter_format, 0, 0, 1) + ZEND_ARG_INFO(0, num) + ZEND_ARG_INFO(0, type) +ZEND_END_ARG_INFO() +/* }}} */ + +/* {{{ NumberFormatter_class_functions + * Every 'NumberFormatter' class method has an entry in this table + */ +static zend_function_entry NumberFormatter_class_functions[] = { + PHP_ME( NumberFormatter, __construct, arginfo_numberformatter___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR ) + ZEND_FENTRY( create, ZEND_FN( numfmt_create ), arginfo_numberformatter___construct, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC ) + PHP_NAMED_FE( format, ZEND_FN( numfmt_format ), arginfo_numberformatter_format ) + PHP_NAMED_FE( parse, ZEND_FN( numfmt_parse ), number_parse_arginfo ) + PHP_NAMED_FE( formatCurrency, ZEND_FN( numfmt_format_currency ), arginfo_numberformatter_formatcurrency ) + PHP_NAMED_FE( parseCurrency, ZEND_FN( numfmt_parse_currency ), number_parse_currency_arginfo ) + PHP_NAMED_FE( setAttribute, ZEND_FN( numfmt_set_attribute ), arginfo_numberformatter_setattribute ) + PHP_NAMED_FE( getAttribute, ZEND_FN( numfmt_get_attribute ), arginfo_numberformatter_getattribute ) + PHP_NAMED_FE( setTextAttribute, ZEND_FN( numfmt_set_text_attribute ), arginfo_numberformatter_setattribute ) + PHP_NAMED_FE( getTextAttribute, ZEND_FN( numfmt_get_text_attribute ), arginfo_numberformatter_getattribute ) + PHP_NAMED_FE( setSymbol, ZEND_FN( numfmt_set_symbol ), arginfo_numberformatter_setsymbol ) + PHP_NAMED_FE( getSymbol, ZEND_FN( numfmt_get_symbol ), arginfo_numberformatter_getattribute ) + PHP_NAMED_FE( setPattern, ZEND_FN( numfmt_set_pattern ), arginfo_numberformatter_setpattern ) + PHP_NAMED_FE( getPattern, ZEND_FN( numfmt_get_pattern ), arginfo_numberformatter_getpattern ) + PHP_NAMED_FE( getLocale, ZEND_FN( numfmt_get_locale ), arginfo_numberformatter_getlocale ) + PHP_NAMED_FE( getErrorCode, ZEND_FN( numfmt_get_error_code ), arginfo_numberformatter_getpattern ) + PHP_NAMED_FE( getErrorMessage, ZEND_FN( numfmt_get_error_message ), arginfo_numberformatter_getpattern ) + PHP_FE_END +}; +/* }}} */ + +/* {{{ formatter_register_class + * Initialize 'NumberFormatter' class + */ +void formatter_register_class( TSRMLS_D ) +{ + zend_class_entry ce; + + /* Create and register 'NumberFormatter' class. */ + INIT_CLASS_ENTRY( ce, "NumberFormatter", NumberFormatter_class_functions ); + ce.create_object = NumberFormatter_object_create; + 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 = NumberFormatter_object_clone; + + /* Declare 'NumberFormatter' class properties. */ + if( !NumberFormatter_ce_ptr ) + { + zend_error(E_ERROR, "Failed to register NumberFormatter class"); + return; + } +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/formatter/formatter_class.h b/ext/intl/formatter/formatter_class.h new file mode 100644 index 0000000..9582866 --- /dev/null +++ b/ext/intl/formatter/formatter_class.h @@ -0,0 +1,50 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Stanislav Malyshev <stas@zend.com> | + +----------------------------------------------------------------------+ + */ + +#ifndef FORMATTER_CLASS_H +#define FORMATTER_CLASS_H + +#include <php.h> + +#include "intl_common.h" +#include "intl_error.h" +#include "intl_data.h" +#include "formatter_data.h" + +typedef struct { + zend_object zo; + formatter_data nf_data; +} NumberFormatter_object; + +void formatter_register_class( TSRMLS_D ); +extern zend_class_entry *NumberFormatter_ce_ptr; + +/* Auxiliary macros */ + +#define FORMATTER_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(NumberFormatter, nfo) +#define FORMATTER_OBJECT(nfo) (nfo)->nf_data.unum +#define FORMATTER_METHOD_FETCH_OBJECT_NO_CHECK INTL_METHOD_FETCH_OBJECT(NumberFormatter, nfo) +#define FORMATTER_METHOD_FETCH_OBJECT \ + FORMATTER_METHOD_FETCH_OBJECT_NO_CHECK; \ + if (FORMATTER_OBJECT(nfo) == NULL) \ + { \ + intl_errors_set(&nfo->nf_data.error, U_ILLEGAL_ARGUMENT_ERROR, \ + "Found unconstructed NumberFormatter", 0 TSRMLS_CC); \ + RETURN_FALSE; \ + } + + +#endif // #ifndef FORMATTER_CLASS_H diff --git a/ext/intl/formatter/formatter_data.c b/ext/intl/formatter/formatter_data.c new file mode 100644 index 0000000..88f122f --- /dev/null +++ b/ext/intl/formatter/formatter_data.c @@ -0,0 +1,72 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Stanislav Malyshev <stas@zend.com> | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "formatter_data.h" + +/* {{{ void formatter_data_init( formatter_data* nf_data ) + * Initialize internals of formatter_data. + */ +void formatter_data_init( formatter_data* nf_data TSRMLS_DC ) +{ + if( !nf_data ) + return; + + nf_data->unum = NULL; + intl_error_reset( &nf_data->error TSRMLS_CC ); +} +/* }}} */ + +/* {{{ void formatter_data_free( formatter_data* nf_data ) + * Clean up mem allocted by internals of formatter_data + */ +void formatter_data_free( formatter_data* nf_data TSRMLS_DC ) +{ + if( !nf_data ) + return; + + if( nf_data->unum ) + unum_close( nf_data->unum ); + + nf_data->unum = NULL; + intl_error_reset( &nf_data->error TSRMLS_CC ); +} +/* }}} */ + +/* {{{ formatter_data* formatter_data_create() + * Alloc mem for formatter_data and initialize it with default values. + */ +formatter_data* formatter_data_create( TSRMLS_D ) +{ + formatter_data* nf_data = ecalloc( 1, sizeof(formatter_data) ); + + formatter_data_init( nf_data TSRMLS_CC ); + + return nf_data; +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/formatter/formatter_data.h b/ext/intl/formatter/formatter_data.h new file mode 100644 index 0000000..adc4818 --- /dev/null +++ b/ext/intl/formatter/formatter_data.h @@ -0,0 +1,38 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Stanislav Malyshev <stas@zend.com> | + +----------------------------------------------------------------------+ + */ + +#ifndef FORMATTER_DATA_H +#define FORMATTER_DATA_H + +#include <php.h> + +#include <unicode/unum.h> + +#include "intl_error.h" + +typedef struct { + // error hangling + intl_error error; + + // formatter handling + UNumberFormat* unum; +} formatter_data; + +formatter_data* formatter_data_create( TSRMLS_D ); +void formatter_data_init( formatter_data* nf_data TSRMLS_DC ); +void formatter_data_free( formatter_data* nf_data TSRMLS_DC ); + +#endif // FORMATTER_DATA_H diff --git a/ext/intl/formatter/formatter_format.c b/ext/intl/formatter/formatter_format.c new file mode 100644 index 0000000..ce1c941 --- /dev/null +++ b/ext/intl/formatter/formatter_format.c @@ -0,0 +1,204 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Stanislav Malyshev <stas@zend.com> | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unicode/ustring.h> + +#include "php_intl.h" +#include "formatter_class.h" +#include "formatter_format.h" +#include "intl_convert.h" + +/* {{{ proto mixed NumberFormatter::format( mixed $num[, int $type] ) + * Format a number. }}} */ +/* {{{ proto mixed numfmt_format( NumberFormatter $nf, mixed $num[, int type] ) + * Format a number. + */ +PHP_FUNCTION( numfmt_format ) +{ + zval **number; + long type = FORMAT_TYPE_DEFAULT; + UChar format_buf[32]; + UChar* formatted = format_buf; + int formatted_len = USIZE(format_buf); + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OZ|l", + &object, NumberFormatter_ce_ptr, &number, &type ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "numfmt_format: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + if(type == FORMAT_TYPE_DEFAULT) { + if(Z_TYPE_PP(number) == IS_STRING) { + convert_scalar_to_number_ex(number); + } + + if(Z_TYPE_PP(number) == IS_LONG) { + /* take INT32 on 32-bit, int64 on 64-bit */ + type = (sizeof(long) == 8)?FORMAT_TYPE_INT64:FORMAT_TYPE_INT32; + } else if(Z_TYPE_PP(number) == IS_DOUBLE) { + type = FORMAT_TYPE_DOUBLE; + } else { + type = FORMAT_TYPE_INT32; + } + } + + if(Z_TYPE_PP(number) != IS_DOUBLE && Z_TYPE_PP(number) != IS_LONG) { + SEPARATE_ZVAL_IF_NOT_REF(number); + convert_scalar_to_number( *number TSRMLS_CC ); + } + + switch(type) { + case FORMAT_TYPE_INT32: + convert_to_long_ex(number); + formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)Z_LVAL_PP(number), + formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) { + intl_error_reset(INTL_DATA_ERROR_P(nfo) TSRMLS_CC); + formatted = eumalloc(formatted_len); + formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)Z_LVAL_PP(number), + formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) { + efree(formatted); + } + } + INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" ); + break; + + case FORMAT_TYPE_INT64: + { + int64_t value = (Z_TYPE_PP(number) == IS_DOUBLE)?(int64_t)Z_DVAL_PP(number):Z_LVAL_PP(number); + formatted_len = unum_formatInt64(FORMATTER_OBJECT(nfo), value, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) { + intl_error_reset(INTL_DATA_ERROR_P(nfo) TSRMLS_CC); + formatted = eumalloc(formatted_len); + formatted_len = unum_formatInt64(FORMATTER_OBJECT(nfo), value, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) { + efree(formatted); + } + } + INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" ); + } + break; + + case FORMAT_TYPE_DOUBLE: + convert_to_double_ex(number); + formatted_len = unum_formatDouble(FORMATTER_OBJECT(nfo), Z_DVAL_PP(number), formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) { + intl_error_reset(INTL_DATA_ERROR_P(nfo) TSRMLS_CC); + formatted = eumalloc(formatted_len); + unum_formatDouble(FORMATTER_OBJECT(nfo), Z_DVAL_PP(number), formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) { + efree(formatted); + } + } + INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" ); + break; + + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported format type %ld", type); + RETURN_FALSE; + break; + } + + INTL_METHOD_RETVAL_UTF8( nfo, formatted, formatted_len, ( formatted != format_buf ) ); +} +/* }}} */ + +/* {{{ proto mixed NumberFormatter::formatCurrency( double $num, string $currency ) + * Format a number as currency. }}} */ +/* {{{ proto mixed numfmt_format_currency( NumberFormatter $nf, double $num, string $currency ) + * Format a number as currency. + */ +PHP_FUNCTION( numfmt_format_currency ) +{ + double number; + UChar format_buf[32]; + UChar* formatted = format_buf; + int formatted_len = USIZE(format_buf); + char* currency = NULL; + int currency_len = 0; + UChar* scurrency = NULL; + int scurrency_len = 0; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ods", + &object, NumberFormatter_ce_ptr, &number, ¤cy, ¤cy_len ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "numfmt_format_currency: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + /* Convert currency to UTF-16. */ + intl_convert_utf8_to_utf16(&scurrency, &scurrency_len, currency, currency_len, &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "Currency conversion to UTF-16 failed" ); + + /* Format the number using a fixed-length buffer. */ + formatted_len = unum_formatDoubleCurrency(FORMATTER_OBJECT(nfo), number, scurrency, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + + /* If the buffer turned out to be too small + * then allocate another buffer dynamically + * and use it to format the number. + */ + if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) { + intl_error_reset(INTL_DATA_ERROR_P(nfo) TSRMLS_CC); + formatted = eumalloc(formatted_len); + unum_formatDoubleCurrency(FORMATTER_OBJECT(nfo), number, scurrency, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + } + + if( U_FAILURE( INTL_DATA_ERROR_CODE((nfo)) ) ) { + intl_error_set_code( NULL, INTL_DATA_ERROR_CODE((nfo)) TSRMLS_CC ); + intl_errors_set_custom_msg( INTL_DATA_ERROR_P(nfo), "Number formatting failed", 0 TSRMLS_CC ); + RETVAL_FALSE; + if (formatted != format_buf) { + efree(formatted); + } + } else { + INTL_METHOD_RETVAL_UTF8( nfo, formatted, formatted_len, ( formatted != format_buf ) ); + } + + if(scurrency) { + efree(scurrency); + } +} + +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/formatter/formatter_format.h b/ext/intl/formatter/formatter_format.h new file mode 100644 index 0000000..35fafd1 --- /dev/null +++ b/ext/intl/formatter/formatter_format.h @@ -0,0 +1,31 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Stanislav Malyshev <stas@zend.com> | + +----------------------------------------------------------------------+ + */ + +#ifndef FORMATTER_FORMAT_H +#define FORMATTER_FORMAT_H + +#include <php.h> + +PHP_FUNCTION( numfmt_format ); +PHP_FUNCTION( numfmt_format_currency ); + +#define FORMAT_TYPE_DEFAULT 0 +#define FORMAT_TYPE_INT32 1 +#define FORMAT_TYPE_INT64 2 +#define FORMAT_TYPE_DOUBLE 3 +#define FORMAT_TYPE_CURRENCY 4 + +#endif // FORMATTER_FORMAT_H diff --git a/ext/intl/formatter/formatter_main.c b/ext/intl/formatter/formatter_main.c new file mode 100644 index 0000000..5cb6483 --- /dev/null +++ b/ext/intl/formatter/formatter_main.c @@ -0,0 +1,156 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Stanislav Malyshev <stas@zend.com> | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unicode/ustring.h> + +#include "php_intl.h" +#include "formatter_class.h" +#include "intl_convert.h" + +/* {{{ */ +static void numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS) +{ + char* locale; + char* pattern = NULL; + int locale_len = 0, pattern_len = 0; + long style; + UChar* spattern = NULL; + int spattern_len = 0; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "sl|s", + &locale, &locale_len, &style, &pattern, &pattern_len ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "numfmt_create: unable to parse input parameters", 0 TSRMLS_CC ); + zval_dtor(return_value); + RETURN_NULL(); + } + + INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value); + object = return_value; + FORMATTER_METHOD_FETCH_OBJECT_NO_CHECK; + + /* Convert pattern (if specified) to UTF-16. */ + if(pattern && pattern_len) { + intl_convert_utf8_to_utf16(&spattern, &spattern_len, pattern, pattern_len, &INTL_DATA_ERROR_CODE(nfo)); + INTL_CTOR_CHECK_STATUS(nfo, "numfmt_create: error converting pattern to UTF-16"); + } + + if(locale_len == 0) { + locale = INTL_G(default_locale); + } + + /* Create an ICU number formatter. */ + FORMATTER_OBJECT(nfo) = unum_open(style, spattern, spattern_len, locale, NULL, &INTL_DATA_ERROR_CODE(nfo)); + + if(spattern) { + efree(spattern); + } + + INTL_CTOR_CHECK_STATUS(nfo, "numfmt_create: number formatter creation failed"); +} +/* }}} */ + +/* {{{ proto NumberFormatter NumberFormatter::create( string $locale, int style[, string $pattern ] ) + * Create number formatter. }}} */ +/* {{{ proto NumberFormatter numfmt_create( string $locale, int style[, string $pattern ] ) + * Create number formatter. + */ +PHP_FUNCTION( numfmt_create ) +{ + object_init_ex( return_value, NumberFormatter_ce_ptr ); + numfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + +/* {{{ proto void NumberFormatter::__construct( string $locale, int style[, string $pattern ] ) + * NumberFormatter object constructor. + */ +PHP_METHOD( NumberFormatter, __construct ) +{ + return_value = getThis(); + numfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + +/* {{{ proto int NumberFormatter::getErrorCode() + * Get formatter's last error code. }}} */ +/* {{{ proto int numfmt_get_error_code( NumberFormatter $nf ) + * Get formatter's last error code. + */ +PHP_FUNCTION( numfmt_get_error_code ) +{ + FORMATTER_METHOD_INIT_VARS + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, NumberFormatter_ce_ptr ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "numfmt_get_error_code: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + nfo = (NumberFormatter_object *) zend_object_store_get_object( object TSRMLS_CC ); + + /* Return formatter's last error code. */ + RETURN_LONG( INTL_DATA_ERROR_CODE(nfo) ); +} +/* }}} */ + +/* {{{ proto string NumberFormatter::getErrorMessage( ) + * Get text description for formatter's last error code. }}} */ +/* {{{ proto string numfmt_get_error_message( NumberFormatter $nf ) + * Get text description for formatter's last error code. + */ +PHP_FUNCTION( numfmt_get_error_message ) +{ + char* message = NULL; + FORMATTER_METHOD_INIT_VARS + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, NumberFormatter_ce_ptr ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "numfmt_get_error_message: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + nfo = (NumberFormatter_object *) zend_object_store_get_object( object TSRMLS_CC ); + + /* Return last error message. */ + message = intl_error_get_message( INTL_DATA_ERROR_P(nfo) TSRMLS_CC ); + RETURN_STRING( message, 0); +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/formatter/formatter_main.h b/ext/intl/formatter/formatter_main.h new file mode 100644 index 0000000..7669e68 --- /dev/null +++ b/ext/intl/formatter/formatter_main.h @@ -0,0 +1,27 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Stanislav Malyshev <stas@zend.com> | + +----------------------------------------------------------------------+ + */ + +#ifndef FORMATTER_MAIN_H +#define FORMATTER_MAIN_H + +#include <php.h> + +PHP_FUNCTION( numfmt_create ); +PHP_FUNCTION( numfmt_get_error_code ); +PHP_FUNCTION( numfmt_get_error_message ); +PHP_METHOD( NumberFormatter, __construct ); + +#endif // FORMATTER_FORMAT_H diff --git a/ext/intl/formatter/formatter_parse.c b/ext/intl/formatter/formatter_parse.c new file mode 100644 index 0000000..6f3a3a1 --- /dev/null +++ b/ext/intl/formatter/formatter_parse.c @@ -0,0 +1,187 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Stanislav Malyshev <stas@zend.com> | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unicode/ustring.h> +#include <locale.h> + +#include "php_intl.h" +#include "formatter_class.h" +#include "formatter_format.h" +#include "formatter_parse.h" +#include "intl_convert.h" + +#define ICU_LOCALE_BUG 1 + +/* {{{ proto mixed NumberFormatter::parse( string $str[, int $type, int &$position ]) + * Parse a number. }}} */ +/* {{{ proto mixed numfmt_parse( NumberFormatter $nf, string $str[, int $type, int &$position ]) + * Parse a number. + */ +PHP_FUNCTION( numfmt_parse ) +{ + long type = FORMAT_TYPE_DOUBLE; + UChar* sstr = NULL; + int sstr_len = 0; + char* str = NULL; + int str_len; + int32_t val32, position = 0; + int64_t val64; + double val_double; + int32_t* position_p = NULL; + zval *zposition = NULL; + char *oldlocale; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|lz!", + &object, NumberFormatter_ce_ptr, &str, &str_len, &type, &zposition ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "number_parse: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + /* Convert given string to UTF-16. */ + intl_convert_utf8_to_utf16(&sstr, &sstr_len, str, str_len, &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" ); + + if(zposition) { + convert_to_long(zposition); + position = (int32_t)Z_LVAL_P( zposition ); + position_p = &position; + } + +#if ICU_LOCALE_BUG && defined(LC_NUMERIC) + oldlocale = setlocale(LC_NUMERIC, "C"); +#endif + + switch(type) { + case FORMAT_TYPE_INT32: + val32 = unum_parse(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo)); + RETVAL_LONG(val32); + break; + case FORMAT_TYPE_INT64: + val64 = unum_parseInt64(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo)); + if(val64 > LONG_MAX || val64 < LONG_MIN) { + RETVAL_DOUBLE(val64); + } else { + RETVAL_LONG((long)val64); + } + break; + case FORMAT_TYPE_DOUBLE: + val_double = unum_parseDouble(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo)); + RETVAL_DOUBLE(val_double); + break; + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported format type %ld", type); + RETVAL_FALSE; + break; + } +#if ICU_LOCALE_BUG && defined(LC_NUMERIC) + setlocale(LC_NUMERIC, oldlocale); +#endif + if(zposition) { + zval_dtor(zposition); + ZVAL_LONG(zposition, position); + } + + if (sstr) { + efree(sstr); + } + + INTL_METHOD_CHECK_STATUS( nfo, "Number parsing failed" ); +} +/* }}} */ + +/* {{{ proto double NumberFormatter::parseCurrency( string $str, string $¤cy[, int $&position] ) + * Parse a number as currency. }}} */ +/* {{{ proto double numfmt_parse_currency( NumberFormatter $nf, string $str, string $¤cy[, int $&position] ) + * Parse a number as currency. + */ +PHP_FUNCTION( numfmt_parse_currency ) +{ + double number; + UChar currency[5] = {0}; + UChar* sstr = NULL; + int sstr_len = 0; + char *currency_str = NULL; + int currency_len = 0; + char *str; + int str_len; + int32_t* position_p = NULL; + int32_t position = 0; + zval *zcurrency, *zposition = NULL; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Osz|z!", + &object, NumberFormatter_ce_ptr, &str, &str_len, &zcurrency, &zposition ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "number_parse_currency: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + /* Convert given string to UTF-16. */ + intl_convert_utf8_to_utf16(&sstr, &sstr_len, str, str_len, &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" ); + + if(zposition) { + convert_to_long(zposition); + position = (int32_t)Z_LVAL_P( zposition ); + position_p = &position; + } + + number = unum_parseDoubleCurrency(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, currency, &INTL_DATA_ERROR_CODE(nfo)); + if(zposition) { + zval_dtor(zposition); + ZVAL_LONG(zposition, position); + } + if (sstr) { + efree(sstr); + } + INTL_METHOD_CHECK_STATUS( nfo, "Number parsing failed" ); + + /* Convert parsed currency to UTF-8 and pass it back to caller. */ + intl_convert_utf16_to_utf8(¤cy_str, ¤cy_len, currency, u_strlen(currency), &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "Currency conversion to UTF-8 failed" ); + zval_dtor( zcurrency ); + ZVAL_STRINGL(zcurrency, currency_str, currency_len, 0); + + RETVAL_DOUBLE( number ); +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/intl/formatter/formatter_parse.h b/ext/intl/formatter/formatter_parse.h new file mode 100644 index 0000000..cb96c72 --- /dev/null +++ b/ext/intl/formatter/formatter_parse.h @@ -0,0 +1,25 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Stanislav Malyshev <stas@zend.com> | + +----------------------------------------------------------------------+ + */ + +#ifndef FORMATTER_PARSE_H +#define FORMATTER_PARSE_H + +#include <php.h> + +PHP_FUNCTION( numfmt_parse ); +PHP_FUNCTION( numfmt_parse_currency ); + +#endif // FORMATTER_PARSE_H |