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