diff options
Diffstat (limited to 'ext/intl')
65 files changed, 1223 insertions, 265 deletions
diff --git a/ext/intl/ERROR.CONVENTIONS b/ext/intl/ERROR.CONVENTIONS index 41cd14ec06..a7ef53665e 100644 --- a/ext/intl/ERROR.CONVENTIONS +++ b/ext/intl/ERROR.CONVENTIONS @@ -21,9 +21,9 @@ intl.use_exceptions you get more fine-grained information about where the error occurred). The internal PHP code can set the global last error with: -void intl_error_set_code(intl_error* err, UErrorCode err_code TSRMLS_DC); -void intl_error_set_custom_msg(intl_error* err, char* msg, int copyMsg TSRMLS_DC); -void intl_error_set(intl_error* err, UErrorCode code, char* msg, int copyMsg TSRMLS_DC); +void intl_error_set_code(intl_error* err, UErrorCode err_code); +void intl_error_set_custom_msg(intl_error* err, char* msg, int copyMsg); +void intl_error_set(intl_error* err, UErrorCode code, char* msg, int copyMsg); and by passing NULL as the first parameter. The last function is a combination of the first two. If the message is not a static buffer, copyMsg should be 1. @@ -44,9 +44,9 @@ typedef struct { The global error and the object error can be SIMULTANEOUSLY set with these functions: -void intl_errors_set_custom_msg(intl_error* err, char* msg, int copyMsg TSRMLS_DC); -void intl_errors_set_code(intl_error* err, UErrorCode err_code TSRMLS_DC); -void intl_errors_set(intl_error* err, UErrorCode code, char* msg, int copyMsg TSRMLS_DC); +void intl_errors_set_custom_msg(intl_error* err, char* msg, int copyMsg); +void intl_errors_set_code(intl_error* err, UErrorCode err_code); +void intl_errors_set(intl_error* err, UErrorCode code, char* msg, int copyMsg); by passing a pointer to the object's intl_error structed as the first parameter. Node the extra 's' in the functions' names ('errors', not 'error'). @@ -79,8 +79,8 @@ Errors should be lost after a function call. This is different from the way ICU operates, where functions return immediately if an error is set. Error resetting can be done with: -void intl_error_reset(NULL TSRMLS_DC); /* reset global error */ -void intl_errors_reset(intl_error* err TSRMLS_DC ); /* reset global and object error */ +void intl_error_reset(NULL); /* reset global error */ +void intl_errors_reset(intl_error* err); /* reset global and object error */ In practice, intl_errors_reset() is not used because most classes have also plain functions mapped to the same internal functions as their instance methods. @@ -97,10 +97,10 @@ U_CFUNC PHP_FUNCTION(breakiter_set_text) BREAKITER_METHOD_INIT_VARS; /* macro also resets global error */ object = getThis(); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &text, &text_len) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "breakiter_set_text: bad arguments", 0 TSRMLS_CC); + "breakiter_set_text: bad arguments", 0); RETURN_FALSE; } diff --git a/ext/intl/calendar/calendar_class.cpp b/ext/intl/calendar/calendar_class.cpp index 6b6feef8d9..574f9a0fc3 100644 --- a/ext/intl/calendar/calendar_class.cpp +++ b/ext/intl/calendar/calendar_class.cpp @@ -177,7 +177,7 @@ static HashTable *Calendar_get_debug_info(zval *object, int *is_temp) HashTable *debug_info_tz; timezone_object_construct(&cal->getTimeZone(), &ztz , 0); - debug_info = Z_OBJ_HANDLER(ztz, get_debug_info)(&ztz, &is_tmp); + debug_info_tz = Z_OBJ_HANDLER(ztz, get_debug_info)(&ztz, &is_tmp); assert(is_tmp == 1); array_init(&ztz_debug); @@ -505,8 +505,6 @@ void calendar_register_IntlCalendar_class(void) CALENDAR_DECL_LONG_CONST("FIELD_AM_PM", UCAL_AM_PM); CALENDAR_DECL_LONG_CONST("FIELD_HOUR", UCAL_HOUR); CALENDAR_DECL_LONG_CONST("FIELD_HOUR_OF_DAY", UCAL_HOUR_OF_DAY); - CALENDAR_DECL_LONG_CONST("FIELD_HOUR", UCAL_HOUR); - CALENDAR_DECL_LONG_CONST("FIELD_HOUR_OF_DAY", UCAL_HOUR_OF_DAY); CALENDAR_DECL_LONG_CONST("FIELD_MINUTE", UCAL_MINUTE); CALENDAR_DECL_LONG_CONST("FIELD_SECOND", UCAL_SECOND); CALENDAR_DECL_LONG_CONST("FIELD_MILLISECOND", UCAL_MILLISECOND); diff --git a/ext/intl/calendar/calendar_methods.cpp b/ext/intl/calendar/calendar_methods.cpp index ac5b33a89c..155ed5f7f4 100644 --- a/ext/intl/calendar/calendar_methods.cpp +++ b/ext/intl/calendar/calendar_methods.cpp @@ -522,48 +522,28 @@ U_CFUNC PHP_FUNCTION(intlcal_roll) U_CFUNC PHP_FUNCTION(intlcal_clear) { - zval args_a[2] = {0}, - *args = &args_a[0]; - zend_long field; - int variant; + zend_long field; + zend_bool field_is_null = 1; CALENDAR_METHOD_INIT_VARS; - if (ZEND_NUM_ARGS() > (getThis() ? 1 : 2) || - zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "intlcal_clear: too many arguments", 0); - RETURN_FALSE; - } - if (!getThis()) { - args++; - } - if (Z_ISUNDEF(args[0]) || Z_TYPE(args[0]) == IS_NULL) { - zval *dummy; /* we know it's null */ - if (zend_parse_method_parameters(ZEND_NUM_ARGS(), - getThis(), "O|z", &object, Calendar_ce_ptr, &dummy) == FAILURE) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "intlcal_clear: bad arguments", 0); - RETURN_FALSE; - } - variant = 0; - } else if (zend_parse_method_parameters(ZEND_NUM_ARGS(), - getThis(), "Ol", &object, Calendar_ce_ptr, &field) == FAILURE) { + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), + getThis(), "O|l!", &object, Calendar_ce_ptr, &field, &field_is_null) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "intlcal_clear: bad arguments", 0); RETURN_FALSE; - } else if (field < 0 || field >= UCAL_FIELD_COUNT) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "intlcal_clear: invalid field", 0); - RETURN_FALSE; - } else { - variant = 1; } CALENDAR_METHOD_FETCH_OBJECT; - if (variant == 0) { + if (field_is_null) { co->ucal->clear(); } else { + if (field < 0 || field >= UCAL_FIELD_COUNT) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "intlcal_clear: invalid field", 0); + RETURN_FALSE; + } + co->ucal->clear((UCalendarDateFields)field); } @@ -614,7 +594,7 @@ U_CFUNC PHP_FUNCTION(intlcal_get_actual_minimum) #if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 44 U_CFUNC PHP_FUNCTION(intlcal_get_day_of_week_type) { - zend_ulong dow; + zend_long dow; CALENDAR_METHOD_INIT_VARS; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), @@ -923,15 +903,11 @@ U_CFUNC PHP_FUNCTION(intlcal_is_set) U_CFUNC PHP_FUNCTION(intlcal_is_weekend) { double date; - zval *rawDate = NULL; + zend_bool date_is_null = 1; CALENDAR_METHOD_INIT_VARS; - if (zend_parse_method_parameters_ex(ZEND_PARSE_PARAMS_QUIET, - ZEND_NUM_ARGS(), getThis(), - "O|z!", &object, Calendar_ce_ptr, &rawDate) == FAILURE - || (rawDate != NULL && - zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), - "O|d", &object, Calendar_ce_ptr, &date) == FAILURE)) { + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), + "O|d!", &object, Calendar_ce_ptr, &date, &date_is_null) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "intlcal_is_weekend: bad arguments", 0); RETURN_FALSE; @@ -939,7 +915,7 @@ U_CFUNC PHP_FUNCTION(intlcal_is_weekend) CALENDAR_METHOD_FETCH_OBJECT; - if (rawDate == NULL) { + if (date_is_null) { RETURN_BOOL((int)co->ucal->isWeekend()); } else { UBool ret = co->ucal->isWeekend((UDate)date, CALENDAR_ERROR_CODE(co)); diff --git a/ext/intl/collator/collator_convert.c b/ext/intl/collator/collator_convert.c index 8f06c8f1ca..2d431a19d6 100644 --- a/ext/intl/collator/collator_convert.c +++ b/ext/intl/collator/collator_convert.c @@ -28,12 +28,6 @@ #include <unicode/ustring.h> #include <php.h> -#if PHP_VERSION_ID <= 50100 -#define CAST_OBJECT_SHOULD_FREE ,0 -#else -#define CAST_OBJECT_SHOULD_FREE -#endif - #define COLLATOR_CONVERT_RETURN_FAILED(retval) { \ Z_TRY_ADDREF_P(retval); \ return retval; \ @@ -258,7 +252,7 @@ zval* collator_convert_object_to_string( zval* obj, zval *rv ) { zstr = rv; - if( Z_OBJ_HT_P(obj)->cast_object( obj, zstr, IS_STRING CAST_OBJECT_SHOULD_FREE ) == FAILURE ) + if( Z_OBJ_HT_P(obj)->cast_object( obj, zstr, IS_STRING ) == FAILURE ) { /* cast_object failed => bail out. */ zval_ptr_dtor( zstr ); diff --git a/ext/intl/collator/collator_is_numeric.c b/ext/intl/collator/collator_is_numeric.c index 6b0568dd64..4f6efbfa6d 100644 --- a/ext/intl/collator/collator_is_numeric.c +++ b/ext/intl/collator/collator_is_numeric.c @@ -17,17 +17,6 @@ #include "collator_is_numeric.h" -#if ZEND_MODULE_API_NO < 20071006 -/* not 5.3 */ -#ifndef ALLOCA_FLAG -#define ALLOCA_FLAG(use_heap) -#endif -#define _do_alloca(x, y) do_alloca((x)) -#define _free_alloca(x, y) free_alloca((x)) -#else -#define _do_alloca do_alloca -#define _free_alloca free_alloca -#endif /* {{{ collator_u_strtod * Taken from PHP6:zend_u_strtod() */ @@ -87,7 +76,7 @@ static double collator_u_strtod(const UChar *nptr, UChar **endptr) /* {{{ */ if (length < sizeof(buf)) { numbuf = buf; } else { - numbuf = (char *) _do_alloca(length + 1, use_heap); + numbuf = (char *) do_alloca(length + 1, use_heap); } bufpos = numbuf; @@ -100,7 +89,7 @@ static double collator_u_strtod(const UChar *nptr, UChar **endptr) /* {{{ */ value = zend_strtod(numbuf, NULL); if (numbuf != buf) { - _free_alloca(numbuf, use_heap); + free_alloca(numbuf, use_heap); } if (endptr != NULL) { diff --git a/ext/intl/collator/collator_sort.c b/ext/intl/collator/collator_sort.c index 8727c1d8ab..1ad42d3660 100644 --- a/ext/intl/collator/collator_sort.c +++ b/ext/intl/collator/collator_sort.c @@ -144,7 +144,6 @@ static int collator_regular_compare_function(zval *result, zval *op1, zval *op2) */ static int collator_numeric_compare_function(zval *result, zval *op1, zval *op2) { - int rc = SUCCESS; zval num1, num2; zval *num1_p = NULL; zval *num2_p = NULL; @@ -161,14 +160,14 @@ static int collator_numeric_compare_function(zval *result, zval *op1, zval *op2) op2 = num2_p; } - rc = numeric_compare_function( result, op1, op2); + ZVAL_LONG(result, numeric_compare_function(op1, op2)); if( num1_p ) zval_ptr_dtor( num1_p ); if( num2_p ) zval_ptr_dtor( num2_p ); - return rc; + return SUCCESS; } /* }}} */ @@ -310,7 +309,7 @@ static void collator_sort_internal( int renumber, INTERNAL_FUNCTION_PARAMETERS ) /* Set 'compare function' according to sort flags. */ INTL_G(compare_func) = collator_get_compare_function( sort_flags ); - hash = HASH_OF( array ); + hash = Z_ARRVAL_P( array ); /* Convert strings in the specified array from UTF-8 to UTF-16. */ collator_convert_hash_from_utf8_to_utf16( hash, COLLATOR_ERROR_CODE_P( co ) ); @@ -364,6 +363,7 @@ static void collator_sortkey_swap(collator_sort_key_index_t *p, collator_sort_ke PHP_FUNCTION( collator_sort_with_sort_keys ) { zval* array = NULL; + zval garbage; HashTable* hash = NULL; zval* hashData = NULL; /* currently processed item of input hash */ @@ -385,8 +385,6 @@ PHP_FUNCTION( collator_sort_with_sort_keys ) int utf16_buf_size = DEF_UTF16_BUF_SIZE; /* the length of utf16_buf */ int utf16_len = 0; /* length of converted string */ - HashTable* sortedHash = NULL; - COLLATOR_METHOD_INIT_VARS /* Parse parameters. */ @@ -414,7 +412,7 @@ PHP_FUNCTION( collator_sort_with_sort_keys ) /* * Sort specified array. */ - hash = HASH_OF( array ); + hash = Z_ARRVAL_P( array ); if( !hash || zend_hash_num_elements( hash ) == 0 ) RETURN_TRUE; @@ -508,7 +506,7 @@ PHP_FUNCTION( collator_sort_with_sort_keys ) zend_sort( sortKeyIndxBuf, sortKeyCount, sortKeyIndxSize, collator_cmp_sort_keys, (swap_func_t)collator_sortkey_swap); - zval_ptr_dtor( array ); + ZVAL_COPY_VALUE(&garbage, array); /* for resulting hash we'll assign new hash keys rather then reordering */ array_init(array); @@ -521,6 +519,7 @@ PHP_FUNCTION( collator_sort_with_sort_keys ) if( utf16_buf ) efree( utf16_buf ); + zval_ptr_dtor(&garbage); efree( sortKeyIndxBuf ); efree( sortKeyBuf ); diff --git a/ext/intl/common/common_enum.cpp b/ext/intl/common/common_enum.cpp index e76f3b830f..0531a6b933 100644 --- a/ext/intl/common/common_enum.cpp +++ b/ext/intl/common/common_enum.cpp @@ -183,7 +183,7 @@ static zend_object_iterator *IntlIterator_get_iterator( return NULL; } - ++GC_REFCOUNT(ii->iterator); + ++GC_REFCOUNT(&ii->iterator->std); return ii->iterator; } diff --git a/ext/intl/dateformat/dateformat_create.cpp b/ext/intl/dateformat/dateformat_create.cpp index 1999b6a8c1..00a5cc593c 100644 --- a/ext/intl/dateformat/dateformat_create.cpp +++ b/ext/intl/dateformat/dateformat_create.cpp @@ -36,46 +36,51 @@ extern "C" { #include "dateformat_helpers.h" #include "zend_exceptions.h" +#if U_ICU_VERSION_MAJOR_NUM < 50 +#define UDAT_PATTERN 0 +#endif + +#define INTL_UDATE_FMT_OK(i) \ + (UDAT_FULL == (i) || UDAT_LONG == (i) || \ + UDAT_MEDIUM == (i) || UDAT_SHORT == (i) || \ + UDAT_RELATIVE == (i) || UDAT_FULL_RELATIVE == (i) || \ + UDAT_LONG_RELATIVE == (i) || UDAT_MEDIUM_RELATIVE == (i) || \ + UDAT_SHORT_RELATIVE == (i) || UDAT_NONE == (i) || \ + UDAT_PATTERN == (i)) + /* {{{ */ static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor) { zval *object; - const char *locale_str; - size_t locale_len = 0; + size_t locale_len = 0; Locale locale; - zend_long date_type = 0; - zend_long time_type = 0; + zend_long date_type = 0; + zend_long time_type = 0; zval *calendar_zv = NULL; - Calendar *calendar = NULL; + Calendar *calendar = NULL; zend_long calendar_type; bool calendar_owned; zval *timezone_zv = NULL; - TimeZone *timezone = NULL; + TimeZone *timezone = NULL; bool explicit_tz; - char* pattern_str = NULL; - size_t pattern_str_len = 0; - UChar* svalue = NULL; /* UTF-16 pattern_str */ - int32_t slength = 0; + char* pattern_str = NULL; + size_t pattern_str_len = 0; + UChar* svalue = NULL; /* UTF-16 pattern_str */ + int32_t slength = 0; IntlDateFormatter_object* dfo; int zpp_flags = is_constructor ? ZEND_PARSE_PARAMS_THROW : 0; intl_error_reset(NULL); object = return_value; /* Parse parameters. */ - if (zend_parse_parameters_ex(zpp_flags, ZEND_NUM_ARGS(), "sll|zzs", + if (zend_parse_parameters_ex(zpp_flags, ZEND_NUM_ARGS(), "sll|zzs", &locale_str, &locale_len, &date_type, &time_type, &timezone_zv, &calendar_zv, &pattern_str, &pattern_str_len) == FAILURE) { intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: " "unable to parse input parameters", 0); return FAILURE; - } - - INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len); - if (locale_len == 0) { - locale_str = intl_locale_get_default(); } - locale = Locale::createFromName(locale_str); DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK; @@ -85,6 +90,21 @@ static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor) return FAILURE; } + if (!INTL_UDATE_FMT_OK(date_type)) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: invalid date format style", 0); + return FAILURE; + } + if (!INTL_UDATE_FMT_OK(time_type)) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: invalid time format style", 0); + return FAILURE; + } + + INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len); + if (locale_len == 0) { + locale_str = intl_locale_get_default(); + } + locale = Locale::createFromName(locale_str); + /* process calendar */ if (datefmt_process_calendar_arg(calendar_zv, locale, "datefmt_create", INTL_DATA_ERROR_P(dfo), calendar, calendar_type, @@ -117,17 +137,19 @@ static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor) } } + DATE_FORMAT_OBJECT(dfo) = udat_open((UDateFormatStyle)time_type, + (UDateFormatStyle)date_type, locale_str, NULL, 0, svalue, + slength, &INTL_DATA_ERROR_CODE(dfo)); + if (pattern_str && pattern_str_len > 0) { - DATE_FORMAT_OBJECT(dfo) = udat_open(UDAT_IGNORE, UDAT_IGNORE, - locale_str, NULL, 0, svalue, slength, - &INTL_DATA_ERROR_CODE(dfo)); - } else { - DATE_FORMAT_OBJECT(dfo) = udat_open((UDateFormatStyle)time_type, - (UDateFormatStyle)date_type, locale_str, NULL, 0, svalue, - slength, &INTL_DATA_ERROR_CODE(dfo)); + udat_applyPattern(DATE_FORMAT_OBJECT(dfo), true, svalue, slength); + if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: error applying pattern", 0); + goto error; + } } - if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { DateFormat *df = (DateFormat*)DATE_FORMAT_OBJECT(dfo); if (calendar_owned) { df->adoptCalendar(calendar); @@ -139,7 +161,7 @@ static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor) if (timezone != NULL) { df->adoptTimeZone(timezone); } - } else { + } else { intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: date " "formatter creation failed", 0); goto error; diff --git a/ext/intl/dateformat/dateformat_format_object.cpp b/ext/intl/dateformat/dateformat_format_object.cpp index 3be76332a8..e96ebe8243 100644 --- a/ext/intl/dateformat/dateformat_format_object.cpp +++ b/ext/intl/dateformat/dateformat_format_object.cpp @@ -146,7 +146,9 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object) } //there's no support for relative time in ICU yet - timeStyle = (DateFormat::EStyle)(timeStyle & ~DateFormat::kRelative); + if (timeStyle != DateFormat::NONE) { + timeStyle = (DateFormat::EStyle)(timeStyle & ~DateFormat::kRelative); + } zend_class_entry *instance_ce = Z_OBJCE_P(object); if (instanceof_function(instance_ce, Calendar_ce_ptr)) { @@ -188,11 +190,11 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object) } if (pattern) { - df = new SimpleDateFormat( - UnicodeString(Z_STRVAL_P(format), Z_STRLEN_P(format), - UnicodeString::kInvariant), - Locale::createFromName(locale_str), - status); + StringPiece sp(Z_STRVAL_P(format)); + df = new SimpleDateFormat( + UnicodeString::fromUTF8(sp), + Locale::createFromName(locale_str), + status); if (U_FAILURE(status)) { intl_error_set(NULL, status, diff --git a/ext/intl/formatter/formatter_format.c b/ext/intl/formatter/formatter_format.c index 5307e426eb..369756ebdb 100644 --- a/ext/intl/formatter/formatter_format.c +++ b/ext/intl/formatter/formatter_format.c @@ -68,7 +68,6 @@ PHP_FUNCTION( numfmt_format ) } if(Z_TYPE_P(number) != IS_DOUBLE && Z_TYPE_P(number) != IS_LONG) { - SEPARATE_ZVAL_IF_NOT_REF(number); convert_scalar_to_number(number ); } diff --git a/ext/intl/grapheme/grapheme_string.c b/ext/intl/grapheme/grapheme_string.c index b5a1902025..0735a7e822 100644 --- a/ext/intl/grapheme/grapheme_string.c +++ b/ext/intl/grapheme/grapheme_string.c @@ -110,7 +110,7 @@ PHP_FUNCTION(grapheme_strpos) size_t haystack_len, needle_len; const char *found; zend_long loffset = 0; - int32_t offset = 0; + int32_t offset = 0, noffset = 0; zend_long ret_pos; if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|l", &haystack, &haystack_len, &needle, &needle_len, &loffset) == FAILURE) { @@ -126,6 +126,7 @@ PHP_FUNCTION(grapheme_strpos) /* we checked that it will fit: */ offset = (int32_t) loffset; + noffset = offset >= 0 ? offset : haystack_len + offset; /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ @@ -134,20 +135,21 @@ PHP_FUNCTION(grapheme_strpos) RETURN_FALSE; } + if (offset >= 0) { + /* quick check to see if the string might be there + * I realize that 'offset' is 'grapheme count offset' but will work in spite of that + */ + found = php_memnstr(haystack + noffset, needle, needle_len, haystack + haystack_len); - /* quick check to see if the string might be there - * I realize that 'offset' is 'grapheme count offset' but will work in spite of that - */ - found = php_memnstr(haystack + offset, needle, needle_len, haystack + haystack_len); - - /* if it isn't there the we are done */ - if (!found) { - RETURN_FALSE; - } + /* if it isn't there the we are done */ + if (!found) { + RETURN_FALSE; + } - /* if it is there, and if the haystack is ascii, we are all done */ - if ( grapheme_ascii_check((unsigned char *)haystack, haystack_len) >= 0 ) { - RETURN_LONG(found - haystack); + /* if it is there, and if the haystack is ascii, we are all done */ + if ( grapheme_ascii_check((unsigned char *)haystack, haystack_len) >= 0 ) { + RETURN_LONG(found - haystack); + } } /* do utf16 part of the strpos */ @@ -195,16 +197,16 @@ PHP_FUNCTION(grapheme_stripos) RETURN_FALSE; } - is_ascii = ( grapheme_ascii_check((unsigned char*)haystack, haystack_len) >= 0 ); if ( is_ascii ) { + int32_t noffset = offset >= 0 ? offset : haystack_len + offset; needle_dup = estrndup(needle, needle_len); php_strtolower(needle_dup, needle_len); haystack_dup = estrndup(haystack, haystack_len); php_strtolower(haystack_dup, haystack_len); - found = php_memnstr(haystack_dup + offset, needle_dup, needle_len, haystack_dup + haystack_len); + found = php_memnstr(haystack_dup + noffset, needle_dup, needle_len, haystack_dup + haystack_len); efree(haystack_dup); efree(needle_dup); @@ -383,9 +385,9 @@ PHP_FUNCTION(grapheme_substr) UBreakIterator* bi = NULL; int sub_str_start_pos, sub_str_end_pos; int32_t (*iter_func)(UBreakIterator *); - int no_length = 1; + zend_bool no_length = 1; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|l!", (char **)&str, &str_len, &lstart, &length, &no_length) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|l!", &str, &str_len, &lstart, &length, &no_length) == FAILURE) { intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_substr: unable to parse input param", 0 ); RETURN_FALSE; @@ -802,6 +804,10 @@ PHP_FUNCTION(grapheme_extract) RETURN_FALSE; } + if (lstart < 0) { + lstart += str_len; + } + if ( NULL != next ) { if ( !Z_ISREF_P(next) ) { intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, @@ -810,7 +816,7 @@ PHP_FUNCTION(grapheme_extract) } else { ZVAL_DEREF(next); /* initialize next */ - SEPARATE_ZVAL(next); + SEPARATE_ZVAL_NOREF(next); zval_dtor(next); ZVAL_LONG(next, lstart); } diff --git a/ext/intl/intl_data.h b/ext/intl/intl_data.h index 12e0a9924e..74b7092fbb 100644 --- a/ext/intl/intl_data.h +++ b/ext/intl/intl_data.h @@ -45,7 +45,7 @@ typedef struct _intl_data { obj = Z_##oclass##_P( object ); \ intl_error_reset( INTL_DATA_ERROR_P(obj) ); \ -/* Check status by error code, if error - exit */ +/* Check status by error code, if error return false */ #define INTL_CHECK_STATUS(err, msg) \ intl_error_set_code( NULL, (err) ); \ if( U_FAILURE((err)) ) \ @@ -54,6 +54,16 @@ typedef struct _intl_data { RETURN_FALSE; \ } +/* Check status by error code, if error return null */ +#define INTL_CHECK_STATUS_OR_NULL(err, msg) \ + intl_error_set_code( NULL, (err) ); \ + if( U_FAILURE((err)) ) \ + { \ + intl_error_set_custom_msg( NULL, msg, 0 ); \ + RETURN_NULL(); \ + } + + /* Check status in object, if error return false */ #define INTL_METHOD_CHECK_STATUS(obj, msg) \ intl_error_set_code( NULL, INTL_DATA_ERROR_CODE((obj)) ); \ diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c index 895d803ef9..857c14a005 100644 --- a/ext/intl/locale/locale_methods.c +++ b/ext/intl/locale/locale_methods.c @@ -256,9 +256,9 @@ PHP_NAMED_FUNCTION(zif_locale_set_default) * common code shared by get_primary_language,get_script or get_region or get_variant * result = 0 if error, 1 if successful , -1 if no value */ -static char* get_icu_value_internal( const char* loc_name , char* tag_name, int* result , int fromParseLocale) +static zend_string* get_icu_value_internal( const char* loc_name , char* tag_name, int* result , int fromParseLocale) { - char* tag_value = NULL; + zend_string* tag_value = NULL; int32_t tag_value_len = 512; int singletonPos = 0; @@ -274,7 +274,7 @@ static char* get_icu_value_internal( const char* loc_name , char* tag_name, int* grOffset = findOffset( LOC_GRANDFATHERED , loc_name ); if( grOffset >= 0 ){ if( strcmp(tag_name , LOC_LANG_TAG)==0 ){ - return estrdup(loc_name); + return zend_string_init(loc_name, strlen(loc_name), 0); } else { /* Since Grandfathered , no value , do nothing , retutn NULL */ return NULL; @@ -285,7 +285,7 @@ static char* get_icu_value_internal( const char* loc_name , char* tag_name, int* /* Handle singletons */ if( strcmp(tag_name , LOC_LANG_TAG)==0 ){ if( strlen(loc_name)>1 && (isIDPrefix(loc_name) == 1) ){ - return estrdup(loc_name); + return zend_string_init(loc_name, strlen(loc_name), 0); } } @@ -308,36 +308,41 @@ static char* get_icu_value_internal( const char* loc_name , char* tag_name, int* } /* Proceed to ICU */ - do{ - tag_value = erealloc( tag_value , buflen ); + do{ + if (tag_value) { + tag_value = zend_string_realloc( tag_value , buflen, 0); + } else { + tag_value = zend_string_alloc( buflen, 0); + } tag_value_len = buflen; if( strcmp(tag_name , LOC_SCRIPT_TAG)==0 ){ - buflen = uloc_getScript ( mod_loc_name ,tag_value , tag_value_len , &status); + buflen = uloc_getScript ( mod_loc_name , tag_value->val , tag_value_len , &status); } if( strcmp(tag_name , LOC_LANG_TAG )==0 ){ - buflen = uloc_getLanguage ( mod_loc_name ,tag_value , tag_value_len , &status); + buflen = uloc_getLanguage ( mod_loc_name , tag_value->val , tag_value_len , &status); } if( strcmp(tag_name , LOC_REGION_TAG)==0 ){ - buflen = uloc_getCountry ( mod_loc_name ,tag_value , tag_value_len , &status); + buflen = uloc_getCountry ( mod_loc_name , tag_value->val , tag_value_len , &status); } if( strcmp(tag_name , LOC_VARIANT_TAG)==0 ){ - buflen = uloc_getVariant ( mod_loc_name ,tag_value , tag_value_len , &status); + buflen = uloc_getVariant ( mod_loc_name , tag_value->val , tag_value_len , &status); } if( strcmp(tag_name , LOC_CANONICALIZE_TAG)==0 ){ - buflen = uloc_canonicalize ( mod_loc_name ,tag_value , tag_value_len , &status); + buflen = uloc_canonicalize ( mod_loc_name , tag_value->val , tag_value_len , &status); } if( U_FAILURE( status ) ) { if( status == U_BUFFER_OVERFLOW_ERROR ) { status = U_ZERO_ERROR; + buflen++; /* add space for \0 */ continue; } /* Error in retriving data */ *result = 0; if( tag_value ){ - efree( tag_value ); + zend_string_release( tag_value ); } if( mod_loc_name ){ efree( mod_loc_name); @@ -350,7 +355,7 @@ static char* get_icu_value_internal( const char* loc_name , char* tag_name, int* /* No value found */ *result = -1; if( tag_value ){ - efree( tag_value ); + zend_string_release( tag_value ); } if( mod_loc_name ){ efree( mod_loc_name); @@ -363,6 +368,8 @@ static char* get_icu_value_internal( const char* loc_name , char* tag_name, int* if( mod_loc_name ){ efree( mod_loc_name); } + + tag_value->len = strlen(tag_value->val); return tag_value; } /* }}} */ @@ -377,7 +384,7 @@ static void get_icu_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS) const char* loc_name = NULL; size_t loc_name_len = 0; - char* tag_value = NULL; + zend_string* tag_value = NULL; char* empty_result = ""; int result = 0; @@ -406,16 +413,14 @@ static void get_icu_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS) /* No value found */ if( result == -1 ) { if( tag_value){ - efree( tag_value); + zend_string_release( tag_value); } RETURN_STRING( empty_result); } /* value found */ if( tag_value){ - RETVAL_STRING( tag_value ); - //??? - efree(tag_value); + RETVAL_STR( tag_value ); return; } @@ -822,7 +827,7 @@ static int append_multiple_key_values(smart_str* loc_name, HashTable* hash_arr, smart_str_appendl(loc_name, Z_STRVAL_P(ele_value) , Z_STRLEN_P(ele_value)); return SUCCESS; } else if(Z_TYPE_P(ele_value) == IS_ARRAY ) { - HashTable *arr = HASH_OF(ele_value); + HashTable *arr = Z_ARRVAL_P(ele_value); zval *data; ZEND_HASH_FOREACH_VAL(arr, data) { @@ -918,7 +923,7 @@ PHP_FUNCTION(locale_compose) RETURN_FALSE; } - hash_arr = HASH_OF( arr ); + hash_arr = Z_ARRVAL_P( arr ); if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 ) RETURN_FALSE; @@ -985,9 +990,9 @@ PHP_FUNCTION(locale_compose) * e.g. for locale='en_US-x-prv1-prv2-prv3' * returns a pointer to the string 'prv1-prv2-prv3' */ -static char* get_private_subtags(const char* loc_name) +static zend_string* get_private_subtags(const char* loc_name) { - char* result =NULL; + zend_string* result =NULL; int singletonPos = 0; int len =0; const char* mod_loc_name =NULL; @@ -1005,7 +1010,7 @@ static char* get_private_subtags(const char* loc_name) } else{ /* result = mod_loc_name + singletonPos +2; */ - result = estrndup(mod_loc_name + singletonPos+2 , (len -( singletonPos +2) ) ); + result = zend_string_init(mod_loc_name + singletonPos+2 , (len -( singletonPos +2) ), 0); } break; } @@ -1032,7 +1037,7 @@ static char* get_private_subtags(const char* loc_name) */ static int add_array_entry(const char* loc_name, zval* hash_arr, char* key_name) { - char* key_value = NULL; + zend_string* key_value = NULL; char* cur_key_name = NULL; char* token = NULL; char* last_ptr = NULL; @@ -1052,7 +1057,7 @@ static int add_array_entry(const char* loc_name, zval* hash_arr, char* key_name) ( strcmp(key_name , LOC_VARIANT_TAG)==0) ){ if( result > 0 && key_value){ /* Tokenize on the "_" or "-" */ - token = php_strtok_r( key_value , DELIMITER ,&last_ptr); + token = php_strtok_r( key_value->val , DELIMITER ,&last_ptr); if( cur_key_name ){ efree( cur_key_name); } @@ -1069,10 +1074,15 @@ static int add_array_entry(const char* loc_name, zval* hash_arr, char* key_name) } */ } + if (key_value) { + zend_string_release(key_value); + } } else { if( result == 1 ){ - add_assoc_string( hash_arr, key_name , key_value); + add_assoc_str( hash_arr, key_name , key_value); cur_result = 1; + } else if (key_value) { + zend_string_release(key_value); } } @@ -1080,9 +1090,6 @@ static int add_array_entry(const char* loc_name, zval* hash_arr, char* key_name) efree( cur_key_name); } /*if( key_name != LOC_PRIVATE_TAG && key_value){*/ - if( key_value){ - efree(key_value); - } return cur_result; } /* }}} */ @@ -1144,7 +1151,7 @@ PHP_FUNCTION(locale_get_all_variants) int result = 0; char* token = NULL; - char* variant = NULL; + zend_string* variant = NULL; char* saved_ptr = NULL; intl_error_reset( NULL ); @@ -1174,7 +1181,7 @@ PHP_FUNCTION(locale_get_all_variants) variant = get_icu_value_internal( loc_name , LOC_VARIANT_TAG , &result ,0); if( result > 0 && variant){ /* Tokenize on the "_" or "-" */ - token = php_strtok_r( variant , DELIMITER , &saved_ptr); + token = php_strtok_r( variant->val , DELIMITER , &saved_ptr); add_next_index_stringl( return_value, token , strlen(token)); /* tokenize on the "_" or "-" and stop at singleton if any */ while( (token = php_strtok_r(NULL , DELIMITER, &saved_ptr)) && (strlen(token)>1) ){ @@ -1182,7 +1189,7 @@ PHP_FUNCTION(locale_get_all_variants) } } if( variant ){ - efree( variant ); + zend_string_release( variant ); } } @@ -1241,8 +1248,8 @@ PHP_FUNCTION(locale_filter_matches) char* token = 0; char* chrcheck = NULL; - char* can_lang_tag = NULL; - char* can_loc_range = NULL; + zend_string* can_lang_tag = NULL; + zend_string* can_loc_range = NULL; char* cur_lang_tag = NULL; char* cur_loc_range = NULL; @@ -1288,23 +1295,23 @@ PHP_FUNCTION(locale_filter_matches) } /* Convert to lower case for case-insensitive comparison */ - cur_lang_tag = ecalloc( 1, strlen(can_lang_tag) + 1); + cur_lang_tag = ecalloc( 1, can_lang_tag->len + 1); /* Convert to lower case for case-insensitive comparison */ - result = strToMatch( can_lang_tag , cur_lang_tag); + result = strToMatch( can_lang_tag->val , cur_lang_tag); if( result == 0) { efree( cur_lang_tag ); - efree( can_lang_tag ); + zend_string_release( can_lang_tag ); RETURN_FALSE; } - cur_loc_range = ecalloc( 1, strlen(can_loc_range) + 1); - result = strToMatch( can_loc_range , cur_loc_range ); + cur_loc_range = ecalloc( 1, can_loc_range->len + 1); + result = strToMatch( can_loc_range->val , cur_loc_range ); if( result == 0) { efree( cur_lang_tag ); - efree( can_lang_tag ); + zend_string_release( can_lang_tag ); efree( cur_loc_range ); - efree( can_loc_range ); + zend_string_release( can_loc_range ); RETURN_FALSE; } @@ -1322,10 +1329,10 @@ PHP_FUNCTION(locale_filter_matches) efree( cur_loc_range ); } if( can_lang_tag){ - efree( can_lang_tag ); + zend_string_release( can_lang_tag ); } if( can_loc_range){ - efree( can_loc_range ); + zend_string_release( can_loc_range ); } RETURN_TRUE; } @@ -1339,10 +1346,10 @@ PHP_FUNCTION(locale_filter_matches) efree( cur_loc_range ); } if( can_lang_tag){ - efree( can_lang_tag ); + zend_string_release( can_lang_tag ); } if( can_loc_range){ - efree( can_loc_range ); + zend_string_release( can_loc_range ); } RETURN_FALSE; @@ -1416,12 +1423,12 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int cur_arr_len = 0; int result = 0; - char* lang_tag = NULL; + zend_string* lang_tag = NULL; zval* ele_value = NULL; char** cur_arr = NULL; char* cur_loc_range = NULL; - char* can_loc_range = NULL; + zend_string* can_loc_range = NULL; int saved_pos = 0; zend_string* return_value = NULL; @@ -1448,16 +1455,16 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, if(canonicalize) { for(i=0; i<cur_arr_len; i++) { lang_tag = get_icu_value_internal(cur_arr[i*2], LOC_CANONICALIZE_TAG, &result, 0); - if(result != 1 || lang_tag == NULL || !lang_tag[0]) { + if(result != 1 || lang_tag == NULL || !lang_tag->val[0]) { if(lang_tag) { - efree(lang_tag); + zend_string_release(lang_tag); } intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag" , 0); LOOKUP_CLEAN_RETURN(NULL); } - cur_arr[i*2] = erealloc(cur_arr[i*2], strlen(lang_tag)+1); - result = strToMatch(lang_tag, cur_arr[i*2]); - efree(lang_tag); + cur_arr[i*2] = erealloc(cur_arr[i*2], lang_tag->len+1); + result = strToMatch(lang_tag->val, cur_arr[i*2]); + zend_string_release(lang_tag); if(result == 0) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag" , 0); LOOKUP_CLEAN_RETURN(NULL); @@ -1469,15 +1476,15 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, if(canonicalize) { /* Canonicalize the loc_range */ can_loc_range = get_icu_value_internal(loc_range, LOC_CANONICALIZE_TAG, &result , 0); - if( result != 1 || can_loc_range == NULL || !can_loc_range[0]) { + if( result != 1 || can_loc_range == NULL || !can_loc_range->val[0]) { /* Error */ intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize loc_range" , 0 ); if(can_loc_range) { - efree(can_loc_range); + zend_string_release(can_loc_range); } LOOKUP_CLEAN_RETURN(NULL); } else { - loc_range = can_loc_range; + loc_range = can_loc_range->val; } } @@ -1485,7 +1492,7 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, /* convert to lower and replace hyphens */ result = strToMatch(loc_range, cur_loc_range); if(can_loc_range) { - efree(can_loc_range); + zend_string_release(can_loc_range); } if(result == 0) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag" , 0); @@ -1542,10 +1549,14 @@ PHP_FUNCTION(locale_lookup) } if(loc_range_len == 0) { - loc_range = intl_locale_get_default(); + if(fallback_loc_str) { + loc_range = ZSTR_VAL(fallback_loc_str); + } else { + loc_range = intl_locale_get_default(); + } } - hash_arr = HASH_OF(arr); + hash_arr = Z_ARRVAL_P(arr); if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 ) { RETURN_EMPTY_STRING(); diff --git a/ext/intl/msgformat/msgformat.c b/ext/intl/msgformat/msgformat.c index e0919ec42b..d3f8416c03 100644 --- a/ext/intl/msgformat/msgformat.c +++ b/ext/intl/msgformat/msgformat.c @@ -23,6 +23,7 @@ #include "php_intl.h" #include "msgformat_class.h" +#include "msgformat_data.h" #include "intl_convert.h" /* {{{ */ diff --git a/ext/intl/msgformat/msgformat_attr.c b/ext/intl/msgformat/msgformat_attr.c index a20a7e411d..78eb727c61 100644 --- a/ext/intl/msgformat/msgformat_attr.c +++ b/ext/intl/msgformat/msgformat_attr.c @@ -21,11 +21,11 @@ #include "php_intl.h" #include "msgformat_class.h" #include "msgformat_attr.h" +#include "msgformat_data.h" #include "intl_convert.h" #include <unicode/ustring.h> - /* {{{ proto string MessageFormatter::getPattern( ) * Get formatter pattern. }}} */ /* {{{ proto string msgfmt_get_pattern( MessageFormatter $mf ) diff --git a/ext/intl/msgformat/msgformat_format.c b/ext/intl/msgformat/msgformat_format.c index 5aa68e2735..959a4fd5a0 100644 --- a/ext/intl/msgformat/msgformat_format.c +++ b/ext/intl/msgformat/msgformat_format.c @@ -104,7 +104,7 @@ PHP_FUNCTION( msgfmt_format_message ) size_t pattern_len = 0; const char *slocale = NULL; size_t slocale_len = 0; - MessageFormatter_object mf = {0}; + MessageFormatter_object mf; MessageFormatter_object *mfo = &mf; /* Parse parameters. */ @@ -117,6 +117,7 @@ PHP_FUNCTION( msgfmt_format_message ) RETURN_FALSE; } + memset(mfo, 0, sizeof(*mfo)); msgformat_data_init(&mfo->mf_data); if(pattern && pattern_len) { diff --git a/ext/intl/msgformat/msgformat_helpers.cpp b/ext/intl/msgformat/msgformat_helpers.cpp index ed63105fa7..ce7899edd9 100644 --- a/ext/intl/msgformat/msgformat_helpers.cpp +++ b/ext/intl/msgformat/msgformat_helpers.cpp @@ -264,6 +264,10 @@ static HashTable *umsg_parse_format(MessageFormatter_object *mfo, type = Formattable::kDouble; } else if (argType == UMSGPAT_ARG_TYPE_SELECT) { type = Formattable::kString; +#if U_ICU_VERSION_MAJOR_NUM >= 50 + } else if (argType == UMSGPAT_ARG_TYPE_SELECTORDINAL) { + type = Formattable::kDouble; +#endif } else { type = Formattable::kString; } diff --git a/ext/intl/msgformat/msgformat_parse.c b/ext/intl/msgformat/msgformat_parse.c index 4d63a0169a..349633912b 100644 --- a/ext/intl/msgformat/msgformat_parse.c +++ b/ext/intl/msgformat/msgformat_parse.c @@ -97,7 +97,7 @@ PHP_FUNCTION( msgfmt_parse_message ) size_t slocale_len = 0; char *source = NULL; size_t src_len = 0; - MessageFormatter_object mf = {0}; + MessageFormatter_object mf; MessageFormatter_object *mfo = &mf; /* Parse parameters. */ @@ -110,6 +110,7 @@ PHP_FUNCTION( msgfmt_parse_message ) RETURN_FALSE; } + memset(mfo, 0, sizeof(*mfo)); msgformat_data_init(&mfo->mf_data); if(pattern && pattern_len) { diff --git a/ext/intl/php_intl.c b/ext/intl/php_intl.c index 12bd9fdc74..fd35e57120 100644 --- a/ext/intl/php_intl.c +++ b/ext/intl/php_intl.c @@ -892,7 +892,7 @@ zend_module_entry intl_module_entry = { #ifdef COMPILE_DL_INTL #ifdef ZTS -ZEND_TSRMLS_CACHE_DEFINE(); +ZEND_TSRMLS_CACHE_DEFINE() #endif ZEND_GET_MODULE( intl ) #endif diff --git a/ext/intl/php_intl.h b/ext/intl/php_intl.h index 638fdef1ca..e672e54087 100644 --- a/ext/intl/php_intl.h +++ b/ext/intl/php_intl.h @@ -55,17 +55,13 @@ ZEND_BEGIN_MODULE_GLOBALS(intl) zend_bool use_exceptions; ZEND_END_MODULE_GLOBALS(intl) -/* Macro to access request-wide global variables. */ -#ifdef ZTS -#define INTL_G(v) ZEND_TSRMG(intl_globals_id, zend_intl_globals *, v) -#ifdef COMPILE_DL_INTL -ZEND_TSRMLS_CACHE_EXTERN(); -#endif -#else -#define INTL_G(v) (intl_globals.v) +#if defined(ZTS) && defined(COMPILE_DL_INTL) +ZEND_TSRMLS_CACHE_EXTERN() #endif ZEND_EXTERN_MODULE_GLOBALS(intl) +/* Macro to access request-wide global variables. */ +#define INTL_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(intl, v) PHP_MINIT_FUNCTION(intl); PHP_MSHUTDOWN_FUNCTION(intl); diff --git a/ext/intl/resourcebundle/resourcebundle_class.c b/ext/intl/resourcebundle/resourcebundle_class.c index d6b071a249..fd255d57cd 100644 --- a/ext/intl/resourcebundle/resourcebundle_class.c +++ b/ext/intl/resourcebundle/resourcebundle_class.c @@ -49,8 +49,6 @@ static void ResourceBundle_object_destroy( zend_object *object ) if (rb->child) { ures_close( rb->child ); } - - //???zend_object_std_dtor( object ); } /* }}} */ diff --git a/ext/intl/tests/bug53735.phpt b/ext/intl/tests/bug53735.phpt new file mode 100644 index 0000000000..5fc14e978c --- /dev/null +++ b/ext/intl/tests/bug53735.phpt @@ -0,0 +1,32 @@ +--TEST-- +Bug #53735 NumberFormatter returns NaN when converting float point +--SKIPIF-- +<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +<?php if (version_compare(INTL_ICU_VERSION, '51.2') < 0) die('skip for ICU >= 51.2'); ?> +--FILE-- +<?php + +$fmt = numfmt_create("da_DK", \NumberFormatter::CURRENCY); + +var_dump(numfmt_format($fmt, 5.5)); +setlocale(LC_ALL, "da_DK.UTF-8"); + +var_dump(numfmt_format($fmt, 5.5)); +var_dump(numfmt_format($fmt, "5,5")); + + +$fmt = new \NumberFormatter("de_DE", \NumberFormatter::DECIMAL); +var_dump($fmt->format(23.25)); + +$f = new NumberFormatter('hu_HU', NumberFormatter::PERCENT, '#,##0%'); +var_dump($f->format(0.26)); + +?> +==DONE== +--EXPECTF-- +string(%d) "5,50 kr%A" +string(%d) "5,50 kr%A" +string(%d) "5,00 kr%A" +string(5) "23,25" +string(3) "26%" +==DONE== diff --git a/ext/intl/tests/bug67052.phpt b/ext/intl/tests/bug67052.phpt index 80c7e88017..7f0c4cba51 100644 --- a/ext/intl/tests/bug67052.phpt +++ b/ext/intl/tests/bug67052.phpt @@ -17,7 +17,7 @@ setlocale(LC_ALL, $l); function ut_main() { - setlocale(LC_ALL, 'de_DE'); + setlocale(LC_ALL, 'de_DE.UTF-8'); $fmt = new NumberFormatter( 'sl_SI.UTF-8', NumberFormatter::DECIMAL); $num = "1.234.567,891"; $res_str = $fmt->parse($num)."\n"; @@ -31,5 +31,5 @@ ut_run(); ?> --EXPECT-- 1234567,891 -de_DE +de_DE.UTF-8 diff --git a/ext/intl/tests/bug69374.phpt b/ext/intl/tests/bug69374.phpt new file mode 100644 index 0000000000..4d9fffab7a --- /dev/null +++ b/ext/intl/tests/bug69374.phpt @@ -0,0 +1,24 @@ +--TEST-- +IntlDateFormatter::formatObject(): returns wrong utf8 value when $format param is utf8 string pattern. +--SKIPIF-- +<?php +if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?> +<?php if (version_compare(INTL_ICU_VERSION, '50.1.2') < 0) die('skip for ICU >= 51.1.2'); ?> +--FILE-- +<?php +$millitimestamp = 1428133423941.0; // 14:43:43 April 04 2015 +$pattern1 = '\'tháng\' MM, y'; // yMM format for Vietnamese +$pattern2 = 'y년 MMM'; // yMM format for Korean +$date = IntlCalendar::createInstance('Asia/Ho_Chi_Minh'); +$date->setTime($millitimestamp); +echo IntlDateFormatter::formatObject($date, $pattern1, 'vi_VN'), "\n"; +echo IntlDateFormatter::formatObject ($date, $pattern2, 'ko_KR'), "\n"; +?> +==DONE== + +--EXPECTF-- +tháng 04, 2015 +2015년 4월 +==DONE== + + diff --git a/ext/intl/tests/bug69398.phpt b/ext/intl/tests/bug69398.phpt new file mode 100644 index 0000000000..ea7dbd5098 --- /dev/null +++ b/ext/intl/tests/bug69398.phpt @@ -0,0 +1,22 @@ +--TEST-- +IntlDateFormatter::formatObject(): returns wrong value when time style is NONE. +--SKIPIF-- +<?php +if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?> +<?php if (version_compare(INTL_ICU_VERSION, '50.1.2') < 0) die('skip for ICU >= 51.1.2'); ?> +--FILE-- +<?php +$millitimestamp = 1428133423941.0; // 14:43:43 April 04 2015 +$date = IntlCalendar::createInstance('Asia/Ho_Chi_Minh'); +$date->setTime($millitimestamp); +echo IntlDateFormatter::formatObject($date, array(IntlDateFormatter::SHORT, IntlDateFormatter::NONE), 'vi_VN'), "\n"; +echo IntlDateFormatter::formatObject ($date, array(IntlDateFormatter::SHORT, IntlDateFormatter::NONE), 'ko_KR'), "\n"; +?> +==DONE== + +--EXPECTF-- +04/04/2015 +15. 4. 4. +==DONE== + + diff --git a/ext/intl/tests/bug70451.phpt b/ext/intl/tests/bug70451.phpt new file mode 100644 index 0000000000..75392c8dad --- /dev/null +++ b/ext/intl/tests/bug70451.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #70451 IntlChar::charFromName() not consistent with C library or HHVM +--SKIPIF-- +<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +--FILE-- +<?php +var_dump(IntlChar::charFromName("RECYCLING SYMBOL FOR TYPE-1 PLASTICS")); +var_dump(IntlChar::charFromName("sdfasdfasdfasdf")); +?> +--EXPECT-- +int(9843) +NULL diff --git a/ext/intl/tests/bug70452.phpt b/ext/intl/tests/bug70452.phpt new file mode 100644 index 0000000000..ee1cd7053a --- /dev/null +++ b/ext/intl/tests/bug70452.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #70452 string IntlChar::charName() can sometimes return bool(false) +--SKIPIF-- +<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +--FILE-- +<?php +// Rely on the default value for the second parameter +var_dump(IntlChar::charName("A")); +// Provide a valid option for the second parameter +var_dump(IntlChar::charName("A", IntlChar::UNICODE_CHAR_NAME)); +// Another valid option, but with no corresponding name for that given option +// This properly returns an empty string, as expected +var_dump(IntlChar::charName("A", IntlChar::UNICODE_10_CHAR_NAME)); +// Provide an invalid value for the second parameter +var_dump(IntlChar::charName("A", 12345)); +?> +--EXPECT-- +string(22) "LATIN CAPITAL LETTER A" +string(22) "LATIN CAPITAL LETTER A" +string(0) "" +NULL diff --git a/ext/intl/tests/bug71020.phpt b/ext/intl/tests/bug71020.phpt new file mode 100644 index 0000000000..368d967efd --- /dev/null +++ b/ext/intl/tests/bug71020.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #71020 (Use after free in Collator::sortWithSortKeys) +--SKIPIF-- +<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +--FILE-- +<?php + +$var_3=new Collator("Whatever"); +for($x=0;$x<0xbb;$x++) + $myarray[substr(md5(microtime()),rand(0,26),9) . strval($x)]= substr(md5(microtime()),rand(0,26),9) . strval($x); +$var_3->sortWithSortKeys($myarray); +?> +okey +--EXPECT-- +okey diff --git a/ext/intl/tests/bug72061.phpt b/ext/intl/tests/bug72061.phpt new file mode 100644 index 0000000000..782c32c11c --- /dev/null +++ b/ext/intl/tests/bug72061.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #72061: Out-of-bounds reads in zif_grapheme_stripos with negative offset +--SKIPIF-- +<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +--FILE-- +<?php + +var_dump(grapheme_stripos(str_repeat("ABCD", 16384), "A", -201)); +var_dump(grapheme_strpos(str_repeat("ABCD", 16384), "A", -201)); +?> +DONE +--EXPECT-- +int(65336) +int(65336) +DONE
\ No newline at end of file diff --git a/ext/intl/tests/bug72241.phpt b/ext/intl/tests/bug72241.phpt new file mode 100644 index 0000000000..397e1e7834 --- /dev/null +++ b/ext/intl/tests/bug72241.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #72241: get_icu_value_internal out-of-bounds read +--SKIPIF-- +<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +--FILE-- +<?php +$var1=str_repeat("A", 1000); +$out = locale_get_primary_language($var1); +echo strlen($out) . PHP_EOL; +echo unpack('H*', $out)[1] . PHP_EOL; +--EXPECT-- +1000 +61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 + diff --git a/ext/intl/tests/calendar_before_after_error.phpt b/ext/intl/tests/calendar_before_after_error.phpt index 938c7a5fb7..7d57b93a33 100644 --- a/ext/intl/tests/calendar_before_after_error.phpt +++ b/ext/intl/tests/calendar_before_after_error.phpt @@ -67,9 +67,9 @@ bool(false) error: 2, IntlCalendar::before() expects exactly 1 parameter, 0 given error: 2, IntlCalendar::before(): intlcal_before/after: bad arguments bool(false) -error: 1, Argument 1 passed to IntlCalendar::after() must be an instance of IntlCalendar, integer given +error: 0, Argument 1 passed to IntlCalendar::after() must be an instance of IntlCalendar, integer given -error: 1, Argument 1 passed to IntlCalendar::before() must be an instance of IntlCalendar, integer given +error: 0, Argument 1 passed to IntlCalendar::before() must be an instance of IntlCalendar, integer given error: 2, IntlCalendar::after() expects exactly 1 parameter, 2 given error: 2, IntlCalendar::after(): intlcal_before/after: bad arguments diff --git a/ext/intl/tests/calendar_clear_error.phpt b/ext/intl/tests/calendar_clear_error.phpt index 7e9c52b2a5..7ff2ff0867 100644 --- a/ext/intl/tests/calendar_clear_error.phpt +++ b/ext/intl/tests/calendar_clear_error.phpt @@ -18,8 +18,9 @@ var_dump($c->clear(-1)); var_dump(intlcal_clear($c, -1)); var_dump(intlcal_clear(1, 2)); --EXPECTF-- +Warning: IntlCalendar::clear() expects at most 1 parameter, 2 given in %s on line %d -Warning: IntlCalendar::clear(): intlcal_clear: too many arguments in %s on line %d +Warning: IntlCalendar::clear(): intlcal_clear: bad arguments in %s on line %d bool(false) Warning: IntlCalendar::clear(): intlcal_clear: invalid field in %s on line %d diff --git a/ext/intl/tests/calendar_equals_error.phpt b/ext/intl/tests/calendar_equals_error.phpt index 8465541c87..a9f164d38f 100644 --- a/ext/intl/tests/calendar_equals_error.phpt +++ b/ext/intl/tests/calendar_equals_error.phpt @@ -49,10 +49,10 @@ try { error: 2, IntlCalendar::equals() expects exactly 1 parameter, 0 given error: 2, IntlCalendar::equals(): intlcal_equals: bad arguments bool(false) -error: 1, Argument 1 passed to IntlCalendar::equals() must be an instance of IntlCalendar, instance of stdClass given +error: 0, Argument 1 passed to IntlCalendar::equals() must be an instance of IntlCalendar, instance of stdClass given -error: 1, Argument 1 passed to IntlCalendar::equals() must be an instance of IntlCalendar, integer given +error: 0, Argument 1 passed to IntlCalendar::equals() must be an instance of IntlCalendar, integer given -error: 1, Argument 2 passed to intlcal_equals() must be an instance of IntlCalendar, array given +error: 0, Argument 2 passed to intlcal_equals() must be an instance of IntlCalendar, array given -error: 1, Argument 1 passed to intlcal_equals() must be an instance of IntlCalendar, integer given +error: 0, Argument 1 passed to intlcal_equals() must be an instance of IntlCalendar, integer given diff --git a/ext/intl/tests/calendar_get_Least_Greatest_Minimum_Maximum_error.phpt b/ext/intl/tests/calendar_get_Least_Greatest_Minimum_Maximum_error.phpt index 3d881a781d..5d74a7d72d 100644 --- a/ext/intl/tests/calendar_get_Least_Greatest_Minimum_Maximum_error.phpt +++ b/ext/intl/tests/calendar_get_Least_Greatest_Minimum_Maximum_error.phpt @@ -98,11 +98,11 @@ bool(false) Warning: intlcal_get_minimum(): intlcal_get_minimum: invalid field in %s on line %d bool(false) -error: 1, Argument 1 passed to intlcal_get_least_maximum() must be an instance of IntlCalendar, integer given +error: 0, Argument 1 passed to intlcal_get_least_maximum() must be an instance of IntlCalendar, integer given -error: 1, Argument 1 passed to intlcal_get_maximum() must be an instance of IntlCalendar, integer given +error: 0, Argument 1 passed to intlcal_get_maximum() must be an instance of IntlCalendar, integer given -error: 1, Argument 1 passed to intlcal_get_greatest_minimum() must be an instance of IntlCalendar, integer given +error: 0, Argument 1 passed to intlcal_get_greatest_minimum() must be an instance of IntlCalendar, integer given -error: 1, Argument 1 passed to intlcal_get_minimum() must be an instance of IntlCalendar, integer given +error: 0, Argument 1 passed to intlcal_get_minimum() must be an instance of IntlCalendar, integer given diff --git a/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error2.phpt b/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error2.phpt index b29e8ed0cb..88b03f8cdb 100644 --- a/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error2.phpt +++ b/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error2.phpt @@ -105,9 +105,9 @@ bool(false) error: 2, intlcal_get_actual_minimum() expects parameter 2 to be integer, string given error: 2, intlcal_get_actual_minimum(): intlcal_get_actual_minimum: bad arguments bool(false) -error: 1, Argument 1 passed to intlcal_get() must be an instance of IntlCalendar, integer given +error: 0, Argument 1 passed to intlcal_get() must be an instance of IntlCalendar, integer given -error: 1, Argument 1 passed to intlcal_get_actual_maximum() must be an instance of IntlCalendar, integer given +error: 0, Argument 1 passed to intlcal_get_actual_maximum() must be an instance of IntlCalendar, integer given -error: 1, Argument 1 passed to intlcal_get_actual_minimum() must be an instance of IntlCalendar, integer given +error: 0, Argument 1 passed to intlcal_get_actual_minimum() must be an instance of IntlCalendar, integer given diff --git a/ext/intl/tests/calendar_isEquivalentTo_error.phpt b/ext/intl/tests/calendar_isEquivalentTo_error.phpt index ac19e1dd90..35b8fc189a 100644 --- a/ext/intl/tests/calendar_isEquivalentTo_error.phpt +++ b/ext/intl/tests/calendar_isEquivalentTo_error.phpt @@ -50,16 +50,16 @@ try { } --EXPECT-- -error: 1, Argument 1 passed to IntlCalendar::isEquivalentTo() must be an instance of IntlCalendar, integer given +error: 0, Argument 1 passed to IntlCalendar::isEquivalentTo() must be an instance of IntlCalendar, integer given error: 2, IntlCalendar::isEquivalentTo() expects exactly 1 parameter, 2 given error: 2, IntlCalendar::isEquivalentTo(): intlcal_is_equivalent_to: bad arguments bool(false) -error: 1, Argument 1 passed to IntlCalendar::isEquivalentTo() must be an instance of IntlCalendar, integer given +error: 0, Argument 1 passed to IntlCalendar::isEquivalentTo() must be an instance of IntlCalendar, integer given error: 2, intlcal_is_equivalent_to() expects exactly 2 parameters, 1 given error: 2, intlcal_is_equivalent_to(): intlcal_is_equivalent_to: bad arguments bool(false) -error: 1, Argument 2 passed to intlcal_is_equivalent_to() must be an instance of IntlCalendar, integer given +error: 0, Argument 2 passed to intlcal_is_equivalent_to() must be an instance of IntlCalendar, integer given -error: 1, Argument 1 passed to intlcal_is_equivalent_to() must be an instance of IntlCalendar, integer given +error: 0, Argument 1 passed to intlcal_is_equivalent_to() must be an instance of IntlCalendar, integer given diff --git a/ext/intl/tests/calendar_isWeekend_error.phpt b/ext/intl/tests/calendar_isWeekend_error.phpt index 8f723cc3c9..417bcb4c23 100644 --- a/ext/intl/tests/calendar_isWeekend_error.phpt +++ b/ext/intl/tests/calendar_isWeekend_error.phpt @@ -21,6 +21,7 @@ var_dump(intlcal_is_weekend($c, "jj")); var_dump(intlcal_is_weekend(1)); --EXPECTF-- +Warning: IntlCalendar::isWeekend() expects at most 1 parameter, 2 given in %s on line %d Warning: IntlCalendar::isWeekend(): intlcal_is_weekend: bad arguments in %s on line %d bool(false) diff --git a/ext/intl/tests/calendar_setTimeZone_error.phpt b/ext/intl/tests/calendar_setTimeZone_error.phpt index 410dc86c60..4dee131ef7 100644 --- a/ext/intl/tests/calendar_setTimeZone_error.phpt +++ b/ext/intl/tests/calendar_setTimeZone_error.phpt @@ -51,4 +51,4 @@ bool(false) error: 2, intlcal_set_time_zone() expects exactly 2 parameters, 3 given error: 2, intlcal_set_time_zone(): intlcal_set_time_zone: bad arguments bool(false) -error: 1, Argument 1 passed to intlcal_set_time_zone() must be an instance of IntlCalendar, integer given +error: 0, Argument 1 passed to intlcal_set_time_zone() must be an instance of IntlCalendar, integer given diff --git a/ext/intl/tests/collator_get_sort_key_variant4.phpt b/ext/intl/tests/collator_get_sort_key_variant4.phpt index ed2c9bc175..bd7af6a284 100644 --- a/ext/intl/tests/collator_get_sort_key_variant4.phpt +++ b/ext/intl/tests/collator_get_sort_key_variant4.phpt @@ -1,5 +1,5 @@ --TEST-- -collator_get_sort_key() icu >= 55.1 +collator_get_sort_key() icu >= 54.1 --SKIPIF-- <?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> <?php if (version_compare(INTL_ICU_VERSION, '55.1') >= 0) die('skip for ICU < 55.1'); ?> diff --git a/ext/intl/tests/collator_get_sort_key_variant5.phpt b/ext/intl/tests/collator_get_sort_key_variant5.phpt index 52a3af9766..c7717389b7 100644 --- a/ext/intl/tests/collator_get_sort_key_variant5.phpt +++ b/ext/intl/tests/collator_get_sort_key_variant5.phpt @@ -2,6 +2,7 @@ collator_get_sort_key() icu >= 55.1 --SKIPIF-- <?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +<?php if (version_compare(INTL_ICU_VERSION, '56.1') >= 0) die('skip for ICU < 56.1'); ?> <?php if (version_compare(INTL_ICU_VERSION, '55.1') < 0) die('skip for ICU >= 55.1'); ?> --FILE-- <?php diff --git a/ext/intl/tests/collator_get_sort_key_variant6.phpt b/ext/intl/tests/collator_get_sort_key_variant6.phpt new file mode 100644 index 0000000000..d8105d76d4 --- /dev/null +++ b/ext/intl/tests/collator_get_sort_key_variant6.phpt @@ -0,0 +1,98 @@ +--TEST-- +collator_get_sort_key() icu >= 56.1 +--SKIPIF-- +<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +<?php if (version_compare(INTL_ICU_VERSION, '56.1') < 0) die('skip for ICU >= 56.1'); ?> +--FILE-- +<?php + +/* + * Get sort keys using various locales + */ +function sort_arrays( $locale, $data ) +{ + $res_str = ''; + + $coll = ut_coll_create( $locale ); + + foreach($data as $value) { + $res_val = ut_coll_get_sort_key( $coll, $value ); + $res_str .= "source: ".$value."\n". + "key: ".bin2hex($res_val)."\n"; + } + + return $res_str; +} + + +function ut_main() +{ + $res_str = ''; + + // Regular strings keys + $test_params = array( + 'abc', 'abd', 'aaa', + 'аа', 'а', 'z', + '', null , '3', + 'y' , 'i' , 'k' + ); + + $res_str .= sort_arrays( 'en_US', $test_params ); + + // Sort a non-ASCII array using ru_RU locale. + $test_params = array( + 'абг', 'абв', 'жжж', 'эюя' + ); + + $res_str .= sort_arrays( 'ru_RU', $test_params ); + + // Sort an array using Lithuanian locale. + $res_str .= sort_arrays( 'lt_LT', $test_params ); + + return $res_str . "\n"; +} + +include_once( 'ut_common.inc' ); +ut_run(); +?> +--EXPECT-- +source: abc +key: 292b2d01070107 +source: abd +key: 292b2f01070107 +source: aaa +key: 29292901070107 +source: аа +key: 60060601060106 +source: а +key: 600601050105 +source: z +key: 5b01050105 +source: +key: 0101 +source: +key: 0101 +source: 3 +key: 1801050105 +source: y +key: 5901050105 +source: i +key: 3901050105 +source: k +key: 3d01050105 +source: абг +key: 26060c1001070107 +source: абв +key: 26060c0e01070107 +source: жжж +key: 262c2c2c01070107 +source: эюя +key: 26eef0f401070107 +source: абг +key: 60060c1001070107 +source: абв +key: 60060c0e01070107 +source: жжж +key: 602c2c2c01070107 +source: эюя +key: 60eef0f401070107 diff --git a/ext/intl/tests/dateformat_bug68893.phpt b/ext/intl/tests/dateformat_bug68893.phpt new file mode 100644 index 0000000000..b3faf54342 --- /dev/null +++ b/ext/intl/tests/dateformat_bug68893.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug #68893 Stackoverflow in datefmt_create +--SKIPIF-- +<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +--FILE-- +<?php + +$f = datefmt_create("en_us", -10000000, 1); +var_dump($f, intl_get_error_message()); + +$f = datefmt_create("en_us", 1, -10000000); +var_dump($f, intl_get_error_message()); + +?> +--EXPECT-- +NULL +string(67) "datefmt_create: invalid date format style: U_ILLEGAL_ARGUMENT_ERROR" +NULL +string(67) "datefmt_create: invalid time format style: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/dateformat_bug71516.phpt b/ext/intl/tests/dateformat_bug71516.phpt new file mode 100644 index 0000000000..88ba9bf840 --- /dev/null +++ b/ext/intl/tests/dateformat_bug71516.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #71516 IntlDateFormatter losts locale if pattern is set via constructor +--SKIPIF-- +<?php +if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?> +--FILE-- +<?php + +$loc = "ru_RU"; +$goodFormatter = new IntlDateFormatter($loc, IntlDateFormatter::FULL, IntlDateFormatter::FULL, new DateTimeZone("UTC")); +$badFormatter = new IntlDateFormatter($loc, IntlDateFormatter::FULL, IntlDateFormatter::FULL, new DateTimeZone("UTC"), null, "d MMM"); +$badFormatter2 = new IntlDateFormatter($loc, IntlDateFormatter::FULL, IntlDateFormatter::FULL, new DateTimeZone("UTC")); +$badFormatter2->setPattern("d MMM"); + +echo "Formatter without pattern: " . $goodFormatter->getLocale() . PHP_EOL; +echo "Formatter with pattern: " . $badFormatter->getLocale() . PHP_EOL; +echo "Formatter with pattern set later: " . $badFormatter2->getLocale() . PHP_EOL; + +?> +==DONE== +--EXPECT-- +Formatter without pattern: ru +Formatter with pattern: ru +Formatter with pattern set later: ru +==DONE== diff --git a/ext/intl/tests/formatter_format5.phpt b/ext/intl/tests/formatter_format5.phpt index cbaf140a0f..0bc4a6679b 100644 --- a/ext/intl/tests/formatter_format5.phpt +++ b/ext/intl/tests/formatter_format5.phpt @@ -1,7 +1,8 @@ --TEST-- -numfmt_format() icu >= 54.1 +numfmt_format() icu >= 54.1 && icu < 56.1 --SKIPIF-- <?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +<?php if (version_compare(INTL_ICU_VERSION, '56.1') >= 0) die('skip for ICU < 56.1'); ?> <?php if (version_compare(INTL_ICU_VERSION, '54.1') < 0) die('skip for ICU >= 54.1'); ?> --FILE-- <?php diff --git a/ext/intl/tests/formatter_format6.phpt b/ext/intl/tests/formatter_format6.phpt new file mode 100644 index 0000000000..80894c332b --- /dev/null +++ b/ext/intl/tests/formatter_format6.phpt @@ -0,0 +1,130 @@ +--TEST-- +numfmt_format() icu >= 56.1 +--SKIPIF-- +<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +<?php if (version_compare(INTL_ICU_VERSION, '56.1') < 0) die('skip for ICU >= 56.1'); ?> +--FILE-- +<?php + +/* + * Format a number using misc locales/patterns. + */ + +/* + * TODO: doesn't pass on ICU 3.6 because 'ru' and 'de' locales changed + * currency and percent formatting. + */ + +function ut_main() +{ + $styles = array( + NumberFormatter::PATTERN_DECIMAL => '##.#####################', + NumberFormatter::DECIMAL => '', + NumberFormatter::CURRENCY => '', + NumberFormatter::PERCENT => '', + NumberFormatter::SCIENTIFIC => '', + NumberFormatter::SPELLOUT => '@@@@@@@', + NumberFormatter::ORDINAL => '', + NumberFormatter::DURATION => '', + NumberFormatter::PATTERN_RULEBASED => '#####.###', + 1234999, // bad one + ); + + $integer = array( + NumberFormatter::ORDINAL => '', + NumberFormatter::DURATION => '', + ); + $locales = array( + 'en_US', + 'ru_UA', + 'de', + 'fr', + 'en_UK' + ); + + $str_res = ''; + $number = 1234567.891234567890000; + + foreach( $locales as $locale ) + { + $str_res .= "\nLocale is: $locale\n"; + foreach( $styles as $style => $pattern ) + { + $fmt = ut_nfmt_create( $locale, $style, $pattern ); + + if(!$fmt) { + $str_res .= "Bad formatter!\n"; + continue; + } + $str_res .= dump( isset($integer[$style])?ut_nfmt_format( $fmt, $number, NumberFormatter::TYPE_INT32):ut_nfmt_format( $fmt, $number ) ) . "\n"; + } + } + return $str_res; +} + +include_once( 'ut_common.inc' ); + +// Run the test +ut_run(); + +?> +--EXPECTREGEX-- +Locale is: en_US +'1234567.89123457' +'1,234,567.891' +'\$1,234,567.89' +'123,456,789%' +'1.23456789123457E6' +'one million,? two hundred (and )?thirty-four thousand,? five hundred (and )?sixty-seven point eight nine one two three four five seven' +'1,234,567(th|ᵗʰ)' +'342:56:07' +'#####.###' +'USD1,234,567.89' + +Locale is: ru_UA +'1234567,89123457' +'1 234 567,891' +'1 234 567,89 ?(грн\.|₴)' +'123 456 789 ?%' +'1,23456789123457E6' +'один миллион двести тридцать четыре тысячи пятьсот шестьдесят семь целых восемьдесят девять миллионов сто двадцать три тысячи четыреста пятьдесят семь стомиллионных' +'1 234 567.?' +'1 234 567' +'#####.###' +'1 234 567,89 UAH' + +Locale is: de +'1234567,89123457' +'1.234.567,891' +'(¤ )?1.234.567,89( ¤)?' +'123\.456\.789 %' +'1,23456789123457E6' +'eine Million zweihundertvierunddreißigtausendfünfhundertsiebenundsechzig Komma acht neun eins zwei drei vier fünf sieben' +'1.234.567.?' +'1.234.567' +'#####.###' +'1.234.567,89 ¤¤' + +Locale is: fr +'1234567,89123457' +'1 234 567,891' +'1 234 567,89 ¤' +'123 456 789 ?%' +'1,23456789123457E6' +'un million deux cent trente-quatre mille cinq cent soixante-sept virgule huit neuf un deux trois quatre cinq sept' +'1 234 567e' +'1 234 567' +'#####.###' +'1 234 567,89 ¤¤' + +Locale is: en_UK +'1234567.89123457' +'1,234,567.891' +'¤1,234,567.89' +'123,456,789%' +'1.23456789123457E6' +'one million,? two hundred (and )?thirty-four thousand,? five hundred (and )?sixty-seven point eight nine one two three four five seven' +'1,234,567(th|ᵗʰ)' +'342:56:07' +'#####.###' +'¤¤1,234,567.89' diff --git a/ext/intl/tests/formatter_get_set_text_attribute.phpt b/ext/intl/tests/formatter_get_set_text_attribute.phpt index 539ff52322..0535da477b 100644 --- a/ext/intl/tests/formatter_get_set_text_attribute.phpt +++ b/ext/intl/tests/formatter_get_set_text_attribute.phpt @@ -1,7 +1,8 @@ --TEST-- -numfmt_get/set_text_attribute() +numfmt_get/set_text_attribute() ICU < 56.1 --SKIPIF-- <?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +<?php if (version_compare(INTL_ICU_VERSION, '56.1') >= 0) die('skip for ICU < 56.1'); ?> --FILE-- <?php diff --git a/ext/intl/tests/formatter_get_set_text_attribute_var2.phpt b/ext/intl/tests/formatter_get_set_text_attribute_var2.phpt new file mode 100644 index 0000000000..f1306094c4 --- /dev/null +++ b/ext/intl/tests/formatter_get_set_text_attribute_var2.phpt @@ -0,0 +1,122 @@ +--TEST-- +numfmt_get/set_text_attribute() ICU >= 56.1 +--SKIPIF-- +<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +<?php if (version_compare(INTL_ICU_VERSION, '56.1') < 0) die('skip for ICU >= 56.1'); ?> +--FILE-- +<?php + +/* + * Get/set text attribute. + */ + + +function ut_main() +{ + // Array with data for testing + $long_str = str_repeat('blah', 100); + $attributes = array( + 'POSITIVE_PREFIX' => array( NumberFormatter::POSITIVE_PREFIX, '_+_', 12345.1234 ), + 'POSITIVE_SUFFIX' => array( NumberFormatter::POSITIVE_SUFFIX, '_+_', 12345.1234 ), + 'NEGATIVE_PREFIX' => array( NumberFormatter::NEGATIVE_PREFIX, '_-_', -12345.1234 ), + 'NEGATIVE_SUFFIX' => array( NumberFormatter::NEGATIVE_SUFFIX, '_-_', -12345.1234 ), + 'PADDING_CHARACTER' => array( NumberFormatter::PADDING_CHARACTER, '^', 12345.1234 ), + 'POSITIVE_PREFIX-2' => array( NumberFormatter::POSITIVE_PREFIX, $long_str, 12345.1234 ), +// 'CURRENCY_CODE' => array( NumberFormatter::CURRENCY_CODE, '_C_', 12345.1234 ) +// 'DEFAULT_RULESET' => array( NumberFormatter::DEFAULT_RULESET, '_DR_', 12345.1234 ), +// 'PUBLIC_RULESETS' => array( NumberFormatter::PUBLIC_RULESETS, '_PR_', 12345.1234 ) + ); + + $res_str = ''; + + $fmt = ut_nfmt_create( "en_US", NumberFormatter::DECIMAL ); + + foreach( $attributes as $attr_name => $data ) + { + list( $attr, $new_val, $test_number ) = $data; + $res_str .= "\nAttribute $attr_name\n"; + + if( $attr == NumberFormatter::PADDING_CHARACTER ) + ut_nfmt_set_attribute( $fmt, NumberFormatter::FORMAT_WIDTH, 21 ); + + // Get default attribute's value + $def_val = ut_nfmt_get_text_attribute( $fmt, $attr ); + if( $def_val === false ) + $res_str .= "get_text_attribute() error: " . ut_nfmt_get_error_message( $fmt ) . "\n"; + + $res_str .= "Default value: [$def_val]\n"; + $res_str .= "Formatting number with default value: " . ut_nfmt_format( $fmt, $test_number ) . "\n"; + + // Set new attribute's value and see if it works out. + $res_val = ut_nfmt_set_text_attribute( $fmt, $attr, $new_val ); + if( !$res_val ) + $res_str .= "set_text_attribute() error: " . ut_nfmt_get_error_message( $fmt ) . "\n"; + + // Get attribute value back. + $new_val_check = ut_nfmt_get_text_attribute( $fmt, $attr ); + $res_str .= "New value: [$new_val_check]\n"; + $res_str .= "Formatting number with new value: " . ut_nfmt_format( $fmt, $test_number ) . "\n"; + + // Check if the new value has been set. + if( $new_val !== $new_val_check ) + $res_str .= "ERROR: New $attr_name symbol value has not been set correctly.\n"; + + // Restore attribute's value to default + ut_nfmt_set_text_attribute( $fmt, $attr, $def_val ); + + if( $attr == NumberFormatter::PADDING_CHARACTER ) + ut_nfmt_set_attribute( $fmt, NumberFormatter::FORMAT_WIDTH, 0 ); + } + + // + $fmt = ut_nfmt_create( "uk_UA", NumberFormatter::CURRENCY ); + $res_str .= sprintf( "\nCurrency ISO-code for locale 'uk_UA' is: %s\n", + ut_nfmt_get_text_attribute( $fmt, NumberFormatter::CURRENCY_CODE ) ); + + return $res_str; +} + +include_once( 'ut_common.inc' ); +ut_run(); + +?> +--EXPECT-- +Attribute POSITIVE_PREFIX +Default value: [] +Formatting number with default value: 12,345.123 +New value: [_+_] +Formatting number with new value: _+_12,345.123 + +Attribute POSITIVE_SUFFIX +Default value: [] +Formatting number with default value: 12,345.123 +New value: [_+_] +Formatting number with new value: 12,345.123_+_ + +Attribute NEGATIVE_PREFIX +Default value: [-] +Formatting number with default value: -12,345.123 +New value: [_-_] +Formatting number with new value: _-_12,345.123 + +Attribute NEGATIVE_SUFFIX +Default value: [] +Formatting number with default value: -12,345.123 +New value: [_-_] +Formatting number with new value: -12,345.123_-_ + +Attribute PADDING_CHARACTER +Default value: [ ] +Formatting number with default value: 12,345.123 +New value: [^] +Formatting number with new value: ^^^^^^^^^^^12,345.123 + +Attribute POSITIVE_PREFIX-2 +Default value: [] +Formatting number with default value: 12,345.123 +New value: [blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah] +Formatting number with new value: blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah12,345.123 + +Currency ISO-code for locale 'uk_UA' is: UAH + + diff --git a/ext/intl/tests/grapheme.phpt b/ext/intl/tests/grapheme.phpt index def9110d0d..251b1d142f 100644 --- a/ext/intl/tests/grapheme.phpt +++ b/ext/intl/tests/grapheme.phpt @@ -68,9 +68,13 @@ function ut_main() array( "abc", "a", 0 ), array( "abc", "a", 0, 0 ), array( "abc", "a", 1, "false" ), + array( "abc", "a", -1, "false" ), array( "ababc", "a", 1, 2 ), array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o", "o", 2, 6 ), + array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o", "o", -1, 6 ), + array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o", "o", -5, 6 ), array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, 2, 3 ), + array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, -4, 3 ), array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "opq", "op", 5 ), array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "opq", "opq", 5 ), @@ -91,6 +95,7 @@ function ut_main() array( "ababc", "ab", 1, 2 ), array( "ababc", "abc", 1, 2 ), array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o" . $char_a_ring_nfd . "bc", "o" . $char_a_ring_nfd . "bc", 2, 6 ), + array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o" . $char_a_ring_nfd . "bc", "o" . $char_a_ring_nfd . "bc", -8, 6 ), array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_a_ring_nfd . "bc" . $char_a_ring_nfd . "def", $char_a_ring_nfd . "bc" . $char_a_ring_nfd, 2, 3 ), ); @@ -120,10 +125,12 @@ function ut_main() $tests = array( array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O", "o", 2, 6 ), + array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Oo", "o", -6, 6 ), array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_A_ring_nfd . "bc", $char_a_ring_nfd, 2, 3 ), array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O", "o", 5 ), array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, "O", "false" ), array( "a" . $char_a_ring_nfd . "bc" . $char_O_diaeresis_nfd, $char_o_diaeresis_nfd, 4 ), + array( "a" . $char_a_ring_nfd . "bc" . $char_O_diaeresis_nfd, $char_o_diaeresis_nfd, -1, 4 ), array( $char_o_diaeresis_nfd . "a" . $char_a_ring_nfd . "bc", $char_A_ring_nfd, 2 ), array( "a" . $char_A_ring_nfd . "bc", $char_a_ring_nfd, 1 ), array( "Abc", $char_a_ring_nfd, "false" ), @@ -153,6 +160,7 @@ function ut_main() array( "aBc", "abC", 0, 0 ), array( "abc", "aBc", 1, "false" ), array( "ABabc", "AB", 1, 2 ), + array( "ABabc", "AB", -4, 2 ), array( "abaBc", "aBc", 1, 2 ), array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o" . $char_A_ring_nfd . "bC", "O" . $char_a_ring_nfd . "bC", 2, 6 ), array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_A_ring_nfd . "bC" . $char_a_ring_nfd . "def", $char_a_ring_nfd . "Bc" . $char_a_ring_nfd, 2, 3 ), @@ -559,6 +567,7 @@ function ut_main() array( "abc", 1, 0, 1, "a" ), array( "abc", 1, 1, 2, "b" ), array( "abc", 1, 2, 3, "c" ), + array( "abc", 1, -2, 2, "b" ), array( "abc", 0, 2, 2, "" ), array( "http://news.bbc.co.uk/2/hi/middle_east/7831588.stm", 48, 48 , 50 , "tm" ), @@ -569,8 +578,11 @@ function ut_main() array( $char_a_ring_nfd . "bc", 2, 0, 4, $char_a_ring_nfd . "b" ), array( $char_a_ring_nfd . "bc", 1, 0, 3, $char_a_ring_nfd . "" ), array( $char_a_ring_nfd . "bcde", 2, 3, 5, "bc" ), + array( $char_a_ring_nfd . "bcde", 2, -4, 5, "bc" ), array( $char_a_ring_nfd . "bcde", 2, 4, 6, "cd" ), + array( $char_a_ring_nfd . "bcde", 2, -7, 4, $char_a_ring_nfd . "b" ), array( $char_a_ring_nfd . "bcde" . $char_a_ring_nfd . "f", 4, 5, 11, "de" . $char_a_ring_nfd . "f" ), + array( $char_a_ring_nfd . "bcde" . $char_a_ring_nfd . "f", 4, -6, 11, "de" . $char_a_ring_nfd . "f" ), array( $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 3, $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd ), array( $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, $char_a_ring_nfd . $char_o_diaeresis_nfd ), @@ -794,9 +806,13 @@ find "b" in "abc" - grapheme_strpos = 1 == 1 find "a" in "abc" - grapheme_strpos = 0 == 0 find "a" in "abc" - grapheme_strpos from 0 = 0 == 0 find "a" in "abc" - grapheme_strpos from 1 = false == false +find "a" in "abc" - grapheme_strpos from -1 = false == false find "a" in "ababc" - grapheme_strpos from 1 = 2 == 2 find "o" in "aoa%CC%8Abco%CC%88o" - grapheme_strpos from 2 = 6 == 6 +find "o" in "aoa%CC%8Abco%CC%88o" - grapheme_strpos from -1 = 6 == 6 +find "o" in "aoa%CC%8Abco%CC%88o" - grapheme_strpos from -5 = 6 == 6 find "a%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abc" - grapheme_strpos from 2 = 3 == 3 +find "a%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abc" - grapheme_strpos from -4 = 3 == 3 find "op" in "aa%CC%8Abco%CC%88opq" - grapheme_strpos = 5 == 5 find "opq" in "aa%CC%8Abco%CC%88opq" - grapheme_strpos = 5 == 5 find "abc" in "aa%CC%8Abco%CC%88" - grapheme_strpos = false == false @@ -816,15 +832,18 @@ find "abc" in "abc" - grapheme_strpos from 1 = false == false find "ab" in "ababc" - grapheme_strpos from 1 = 2 == 2 find "abc" in "ababc" - grapheme_strpos from 1 = 2 == 2 find "oa%CC%8Abc" in "aoa%CC%8Abco%CC%88oa%CC%8Abc" - grapheme_strpos from 2 = 6 == 6 +find "oa%CC%8Abc" in "aoa%CC%8Abco%CC%88oa%CC%8Abc" - grapheme_strpos from -8 = 6 == 6 find "a%CC%8Abca%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abca%CC%8Adef" - grapheme_strpos from 2 = 3 == 3 function grapheme_stripos($haystack, $needle, $offset = 0) {} find "o" in "aoa%CC%8Abco%CC%88O" - grapheme_stripos from 2 = 6 == 6 +find "o" in "aoa%CC%8Abco%CC%88Oo" - grapheme_stripos from -6 = 6 == 6 find "a%CC%8A" in "o%CC%88a%CC%8AaA%CC%8Abc" - grapheme_stripos from 2 = 3 == 3 find "o" in "aa%CC%8Abco%CC%88O" - grapheme_stripos = 5 == 5 find "O" in "aa%CC%8Abco%CC%88" - grapheme_stripos = false == false find "o%CC%88" in "aa%CC%8AbcO%CC%88" - grapheme_stripos = 4 == 4 +find "o%CC%88" in "aa%CC%8AbcO%CC%88" - grapheme_stripos from -1 = 4 == 4 find "A%CC%8A" in "o%CC%88aa%CC%8Abc" - grapheme_stripos = 2 == 2 find "a%CC%8A" in "aA%CC%8Abc" - grapheme_stripos = 1 == 1 find "a%CC%8A" in "Abc" - grapheme_stripos = false == false @@ -853,6 +872,7 @@ find "ab" in "ABc" - grapheme_stripos from 0 = 0 == 0 find "abC" in "aBc" - grapheme_stripos from 0 = 0 == 0 find "aBc" in "abc" - grapheme_stripos from 1 = false == false find "AB" in "ABabc" - grapheme_stripos from 1 = 2 == 2 +find "AB" in "ABabc" - grapheme_stripos from -4 = 2 == 2 find "aBc" in "abaBc" - grapheme_stripos from 1 = 2 == 2 find "Oa%CC%8AbC" in "aoa%CC%8Abco%CC%88oA%CC%8AbC" - grapheme_stripos from 2 = 6 == 6 find "a%CC%8ABca%CC%8A" in "o%CC%88a%CC%8AaA%CC%8AbCa%CC%8Adef" - grapheme_stripos from 2 = 3 == 3 @@ -1094,6 +1114,7 @@ extract from "abc" "0" graphemes - grapheme_extract starting at byte position 0 extract from "abc" "1" graphemes - grapheme_extract starting at byte position 0 with $next = a == a $next=1 == 1 extract from "abc" "1" graphemes - grapheme_extract starting at byte position 1 with $next = b == b $next=2 == 2 extract from "abc" "1" graphemes - grapheme_extract starting at byte position 2 with $next = c == c $next=3 == 3 +extract from "abc" "1" graphemes - grapheme_extract starting at byte position -2 with $next = b == b $next=2 == 2 extract from "abc" "0" graphemes - grapheme_extract starting at byte position 2 with $next = == $next=2 == 2 extract from "http%3A%2F%2Fnews.bbc.co.uk%2F2%2Fhi%2Fmiddle_east%2F7831588.stm" "48" graphemes - grapheme_extract starting at byte position 48 with $next = tm == tm $next=50 == 50 extract from "a%CC%8Abc" "3" graphemes - grapheme_extract = a%CC%8Abc == a%CC%8Abc @@ -1103,8 +1124,11 @@ extract from "a%CC%8Abc" "3" graphemes - grapheme_extract starting at byte posit extract from "a%CC%8Abc" "2" graphemes - grapheme_extract starting at byte position 0 with $next = a%CC%8Ab == a%CC%8Ab $next=4 == 4 extract from "a%CC%8Abc" "1" graphemes - grapheme_extract starting at byte position 0 with $next = a%CC%8A == a%CC%8A $next=3 == 3 extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position 3 with $next = bc == bc $next=5 == 5 +extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position -4 with $next = bc == bc $next=5 == 5 extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position 4 with $next = cd == cd $next=6 == 6 +extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position -7 with $next = a%CC%8Ab == a%CC%8Ab $next=4 == 4 extract from "a%CC%8Abcdea%CC%8Af" "4" graphemes - grapheme_extract starting at byte position 5 with $next = dea%CC%8Af == dea%CC%8Af $next=11 == 11 +extract from "a%CC%8Abcdea%CC%8Af" "4" graphemes - grapheme_extract starting at byte position -6 with $next = dea%CC%8Af == dea%CC%8Af $next=11 == 11 extract from "a%CC%8Ao%CC%88o%CC%88" "3" graphemes - grapheme_extract = a%CC%8Ao%CC%88o%CC%88 == a%CC%8Ao%CC%88o%CC%88 extract from "a%CC%8Ao%CC%88o%CC%88" "2" graphemes - grapheme_extract = a%CC%8Ao%CC%88 == a%CC%8Ao%CC%88 extract from "a%CC%8Ao%CC%88c" "1" graphemes - grapheme_extract = a%CC%8A == a%CC%8A diff --git a/ext/intl/tests/locale_bug66289.phpt b/ext/intl/tests/locale_bug66289.phpt new file mode 100644 index 0000000000..6afd821b5a --- /dev/null +++ b/ext/intl/tests/locale_bug66289.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #66289 Locale::lookup incorrectly returns en or en_US if locale is empty +--SKIPIF-- +<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +--FILE-- +<?php + +ini_set("intl.default_locale", "en-US"); +$availableLocales = array('fr_FR', 'de', 'es_ES', 'es_419', 'en_US'); +var_dump(locale_lookup($availableLocales, false, true, 'fr_FR')); +var_dump(locale_lookup($availableLocales, false, true, null)); + +$availableLocales = array('fr_FR', 'de', 'es_ES', 'es_419'); +var_dump(locale_lookup($availableLocales, false, true, 'fr_FR')); + +ini_set("intl.default_locale", "de-DE"); +$availableLocales = array(Locale::getDefault()); +var_dump(locale_lookup($availableLocales, false, true)); + +?> +==DONE== +--EXPECT-- +string(5) "fr_fr" +string(5) "en_us" +string(5) "fr_fr" +string(5) "de_de" +==DONE== diff --git a/ext/intl/tests/msgfmt_bug70484.phpt b/ext/intl/tests/msgfmt_bug70484.phpt new file mode 100644 index 0000000000..9d0bdc4ee8 --- /dev/null +++ b/ext/intl/tests/msgfmt_bug70484.phpt @@ -0,0 +1,97 @@ +--TEST-- +Bug #70484 selectordinal doesn't work with named parameters +--SKIPIF-- +<?php +if (!extension_loaded('intl')) + die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '5.0') < 0) + die('skip for ICU 5.0+'); +--FILE-- +<?php + +$locale = array("de", "fr", "en", "ru",); + +$data = array(42, 42.42, 2147483643, 2147483643.12345, 5); + +foreach ($locale as $lc) { + echo "$lc string key\n"; + $m = new MessageFormatter($lc, "{n, selectordinal, =5 {five} zero {#-zero} one {#-one} two {#-two} few {#-few} many {#-many} other {#-other}}"); + foreach ($data as $i) { + var_dump($m->format(array("n" => $i))); + if ($m->getErrorCode()) { + echo "$lc $i ", $m->getErrorMessage(); + } + } + echo "\n"; + + echo "$lc numeric key\n"; + $m = new MessageFormatter($lc, "{0, selectordinal, =5 {five} zero {#-zero} one {#-one} two {#-two} few {#-few} many {#-many} other {#-other}}"); + foreach ($data as $i) { + var_dump($m->format(array($i))); + if ($m->getErrorCode()) { + echo "$lc $i ", $m->getErrorMessage(); + } + } + echo "\n"; +} + +?> +==DONE== +--EXPECT-- +de string key +string(8) "42-other" +string(11) "42,42-other" +string(19) "2.147.483.643-other" +string(23) "2.147.483.643,123-other" +string(4) "five" + +de numeric key +string(8) "42-other" +string(11) "42,42-other" +string(19) "2.147.483.643-other" +string(23) "2.147.483.643,123-other" +string(4) "five" + +fr string key +string(8) "42-other" +string(11) "42,42-other" +string(22) "2 147 483 643-other" +string(26) "2 147 483 643,123-other" +string(4) "five" + +fr numeric key +string(8) "42-other" +string(11) "42,42-other" +string(22) "2 147 483 643-other" +string(26) "2 147 483 643,123-other" +string(4) "five" + +en string key +string(6) "42-two" +string(11) "42.42-other" +string(17) "2,147,483,643-few" +string(23) "2,147,483,643.123-other" +string(4) "five" + +en numeric key +string(6) "42-two" +string(11) "42.42-other" +string(17) "2,147,483,643-few" +string(23) "2,147,483,643.123-other" +string(4) "five" + +ru string key +string(8) "42-other" +string(11) "42,42-other" +string(22) "2 147 483 643-other" +string(26) "2 147 483 643,123-other" +string(4) "five" + +ru numeric key +string(8) "42-other" +string(11) "42,42-other" +string(22) "2 147 483 643-other" +string(26) "2 147 483 643,123-other" +string(4) "five" + +==DONE== diff --git a/ext/intl/tests/timezone_IDforWindowsID_basic.phpt b/ext/intl/tests/timezone_IDforWindowsID_basic.phpt new file mode 100644 index 0000000000..4127d8e31c --- /dev/null +++ b/ext/intl/tests/timezone_IDforWindowsID_basic.phpt @@ -0,0 +1,46 @@ +--TEST-- +IntlTimeZone::getIDForWindowsID basic test +--SKIPIF-- +<?php +if (!extension_loaded('intl')) + die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '52') < 0) + die('skip for ICU >= 52'); +--FILE-- +<?php + +$tzs = array( + 'Gnomeregan' => array(NULL), + 'India Standard Time' => array(NULL), + 'Pacific Standard Time' => array('001', 'CA', 'MX', 'US', 'ZZ'), + 'Romance Standard Time' => array('001', 'BE', 'DK', 'ES', 'FR'), +); + +foreach ($tzs as $tz => $regions) { + echo "** $tz\n"; + foreach ($regions as $region) { + var_dump(IntlTimeZone::getIDForWindowsID($tz, $region)); + if (intl_get_error_code() != U_ZERO_ERROR) { + echo "Error: ", intl_get_error_message(), "\n"; + } + } +} + +--EXPECT-- +** Gnomeregan +bool(false) +Error: intltz_get_windows_id: Unknown windows timezone: U_ILLEGAL_ARGUMENT_ERROR +** India Standard Time +string(13) "Asia/Calcutta" +** Pacific Standard Time +string(19) "America/Los_Angeles" +string(17) "America/Vancouver" +string(15) "America/Tijuana" +string(19) "America/Los_Angeles" +string(7) "PST8PDT" +** Romance Standard Time +string(12) "Europe/Paris" +string(15) "Europe/Brussels" +string(17) "Europe/Copenhagen" +string(13) "Europe/Madrid" +string(12) "Europe/Paris" diff --git a/ext/intl/tests/timezone_getCanonicalID_error.phpt b/ext/intl/tests/timezone_getCanonicalID_error.phpt index e268e216a8..b29ca67701 100644 --- a/ext/intl/tests/timezone_getCanonicalID_error.phpt +++ b/ext/intl/tests/timezone_getCanonicalID_error.phpt @@ -11,7 +11,6 @@ ini_set("intl.error_level", E_WARNING); var_dump(IntlTimeZone::getCanonicalID()); var_dump(IntlTimeZone::getCanonicalID(array())); var_dump(IntlTimeZone::getCanonicalID("foo\x81")); -var_dump(IntlTimeZone::getCanonicalID('foobar', null)); --EXPECTF-- @@ -28,8 +27,3 @@ bool(false) Warning: IntlTimeZone::getCanonicalID(): intltz_get_canonical_id: could not convert time zone id to UTF-16 in %s on line %d bool(false) - -Fatal error: Uncaught Error: Cannot pass parameter 2 by reference in %s:%d -Stack trace: -#0 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/timezone_hasSameRules_error.phpt b/ext/intl/tests/timezone_hasSameRules_error.phpt index 5fb5bdde7a..0e9b4a8bd6 100644 --- a/ext/intl/tests/timezone_hasSameRules_error.phpt +++ b/ext/intl/tests/timezone_hasSameRules_error.phpt @@ -31,9 +31,9 @@ try { } --EXPECT-- -int(1) +int(0) string(99) "Argument 1 passed to IntlTimeZone::hasSameRules() must be an instance of IntlTimeZone, string given" -int(1) +int(0) string(92) "Argument 1 passed to intltz_has_same_rules() must be an instance of IntlTimeZone, null given" diff --git a/ext/intl/tests/timezone_windowsID_basic.phpt b/ext/intl/tests/timezone_windowsID_basic.phpt new file mode 100644 index 0000000000..dd48f016e2 --- /dev/null +++ b/ext/intl/tests/timezone_windowsID_basic.phpt @@ -0,0 +1,43 @@ +--TEST-- +IntlTimeZone::getWindowsID basic test +--SKIPIF-- +<?php +if (!extension_loaded('intl')) + die('skip intl extension not enabled'); +if (version_compare(INTL_ICU_VERSION, '52') < 0) + die('skip for ICU >= 52'); +--FILE-- +<?php + +$tzs = array( + 'America/Bogota', + 'America/Havana', + 'America/Indiana/Knox', + 'America/Los_Angeles', + 'Azeroth/Kalimdor/Durotar', + 'Africa/Casablanca', + 'Asia/Singapore', + 'Australia/Perth', + 'Europe/London', + 'Europe/Istanbul', +); + +foreach ($tzs as $tz) { + var_dump(IntlTimeZone::getWindowsID($tz)); + if (intl_get_error_code() != U_ZERO_ERROR) { + echo "Error: ", intl_get_error_message(), "\n"; + } +} + +--EXPECT-- +string(24) "SA Pacific Standard Time" +string(21) "Eastern Standard Time" +string(21) "Central Standard Time" +string(21) "Pacific Standard Time" +bool(false) +Error: intltz_get_windows_id: Unknown system timezone: U_ILLEGAL_ARGUMENT_ERROR +string(21) "Morocco Standard Time" +string(23) "Singapore Standard Time" +string(26) "W. Australia Standard Time" +string(17) "GMT Standard Time" +string(20) "Turkey Standard Time" diff --git a/ext/intl/tests/uconverter_getAvailable_wrongparam_001.phpt b/ext/intl/tests/uconverter_getAvailable_wrongparam_001.phpt new file mode 100644 index 0000000000..4e381289b3 --- /dev/null +++ b/ext/intl/tests/uconverter_getAvailable_wrongparam_001.phpt @@ -0,0 +1,8 @@ +--TEST-- +Check the function UConverter::getAvailable with parameter wrong +--SKIPIF-- +<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?> +--FILE-- +<?php UConverter::getAvailable("This is an ascii string"); ?> +--EXPECTF-- +Warning: UConverter::getAvailable() expects exactly 0 parameters, 1 given in %s on line %d diff --git a/ext/intl/timezone/timezone_class.cpp b/ext/intl/timezone/timezone_class.cpp index d1e8e2e0a6..f67e55ae4e 100644 --- a/ext/intl/timezone/timezone_class.cpp +++ b/ext/intl/timezone/timezone_class.cpp @@ -439,6 +439,17 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ainfo_tz_void, 0, 0, 0) ZEND_END_ARG_INFO() +#if U_ICU_VERSION_MAJOR_NUM >= 52 +ZEND_BEGIN_ARG_INFO_EX(ainfo_tz_getWindowsID, 0, ZEND_RETURN_VALUE, 1) + ZEND_ARG_INFO(0, timezone) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(ainfo_tz_getIDForWindowsID, 0, ZEND_RETURN_VALUE, 1) + ZEND_ARG_INFO(0, timezone) + ZEND_ARG_INFO(0, region) +ZEND_END_ARG_INFO() +#endif + /* }}} */ /* {{{ TimeZone_class_functions @@ -475,6 +486,10 @@ static zend_function_entry TimeZone_class_functions[] = { PHP_ME_MAPPING(toDateTimeZone, intltz_to_date_time_zone, ainfo_tz_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getErrorCode, intltz_get_error_code, ainfo_tz_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getErrorMessage, intltz_get_error_message, ainfo_tz_void, ZEND_ACC_PUBLIC) +#if U_ICU_VERSION_MAJOR_NUM >= 52 + PHP_ME_MAPPING(getWindowsID, intltz_get_windows_id, ainfo_tz_getWindowsID, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME_MAPPING(getIDForWindowsID, intltz_get_id_for_windows_id, ainfo_tz_getIDForWindowsID, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) +#endif PHP_FE_END }; /* }}} */ diff --git a/ext/intl/timezone/timezone_methods.cpp b/ext/intl/timezone/timezone_methods.cpp index c46b448bbe..20c0e02480 100644 --- a/ext/intl/timezone/timezone_methods.cpp +++ b/ext/intl/timezone/timezone_methods.cpp @@ -440,7 +440,7 @@ U_CFUNC PHP_FUNCTION(intltz_use_daylight_time) U_CFUNC PHP_FUNCTION(intltz_get_offset) { - UDate date; + double date; zend_bool local; zval *rawOffsetArg, *dstOffsetArg; @@ -458,7 +458,7 @@ U_CFUNC PHP_FUNCTION(intltz_get_offset) TIMEZONE_METHOD_FETCH_OBJECT; - to->utimezone->getOffset(date, (UBool) local, rawOffset, dstOffset, + to->utimezone->getOffset((UDate) date, (UBool) local, rawOffset, dstOffset, TIMEZONE_ERROR_CODE(to)); INTL_METHOD_CHECK_STATUS(to, "intltz_get_offset: error obtaining offset"); @@ -647,3 +647,81 @@ U_CFUNC PHP_FUNCTION(intltz_get_error_message) message = intl_error_get_message(TIMEZONE_ERROR_P(to)); RETURN_STR(message); } + +#if U_ICU_VERSION_MAJOR_NUM >= 52 +/* {{{ proto string IntlTimeZone::getWindowsID(string $timezone) + proto string intltz_get_windows_id(string $timezone) +Translate a system timezone (e.g. "America/Los_Angeles" into a +Windows Timezone (e.g. "Pacific Standard Time") + */ +U_CFUNC PHP_FUNCTION(intltz_get_windows_id) +{ + zend_string *id, *winID; + UnicodeString uID, uWinID; + UErrorCode error; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &id) == FAILURE) { + return; + } + + error = U_ZERO_ERROR; + if (intl_stringFromChar(uID, id->val, id->len, &error) == FAILURE) { + intl_error_set(NULL, error, + "intltz_get_windows_id: could not convert time zone id to UTF-16", 0); + RETURN_FALSE; + } + + error = U_ZERO_ERROR; + TimeZone::getWindowsID(uID, uWinID, error); + INTL_CHECK_STATUS(error, "intltz_get_windows_id: Unable to get timezone from windows ID"); + if (uWinID.length() == 0) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "intltz_get_windows_id: Unknown system timezone", 0); + RETURN_FALSE; + } + + error = U_ZERO_ERROR; + winID = intl_convert_utf16_to_utf8(uWinID.getBuffer(), uWinID.length(), &error); + INTL_CHECK_STATUS(error, "intltz_get_windows_id: could not convert time zone id to UTF-8"); + RETURN_STR(winID); +} +/* }}} */ + +/* {{{ proto string IntlTimeZone::getIDForWindowsID(string $timezone[, string $region = NULL]) + proto string intltz_get_id_for_windows_id(string $timezone[, string $region = NULL]) +Translate a windows timezone (e.g. "Pacific Time Zone" into a +System Timezone (e.g. "America/Los_Angeles") + */ +U_CFUNC PHP_FUNCTION(intltz_get_id_for_windows_id) +{ + zend_string *winID, *region = NULL, *id; + UnicodeString uWinID, uID; + UErrorCode error; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|S", &winID, ®ion) == FAILURE) { + return; + } + + error = U_ZERO_ERROR; + if (intl_stringFromChar(uWinID, winID->val, winID->len, &error) == FAILURE) { + intl_error_set(NULL, error, + "intltz_get_id_for_windows_id: could not convert time zone id to UTF-16", 0); + RETURN_FALSE; + } + + error = U_ZERO_ERROR; + TimeZone::getIDForWindowsID(uWinID, region ? region->val : NULL, uID, error); + INTL_CHECK_STATUS(error, "intltz_get_id_for_windows_id: Unable to get windows ID for timezone"); + if (uID.length() == 0) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "intltz_get_windows_id: Unknown windows timezone", 0); + RETURN_FALSE; + } + + error = U_ZERO_ERROR; + id = intl_convert_utf16_to_utf8(uID.getBuffer(), uID.length(), &error); + INTL_CHECK_STATUS(error, "intltz_get_id_for_windows_id: could not convert time zone id to UTF-8"); + RETURN_STR(id); +} +/* }}} */ +#endif diff --git a/ext/intl/timezone/timezone_methods.h b/ext/intl/timezone/timezone_methods.h index 29d72913fd..6e6fa3f472 100644 --- a/ext/intl/timezone/timezone_methods.h +++ b/ext/intl/timezone/timezone_methods.h @@ -65,4 +65,9 @@ PHP_FUNCTION(intltz_get_error_code); PHP_FUNCTION(intltz_get_error_message); +#if U_ICU_VERSION_MAJOR_NUM >= 52 +PHP_FUNCTION(intltz_get_windows_id); +PHP_FUNCTION(intltz_get_id_for_windows_id); +#endif + #endif /* #ifndef TIMEZONE_METHODS_H */ diff --git a/ext/intl/transliterator/transliterator_class.c b/ext/intl/transliterator/transliterator_class.c index 9a4cee97b0..96e52a15fd 100644 --- a/ext/intl/transliterator/transliterator_class.c +++ b/ext/intl/transliterator/transliterator_class.c @@ -269,9 +269,15 @@ static zval *Transliterator_read_property( zval *object, zval *member, int type, static void Transliterator_write_property( zval *object, zval *member, zval *value, void **cache_slot ) { + zend_class_entry *scope; TRANSLITERATOR_PROPERTY_HANDLER_PROLOG; - if( ( EG( scope ) != Transliterator_ce_ptr ) && + if (EG(fake_scope)) { + scope = EG(fake_scope); + } else { + scope = zend_get_executed_scope(); + } + if( ( scope != Transliterator_ce_ptr ) && ( zend_binary_strcmp( "id", sizeof( "id" ) - 1, Z_STRVAL_P( member ), Z_STRLEN_P( member ) ) == 0 ) ) { diff --git a/ext/intl/transliterator/transliterator_methods.c b/ext/intl/transliterator/transliterator_methods.c index e7b0870891..f0e5dcd2e8 100644 --- a/ext/intl/transliterator/transliterator_methods.c +++ b/ext/intl/transliterator/transliterator_methods.c @@ -332,7 +332,6 @@ PHP_FUNCTION( transliterator_transliterate ) int res; if(Z_TYPE_P( arg1 ) != IS_STRING ) { - SEPARATE_ZVAL( arg1 ); convert_to_string( arg1 ); } object = &tmp_object; diff --git a/ext/intl/uchar/tests/basic-functionality.phpt b/ext/intl/uchar/tests/basic-functionality.phpt index eb8e4fb261..b61e129051 100644 --- a/ext/intl/uchar/tests/basic-functionality.phpt +++ b/ext/intl/uchar/tests/basic-functionality.phpt @@ -1,5 +1,7 @@ --TEST-- IntlChar basic functionality +--SKIPIF-- +<?php if (!extension_loaded('intl')) die("skip requires ext/intl") ?> --FILE-- <?php diff --git a/ext/intl/uchar/tests/bug70453.phpt b/ext/intl/uchar/tests/bug70453.phpt new file mode 100644 index 0000000000..4b3024e241 --- /dev/null +++ b/ext/intl/uchar/tests/bug70453.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #70453 (IntlChar::foldCase() incorrect arguments and missing constants) +--SKIPIF-- +<?php if (!extension_loaded('intl')) die("skip requires ext/intl") ?> +--FILE-- +<?php +$method = new ReflectionMethod('IntlChar', 'foldCase'); +$param = $method->getParameters()[1]; +var_dump($param->name, $param->isOptional(), $param->isPassedByReference()); +var_dump(IntlChar::foldCase('I', IntlChar::FOLD_CASE_DEFAULT)); +var_dump(IntlChar::foldCase('I', IntlChar::FOLD_CASE_EXCLUDE_SPECIAL_I)); +?> +--EXPECT-- +string(7) "options" +bool(true) +bool(false) +string(1) "i" +string(2) "ı" diff --git a/ext/intl/uchar/tests/bug70454.phpt b/ext/intl/uchar/tests/bug70454.phpt new file mode 100644 index 0000000000..351bb65243 --- /dev/null +++ b/ext/intl/uchar/tests/bug70454.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #70454 (IntlChar::forDigit second parameter should be optional) +--SKIPIF-- +<?php if (!extension_loaded('intl')) die("skip requires ext/intl") ?> +--FILE-- +<?php +var_dump(IntlChar::forDigit(0)); +var_dump(IntlChar::forDigit(3)); +var_dump(IntlChar::forDigit(3, 10)); +var_dump(IntlChar::forDigit(10)); +var_dump(IntlChar::forDigit(10, 16)); +?> +--EXPECT-- +int(48) +int(51) +int(51) +int(0) +int(97) diff --git a/ext/intl/uchar/tests/bug70455.phpt b/ext/intl/uchar/tests/bug70455.phpt new file mode 100644 index 0000000000..00ee8984a0 --- /dev/null +++ b/ext/intl/uchar/tests/bug70455.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #70455 Missing constant: IntlChar::NO_NUMERIC_VALUE +--SKIPIF-- +<?php if (!extension_loaded('intl')) die("skip requires ext/intl") ?> +--FILE-- +<?php +$value = IntlChar::getNumericValue("x"); +var_dump($value); +var_dump($value === IntlChar::NO_NUMERIC_VALUE); +?> +--EXPECT-- +float(-123456789) +bool(true) diff --git a/ext/intl/uchar/uchar.c b/ext/intl/uchar/uchar.c index 0dbe9c9cf8..266c62821b 100644 --- a/ext/intl/uchar/uchar.c +++ b/ext/intl/uchar/uchar.c @@ -32,7 +32,7 @@ static inline int convert_cp(UChar32* pcp, zval *zcp) { return SUCCESS; } -/* {{{ proto string IntlChar::chr(int|string $char) +/* {{{ proto string IntlChar::chr(int|string $codepoint) * Converts a numeric codepoint to UTF-8 * Acts as an identify function when given a valid UTF-8 encoded codepoint */ @@ -59,7 +59,7 @@ IC_METHOD(chr) { } /* }}} */ -/* {{{ proto int IntlChar::ord(int|string $codepoint) +/* {{{ proto int IntlChar::ord(int|string $character) * Converts a UTf-8 encoded codepoint to its integer U32 value * Acts as an identity function when passed a valid integer codepoint */ @@ -79,7 +79,7 @@ IC_METHOD(ord) { } /* }}} */ -/* {{{ proto bool IntlChar::hasBinaryProperty(int|string $char, int $property) */ +/* {{{ proto bool IntlChar::hasBinaryProperty(int|string $codepoint, int $property) */ ZEND_BEGIN_ARG_INFO_EX(hasBinaryProperty_arginfo, 0, ZEND_RETURN_VALUE, 2) ZEND_ARG_INFO(0, codepoint) ZEND_ARG_INFO(0, property) @@ -98,7 +98,7 @@ IC_METHOD(hasBinaryProperty) { } /* }}} */ -/* {{{ proto int IntlChar::getIntPropertyValue(int|string $char, int $property) */ +/* {{{ proto int IntlChar::getIntPropertyValue(int|string $codepoint, int $property) */ ZEND_BEGIN_ARG_INFO_EX(getIntPropertyValue_arginfo, 0, ZEND_RETURN_VALUE, 2) ZEND_ARG_INFO(0, codepoint) ZEND_ARG_INFO(0, property) @@ -147,7 +147,7 @@ IC_METHOD(getIntPropertyMaxValue) { } /* }}} */ -/* {{{ proto float IntlChar::getNumericValue(int|string $char) */ +/* {{{ proto float IntlChar::getNumericValue(int|string $codepoint) */ ZEND_BEGIN_ARG_INFO_EX(getNumericValue_arginfo, 0, ZEND_RETURN_VALUE, 1) ZEND_ARG_INFO(0, codepoint) ZEND_END_ARG_INFO(); @@ -164,7 +164,7 @@ IC_METHOD(getNumericValue) { } /* }}} */ -/* {{{ proto void IntlChar::enumCharTypes(callable $cb) */ +/* {{{ proto void IntlChar::enumCharTypes(callable $callback) */ ZEND_BEGIN_ARG_INFO_EX(enumCharTypes_arginfo, 0, ZEND_RETURN_VALUE, 0) ZEND_ARG_INFO(0, callback) ZEND_END_ARG_INFO(); @@ -209,7 +209,7 @@ IC_METHOD(enumCharTypes) { } /* }}} */ -/* {{{ proto int IntlChar::getBlockCode(int|string $char) */ +/* {{{ proto int IntlChar::getBlockCode(int|string $codepoint) */ ZEND_BEGIN_ARG_INFO_EX(getBlockCode_arginfo, 0, ZEND_RETURN_VALUE, 1) ZEND_ARG_INFO(0, codepoint) ZEND_END_ARG_INFO() @@ -226,7 +226,7 @@ IC_METHOD(getBlockCode) { } /* }}} */ -/* {{{ proto string IntlChar::charName(int|string $char, int $nameChoice = IntlChar::UNICODE_CHAR_NAME) */ +/* {{{ proto string IntlChar::charName(int|string $codepoint, int $nameChoice = IntlChar::UNICODE_CHAR_NAME) */ ZEND_BEGIN_ARG_INFO_EX(charName_arginfo, 0, ZEND_RETURN_VALUE, 1) ZEND_ARG_INFO(0, codepoint) ZEND_ARG_INFO(0, nameChoice) @@ -241,7 +241,7 @@ IC_METHOD(charName) { if ((zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &zcp, &nameChoice) == FAILURE) || (convert_cp(&cp, zcp) == FAILURE)) { - return; + RETURN_NULL(); } buffer_len = u_charName(cp, (UCharNameChoice)nameChoice, NULL, 0, &error); @@ -250,13 +250,13 @@ IC_METHOD(charName) { buffer_len = u_charName(cp, (UCharNameChoice)nameChoice, ZSTR_VAL(buffer), ZSTR_LEN(buffer) + 1, &error); if (U_FAILURE(error)) { zend_string_free(buffer); - INTL_CHECK_STATUS(error, "Failure getting character name"); + INTL_CHECK_STATUS_OR_NULL(error, "Failure getting character name"); } RETURN_NEW_STR(buffer); } /* }}} */ -/* {{{ proto int IntlChar::charFromName(string $name, int $nameChoice = IntlChar::UNICODE_CHAR_NAME) */ +/* {{{ proto int IntlChar::charFromName(string $characterName, int $nameChoice = IntlChar::UNICODE_CHAR_NAME) */ ZEND_BEGIN_ARG_INFO_EX(charFromName_arginfo, 0, ZEND_RETURN_VALUE, 1) ZEND_ARG_INFO(0, characterName) ZEND_ARG_INFO(0, nameChoice) @@ -269,11 +269,11 @@ IC_METHOD(charFromName) { UErrorCode error = U_ZERO_ERROR; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &name, &name_len, &nameChoice) == FAILURE) { - return; + RETURN_NULL(); } ret = u_charFromName((UCharNameChoice)nameChoice, name, &error); - INTL_CHECK_STATUS(error, NULL); + INTL_CHECK_STATUS_OR_NULL(error, NULL); RETURN_LONG(ret); } /* }}} */ @@ -374,7 +374,7 @@ IC_METHOD(getPropertyEnum) { } /* }}} */ -/* {{{ proto string IntlChar::getPropertyValueName(int $prop, int $val[, int $nameChoice = IntlChar::LONG_PROPERTY_NAME) */ +/* {{{ proto string IntlChar::getPropertyValueName(int $property, int $value[, int $nameChoice = IntlChar::LONG_PROPERTY_NAME) */ ZEND_BEGIN_ARG_INFO_EX(getPropertyValueName_arginfo, 0, ZEND_RETURN_VALUE, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) @@ -417,9 +417,10 @@ IC_METHOD(getPropertyValueEnum) { } /* }}} */ -/* {{{ proto int|string IntlChar::foldCase(int|string $char, int $options = IntlChar::FOLD_CASE_DEFAULT) */ +/* {{{ proto int|string IntlChar::foldCase(int|string $codepoint, int $options = IntlChar::FOLD_CASE_DEFAULT) */ ZEND_BEGIN_ARG_INFO_EX(foldCase_arginfo, 0, ZEND_RETURN_VALUE, 1) - ZEND_ARG_INFO(0, foldCase) + ZEND_ARG_INFO(0, codepoint) + ZEND_ARG_INFO(0, options) ZEND_END_ARG_INFO(); IC_METHOD(foldCase) { UChar32 cp, ret; @@ -444,7 +445,7 @@ IC_METHOD(foldCase) { } /* }}} */ -/* {{{ proto int IntlChar::digit(int|string $char[, int $radix = 10]) */ +/* {{{ proto int IntlChar::digit(int|string $codepoint[, int $radix = 10]) */ ZEND_BEGIN_ARG_INFO_EX(digit_arginfo, 0, ZEND_RETURN_VALUE, 1) ZEND_ARG_INFO(0, codepoint) ZEND_ARG_INFO(0, radix) @@ -478,7 +479,7 @@ ZEND_END_ARG_INFO(); IC_METHOD(forDigit) { zend_long digit, radix = 10; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &digit, &radix) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &digit, &radix) == FAILURE) { return; } @@ -486,7 +487,7 @@ IC_METHOD(forDigit) { } /* }}} */ -/* {{{ proto array IntlChar::charAge(int|string $char) */ +/* {{{ proto array IntlChar::charAge(int|string $codepoint) */ ZEND_BEGIN_ARG_INFO_EX(charAge_arginfo, 0, ZEND_RETURN_VALUE, 1) ZEND_ARG_INFO(0, codepoint) ZEND_END_ARG_INFO(); @@ -525,7 +526,7 @@ IC_METHOD(getUnicodeVersion) { } /* }}} */ -/* {{{ proto string IntlChar::getFC_NFKC_Closure(int|string $char) */ +/* {{{ proto string IntlChar::getFC_NFKC_Closure(int|string $codepoint) */ ZEND_BEGIN_ARG_INFO_EX(getFC_NFKC_Closure_arginfo, 0, ZEND_RETURN_VALUE, 1) ZEND_ARG_INFO(0, codepoint) ZEND_END_ARG_INFO(); @@ -562,7 +563,7 @@ IC_METHOD(getFC_NFKC_Closure) { } /* }}} */ -/* {{{ proto bool IntlChar::<name>(int|string $char) */ +/* {{{ proto bool IntlChar::<name>(int|string $codepoint) */ #define IC_BOOL_METHOD_CHAR(name) \ ZEND_BEGIN_ARG_INFO_EX(name##_arginfo, 0, ZEND_RETURN_VALUE, 1) \ ZEND_ARG_INFO(0, codepoint) \ @@ -604,7 +605,7 @@ IC_BOOL_METHOD_CHAR(isJavaIDPart) #undef IC_BOOL_METHOD_CHAR /* }}} */ -/* {{{ proto int IntlChar::<name>(int|string $char) */ +/* {{{ proto int IntlChar::<name>(int|string $codepoint) */ #define IC_INT_METHOD_CHAR(name) \ ZEND_BEGIN_ARG_INFO_EX(name##_arginfo, 0, ZEND_RETURN_VALUE, 1) \ ZEND_ARG_INFO(0, codepoint) \ @@ -622,7 +623,7 @@ IC_INT_METHOD_CHAR(charDigitValue) #undef IC_INT_METHOD_CHAR /* }}} */ -/* {{{ proto int|string IntlChar::<name>(int|string $char) +/* {{{ proto int|string IntlChar::<name>(int|string $codepoint) * Returns a utf-8 character if codepoint was passed as a utf-8 sequence * Returns an int otherwise */ @@ -734,6 +735,9 @@ int php_uchar_minit(INIT_FUNC_ARGS) { zend_declare_class_constant_string(ce, "UNICODE_VERSION", sizeof("UNICODE_VERISON")-1, U_UNICODE_VERSION); IC_CONSTL("CODEPOINT_MIN", UCHAR_MIN_VALUE) IC_CONSTL("CODEPOINT_MAX", UCHAR_MAX_VALUE) + IC_CONSTL("FOLD_CASE_DEFAULT", U_FOLD_CASE_DEFAULT) + IC_CONSTL("FOLD_CASE_EXCLUDE_SPECIAL_I", U_FOLD_CASE_EXCLUDE_SPECIAL_I) + zend_declare_class_constant_double(ce, "NO_NUMERIC_VALUE", sizeof("NO_NUMERIC_VALUE")-1, U_NO_NUMERIC_VALUE); /* All enums used by the uchar APIs. There are a LOT of them, * so they're separated out into include files, |