formatter_attr.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  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: Stanislav Malyshev <stas@zend.com> |
  14. +----------------------------------------------------------------------+
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #include "php_intl.h"
  20. #include "formatter_class.h"
  21. #include "formatter_attr.h"
  22. #include "intl_convert.h"
  23. #include <unicode/ustring.h>
  24. /* {{{ proto mixed NumberFormatter::getAttribute( int $attr )
  25. * Get formatter attribute value. }}} */
  26. /* {{{ proto mixed numfmt_get_attribute( NumberFormatter $nf, int $attr )
  27. * Get formatter attribute value.
  28. */
  29. PHP_FUNCTION( numfmt_get_attribute )
  30. {
  31. zend_long attribute, value;
  32. FORMATTER_METHOD_INIT_VARS;
  33. /* Parse parameters. */
  34. if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ol",
  35. &object, NumberFormatter_ce_ptr, &attribute ) == FAILURE )
  36. {
  37. intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
  38. "numfmt_get_attribute: unable to parse input params", 0 );
  39. RETURN_FALSE;
  40. }
  41. /* Fetch the object. */
  42. FORMATTER_METHOD_FETCH_OBJECT;
  43. switch(attribute) {
  44. case UNUM_PARSE_INT_ONLY:
  45. case UNUM_GROUPING_USED:
  46. case UNUM_DECIMAL_ALWAYS_SHOWN:
  47. case UNUM_MAX_INTEGER_DIGITS:
  48. case UNUM_MIN_INTEGER_DIGITS:
  49. case UNUM_INTEGER_DIGITS:
  50. case UNUM_MAX_FRACTION_DIGITS:
  51. case UNUM_MIN_FRACTION_DIGITS:
  52. case UNUM_FRACTION_DIGITS:
  53. case UNUM_MULTIPLIER:
  54. case UNUM_GROUPING_SIZE:
  55. case UNUM_ROUNDING_MODE:
  56. case UNUM_FORMAT_WIDTH:
  57. case UNUM_PADDING_POSITION:
  58. case UNUM_SECONDARY_GROUPING_SIZE:
  59. case UNUM_SIGNIFICANT_DIGITS_USED:
  60. case UNUM_MIN_SIGNIFICANT_DIGITS:
  61. case UNUM_MAX_SIGNIFICANT_DIGITS:
  62. case UNUM_LENIENT_PARSE:
  63. value = unum_getAttribute(FORMATTER_OBJECT(nfo), attribute);
  64. if(value == -1) {
  65. INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR;
  66. } else {
  67. RETVAL_LONG(value);
  68. }
  69. break;
  70. case UNUM_ROUNDING_INCREMENT:
  71. {
  72. double value_double = unum_getDoubleAttribute(FORMATTER_OBJECT(nfo), attribute);
  73. if(value_double == -1) {
  74. INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR;
  75. } else {
  76. RETVAL_DOUBLE(value_double);
  77. }
  78. }
  79. break;
  80. default:
  81. INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR;
  82. break;
  83. }
  84. INTL_METHOD_CHECK_STATUS( nfo, "Error getting attribute value" );
  85. }
  86. /* }}} */
  87. /* {{{ proto string NumberFormatter::getTextAttribute( int $attr )
  88. * Get formatter attribute value. }}} */
  89. /* {{{ proto string numfmt_get_text_attribute( NumberFormatter $nf, int $attr )
  90. * Get formatter attribute value.
  91. */
  92. PHP_FUNCTION( numfmt_get_text_attribute )
  93. {
  94. zend_long attribute;
  95. UChar value_buf[64];
  96. int32_t value_buf_size = USIZE( value_buf );
  97. UChar* value = value_buf;
  98. int32_t length = 0;
  99. FORMATTER_METHOD_INIT_VARS;
  100. /* Parse parameters. */
  101. if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ol",
  102. &object, NumberFormatter_ce_ptr, &attribute ) == FAILURE )
  103. {
  104. intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
  105. "numfmt_get_text_attribute: unable to parse input params", 0 );
  106. RETURN_FALSE;
  107. }
  108. /* Fetch the object. */
  109. FORMATTER_METHOD_FETCH_OBJECT;
  110. length = unum_getTextAttribute( FORMATTER_OBJECT(nfo), attribute, value, value_buf_size, &INTL_DATA_ERROR_CODE(nfo) );
  111. if(INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR && length >= value_buf_size) {
  112. ++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */
  113. INTL_DATA_ERROR_CODE(nfo) = U_ZERO_ERROR;
  114. value = eumalloc(length);
  115. length = unum_getTextAttribute( FORMATTER_OBJECT(nfo), attribute, value, length, &INTL_DATA_ERROR_CODE(nfo) );
  116. if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) {
  117. efree(value);
  118. value = value_buf;
  119. }
  120. }
  121. INTL_METHOD_CHECK_STATUS( nfo, "Error getting attribute value" );
  122. INTL_METHOD_RETVAL_UTF8( nfo, value, length, ( value != value_buf ) );
  123. }
  124. /* }}} */
  125. /* {{{ proto bool NumberFormatter::setAttribute( int $attr, mixed $value )
  126. * Get formatter attribute value. }}} */
  127. /* {{{ proto bool numfmt_set_attribute( NumberFormatter $nf, int $attr, mixed $value )
  128. * Get formatter attribute value.
  129. */
  130. PHP_FUNCTION( numfmt_set_attribute )
  131. {
  132. zend_long attribute;
  133. zval *value;
  134. FORMATTER_METHOD_INIT_VARS;
  135. /* Parse parameters. */
  136. if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Olz",
  137. &object, NumberFormatter_ce_ptr, &attribute, &value ) == FAILURE)
  138. {
  139. intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
  140. "numfmt_set_attribute: unable to parse input params", 0 );
  141. RETURN_FALSE;
  142. }
  143. /* Fetch the object. */
  144. FORMATTER_METHOD_FETCH_OBJECT;
  145. switch(attribute) {
  146. case UNUM_PARSE_INT_ONLY:
  147. case UNUM_GROUPING_USED:
  148. case UNUM_DECIMAL_ALWAYS_SHOWN:
  149. case UNUM_MAX_INTEGER_DIGITS:
  150. case UNUM_MIN_INTEGER_DIGITS:
  151. case UNUM_INTEGER_DIGITS:
  152. case UNUM_MAX_FRACTION_DIGITS:
  153. case UNUM_MIN_FRACTION_DIGITS:
  154. case UNUM_FRACTION_DIGITS:
  155. case UNUM_MULTIPLIER:
  156. case UNUM_GROUPING_SIZE:
  157. case UNUM_ROUNDING_MODE:
  158. case UNUM_FORMAT_WIDTH:
  159. case UNUM_PADDING_POSITION:
  160. case UNUM_SECONDARY_GROUPING_SIZE:
  161. case UNUM_SIGNIFICANT_DIGITS_USED:
  162. case UNUM_MIN_SIGNIFICANT_DIGITS:
  163. case UNUM_MAX_SIGNIFICANT_DIGITS:
  164. case UNUM_LENIENT_PARSE:
  165. unum_setAttribute(FORMATTER_OBJECT(nfo), attribute, zval_get_long(value));
  166. break;
  167. case UNUM_ROUNDING_INCREMENT:
  168. unum_setDoubleAttribute(FORMATTER_OBJECT(nfo), attribute, zval_get_double(value));
  169. break;
  170. default:
  171. INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR;
  172. break;
  173. }
  174. INTL_METHOD_CHECK_STATUS( nfo, "Error setting attribute value" );
  175. RETURN_TRUE;
  176. }
  177. /* }}} */
  178. /* {{{ proto bool NumberFormatter::setTextAttribute( int $attr, string $value )
  179. * Get formatter attribute value. }}} */
  180. /* {{{ proto bool numfmt_set_text_attribute( NumberFormatter $nf, int $attr, string $value )
  181. * Get formatter attribute value.
  182. */
  183. PHP_FUNCTION( numfmt_set_text_attribute )
  184. {
  185. int32_t slength = 0;
  186. UChar *svalue = NULL;
  187. zend_long attribute;
  188. char *value;
  189. size_t len;
  190. FORMATTER_METHOD_INIT_VARS;
  191. /* Parse parameters. */
  192. if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ols",
  193. &object, NumberFormatter_ce_ptr, &attribute, &value, &len ) == FAILURE)
  194. {
  195. intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
  196. "numfmt_set_text_attribute: unable to parse input params", 0 );
  197. RETURN_FALSE;
  198. }
  199. /* Fetch the object. */
  200. FORMATTER_METHOD_FETCH_OBJECT;
  201. /* Convert given attribute value to UTF-16. */
  202. intl_convert_utf8_to_utf16(&svalue, &slength, value, len, &INTL_DATA_ERROR_CODE(nfo));
  203. INTL_METHOD_CHECK_STATUS( nfo, "Error converting attribute value to UTF-16" );
  204. /* Actually set new attribute value. */
  205. unum_setTextAttribute(FORMATTER_OBJECT(nfo), attribute, svalue, slength, &INTL_DATA_ERROR_CODE(nfo));
  206. if (svalue) {
  207. efree(svalue);
  208. }
  209. INTL_METHOD_CHECK_STATUS( nfo, "Error setting text attribute" );
  210. RETURN_TRUE;
  211. }
  212. /* }}} */
  213. /* {{{ proto string NumberFormatter::getSymbol( int $attr )
  214. * Get formatter symbol value. }}} */
  215. /* {{{ proto string numfmt_get_symbol( NumberFormatter $nf, int $attr )
  216. * Get formatter symbol value.
  217. */
  218. PHP_FUNCTION( numfmt_get_symbol )
  219. {
  220. zend_long symbol;
  221. UChar value_buf[4];
  222. UChar *value = value_buf;
  223. uint32_t length = USIZE(value_buf);
  224. FORMATTER_METHOD_INIT_VARS;
  225. /* Parse parameters. */
  226. if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ol",
  227. &object, NumberFormatter_ce_ptr, &symbol ) == FAILURE )
  228. {
  229. intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
  230. "numfmt_get_symbol: unable to parse input params", 0 );
  231. RETURN_FALSE;
  232. }
  233. if(symbol >= UNUM_FORMAT_SYMBOL_COUNT || symbol < 0) {
  234. intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "numfmt_get_symbol: invalid symbol value", 0 );
  235. RETURN_FALSE;
  236. }
  237. /* Fetch the object. */
  238. FORMATTER_METHOD_FETCH_OBJECT;
  239. length = unum_getSymbol(FORMATTER_OBJECT(nfo), symbol, value_buf, length, &INTL_DATA_ERROR_CODE(nfo));
  240. if(INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR && length >= USIZE( value_buf )) {
  241. ++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */
  242. INTL_DATA_ERROR_CODE(nfo) = U_ZERO_ERROR;
  243. value = eumalloc(length);
  244. length = unum_getSymbol(FORMATTER_OBJECT(nfo), symbol, value, length, &INTL_DATA_ERROR_CODE(nfo));
  245. if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) {
  246. efree(value);
  247. value = value_buf;
  248. }
  249. }
  250. INTL_METHOD_CHECK_STATUS( nfo, "Error getting symbol value" );
  251. INTL_METHOD_RETVAL_UTF8( nfo, value, length, ( value_buf != value ) );
  252. }
  253. /* }}} */
  254. /* {{{ proto bool NumberFormatter::setSymbol( int $attr, string $symbol )
  255. * Set formatter symbol value. }}} */
  256. /* {{{ proto bool numfmt_set_symbol( NumberFormatter $nf, int $attr, string $symbol )
  257. * Set formatter symbol value.
  258. */
  259. PHP_FUNCTION( numfmt_set_symbol )
  260. {
  261. zend_long symbol;
  262. char* value = NULL;
  263. size_t value_len = 0;
  264. UChar* svalue = 0;
  265. int32_t slength = 0;
  266. FORMATTER_METHOD_INIT_VARS;
  267. /* Parse parameters. */
  268. if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ols",
  269. &object, NumberFormatter_ce_ptr, &symbol, &value, &value_len ) == FAILURE )
  270. {
  271. intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
  272. "numfmt_set_symbol: unable to parse input params", 0 );
  273. RETURN_FALSE;
  274. }
  275. if (symbol >= UNUM_FORMAT_SYMBOL_COUNT || symbol < 0) {
  276. intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "numfmt_set_symbol: invalid symbol value", 0 );
  277. RETURN_FALSE;
  278. }
  279. /* Fetch the object. */
  280. FORMATTER_METHOD_FETCH_OBJECT;
  281. /* Convert given symbol to UTF-16. */
  282. intl_convert_utf8_to_utf16(&svalue, &slength, value, value_len, &INTL_DATA_ERROR_CODE(nfo));
  283. INTL_METHOD_CHECK_STATUS( nfo, "Error converting symbol value to UTF-16" );
  284. /* Actually set the symbol. */
  285. unum_setSymbol(FORMATTER_OBJECT(nfo), symbol, svalue, slength, &INTL_DATA_ERROR_CODE(nfo));
  286. if (svalue) {
  287. efree(svalue);
  288. }
  289. INTL_METHOD_CHECK_STATUS( nfo, "Error setting symbol value" );
  290. RETURN_TRUE;
  291. }
  292. /* }}} */
  293. /* {{{ proto string NumberFormatter::getPattern( )
  294. * Get formatter pattern. }}} */
  295. /* {{{ proto string numfmt_get_pattern( NumberFormatter $nf )
  296. * Get formatter pattern.
  297. */
  298. PHP_FUNCTION( numfmt_get_pattern )
  299. {
  300. UChar value_buf[64];
  301. uint32_t length = USIZE( value_buf );
  302. UChar* value = value_buf;
  303. FORMATTER_METHOD_INIT_VARS;
  304. /* Parse parameters. */
  305. if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O",
  306. &object, NumberFormatter_ce_ptr ) == FAILURE )
  307. {
  308. intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
  309. "numfmt_get_pattern: unable to parse input params", 0 );
  310. RETURN_FALSE;
  311. }
  312. /* Fetch the object. */
  313. FORMATTER_METHOD_FETCH_OBJECT;
  314. length = unum_toPattern(FORMATTER_OBJECT(nfo), 0, value, length, &INTL_DATA_ERROR_CODE(nfo));
  315. if(INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR && length >= USIZE( value_buf )) {
  316. ++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */
  317. INTL_DATA_ERROR_CODE(nfo) = U_ZERO_ERROR;
  318. value = eumalloc(length);
  319. length = unum_toPattern( FORMATTER_OBJECT(nfo), 0, value, length, &INTL_DATA_ERROR_CODE(nfo) );
  320. if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) {
  321. efree(value);
  322. value = value_buf;
  323. }
  324. }
  325. INTL_METHOD_CHECK_STATUS( nfo, "Error getting formatter pattern" );
  326. INTL_METHOD_RETVAL_UTF8( nfo, value, length, ( value != value_buf ) );
  327. }
  328. /* }}} */
  329. /* {{{ proto bool NumberFormatter::setPattern( string $pattern )
  330. * Set formatter pattern. }}} */
  331. /* {{{ proto bool numfmt_set_pattern( NumberFormatter $nf, string $pattern )
  332. * Set formatter pattern.
  333. */
  334. PHP_FUNCTION( numfmt_set_pattern )
  335. {
  336. char* value = NULL;
  337. size_t value_len = 0;
  338. int32_t slength = 0;
  339. UChar* svalue = NULL;
  340. FORMATTER_METHOD_INIT_VARS;
  341. /* Parse parameters. */
  342. if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os",
  343. &object, NumberFormatter_ce_ptr, &value, &value_len ) == FAILURE )
  344. {
  345. intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
  346. "numfmt_set_pattern: unable to parse input params", 0 );
  347. RETURN_FALSE;
  348. }
  349. FORMATTER_METHOD_FETCH_OBJECT;
  350. /* Convert given pattern to UTF-16. */
  351. intl_convert_utf8_to_utf16(&svalue, &slength, value, value_len, &INTL_DATA_ERROR_CODE(nfo));
  352. INTL_METHOD_CHECK_STATUS( nfo, "Error converting pattern to UTF-16" );
  353. /* TODO: add parse error information */
  354. unum_applyPattern(FORMATTER_OBJECT(nfo), 0, svalue, slength, NULL, &INTL_DATA_ERROR_CODE(nfo));
  355. if (svalue) {
  356. efree(svalue);
  357. }
  358. INTL_METHOD_CHECK_STATUS( nfo, "Error setting pattern value" );
  359. RETURN_TRUE;
  360. }
  361. /* }}} */
  362. /* {{{ proto string NumberFormatter::getLocale([int type])
  363. * Get formatter locale. }}} */
  364. /* {{{ proto string numfmt_get_locale( NumberFormatter $nf[, int type] )
  365. * Get formatter locale.
  366. */
  367. PHP_FUNCTION( numfmt_get_locale )
  368. {
  369. zend_long type = ULOC_ACTUAL_LOCALE;
  370. char* loc;
  371. FORMATTER_METHOD_INIT_VARS;
  372. /* Parse parameters. */
  373. if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O|l",
  374. &object, NumberFormatter_ce_ptr, &type ) == FAILURE )
  375. {
  376. intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
  377. "numfmt_get_locale: unable to parse input params", 0 );
  378. RETURN_FALSE;
  379. }
  380. /* Fetch the object. */
  381. FORMATTER_METHOD_FETCH_OBJECT;
  382. loc = (char *)unum_getLocaleByType(FORMATTER_OBJECT(nfo), type, &INTL_DATA_ERROR_CODE(nfo));
  383. INTL_METHOD_CHECK_STATUS( nfo, "Error getting locale" );
  384. RETURN_STRING(loc);
  385. }
  386. /* }}} */
  387. /*
  388. * Local variables:
  389. * tab-width: 4
  390. * c-basic-offset: 4
  391. * End:
  392. * vim600: noet sw=4 ts=4 fdm=marker
  393. * vim<600: noet sw=4 ts=4
  394. */