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