Back to index

php5  5.3.10
resourcebundle_class.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | This source file is subject to version 3.01 of the PHP license,      |
00006    | that is bundled with this package in the file LICENSE, and is        |
00007    | available through the world-wide-web at the following url:           |
00008    | http://www.php.net/license/3_01.txt                                  |
00009    | If you did not receive a copy of the PHP license and are unable to   |
00010    | obtain it through the world-wide-web, please send a note to          |
00011    | license@php.net so we can mail you a copy immediately.               |
00012    +----------------------------------------------------------------------+
00013    | Authors: Hans-Peter Oeri (University of St.Gallen) <hp@oeri.ch>      |
00014    +----------------------------------------------------------------------+
00015  */
00016 
00017 #include <stdlib.h>
00018 #include <unicode/ures.h>
00019 #include <unicode/uenum.h>
00020 
00021 #include <zend.h>
00022 #include <Zend/zend_exceptions.h>
00023 #include <Zend/zend_interfaces.h>
00024 #include <php.h>
00025 
00026 #include "php_intl.h"
00027 #include "intl_data.h"
00028 
00029 #include "resourcebundle/resourcebundle.h"
00030 #include "resourcebundle/resourcebundle_iterator.h"
00031 #include "resourcebundle/resourcebundle_class.h"
00032 
00033 zend_class_entry *ResourceBundle_ce_ptr = NULL;
00034 
00035 static zend_object_handlers ResourceBundle_object_handlers;
00036 
00037 /* {{{ ResourceBundle_object_dtor */
00038 static void ResourceBundle_object_destroy( void *object, zend_object_handle handle TSRMLS_DC )
00039 {
00040        ResourceBundle_object *rb = (ResourceBundle_object *) object;
00041 
00042        // only free local errors
00043        intl_error_reset( INTL_DATA_ERROR_P(rb) TSRMLS_CC );
00044 
00045        if (rb->me) {
00046               ures_close( rb->me );
00047        }
00048        if (rb->child) {
00049               ures_close( rb->child );
00050        }
00051 
00052        zend_object_std_dtor( object TSRMLS_CC );
00053        efree(object);
00054 }
00055 /* }}} */
00056 
00057 /* {{{ ResourceBundle_object_create */
00058 static zend_object_value ResourceBundle_object_create( zend_class_entry *ce TSRMLS_DC )
00059 {
00060        zend_object_value     retval;
00061        ResourceBundle_object *rb;
00062 
00063        rb = ecalloc( 1, sizeof(ResourceBundle_object) );
00064 
00065        zend_object_std_init( (zend_object *) rb, ce TSRMLS_CC );
00066 
00067        intl_error_init( INTL_DATA_ERROR_P(rb) TSRMLS_CC );
00068        rb->me = NULL;
00069        rb->child = NULL;
00070 
00071        retval.handlers = &ResourceBundle_object_handlers;
00072        retval.handle = zend_objects_store_put(   rb, ResourceBundle_object_destroy, NULL, NULL TSRMLS_CC );
00073 
00074        return retval;
00075 }
00076 /* }}} */
00077 
00078 /* {{{ ResourceBundle_ctor */
00079 static void resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS) 
00080 {
00081        char *    bundlename;
00082        int       bundlename_len = 0;
00083        char *    locale;
00084        int       locale_len = 0;
00085        zend_bool fallback = 1;
00086 
00087        char *    pbuf;
00088 
00089        zval                  *object = return_value;
00090        ResourceBundle_object *rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC);
00091 
00092        intl_error_reset( NULL TSRMLS_CC );
00093 
00094        if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", 
00095               &locale, &locale_len, &bundlename, &bundlename_len, &fallback ) == FAILURE )
00096        {
00097               intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
00098                      "resourcebundle_ctor: unable to parse input parameters", 0 TSRMLS_CC );
00099               zval_dtor( return_value );
00100               RETURN_NULL();
00101        }
00102 
00103        INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value);
00104 
00105        if (fallback) {
00106               rb->me = ures_open(bundlename, locale, &INTL_DATA_ERROR_CODE(rb));
00107        } else {
00108               rb->me = ures_openDirect(bundlename, locale, &INTL_DATA_ERROR_CODE(rb));
00109        }
00110 
00111        INTL_CTOR_CHECK_STATUS(rb, "resourcebundle_ctor: Cannot load libICU resource bundle");
00112 
00113        if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING || INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) {
00114               intl_errors_set_code( NULL, INTL_DATA_ERROR_CODE(rb) TSRMLS_CC );
00115               spprintf( &pbuf, 0, "resourcebundle_ctor: Cannot load libICU resource '%s' without fallback from %s to %s",
00116                             bundlename, locale, ures_getLocaleByType( rb->me, ULOC_ACTUAL_LOCALE, &INTL_DATA_ERROR_CODE(rb)) );
00117               intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 TSRMLS_CC );
00118               efree(pbuf);
00119               zval_dtor( return_value );
00120               RETURN_NULL();
00121        }
00122 }
00123 /* }}} */
00124 
00125 /* {{{ arginfo_resourcebundle__construct */
00126 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle___construct, 0, 0, 2 )
00127        ZEND_ARG_INFO( 0, locale )
00128        ZEND_ARG_INFO( 0, bundlename )
00129        ZEND_ARG_INFO( 0, fallback )
00130 ZEND_END_ARG_INFO()
00131 /* }}} */
00132 
00133 /* {{{ proto void ResourceBundle::__construct( string $locale [, string $bundlename [, bool $fallback = true ]] )
00134  * ResourceBundle object constructor
00135  */
00136 PHP_METHOD( ResourceBundle, __construct )
00137 {
00138        return_value = getThis();
00139        resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
00140 }
00141 /* }}} */
00142 
00143 /* {{{ proto ResourceBundle ResourceBundle::create( string $locale [, string $bundlename [, bool $fallback = true ]] )
00144 proto ResourceBundle resourcebundle_create( string $locale [, string $bundlename [, bool $fallback = true ]] )
00145 */
00146 PHP_FUNCTION( resourcebundle_create ) 
00147 {
00148        object_init_ex( return_value, ResourceBundle_ce_ptr );
00149        resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
00150 }
00151 /* }}} */
00152 
00153 /* {{{ resourcebundle_array_fetch */
00154 static void resourcebundle_array_fetch(zval *object, zval *offset, zval *return_value, int fallback TSRMLS_DC) 
00155 {
00156        int32_t     meindex;
00157        char *      mekey;
00158        long        mekeylen;
00159     zend_bool    is_numeric = 0;
00160        char         *pbuf;
00161        ResourceBundle_object *rb;
00162 
00163        intl_error_reset( NULL TSRMLS_CC );       
00164        RESOURCEBUNDLE_METHOD_FETCH_OBJECT;
00165 
00166        if(Z_TYPE_P(offset) == IS_LONG) {
00167               is_numeric = 1;
00168               meindex = Z_LVAL_P(offset);
00169               rb->child = ures_getByIndex( rb->me, meindex, rb->child, &INTL_DATA_ERROR_CODE(rb) );
00170        } else if(Z_TYPE_P(offset) == IS_STRING) {
00171               mekey = Z_STRVAL_P(offset);
00172               mekeylen = Z_STRLEN_P(offset);
00173               rb->child = ures_getByKey(rb->me, mekey, rb->child, &INTL_DATA_ERROR_CODE(rb) );
00174        } else {
00175               intl_errors_set(INTL_DATA_ERROR_P(rb), U_ILLEGAL_ARGUMENT_ERROR,      
00176                      "resourcebundle_get: index should be integer or string", 0 TSRMLS_CC);
00177               RETURN_NULL();
00178        }
00179 
00180        intl_error_set_code( NULL, INTL_DATA_ERROR_CODE(rb) TSRMLS_CC );      
00181        if (U_FAILURE(INTL_DATA_ERROR_CODE(rb))) {
00182               if (is_numeric) {
00183                      spprintf( &pbuf, 0, "Cannot load resource element %d", meindex );
00184               } else {
00185                      spprintf( &pbuf, 0, "Cannot load resource element '%s'", mekey );
00186               }
00187               intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 TSRMLS_CC );
00188               efree(pbuf);
00189               RETURN_NULL();
00190        }
00191 
00192        if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING || INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) {
00193               UErrorCode icuerror;
00194               const char * locale = ures_getLocaleByType( rb->me, ULOC_ACTUAL_LOCALE, &icuerror );
00195               if (is_numeric) {
00196                      spprintf( &pbuf, 0, "Cannot load element %d without fallback from to %s", meindex, locale );
00197               } else {
00198                      spprintf( &pbuf, 0, "Cannot load element '%s' without fallback from to %s", mekey, locale );
00199               }
00200               intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 TSRMLS_CC );
00201               efree(pbuf);
00202               RETURN_NULL();
00203        }
00204 
00205        resourcebundle_extract_value( return_value, rb TSRMLS_CC );
00206 }
00207 /* }}} */
00208 
00209 /* {{{ resourcebundle_array_get */
00210 zval *resourcebundle_array_get(zval *object, zval *offset, int type TSRMLS_DC) 
00211 {
00212        zval *retval;
00213 
00214        if(offset == NULL) {
00215               php_error( E_ERROR, "Cannot apply [] to ResourceBundle object" );
00216        }
00217        MAKE_STD_ZVAL(retval);
00218 
00219        resourcebundle_array_fetch(object, offset, retval, 1 TSRMLS_CC);
00220        Z_DELREF_P(retval);
00221        return retval;
00222 }
00223 /* }}} */
00224 
00225 /* {{{ arginfo_resourcebundle_get */
00226 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_get, 0, 0, 1 )
00227        ZEND_ARG_INFO( 0, index )
00228        ZEND_ARG_INFO( 0, fallback )
00229 ZEND_END_ARG_INFO()
00230 /* }}} */
00231 
00232 /* {{{ proto mixed ResourceBundle::get( integer|string $resindex [, bool $fallback = true ] )
00233  * proto mixed resourcebundle_get( ResourceBundle $rb, integer|string $resindex [, bool $fallback = true ] )
00234  * Get resource identified by numerical index or key name.
00235  */
00236 PHP_FUNCTION( resourcebundle_get )
00237 {
00238        zend_bool   fallback = 1;
00239        zval *        offset;
00240        zval *      object;
00241 
00242        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz|b",      &object, ResourceBundle_ce_ptr, &offset, &fallback ) == FAILURE) {
00243               intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,   
00244                      "resourcebundle_get: unable to parse input params", 0 TSRMLS_CC);
00245               RETURN_FALSE;
00246        }
00247 
00248        resourcebundle_array_fetch(object, offset, return_value, fallback TSRMLS_CC);
00249 }
00250 /* }}} */
00251 
00252 /* {{{ resourcebundle_array_count */
00253 int resourcebundle_array_count(zval *object, long *count TSRMLS_DC) 
00254 {
00255        ResourceBundle_object *rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC);
00256 
00257        *count = ures_getSize( rb->me );
00258 
00259        return SUCCESS;
00260 }
00261 /* }}} */
00262 
00263 /* {{{ arginfo_resourcebundle_count */
00264 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_count, 0, 0, 0 )
00265 ZEND_END_ARG_INFO()
00266 /* }}} */
00267 
00268 /* {{{ proto int ResourceBundle::count()
00269  * proto int resourcebundle_count( ResourceBundle $bundle )
00270  * Get resources count
00271  */
00272 PHP_FUNCTION( resourcebundle_count )
00273 {
00274        int32_t                len;
00275        RESOURCEBUNDLE_METHOD_INIT_VARS;
00276 
00277        if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, ResourceBundle_ce_ptr ) == FAILURE ) {
00278               intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,   
00279                      "resourcebundle_count: unable to parse input params", 0 TSRMLS_CC);
00280               RETURN_FALSE;
00281        }
00282 
00283        RESOURCEBUNDLE_METHOD_FETCH_OBJECT;
00284 
00285        len = ures_getSize( rb->me );
00286        RETURN_LONG( len );
00287 }
00288 
00289 /* {{{ arginfo_resourcebundle_getlocales */
00290 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_getlocales, 0, 0, 1 )
00291        ZEND_ARG_INFO( 0, bundlename )
00292 ZEND_END_ARG_INFO()
00293 /* }}} */
00294 
00295 /* {{{ proto array ResourceBundle::getLocales( string $bundlename )
00296  * proto array resourcebundle_locales( string $bundlename )
00297  * Get available locales from ResourceBundle name
00298  */
00299 PHP_FUNCTION( resourcebundle_locales )
00300 {
00301        char * bundlename;
00302        int    bundlename_len = 0;
00303        const char * entry;
00304        int entry_len;
00305        UEnumeration *icuenum;
00306        UErrorCode   icuerror = U_ZERO_ERROR;
00307 
00308        intl_errors_reset( NULL TSRMLS_CC );
00309 
00310        if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &bundlename, &bundlename_len ) == FAILURE )
00311        {
00312               intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,   
00313                      "resourcebundle_locales: unable to parse input params", 0 TSRMLS_CC);
00314               RETURN_FALSE;
00315        }
00316 
00317        if(bundlename_len == 0) {
00318               // fetch default locales list
00319               bundlename = NULL;
00320        }
00321 
00322        icuenum = ures_openAvailableLocales( bundlename, &icuerror );
00323        INTL_CHECK_STATUS(icuerror, "Cannot fetch locales list");             
00324 
00325        uenum_reset( icuenum, &icuerror );
00326        INTL_CHECK_STATUS(icuerror, "Cannot iterate locales list");           
00327 
00328        array_init( return_value );
00329        while ((entry = uenum_next( icuenum, &entry_len, &icuerror ))) {
00330               add_next_index_stringl( return_value, (char *) entry, entry_len, 1 );
00331        }
00332        uenum_close( icuenum );
00333 }
00334 /* }}} */
00335 
00336 /* {{{ arginfo_resourcebundle_get_error_code */
00337 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_get_error_code, 0, 0, 0 )
00338 ZEND_END_ARG_INFO()
00339 /* }}} */
00340 
00341 /* {{{ proto string ResourceBundle::getErrorCode( )
00342  * proto string resourcebundle_get_error_code( ResourceBundle $bundle )
00343  * Get text description for ResourceBundle's last error code.
00344  */
00345 PHP_FUNCTION( resourcebundle_get_error_code )
00346 {
00347        RESOURCEBUNDLE_METHOD_INIT_VARS;
00348 
00349        if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
00350               &object, ResourceBundle_ce_ptr ) == FAILURE )
00351        {
00352               intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
00353                      "resourcebundle_get_error_code: unable to parse input params", 0 TSRMLS_CC );
00354               RETURN_FALSE;
00355        }
00356 
00357        rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC );
00358 
00359        RETURN_LONG(INTL_DATA_ERROR_CODE(rb));
00360 }
00361 /* }}} */
00362 
00363 /* {{{ arginfo_resourcebundle_get_error_message */
00364 ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_get_error_message, 0, 0, 0 )
00365 ZEND_END_ARG_INFO()
00366 /* }}} */
00367 
00368 /* {{{ proto string ResourceBundle::getErrorMessage( )
00369  * proto string resourcebundle_get_error_message( ResourceBundle $bundle )
00370  * Get text description for ResourceBundle's last error.
00371  */
00372 PHP_FUNCTION( resourcebundle_get_error_message )
00373 {
00374        char* message = NULL;
00375        RESOURCEBUNDLE_METHOD_INIT_VARS;
00376 
00377        if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
00378               &object, ResourceBundle_ce_ptr ) == FAILURE )
00379        {
00380               intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
00381                      "resourcebundle_get_error_message: unable to parse input params", 0 TSRMLS_CC );
00382               RETURN_FALSE;
00383        }
00384 
00385        rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC );
00386        message = (char *)intl_error_get_message(INTL_DATA_ERROR_P(rb) TSRMLS_CC);
00387        RETURN_STRING(message, 0);
00388 }
00389 /* }}} */
00390 
00391 /* {{{ ResourceBundle_class_functions
00392  * Every 'ResourceBundle' class method has an entry in this table
00393  */
00394 static function_entry ResourceBundle_class_functions[] = {
00395        PHP_ME( ResourceBundle, __construct, arginfo_resourcebundle___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR )
00396        ZEND_NAMED_ME( create, ZEND_FN( resourcebundle_create ), arginfo_resourcebundle___construct, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
00397        ZEND_NAMED_ME( get, ZEND_FN(resourcebundle_get), arginfo_resourcebundle_get, ZEND_ACC_PUBLIC )
00398        ZEND_NAMED_ME( count, ZEND_FN(resourcebundle_count), arginfo_resourcebundle_count, ZEND_ACC_PUBLIC )
00399        ZEND_NAMED_ME( getLocales, ZEND_FN(resourcebundle_locales), arginfo_resourcebundle_getlocales, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC )
00400        ZEND_NAMED_ME( getErrorCode, ZEND_FN(resourcebundle_get_error_code), arginfo_resourcebundle_get_error_code, ZEND_ACC_PUBLIC )
00401        ZEND_NAMED_ME( getErrorMessage, ZEND_FN(resourcebundle_get_error_message), arginfo_resourcebundle_get_error_message, ZEND_ACC_PUBLIC )
00402        PHP_FE_END
00403 };
00404 /* }}} */
00405 
00406 /* {{{ resourcebundle_register_class
00407  * Initialize 'ResourceBundle' class
00408  */
00409 void resourcebundle_register_class( TSRMLS_D )
00410 {
00411        zend_class_entry ce;
00412 
00413        INIT_CLASS_ENTRY( ce, "ResourceBundle", ResourceBundle_class_functions );
00414 
00415        ce.create_object = ResourceBundle_object_create;
00416        ce.get_iterator = resourcebundle_get_iterator;
00417 
00418        ResourceBundle_ce_ptr = zend_register_internal_class( &ce TSRMLS_CC );
00419 
00420        if( !ResourceBundle_ce_ptr )
00421        {
00422               zend_error(E_ERROR, "Failed to register ResourceBundle class");
00423               return;
00424        }
00425 
00426        ResourceBundle_object_handlers = std_object_handlers;
00427        ResourceBundle_object_handlers.clone_obj    = NULL; /* ICU ResourceBundle has no clone implementation */
00428        ResourceBundle_object_handlers.read_dimension = resourcebundle_array_get;
00429        ResourceBundle_object_handlers.count_elements = resourcebundle_array_count;
00430 }
00431 /* }}} */
00432 
00433 /*
00434  * Local variables:
00435  * tab-width: 4
00436  * c-basic-offset: 4
00437  * End:
00438  * vim600: noet sw=4 ts=4 fdm=marker
00439  * vim<600: noet sw=4 ts=4
00440  */