1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 6 |
4 : +----------------------------------------------------------------------+
5 : | This source file is subject to version 3.01 of the PHP license, |
6 : | that is bundled with this package in the file LICENSE, and is |
7 : | available through the world-wide-web at the following url: |
8 : | http://www.php.net/license/3_01.txt |
9 : | If you did not receive a copy of the PHP license and are unable to |
10 : | obtain it through the world-wide-web, please send a note to |
11 : | license@php.net so we can mail you a copy immediately. |
12 : +----------------------------------------------------------------------+
13 : | Authors: Andrei Zmievski <andrei@php.net> |
14 : +----------------------------------------------------------------------+
15 : */
16 :
17 : /* $Id: property.c 284422 2009-07-20 09:52:54Z pajoye $ */
18 :
19 : #include "php_unicode.h"
20 :
21 : typedef UBool (*prop_check_func_t)(UChar32 ch);
22 :
23 : typedef struct {
24 : zval **args[4];
25 : void ***thread_ctx;
26 : zend_fcall_info fci;
27 : zend_fcall_info_cache fci_cache;
28 : } char_enum_context_t;
29 :
30 : static void check_property_impl(INTERNAL_FUNCTION_PARAMETERS, prop_check_func_t checker)
31 0 : {
32 : UChar *str;
33 : int str_len;
34 0 : zend_bool result = 1;
35 0 : int offset = 0;
36 : UChar32 ch;
37 :
38 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "u", &str, &str_len) == FAILURE) {
39 0 : return;
40 : }
41 :
42 0 : if (str_len == 0) {
43 0 : RETURN_FALSE;
44 : }
45 :
46 0 : while (offset < str_len && result) {
47 0 : U16_NEXT(str, offset, str_len, ch);
48 0 : result = checker(ch);
49 : }
50 :
51 0 : RETURN_BOOL(result);
52 : }
53 :
54 : /* {{{ C/POSIX migration functions */
55 :
56 : /* {{{ proto bool char_is_lower(string text) U
57 : Determines if the string is lowercase */
58 : PHP_FUNCTION(char_is_lower)
59 0 : {
60 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_islower);
61 0 : }
62 : /* }}} */
63 :
64 : /* {{{ proto bool char_is_upper(string text) U
65 : Determines if the string is uppercase */
66 : PHP_FUNCTION(char_is_upper)
67 0 : {
68 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isupper);
69 0 : }
70 : /* }}} */
71 :
72 : /* {{{ proto bool char_is_digit(string text) U
73 : Determines if the string consists only of digits */
74 : PHP_FUNCTION(char_is_digit)
75 0 : {
76 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isdigit);
77 0 : }
78 : /* }}} */
79 :
80 : /* {{{ proto bool char_is_alpha(string text) U
81 : Determines if the string consists only of letter characters */
82 : PHP_FUNCTION(char_is_alpha)
83 0 : {
84 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isalpha);
85 0 : }
86 : /* }}} */
87 :
88 : /* {{{ proto bool char_is_alnum(string text) U
89 : Determines if the string consists only of alpanumeric characters */
90 : PHP_FUNCTION(char_is_alnum)
91 0 : {
92 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isalnum);
93 0 : }
94 : /* }}} */
95 :
96 : /* {{{ proto bool char_is_xdigit(string text) U
97 : Determines if the string consists only of hexadecimal digits */
98 : PHP_FUNCTION(char_is_xdigit)
99 0 : {
100 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isxdigit);
101 0 : }
102 : /* }}} */
103 :
104 : /* {{{ proto bool char_is_punct(string text) U
105 : Determines if the string consists only of punctuation characters */
106 : PHP_FUNCTION(char_is_punct)
107 0 : {
108 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_ispunct);
109 0 : }
110 : /* }}} */
111 :
112 : /* {{{ proto bool char_is_graph(string text) U
113 : Determines if the string consists only of "graphic" characters */
114 : PHP_FUNCTION(char_is_graph)
115 0 : {
116 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isgraph);
117 0 : }
118 : /* }}} */
119 :
120 : /* {{{ proto bool char_is_blank(string text) U
121 : Determines if the string consists only of "blank" characters */
122 : PHP_FUNCTION(char_is_blank)
123 0 : {
124 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isblank);
125 0 : }
126 : /* }}} */
127 :
128 : /* {{{ proto bool char_is_space(string text) U
129 : Determines if the string consists only of space characters */
130 : PHP_FUNCTION(char_is_space)
131 0 : {
132 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isspace);
133 0 : }
134 : /* }}} */
135 :
136 : /* {{{ proto bool char_is_cntrl(string text) U
137 : Determines if the string consists only of control characters */
138 : PHP_FUNCTION(char_is_cntrl)
139 0 : {
140 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_iscntrl);
141 0 : }
142 : /* }}} */
143 :
144 : /* {{{ proto bool char_is_print(string text) U
145 : Determines if the string consists only of printable characters */
146 : PHP_FUNCTION(char_is_print)
147 0 : {
148 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isprint);
149 0 : }
150 : /* }}} */
151 :
152 : /* }}} */
153 :
154 : /* {{{ Additional binary property functions */
155 :
156 : /* {{{ proto bool char_is_defined(string text) U
157 : Determines if the string consists only of defined characters (valid Unicode points) */
158 : PHP_FUNCTION(char_is_defined)
159 0 : {
160 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isdefined);
161 0 : }
162 : /* }}} */
163 :
164 : /* {{{ proto bool char_is_id_start(string text) U
165 : Determines if the specified character is permissible as the first character in an identifier according to Unicode */
166 : PHP_FUNCTION(char_is_id_start)
167 0 : {
168 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isIDStart);
169 0 : }
170 : /* }}} */
171 :
172 : /* {{{ proto bool char_is_id_part(string text) U
173 : etermines if the specified characters are permissible in an identifier, according to Java */
174 : PHP_FUNCTION(char_is_id_part)
175 0 : {
176 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isIDPart);
177 0 : }
178 : /* }}} */
179 :
180 : /* {{{ proto bool char_is_id_ignorable(string text) U
181 : Determines if the specified characters should be regarded as an ignorable character in an identifier, according to Java */
182 : PHP_FUNCTION(char_is_id_ignorable)
183 0 : {
184 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isIDIgnorable);
185 0 : }
186 : /* }}} */
187 :
188 : /* {{{ proto bool char_is_iso_control(string text) U
189 : Determines whether the specified code points are ISO control codes */
190 : PHP_FUNCTION(char_is_iso_control)
191 0 : {
192 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isISOControl);
193 0 : }
194 : /* }}} */
195 :
196 : /* {{{ proto bool char_is_mirrored(string text) U
197 : Determines whether the specified characters have the Bidi_Mirrored property */
198 : PHP_FUNCTION(char_is_mirrored)
199 0 : {
200 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isMirrored);
201 0 : }
202 : /* }}} */
203 :
204 : /* {{{ proto bool char_is_base(string text) U
205 : Determines if the string consists of only of base characters */
206 : PHP_FUNCTION(char_is_base)
207 0 : {
208 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isbase);
209 0 : }
210 : /* }}} */
211 :
212 : /* {{{ proto bool char_is_whitespace(string text) U
213 : Determines if the string consists only of whitespace characters, according to Java/ICU */
214 : PHP_FUNCTION(char_is_whitespace)
215 0 : {
216 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isUWhiteSpace);
217 0 : }
218 : /* }}} */
219 :
220 : /* {{{ proto bool char_is_alphabetic(string text) U
221 : Determines if the string consists only of characters with Alphabetic property */
222 : PHP_FUNCTION(char_is_alphabetic)
223 0 : {
224 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isUAlphabetic);
225 0 : }
226 : /* }}} */
227 :
228 : /* {{{ proto bool char_is_uppercase(string text) U
229 : Determines if the string consists only of characters with Uppercase property */
230 : PHP_FUNCTION(char_is_uppercase)
231 0 : {
232 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isUUppercase);
233 0 : }
234 : /* }}} */
235 :
236 : /* {{{ proto bool char_is_lowercase (string text) U
237 : Determines if the string consists only of characters with Lowercase property */
238 : PHP_FUNCTION(char_is_lowercase)
239 0 : {
240 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_isULowercase);
241 0 : }
242 : /* }}} */
243 :
244 : /* {{{ proto bool char_is_titlecase(string text) U
245 : Determines whether the string consists only of titlecase characters */
246 : PHP_FUNCTION(char_is_titlecase)
247 0 : {
248 0 : check_property_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, u_istitle);
249 0 : }
250 : /* }}} */
251 :
252 : /* }}} */
253 :
254 : /* {{{ Single character properties */
255 :
256 : /* {{{ proto float char_get_numeric_value(char text) U
257 : Get the numeric value for the character, as defined in the Unicode Character Database */
258 : PHP_FUNCTION(char_get_numeric_value)
259 0 : {
260 : UChar *str;
261 : int str_len;
262 0 : int offset = 0;
263 : UChar32 ch;
264 :
265 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "u", &str, &str_len) == FAILURE) {
266 0 : return;
267 : }
268 :
269 0 : if (str_len == 0) {
270 0 : RETURN_FALSE;
271 : }
272 0 : U16_NEXT(str, offset, str_len, ch);
273 :
274 0 : RETURN_DOUBLE(u_getNumericValue(ch));
275 : }
276 : /* }}} */
277 :
278 : /* {{{ proto int char_get_combining_class(char text) U
279 : Returns the combining class of the character */
280 : PHP_FUNCTION(char_get_combining_class)
281 0 : {
282 : UChar *str;
283 : int str_len;
284 0 : int offset = 0;
285 : UChar32 ch;
286 :
287 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "u", &str, &str_len) == FAILURE) {
288 0 : return;
289 : }
290 :
291 0 : if (str_len == 0) {
292 0 : RETURN_FALSE;
293 : }
294 0 : U16_NEXT(str, offset, str_len, ch);
295 :
296 0 : RETURN_LONG((long)u_getCombiningClass(ch));
297 : }
298 : /* }}} */
299 :
300 : /* {{{ proto int char_get_digit_value(char text[, int radix]) U
301 : Returns the decimal digit value of the character (optionally in the specific radix). */
302 : PHP_FUNCTION(char_get_digit_value)
303 0 : {
304 : UChar *str;
305 : int str_len;
306 0 : int offset = 0;
307 0 : long radix = 0;
308 : UChar32 ch;
309 :
310 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "u|l", &str, &str_len, &radix) == FAILURE) {
311 0 : return;
312 : }
313 :
314 0 : if (str_len == 0) {
315 0 : RETURN_FALSE;
316 : }
317 0 : U16_NEXT(str, offset, str_len, ch);
318 :
319 0 : if (ZEND_NUM_ARGS() > 1) {
320 0 : if (radix < 2 || radix > 36) {
321 0 : php_error(E_WARNING, "Radix has to be in 2-36 range");
322 0 : return;
323 : }
324 0 : RETURN_LONG(u_digit(ch, (int8_t) radix));
325 : } else {
326 0 : RETURN_LONG(u_charDigitValue(ch));
327 : }
328 : }
329 : /* }}} */
330 :
331 : /* {{{ proto char char_get_mirrored(char c) U
332 : Maps the specified character to its "mirror-image" */
333 : PHP_FUNCTION(char_get_mirrored)
334 0 : {
335 : UChar *str;
336 : int str_len;
337 0 : int offset = 0;
338 : UChar32 ch;
339 :
340 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "u", &str, &str_len) == FAILURE) {
341 0 : return;
342 : }
343 :
344 0 : if (str_len == 0) {
345 0 : RETURN_FALSE;
346 : }
347 0 : U16_NEXT(str, offset, str_len, ch);
348 :
349 0 : RETURN_UCHAR32(u_charMirror(ch));
350 : }
351 : /* }}} */
352 :
353 : /* {{{ proto int char_get_direction(char c) U
354 : Returns the bidirectional category value for the character, which is used in the Unicode bidirectional algorithm (UAX #9 http://www.unicode.org/reports/tr9/) */
355 : PHP_FUNCTION(char_get_direction)
356 0 : {
357 : UChar *str;
358 : int str_len;
359 0 : int offset = 0;
360 : UChar32 ch;
361 :
362 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "u", &str, &str_len) == FAILURE) {
363 0 : return;
364 : }
365 :
366 0 : if (str_len == 0) {
367 0 : RETURN_FALSE;
368 : }
369 0 : U16_NEXT(str, offset, str_len, ch);
370 :
371 0 : RETURN_LONG((long)u_charDirection(ch));
372 : }
373 : /* }}} */
374 :
375 : /* {{{ proto string char_get_age(char c) U
376 : Get the "age" of the code point (the Unicode version when it was first designated or assigned a character) */
377 : PHP_FUNCTION(char_get_age)
378 0 : {
379 : UChar *str;
380 : int str_len;
381 0 : int offset = 0;
382 : UChar32 ch;
383 : UVersionInfo version;
384 0 : char buf[18] = { 0, };
385 :
386 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "u", &str, &str_len) == FAILURE) {
387 0 : return;
388 : }
389 :
390 0 : if (str_len == 0) {
391 0 : RETURN_FALSE;
392 : }
393 0 : U16_NEXT(str, offset, str_len, ch);
394 :
395 0 : u_charAge(ch, version);
396 0 : u_versionToString(version, buf);
397 :
398 0 : RETURN_ASCII_STRING(buf, ZSTR_DUPLICATE);
399 : }
400 : /* }}} */
401 :
402 : /* {{{ proto int char_get_type(char c) U
403 : Returns the general category value for the code point */
404 : PHP_FUNCTION(char_get_type)
405 0 : {
406 : UChar *str;
407 : int str_len;
408 0 : int offset = 0;
409 : UChar32 ch;
410 :
411 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "u", &str, &str_len) == FAILURE) {
412 0 : return;
413 : }
414 :
415 0 : if (str_len == 0) {
416 0 : RETURN_FALSE;
417 : }
418 0 : U16_NEXT(str, offset, str_len, ch);
419 :
420 0 : RETURN_LONG(u_charType(ch));
421 : }
422 : /* }}} */
423 :
424 : /* {{{ proto bool char_is_valid(char c) U
425 : Determines if the the code point is valid character, according to Unicode */
426 : PHP_FUNCTION(char_is_valid)
427 0 : {
428 : UChar *str;
429 : int str_len;
430 0 : int offset = 0;
431 : UChar32 ch;
432 :
433 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "u", &str, &str_len) == FAILURE) {
434 0 : return;
435 : }
436 :
437 0 : if (str_len == 0) {
438 0 : RETURN_FALSE;
439 : }
440 0 : U16_NEXT(str, offset, str_len, ch);
441 :
442 0 : RETURN_BOOL(U_IS_UNICODE_CHAR(ch));
443 : }
444 : /* }}} */
445 :
446 : /* {{{ proto char char_from_digit(int digit[, int radix = 10]) U
447 : Get the character representation for the specified digit (optionally in the specified radix) */
448 : PHP_FUNCTION(char_from_digit)
449 0 : {
450 : long digit;
451 0 : long radix = 10;
452 : UChar32 ch;
453 :
454 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &digit, &radix) == FAILURE) {
455 0 : return;
456 : }
457 :
458 0 : if (ZEND_NUM_ARGS() > 1) {
459 0 : if (radix < 2 || radix > 36) {
460 0 : php_error(E_WARNING, "Radix has to be in 2-36 range");
461 0 : return;
462 : }
463 : }
464 0 : ch = u_forDigit(digit, (int8_t) radix);
465 :
466 0 : if (ch == (UChar32)0) {
467 0 : RETURN_FALSE;
468 : }
469 :
470 0 : RETURN_UCHAR32(ch);
471 : }
472 : /* }}} */
473 :
474 : /* {{{ proto char char_from_name(string charname[, bool extended = false]) U
475 : Translate a human readable character name into a codepoint */
476 : PHP_FUNCTION(char_from_name)
477 0 : {
478 : void *name;
479 : int name_len;
480 : zend_uchar name_type;
481 : UChar32 ch;
482 0 : UCharNameChoice choice = U_UNICODE_CHAR_NAME;
483 0 : zend_bool extended = FALSE;
484 : char *buf;
485 0 : UErrorCode status = U_ZERO_ERROR;
486 :
487 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|b", &name, &name_len, &name_type, &extended) == FAILURE) {
488 0 : return;
489 : }
490 :
491 0 : if (extended) {
492 0 : choice = U_EXTENDED_CHAR_NAME;
493 : }
494 :
495 0 : if (name_type == IS_UNICODE) {
496 0 : buf = zend_unicode_to_ascii(name, name_len TSRMLS_CC);
497 0 : if (buf == NULL) {
498 0 : php_error(E_WARNING, "Character name has to consist only of ASCII characters");
499 0 : RETURN_FALSE;
500 : }
501 : } else {
502 0 : buf = (char *) name;
503 : }
504 :
505 0 : ch = u_charFromName(choice, buf, &status);
506 :
507 0 : if (name_type == IS_UNICODE) {
508 0 : efree(buf);
509 : }
510 :
511 0 : if (U_SUCCESS(status)) {
512 0 : RETURN_UCHAR32(ch);
513 : } else {
514 0 : RETURN_FALSE;
515 : }
516 : }
517 : /* }}} */
518 :
519 : /* {{{ proto string char_get_name(char c[, bool extended = false]) U
520 : Get the human readable name associated with the character */
521 : PHP_FUNCTION(char_get_name)
522 0 : {
523 : UChar *str;
524 : int str_len;
525 0 : int offset = 0;
526 : UChar32 ch;
527 0 : zend_bool extended = FALSE;
528 0 : UCharNameChoice choice = U_UNICODE_CHAR_NAME;
529 : char *buf;
530 0 : int buf_len = 128;
531 0 : UErrorCode status = U_ZERO_ERROR;
532 :
533 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "u|b", &str, &str_len, &extended) == FAILURE) {
534 0 : return;
535 : }
536 :
537 0 : if (str_len == 0) {
538 0 : RETURN_FALSE;
539 : }
540 :
541 0 : if (extended) {
542 0 : choice = U_EXTENDED_CHAR_NAME;
543 : }
544 :
545 0 : U16_NEXT(str, offset, str_len, ch);
546 :
547 0 : buf = emalloc(buf_len);
548 0 : buf_len = u_charName(ch, choice, buf, buf_len, &status);
549 0 : if (buf_len == 0) {
550 0 : efree(buf);
551 0 : RETURN_FALSE;
552 0 : } else if (status == U_BUFFER_OVERFLOW_ERROR) {
553 0 : status = U_ZERO_ERROR;
554 0 : buf = erealloc(buf, buf_len+1);
555 0 : buf_len = u_charName(ch, choice, buf, buf_len+1, &status);
556 : }
557 :
558 0 : RETURN_ASCII_STRINGL(buf, buf_len, ZSTR_AUTOFREE);
559 : }
560 : /* }}} */
561 :
562 : /* }}} */
563 :
564 : /* {{{ Other property functions */
565 :
566 : /* {{{ proto bool char_has_binary_property(string text, int property) U
567 : Determines if all the characters in the string have the specified binary property */
568 : PHP_FUNCTION(char_has_binary_property)
569 0 : {
570 0 : UChar *str = NULL;
571 : int str_len;
572 : long prop;
573 : UProperty uprop;
574 0 : int offset = 0;
575 0 : zend_bool result = 1;
576 : UChar32 ch;
577 :
578 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ul", &str, &str_len, &prop) == FAILURE) {
579 0 : return;
580 : }
581 :
582 0 : if (str_len == 0) {
583 0 : RETURN_FALSE;
584 : }
585 :
586 0 : uprop = (UProperty)prop;
587 :
588 0 : while (offset < str_len && result) {
589 0 : U16_NEXT(str, offset, str_len, ch);
590 0 : result = u_hasBinaryProperty(ch, uprop);
591 : }
592 :
593 0 : RETURN_BOOL(result);
594 : }
595 : /* }}} */
596 :
597 : /* {{{ proto int char_get_property_value(char c, int property) U
598 : Get the value of a property associated with the character */
599 : PHP_FUNCTION(char_get_property_value)
600 0 : {
601 : UChar *str;
602 : int str_len;
603 0 : int offset = 0;
604 : UChar32 ch;
605 : long prop;
606 :
607 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ul", &str, &str_len, &prop) == FAILURE) {
608 0 : return;
609 : }
610 :
611 0 : if (str_len == 0) {
612 0 : RETURN_FALSE;
613 : }
614 :
615 0 : U16_NEXT(str, offset, str_len, ch);
616 :
617 0 : if (prop >= UCHAR_BINARY_START && prop < UCHAR_BINARY_LIMIT) {
618 0 : RETURN_BOOL((zend_bool)u_getIntPropertyValue(ch, (UProperty)prop));
619 : } else {
620 0 : RETURN_LONG(u_getIntPropertyValue(ch, (UProperty)prop));
621 : }
622 : }
623 : /* }}} */
624 :
625 : /* {{{ proto int char_get_property_min_value(int property) U
626 : Get the minimum possible value for the specified property */
627 : PHP_FUNCTION(char_get_property_min_value)
628 0 : {
629 : long prop;
630 :
631 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &prop) == FAILURE) {
632 0 : return;
633 : }
634 :
635 0 : RETURN_LONG(u_getIntPropertyMinValue((UProperty)prop));
636 : }
637 : /* }}} */
638 :
639 : /* {{{ proto int char_get_property_max_value(int property) U
640 : Get the maximum possible value associated with the specified property */
641 : PHP_FUNCTION(char_get_property_max_value)
642 0 : {
643 : long prop;
644 :
645 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &prop) == FAILURE) {
646 0 : return;
647 : }
648 :
649 0 : RETURN_LONG(u_getIntPropertyMaxValue((UProperty)prop));
650 : }
651 : /* }}} */
652 :
653 : /* {{{ proto string char_get_property_name(int property) U
654 : Get the Unicode name for the given property */
655 : PHP_FUNCTION(char_get_property_name)
656 0 : {
657 : long prop;
658 0 : long name_choice = U_LONG_PROPERTY_NAME;
659 : const char *name;
660 :
661 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &prop, &name_choice) == FAILURE) {
662 0 : return;
663 : }
664 :
665 0 : if (name_choice < 0) {
666 0 : name_choice = U_LONG_PROPERTY_NAME;
667 : }
668 :
669 0 : name = u_getPropertyName((UProperty) prop, (UPropertyNameChoice) name_choice);
670 0 : if (name) {
671 0 : RETURN_ASCII_STRING((char *)name, ZSTR_DUPLICATE);
672 : } else {
673 0 : RETURN_FALSE;
674 : }
675 : }
676 : /* }}} */
677 :
678 : /* {{{ proto int char_get_property_from_name(string property_name) U
679 : Get the property ID for the given property name */
680 : PHP_FUNCTION(char_get_property_from_name)
681 0 : {
682 : void *name;
683 : int name_len;
684 : char *buf;
685 : zend_uchar name_type;
686 : UProperty prop;
687 :
688 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &name_type) == FAILURE) {
689 0 : return;
690 : }
691 :
692 0 : if (name_type == IS_UNICODE) {
693 0 : buf = zend_unicode_to_ascii(name, name_len TSRMLS_CC);
694 0 : if (buf == NULL) {
695 0 : php_error(E_WARNING, "Property name has to consist only of ASCII characters");
696 0 : RETURN_FALSE;
697 : }
698 : } else {
699 0 : buf = (char *) name;
700 : }
701 :
702 0 : prop = u_getPropertyEnum(buf);
703 0 : if (name_type == IS_UNICODE) {
704 0 : efree(buf);
705 : }
706 :
707 0 : RETURN_LONG(prop);
708 : }
709 : /* }}} */
710 :
711 : /* {{{ proto string char_get_property_value_name(int property, int value[, int name_choice]) U
712 : Get the Unicode name for the givenproperty value */
713 : PHP_FUNCTION(char_get_property_value_name)
714 0 : {
715 : long prop;
716 : long value;
717 0 : long name_choice = U_LONG_PROPERTY_NAME;
718 : const char *name;
719 :
720 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll|l", &prop, &value, &name_choice) == FAILURE) {
721 0 : return;
722 : }
723 :
724 0 : if (name_choice < 0) {
725 0 : name_choice = U_LONG_PROPERTY_NAME;
726 : }
727 :
728 0 : name = u_getPropertyValueName((UProperty) prop, (int32_t) value, (UPropertyNameChoice) name_choice);
729 0 : if (name) {
730 0 : RETURN_ASCII_STRING((char *)name, ZSTR_DUPLICATE);
731 : } else {
732 0 : RETURN_FALSE;
733 : }
734 : }
735 : /* }}} */
736 :
737 : /* {{{ proto int char_get_property_value_from_name(int property, string value_name) U
738 : Get the value ID for the given property value name */
739 : PHP_FUNCTION(char_get_property_value_from_name)
740 0 : {
741 : long prop;
742 : void *name;
743 : int name_len;
744 : zend_uchar name_type;
745 : char *buf;
746 : long value;
747 :
748 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lt", &prop, &name, &name_len, &name_type) == FAILURE) {
749 0 : return;
750 : }
751 :
752 0 : if (name_type == IS_UNICODE) {
753 0 : buf = zend_unicode_to_ascii(name, name_len TSRMLS_CC);
754 0 : if (buf == NULL) {
755 0 : php_error(E_WARNING, "Property value name has to consist only of ASCII characters");
756 0 : RETURN_FALSE;
757 : }
758 : } else {
759 0 : buf = (char *) name;
760 : }
761 :
762 0 : value = u_getPropertyValueEnum((UProperty)prop, buf);
763 0 : if (name_type == IS_UNICODE) {
764 0 : efree(buf);
765 : }
766 :
767 0 : RETURN_LONG(value);
768 : }
769 : /* }}} */
770 :
771 : /* }}} */
772 :
773 : /* {{{ Enumerator functions */
774 :
775 : static UBool php_enum_char_names(const void *context,
776 : UChar32 code,
777 : UCharNameChoice nameChoice,
778 : const char *name,
779 : int32_t length)
780 0 : {
781 0 : char_enum_context_t *ctx = (char_enum_context_t *)context;
782 0 : zval *retval_ptr = NULL;
783 : int status;
784 0 : UBool result = FALSE;
785 : TSRMLS_FETCH_FROM_CTX(ctx->thread_ctx);
786 :
787 0 : convert_to_long_ex(ctx->args[0]);
788 0 : convert_to_unicode_ex(ctx->args[1]);
789 0 : convert_to_boolean_ex(ctx->args[2]);
790 :
791 0 : ZVAL_LONG(*ctx->args[0], code);
792 0 : if (Z_USTRVAL_PP(ctx->args[1])) {
793 0 : efree(Z_USTRVAL_PP(ctx->args[1]));
794 : }
795 0 : ZVAL_ASCII_STRINGL(*ctx->args[1], (char *)name, length, ZSTR_DUPLICATE);
796 0 : ZVAL_BOOL(*ctx->args[2], nameChoice == U_EXTENDED_CHAR_NAME);
797 :
798 0 : ctx->fci.retval_ptr_ptr = &retval_ptr;
799 :
800 0 : status = zend_call_function(&ctx->fci, &ctx->fci_cache TSRMLS_CC);
801 :
802 0 : if (status == SUCCESS && retval_ptr && !EG(exception)) {
803 0 : convert_to_boolean(retval_ptr);
804 0 : result = (UBool)Z_BVAL_P(retval_ptr);
805 : } else {
806 0 : if (!EG(exception)) {
807 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Enumeration callback encountered an error");
808 : }
809 0 : result = FALSE;
810 : }
811 0 : if (retval_ptr) {
812 0 : zval_ptr_dtor(&retval_ptr);
813 : }
814 0 : return result;
815 : }
816 :
817 : static UBool php_enum_char_type_range(const void *context,
818 : UChar32 start,
819 : UChar32 limit,
820 : UCharCategory type)
821 0 : {
822 0 : char_enum_context_t *ctx = (char_enum_context_t *)context;
823 0 : zval *retval_ptr = NULL;
824 : int status;
825 0 : UBool result = FALSE;
826 : TSRMLS_FETCH_FROM_CTX(ctx->thread_ctx);
827 :
828 0 : convert_to_long_ex(ctx->args[0]);
829 0 : convert_to_long_ex(ctx->args[1]);
830 0 : convert_to_long_ex(ctx->args[2]);
831 :
832 0 : ZVAL_LONG(*ctx->args[0], start);
833 0 : ZVAL_LONG(*ctx->args[1], limit);
834 0 : ZVAL_LONG(*ctx->args[2], type);
835 :
836 0 : ctx->fci.retval_ptr_ptr = &retval_ptr;
837 :
838 0 : status = zend_call_function(&ctx->fci, &ctx->fci_cache TSRMLS_CC);
839 :
840 0 : if (status == SUCCESS && retval_ptr && !EG(exception)) {
841 0 : convert_to_boolean(retval_ptr);
842 0 : result = (UBool)Z_BVAL_P(retval_ptr);
843 : } else {
844 0 : if (!EG(exception)) {
845 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Enumeration callback encountered an error");
846 : }
847 0 : result = FALSE;
848 : }
849 0 : if (retval_ptr) {
850 0 : zval_ptr_dtor(&retval_ptr);
851 : }
852 0 : return result;
853 : }
854 :
855 : /* {{{ proto bool char_enum_names(callback Callback, int start, int limit[, bool extended = false]) U
856 : Enumerate all assigned Unicode characters between the start and limit code points (start inclusive, limit exclusive) and call a function for each, passing the code point value and the character name. */
857 : PHP_FUNCTION(char_enum_names)
858 0 : {
859 : zval *callback;
860 : long start, limit;
861 0 : zend_bool extended = FALSE;
862 : zval *zcode, *zname, *zextended;
863 : char_enum_context_t ectx;
864 0 : UCharNameChoice choice = U_UNICODE_CHAR_NAME;
865 0 : UErrorCode status = U_ZERO_ERROR;
866 :
867 0 : if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "zll|b", &callback, &start, &limit, &extended)) {
868 0 : return;
869 : }
870 :
871 0 : if (!zend_is_callable(callback, 0, NULL TSRMLS_CC)) {
872 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid enumeration callback");
873 0 : return;
874 : }
875 :
876 0 : if (extended) {
877 0 : choice = U_EXTENDED_CHAR_NAME;
878 : }
879 :
880 : /* Do all the heavy lifing once, instead of in the callback */
881 0 : MAKE_STD_ZVAL(zcode);
882 0 : MAKE_STD_ZVAL(zextended);
883 0 : MAKE_STD_ZVAL(zname);
884 :
885 0 : ZVAL_LONG(zcode, 0);
886 0 : ZVAL_BOOL(zextended, 0);
887 0 : Z_TYPE_P(zname) = IS_UNICODE;
888 0 : Z_USTRVAL_P(zname) = NULL;
889 :
890 0 : memset(&ectx, 0, sizeof(char_enum_context_t));
891 0 : ectx.fci.size = sizeof(ectx.fci);
892 0 : ectx.fci.function_table = EG(function_table);
893 0 : ectx.fci.function_name = callback;
894 0 : ectx.fci.no_separation = 1;
895 0 : ectx.fci_cache = empty_fcall_info_cache;
896 0 : ectx.args[0] = &zcode;
897 0 : ectx.args[1] = &zname;
898 0 : ectx.args[2] = &zextended;
899 0 : ectx.fci.param_count = 3;
900 0 : ectx.fci.params = ectx.args;
901 : TSRMLS_SET_CTX(ectx.thread_ctx);
902 :
903 0 : u_enumCharNames(start, limit, (UEnumCharNamesFn *)php_enum_char_names,
904 : (void *)&ectx, choice, &status);
905 :
906 0 : zval_ptr_dtor(&zcode);
907 0 : zval_ptr_dtor(&zextended);
908 0 : zval_ptr_dtor(&zname);
909 :
910 0 : if (U_SUCCESS(status)) {
911 0 : RETURN_TRUE;
912 : } else {
913 0 : RETURN_FALSE;
914 : }
915 : }
916 : /* }}} */
917 :
918 : /* {{{ proto bool char_enum_types(callback Callback) U
919 : Enumerate all code points with their general categories invoking a callback for each category */
920 : PHP_FUNCTION(char_enum_types)
921 0 : {
922 : zval *callback;
923 : zval *zstart, *zlimit, *ztype;
924 : char_enum_context_t ectx;
925 :
926 0 : if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "z", &callback)) {
927 0 : return;
928 : }
929 :
930 0 : if (!zend_is_callable(callback, 0, NULL TSRMLS_CC)) {
931 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid enumeration callback");
932 0 : return;
933 : }
934 :
935 : /* Do all the heavy lifing once, instead of in the callback */
936 0 : MAKE_STD_ZVAL(zstart);
937 0 : MAKE_STD_ZVAL(zlimit);
938 0 : MAKE_STD_ZVAL(ztype);
939 :
940 0 : ZVAL_LONG(zstart, 0);
941 0 : ZVAL_LONG(zlimit, 0);
942 0 : ZVAL_LONG(ztype, 0);
943 :
944 0 : memset(&ectx, 0, sizeof(char_enum_context_t));
945 0 : ectx.fci.size = sizeof(ectx.fci);
946 0 : ectx.fci.function_table = EG(function_table);
947 0 : ectx.fci.function_name = callback;
948 0 : ectx.fci.no_separation = 1;
949 0 : ectx.fci_cache = empty_fcall_info_cache;
950 0 : ectx.args[0] = &zstart;
951 0 : ectx.args[1] = &zlimit;
952 0 : ectx.args[2] = &ztype;
953 0 : ectx.fci.param_count = 3;
954 0 : ectx.fci.params = ectx.args;
955 : TSRMLS_SET_CTX(ectx.thread_ctx);
956 :
957 0 : u_enumCharTypes((UCharEnumTypeRange *)php_enum_char_type_range, (void *)&ectx);
958 :
959 0 : zval_ptr_dtor(&zstart);
960 0 : zval_ptr_dtor(&zlimit);
961 0 : zval_ptr_dtor(&ztype);
962 :
963 0 : RETURN_TRUE;
964 : }
965 : /* }}} */
966 :
967 :
968 : /* }}} */
969 :
970 : /*
971 : * Local variables:
972 : * tab-width: 4
973 : * c-basic-offset: 4
974 : * End:
975 : * vim600: noet sw=4 ts=4 fdm=marker
976 : * vim<600: noet sw=4 ts=4
977 : */
|