root/ext/intl/resourcebundle/resourcebundle_class.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ResourceBundle_object_destroy
  2. ResourceBundle_object_create
  3. resourcebundle_ctor
  4. ZEND_BEGIN_ARG_INFO_EX
  5. PHP_FUNCTION
  6. resourcebundle_array_fetch
  7. resourcebundle_array_get
  8. ZEND_BEGIN_ARG_INFO_EX
  9. resourcebundle_array_count
  10. ZEND_BEGIN_ARG_INFO_EX
  11. ZEND_BEGIN_ARG_INFO_EX
  12. ZEND_BEGIN_ARG_INFO_EX
  13. ZEND_BEGIN_ARG_INFO_EX
  14. resourcebundle_register_class

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 5                                                        |
   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    +----------------------------------------------------------------------+
  15  */
  16 
  17 #include <stdlib.h>
  18 #include <unicode/ures.h>
  19 #include <unicode/uenum.h>
  20 
  21 #include <zend.h>
  22 #include <Zend/zend_exceptions.h>
  23 #include <Zend/zend_interfaces.h>
  24 #include <php.h>
  25 
  26 #include "php_intl.h"
  27 #include "intl_data.h"
  28 
  29 #include "resourcebundle/resourcebundle.h"
  30 #include "resourcebundle/resourcebundle_iterator.h"
  31 #include "resourcebundle/resourcebundle_class.h"
  32 
  33 zend_class_entry *ResourceBundle_ce_ptr = NULL;
  34 
  35 static zend_object_handlers ResourceBundle_object_handlers;
  36 
  37 /* {{{ ResourceBundle_object_dtor */
  38 static void ResourceBundle_object_destroy( void *object, zend_object_handle handle TSRMLS_DC )
  39 {
  40         ResourceBundle_object *rb = (ResourceBundle_object *) object;
  41 
  42         // only free local errors
  43         intl_error_reset( INTL_DATA_ERROR_P(rb) TSRMLS_CC );
  44 
  45         if (rb->me) {
  46                 ures_close( rb->me );
  47         }
  48         if (rb->child) {
  49                 ures_close( rb->child );
  50         }
  51 
  52         zend_object_std_dtor( object TSRMLS_CC );
  53         efree(object);
  54 }
  55 /* }}} */
  56 
  57 /* {{{ ResourceBundle_object_create */
  58 static zend_object_value ResourceBundle_object_create( zend_class_entry *ce TSRMLS_DC )
  59 {
  60         zend_object_value     retval;
  61         ResourceBundle_object *rb;
  62 
  63         rb = ecalloc( 1, sizeof(ResourceBundle_object) );
  64 
  65         zend_object_std_init( (zend_object *) rb, ce TSRMLS_CC );
  66         object_properties_init((zend_object *) rb, ce);
  67 
  68         intl_error_init( INTL_DATA_ERROR_P(rb) TSRMLS_CC );
  69         rb->me = NULL;
  70         rb->child = NULL;
  71 
  72         retval.handlers = &ResourceBundle_object_handlers;
  73         retval.handle = zend_objects_store_put( rb, ResourceBundle_object_destroy, NULL, NULL TSRMLS_CC );
  74 
  75         return retval;
  76 }
  77 /* }}} */
  78 
  79 /* {{{ ResourceBundle_ctor */
  80 static void resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS) 
  81 {
  82         const char      *bundlename;
  83         int                     bundlename_len = 0;
  84         const char      *locale;
  85         int                     locale_len = 0;
  86         zend_bool       fallback = 1;
  87 
  88         zval                  *object = return_value;
  89         ResourceBundle_object *rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC);
  90 
  91         intl_error_reset( NULL TSRMLS_CC );
  92 
  93         if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s!s!|b", 
  94                 &locale, &locale_len, &bundlename, &bundlename_len, &fallback ) == FAILURE )
  95         {
  96                 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
  97                         "resourcebundle_ctor: unable to parse input parameters", 0 TSRMLS_CC );
  98                 zval_dtor( return_value );
  99                 RETURN_NULL();
 100         }
 101 
 102         INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value);
 103         
 104         if (locale == NULL) {
 105                 locale = intl_locale_get_default(TSRMLS_C);
 106         }
 107 
 108         if (fallback) {
 109                 rb->me = ures_open(bundlename, locale, &INTL_DATA_ERROR_CODE(rb));
 110         } else {
 111                 rb->me = ures_openDirect(bundlename, locale, &INTL_DATA_ERROR_CODE(rb));
 112         }
 113 
 114         INTL_CTOR_CHECK_STATUS(rb, "resourcebundle_ctor: Cannot load libICU resource bundle");
 115 
 116         if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING ||
 117                         INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) {
 118                 char *pbuf;
 119                 intl_errors_set_code(NULL, INTL_DATA_ERROR_CODE(rb) TSRMLS_CC);
 120                 spprintf(&pbuf, 0, "resourcebundle_ctor: Cannot load libICU resource "
 121                                 "'%s' without fallback from %s to %s",
 122                                 bundlename ? bundlename : "(default data)", locale,
 123                                 ures_getLocaleByType(
 124                                         rb->me, ULOC_ACTUAL_LOCALE, &INTL_DATA_ERROR_CODE(rb)));
 125                 intl_errors_set_custom_msg(INTL_DATA_ERROR_P(rb), pbuf, 1 TSRMLS_CC);
 126                 efree(pbuf);
 127                 zval_dtor(return_value);
 128                 RETURN_NULL();
 129         }
 130 }
 131 /* }}} */
 132 
 133 /* {{{ arginfo_resourcebundle__construct */
 134 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle___construct, 0, 0, 2 )
 135         ZEND_ARG_INFO( 0, locale )
 136         ZEND_ARG_INFO( 0, bundlename )
 137         ZEND_ARG_INFO( 0, fallback )
 138 ZEND_END_ARG_INFO()
 139 /* }}} */
 140 
 141 /* {{{ proto void ResourceBundle::__construct( string $locale [, string $bundlename [, bool $fallback = true ]] )
 142  * ResourceBundle object constructor
 143  */
 144 PHP_METHOD( ResourceBundle, __construct )
 145 {
 146         return_value = getThis();
 147         resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
 148 }
 149 /* }}} */
 150 
 151 /* {{{ proto ResourceBundle ResourceBundle::create( string $locale [, string $bundlename [, bool $fallback = true ]] )
 152 proto ResourceBundle resourcebundle_create( string $locale [, string $bundlename [, bool $fallback = true ]] )
 153 */
 154 PHP_FUNCTION( resourcebundle_create ) 
 155 {
 156         object_init_ex( return_value, ResourceBundle_ce_ptr );
 157         resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
 158 }
 159 /* }}} */
 160 
 161 /* {{{ resourcebundle_array_fetch */
 162 static void resourcebundle_array_fetch(zval *object, zval *offset, zval *return_value, int fallback TSRMLS_DC) 
 163 {
 164         int32_t     meindex = 0;
 165         char *      mekey = NULL;
 166     zend_bool    is_numeric = 0;
 167         char         *pbuf;
 168         ResourceBundle_object *rb;
 169 
 170         intl_error_reset( NULL TSRMLS_CC );     
 171         RESOURCEBUNDLE_METHOD_FETCH_OBJECT;
 172 
 173         if(Z_TYPE_P(offset) == IS_LONG) {
 174                 is_numeric = 1;
 175                 meindex = Z_LVAL_P(offset);
 176                 rb->child = ures_getByIndex( rb->me, meindex, rb->child, &INTL_DATA_ERROR_CODE(rb) );
 177         } else if(Z_TYPE_P(offset) == IS_STRING) {
 178                 mekey = Z_STRVAL_P(offset);
 179                 rb->child = ures_getByKey(rb->me, mekey, rb->child, &INTL_DATA_ERROR_CODE(rb) );
 180         } else {
 181                 intl_errors_set(INTL_DATA_ERROR_P(rb), U_ILLEGAL_ARGUMENT_ERROR,        
 182                         "resourcebundle_get: index should be integer or string", 0 TSRMLS_CC);
 183                 RETURN_NULL();
 184         }
 185 
 186         intl_error_set_code( NULL, INTL_DATA_ERROR_CODE(rb) TSRMLS_CC );        
 187         if (U_FAILURE(INTL_DATA_ERROR_CODE(rb))) {
 188                 if (is_numeric) {
 189                         spprintf( &pbuf, 0, "Cannot load resource element %d", meindex );
 190                 } else {
 191                         spprintf( &pbuf, 0, "Cannot load resource element '%s'", mekey );
 192                 }
 193                 intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 TSRMLS_CC );
 194                 efree(pbuf);
 195                 RETURN_NULL();
 196         }
 197 
 198         if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING || INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) {
 199                 UErrorCode icuerror;
 200                 const char * locale = ures_getLocaleByType( rb->me, ULOC_ACTUAL_LOCALE, &icuerror );
 201                 if (is_numeric) {
 202                         spprintf( &pbuf, 0, "Cannot load element %d without fallback from to %s", meindex, locale );
 203                 } else {
 204                         spprintf( &pbuf, 0, "Cannot load element '%s' without fallback from to %s", mekey, locale );
 205                 }
 206                 intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 TSRMLS_CC );
 207                 efree(pbuf);
 208                 RETURN_NULL();
 209         }
 210 
 211         resourcebundle_extract_value( return_value, rb TSRMLS_CC );
 212 }
 213 /* }}} */
 214 
 215 /* {{{ resourcebundle_array_get */
 216 zval *resourcebundle_array_get(zval *object, zval *offset, int type TSRMLS_DC) 
 217 {
 218         zval *retval;
 219 
 220         if(offset == NULL) {
 221                 php_error( E_ERROR, "Cannot apply [] to ResourceBundle object" );
 222         }
 223         MAKE_STD_ZVAL(retval);
 224 
 225         resourcebundle_array_fetch(object, offset, retval, 1 TSRMLS_CC);
 226         Z_DELREF_P(retval);
 227         return retval;
 228 }
 229 /* }}} */
 230 
 231 /* {{{ arginfo_resourcebundle_get */
 232 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_get, 0, 0, 1 )
 233         ZEND_ARG_INFO( 0, index )
 234         ZEND_ARG_INFO( 0, fallback )
 235 ZEND_END_ARG_INFO()
 236 /* }}} */
 237 
 238 /* {{{ proto mixed ResourceBundle::get( integer|string $resindex [, bool $fallback = true ] )
 239  * proto mixed resourcebundle_get( ResourceBundle $rb, integer|string $resindex [, bool $fallback = true ] )
 240  * Get resource identified by numerical index or key name.
 241  */
 242 PHP_FUNCTION( resourcebundle_get )
 243 {
 244         zend_bool   fallback = 1;
 245         zval *          offset;
 246         zval *      object;
 247 
 248         if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz|b",  &object, ResourceBundle_ce_ptr, &offset, &fallback ) == FAILURE) {
 249                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,  
 250                         "resourcebundle_get: unable to parse input params", 0 TSRMLS_CC);
 251                 RETURN_FALSE;
 252         }
 253 
 254         resourcebundle_array_fetch(object, offset, return_value, fallback TSRMLS_CC);
 255 }
 256 /* }}} */
 257 
 258 /* {{{ resourcebundle_array_count */
 259 int resourcebundle_array_count(zval *object, long *count TSRMLS_DC) 
 260 {
 261         ResourceBundle_object *rb;
 262         RESOURCEBUNDLE_METHOD_FETCH_OBJECT_NO_CHECK;
 263 
 264         if (rb->me == NULL) {
 265                 intl_errors_set(&rb->error, U_ILLEGAL_ARGUMENT_ERROR,
 266                                 "Found unconstructed ResourceBundle", 0 TSRMLS_CC);
 267                 return 0;
 268         }
 269 
 270         *count = ures_getSize( rb->me );
 271 
 272         return SUCCESS;
 273 }
 274 /* }}} */
 275 
 276 /* {{{ arginfo_resourcebundle_count */
 277 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_count, 0, 0, 0 )
 278 ZEND_END_ARG_INFO()
 279 /* }}} */
 280 
 281 /* {{{ proto int ResourceBundle::count()
 282  * proto int resourcebundle_count( ResourceBundle $bundle )
 283  * Get resources count
 284  */
 285 PHP_FUNCTION( resourcebundle_count )
 286 {
 287         int32_t                len;
 288         RESOURCEBUNDLE_METHOD_INIT_VARS;
 289 
 290         if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, ResourceBundle_ce_ptr ) == FAILURE ) {
 291                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,  
 292                         "resourcebundle_count: unable to parse input params", 0 TSRMLS_CC);
 293                 RETURN_FALSE;
 294         }
 295 
 296         RESOURCEBUNDLE_METHOD_FETCH_OBJECT;
 297 
 298         len = ures_getSize( rb->me );
 299         RETURN_LONG( len );
 300 }
 301 
 302 /* {{{ arginfo_resourcebundle_getlocales */
 303 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_getlocales, 0, 0, 1 )
 304         ZEND_ARG_INFO( 0, bundlename )
 305 ZEND_END_ARG_INFO()
 306 /* }}} */
 307 
 308 /* {{{ proto array ResourceBundle::getLocales( string $bundlename )
 309  * proto array resourcebundle_locales( string $bundlename )
 310  * Get available locales from ResourceBundle name
 311  */
 312 PHP_FUNCTION( resourcebundle_locales )
 313 {
 314         char * bundlename;
 315         int    bundlename_len = 0;
 316         const char * entry;
 317         int entry_len;
 318         UEnumeration *icuenum;
 319         UErrorCode   icuerror = U_ZERO_ERROR;
 320 
 321         intl_errors_reset( NULL TSRMLS_CC );
 322 
 323         if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &bundlename, &bundlename_len ) == FAILURE )
 324         {
 325                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,  
 326                         "resourcebundle_locales: unable to parse input params", 0 TSRMLS_CC);
 327                 RETURN_FALSE;
 328         }
 329 
 330         if(bundlename_len == 0) {
 331                 // fetch default locales list
 332                 bundlename = NULL;
 333         }
 334 
 335         icuenum = ures_openAvailableLocales( bundlename, &icuerror );
 336         INTL_CHECK_STATUS(icuerror, "Cannot fetch locales list");               
 337 
 338         uenum_reset( icuenum, &icuerror );
 339         INTL_CHECK_STATUS(icuerror, "Cannot iterate locales list");             
 340 
 341         array_init( return_value );
 342         while ((entry = uenum_next( icuenum, &entry_len, &icuerror ))) {
 343                 add_next_index_stringl( return_value, (char *) entry, entry_len, 1 );
 344         }
 345         uenum_close( icuenum );
 346 }
 347 /* }}} */
 348 
 349 /* {{{ arginfo_resourcebundle_get_error_code */
 350 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_get_error_code, 0, 0, 0 )
 351 ZEND_END_ARG_INFO()
 352 /* }}} */
 353 
 354 /* {{{ proto string ResourceBundle::getErrorCode( )
 355  * proto string resourcebundle_get_error_code( ResourceBundle $bundle )
 356  * Get text description for ResourceBundle's last error code.
 357  */
 358 PHP_FUNCTION( resourcebundle_get_error_code )
 359 {
 360         RESOURCEBUNDLE_METHOD_INIT_VARS;
 361 
 362         if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
 363                 &object, ResourceBundle_ce_ptr ) == FAILURE )
 364         {
 365                 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
 366                         "resourcebundle_get_error_code: unable to parse input params", 0 TSRMLS_CC );
 367                 RETURN_FALSE;
 368         }
 369 
 370         rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC );
 371 
 372         RETURN_LONG(INTL_DATA_ERROR_CODE(rb));
 373 }
 374 /* }}} */
 375 
 376 /* {{{ arginfo_resourcebundle_get_error_message */
 377 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_get_error_message, 0, 0, 0 )
 378 ZEND_END_ARG_INFO()
 379 /* }}} */
 380 
 381 /* {{{ proto string ResourceBundle::getErrorMessage( )
 382  * proto string resourcebundle_get_error_message( ResourceBundle $bundle )
 383  * Get text description for ResourceBundle's last error.
 384  */
 385 PHP_FUNCTION( resourcebundle_get_error_message )
 386 {
 387         char* message = NULL;
 388         RESOURCEBUNDLE_METHOD_INIT_VARS;
 389 
 390         if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
 391                 &object, ResourceBundle_ce_ptr ) == FAILURE )
 392         {
 393                 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
 394                         "resourcebundle_get_error_message: unable to parse input params", 0 TSRMLS_CC );
 395                 RETURN_FALSE;
 396         }
 397 
 398         rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC );
 399         message = (char *)intl_error_get_message(INTL_DATA_ERROR_P(rb) TSRMLS_CC);
 400         RETURN_STRING(message, 0);
 401 }
 402 /* }}} */
 403 
 404 /* {{{ ResourceBundle_class_functions
 405  * Every 'ResourceBundle' class method has an entry in this table
 406  */
 407 static zend_function_entry ResourceBundle_class_functions[] = {
 408         PHP_ME( ResourceBundle, __construct, arginfo_resourcebundle___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR )
 409         ZEND_NAMED_ME( create, ZEND_FN( resourcebundle_create ), arginfo_resourcebundle___construct, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
 410         ZEND_NAMED_ME( get, ZEND_FN(resourcebundle_get), arginfo_resourcebundle_get, ZEND_ACC_PUBLIC )
 411         ZEND_NAMED_ME( count, ZEND_FN(resourcebundle_count), arginfo_resourcebundle_count, ZEND_ACC_PUBLIC )
 412         ZEND_NAMED_ME( getLocales, ZEND_FN(resourcebundle_locales), arginfo_resourcebundle_getlocales, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC )
 413         ZEND_NAMED_ME( getErrorCode, ZEND_FN(resourcebundle_get_error_code), arginfo_resourcebundle_get_error_code, ZEND_ACC_PUBLIC )
 414         ZEND_NAMED_ME( getErrorMessage, ZEND_FN(resourcebundle_get_error_message), arginfo_resourcebundle_get_error_message, ZEND_ACC_PUBLIC )
 415         PHP_FE_END
 416 };
 417 /* }}} */
 418 
 419 /* {{{ resourcebundle_register_class
 420  * Initialize 'ResourceBundle' class
 421  */
 422 void resourcebundle_register_class( TSRMLS_D )
 423 {
 424         zend_class_entry ce;
 425 
 426         INIT_CLASS_ENTRY( ce, "ResourceBundle", ResourceBundle_class_functions );
 427 
 428         ce.create_object = ResourceBundle_object_create;
 429         ce.get_iterator = resourcebundle_get_iterator;
 430 
 431         ResourceBundle_ce_ptr = zend_register_internal_class( &ce TSRMLS_CC );
 432 
 433         if( !ResourceBundle_ce_ptr )
 434         {
 435                 zend_error(E_ERROR, "Failed to register ResourceBundle class");
 436                 return;
 437         }
 438 
 439         ResourceBundle_object_handlers = std_object_handlers;
 440         ResourceBundle_object_handlers.clone_obj          = NULL; /* ICU ResourceBundle has no clone implementation */
 441         ResourceBundle_object_handlers.read_dimension = resourcebundle_array_get;
 442         ResourceBundle_object_handlers.count_elements = resourcebundle_array_count;
 443 
 444         zend_class_implements(ResourceBundle_ce_ptr TSRMLS_CC, 1, zend_ce_traversable);
 445 }
 446 /* }}} */
 447 
 448 /*
 449  * Local variables:
 450  * tab-width: 4
 451  * c-basic-offset: 4
 452  * End:
 453  * vim600: noet sw=4 ts=4 fdm=marker
 454  * vim<600: noet sw=4 ts=4
 455  */

/* [<][>][^][v][top][bottom][index][help] */