1414
1515extern " C" {
1616#include " php.h"
17+ }
18+
19+ #include < unicode/listformatter.h>
20+ #include < unicode/locid.h>
21+ #include " ../intl_convertcpp.h"
22+
23+ extern " C" {
1724#include " php_intl.h"
18- #include " intl_convert.h"
1925}
20- #include < unicode/ulistformatter.h>
2126#include " listformatter_class.h"
2227#include " listformatter_arginfo.h"
2328
@@ -27,9 +32,7 @@ static void listformatter_free_obj(zend_object *object)
2732{
2833 ListFormatter_object *obj = php_intl_listformatter_fetch_object (object);
2934
30- if ( obj->lf_data .ulistfmt )
31- ulistfmt_close ( obj->lf_data .ulistfmt );
32-
35+ delete obj->lf_data .ulistfmt ;
3336 obj->lf_data .ulistfmt = nullptr ;
3437 intl_error_reset ( &obj->lf_data .error );
3538
@@ -78,7 +81,7 @@ PHP_METHOD(IntlListFormatter, __construct)
7881 RETURN_THROWS ();
7982 }
8083
81- if (strlen ( uloc_getISO3Language ( locale)) == 0 ) {
84+ if (icu::Locale ( locale). getISO3Language ()[ 0 ] == ' \0 ' ) {
8285 zend_argument_value_error (1 , " \" %s\" is invalid" , locale);
8386 RETURN_THROWS ();
8487 }
@@ -89,13 +92,13 @@ PHP_METHOD(IntlListFormatter, __construct)
8992 zend_argument_value_error (2 , " must be one of IntlListFormatter::TYPE_AND, IntlListFormatter::TYPE_OR, or IntlListFormatter::TYPE_UNITS" );
9093 RETURN_THROWS ();
9194 }
92-
95+
9396 if (width != ULISTFMT_WIDTH_WIDE && width != ULISTFMT_WIDTH_SHORT && width != ULISTFMT_WIDTH_NARROW) {
9497 zend_argument_value_error (3 , " must be one of IntlListFormatter::WIDTH_WIDE, IntlListFormatter::WIDTH_SHORT, or IntlListFormatter::WIDTH_NARROW" );
9598 RETURN_THROWS ();
9699 }
97100
98- LISTFORMATTER_OBJECT (obj) = ulistfmt_openForType ( locale, static_cast <UListFormatterType>(type), static_cast <UListFormatterWidth>(width), & status);
101+ LISTFORMATTER_OBJECT (obj) = ListFormatter::createInstance ( icu::Locale ( locale) , static_cast <UListFormatterType>(type), static_cast <UListFormatterWidth>(width), status);
99102 #else
100103 if (type != INTL_LISTFORMATTER_FALLBACK_TYPE_AND) {
101104 zend_argument_value_error (2 , " contains an unsupported type. ICU 66 and below only support IntlListFormatter::TYPE_AND" );
@@ -107,7 +110,7 @@ PHP_METHOD(IntlListFormatter, __construct)
107110 RETURN_THROWS ();
108111 }
109112
110- LISTFORMATTER_OBJECT (obj) = ulistfmt_open ( locale, & status);
113+ LISTFORMATTER_OBJECT (obj) = ListFormatter::createInstance ( icu::Locale ( locale), status);
111114 #endif
112115
113116 if (U_FAILURE (status)) {
@@ -131,84 +134,50 @@ PHP_METHOD(IntlListFormatter, format)
131134 RETURN_EMPTY_STRING ();
132135 }
133136
134- const UChar **items = (const UChar **)safe_emalloc (count, sizeof (const UChar *), 0 );
135- int32_t *itemLengths = (int32_t *)safe_emalloc (count, sizeof (int32_t ), 0 );
137+ UnicodeString *items = new UnicodeString[count];
136138 uint32_t i = 0 ;
137139 zval *val;
138140
139141 ZEND_HASH_FOREACH_VAL (ht, val) {
140142 zend_string *str_val, *tmp_str;
141-
142- str_val = zval_get_tmp_string (val, &tmp_str);
143-
144- // Convert PHP string to UTF-16
145- UChar *ustr = nullptr ;
146- int32_t ustr_len = 0 ;
147- UErrorCode status = U_ZERO_ERROR;
148-
149- intl_convert_utf8_to_utf16 (&ustr, &ustr_len, ZSTR_VAL (str_val), ZSTR_LEN (str_val), &status);
143+ UErrorCode conv_status = U_ZERO_ERROR;
144+
145+ str_val = zval_try_get_tmp_string (val, &tmp_str);
146+ if (UNEXPECTED (!str_val)) {
147+ delete[] items;
148+ RETURN_THROWS ();
149+ }
150+ intl_stringFromChar (items[i], ZSTR_VAL (str_val), ZSTR_LEN (str_val), &conv_status);
150151 zend_tmp_string_release (tmp_str);
151152
152- if (U_FAILURE (status)) {
153- // We can't use goto cleanup because items and itemLengths are incompletely allocated
154- for (uint32_t j = 0 ; j < i; j++) {
155- efree ((void *)items[j]);
156- }
157- efree (items);
158- efree (itemLengths);
159- intl_error_set (nullptr , status, " Failed to convert string to UTF-16" );
153+ if (U_FAILURE (conv_status)) {
154+ delete[] items;
155+ intl_error_set (nullptr , conv_status, " Failed to convert string to UTF-16" );
160156 RETURN_FALSE;
161157 }
162-
163- items[i] = ustr;
164- itemLengths[i] = ustr_len;
158+
165159 i++;
166160 } ZEND_HASH_FOREACH_END ();
167161
168162 UErrorCode status = U_ZERO_ERROR;
169- int32_t resultLength;
170- UChar *result = nullptr ;
171- zend_string *ret = nullptr ;
172-
173- resultLength = ulistfmt_format (LISTFORMATTER_OBJECT (obj), items, itemLengths, count, nullptr , 0 , &status);
174-
175- if (U_FAILURE (status) && status != U_BUFFER_OVERFLOW_ERROR) {
176- intl_error_set (nullptr , status, " Failed to format list" );
177- RETVAL_FALSE;
178- goto cleanup;
179- }
163+ UnicodeString result;
180164
181- // Allocate buffer and try again
182- status = U_ZERO_ERROR;
183- result = (UChar *)safe_emalloc (resultLength + 1 , sizeof (UChar), 0 );
184- ulistfmt_format (LISTFORMATTER_OBJECT (obj), items, itemLengths, count, result, resultLength, &status);
165+ LISTFORMATTER_OBJECT (obj)->format (items, count, result, status);
166+ delete[] items;
185167
186168 if (U_FAILURE (status)) {
187- if (result) {
188- efree (result);
189- }
190169 intl_error_set (nullptr , status, " Failed to format list" );
191- RETVAL_FALSE;
192- goto cleanup;
170+ RETURN_FALSE;
193171 }
194172
195- // Convert result back to UTF-8
196- ret = intl_convert_utf16_to_utf8 (result, resultLength, &status);
197- efree (result);
198-
173+ zend_string *ret = intl_charFromString (result, &status);
174+
199175 if (!ret) {
200176 intl_error_set (nullptr , status, " Failed to convert result to UTF-8" );
201- RETVAL_FALSE;
202- } else {
203- RETVAL_NEW_STR (ret);
177+ RETURN_FALSE;
204178 }
205179
206- cleanup:
207- for (i = 0 ; i < count; i++) {
208- efree ((void *)items[i]);
209- }
210- efree (items);
211- efree (itemLengths);
180+ RETVAL_STR (ret);
212181}
213182
214183PHP_METHOD (IntlListFormatter, getErrorCode)
@@ -236,7 +205,7 @@ void listformatter_register_class(void)
236205{
237206 zend_class_entry *class_entry = register_class_IntlListFormatter ();
238207 class_entry->create_object = listformatter_create_object;
239-
208+
240209 memcpy (&listformatter_handlers, zend_get_std_object_handlers (), sizeof (zend_object_handlers));
241210 listformatter_handlers.offset = XtOffsetOf (ListFormatter_object, zo);
242211 listformatter_handlers.free_obj = listformatter_free_obj;
0 commit comments