Skip to content

Use new Fast ZPP macros for string|int param in intl/UChar #5512

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 94 additions & 97 deletions ext/intl/uchar/uchar.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,56 +8,53 @@

#define IC_METHOD(mname) PHP_METHOD(IntlChar, mname)

static inline int convert_cp(UChar32* pcp, zval *zcp) {
zend_long cp = -1;

if (Z_TYPE_P(zcp) == IS_LONG) {
cp = Z_LVAL_P(zcp);
} else if (Z_TYPE_P(zcp) == IS_STRING) {
static inline int convert_cp(UChar32* pcp, zend_string *string_codepoint, zend_long int_codepoint) {
if (string_codepoint != NULL) {
int32_t i = 0;
size_t zcp_len = Z_STRLEN_P(zcp);
size_t string_codepoint_length = ZSTR_LEN(string_codepoint);

if (ZEND_SIZE_T_INT_OVFL(zcp_len)) {
if (ZEND_SIZE_T_INT_OVFL(string_codepoint_length)) {
intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR);
intl_error_set_custom_msg(NULL, "Input string is too long.", 0);
return FAILURE;
}

U8_NEXT(Z_STRVAL_P(zcp), i, zcp_len, cp);
if ((size_t)i != zcp_len) {
U8_NEXT(ZSTR_VAL(string_codepoint), i, string_codepoint_length, int_codepoint);
if ((size_t)i != string_codepoint_length) {
intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR);
intl_error_set_custom_msg(NULL, "Passing a UTF-8 character for codepoint requires a string which is exactly one UTF-8 codepoint long.", 0);
return FAILURE;
}
} else {
intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR);
intl_error_set_custom_msg(NULL, "Invalid parameter for unicode point. Must be either integer or UTF-8 sequence.", 0);
return FAILURE;
}
if ((cp < UCHAR_MIN_VALUE) || (cp > UCHAR_MAX_VALUE)) {

if ((int_codepoint < UCHAR_MIN_VALUE) || (int_codepoint > UCHAR_MAX_VALUE)) {
intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR);
intl_error_set_custom_msg(NULL, "Codepoint out of range", 0);
return FAILURE;
}
*pcp = (UChar32)cp;
*pcp = (UChar32)int_codepoint;
return SUCCESS;
}

static zend_never_inline int parse_code_point_param(INTERNAL_FUNCTION_PARAMETERS, UChar32 *cp) {
zend_string *string_codepoint;
zend_long int_codepoint;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
return convert_cp(cp, string_codepoint, int_codepoint);
}

/* {{{ 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
*/
IC_METHOD(chr) {
UChar32 cp;
zval *zcp;
char buffer[5];
int buffer_len = 0;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zcp) == FAILURE) {
RETURN_THROWS();
}

if (convert_cp(&cp, zcp) == FAILURE) {
if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
RETURN_NULL();
}

Expand All @@ -76,13 +73,8 @@ IC_METHOD(chr) {
*/
IC_METHOD(ord) {
UChar32 cp;
zval *zcp;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zcp) == FAILURE) {
RETURN_THROWS();
}

if (convert_cp(&cp, zcp) == FAILURE) {
if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
RETURN_NULL();
}

Expand All @@ -94,13 +86,15 @@ IC_METHOD(ord) {
IC_METHOD(hasBinaryProperty) {
UChar32 cp;
zend_long prop;
zval *zcp;
zend_string *string_codepoint;
zend_long int_codepoint;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "zl", &zcp, &prop) == FAILURE) {
RETURN_THROWS();
}
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
Z_PARAM_LONG(prop)
ZEND_PARSE_PARAMETERS_END();

if (convert_cp(&cp, zcp) == FAILURE) {
if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) {
RETURN_NULL();
}

Expand All @@ -112,13 +106,15 @@ IC_METHOD(hasBinaryProperty) {
IC_METHOD(getIntPropertyValue) {
UChar32 cp;
zend_long prop;
zval *zcp;
zend_string *string_codepoint;
zend_long int_codepoint;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "zl", &zcp, &prop) == FAILURE) {
RETURN_THROWS();
}
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
Z_PARAM_LONG(prop)
ZEND_PARSE_PARAMETERS_END();

if (convert_cp(&cp, zcp) == FAILURE) {
if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) {
RETURN_NULL();
}

