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

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 );
1.1.1.3   misho      66:        object_properties_init((zend_object *) rb, ce);
1.1       misho      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:        char *    bundlename;
                     83:        int       bundlename_len = 0;
                     84:        char *    locale;
                     85:        int       locale_len = 0;
                     86:        zend_bool fallback = 1;
                     87: 
                     88:        char *    pbuf;
                     89: 
                     90:        zval                  *object = return_value;
                     91:        ResourceBundle_object *rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC);
                     92: 
                     93:        intl_error_reset( NULL TSRMLS_CC );
                     94: 
1.1.1.3   misho      95:        if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s!s!|b", 
1.1       misho      96:                &locale, &locale_len, &bundlename, &bundlename_len, &fallback ) == FAILURE )
                     97:        {
                     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 );
                    101:                RETURN_NULL();
                    102:        }
                    103: 
                    104:        INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value);
1.1.1.3   misho     105:        
                    106:        if (locale == NULL) {
                    107:                locale = INTL_G(default_locale);
                    108:        }
1.1       misho     109: 
                    110:        if (fallback) {
                    111:                rb->me = ures_open(bundlename, locale, &INTL_DATA_ERROR_CODE(rb));
                    112:        } else {
                    113:                rb->me = ures_openDirect(bundlename, locale, &INTL_DATA_ERROR_CODE(rb));
                    114:        }
                    115: 
                    116:        INTL_CTOR_CHECK_STATUS(rb, "resourcebundle_ctor: Cannot load libICU resource bundle");
                    117: 
