xref: /php-src/ext/intl/formatter/formatter_main.c (revision 683e7878)
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 	const 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 	/* Parse parameters. */
38 	if( zend_parse_parameters( ZEND_NUM_ARGS(), "sl|s!",
39 		&locale, &locale_len, &style, &pattern, &pattern_len ) == FAILURE )
40 	{
41 		return FAILURE;
42 	}
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 = 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