2 +----------------------------------------------------------------------+
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: Hans-Peter Oeri (University of St.Gallen) <hp@oeri.ch> |
14 +----------------------------------------------------------------------+
18 #include <unicode/ures.h>
19 #include <unicode/uenum.h>
22 #include <Zend/zend_exceptions.h>
23 #include <Zend/zend_interfaces.h>
27 #include "intl_data.h"
29 #include "resourcebundle/resourcebundle.h"
30 #include "resourcebundle/resourcebundle_iterator.h"
31 #include "resourcebundle/resourcebundle_class.h"
33 zend_class_entry
*ResourceBundle_ce_ptr
= NULL
;
35 static zend_object_handlers ResourceBundle_object_handlers
;
37 /* {{{ ResourceBundle_object_dtor */
38 static void ResourceBundle_object_destroy( void *object
, zend_object_handle handle TSRMLS_DC
)
40 ResourceBundle_object
*rb
= (ResourceBundle_object
*) object
;
42 // only free local errors
43 intl_error_reset( INTL_DATA_ERROR_P(rb
) TSRMLS_CC
);
49 ures_close( rb
->child
);
52 zend_object_std_dtor( object TSRMLS_CC
);
57 /* {{{ ResourceBundle_object_create */
58 static zend_object_value
ResourceBundle_object_create( zend_class_entry
*ce TSRMLS_DC
)
60 zend_object_value retval
;
61 ResourceBundle_object
*rb
;
63 rb
= ecalloc( 1, sizeof(ResourceBundle_object
) );
65 zend_object_std_init( (zend_object
*) rb
, ce TSRMLS_CC
);
66 object_properties_init((zend_object
*) rb
, ce
);
68 intl_error_init( INTL_DATA_ERROR_P(rb
) TSRMLS_CC
);
72 retval
.handlers
= &ResourceBundle_object_handlers
;
73 retval
.handle
= zend_objects_store_put( rb
, ResourceBundle_object_destroy
, NULL
, NULL TSRMLS_CC
);
79 /* {{{ ResourceBundle_ctor */
80 static void resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS
)
83 int bundlename_len
= 0;
86 zend_bool fallback
= 1;
90 zval
*object
= return_value
;
91 ResourceBundle_object
*rb
= (ResourceBundle_object
*) zend_object_store_get_object( object TSRMLS_CC
);
93 intl_error_reset( NULL TSRMLS_CC
);
95 if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC
, "s!s!|b",
96 &locale
, &locale_len
, &bundlename
, &bundlename_len
, &fallback
) == FAILURE
)
98 intl_error_set( NULL
, U_ILLEGAL_ARGUMENT_ERROR
,
99 "resourcebundle_ctor: unable to parse input parameters", 0 TSRMLS_CC
);
100 zval_dtor( return_value
);
104 INTL_CHECK_LOCALE_LEN_OBJ(locale_len
, return_value
);
106 if (locale
== NULL
) {
107 locale
= INTL_G(default_locale
);
111 rb
->me
= ures_open(bundlename
, locale
, &INTL_DATA_ERROR_CODE(rb
));
113 rb
->me
= ures_openDirect(bundlename
, locale
, &INTL_DATA_ERROR_CODE(rb
));
116 INTL_CTOR_CHECK_STATUS(rb
, "resourcebundle_ctor: Cannot load libICU resource bundle");
118 if (!fallback
&& (INTL_DATA_ERROR_CODE(rb
) == U_USING_FALLBACK_WARNING
||
119 INTL_DATA_ERROR_CODE(rb
) == U_USING_DEFAULT_WARNING
)) {
120 intl_errors_set_code(NULL
, INTL_DATA_ERROR_CODE(rb
) TSRMLS_CC
);
121 spprintf(&pbuf
, 0, "resourcebundle_ctor: Cannot load libICU resource "
122 "'%s' without fallback from %s to %s",
123 bundlename
? bundlename
: "(default data)", locale
,
124 ures_getLocaleByType(
125 rb
->me
, ULOC_ACTUAL_LOCALE
, &INTL_DATA_ERROR_CODE(rb
)));
126 intl_errors_set_custom_msg(INTL_DATA_ERROR_P(rb
), pbuf
, 1 TSRMLS_CC
);
128 zval_dtor(return_value
);
134 /* {{{ arginfo_resourcebundle__construct */
135 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle___construct
, 0, 0, 2 )
136 ZEND_ARG_INFO( 0, locale
)
137 ZEND_ARG_INFO( 0, bundlename
)
138 ZEND_ARG_INFO( 0, fallback
)
142 /* {{{ proto void ResourceBundle::__construct( string $locale [, string $bundlename [, bool $fallback = true ]] )
143 * ResourceBundle object constructor
145 PHP_METHOD( ResourceBundle
, __construct
)
147 return_value
= getThis();
148 resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU
);
152 /* {{{ proto ResourceBundle ResourceBundle::create( string $locale [, string $bundlename [, bool $fallback = true ]] )
153 proto ResourceBundle resourcebundle_create( string $locale [, string $bundlename [, bool $fallback = true ]] )
155 PHP_FUNCTION( resourcebundle_create
)
157 object_init_ex( return_value
, ResourceBundle_ce_ptr
);
158 resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU
);
162 /* {{{ resourcebundle_array_fetch */
163 static void resourcebundle_array_fetch(zval
*object
, zval
*offset
, zval
*return_value
, int fallback TSRMLS_DC
)
168 zend_bool is_numeric
= 0;
170 ResourceBundle_object
*rb
;
172 intl_error_reset( NULL TSRMLS_CC
);
173 RESOURCEBUNDLE_METHOD_FETCH_OBJECT
;
175 if(Z_TYPE_P(offset
) == IS_LONG
) {
177 meindex
= Z_LVAL_P(offset
);
178 rb
->child
= ures_getByIndex( rb
->me
, meindex
, rb
->child
, &INTL_DATA_ERROR_CODE(rb
) );
179 } else if(Z_TYPE_P(offset
) == IS_STRING
) {
180 mekey
= Z_STRVAL_P(offset
);
181 mekeylen
= Z_STRLEN_P(offset
);
182 rb
->child
= ures_getByKey(rb
->me
, mekey
, rb
->child
, &INTL_DATA_ERROR_CODE(rb
) );
184 intl_errors_set(INTL_DATA_ERROR_P(rb
), U_ILLEGAL_ARGUMENT_ERROR
,
185 "resourcebundle_get: index should be integer or string", 0 TSRMLS_CC
);
189 intl_error_set_code( NULL
, INTL_DATA_ERROR_CODE(rb
) TSRMLS_CC
);
190 if (U_FAILURE(INTL_DATA_ERROR_CODE(rb
))) {
192 spprintf( &pbuf
, 0, "Cannot load resource element %d", meindex
);
194 spprintf( &pbuf
, 0, "Cannot load resource element '%s'", mekey
);
196 intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb
), pbuf
, 1 TSRMLS_CC
);
201 if (!fallback
&& (INTL_DATA_ERROR_CODE(rb
) == U_USING_FALLBACK_WARNING
|| INTL_DATA_ERROR_CODE(rb
) == U_USING_DEFAULT_WARNING
)) {
203 const char * locale
= ures_getLocaleByType( rb
->me
, ULOC_ACTUAL_LOCALE
, &icuerror
);
205 spprintf( &pbuf
, 0, "Cannot load element %d without fallback from to %s", meindex
, locale
);
207 spprintf( &pbuf
, 0, "Cannot load element '%s' without fallback from to %s", mekey
, locale
);
209 intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb
), pbuf
, 1 TSRMLS_CC
);
214 resourcebundle_extract_value( return_value
, rb TSRMLS_CC
);
218 /* {{{ resourcebundle_array_get */
219 zval
*resourcebundle_array_get(zval
*object
, zval
*offset
, int type TSRMLS_DC
)
224 php_error( E_ERROR
, "Cannot apply [] to ResourceBundle object" );
226 MAKE_STD_ZVAL(retval
);
228 resourcebundle_array_fetch(object
, offset
, retval
, 1 TSRMLS_CC
);
234 /* {{{ arginfo_resourcebundle_get */
235 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_get
, 0, 0, 1 )
236 ZEND_ARG_INFO( 0, index
)
237 ZEND_ARG_INFO( 0, fallback
)
241 /* {{{ proto mixed ResourceBundle::get( integer|string $resindex [, bool $fallback = true ] )
242 * proto mixed resourcebundle_get( ResourceBundle $rb, integer|string $resindex [, bool $fallback = true ] )
243 * Get resource identified by numerical index or key name.
245 PHP_FUNCTION( resourcebundle_get
)
247 zend_bool fallback
= 1;
251 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, getThis(), "Oz|b", &object
, ResourceBundle_ce_ptr
, &offset
, &fallback
) == FAILURE
) {
252 intl_error_set(NULL
, U_ILLEGAL_ARGUMENT_ERROR
,
253 "resourcebundle_get: unable to parse input params", 0 TSRMLS_CC
);
257 resourcebundle_array_fetch(object
, offset
, return_value
, fallback TSRMLS_CC
);
261 /* {{{ resourcebundle_array_count */
262 int resourcebundle_array_count(zval
*object
, long *count TSRMLS_DC
)
264 ResourceBundle_object
*rb
;
265 RESOURCEBUNDLE_METHOD_FETCH_OBJECT_NO_CHECK
;
267 if (rb
->me
== NULL
) {
268 intl_errors_set(&rb
->error
, U_ILLEGAL_ARGUMENT_ERROR
,
269 "Found unconstructed ResourceBundle", 0 TSRMLS_CC
);
273 *count
= ures_getSize( rb
->me
);
279 /* {{{ arginfo_resourcebundle_count */
280 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_count
, 0, 0, 0 )
284 /* {{{ proto int ResourceBundle::count()
285 * proto int resourcebundle_count( ResourceBundle $bundle )
286 * Get resources count
288 PHP_FUNCTION( resourcebundle_count
)
291 RESOURCEBUNDLE_METHOD_INIT_VARS
;
293 if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC
, getThis(), "O", &object
, ResourceBundle_ce_ptr
) == FAILURE
) {
294 intl_error_set(NULL
, U_ILLEGAL_ARGUMENT_ERROR
,
295 "resourcebundle_count: unable to parse input params", 0 TSRMLS_CC
);
299 RESOURCEBUNDLE_METHOD_FETCH_OBJECT
;
301 len
= ures_getSize( rb
->me
);
305 /* {{{ arginfo_resourcebundle_getlocales */
306 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_getlocales
, 0, 0, 1 )
307 ZEND_ARG_INFO( 0, bundlename
)
311 /* {{{ proto array ResourceBundle::getLocales( string $bundlename )
312 * proto array resourcebundle_locales( string $bundlename )
313 * Get available locales from ResourceBundle name
315 PHP_FUNCTION( resourcebundle_locales
)
318 int bundlename_len
= 0;
321 UEnumeration
*icuenum
;
322 UErrorCode icuerror
= U_ZERO_ERROR
;
324 intl_errors_reset( NULL TSRMLS_CC
);
326 if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &bundlename
, &bundlename_len
) == FAILURE
)
328 intl_error_set(NULL
, U_ILLEGAL_ARGUMENT_ERROR
,
329 "resourcebundle_locales: unable to parse input params", 0 TSRMLS_CC
);
333 if(bundlename_len
== 0) {
334 // fetch default locales list
338 icuenum
= ures_openAvailableLocales( bundlename
, &icuerror
);
339 INTL_CHECK_STATUS(icuerror
, "Cannot fetch locales list");
341 uenum_reset( icuenum
, &icuerror
);
342 INTL_CHECK_STATUS(icuerror
, "Cannot iterate locales list");
344 array_init( return_value
);
345 while ((entry
= uenum_next( icuenum
, &entry_len
, &icuerror
))) {
346 add_next_index_stringl( return_value
, (char *) entry
, entry_len
, 1 );
348 uenum_close( icuenum
);
352 /* {{{ arginfo_resourcebundle_get_error_code */
353 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_get_error_code
, 0, 0, 0 )
357 /* {{{ proto string ResourceBundle::getErrorCode( )
358 * proto string resourcebundle_get_error_code( ResourceBundle $bundle )
359 * Get text description for ResourceBundle's last error code.
361 PHP_FUNCTION( resourcebundle_get_error_code
)
363 RESOURCEBUNDLE_METHOD_INIT_VARS
;
365 if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC
, getThis(), "O",
366 &object
, ResourceBundle_ce_ptr
) == FAILURE
)
368 intl_error_set( NULL
, U_ILLEGAL_ARGUMENT_ERROR
,
369 "resourcebundle_get_error_code: unable to parse input params", 0 TSRMLS_CC
);
373 rb
= (ResourceBundle_object
*) zend_object_store_get_object( object TSRMLS_CC
);
375 RETURN_LONG(INTL_DATA_ERROR_CODE(rb
));
379 /* {{{ arginfo_resourcebundle_get_error_message */
380 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_get_error_message
, 0, 0, 0 )
384 /* {{{ proto string ResourceBundle::getErrorMessage( )
385 * proto string resourcebundle_get_error_message( ResourceBundle $bundle )
386 * Get text description for ResourceBundle's last error.
388 PHP_FUNCTION( resourcebundle_get_error_message
)
390 char* message
= NULL
;
391 RESOURCEBUNDLE_METHOD_INIT_VARS
;
393 if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC
, getThis(), "O",
394 &object
, ResourceBundle_ce_ptr
) == FAILURE
)
396 intl_error_set( NULL
, U_ILLEGAL_ARGUMENT_ERROR
,
397 "resourcebundle_get_error_message: unable to parse input params", 0 TSRMLS_CC
);
401 rb
= (ResourceBundle_object
*) zend_object_store_get_object( object TSRMLS_CC
);
402 message
= (char *)intl_error_get_message(INTL_DATA_ERROR_P(rb
) TSRMLS_CC
);
403 RETURN_STRING(message
, 0);
407 /* {{{ ResourceBundle_class_functions
408 * Every 'ResourceBundle' class method has an entry in this table
410 static zend_function_entry ResourceBundle_class_functions
[] = {
411 PHP_ME( ResourceBundle
, __construct
, arginfo_resourcebundle___construct
, ZEND_ACC_PUBLIC
|ZEND_ACC_CTOR
)
412 ZEND_NAMED_ME( create
, ZEND_FN( resourcebundle_create
), arginfo_resourcebundle___construct
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
413 ZEND_NAMED_ME( get
, ZEND_FN(resourcebundle_get
), arginfo_resourcebundle_get
, ZEND_ACC_PUBLIC
)
414 ZEND_NAMED_ME( count
, ZEND_FN(resourcebundle_count
), arginfo_resourcebundle_count
, ZEND_ACC_PUBLIC
)
415 ZEND_NAMED_ME( getLocales
, ZEND_FN(resourcebundle_locales
), arginfo_resourcebundle_getlocales
, ZEND_ACC_PUBLIC
| ZEND_ACC_STATIC
)
416 ZEND_NAMED_ME( getErrorCode
, ZEND_FN(resourcebundle_get_error_code
), arginfo_resourcebundle_get_error_code
, ZEND_ACC_PUBLIC
)
417 ZEND_NAMED_ME( getErrorMessage
, ZEND_FN(resourcebundle_get_error_message
), arginfo_resourcebundle_get_error_message
, ZEND_ACC_PUBLIC
)
422 /* {{{ resourcebundle_register_class
423 * Initialize 'ResourceBundle' class
425 void resourcebundle_register_class( TSRMLS_D
)
429 INIT_CLASS_ENTRY( ce
, "ResourceBundle", ResourceBundle_class_functions
);
431 ce
.create_object
= ResourceBundle_object_create
;
432 ce
.get_iterator
= resourcebundle_get_iterator
;
434 ResourceBundle_ce_ptr
= zend_register_internal_class( &ce TSRMLS_CC
);
436 if( !ResourceBundle_ce_ptr
)
438 zend_error(E_ERROR
, "Failed to register ResourceBundle class");
442 ResourceBundle_object_handlers
= std_object_handlers
;
443 ResourceBundle_object_handlers
.clone_obj
= NULL
; /* ICU ResourceBundle has no clone implementation */
444 ResourceBundle_object_handlers
.read_dimension
= resourcebundle_array_get
;
445 ResourceBundle_object_handlers
.count_elements
= resourcebundle_array_count
;
447 zend_class_implements(ResourceBundle_ce_ptr TSRMLS_CC
, 1, zend_ce_traversable
);
456 * vim600: noet sw=4 ts=4 fdm=marker
457 * vim<600: noet sw=4 ts=4