Annotation of embedaddon/php/ext/intl/resourcebundle/resourcebundle_class.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>