mirror of
https://github.com/php/php-src.git
synced 2026-10-29 10:22:06 +08:00
ext/intl: Migrate formatter, listformatter, and rangeformatter from I… (#21378)
- formatter: Replace intl_convert_utf8_to_utf16/uloc_getISO3Language with intl_stringFromChar/icu::Locale, use UnicodeString for pattern handling - listformatter: Replace ulistfmt_open/ulistfmt_openForType/ulistfmt_close/ ulistfmt_format with ListFormatter C++ equivalents, use UnicodeString array and intl_stringFromChar/intl_charFromString for string conversions - rangeformatter: Replace uloc_getISO3Language with icu::Locale::getISO3Language - Replace UNumberFormat*/unum_* with icu::NumberFormat C++ equivalents. - Attribute get/set still use reinterpret_cast<UNumberFormat*> for now.
This commit is contained in:
1 parent
b89e0ef305
commit
3ed80a154d
12 files changed
+245
-252
No files matched your search
@@ -16,13 +16,16 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <unicode/unum.h>
|
||||
#include "../intl_convertcpp.h"
|
||||
#include "formatter_class.h"
|
||||
|
||||
extern "C" {
|
||||
#include "php_intl.h"
|
||||
#include "intl_convert.h"
|
||||
}
|
||||
#include "formatter_class.h"
|
||||
|
||||
#include <unicode/ustring.h>
|
||||
#define FORMATTER_UNUM(nfo) reinterpret_cast<UNumberFormat*>(FORMATTER_OBJECT(nfo))
|
||||
|
||||
/* {{{ Get formatter attribute value. */
|
||||
U_CFUNC PHP_FUNCTION( numfmt_get_attribute )
|
||||
@@ -62,7 +65,7 @@ U_CFUNC PHP_FUNCTION( numfmt_get_attribute )
|
||||
case UNUM_MIN_SIGNIFICANT_DIGITS:
|
||||
case UNUM_MAX_SIGNIFICANT_DIGITS:
|
||||
case UNUM_LENIENT_PARSE:
|
||||
value = unum_getAttribute(FORMATTER_OBJECT(nfo), attribute);
|
||||
value = unum_getAttribute(FORMATTER_UNUM(nfo), attribute);
|
||||
if(value == -1) {
|
||||
INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR;
|
||||
} else {
|
||||
@@ -71,7 +74,7 @@ U_CFUNC PHP_FUNCTION( numfmt_get_attribute )
|
||||
break;
|
||||
case UNUM_ROUNDING_INCREMENT:
|
||||
{
|
||||
double value_double = unum_getDoubleAttribute(FORMATTER_OBJECT(nfo), attribute);
|
||||
double value_double = unum_getDoubleAttribute(FORMATTER_UNUM(nfo), attribute);
|
||||
if(value_double == -1) {
|
||||
INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR;
|
||||
} else {
|
||||
@@ -110,12 +113,12 @@ U_CFUNC PHP_FUNCTION( numfmt_get_text_attribute )
|
||||
|
||||
UNumberFormatTextAttribute attribute = static_cast<UNumberFormatTextAttribute>(lattribute);
|
||||
|
||||
length = unum_getTextAttribute( FORMATTER_OBJECT(nfo), attribute, value, value_buf_size, &INTL_DATA_ERROR_CODE(nfo) );
|
||||
length = unum_getTextAttribute( FORMATTER_UNUM(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) );
|
||||
length = unum_getTextAttribute( FORMATTER_UNUM(nfo), attribute, value, length, &INTL_DATA_ERROR_CODE(nfo) );
|
||||
if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) {
|
||||
efree(value);
|
||||
value = value_buf;
|
||||
@@ -166,10 +169,10 @@ U_CFUNC PHP_FUNCTION( numfmt_set_attribute )
|
||||
case UNUM_MIN_SIGNIFICANT_DIGITS:
|
||||
case UNUM_MAX_SIGNIFICANT_DIGITS:
|
||||
case UNUM_LENIENT_PARSE:
|
||||
unum_setAttribute(FORMATTER_OBJECT(nfo), attribute, zval_get_long(value));
|
||||
unum_setAttribute(FORMATTER_UNUM(nfo), attribute, zval_get_long(value));
|
||||
break;
|
||||
case UNUM_ROUNDING_INCREMENT:
|
||||
unum_setDoubleAttribute(FORMATTER_OBJECT(nfo), attribute, zval_get_double(value));
|
||||
unum_setDoubleAttribute(FORMATTER_UNUM(nfo), attribute, zval_get_double(value));
|
||||
break;
|
||||
default:
|
||||
INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR;
|
||||
@@ -185,8 +188,6 @@ U_CFUNC PHP_FUNCTION( numfmt_set_attribute )
|
||||
/* {{{ Get formatter attribute value. */
|
||||
U_CFUNC PHP_FUNCTION( numfmt_set_text_attribute )
|
||||
{
|
||||
int32_t slength = 0;
|
||||
UChar *svalue = NULL;
|
||||
zend_long attribute;
|
||||
char *value;
|
||||
size_t len;
|
||||
@@ -203,14 +204,12 @@ U_CFUNC PHP_FUNCTION( numfmt_set_text_attribute )
|
||||
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));
|
||||
UnicodeString svalue;
|
||||
intl_stringFromChar(svalue, 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), static_cast<UNumberFormatTextAttribute>(attribute), svalue, slength, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if (svalue) {
|
||||
efree(svalue);
|
||||
}
|
||||
unum_setTextAttribute(FORMATTER_UNUM(nfo), static_cast<UNumberFormatTextAttribute>(attribute), svalue.getBuffer(), svalue.length(), &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error setting text attribute" );
|
||||
|
||||
RETURN_TRUE;
|
||||
@@ -243,12 +242,12 @@ U_CFUNC PHP_FUNCTION( numfmt_get_symbol )
|
||||
/* Fetch the object. */
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
length = unum_getSymbol(FORMATTER_OBJECT(nfo), symbol, value_buf, length, &INTL_DATA_ERROR_CODE(nfo));
|
||||
length = unum_getSymbol(FORMATTER_UNUM(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));
|
||||
length = unum_getSymbol(FORMATTER_UNUM(nfo), symbol, value, length, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) {
|
||||
efree(value);
|
||||
value = value_buf;
|
||||
@@ -266,8 +265,6 @@ U_CFUNC PHP_FUNCTION( numfmt_set_symbol )
|
||||
zend_long lsymbol;
|
||||
char* value = NULL;
|
||||
size_t value_len = 0;
|
||||
UChar* svalue = 0;
|
||||
int32_t slength = 0;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
/* Parse parameters. */
|
||||
@@ -288,14 +285,12 @@ U_CFUNC PHP_FUNCTION( numfmt_set_symbol )
|
||||
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));
|
||||
UnicodeString svalue;
|
||||
intl_stringFromChar(svalue, 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);
|
||||
}
|
||||
unum_setSymbol(FORMATTER_UNUM(nfo), symbol, svalue.getBuffer(), svalue.length(), &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error setting symbol value" );
|
||||
|
||||
RETURN_TRUE;
|
||||
@@ -320,12 +315,12 @@ U_CFUNC PHP_FUNCTION( numfmt_get_pattern )
|
||||
/* Fetch the object. */
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
length = unum_toPattern(FORMATTER_OBJECT(nfo), 0, value, length, &INTL_DATA_ERROR_CODE(nfo));
|
||||
length = unum_toPattern(FORMATTER_UNUM(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) );
|
||||
length = unum_toPattern( FORMATTER_UNUM(nfo), 0, value, length, &INTL_DATA_ERROR_CODE(nfo) );
|
||||
if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) {
|
||||
efree(value);
|
||||
value = value_buf;
|
||||
@@ -342,8 +337,6 @@ U_CFUNC PHP_FUNCTION( numfmt_set_pattern )
|
||||
{
|
||||
char* value = NULL;
|
||||
size_t value_len = 0;
|
||||
int32_t slength = 0;
|
||||
UChar* svalue = NULL;
|
||||
UParseError spattern_error = {0};
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
@@ -357,13 +350,11 @@ U_CFUNC PHP_FUNCTION( numfmt_set_pattern )
|
||||
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));
|
||||
UnicodeString svalue;
|
||||
intl_stringFromChar(svalue, value, value_len, &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error converting pattern to UTF-16" );
|
||||
|
||||
unum_applyPattern(FORMATTER_OBJECT(nfo), 0, svalue, slength, &spattern_error, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if (svalue) {
|
||||
efree(svalue);
|
||||
}
|
||||
unum_applyPattern(FORMATTER_UNUM(nfo), 0, svalue.getBuffer(), svalue.length(), &spattern_error, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if (U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) {
|
||||
char *msg;
|
||||
spprintf(&msg, 0, "Error setting pattern value at line %d, offset %d", spattern_error.line, spattern_error.offset);
|
||||
@@ -393,7 +384,7 @@ U_CFUNC PHP_FUNCTION( numfmt_get_locale )
|
||||
/* Fetch the object. */
|
||||
FORMATTER_METHOD_FETCH_OBJECT;
|
||||
|
||||
loc = unum_getLocaleByType(FORMATTER_OBJECT(nfo), static_cast<ULocDataLocaleType>(type), &INTL_DATA_ERROR_CODE(nfo));
|
||||
loc = unum_getLocaleByType(FORMATTER_UNUM(nfo), static_cast<ULocDataLocaleType>(type), &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Error getting locale" );
|
||||
RETURN_STRING(loc);
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include <unicode/unum.h>
|
||||
|
||||
#include "formatter_class.h"
|
||||
extern "C" {
|
||||
#include "php_intl.h"
|
||||
@@ -72,10 +70,9 @@ U_CFUNC zend_object *NumberFormatter_object_clone(zend_object *object)
|
||||
zend_objects_clone_members(&new_nfo->zo, &nfo->zo);
|
||||
|
||||
/* clone formatter object. It may fail, the destruction code must handle this case */
|
||||
if (FORMATTER_OBJECT(nfo) != NULL) {
|
||||
UErrorCode error = U_ZERO_ERROR;
|
||||
FORMATTER_OBJECT(new_nfo) = unum_clone(FORMATTER_OBJECT(nfo), &error);
|
||||
if (U_FAILURE(error)) {
|
||||
if (FORMATTER_OBJECT(nfo) != nullptr) {
|
||||
FORMATTER_OBJECT(new_nfo) = FORMATTER_OBJECT(nfo)->clone();
|
||||
if (FORMATTER_OBJECT(new_nfo) == nullptr) {
|
||||
zend_throw_error(NULL, "Failed to clone NumberFormatter");
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#ifndef FORMATTER_CLASS_H
|
||||
#define FORMATTER_CLASS_H
|
||||
|
||||
#include <php.h>
|
||||
#include "formatter_data.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -23,7 +23,6 @@ extern "C" {
|
||||
#include "intl_common.h"
|
||||
#include "intl_error.h"
|
||||
#include "intl_data.h"
|
||||
#include "formatter_data.h"
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -26,7 +26,7 @@ void formatter_data_init( formatter_data* nf_data )
|
||||
if( !nf_data )
|
||||
return;
|
||||
|
||||
nf_data->unum = NULL;
|
||||
nf_data->unum = nullptr;
|
||||
intl_error_reset( &nf_data->error );
|
||||
}
|
||||
/* }}} */
|
||||
@@ -39,10 +39,8 @@ void formatter_data_free( formatter_data* nf_data )
|
||||
if( !nf_data )
|
||||
return;
|
||||
|
||||
if( nf_data->unum )
|
||||
unum_close( nf_data->unum );
|
||||
|
||||
nf_data->unum = NULL;
|
||||
delete nf_data->unum;
|
||||
nf_data->unum = nullptr;
|
||||
intl_error_reset( &nf_data->error );
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -15,9 +15,21 @@
|
||||
#ifndef FORMATTER_DATA_H
|
||||
#define FORMATTER_DATA_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <php.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <unicode/unum.h>
|
||||
#include <unicode/numfmt.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
using icu::NumberFormat;
|
||||
#else
|
||||
typedef void NumberFormat;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -32,7 +44,7 @@ typedef struct {
|
||||
intl_error error;
|
||||
|
||||
// formatter handling
|
||||
UNumberFormat* unum;
|
||||
NumberFormat* unum;
|
||||
} formatter_data;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -16,24 +16,21 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "php_intl.h"
|
||||
#include "intl_convert.h"
|
||||
}
|
||||
|
||||
#include <unicode/ustring.h>
|
||||
|
||||
#include <unicode/curramt.h>
|
||||
#include <unicode/fmtable.h>
|
||||
#include "../intl_convertcpp.h"
|
||||
#include "formatter_class.h"
|
||||
#include "formatter_format.h"
|
||||
|
||||
extern "C" {
|
||||
#include "php_intl.h"
|
||||
}
|
||||
|
||||
/* {{{ Format a number. */
|
||||
U_CFUNC PHP_FUNCTION( numfmt_format )
|
||||
{
|
||||
zval *number;
|
||||
zend_long type = FORMAT_TYPE_DEFAULT;
|
||||
UChar format_buf[32];
|
||||
UChar* formatted = format_buf;
|
||||
int32_t formatted_len = USIZE(format_buf);
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
/* Parse parameters. */
|
||||
@@ -59,50 +56,27 @@ U_CFUNC PHP_FUNCTION( numfmt_format )
|
||||
}
|
||||
}
|
||||
|
||||
icu::UnicodeString result;
|
||||
icu::FieldPosition pos;
|
||||
|
||||
switch(type) {
|
||||
case FORMAT_TYPE_INT32:
|
||||
convert_to_long(number);
|
||||
formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)Z_LVAL_P(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));
|
||||
formatted = eumalloc(formatted_len);
|
||||
formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)Z_LVAL_P(number),
|
||||
formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) {
|
||||
efree(formatted);
|
||||
}
|
||||
}
|
||||
FORMATTER_OBJECT(nfo)->format((int32_t)Z_LVAL_P(number), result, pos, INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" );
|
||||
break;
|
||||
|
||||
case FORMAT_TYPE_INT64:
|
||||
{
|
||||
int64_t value = (Z_TYPE_P(number) == IS_DOUBLE)?(int64_t)Z_DVAL_P(number):Z_LVAL_P(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));
|
||||
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);
|
||||
}
|
||||
}
|
||||
FORMATTER_OBJECT(nfo)->format(value, result, pos, INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" );
|
||||
}
|
||||
break;
|
||||
|
||||
case FORMAT_TYPE_DOUBLE:
|
||||
convert_to_double(number);
|
||||
formatted_len = unum_formatDouble(FORMATTER_OBJECT(nfo), Z_DVAL_P(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));
|
||||
formatted = eumalloc(formatted_len);
|
||||
unum_formatDouble(FORMATTER_OBJECT(nfo), Z_DVAL_P(number), formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
|
||||
if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) {
|
||||
efree(formatted);
|
||||
}
|
||||
}
|
||||
FORMATTER_OBJECT(nfo)->format(Z_DVAL_P(number), result, pos, INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" );
|
||||
break;
|
||||
case FORMAT_TYPE_CURRENCY:
|
||||
@@ -120,7 +94,9 @@ U_CFUNC PHP_FUNCTION( numfmt_format )
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
INTL_METHOD_RETVAL_UTF8( nfo, formatted, formatted_len, ( formatted != format_buf ) );
|
||||
zend_string *u8str = intl_charFromString(result, &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS(nfo, "Error converting result to UTF-8");
|
||||
RETVAL_STR(u8str);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -128,13 +104,8 @@ U_CFUNC PHP_FUNCTION( numfmt_format )
|
||||
U_CFUNC PHP_FUNCTION( numfmt_format_currency )
|
||||
{
|
||||
double number;
|
||||
UChar format_buf[32];
|
||||
UChar* formatted = format_buf;
|
||||
int32_t formatted_len = USIZE(format_buf);
|
||||
char* currency = NULL;
|
||||
size_t currency_len = 0;
|
||||
UChar* scurrency = NULL;
|
||||
int32_t scurrency_len = 0;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
/* Parse parameters. */
|
||||
@@ -148,36 +119,31 @@ U_CFUNC PHP_FUNCTION( numfmt_format_currency )
|
||||
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));
|
||||
icu::UnicodeString ucurrency;
|
||||
intl_stringFromChar(ucurrency, 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));
|
||||
/* Format using CurrencyAmount. */
|
||||
icu::CurrencyAmount *currAmt = new icu::CurrencyAmount(number, ucurrency.getTerminatedBuffer(), INTL_DATA_ERROR_CODE(nfo));
|
||||
if (U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) {
|
||||
delete currAmt;
|
||||
intl_errors_set_custom_msg(INTL_DATA_ERROR_P(nfo), "Number formatting failed");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
icu::Formattable fmt;
|
||||
fmt.adoptObject(currAmt);
|
||||
icu::UnicodeString result;
|
||||
icu::FieldPosition pos;
|
||||
FORMATTER_OBJECT(nfo)->format(fmt, result, pos, 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));
|
||||
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_errors_set_custom_msg(INTL_DATA_ERROR_P(nfo), "Number formatting failed");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if( U_FAILURE( INTL_DATA_ERROR_CODE((nfo)) ) ) {
|
||||
intl_error_set_code( NULL, INTL_DATA_ERROR_CODE((nfo)) );
|
||||
intl_errors_set_custom_msg( INTL_DATA_ERROR_P(nfo), "Number formatting failed");
|
||||
RETVAL_FALSE;
|
||||
if (formatted != format_buf) {
|
||||
efree(formatted);
|
||||
}
|
||||
} else {
|
||||
INTL_METHOD_RETVAL_UTF8( nfo, formatted, formatted_len, ( formatted != format_buf ) );
|
||||
}
|
||||
|
||||
if(scurrency) {
|
||||
efree(scurrency);
|
||||
}
|
||||
zend_string *u8str = intl_charFromString(result, &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS(nfo, "Error converting result to UTF-8");
|
||||
RETVAL_STR(u8str);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
@@ -16,14 +16,17 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <unicode/ustring.h>
|
||||
#include <unicode/uloc.h>
|
||||
#include <unicode/locid.h>
|
||||
#include <unicode/decimfmt.h>
|
||||
#include <unicode/dcfmtsym.h>
|
||||
#include <unicode/rbnf.h>
|
||||
#include <unicode/compactdecimalformat.h>
|
||||
#include "../intl_convertcpp.h"
|
||||
#include "formatter_class.h"
|
||||
|
||||
extern "C" {
|
||||
#include "php_intl.h"
|
||||
#include "intl_convert.h"
|
||||
}
|
||||
#include "formatter_class.h"
|
||||
|
||||
/* {{{ */
|
||||
static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
|
||||
@@ -32,8 +35,7 @@ static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
|
||||
char* pattern = NULL;
|
||||
size_t locale_len = 0, pattern_len = 0;
|
||||
zend_long style;
|
||||
UChar* spattern = NULL;
|
||||
int32_t spattern_len = 0;
|
||||
UnicodeString upattern;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(2, 3)
|
||||
@@ -53,7 +55,7 @@ static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
|
||||
|
||||
/* 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_stringFromChar(upattern, pattern, pattern_len, &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_CTOR_CHECK_STATUS(nfo, "error converting pattern to UTF-16");
|
||||
}
|
||||
|
||||
@@ -61,7 +63,7 @@ static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
|
||||
locale = (char *)intl_locale_get_default();
|
||||
}
|
||||
|
||||
if (strlen(uloc_getISO3Language(locale)) == 0) {
|
||||
if (icu::Locale(locale).getISO3Language()[0] == '\0') {
|
||||
zend_argument_value_error(1, "\"%s\" is invalid", locale);
|
||||
return FAILURE;
|
||||
}
|
||||
@@ -70,12 +72,55 @@ static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
|
||||
const char* final_locale = canonicalized_locale ? canonicalized_locale : locale;
|
||||
|
||||
/* Create an ICU number formatter. */
|
||||
FORMATTER_OBJECT(nfo) = unum_open(static_cast<UNumberFormatStyle>(style), spattern, spattern_len, final_locale, nullptr, &INTL_DATA_ERROR_CODE(nfo));
|
||||
|
||||
if (spattern) {
|
||||
efree(spattern);
|
||||
icu::Locale loc(final_locale);
|
||||
switch (style) {
|
||||
case UNUM_PATTERN_DECIMAL: {
|
||||
icu::DecimalFormatSymbols *syms = new icu::DecimalFormatSymbols(loc, INTL_DATA_ERROR_CODE(nfo));
|
||||
if (U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) {
|
||||
delete syms;
|
||||
break;
|
||||
}
|
||||
FORMATTER_OBJECT(nfo) = new icu::DecimalFormat(upattern, syms, INTL_DATA_ERROR_CODE(nfo));
|
||||
if (FORMATTER_OBJECT(nfo) == nullptr) {
|
||||
delete syms;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UNUM_PATTERN_RULEBASED: {
|
||||
UParseError parseError;
|
||||
FORMATTER_OBJECT(nfo) = new icu::RuleBasedNumberFormat(upattern, loc, parseError, INTL_DATA_ERROR_CODE(nfo));
|
||||
break;
|
||||
}
|
||||
case UNUM_SPELLOUT:
|
||||
FORMATTER_OBJECT(nfo) = new icu::RuleBasedNumberFormat(icu::URBNF_SPELLOUT, loc, INTL_DATA_ERROR_CODE(nfo));
|
||||
break;
|
||||
case UNUM_ORDINAL:
|
||||
FORMATTER_OBJECT(nfo) = new icu::RuleBasedNumberFormat(icu::URBNF_ORDINAL, loc, INTL_DATA_ERROR_CODE(nfo));
|
||||
break;
|
||||
case UNUM_DURATION:
|
||||
FORMATTER_OBJECT(nfo) = new icu::RuleBasedNumberFormat(icu::URBNF_DURATION, loc, INTL_DATA_ERROR_CODE(nfo));
|
||||
break;
|
||||
case UNUM_NUMBERING_SYSTEM: {
|
||||
UErrorCode localErr = U_ZERO_ERROR;
|
||||
int32_t keywordLength = loc.getKeywordValue("numbers", nullptr, 0, localErr);
|
||||
if (keywordLength > 0) {
|
||||
FORMATTER_OBJECT(nfo) = NumberFormat::createInstance(loc, UNUM_DEFAULT, INTL_DATA_ERROR_CODE(nfo));
|
||||
} else {
|
||||
FORMATTER_OBJECT(nfo) = new icu::RuleBasedNumberFormat(icu::URBNF_NUMBERING_SYSTEM, loc, INTL_DATA_ERROR_CODE(nfo));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UNUM_DECIMAL_COMPACT_SHORT:
|
||||
FORMATTER_OBJECT(nfo) = icu::CompactDecimalFormat::createInstance(loc, UNUM_SHORT, INTL_DATA_ERROR_CODE(nfo));
|
||||
break;
|
||||
case UNUM_DECIMAL_COMPACT_LONG:
|
||||
FORMATTER_OBJECT(nfo) = icu::CompactDecimalFormat::createInstance(loc, UNUM_LONG, INTL_DATA_ERROR_CODE(nfo));
|
||||
break;
|
||||
default:
|
||||
FORMATTER_OBJECT(nfo) = NumberFormat::createInstance(loc, static_cast<UNumberFormatStyle>(style), INTL_DATA_ERROR_CODE(nfo));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (canonicalized_locale) {
|
||||
efree(canonicalized_locale);
|
||||
}
|
||||
|
||||
@@ -16,31 +16,28 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "php_intl.h"
|
||||
#include "intl_convert.h"
|
||||
}
|
||||
|
||||
#include <unicode/ustring.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include <unicode/fmtable.h>
|
||||
#include <unicode/curramt.h>
|
||||
#include "../intl_convertcpp.h"
|
||||
#include "formatter_class.h"
|
||||
#include "formatter_format.h"
|
||||
|
||||
extern "C" {
|
||||
#include "php_intl.h"
|
||||
}
|
||||
|
||||
#include <locale.h>
|
||||
#include <memory>
|
||||
|
||||
#define ICU_LOCALE_BUG 1
|
||||
|
||||
/* {{{ Parse a number. */
|
||||
U_CFUNC PHP_FUNCTION( numfmt_parse )
|
||||
{
|
||||
zend_long type = FORMAT_TYPE_DOUBLE;
|
||||
UChar* sstr = NULL;
|
||||
int32_t sstr_len = 0;
|
||||
char* str = NULL;
|
||||
size_t str_len;
|
||||
int32_t val32, position = 0;
|
||||
int64_t val64;
|
||||
double val_double;
|
||||
int32_t* position_p = NULL;
|
||||
int32_t position = 0;
|
||||
zval *zposition = NULL;
|
||||
char *oldlocale;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
@@ -54,14 +51,14 @@ U_CFUNC PHP_FUNCTION( numfmt_parse )
|
||||
|
||||
if (zposition) {
|
||||
position = (int32_t) zval_get_long(zposition);
|
||||
position_p = &position;
|
||||
}
|
||||
|
||||
/* 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));
|
||||
icu::UnicodeString ustr;
|
||||
intl_stringFromChar(ustr, str, str_len, &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" );
|
||||
|
||||
#if ICU_LOCALE_BUG && defined(LC_NUMERIC)
|
||||
@@ -72,21 +69,38 @@ U_CFUNC PHP_FUNCTION( numfmt_parse )
|
||||
|
||||
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 > ZEND_LONG_MAX || val64 < ZEND_LONG_MIN) {
|
||||
RETVAL_DOUBLE(val64);
|
||||
case FORMAT_TYPE_DOUBLE:
|
||||
{
|
||||
icu::Formattable result;
|
||||
icu::ParsePosition pp(position);
|
||||
FORMATTER_OBJECT(nfo)->parse(ustr, result, pp);
|
||||
|
||||
if (pp.getErrorIndex() >= 0) {
|
||||
INTL_DATA_ERROR_CODE(nfo) = U_PARSE_ERROR;
|
||||
} else {
|
||||
RETVAL_LONG((zend_long)val64);
|
||||
position = pp.getIndex();
|
||||
switch(type) {
|
||||
case FORMAT_TYPE_INT32:
|
||||
RETVAL_LONG(result.getLong(INTL_DATA_ERROR_CODE(nfo)));
|
||||
break;
|
||||
case FORMAT_TYPE_INT64:
|
||||
{
|
||||
int64_t val64 = result.getInt64(INTL_DATA_ERROR_CODE(nfo));
|
||||
if(val64 > ZEND_LONG_MAX || val64 < ZEND_LONG_MIN) {
|
||||
RETVAL_DOUBLE(val64);
|
||||
} else {
|
||||
RETVAL_LONG((zend_long)val64);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FORMAT_TYPE_DOUBLE:
|
||||
RETVAL_DOUBLE(result.getDouble(INTL_DATA_ERROR_CODE(nfo)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
case FORMAT_TYPE_CURRENCY:
|
||||
if (hasThis()) {
|
||||
const char *space;
|
||||
@@ -113,10 +127,6 @@ cleanup:
|
||||
efree(oldlocale);
|
||||
#endif
|
||||
|
||||
if (sstr) {
|
||||
efree(sstr);
|
||||
}
|
||||
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Number parsing failed" );
|
||||
}
|
||||
/* }}} */
|
||||
@@ -124,14 +134,8 @@ cleanup:
|
||||
/* {{{ Parse a number as currency. */
|
||||
U_CFUNC PHP_FUNCTION( numfmt_parse_currency )
|
||||
{
|
||||
double number;
|
||||
UChar currency[5] = {0};
|
||||
UChar* sstr = NULL;
|
||||
int32_t sstr_len = 0;
|
||||
zend_string *u8str;
|
||||
char *str;
|
||||
size_t str_len;
|
||||
int32_t* position_p = NULL;
|
||||
int32_t position = 0;
|
||||
zval *zcurrency, *zposition = NULL;
|
||||
FORMATTER_METHOD_INIT_VARS;
|
||||
@@ -147,27 +151,34 @@ U_CFUNC PHP_FUNCTION( numfmt_parse_currency )
|
||||
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));
|
||||
icu::UnicodeString ustr;
|
||||
intl_stringFromChar(ustr, str, str_len, &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" );
|
||||
|
||||
if(zposition) {
|
||||
position = (int32_t) zval_get_long(zposition);
|
||||
position_p = &position;
|
||||
}
|
||||
|
||||
number = unum_parseDoubleCurrency(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, currency, &INTL_DATA_ERROR_CODE(nfo));
|
||||
icu::ParsePosition pp(position);
|
||||
std::unique_ptr<icu::CurrencyAmount> currAmt(FORMATTER_OBJECT(nfo)->parseCurrency(ustr, pp));
|
||||
|
||||
if (currAmt == nullptr || pp.getErrorIndex() >= 0) {
|
||||
INTL_DATA_ERROR_CODE(nfo) = U_PARSE_ERROR;
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Number parsing failed" );
|
||||
}
|
||||
|
||||
if(zposition) {
|
||||
ZEND_TRY_ASSIGN_REF_LONG(zposition, position);
|
||||
ZEND_TRY_ASSIGN_REF_LONG(zposition, pp.getIndex());
|
||||
}
|
||||
if (sstr) {
|
||||
efree(sstr);
|
||||
}
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Number parsing failed" );
|
||||
|
||||
double number = currAmt->getNumber().getDouble(INTL_DATA_ERROR_CODE(nfo));
|
||||
|
||||
/* Convert parsed currency to UTF-8 and pass it back to caller. */
|
||||
u8str = intl_convert_utf16_to_utf8(currency, u_strlen(currency), &INTL_DATA_ERROR_CODE(nfo));
|
||||
icu::UnicodeString ucurrency(currAmt->getISOCurrency());
|
||||
|
||||
zend_string *u8str = intl_charFromString(ucurrency, &INTL_DATA_ERROR_CODE(nfo));
|
||||
INTL_METHOD_CHECK_STATUS( nfo, "Currency conversion to UTF-8 failed" );
|
||||
ZEND_TRY_ASSIGN_REF_NEW_STR(zcurrency, u8str);
|
||||
ZEND_TRY_ASSIGN_REF_STR(zcurrency, u8str);
|
||||
|
||||
RETVAL_DOUBLE( number );
|
||||
}
|
||||
|
||||
@@ -14,22 +14,27 @@
|
||||
|
||||
extern "C" {
|
||||
#include "php.h"
|
||||
#include "php_intl.h"
|
||||
#include "intl_convert.h"
|
||||
}
|
||||
#include <unicode/ulistformatter.h>
|
||||
|
||||
#include <unicode/listformatter.h>
|
||||
#include <unicode/locid.h>
|
||||
#include "../intl_convertcpp.h"
|
||||
|
||||
extern "C" {
|
||||
#include "php_intl.h"
|
||||
}
|
||||
#include "listformatter_class.h"
|
||||
#include "listformatter_arginfo.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
static zend_object_handlers listformatter_handlers;
|
||||
|
||||
static void listformatter_free_obj(zend_object *object)
|
||||
{
|
||||
ListFormatter_object *obj = php_intl_listformatter_fetch_object(object);
|
||||
|
||||
if( obj->lf_data.ulistfmt )
|
||||
ulistfmt_close( obj->lf_data.ulistfmt );
|
||||
|
||||
delete obj->lf_data.ulistfmt;
|
||||
obj->lf_data.ulistfmt = nullptr;
|
||||
intl_error_reset( &obj->lf_data.error );
|
||||
|
||||
@@ -78,7 +83,7 @@ PHP_METHOD(IntlListFormatter, __construct)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (strlen(uloc_getISO3Language(locale)) == 0) {
|
||||
if (icu::Locale(locale).getISO3Language()[0] == '\0') {
|
||||
zend_argument_value_error(1, "\"%s\" is invalid", locale);
|
||||
RETURN_THROWS();
|
||||
}
|
||||
@@ -89,13 +94,13 @@ PHP_METHOD(IntlListFormatter, __construct)
|
||||
zend_argument_value_error(2, "must be one of IntlListFormatter::TYPE_AND, IntlListFormatter::TYPE_OR, or IntlListFormatter::TYPE_UNITS");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
|
||||
if (width != ULISTFMT_WIDTH_WIDE && width != ULISTFMT_WIDTH_SHORT && width != ULISTFMT_WIDTH_NARROW) {
|
||||
zend_argument_value_error(3, "must be one of IntlListFormatter::WIDTH_WIDE, IntlListFormatter::WIDTH_SHORT, or IntlListFormatter::WIDTH_NARROW");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
LISTFORMATTER_OBJECT(obj) = ulistfmt_openForType(locale, static_cast<UListFormatterType>(type), static_cast<UListFormatterWidth>(width), &status);
|
||||
LISTFORMATTER_OBJECT(obj) = ListFormatter::createInstance(icu::Locale(locale), static_cast<UListFormatterType>(type), static_cast<UListFormatterWidth>(width), status);
|
||||
#else
|
||||
if (type != INTL_LISTFORMATTER_FALLBACK_TYPE_AND) {
|
||||
zend_argument_value_error(2, "contains an unsupported type. ICU 66 and below only support IntlListFormatter::TYPE_AND");
|
||||
@@ -107,7 +112,7 @@ PHP_METHOD(IntlListFormatter, __construct)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
LISTFORMATTER_OBJECT(obj) = ulistfmt_open(locale, &status);
|
||||
LISTFORMATTER_OBJECT(obj) = ListFormatter::createInstance(icu::Locale(locale), status);
|
||||
#endif
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
@@ -131,84 +136,47 @@ PHP_METHOD(IntlListFormatter, format)
|
||||
RETURN_EMPTY_STRING();
|
||||
}
|
||||
|
||||
const UChar **items = (const UChar **)safe_emalloc(count, sizeof(const UChar *), 0);
|
||||
int32_t *itemLengths = (int32_t *)safe_emalloc(count, sizeof(int32_t), 0);
|
||||
std::unique_ptr<UnicodeString[]> items(new UnicodeString[count]);
|
||||
uint32_t i = 0;
|
||||
zval *val;
|
||||
|
||||
ZEND_HASH_FOREACH_VAL(ht, val) {
|
||||
zend_string *str_val, *tmp_str;
|
||||
|
||||
str_val = zval_get_tmp_string(val, &tmp_str);
|
||||
|
||||
// Convert PHP string to UTF-16
|
||||
UChar *ustr = nullptr;
|
||||
int32_t ustr_len = 0;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
intl_convert_utf8_to_utf16(&ustr, &ustr_len, ZSTR_VAL(str_val), ZSTR_LEN(str_val), &status);
|
||||
UErrorCode conv_status = U_ZERO_ERROR;
|
||||
|
||||
str_val = zval_try_get_tmp_string(val, &tmp_str);
|
||||
if (UNEXPECTED(!str_val)) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
intl_stringFromChar(items[i], ZSTR_VAL(str_val), ZSTR_LEN(str_val), &conv_status);
|
||||
zend_tmp_string_release(tmp_str);
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
// We can't use goto cleanup because items and itemLengths are incompletely allocated
|
||||
for (uint32_t j = 0; j < i; j++) {
|
||||
efree((void *)items[j]);
|
||||
}
|
||||
efree(items);
|
||||
efree(itemLengths);
|
||||
intl_error_set(nullptr, status, "Failed to convert string to UTF-16");
|
||||
if (U_FAILURE(conv_status)) {
|
||||
intl_error_set(nullptr, conv_status, "Failed to convert string to UTF-16");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
items[i] = ustr;
|
||||
itemLengths[i] = ustr_len;
|
||||
|
||||
i++;
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t resultLength;
|
||||
UChar *result = nullptr;
|
||||
zend_string *ret = nullptr;
|
||||
UnicodeString result;
|
||||
|
||||
resultLength = ulistfmt_format(LISTFORMATTER_OBJECT(obj), items, itemLengths, count, nullptr, 0, &status);
|
||||
|
||||
if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR) {
|
||||
intl_error_set(nullptr, status, "Failed to format list");
|
||||
RETVAL_FALSE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Allocate buffer and try again
|
||||
status = U_ZERO_ERROR;
|
||||
result = (UChar *)safe_emalloc(resultLength + 1, sizeof(UChar), 0);
|
||||
ulistfmt_format(LISTFORMATTER_OBJECT(obj), items, itemLengths, count, result, resultLength, &status);
|
||||
LISTFORMATTER_OBJECT(obj)->format(items.get(), count, result, status);
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
if (result) {
|
||||
efree(result);
|
||||
}
|
||||
intl_error_set(nullptr, status, "Failed to format list");
|
||||
RETVAL_FALSE;
|
||||
goto cleanup;
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Convert result back to UTF-8
|
||||
ret = intl_convert_utf16_to_utf8(result, resultLength, &status);
|
||||
efree(result);
|
||||
|
||||
zend_string *ret = intl_charFromString(result, &status);
|
||||
|
||||
if (!ret) {
|
||||
intl_error_set(nullptr, status, "Failed to convert result to UTF-8");
|
||||
RETVAL_FALSE;
|
||||
} else {
|
||||
RETVAL_NEW_STR(ret);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
for (i = 0; i < count; i++) {
|
||||
efree((void *)items[i]);
|
||||
}
|
||||
efree(items);
|
||||
efree(itemLengths);
|
||||
RETVAL_STR(ret);
|
||||
}
|
||||
|
||||
PHP_METHOD(IntlListFormatter, getErrorCode)
|
||||
@@ -236,7 +204,7 @@ void listformatter_register_class(void)
|
||||
{
|
||||
zend_class_entry *class_entry = register_class_IntlListFormatter();
|
||||
class_entry->create_object = listformatter_create_object;
|
||||
|
||||
|
||||
memcpy(&listformatter_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
|
||||
listformatter_handlers.offset = offsetof(ListFormatter_object, zo);
|
||||
listformatter_handlers.free_obj = listformatter_free_obj;
|
||||
|
||||
@@ -21,14 +21,20 @@
|
||||
#include "intl_error.h"
|
||||
#include "intl_data.h"
|
||||
|
||||
#include <unicode/ulistformatter.h>
|
||||
#include <unicode/listformatter.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
using icu::ListFormatter;
|
||||
#else
|
||||
typedef void ListFormatter;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
// error handling
|
||||
intl_error error;
|
||||
|
||||
// formatter handling
|
||||
UListFormatter* ulistfmt;
|
||||
ListFormatter* ulistfmt;
|
||||
} listformatter_data;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -22,6 +22,7 @@ extern "C" {
|
||||
#include <unicode/numberrangeformatter.h>
|
||||
#include <unicode/numberformatter.h>
|
||||
#include <unicode/unistr.h>
|
||||
#include <unicode/locid.h>
|
||||
#include "../intl_convertcpp.h"
|
||||
|
||||
extern "C" {
|
||||
@@ -30,7 +31,6 @@ extern "C" {
|
||||
#include "../intl_data.h"
|
||||
#include "rangeformatter_arginfo.h"
|
||||
#include "rangeformatter_class.h"
|
||||
#include "intl_convert.h"
|
||||
}
|
||||
|
||||
using icu::number::NumberRangeFormatter;
|
||||
@@ -91,7 +91,7 @@ U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, createFromSkeleton)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (strlen(uloc_getISO3Language(locale)) == 0) {
|
||||
if (icu::Locale(locale).getISO3Language()[0] == '\0') {
|
||||
zend_argument_value_error(2, "\"%s\" is invalid", locale);
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
@@ -137,9 +137,9 @@ TypeError: numfmt_create(): Argument #1 ($locale) must be of type string, array
|
||||
'U_ZERO_ERROR'
|
||||
|
||||
IntlException: NumberFormatter::__construct(): number formatter creation failed
|
||||
'NumberFormatter::__construct(): number formatter creation failed: U_UNSUPPORTED_ERROR'
|
||||
'NumberFormatter::create(): number formatter creation failed: U_UNSUPPORTED_ERROR'
|
||||
'numfmt_create(): number formatter creation failed: U_UNSUPPORTED_ERROR'
|
||||
'NumberFormatter::__construct(): number formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR'
|
||||
'NumberFormatter::create(): number formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR'
|
||||
'numfmt_create(): number formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR'
|
||||
|
||||
IntlException: NumberFormatter::__construct(): number formatter creation failed
|
||||
'NumberFormatter::__construct(): number formatter creation failed: U_MEMORY_ALLOCATION_ERROR'
|
||||
|
||||
Reference in new issue
Block a user