1 /*
2 +----------------------------------------------------------------------+
3 | This source file is subject to version 3.01 of the PHP license, |
4 | that is bundled with this package in the file LICENSE, and is |
5 | available through the world-wide-web at the following url: |
6 | https://www.php.net/license/3_01.txt |
7 | If you did not receive a copy of the PHP license and are unable to |
8 | obtain it through the world-wide-web, please send a note to |
9 | license@php.net so we can mail you a copy immediately. |
10 +----------------------------------------------------------------------+
11 | Authors: Stanislav Malyshev <stas@zend.com> |
12 +----------------------------------------------------------------------+
13 */
14
15 #ifdef HAVE_CONFIG_H
16 #include <config.h>
17 #endif
18
19 #include <unicode/ustring.h>
20 #include <unicode/uloc.h>
21
22 #include "php_intl.h"
23 #include "formatter_class.h"
24 #include "intl_convert.h"
25
26 /* {{{ */
numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS,zend_error_handling * error_handling,bool * error_handling_replaced)27 static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_handling, bool *error_handling_replaced)
28 {
29 char* locale;
30 char* pattern = NULL;
31 size_t locale_len = 0, pattern_len = 0;
32 zend_long style;
33 UChar* spattern = NULL;
34 int32_t spattern_len = 0;
35 FORMATTER_METHOD_INIT_VARS;
36
37 ZEND_PARSE_PARAMETERS_START(2, 3)
38 Z_PARAM_STRING(locale, locale_len)
39 Z_PARAM_LONG(style)
40 Z_PARAM_OPTIONAL
41 Z_PARAM_STRING_OR_NULL(pattern, pattern_len)
42 ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
43
44 if (error_handling != NULL) {
45 zend_replace_error_handling(EH_THROW, IntlException_ce_ptr, error_handling);
46 *error_handling_replaced = 1;
47 }
48
49 INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len);
50 object = return_value;
51 FORMATTER_METHOD_FETCH_OBJECT_NO_CHECK;
52 if (FORMATTER_OBJECT(nfo)) {
53 zend_throw_error(NULL, "NumberFormatter object is already constructed");
54 return FAILURE;
55 }
56
57 /* Convert pattern (if specified) to UTF-16. */
58 if(pattern && pattern_len) {
59 intl_convert_utf8_to_utf16(&spattern, &spattern_len, pattern, pattern_len, &INTL_DATA_ERROR_CODE(nfo));
60 INTL_CTOR_CHECK_STATUS(nfo, "numfmt_create: error converting pattern to UTF-16");
61 }
62
63 if(locale_len == 0) {
64 locale = (char *)intl_locale_get_default();
65 }
66
67 if (strlen(uloc_getISO3Language(locale)) == 0) {
68 zend_argument_value_error(1, "\"%s\" is invalid", locale);
69 return FAILURE;
70 }
71
72 /* Create an ICU number formatter. */
73 FORMATTER_OBJECT(nfo) = unum_open(style, spattern, spattern_len, locale, NULL, &INTL_DATA_ERROR_CODE(nfo));
74
75 if(spattern) {
76 efree(spattern);
77 }
78
79 INTL_CTOR_CHECK_STATUS(nfo, "numfmt_create: number formatter creation failed");
80 return SUCCESS;
81 }
82 /* }}} */
83
84 /* {{{ Create number formatter. */
PHP_FUNCTION(numfmt_create)85 PHP_FUNCTION( numfmt_create )
86 {
87 object_init_ex( return_value, NumberFormatter_ce_ptr );
88 if (numfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL, NULL) == FAILURE) {
89 zval_ptr_dtor(return_value);
90 RETURN_NULL();
91 }
92 }
93 /* }}} */
94
95 /* {{{ NumberFormatter object constructor. */
PHP_METHOD(NumberFormatter,__construct)96 PHP_METHOD( NumberFormatter, __construct )
97 {
98 zend_error_handling error_handling;
99 bool error_handling_replaced = 0;
100
101 return_value = ZEND_THIS;
102 if (numfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, &error_handling, &error_handling_replaced) == FAILURE) {
103 if (!EG(exception)) {
104 zend_throw_exception(IntlException_ce_ptr, "Constructor failed", 0);
105 }
106 }
107 if (error_handling_replaced) {
108 zend_restore_error_handling(&error_handling);
109 }
110 }
111 /* }}} */
112
113 /* {{{ Get formatter's last error code. */
PHP_FUNCTION(numfmt_get_error_code)114 PHP_FUNCTION( numfmt_get_error_code )
115 {
116 FORMATTER_METHOD_INIT_VARS
117
118 /* Parse parameters. */
119 if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O",
120 &object, NumberFormatter_ce_ptr ) == FAILURE )
121 {
122 RETURN_THROWS();
123 }
124
125 nfo = Z_INTL_NUMBERFORMATTER_P(object);
126
127 /* Return formatter's last error code. */
128 RETURN_LONG( INTL_DATA_ERROR_CODE(nfo) );
129 }
130 /* }}} */
131
132 /* {{{ Get text description for formatter's last error code. */
PHP_FUNCTION(numfmt_get_error_message)133 PHP_FUNCTION( numfmt_get_error_message )
134 {
135 zend_string *message = NULL;
136 FORMATTER_METHOD_INIT_VARS
137
138 /* Parse parameters. */
139 if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O",
140 &object, NumberFormatter_ce_ptr ) == FAILURE )
141 {
142 RETURN_THROWS();
143 }
144
145 nfo = Z_INTL_NUMBERFORMATTER_P(object);
146
147 /* Return last error message. */
148 message = intl_error_get_message( INTL_DATA_ERROR_P(nfo) );
149 RETURN_STR(message);
150 }
151 /* }}} */
152