1.1.1.3   misho     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);
1.1       misho     127:                efree(pbuf);
1.1.1.3   misho     128:                zval_dtor(return_value);
1.1       misho     129:                RETURN_NULL();
                    130:        }
                    131: }
                    132: /* }}} */
                    133: 
                    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 )
                    139: ZEND_END_ARG_INFO()
                    140: /* }}} */
                    141: 
                    142: /* {{{ proto void ResourceBundle::__construct( string $locale [, string $bundlename [, bool $fallback = true ]] )
                    143:  * ResourceBundle object constructor
                    144:  */
                    145: PHP_METHOD( ResourceBundle, __construct )
                    146: {
                    147:        return_value = getThis();
                    148:        resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
                    149: }
                    150: /* }}} */
                    151: 
                    152: /* {{{ proto ResourceBundle ResourceBundle::create( string $locale [, string $bundlename [, bool $fallback = true ]] )
                    153: proto ResourceBundle resourcebundle_create( string $locale [, string $bundlename [, bool $fallback = true ]] )
                    154: */
                    155: PHP_FUNCTION( resourcebundle_create ) 
                    156: {
                    157:        object_init_ex( return_value, ResourceBundle_ce_ptr );
                    158:        resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
                    159: }
                    160: /* }}} */
                    161: 
                    162: /* {{{ resourcebundle_array_fetch */
                    163: static void resourcebundle_array_fetch(zval *object, zval *offset, zval *return_value, int fallback TSRMLS_DC) 
                    164: {
1.1.1.4 ! misho     165:        int32_t     meindex = 0;
        !           166:        char *      mekey = NULL;
1.1       misho     167:        long        mekeylen;
                    168:     zend_bool    is_numeric = 0;
                    169:        char         *pbuf;
                    170:        ResourceBundle_object *rb;
                    171: 
                    172:        intl_error_reset( NULL TSRMLS_CC );     
                    173:        RESOURCEBUNDLE_METHOD_FETCH_OBJECT;
                    174: 
                    175:        if(Z_TYPE_P(offset) == IS_LONG) {
                    176:                is_numeric = 1;
                    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) );
                    183:        } else {
                    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);
                    186:                RETURN_NULL();
                    187:        }
                    188: 
                    189:        intl_error_set_code( NULL, INTL_DATA_ERROR_CODE(rb) TSRMLS_CC );        
                    190:        if (U_FAILURE(INTL_DATA_ERROR_CODE(rb))) {
                    191:                if (is_numeric) {
                    192:                        spprintf( &pbuf, 0, "Cannot load resource element %d", meindex );
                    193:                } else {
                    194:                        spprintf( &pbuf, 0, "Cannot load resource element '%s'", mekey );
                    195:                }
                    196:                intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 TSRMLS_CC );
                    197:                efree(pbuf);
                    198:                RETURN_NULL();
                    199:        }
                    200: 
                    201:        if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING || INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) {
                    202:                UErrorCode icuerror;
                    203:                const char * locale = ures_getLocaleByType( rb->me, ULOC_ACTUAL_LOCALE, &icuerror );
                    204:                if (is_numeric) {
                    205:                        spprintf( &pbuf, 0, "Cannot load element %d without fallback from to %s", meindex, locale );
                    206:                } else {
                    207:                        spprintf( &pbuf, 0, "Cannot load element '%s' without fallback from to %s", mekey, locale );
                    208:                }
                    209:                intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 TSRMLS_CC );
                    210:                efree(pbuf);
                    211:                RETURN_NULL();
                    212:        }
                    213: 
                    214:        resourcebundle_extract_value( return_value, rb TSRMLS_CC );
                    215: }
                    216: /* }}} */
                    217: 
                    218: /* {{{ resourcebundle_array_get */
                    219: zval *resourcebundle_array_get(zval *object, zval *offset, int type TSRMLS_DC) 
                    220: {
                    221:        zval *retval;
                    222: 
                    223:        if(offset == NULL) {
                    224:                php_error( E_ERROR, "Cannot apply [] to ResourceBundle object" );
                    225:        }
                    226:        MAKE_STD_ZVAL(retval);
                    227: 
                    228:        resourcebundle_array_fetch(object, offset, retval, 1 TSRMLS_CC);
                    229:        Z_DELREF_P(retval);
                    230:        return retval;
                    231: }
                    232: /* }}} */
                    233: 
                    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 )
                    238: ZEND_END_ARG_INFO()
                    239: /* }}} */
                    240: 
                    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.
                    244:  */
                    245: PHP_FUNCTION( resourcebundle_get )
                    246: {
                    247:        zend_bool   fallback = 1;
                    248:        zval *          offset;
                    249:        zval *      object;
                    250: 
                    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);
                    254:                RETURN_FALSE;
                    255:        }
                    256: 
                    257:        resourcebundle_array_fetch(object, offset, return_value, fallback TSRMLS_CC);
                    258: }
                    259: /* }}} */
                    260: 
                    261: /* {{{ resourcebundle_array_count */
                    262: int resourcebundle_array_count(zval *object, long *count TSRMLS_DC) 
                    263: {
1.1.1.3   misho     264:        ResourceBundle_object *rb;
                    265:        RESOURCEBUNDLE_METHOD_FETCH_OBJECT_NO_CHECK;
                    266: 
                    267:        if (rb->me == NULL) {
                    268:                intl_errors_set(&rb->error, U_ILLEGAL_ARGUMENT_ERROR,
                    269:                                "Found unconstructed ResourceBundle", 0 TSRMLS_CC);
                    270:                return 0;
                    271:        }
1.1       misho     272: 
                    273:        *count = ures_getSize( rb->me );
                    274: 
                    275:        return SUCCESS;
                    276: }
                    277: /* }}} */
                    278: 
                    279: /* {{{ arginfo_resourcebundle_count */
                    280: ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_count, 0, 0, 0 )
                    281: ZEND_END_ARG_INFO()
                    282: /* }}} */
                    283: 
                    284: /* {{{ proto int ResourceBundle::count()
                    285:  * proto int resourcebundle_count( ResourceBundle $bundle )
                    286:  * Get resources count
                    287:  */
                    288: PHP_FUNCTION( resourcebundle_count )
                    289: {
                    290:        int32_t                len;
                    291:        RESOURCEBUNDLE_METHOD_INIT_VARS;
                    292: 
                    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);
                    296:                RETURN_FALSE;
                    297:        }
                    298: 
                    299:        RESOURCEBUNDLE_METHOD_FETCH_OBJECT;
                    300: 
                    301:        len = ures_getSize( rb->me );
                    302:        RETURN_LONG( len );
                    303: }
                    304: 
                    305: /* {{{ arginfo_resourcebundle_getlocales */
                    306: ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_getlocales, 0, 0, 1 )
                    307:        ZEND_ARG_INFO( 0, bundlename )
                    308: ZEND_END_ARG_INFO()
                    309: /* }}} */
                    310: 
                    311: /* {{{ proto array ResourceBundle::getLocales( string $bundlename )
                    312:  * proto array resourcebundle_locales( string $bundlename )
                    313:  * Get available locales from ResourceBundle name
                    314:  */
                    315: PHP_FUNCTION( resourcebundle_locales )
                    316: {
                    317:        char * bundlename;
                    318:        int    bundlename_len = 0;
                    319:        const char * entry;
                    320:        int entry_len;
                    321:        UEnumeration *icuenum;
                    322:        UErrorCode   icuerror = U_ZERO_ERROR;
                    323: 
                    324:        intl_errors_reset( NULL TSRMLS_CC );
                    325: 
                    326:        if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &bundlename, &bundlename_len ) == FAILURE )
                    327:        {
                    328:                intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,  
                    329:                        "resourcebundle_locales: unable to parse input params", 0 TSRMLS_CC);
                    330:                RETURN_FALSE;
                    331:        }
                    332: 
                    333:        if(bundlename_len == 0) {
                    334:                // fetch default locales list
                    335:                bundlename = NULL;
                    336:        }
                    337: 
                    338:        icuenum = ures_openAvailableLocales( bundlename, &icuerror );
                    339:        INTL_CHECK_STATUS(icuerror, "Cannot fetch locales list");               
                    340: 
                    341:        uenum_reset( icuenum, &icuerror );
                    342:        INTL_CHECK_STATUS(icuerror, "Cannot iterate locales list");             
                    343: 
                    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 );
                    347:        }
                    348:        uenum_close( icuenum );
                    349: }
                    350: /* }}} */
                    351: 
                    352: /* {{{ arginfo_resourcebundle_get_error_code */
                    353: ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_get_error_code, 0, 0, 0 )
                    354: ZEND_END_ARG_INFO()
                    355: /* }}} */
                    356: 
                    357: /* {{{ proto string ResourceBundle::getErrorCode( )
                    358:  * proto string resourcebundle_get_error_code( ResourceBundle $bundle )
                    359:  * Get text description for ResourceBundle's last error code.
                    360:  */
                    361: PHP_FUNCTION( resourcebundle_get_error_code )
                    362: {
                    363:        RESOURCEBUNDLE_METHOD_INIT_VARS;
                    364: 
                    365:        if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
                    366:                &object, ResourceBundle_ce_ptr ) == FAILURE )
                    367:        {
                    368:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                    369:                        "resourcebundle_get_error_code: unable to parse input params", 0 TSRMLS_CC );
                    370:                RETURN_FALSE;
                    371:        }
                    372: 
                    373:        rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC );
                    374: 
                    375:        RETURN_LONG(INTL_DATA_ERROR_CODE(rb));
                    376: }
                    377: /* }}} */
                    378: 
                    379: /* {{{ arginfo_resourcebundle_get_error_message */
                    380: ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_get_error_message, 0, 0, 0 )
                    381: ZEND_END_ARG_INFO()
                    382: /* }}} */
                    383: 
                    384: /* {{{ proto string ResourceBundle::getErrorMessage( )
                    385:  * proto string resourcebundle_get_error_message( ResourceBundle $bundle )
                    386:  * Get text description for ResourceBundle's last error.
                    387:  */
                    388: PHP_FUNCTION( resourcebundle_get_error_message )
                    389: {
                    390:        char* message = NULL;
                    391:        RESOURCEBUNDLE_METHOD_INIT_VARS;
                    392: 
                    393:        if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
                    394:                &object, ResourceBundle_ce_ptr ) == FAILURE )
                    395:        {
                    396:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                    397:                        "resourcebundle_get_error_message: unable to parse input params", 0 TSRMLS_CC );
                    398:                RETURN_FALSE;
                    399:        }
                    400: 
                    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);
                    404: }
                    405: /* }}} */
                    406: 
                    407: /* {{{ ResourceBundle_class_functions
                    408:  * Every 'ResourceBundle' class method has an entry in this table
                    409:  */
