xref: /PHP-7.3/ext/intl/msgformat/msgformat.c (revision 701437a9)
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 <unicode/ustring.h>
22 #include <unicode/umsg.h>
23 
24 #include "php_intl.h"
25 #include "msgformat_class.h"
26 #include "msgformat_data.h"
27 #include "intl_convert.h"
28 
29 /* {{{ */
msgfmt_ctor(INTERNAL_FUNCTION_PARAMETERS,zend_bool is_constructor)30 static int msgfmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor)
31 {
32 	const char* locale;
33 	char*       pattern;
34 	size_t      locale_len = 0, pattern_len = 0;
35 	UChar*      spattern     = NULL;
36 	int         spattern_len = 0;
37 	zval*       object;
38 	MessageFormatter_object* mfo;
39 	int zpp_flags = is_constructor ? ZEND_PARSE_PARAMS_THROW : 0;
40 	intl_error_reset( NULL );
41 
42 	object = return_value;
43 	/* Parse parameters. */
44 	if( zend_parse_parameters_ex( zpp_flags, ZEND_NUM_ARGS(), "ss",
45 		&locale, &locale_len, &pattern, &pattern_len ) == FAILURE )
46 	{
47 		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
48 			"msgfmt_create: unable to parse input parameters", 0 );
49 		return FAILURE;
50 	}
51 
52 	INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len);
53 	MSG_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK;
54 
55 	/* Convert pattern (if specified) to UTF-16. */
56 	if(pattern && pattern_len) {
57 		intl_convert_utf8_to_utf16(&spattern, &spattern_len, pattern, pattern_len, &INTL_DATA_ERROR_CODE(mfo));
58 		INTL_CTOR_CHECK_STATUS(mfo, "msgfmt_create: error converting pattern to UTF-16");
59 	} else {
60 		spattern_len = 0;
61 		spattern = NULL;
62 	}
63 
64 	if(locale_len == 0) {
65 		locale = intl_locale_get_default();
66 	}
67 
68 #ifdef MSG_FORMAT_QUOTE_APOS
69 	if(msgformat_fix_quotes(&spattern, &spattern_len, &INTL_DATA_ERROR_CODE(mfo)) != SUCCESS) {
70 		INTL_CTOR_CHECK_STATUS(mfo, "msgfmt_create: error converting pattern to quote-friendly format");
71 	}
72 #endif
73 
74 	if ((mfo)->mf_data.orig_format) {
75 		msgformat_data_free(&mfo->mf_data);
76 	}
77 
78 	(mfo)->mf_data.orig_format = estrndup(pattern, pattern_len);
79 	(mfo)->mf_data.orig_format_len = pattern_len;
80 
81 	/* Create an ICU message formatter. */
82 	MSG_FORMAT_OBJECT(mfo) = umsg_open(spattern, spattern_len, locale, NULL, &INTL_DATA_ERROR_CODE(mfo));
83 
84 	if(spattern) {
85 		efree(spattern);
86 	}
87 
88 	INTL_CTOR_CHECK_STATUS(mfo, "msgfmt_create: message formatter creation failed");
89 	return SUCCESS;
90 }
91 /* }}} */
92 
93 /* {{{ proto MessageFormatter MesssageFormatter::create( string $locale, string $pattern )
94  * Create formatter. }}} */
95 /* {{{ proto MessageFormatter msgfmt_create( string $locale, string $pattern )
96  * Create formatter.
97  */
PHP_FUNCTION(msgfmt_create)98 PHP_FUNCTION( msgfmt_create )
99 {
100 	object_init_ex( return_value, MessageFormatter_ce_ptr );
101 	if (msgfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0) == FAILURE) {
102 		zval_ptr_dtor(return_value);
103 		RETURN_NULL();
104 	}
105 }
106 /* }}} */
107 
108 /* {{{ proto MessageFormatter::__construct( string $locale, string $pattern )
109  * MessageFormatter object constructor.
110  */
PHP_METHOD(MessageFormatter,__construct)111 PHP_METHOD( MessageFormatter, __construct )
112 {
113 	zend_error_handling error_handling;
114 
115 	zend_replace_error_handling(EH_THROW, IntlException_ce_ptr, &error_handling);
116 	return_value = getThis();
117 	if (msgfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1) == FAILURE) {
118 		if (!EG(exception)) {
119 			zend_throw_exception(IntlException_ce_ptr, "Constructor failed", 0);
120 		}
121 	}
122 	zend_restore_error_handling(&error_handling);
123 }
124 /* }}} */
125 
126 /* {{{ proto int MessageFormatter::getErrorCode()
127  * Get formatter's last error code. }}} */
128 /* {{{ proto int msgfmt_get_error_code( MessageFormatter $nf )
129  * Get formatter's last error code.
130  */
PHP_FUNCTION(msgfmt_get_error_code)131 PHP_FUNCTION( msgfmt_get_error_code )
132 {
133 	zval*                    object  = NULL;
134 	MessageFormatter_object*  mfo     = NULL;
135 
136 	/* Parse parameters. */
137 	if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O",
138 		&object, MessageFormatter_ce_ptr ) == FAILURE )
139 	{
140 		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
141 			"msgfmt_get_error_code: unable to parse input params", 0 );
142 
143 		RETURN_FALSE;
144 	}
145 
146 	mfo = Z_INTL_MESSAGEFORMATTER_P( object );
147 
148 	/* Return formatter's last error code. */
149 	RETURN_LONG( INTL_DATA_ERROR_CODE(mfo) );
150 }
151 /* }}} */
152 
153 /* {{{ proto string MessageFormatter::getErrorMessage( )
154  * Get text description for formatter's last error code. }}} */
155 /* {{{ proto string msgfmt_get_error_message( MessageFormatter $coll )
156  * Get text description for formatter's last error code.
157  */
PHP_FUNCTION(msgfmt_get_error_message)158 PHP_FUNCTION( msgfmt_get_error_message )
159 {
160 	zend_string*             message = NULL;
161 	zval*                    object  = NULL;
162 	MessageFormatter_object*  mfo     = NULL;
163 
164 	/* Parse parameters. */
165 	if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O",
166 		&object, MessageFormatter_ce_ptr ) == FAILURE )
167 	{
168 		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
169 			"msgfmt_get_error_message: unable to parse input params", 0 );
170 
171 		RETURN_FALSE;
172 	}
173 
174 	mfo = Z_INTL_MESSAGEFORMATTER_P( object );
175 
176 	/* Return last error message. */
177 	message = intl_error_get_message( &mfo->mf_data.error );
178 	RETURN_STR(message);
179 }
180 /* }}} */
181 
182 /*
183  * Local variables:
184  * tab-width: 4
185  * c-basic-offset: 4
186  * End:
187  * vim600: noet sw=4 ts=4 fdm=marker
188  * vim<600: noet sw=4 ts=4
189  */
190