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