1 #include "uchar.h"
2 #include "intl_data.h"
3 #include "intl_convert.h"
4
5 #include <unicode/uchar.h>
6 #include <unicode/utf8.h>
7
8 #include "uchar_arginfo.h"
9
10 #define IC_METHOD(mname) PHP_METHOD(IntlChar, mname)
11
convert_cp(UChar32 * pcp,zend_string * string_codepoint,zend_long int_codepoint)12 static inline int convert_cp(UChar32* pcp, zend_string *string_codepoint, zend_long int_codepoint) {
13 if (string_codepoint != NULL) {
14 int32_t i = 0;
15 size_t string_codepoint_length = ZSTR_LEN(string_codepoint);
16
17 if (ZEND_SIZE_T_INT_OVFL(string_codepoint_length)) {
18 intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR);
19 intl_error_set_custom_msg(NULL, "Input string is too long.", 0);
20 return FAILURE;
21 }
22
23 U8_NEXT(ZSTR_VAL(string_codepoint), i, string_codepoint_length, int_codepoint);
24 if ((size_t)i != string_codepoint_length) {
25 intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR);
26 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);
27 return FAILURE;
28 }
29 }
30
31 if ((int_codepoint < UCHAR_MIN_VALUE) || (int_codepoint > UCHAR_MAX_VALUE)) {
32 intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR);
33 intl_error_set_custom_msg(NULL, "Codepoint out of range", 0);
34 return FAILURE;
35 }
36 *pcp = (UChar32)int_codepoint;
37 return SUCCESS;
38 }
39
parse_code_point_param(INTERNAL_FUNCTION_PARAMETERS,UChar32 * cp)40 static zend_never_inline int parse_code_point_param(INTERNAL_FUNCTION_PARAMETERS, UChar32 *cp) {
41 zend_string *string_codepoint;
42 zend_long int_codepoint = 0;
43 ZEND_PARSE_PARAMETERS_START(1, 1)
44 Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
45 ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
46 return convert_cp(cp, string_codepoint, int_codepoint);
47 }
48
49 /* {{{ Converts a numeric codepoint to UTF-8
50 * Acts as an identify function when given a valid UTF-8 encoded codepoint
51 */
IC_METHOD(chr)52 IC_METHOD(chr) {
53 UChar32 cp;
54 char buffer[5];
55 int buffer_len = 0;
56
57 if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
58 RETURN_NULL();
59 }
60
61 /* We can use unsafe because we know the codepoint is in valid range
62 * and that 4 bytes is enough for any unicode point
63 */
64 U8_APPEND_UNSAFE(buffer, buffer_len, cp);
65 buffer[buffer_len] = 0;
66 RETURN_STRINGL(buffer, buffer_len);
67 }
68 /* }}} */
69
70 /* {{{ Converts a UTf-8 encoded codepoint to its integer U32 value
71 * Acts as an identity function when passed a valid integer codepoint
72 */
IC_METHOD(ord)73 IC_METHOD(ord) {
74 UChar32 cp;
75
76 if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
77 RETURN_NULL();
78 }
79
80 RETURN_LONG(cp);
81 }
82 /* }}} */
83
84 /* {{{ */
IC_METHOD(hasBinaryProperty)85 IC_METHOD(hasBinaryProperty) {
86 UChar32 cp;
87 zend_long prop;
88 zend_string *string_codepoint;
89 zend_long int_codepoint = 0;
90
91 ZEND_PARSE_PARAMETERS_START(2, 2)
92 Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
93 Z_PARAM_LONG(prop)
94 ZEND_PARSE_PARAMETERS_END();
95
96 if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) {
97 RETURN_NULL();
98 }
99
100 RETURN_BOOL(u_hasBinaryProperty(cp, (UProperty)prop));
101 }
102 /* }}} */
103
104 /* {{{ */
IC_METHOD(getIntPropertyValue)105 IC_METHOD(getIntPropertyValue) {
106 UChar32 cp;
107 zend_long prop;
108 zend_string *string_codepoint;
109 zend_long int_codepoint = 0;
110
111 ZEND_PARSE_PARAMETERS_START(2, 2)
112 Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
113 Z_PARAM_LONG(prop)
114 ZEND_PARSE_PARAMETERS_END();
115
116 if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) {
117 RETURN_NULL();
118 }
119
120 RETURN_LONG(u_getIntPropertyValue(cp, (UProperty)prop));
121 }
122 /* }}} */
123
124 /* {{{ */
IC_METHOD(getIntPropertyMinValue)125 IC_METHOD(getIntPropertyMinValue) {
126 zend_long prop;
127
128 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &prop) == FAILURE) {
129 RETURN_THROWS();
130 }
131
132 RETURN_LONG(u_getIntPropertyMinValue((UProperty)prop));
133 }
134 /* }}} */
135
136 /* {{{ */
IC_METHOD(getIntPropertyMaxValue)137 IC_METHOD(getIntPropertyMaxValue) {
138 zend_long prop;
139
140 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &prop) == FAILURE) {
141 RETURN_THROWS();
142 }
143
144 RETURN_LONG(u_getIntPropertyMaxValue((UProperty)prop));
145 }
146 /* }}} */
147
148 /* {{{ */
IC_METHOD(getNumericValue)149 IC_METHOD(getNumericValue) {
150 UChar32 cp;
151
152 if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
153 RETURN_NULL();
154 }
155
156 RETURN_DOUBLE(u_getNumericValue(cp));
157 }
158 /* }}} */
159
160 /* {{{ */
161 typedef struct _enumCharType_data {
162 zend_fcall_info fci;
163 zend_fcall_info_cache fci_cache;
164 } enumCharType_data;
enumCharType_callback(enumCharType_data * context,UChar32 start,UChar32 limit,UCharCategory type)165 static UBool enumCharType_callback(enumCharType_data *context,
166 UChar32 start, UChar32 limit, UCharCategory type) {
167 zval retval;
168 zval args[3];
169
170 ZVAL_NULL(&retval);
171 /* Note that $start is INclusive, while $limit is EXclusive
172 * Therefore (0, 32, 15) means CPs 0..31 are of type 15
173 */
174 ZVAL_LONG(&args[0], start);
175 ZVAL_LONG(&args[1], limit);
176 ZVAL_LONG(&args[2], type);
177
178 context->fci.retval = &retval;
179 context->fci.param_count = 3;
180 context->fci.params = args;
181
182 if (zend_call_function(&context->fci, &context->fci_cache) == FAILURE) {
183 intl_error_set_code(NULL, U_INTERNAL_PROGRAM_ERROR);
184 intl_errors_set_custom_msg(NULL, "enumCharTypes callback failed", 0);
185 zval_ptr_dtor(&retval);
186 return 0;
187 }
188 zval_ptr_dtor(&retval);
189 return 1;
190 }
IC_METHOD(enumCharTypes)191 IC_METHOD(enumCharTypes) {
192 enumCharType_data context;
193
194 if (zend_parse_parameters(ZEND_NUM_ARGS(), "f", &context.fci, &context.fci_cache) == FAILURE) {
195 RETURN_THROWS();
196 }
197 u_enumCharTypes((UCharEnumTypeRange*)enumCharType_callback, &context);
198 }
199 /* }}} */
200
201 /* {{{ */
IC_METHOD(getBlockCode)202 IC_METHOD(getBlockCode) {
203 UChar32 cp;
204
205 if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
206 RETURN_NULL();
207 }
208
209 RETURN_LONG(ublock_getCode(cp));
210 }
211 /* }}} */
212
213 /* {{{ */
IC_METHOD(charName)214 IC_METHOD(charName) {
215 UChar32 cp;
216 zend_string *string_codepoint;
217 zend_long int_codepoint = 0;
218 UErrorCode error = U_ZERO_ERROR;
219 zend_long nameChoice = U_UNICODE_CHAR_NAME;
220 zend_string *buffer = NULL;
221 int32_t buffer_len;
222
223 ZEND_PARSE_PARAMETERS_START(1, 2)
224 Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
225 Z_PARAM_OPTIONAL
226 Z_PARAM_LONG(nameChoice)
227 ZEND_PARSE_PARAMETERS_END();
228
229 if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) {
230 RETURN_NULL();
231 }
232
233 buffer_len = u_charName(cp, (UCharNameChoice)nameChoice, NULL, 0, &error);
234 buffer = zend_string_alloc(buffer_len, 0);
235 error = U_ZERO_ERROR;
236 buffer_len = u_charName(cp, (UCharNameChoice)nameChoice, ZSTR_VAL(buffer), ZSTR_LEN(buffer) + 1, &error);
237 if (U_FAILURE(error)) {
238 zend_string_efree(buffer);
239 INTL_CHECK_STATUS_OR_NULL(error, "Failure getting character name");
240 }
241 RETURN_NEW_STR(buffer);
242 }
243 /* }}} */
244
245 /* {{{ */
IC_METHOD(charFromName)246 IC_METHOD(charFromName) {
247 char *name;
248 size_t name_len;
249 zend_long nameChoice = U_UNICODE_CHAR_NAME;
250 UChar32 ret;
251 UErrorCode error = U_ZERO_ERROR;
252
253 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &name, &name_len, &nameChoice) == FAILURE) {
254 RETURN_THROWS();
255 }
256
257 ret = u_charFromName((UCharNameChoice)nameChoice, name, &error);
258 INTL_CHECK_STATUS_OR_NULL(error, NULL);
259 RETURN_LONG(ret);
260 }
261 /* }}} */
262
263 /* {{{ void void IntlChar::enumCharNames(int|string $start, int|string $limit, callable $callback, int $nameChoice = IntlChar::UNICODE_CHAR_NAME) */
264 typedef struct _enumCharNames_data {
265 zend_fcall_info fci;
266 zend_fcall_info_cache fci_cache;
267 } enumCharNames_data;
enumCharNames_callback(enumCharNames_data * context,UChar32 code,UCharNameChoice nameChoice,const char * name,int32_t length)268 static UBool enumCharNames_callback(enumCharNames_data *context,
269 UChar32 code, UCharNameChoice nameChoice,
270 const char *name, int32_t length) {
271 zval retval;
272 zval args[3];
273
274 ZVAL_NULL(&retval);
275 ZVAL_LONG(&args[0], code);
276 ZVAL_LONG(&args[1], nameChoice);
277 ZVAL_STRINGL(&args[2], name, length);
278
279 context->fci.retval = &retval;
280 context->fci.param_count = 3;
281 context->fci.params = args;
282
283 if (zend_call_function(&context->fci, &context->fci_cache) == FAILURE) {
284 intl_error_set_code(NULL, U_INTERNAL_PROGRAM_ERROR);
285 intl_error_set_custom_msg(NULL, "enumCharNames callback failed", 0);
286 zval_ptr_dtor(&retval);
287 zval_ptr_dtor_str(&args[2]);
288 return 0;
289 }
290 zval_ptr_dtor(&retval);
291 zval_ptr_dtor_str(&args[2]);
292 return 1;
293 }
IC_METHOD(enumCharNames)294 IC_METHOD(enumCharNames) {
295 UChar32 start, limit;
296 zend_string *string_start, *string_limit;
297 zend_long int_start = 0, int_limit = 0;
298 enumCharNames_data context;
299 zend_long nameChoice = U_UNICODE_CHAR_NAME;
300 UErrorCode error = U_ZERO_ERROR;
301
302
303 ZEND_PARSE_PARAMETERS_START(3, 4)
304 Z_PARAM_STR_OR_LONG(string_start, int_start)
305 Z_PARAM_STR_OR_LONG(string_limit, int_limit)
306 Z_PARAM_FUNC(context.fci, context.fci_cache)
307 Z_PARAM_OPTIONAL
308 Z_PARAM_LONG(nameChoice)
309 ZEND_PARSE_PARAMETERS_END();
310
311 if (convert_cp(&start, string_start, int_start) == FAILURE || convert_cp(&limit, string_limit, int_limit) == FAILURE) {
312 RETURN_FALSE;
313 }
314
315 u_enumCharNames(start, limit, (UEnumCharNamesFn*)enumCharNames_callback, &context, nameChoice, &error);
316 INTL_CHECK_STATUS(error, NULL);
317 RETURN_TRUE;
318 }
319 /* }}} */
320
321 /* {{{ */
IC_METHOD(getPropertyName)322 IC_METHOD(getPropertyName) {
323 zend_long property;
324 zend_long nameChoice = U_LONG_PROPERTY_NAME;
325 const char *ret;
326
327 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &property, &nameChoice) == FAILURE) {
328 RETURN_THROWS();
329 }
330
331 ret = u_getPropertyName((UProperty)property, (UPropertyNameChoice)nameChoice);
332 if (ret) {
333 RETURN_STRING(ret);
334 } else {
335 intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR);
336 intl_error_set_custom_msg(NULL, "Failed to get property name", 0);
337 RETURN_FALSE;
338 }
339 }
340 /* }}} */
341
342 /* {{{ */
IC_METHOD(getPropertyEnum)343 IC_METHOD(getPropertyEnum) {
344 char *alias;
345 size_t alias_len;
346
347 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &alias, &alias_len) == FAILURE) {
348 RETURN_THROWS();
349 }
350
351 RETURN_LONG(u_getPropertyEnum(alias));
352 }
353 /* }}} */
354
355 /* {{{ */
IC_METHOD(getPropertyValueName)356 IC_METHOD(getPropertyValueName) {
357 zend_long property, value, nameChoice = U_LONG_PROPERTY_NAME;
358 const char *ret;
359
360 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|l", &property, &value, &nameChoice) == FAILURE) {
361 RETURN_THROWS();
362 }
363
364 ret = u_getPropertyValueName((UProperty)property, value, (UPropertyNameChoice)nameChoice);
365 if (ret) {
366 RETURN_STRING(ret);
367 } else {
368 intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR);
369 intl_error_set_custom_msg(NULL, "Failed to get property name", 0);
370 RETURN_FALSE;
371 }
372 }
373 /* }}} */
374
375 /* {{{ */
IC_METHOD(getPropertyValueEnum)376 IC_METHOD(getPropertyValueEnum) {
377 zend_long property;
378 char *name;
379 size_t name_len;
380
381 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &property, &name, &name_len) == FAILURE) {
382 RETURN_THROWS();
383 }
384
385 RETURN_LONG(u_getPropertyValueEnum((UProperty)property, name));
386 }
387 /* }}} */
388
389 /* {{{ */
IC_METHOD(foldCase)390 IC_METHOD(foldCase) {
391 UChar32 cp, ret;
392 zend_long options = U_FOLD_CASE_DEFAULT;
393 zend_string *string_codepoint;
394 zend_long int_codepoint = 0;
395
396 ZEND_PARSE_PARAMETERS_START(1, 2)
397 Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
398 Z_PARAM_OPTIONAL
399 Z_PARAM_LONG(options)
400 ZEND_PARSE_PARAMETERS_END();
401
402 if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) {
403 RETURN_NULL();
404 }
405
406 ret = u_foldCase(cp, options);
407 if (string_codepoint != NULL) {
408 char buffer[5];
409 int buffer_len = 0;
410 U8_APPEND_UNSAFE(buffer, buffer_len, ret);
411 buffer[buffer_len] = 0;
412 RETURN_STRINGL(buffer, buffer_len);
413 } else {
414 RETURN_LONG(ret);
415 }
416 }
417 /* }}} */
418
419 /* {{{ */
IC_METHOD(digit)420 IC_METHOD(digit) {
421 UChar32 cp;
422 zend_long radix = 10;
423 int ret;
424 zend_string *string_codepoint;
425 zend_long int_codepoint = 0;
426
427 ZEND_PARSE_PARAMETERS_START(1, 2)
428 Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
429 Z_PARAM_OPTIONAL
430 Z_PARAM_LONG(radix)
431 ZEND_PARSE_PARAMETERS_END();
432
433 if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) {
434 RETURN_NULL();
435 }
436
437 ret = u_digit(cp, radix);
438 if (ret < 0) {
439 intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR);
440 intl_error_set_custom_msg(NULL, "Invalid digit", 0);
441 RETURN_FALSE;
442 }
443 RETURN_LONG(ret);
444 }
445 /* }}} */
446
447 /* {{{ */
IC_METHOD(forDigit)448 IC_METHOD(forDigit) {
449 zend_long digit, radix = 10;
450
451 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &digit, &radix) == FAILURE) {
452 RETURN_THROWS();
453 }
454
455 RETURN_LONG(u_forDigit(digit, radix));
456 }
457 /* }}} */
458
459 /* {{{ */
IC_METHOD(charAge)460 IC_METHOD(charAge) {
461 UChar32 cp;
462 UVersionInfo version;
463 int i;
464
465 if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
466 RETURN_NULL();
467 }
468
469 u_charAge(cp, version);
470 array_init(return_value);
471 for(i = 0; i < U_MAX_VERSION_LENGTH; ++i) {
472 add_next_index_long(return_value, version[i]);
473 }
474 }
475 /* }}} */
476
477 /* {{{ */
IC_METHOD(getUnicodeVersion)478 IC_METHOD(getUnicodeVersion) {
479 UVersionInfo version;
480 int i;
481
482 if (zend_parse_parameters_none() == FAILURE) {
483 RETURN_THROWS();
484 }
485
486 u_getUnicodeVersion(version);
487 array_init(return_value);
488 for(i = 0; i < U_MAX_VERSION_LENGTH; ++i) {
489 add_next_index_long(return_value, version[i]);
490 }
491 }
492 /* }}} */
493
494 /* {{{ */
IC_METHOD(getFC_NFKC_Closure)495 IC_METHOD(getFC_NFKC_Closure) {
496 UChar32 cp;
497 UChar *closure;
498 zend_string *u8str;
499 int32_t closure_len;
500 UErrorCode error = U_ZERO_ERROR;
501
502 if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
503 RETURN_NULL();
504 }
505
506 closure_len = u_getFC_NFKC_Closure(cp, NULL, 0, &error);
507 if (closure_len == 0) {
508 RETURN_EMPTY_STRING();
509 }
510 closure = safe_emalloc(sizeof(UChar), closure_len + 1, 0);
511 error = U_ZERO_ERROR;
512 closure_len = u_getFC_NFKC_Closure(cp, closure, closure_len, &error);
513 if (U_FAILURE(error)) {
514 efree(closure);
515 INTL_CHECK_STATUS(error, "Failed getting closure");
516 }
517
518 error = U_ZERO_ERROR;
519 u8str = intl_convert_utf16_to_utf8(closure, closure_len, &error);
520 INTL_CHECK_STATUS(error, "Failed converting output to UTF8");
521 efree(closure);
522 RETVAL_NEW_STR(u8str);
523 }
524 /* }}} */
525
526 /* {{{ */
527 #define IC_BOOL_METHOD_CHAR(name) \
528 IC_METHOD(name) { \
529 UChar32 cp; \
530 if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { \
531 RETURN_NULL(); \
532 } \
533 RETURN_BOOL(u_##name(cp)); \
534 }
535 IC_BOOL_METHOD_CHAR(isUAlphabetic)
IC_BOOL_METHOD_CHAR(isULowercase)536 IC_BOOL_METHOD_CHAR(isULowercase)
537 IC_BOOL_METHOD_CHAR(isUUppercase)
538 IC_BOOL_METHOD_CHAR(isUWhiteSpace)
539 IC_BOOL_METHOD_CHAR(islower)
540 IC_BOOL_METHOD_CHAR(isupper)
541 IC_BOOL_METHOD_CHAR(istitle)
542 IC_BOOL_METHOD_CHAR(isdigit)
543 IC_BOOL_METHOD_CHAR(isalpha)
544 IC_BOOL_METHOD_CHAR(isalnum)
545 IC_BOOL_METHOD_CHAR(isxdigit)
546 IC_BOOL_METHOD_CHAR(ispunct)
547 IC_BOOL_METHOD_CHAR(isgraph)
548 IC_BOOL_METHOD_CHAR(isblank)
549 IC_BOOL_METHOD_CHAR(isdefined)
550 IC_BOOL_METHOD_CHAR(isspace)
551 IC_BOOL_METHOD_CHAR(isJavaSpaceChar)
552 IC_BOOL_METHOD_CHAR(isWhitespace)
553 IC_BOOL_METHOD_CHAR(iscntrl)
554 IC_BOOL_METHOD_CHAR(isISOControl)
555 IC_BOOL_METHOD_CHAR(isprint)
556 IC_BOOL_METHOD_CHAR(isbase)
557 IC_BOOL_METHOD_CHAR(isMirrored)
558 IC_BOOL_METHOD_CHAR(isIDStart)
559 IC_BOOL_METHOD_CHAR(isIDPart)
560 IC_BOOL_METHOD_CHAR(isIDIgnorable)
561 IC_BOOL_METHOD_CHAR(isJavaIDStart)
562 IC_BOOL_METHOD_CHAR(isJavaIDPart)
563 #undef IC_BOOL_METHOD_CHAR
564 /* }}} */
565
566 /* {{{ */
567 #define IC_INT_METHOD_CHAR(name) \
568 IC_METHOD(name) { \
569 UChar32 cp; \
570 if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { \
571 RETURN_NULL(); \
572 } \
573 RETURN_LONG(u_##name(cp)); \
574 }
575 IC_INT_METHOD_CHAR(charDirection)
576 IC_INT_METHOD_CHAR(charType)
577 IC_INT_METHOD_CHAR(getCombiningClass)
578 IC_INT_METHOD_CHAR(charDigitValue)
579 #undef IC_INT_METHOD_CHAR
580 /* }}} */
581
582 /* {{{ Returns a utf-8 character if codepoint was passed as a utf-8 sequence
583 * Returns an int otherwise
584 */
585 #define IC_CHAR_METHOD_CHAR(name) \
586 IC_METHOD(name) { \
587 UChar32 cp, ret; \
588 zend_string *string_codepoint; \
589 zend_long int_codepoint = -1; \
590 ZEND_PARSE_PARAMETERS_START(1, 1) \
591 Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) \
592 ZEND_PARSE_PARAMETERS_END(); \
593 if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) { \
594 RETURN_NULL(); \
595 } \
596 ret = u_##name(cp); \
597 if (string_codepoint != NULL) { \
598 char buffer[5]; \
599 int buffer_len = 0; \
600 U8_APPEND_UNSAFE(buffer, buffer_len, ret); \
601 buffer[buffer_len] = 0; \
602 RETURN_STRINGL(buffer, buffer_len); \
603 } else { \
604 RETURN_LONG(ret); \
605 } \
606 }
607 IC_CHAR_METHOD_CHAR(charMirror)
608 IC_CHAR_METHOD_CHAR(tolower)
609 IC_CHAR_METHOD_CHAR(toupper)
610 IC_CHAR_METHOD_CHAR(totitle)
611 #if U_ICU_VERSION_MAJOR_NUM >= 52
612 IC_CHAR_METHOD_CHAR(getBidiPairedBracket)
613 #endif /* ICU >= 52 */
614 #undef IC_CHAR_METHOD_CHAR
615 /* }}} */
616
617 int php_uchar_minit(INIT_FUNC_ARGS) {
618 register_class_IntlChar();
619
620 return SUCCESS;
621 }
622