Expand Down Expand Up @@ -153,13 +149,8 @@ IC_METHOD(getIntPropertyMaxValue) {
/* {{{ proto float IntlChar::getNumericValue(int|string $codepoint) */
IC_METHOD(getNumericValue) {
UChar32 cp;
zval *zcp;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zcp) == FAILURE) {
RETURN_THROWS();
}

if (convert_cp(&cp, zcp) == FAILURE) {
if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
RETURN_NULL();
}

Expand All @@ -173,8 +164,7 @@ typedef struct _enumCharType_data {
zend_fcall_info_cache fci_cache;
} enumCharType_data;
static UBool enumCharType_callback(enumCharType_data *context,
UChar32 start, UChar32 limit,
UCharCategory type) {
UChar32 start, UChar32 limit, UCharCategory type) {
zval retval;
zval args[3];

Expand Down Expand Up @@ -212,13 +202,8 @@ IC_METHOD(enumCharTypes) {
/* {{{ proto int IntlChar::getBlockCode(int|string $codepoint) */
IC_METHOD(getBlockCode) {
UChar32 cp;
zval *zcp;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zcp) == FAILURE) {
RETURN_THROWS();
}

if (convert_cp(&cp, zcp) == FAILURE) {
if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
RETURN_NULL();
}

Expand All @@ -229,17 +214,20 @@ IC_METHOD(getBlockCode) {
/* {{{ proto string IntlChar::charName(int|string $codepoint, int $nameChoice = IntlChar::UNICODE_CHAR_NAME) */
IC_METHOD(charName) {
UChar32 cp;
zval *zcp;
zend_string *string_codepoint;
zend_long int_codepoint;
UErrorCode error = U_ZERO_ERROR;
zend_long nameChoice = U_UNICODE_CHAR_NAME;
zend_string *buffer = NULL;
int32_t buffer_len;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &zcp, &nameChoice) == FAILURE) {
RETURN_THROWS();
}
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(nameChoice)
ZEND_PARSE_PARAMETERS_END();

if (convert_cp(&cp, zcp) == FAILURE) {
if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) {
RETURN_NULL();
}

Expand Down Expand Up @@ -279,8 +267,8 @@ typedef struct _enumCharNames_data {
zend_fcall_info_cache fci_cache;
} enumCharNames_data;
static UBool enumCharNames_callback(enumCharNames_data *context,
UChar32 code, UCharNameChoice nameChoice,
const char *name, int32_t length) {
UChar32 code, UCharNameChoice nameChoice,
const char *name, int32_t length) {
zval retval;
zval args[3];

Expand All @@ -306,16 +294,22 @@ static UBool enumCharNames_callback(enumCharNames_data *context,
}
IC_METHOD(enumCharNames) {
UChar32 start, limit;
zval *zstart, *zlimit;
zend_string *string_start, *string_limit;
zend_long int_start, int_limit;
enumCharNames_data context;
zend_long nameChoice = U_UNICODE_CHAR_NAME;
UErrorCode error = U_ZERO_ERROR;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzf|l", &zstart, &zlimit, &context.fci, &context.fci_cache, &nameChoice) == FAILURE) {
RETURN_THROWS();
}

if (convert_cp(&start, zstart) == FAILURE || convert_cp(&limit, zlimit) == FAILURE) {
ZEND_PARSE_PARAMETERS_START(3, 4)
Z_PARAM_STR_OR_LONG(string_start, int_start)
Z_PARAM_STR_OR_LONG(string_limit, int_limit)
Z_PARAM_FUNC(context.fci, context.fci_cache)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(nameChoice)
ZEND_PARSE_PARAMETERS_END();

if (convert_cp(&start, string_start, int_start) == FAILURE || convert_cp(&limit, string_limit, int_limit) == FAILURE) {
RETURN_NULL();
}

Expand Down Expand Up @@ -395,19 +389,21 @@ IC_METHOD(getPropertyValueEnum) {
/* {{{ proto int|string IntlChar::foldCase(int|string $codepoint, int $options = IntlChar::FOLD_CASE_DEFAULT) */
IC_METHOD(foldCase) {
UChar32 cp, ret;
zval *zcp;
zend_long options = U_FOLD_CASE_DEFAULT;
zend_string *string_codepoint;
zend_long int_codepoint;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &zcp, &options) == FAILURE) {
RETURN_THROWS();
}
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
Z_PARAM_LONG(options)
ZEND_PARSE_PARAMETERS_END();

if (convert_cp(&cp, zcp) == FAILURE) {
if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) {
RETURN_NULL();
}

ret = u_foldCase(cp, options);
if (Z_TYPE_P(zcp) == IS_STRING) {
if (string_codepoint != NULL) {
char buffer[5];
int buffer_len = 0;
U8_APPEND_UNSAFE(buffer, buffer_len, ret);
Expand All @@ -422,15 +418,18 @@ IC_METHOD(foldCase) {
/* {{{ proto int IntlChar::digit(int|string $codepoint[, int $radix = 10]) */
IC_METHOD(digit) {
UChar32 cp;
zval *zcp;
zend_long radix = 10;
int ret;
zend_string *string_codepoint;
zend_long int_codepoint;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &zcp, &radix) == FAILURE) {
RETURN_THROWS();
}
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(radix)
ZEND_PARSE_PARAMETERS_END();

if (convert_cp(&cp, zcp) == FAILURE) {
if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) {
RETURN_NULL();
}

Expand Down Expand Up @@ -459,15 +458,10 @@ IC_METHOD(forDigit) {
/* {{{ proto array IntlChar::charAge(int|string $codepoint) */
IC_METHOD(charAge) {
UChar32 cp;
zval *zcp;
UVersionInfo version;
int i;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zcp) == FAILURE) {
RETURN_THROWS();
}

if (convert_cp(&cp, zcp) == FAILURE) {
if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
RETURN_NULL();
}

Expand Down Expand Up @@ -499,17 +493,12 @@ IC_METHOD(getUnicodeVersion) {
/* {{{ proto string IntlChar::getFC_NFKC_Closure(int|string $codepoint) */
IC_METHOD(getFC_NFKC_Closure) {
UChar32 cp;
zval *zcp;
UChar *closure;
zend_string *u8str;
int32_t closure_len;
UErrorCode error = U_ZERO_ERROR;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zcp) == FAILURE) {
RETURN_THROWS();
}

if (convert_cp(&cp, zcp) == FAILURE) {
if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
RETURN_NULL();
}

Expand All @@ -536,9 +525,10 @@ IC_METHOD(getFC_NFKC_Closure) {
/* {{{ proto bool IntlChar::<name>(int|string $codepoint) */
#define IC_BOOL_METHOD_CHAR(name) \
IC_METHOD(name) { \
UChar32 cp; zval *zcp; \
if ((zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zcp) == FAILURE) || \
(convert_cp(&cp, zcp) == FAILURE)) { return; } \
UChar32 cp; \
if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { \
RETURN_NULL(); \
} \
RETURN_BOOL(u_##name(cp)); \
}
IC_BOOL_METHOD_CHAR(isUAlphabetic)
Expand Down Expand Up @@ -575,9 +565,10 @@ IC_BOOL_METHOD_CHAR(isJavaIDPart)
/* {{{ proto int IntlChar::<name>(int|string $codepoint) */
#define IC_INT_METHOD_CHAR(name) \
IC_METHOD(name) { \
UChar32 cp; zval *zcp; \
if ((zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zcp) == FAILURE) || \
(convert_cp(&cp, zcp) == FAILURE)) { return; } \
UChar32 cp; \
if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { \
RETURN_NULL(); \
} \
RETURN_LONG(u_##name(cp)); \
}
IC_INT_METHOD_CHAR(charDirection)
Expand All @@ -593,11 +584,17 @@ IC_INT_METHOD_CHAR(charDigitValue)
*/
#define IC_CHAR_METHOD_CHAR(name) \
IC_METHOD(name) { \
UChar32 cp, ret; zval *zcp; \
if ((zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zcp) == FAILURE) || \
(convert_cp(&cp, zcp) == FAILURE)) { return; } \
UChar32 cp, ret; \
zend_string *string_codepoint; \
zend_long int_codepoint; \
ZEND_PARSE_PARAMETERS_START(1, 1) \
Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) \
ZEND_PARSE_PARAMETERS_END(); \
if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) { \
RETURN_NULL(); \
} \
ret = u_##name(cp); \
if (Z_TYPE_P(zcp) == IS_STRING) { \
if (string_codepoint != NULL) { \
char buffer[5]; \
int buffer_len = 0; \
U8_APPEND_UNSAFE(buffer, buffer_len, ret); \
Expand Down
Loading