summaryrefslogtreecommitdiff
path: root/ext/intl/formatter
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2013-03-14 05:42:27 +0000
committer <>2013-04-03 16:25:08 +0000
commitc4dd7a1a684490673e25aaf4fabec5df138854c4 (patch)
tree4d57c44caae4480efff02b90b9be86f44bf25409 /ext/intl/formatter
downloadphp2-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.c152
-rw-r--r--ext/intl/formatter/formatter.h24
-rw-r--r--ext/intl/formatter/formatter_attr.c459
-rw-r--r--ext/intl/formatter/formatter_attr.h32
-rw-r--r--ext/intl/formatter/formatter_class.c226
-rw-r--r--ext/intl/formatter/formatter_class.h50
-rw-r--r--ext/intl/formatter/formatter_data.c72
-rw-r--r--ext/intl/formatter/formatter_data.h38
-rw-r--r--ext/intl/formatter/formatter_format.c204
-rw-r--r--ext/intl/formatter/formatter_format.h31
-rw-r--r--ext/intl/formatter/formatter_main.c156
-rw-r--r--ext/intl/formatter/formatter_main.h27
-rw-r--r--ext/intl/formatter/formatter_parse.c187
-rw-r--r--ext/intl/formatter/formatter_parse.h25
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, &currency, &currency_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 $&currency[, int $&position] )
+ * Parse a number as currency. }}} */
+/* {{{ proto double numfmt_parse_currency( NumberFormatter $nf, string $str, string $&currency[, 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(&currency_str, &currency_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