1.1.1.2   misho     410: static zend_function_entry ResourceBundle_class_functions[] = {
1.1       misho     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 )
                    418:        PHP_FE_END
                    419: };
                    420: /* }}} */
                    421: 
                    422: /* {{{ resourcebundle_register_class
                    423:  * Initialize 'ResourceBundle' class
                    424:  */
                    425: void resourcebundle_register_class( TSRMLS_D )
                    426: {
                    427:        zend_class_entry ce;
                    428: 
                    429:        INIT_CLASS_ENTRY( ce, "ResourceBundle", ResourceBundle_class_functions );
                    430: 
                    431:        ce.create_object = ResourceBundle_object_create;
                    432:        ce.get_iterator = resourcebundle_get_iterator;
                    433: 
                    434:        ResourceBundle_ce_ptr = zend_register_internal_class( &ce TSRMLS_CC );
                    435: 
                    436:        if( !ResourceBundle_ce_ptr )
                    437:        {
                    438:                zend_error(E_ERROR, "Failed to register ResourceBundle class");
                    439:                return;
                    440:        }
                    441: 
                    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;
1.1.1.3   misho     446: 
                    447:        zend_class_implements(ResourceBundle_ce_ptr TSRMLS_CC, 1, zend_ce_traversable);
1.1       misho     448: }
                    449: /* }}} */
                    450: 
                    451: /*
                    452:  * Local variables:
                    453:  * tab-width: 4
                    454:  * c-basic-offset: 4
                    455:  * End:
                    456:  * vim600: noet sw=4 ts=4 fdm=marker
                    457:  * vim<600: noet sw=4 ts=4
                    458:  */

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