uchar.c 16 KB

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