mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00

This is a comprehensive refactoring of the error mechanism of the Intl extension. By moving the prefixing of the current method/function being executed to actual error message creation by accessing the execution context, we get the following benefits: - Accurate error messages indicating *what* call caused the error - As we *always* "copy" the message, the `copyMsg` arg becomes unused, meaning we can reduce the size of the `intl_error` struct by 4 bytes. - Saving it as a zend_string means we know the length of the message - Remove the need to pass around a "function name" `char*` across multiple calls - Use Intl's exception mechanism to generate exceptions for constructor call - This removes the need for replacing the error handler - Which didn't do anything anyway in silent mode, which required throwing non-descriptive exceptions
629 lines
15 KiB
C++
629 lines
15 KiB
C++
extern "C" {
|
|
#include "uchar.h"
|
|
#include "intl_data.h"
|
|
#include "intl_convert.h"
|
|
|
|
#include <unicode/uchar.h>
|
|
#include <unicode/utf8.h>
|
|
|
|
#include "uchar_arginfo.h"
|
|
}
|
|
|
|
#define IC_METHOD(mname) PHP_METHOD(IntlChar, mname)
|
|
|
|
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 string_codepoint_length = ZSTR_LEN(string_codepoint);
|
|
|
|
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.");
|
|
return FAILURE;
|
|
}
|
|
|
|
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.");
|
|
return FAILURE;
|
|
}
|
|
}
|
|
|
|
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");
|
|
return FAILURE;
|
|
}
|
|
*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 = 0;
|
|
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);
|
|
}
|
|
|
|
/* {{{ 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;
|
|
char buffer[5];
|
|
int buffer_len = 0;
|
|
|
|
if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
|
|
RETURN_NULL();
|
|
}
|
|
|
|
/* We can use unsafe because we know the codepoint is in valid range
|
|
* and that 4 bytes is enough for any unicode point
|
|
*/
|
|
U8_APPEND_UNSAFE(buffer, buffer_len, cp);
|
|
buffer[buffer_len] = 0;
|
|
RETURN_STRINGL(buffer, buffer_len);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ Converts a UTf-8 encoded codepoint to its integer U32 value
|
|
* Acts as an identity function when passed a valid integer codepoint
|
|
*/
|
|
IC_METHOD(ord) {
|
|
UChar32 cp;
|
|
|
|
if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
|
|
RETURN_NULL();
|
|
}
|
|
|
|
RETURN_LONG(cp);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(hasBinaryProperty) {
|
|
UChar32 cp;
|
|
zend_long prop;
|
|
zend_string *string_codepoint;
|
|
zend_long int_codepoint = 0;
|
|
|
|
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, string_codepoint, int_codepoint) == FAILURE) {
|
|
RETURN_NULL();
|
|
}
|
|
|
|
RETURN_BOOL(u_hasBinaryProperty(cp, (UProperty)prop));
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(getIntPropertyValue) {
|
|
UChar32 cp;
|
|
zend_long prop;
|
|
zend_string *string_codepoint;
|
|
zend_long int_codepoint = 0;
|
|
|
|
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, string_codepoint, int_codepoint) == FAILURE) {
|
|
RETURN_NULL();
|
|
}
|
|
|
|
RETURN_LONG(u_getIntPropertyValue(cp, (UProperty)prop));
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(getIntPropertyMinValue) {
|
|
zend_long prop;
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
Z_PARAM_LONG(prop)
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
RETURN_LONG(u_getIntPropertyMinValue((UProperty)prop));
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(getIntPropertyMaxValue) {
|
|
zend_long prop;
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
Z_PARAM_LONG(prop)
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
RETURN_LONG(u_getIntPropertyMaxValue((UProperty)prop));
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(getNumericValue) {
|
|
UChar32 cp;
|
|
|
|
if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
|
|
RETURN_NULL();
|
|
}
|
|
|
|
RETURN_DOUBLE(u_getNumericValue(cp));
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
typedef struct _enumCharType_data {
|
|
zend_fcall_info fci;
|
|
zend_fcall_info_cache fci_cache;
|
|
} enumCharType_data;
|
|
static UBool enumCharType_callback(enumCharType_data *context,
|
|
UChar32 start, UChar32 limit, UCharCategory type) {
|
|
zval retval;
|
|
zval args[3];
|
|
|
|
ZVAL_NULL(&retval);
|
|
/* Note that $start is INclusive, while $limit is EXclusive
|
|
* Therefore (0, 32, 15) means CPs 0..31 are of type 15
|
|
*/
|
|
ZVAL_LONG(&args[0], start);
|
|
ZVAL_LONG(&args[1], limit);
|
|
ZVAL_LONG(&args[2], type);
|
|
|
|
context->fci.retval = &retval;
|
|
context->fci.param_count = 3;
|
|
context->fci.params = args;
|
|
|
|
if (zend_call_function(&context->fci, &context->fci_cache) == FAILURE) {
|
|
intl_error_set_code(NULL, U_INTERNAL_PROGRAM_ERROR);
|
|
intl_errors_set_custom_msg(NULL, "enumCharTypes callback failed");
|
|
zval_ptr_dtor(&retval);
|
|
return 0;
|
|
}
|
|
zval_ptr_dtor(&retval);
|
|
return 1;
|
|
}
|
|
IC_METHOD(enumCharTypes) {
|
|
enumCharType_data context;
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
Z_PARAM_FUNC(context.fci, context.fci_cache)
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
u_enumCharTypes((UCharEnumTypeRange*)enumCharType_callback, &context);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(getBlockCode) {
|
|
UChar32 cp;
|
|
|
|
if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
|
|
RETURN_NULL();
|
|
}
|
|
|
|
RETURN_LONG(ublock_getCode(cp));
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(charName) {
|
|
UChar32 cp;
|
|
zend_string *string_codepoint;
|
|
zend_long int_codepoint = 0;
|
|
UErrorCode error = U_ZERO_ERROR;
|
|
zend_long nameChoice = U_UNICODE_CHAR_NAME;
|
|
zend_string *buffer = NULL;
|
|
int32_t buffer_len;
|
|
|
|
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, string_codepoint, int_codepoint) == FAILURE) {
|
|
RETURN_NULL();
|
|
}
|
|
|
|
buffer_len = u_charName(cp, (UCharNameChoice)nameChoice, NULL, 0, &error);
|
|
buffer = zend_string_alloc(buffer_len, 0);
|
|
error = U_ZERO_ERROR;
|
|
buffer_len = u_charName(cp, (UCharNameChoice)nameChoice, ZSTR_VAL(buffer), ZSTR_LEN(buffer) + 1, &error);
|
|
if (U_FAILURE(error)) {
|
|
zend_string_efree(buffer);
|
|
INTL_CHECK_STATUS_OR_NULL(error, "Failure getting character name");
|
|
}
|
|
RETURN_NEW_STR(buffer);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(charFromName) {
|
|
char *name;
|
|
size_t name_len;
|
|
zend_long nameChoice = U_UNICODE_CHAR_NAME;
|
|
UChar32 ret;
|
|
UErrorCode error = U_ZERO_ERROR;
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
Z_PARAM_STRING(name, name_len)
|
|
Z_PARAM_OPTIONAL
|
|
Z_PARAM_LONG(nameChoice)
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
ret = u_charFromName((UCharNameChoice)nameChoice, name, &error);
|
|
INTL_CHECK_STATUS_OR_NULL(error, NULL);
|
|
RETURN_LONG(ret);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ void void IntlChar::enumCharNames(int|string $start, int|string $limit, callable $callback, int $nameChoice = IntlChar::UNICODE_CHAR_NAME) */
|
|
typedef struct _enumCharNames_data {
|
|
zend_fcall_info fci;
|
|
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) {
|
|
zval retval;
|
|
zval args[3];
|
|
|
|
ZVAL_NULL(&retval);
|
|
ZVAL_LONG(&args[0], code);
|
|
ZVAL_LONG(&args[1], nameChoice);
|
|
ZVAL_STRINGL(&args[2], name, length);
|
|
|
|
context->fci.retval = &retval;
|
|
context->fci.param_count = 3;
|
|
context->fci.params = args;
|
|
|
|
if (zend_call_function(&context->fci, &context->fci_cache) == FAILURE) {
|
|
intl_error_set_code(NULL, U_INTERNAL_PROGRAM_ERROR);
|
|
intl_error_set_custom_msg(NULL, "enumCharNames callback failed");
|
|
zval_ptr_dtor(&retval);
|
|
zval_ptr_dtor_str(&args[2]);
|
|
return 0;
|
|
}
|
|
zval_ptr_dtor(&retval);
|
|
zval_ptr_dtor_str(&args[2]);
|
|
return 1;
|
|
}
|
|
IC_METHOD(enumCharNames) {
|
|
UChar32 start, limit;
|
|
zend_string *string_start, *string_limit;
|
|
zend_long int_start = 0, int_limit = 0;
|
|
enumCharNames_data context;
|
|
zend_long nameChoice = U_UNICODE_CHAR_NAME;
|
|
UErrorCode error = U_ZERO_ERROR;
|
|
|
|
|
|
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_FALSE;
|
|
}
|
|
|
|
u_enumCharNames(start, limit, (UEnumCharNamesFn*)enumCharNames_callback, &context, static_cast<UCharNameChoice>(nameChoice), &error);
|
|
INTL_CHECK_STATUS(error, NULL);
|
|
RETURN_TRUE;
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(getPropertyName) {
|
|
zend_long property;
|
|
zend_long nameChoice = U_LONG_PROPERTY_NAME;
|
|
const char *ret;
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
Z_PARAM_LONG(property)
|
|
Z_PARAM_OPTIONAL
|
|
Z_PARAM_LONG(nameChoice)
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
ret = u_getPropertyName((UProperty)property, (UPropertyNameChoice)nameChoice);
|
|
if (ret) {
|
|
RETURN_STRING(ret);
|
|
} else {
|
|
intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR);
|
|
intl_error_set_custom_msg(NULL, "Failed to get property name");
|
|
RETURN_FALSE;
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(getPropertyEnum) {
|
|
char *alias;
|
|
size_t alias_len;
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
Z_PARAM_STRING(alias, alias_len)
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
RETURN_LONG(u_getPropertyEnum(alias));
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(getPropertyValueName) {
|
|
zend_long property, value, nameChoice = U_LONG_PROPERTY_NAME;
|
|
const char *ret;
|
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 3)
|
|
Z_PARAM_LONG(property)
|
|
Z_PARAM_LONG(value)
|
|
Z_PARAM_OPTIONAL
|
|
Z_PARAM_LONG(nameChoice)
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
ret = u_getPropertyValueName((UProperty)property, value, (UPropertyNameChoice)nameChoice);
|
|
if (ret) {
|
|
RETURN_STRING(ret);
|
|
} else {
|
|
intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR);
|
|
intl_error_set_custom_msg(NULL, "Failed to get property name");
|
|
RETURN_FALSE;
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(getPropertyValueEnum) {
|
|
zend_long property;
|
|
char *name;
|
|
size_t name_len;
|
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
Z_PARAM_LONG(property)
|
|
Z_PARAM_STRING(name, name_len)
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
RETURN_LONG(u_getPropertyValueEnum((UProperty)property, name));
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(foldCase) {
|
|
UChar32 cp, ret;
|
|
zend_long options = U_FOLD_CASE_DEFAULT;
|
|
zend_string *string_codepoint;
|
|
zend_long int_codepoint = 0;
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
|
|
Z_PARAM_OPTIONAL
|
|
Z_PARAM_LONG(options)
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) {
|
|
RETURN_NULL();
|
|
}
|
|
|
|
ret = u_foldCase(cp, options);
|
|
if (string_codepoint != NULL) {
|
|
char buffer[5];
|
|
int buffer_len = 0;
|
|
U8_APPEND_UNSAFE(buffer, buffer_len, ret);
|
|
buffer[buffer_len] = 0;
|
|
RETURN_STRINGL(buffer, buffer_len);
|
|
} else {
|
|
RETURN_LONG(ret);
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(digit) {
|
|
UChar32 cp;
|
|
zend_long radix = 10;
|
|
int ret;
|
|
zend_string *string_codepoint;
|
|
zend_long int_codepoint = 0;
|
|
|
|
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, string_codepoint, int_codepoint) == FAILURE) {
|
|
RETURN_NULL();
|
|
}
|
|
|
|
ret = u_digit(cp, radix);
|
|
if (ret < 0) {
|
|
intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR);
|
|
intl_error_set_custom_msg(NULL, "Invalid digit");
|
|
RETURN_FALSE;
|
|
}
|
|
RETURN_LONG(ret);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(forDigit) {
|
|
zend_long digit, radix = 10;
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
Z_PARAM_LONG(digit)
|
|
Z_PARAM_OPTIONAL
|
|
Z_PARAM_LONG(radix)
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
RETURN_LONG(u_forDigit(digit, radix));
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(charAge) {
|
|
UChar32 cp;
|
|
UVersionInfo version;
|
|
int i;
|
|
|
|
if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
|
|
RETURN_NULL();
|
|
}
|
|
|
|
u_charAge(cp, version);
|
|
array_init(return_value);
|
|
for(i = 0; i < U_MAX_VERSION_LENGTH; ++i) {
|
|
add_next_index_long(return_value, version[i]);
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(getUnicodeVersion) {
|
|
UVersionInfo version;
|
|
int i;
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
u_getUnicodeVersion(version);
|
|
array_init(return_value);
|
|
for(i = 0; i < U_MAX_VERSION_LENGTH; ++i) {
|
|
add_next_index_long(return_value, version[i]);
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
IC_METHOD(getFC_NFKC_Closure) {
|
|
UChar32 cp;
|
|
UChar *closure;
|
|
zend_string *u8str;
|
|
int32_t closure_len;
|
|
UErrorCode error = U_ZERO_ERROR;
|
|
|
|
if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
|
|
RETURN_NULL();
|
|
}
|
|
|
|
closure_len = u_getFC_NFKC_Closure(cp, NULL, 0, &error);
|
|
if (closure_len == 0) {
|
|
RETURN_EMPTY_STRING();
|
|
}
|
|
closure = reinterpret_cast<UChar *>(safe_emalloc(sizeof(UChar), closure_len + 1, 0));
|
|
error = U_ZERO_ERROR;
|
|
closure_len = u_getFC_NFKC_Closure(cp, closure, closure_len, &error);
|
|
if (U_FAILURE(error)) {
|
|
efree(closure);
|
|
INTL_CHECK_STATUS(error, "Failed getting closure");
|
|
}
|
|
|
|
error = U_ZERO_ERROR;
|
|
u8str = intl_convert_utf16_to_utf8(closure, closure_len, &error);
|
|
INTL_CHECK_STATUS(error, "Failed converting output to UTF8");
|
|
efree(closure);
|
|
RETVAL_NEW_STR(u8str);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
#define IC_BOOL_METHOD_CHAR(name) \
|
|
IC_METHOD(name) { \
|
|
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)
|
|
IC_BOOL_METHOD_CHAR(isULowercase)
|
|
IC_BOOL_METHOD_CHAR(isUUppercase)
|
|
IC_BOOL_METHOD_CHAR(isUWhiteSpace)
|
|
IC_BOOL_METHOD_CHAR(islower)
|
|
IC_BOOL_METHOD_CHAR(isupper)
|
|
IC_BOOL_METHOD_CHAR(istitle)
|
|
IC_BOOL_METHOD_CHAR(isdigit)
|
|
IC_BOOL_METHOD_CHAR(isalpha)
|
|
IC_BOOL_METHOD_CHAR(isalnum)
|
|
IC_BOOL_METHOD_CHAR(isxdigit)
|
|
IC_BOOL_METHOD_CHAR(ispunct)
|
|
IC_BOOL_METHOD_CHAR(isgraph)
|
|
IC_BOOL_METHOD_CHAR(isblank)
|
|
IC_BOOL_METHOD_CHAR(isdefined)
|
|
IC_BOOL_METHOD_CHAR(isspace)
|
|
IC_BOOL_METHOD_CHAR(isJavaSpaceChar)
|
|
IC_BOOL_METHOD_CHAR(isWhitespace)
|
|
IC_BOOL_METHOD_CHAR(iscntrl)
|
|
IC_BOOL_METHOD_CHAR(isISOControl)
|
|
IC_BOOL_METHOD_CHAR(isprint)
|
|
IC_BOOL_METHOD_CHAR(isbase)
|
|
IC_BOOL_METHOD_CHAR(isMirrored)
|
|
IC_BOOL_METHOD_CHAR(isIDStart)
|
|
IC_BOOL_METHOD_CHAR(isIDPart)
|
|
IC_BOOL_METHOD_CHAR(isIDIgnorable)
|
|
IC_BOOL_METHOD_CHAR(isJavaIDStart)
|
|
IC_BOOL_METHOD_CHAR(isJavaIDPart)
|
|
#undef IC_BOOL_METHOD_CHAR
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
#define IC_INT_METHOD_CHAR(name) \
|
|
IC_METHOD(name) { \
|
|
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)
|
|
IC_INT_METHOD_CHAR(charType)
|
|
IC_INT_METHOD_CHAR(getCombiningClass)
|
|
IC_INT_METHOD_CHAR(charDigitValue)
|
|
#undef IC_INT_METHOD_CHAR
|
|
/* }}} */
|
|
|
|
/* {{{ Returns a utf-8 character if codepoint was passed as a utf-8 sequence
|
|
* Returns an int otherwise
|
|
*/
|
|
#define IC_CHAR_METHOD_CHAR(name) \
|
|
IC_METHOD(name) { \
|
|
UChar32 cp, ret; \
|
|
zend_string *string_codepoint; \
|
|
zend_long int_codepoint = -1; \
|
|
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 (string_codepoint != NULL) { \
|
|
char buffer[5]; \
|
|
int buffer_len = 0; \
|
|
U8_APPEND_UNSAFE(buffer, buffer_len, ret); \
|
|
buffer[buffer_len] = 0; \
|
|
RETURN_STRINGL(buffer, buffer_len); \
|
|
} else { \
|
|
RETURN_LONG(ret); \
|
|
} \
|
|
}
|
|
IC_CHAR_METHOD_CHAR(charMirror)
|
|
IC_CHAR_METHOD_CHAR(tolower)
|
|
IC_CHAR_METHOD_CHAR(toupper)
|
|
IC_CHAR_METHOD_CHAR(totitle)
|
|
IC_CHAR_METHOD_CHAR(getBidiPairedBracket)
|
|
#undef IC_CHAR_METHOD_CHAR
|
|
/* }}} */
|
|
|
|
int php_uchar_minit(INIT_FUNC_ARGS) {
|
|
register_class_IntlChar();
|
|
|
|
return SUCCESS;
|
|
}
|