l0t3k wrote: > In ICU, resource bundles are cached for efficiency, but the cache is > per-process, and i seem to recall that the cache is not currently flushed. > Additionally the key is the ICU locale id, so its impossible without source > changes to make this work for user-created resources without collision in > shared hosting mode.
Sounds like gettext() :) Could you elaborate? > that said, it would be perfectly fine for allowing access to locale data. > a few additions i'd make > > 1. allow an indexer as an equivalent to the getByKey() method e.g. > $rb["key"] === $rb->getByIndex("key") > 2. cast handlers in addition to getXXX methods Sounds reasonable, new patch attached. -- Michael
Index: ext/unicode/config.m4 =================================================================== RCS file: /repository/php-src/ext/unicode/config.m4,v retrieving revision 1.10 diff -u -p -d -r1.10 config.m4 --- ext/unicode/config.m4 13 Jun 2006 23:46:04 -0000 1.10 +++ ext/unicode/config.m4 14 Dec 2006 13:15:52 -0000 @@ -4,4 +4,4 @@ dnl PHP_SUBST(UNICODE_SHARED_LIBADD) AC_DEFINE(HAVE_UNICODE, 1, [ ]) -PHP_NEW_EXTENSION(unicode, unicode.c locale.c unicode_iterators.c collator.c property.c constants.c transform.c, $ext_shared) +PHP_NEW_EXTENSION(unicode, unicode.c locale.c unicode_iterators.c collator.c property.c constants.c transform.c resourcebundle.c, $ext_shared) Index: ext/unicode/constants.c =================================================================== RCS file: /repository/php-src/ext/unicode/constants.c,v retrieving revision 1.1 diff -u -p -d -r1.1 constants.c --- ext/unicode/constants.c 5 May 2006 20:56:21 -0000 1.1 +++ ext/unicode/constants.c 14 Dec 2006 13:15:52 -0000 @@ -16,6 +16,7 @@ */ #include "php_unicode.h" +#include <unicode/ures.h> PHPAPI zend_class_entry *u_const_ce; @@ -578,6 +579,28 @@ static void php_register_misc_constants( } /* }}} */ +/* {{{ ResourceBundle constants */ +static void php_register_resourcebundle_constants(TSRMLS_D) +{ + REGISTER_U_CONST(URES_NONE); + REGISTER_U_CONST(URES_STRING); + REGISTER_U_CONST(URES_BINARY); + REGISTER_U_CONST(URES_TABLE); + REGISTER_U_CONST(URES_ALIAS); + REGISTER_U_CONST(URES_INT); + REGISTER_U_CONST(URES_ARRAY); + REGISTER_U_CONST(URES_INT_VECTOR); +} +/* }}} */ + +/* {{{ LocaleData constants */ +static void php_register_localedata_constants(TSRMLS_D) +{ + REGISTER_U_CONST(ULOC_ACTUAL_LOCALE); + REGISTER_U_CONST(ULOC_VALID_LOCALE); +} +/* }}} */ + void php_register_unicode_constants(TSRMLS_D) { zend_class_entry ce; @@ -601,6 +624,8 @@ void php_register_unicode_constants(TSRM php_register_numeric_type_constants(TSRMLS_C); php_register_hangul_syllable_constants(TSRMLS_C); php_register_misc_constants(TSRMLS_C); + php_register_resourcebundle_constants(TSRMLS_C); + php_register_localedata_constants(TSRMLS_C); } /* Index: ext/unicode/php_unicode.h =================================================================== RCS file: /repository/php-src/ext/unicode/php_unicode.h,v retrieving revision 1.14 diff -u -p -d -r1.14 php_unicode.h --- ext/unicode/php_unicode.h 5 May 2006 20:56:21 -0000 1.14 +++ ext/unicode/php_unicode.h 14 Dec 2006 13:15:52 -0000 @@ -72,6 +72,7 @@ PHP_FUNCTION(collator_get_default); PHP_FUNCTION(collator_set_default); PHP_METHOD(collator, __construct); +void php_init_resourcebundle(TSRMLS_D); void php_init_collation(TSRMLS_D); void php_register_unicode_constants(TSRMLS_D); Index: ext/unicode/resourcebundle.c =================================================================== RCS file: ext/unicode/resourcebundle.c diff -N ext/unicode/resourcebundle.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ext/unicode/resourcebundle.c 14 Dec 2006 13:15:52 -0000 @@ -0,0 +1,908 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 6 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | [EMAIL PROTECTED] so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Michael Wallner <[EMAIL PROTECTED]> | + +----------------------------------------------------------------------+ +*/ + +/* $Id: collator.c,v 1.11 2006/10/06 17:14:14 andrei Exp $ */ + +#include "php.h" +#include <unicode/ures.h> +#include <unicode/ucat.h> + +typedef struct _php_resourcebundle { + zend_object zo; + UResourceBundle *ures; + HashTable *properties_ht_ptr; + zval *dimension_zv_ptr; +} php_resourcebundle; + +zend_class_entry *unicode_resourcebundle_ce; +static zend_object_handlers unicode_resourcebundle_oh; + +static PHP_METHOD(ResourceBundle, __construct); +static PHP_METHOD(ResourceBundle, factory); +static PHP_METHOD(ResourceBundle, open); +static PHP_METHOD(ResourceBundle, getVersion); +static PHP_METHOD(ResourceBundle, getType); +static PHP_METHOD(ResourceBundle, getLocale); +static PHP_METHOD(ResourceBundle, getKey); +static PHP_METHOD(ResourceBundle, getString); +static PHP_METHOD(ResourceBundle, getStringByIndex); +static PHP_METHOD(ResourceBundle, getStringByKey); +static PHP_METHOD(ResourceBundle, getBinary); +static PHP_METHOD(ResourceBundle, getInt); +static PHP_METHOD(ResourceBundle, getArray); +static PHP_METHOD(ResourceBundle, getByIndex); +static PHP_METHOD(ResourceBundle, getByKey); +static PHP_METHOD(ResourceBundle, get); +static PHP_METHOD(ResourceBundle, count); +static PHP_METHOD(ResourceBundle, getCat); + +static zend_function_entry unicode_resourcebundle_fe[] = { + PHP_ME(ResourceBundle, factory, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(ResourceBundle, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, open, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, getVersion, NULL, ZEND_ACC_PUBLIC) + PHP_MALIAS(ResourceBundle, getSize, count, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, getType, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, getLocale, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, getKey, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, getString, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, getStringByIndex, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, getStringByKey, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, getBinary, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, getInt, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, getArray, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, getByIndex, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, getByKey, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, get, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, count, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ResourceBundle, getCat, NULL, ZEND_ACC_PUBLIC) + {NULL}, +}; + +#define IF_RB_INIT(rb) if (!(rb)->ures) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Use of uninitialized ResourceBundle"); } else +#define IF_RB_TYPE(rb, t) if (ures_getType((rb)->ures) != (t)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "ResourceBundle is not of type "#t); } else +#define IF_RB_SUCCESS(s) if (U_FAILURE(s)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", u_errorName(s)); } else + +/* {{{ extractors */ +#define _EXTRACT_ALL 0 +static inline void _extract(UResourceBundle *next, zval *zv, uint types TSRMLS_DC); + +static inline void _extract_intvector(UResourceBundle *ures, zval *zv TSRMLS_DC) +{ + UErrorCode status = U_ZERO_ERROR; + int32_t len, i; + const int32_t *vec = ures_getIntVector(ures, &len, &status); + + IF_RB_SUCCESS(status) { + array_init(zv); + for (i = 0; i < len; ++i) { + add_next_index_long(zv, vec[i]); + } + } +} + +static inline void _extract_array(UResourceBundle *ures, zval *zv TSRMLS_DC) +{ + UErrorCode status = U_ZERO_ERROR; + + array_init(zv); + ures_resetIterator(ures); + + while (ures_hasNext(ures)) { + UResourceBundle *next = ures_getNextResource(ures, NULL, &status); + + IF_RB_SUCCESS(status) { + zval *entry; + + MAKE_STD_ZVAL(entry); + ZVAL_NULL(entry); + _extract(next, entry, _EXTRACT_ALL TSRMLS_CC); + add_next_index_zval(zv, entry); + } + } +} + +static inline void _extract_table(UResourceBundle *ures, zval *zv TSRMLS_DC) +{ + UErrorCode status = U_ZERO_ERROR; + + array_init(zv); + ures_resetIterator(ures); + + while (ures_hasNext(ures)) { + UResourceBundle *next = ures_getNextResource(ures, NULL, &status); + + IF_RB_SUCCESS(status) { + zval *entry; + + MAKE_STD_ZVAL(entry); + ZVAL_NULL(entry); + _extract(next, entry, _EXTRACT_ALL TSRMLS_CC); + add_assoc_zval(zv, ures_getKey(next), entry); + } + } +} + +static inline void _extract_string(UResourceBundle *ures, zval *zv TSRMLS_DC) +{ + UErrorCode status = U_ZERO_ERROR; + int32_t str_len; + const UChar *str_buf = ures_getString(ures, &str_len, &status); + + IF_RB_SUCCESS(status) { + ZVAL_UNICODEL(zv, str_buf, str_len, ZSTR_DUPLICATE); + } +} + +static inline void _extract_binary(UResourceBundle *ures, zval *zv TSRMLS_DC) +{ + UErrorCode status = U_ZERO_ERROR; + int32_t bin_len; + const uint8_t *bin_buf = ures_getBinary(ures, &bin_len, &status); + + IF_RB_SUCCESS(status) { + ZVAL_STRINGL(zv, bin_buf, bin_len, ZSTR_DUPLICATE); + } +} + +static inline void _extract_int(UResourceBundle *ures, zval *zv TSRMLS_DC) +{ + UErrorCode status = U_ZERO_ERROR; + int32_t intval = ures_getInt(ures, &status); + + IF_RB_SUCCESS(status) { + ZVAL_LONG(zv, intval); + } +} + +static inline void _extract_alias(UResourceBundle *ures, zval *zv TSRMLS_DC) +{ + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *alias = ures_getByIndex(ures, 0, NULL, &status); + + IF_RB_SUCCESS(status) { + _extract(alias, zv, _EXTRACT_ALL TSRMLS_CC); + } +} + +static inline void _extract(UResourceBundle *ures, zval *zv, uint types TSRMLS_DC) +{ + UResType type = ures_getType(ures); + + if (types && !(types & type)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "ResourceBundle is of type %d", type); + } else { + switch (type) { + case URES_NONE: + break; + case URES_STRING: + _extract_string(ures, zv TSRMLS_CC); + break; + case URES_BINARY: + _extract_binary(ures, zv TSRMLS_CC); + break; + case URES_INT: + _extract_int(ures, zv TSRMLS_CC); + break; + case URES_INT_VECTOR: + _extract_intvector(ures, zv TSRMLS_CC); + break; + case URES_ARRAY: + _extract_array(ures, zv TSRMLS_CC); + break; + case URES_TABLE: + _extract_table(ures, zv TSRMLS_CC); + break; + case URES_ALIAS: + _extract_alias(ures, zv TSRMLS_CC); + break; + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unkown ResourceBundle type %d", type); + break; + } + } +} +/* }}} */ + +/* {{{ zend object ctor/dtor */ +static void unicode_resourcebundle_free_object(zend_object *zo TSRMLS_DC) +{ + php_resourcebundle *rb = (php_resourcebundle *) zo; + + zend_object_std_dtor(zo TSRMLS_CC); + if (rb->ures) { + ures_close(rb->ures); + } + if (rb->properties_ht_ptr) { + zend_hash_destroy(rb->properties_ht_ptr); + FREE_HASHTABLE(rb->properties_ht_ptr); + } + if(rb->dimension_zv_ptr) { + zval_ptr_dtor(&rb->dimension_zv_ptr); + } + efree(rb); +} + +static zend_object_value unicode_resourcebundle_create_object_ex(zend_class_entry *ce, php_resourcebundle **ptr, UResourceBundle *ures TSRMLS_DC) +{ + zend_object_value ov; + php_resourcebundle *rb = ecalloc(1, sizeof(*rb)); + + if (ptr) { + *ptr = rb; + } + if (ures) { + rb->ures = ures; + } + + zend_object_std_init((zend_object *) rb, ce TSRMLS_CC); + zend_hash_copy(rb->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); + + ov.handle = zend_objects_store_put(rb, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) unicode_resourcebundle_free_object, NULL TSRMLS_CC); + ov.handlers = &unicode_resourcebundle_oh; + + return ov; +} + +static zend_object_value unicode_resourcebundle_create_object(zend_class_entry *ce TSRMLS_DC) +{ + return unicode_resourcebundle_create_object_ex(ce, NULL, NULL TSRMLS_CC); +} +/* }}} */ + +/* {{{ object handlers */ +static int unicode_resourcebundle_cast_object(zval *this_ptr, zval *return_value, int type, void *extra TSRMLS_DC) +{ + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + IF_RB_INIT(rb) { + /* scalar types are fine for converting */ + switch (ures_getType(rb->ures)) { + case URES_INT: + _extract_int(rb->ures, return_value TSRMLS_CC); + break; + case URES_STRING: + _extract_string(rb->ures, return_value TSRMLS_CC); + break; + case URES_BINARY: + _extract_binary(rb->ures, return_value TSRMLS_CC); + break; + default: + return FAILURE; + } + convert_to_explicit_type(return_value, type); + return SUCCESS; + } + + return FAILURE; +} + +/* handles (array) cast */ +static HashTable *unicode_resourcebundle_get_properties(zval *this_ptr TSRMLS_DC) +{ + zval rv; + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + INIT_PZVAL(&rv); + ZVAL_NULL(&rv); + + IF_RB_INIT(rb) { + _extract(rb->ures, &rv, URES_ARRAY|URES_TABLE|URES_INT_VECTOR TSRMLS_CC); + } + + if (rb->properties_ht_ptr) { + zend_hash_destroy(rb->properties_ht_ptr); + FREE_HASHTABLE(rb->properties_ht_ptr); + } + + switch (Z_TYPE(rv)) { + case IS_ARRAY: + break; + case IS_NULL: + array_init(&rv); + break; + default: + convert_to_array(&rv); + break; + } + + return rb->properties_ht_ptr = Z_ARRVAL(rv); +} + +static zval *unicode_resourcebundle_read_dimension(zval *this_ptr, zval *offset, int type TSRMLS_DC) +{ + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *ures = NULL; + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + zval tmp, *return_value = &EG(uninitialized_zval); + + /* FIXXME: what if type != BP_VAR_R ? */ + IF_RB_INIT(rb) { + switch (Z_TYPE_P(offset)) { + case IS_LONG: + ures = ures_getByIndex(rb->ures, Z_LVAL_P(offset), NULL, &status); + break; + case IS_STRING: + ures = ures_getByKey(rb->ures, Z_STRVAL_P(offset), NULL, &status); + break; + case IS_UNICODE: + tmp = *offset; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + ures = ures_getByKey(rb->ures, Z_STRVAL(tmp), NULL, &status); + zval_dtor(&tmp); + break; + } + IF_RB_SUCCESS(status) { + if (ures) { + MAKE_STD_ZVAL(return_value); + Z_TYPE_P(return_value) = IS_OBJECT; + Z_OBJVAL_P(return_value) = unicode_resourcebundle_create_object_ex(Z_OBJCE_P(getThis()), NULL, ures TSRMLS_CC); + if (rb->dimension_zv_ptr) { + zval_ptr_dtor(&rb->dimension_zv_ptr); + } + rb->dimension_zv_ptr = return_value; + } + } + } + + return return_value; +} + +static int unicode_resourcebundle_has_dimension(zval *this_ptr, zval *member, int check_empty TSRMLS_DC) +{ + return Z_TYPE_P(unicode_resourcebundle_read_dimension(getThis(), member, 0 TSRMLS_CC)) == IS_OBJECT; +} + +/* }}} */ + +/* {{{ iterators */ +typedef struct _php_resourcebundle_iter { + zend_object_iterator it; + zval *zv; + php_resourcebundle *rb; + struct { + int ref; + zval *obj; + struct { + char *str; + int len; + ulong num; + } key; + } next; +} php_resourcebundle_iter; + +static inline void unicode_resourcebundle_if_dtor_ex(php_resourcebundle_iter *data TSRMLS_DC) +{ + if (data->next.obj) { + zval_ptr_dtor(&data->next.obj); + data->next.obj = NULL; + } + if (data->next.key.str) { + efree(data->next.key.str); + data->next.key.str = NULL; + } + data->next.key.num = 0; +} + +static void unicode_resourcebundle_if_dtor(zend_object_iterator *iter TSRMLS_DC) +{ + php_resourcebundle_iter *data = iter->data; + + unicode_resourcebundle_if_dtor_ex(data TSRMLS_CC); + zval_ptr_dtor(&data->zv); + efree(data); +} + +static int unicode_resourcebundle_if_valid(zend_object_iterator *iter TSRMLS_DC) +{ + return ((php_resourcebundle_iter *) iter->data)->next.obj ? SUCCESS : FAILURE; +} + +static void unicode_resourecbundle_if_get_current_data(zend_object_iterator *iter, zval ***zv TSRMLS_DC) +{ + php_resourcebundle_iter *data = iter->data; + + /* FIXXME: what if by_ref==1 ?*/ + if (data->next.obj) { + *zv = &data->next.obj; + } else { + *zv = NULL; + } +} + +static int unicode_resourcebundle_if_get_current_key(zend_object_iterator *iter, zstr *str_key, uint *str_len, ulong *int_key TSRMLS_DC) +{ + php_resourcebundle_iter *data = iter->data; + + if (data->next.key.str) { + /* dup! */ + str_key->s = estrndup(data->next.key.str, data->next.key.len); + *str_len = data->next.key.len + 1; + return HASH_KEY_IS_STRING; + } else { + *int_key = data->next.key.num - 1; + return HASH_KEY_IS_LONG; + } +} + +static inline void unicode_resourcebundle_if_move_forward_ex(php_resourcebundle_iter *data TSRMLS_DC) +{ + UErrorCode status = U_ZERO_ERROR; + const char *key_str; + UResourceBundle *ures; + + unicode_resourcebundle_if_dtor_ex(data TSRMLS_CC); + + ures = ures_getNextResource(data->rb->ures, NULL, &status); + if (U_SUCCESS(status)) { + ++data->next.key.num; + + MAKE_STD_ZVAL(data->next.obj); + Z_TYPE_P(data->next.obj) = IS_OBJECT; + Z_OBJVAL_P(data->next.obj) = unicode_resourcebundle_create_object_ex(data->rb->zo.ce, NULL, ures TSRMLS_CC); + + if ((key_str = ures_getKey(ures))) { + data->next.key.str = estrndup(key_str, data->next.key.len = strlen(key_str)); + } else { + data->next.key.str = NULL; + } + } +} + +static void unicode_resourcebundle_if_move_forward(zend_object_iterator *iter TSRMLS_DC) +{ + php_resourcebundle_iter *data = iter->data; + + unicode_resourcebundle_if_move_forward_ex(data TSRMLS_CC); +} + +static void unicode_resourcebundle_if_rewind(zend_object_iterator *iter TSRMLS_DC) +{ + php_resourcebundle_iter *data = iter->data; + + ures_resetIterator(data->rb->ures); + + unicode_resourcebundle_if_move_forward_ex(data TSRMLS_CC); +} + +static zend_object_iterator_funcs unicode_resourcebundle_if = { + unicode_resourcebundle_if_dtor, /* release all resources associated with this iterator instance */ + unicode_resourcebundle_if_valid, /* check for end of iteration (FAILURE or SUCCESS if data is valid) */ + unicode_resourecbundle_if_get_current_data, /* fetch the item data for the current element */ + unicode_resourcebundle_if_get_current_key, /* fetch the key for the current element (return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG) (optional, may be NULL) */ + unicode_resourcebundle_if_move_forward, /* step forwards to next element */ + unicode_resourcebundle_if_rewind, /* rewind to start of data (optional, may be NULL) */ + NULL, /* invalidate current value/key (optional, may be NULL) */ +}; + +static zend_object_iterator *unicode_resourcebundle_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) +{ + php_resourcebundle_iter *data = ecalloc(1, sizeof(*data)); + + ZVAL_ADDREF(object); + data->zv = object; + data->rb = zend_object_store_get_object(object TSRMLS_CC); + data->next.ref = by_ref; + + data->it.data = data; + data->it.funcs = &unicode_resourcebundle_if; + + return (zend_object_iterator *) data; +} +/* }}} */ + +/* {{{ unicode_resourcebundle_factory */ +static int unicode_resourcebundle_factory(INTERNAL_FUNCTION_PARAMETERS) +{ + zval *package = NULL, *locale = NULL; + UErrorCode status = U_ZERO_ERROR; + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z/!z/!", &package, &locale)) { + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + if (rb->ures) { + ures_close(rb->ures); + } + /* UTODO: use fs encoding */ + if (package) { + switch (Z_TYPE_P(package)) { + case IS_NULL: + case IS_STRING: + case IS_UNICODE: + break; + default: + convert_to_string(package); + break; + } + } + if (locale) { + switch (Z_TYPE_P(locale)) { + case IS_NULL: + case IS_STRING: + break; + default: + convert_to_string(locale); + break; + } + } + + if (package && Z_TYPE_P(package) == IS_UNICODE) { + rb->ures = ures_openU(Z_USTRVAL_P(package), locale ? Z_STRVAL_P(locale) : NULL, &status); + } else { + rb->ures = ures_open(package ? Z_STRVAL_P(package) : NULL, locale ? Z_STRVAL_P(locale) : NULL, &status); + } + + if (U_SUCCESS(status)) { + zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("warning"), status TSRMLS_CC); + return SUCCESS; + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to open resource bundle '%s' for '%s' locale", package && Z_STRVAL_P(package) ? Z_STRVAL_P(package) : "root", locale && Z_STRVAL_P(locale) ? *Z_STRVAL_P(locale) ? Z_STRVAL_P(locale) : "default" : "root"); + } + } + return FAILURE; +} +/* }}} */ + +/* {{{ proto void ResourceBundle::__construct([string package[, string locale]]) + Create a new ResourceBundle object */ +static PHP_METHOD(ResourceBundle, __construct) +{ + php_set_error_handling(EH_THROW, NULL TSRMLS_CC); + unicode_resourcebundle_factory(INTERNAL_FUNCTION_PARAM_PASSTHRU); + php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); +} +/* }}} */ + +/* {{{ proto static ResourceBundle ResourceBundle::factory([string package[, string locale]]) + Create a new ResourceBundle object */ +static PHP_METHOD(ResourceBundle, factory) +{ + php_set_error_handling(EH_THROW, NULL TSRMLS_CC); + getThis() = return_value; + object_init_ex(getThis(), unicode_resourcebundle_ce); + if (SUCCESS != unicode_resourcebundle_factory(INTERNAL_FUNCTION_PARAM_PASSTHRU)) { + zval_ptr_dtor(&getThis()); + RETVAL_NULL(); + } + php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); +} +/* }}} */ + +/* {{{ proto bool ResourceBundle::open([string package[, string locale]) + Open another ResourceBundle */ +static PHP_METHOD(ResourceBundle, open) +{ + RETURN_BOOL(SUCCESS == unicode_resourcebundle_factory(INTERNAL_FUNCTION_PARAM_PASSTHRU)); +} +/* }}} */ + +/* {{{ proto string ResourceBundle::getVersion(void) + Get ResourceBundle version */ +static PHP_METHOD(ResourceBundle, getVersion) +{ + UVersionInfo version_ptr = {0}; + char version_str[U_MAX_VERSION_STRING_LENGTH] = {0}; + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ""); + + IF_RB_INIT(rb) { + ures_getVersion(rb->ures, version_ptr); + u_versionToString(version_ptr, version_str); + RETURN_ASCII_STRING(version_str, ZSTR_DUPLICATE); + } +} +/* }}} */ + +/* {{{ proto int ResourceBundle::getType(void) + Get the type of the RespourceBundle */ +static PHP_METHOD(ResourceBundle, getType) +{ + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ""); + + IF_RB_INIT(rb) { + RETVAL_LONG(ures_getType(rb->ures)); + } +} +/* }}} */ + +/* {{{ proto string ResourceBundle::getLocale([int locale_type = U::LOC_VALID_LOCALE]) + Get ResourceBundle locale */ +static PHP_METHOD(ResourceBundle, getLocale) +{ + UErrorCode dummy; + long type = ULOC_VALID_LOCALE; + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &type); + + IF_RB_INIT(rb) { + RETURN_ASCII_STRING(ures_getLocaleByType(rb->ures, type, &dummy), ZSTR_DUPLICATE); + } +} +/* }}} */ + +/* {{{ proto string ResourceBundle::getKey() + Get any key associated eith this ResourceBundle */ +static PHP_METHOD(ResourceBundle, getKey) +{ + const char *key; + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ""); + + IF_RB_INIT(rb) { + if ((key = ures_getKey(rb->ures))) { + RETVAL_STRING(key, ZSTR_DUPLICATE); + } + } +} +/* }}} */ + +/* {{{ proto string ResourceBundle::getString() + Returns the contents of a string ResourceBundle */ +static PHP_METHOD(ResourceBundle, getString) +{ + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ""); + + IF_RB_INIT(rb) { + IF_RB_TYPE(rb, URES_STRING) { + _extract_string(rb->ures, return_value TSRMLS_CC); + } + } +} +/* }}} */ + +/* {{{ proto string ResourceBundle::getStringByIndex(int index) + Returns the contents of the string at index index in the ResourceBundle */ +static PHP_METHOD(ResourceBundle, getStringByIndex) +{ + UErrorCode status = U_ZERO_ERROR; + const UChar *str_buf; + int32_t str_len; + long index; + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index)) { + IF_RB_INIT(rb) { + str_buf = ures_getStringByIndex(rb->ures, index, &str_len, &status); + IF_RB_SUCCESS(status) { + RETURN_UNICODEL(str_buf, str_len, ZSTR_DUPLICATE); + } + } + } +} +/* }}} */ + +/* {{{ proto string ResourceBundle::getStringByKey(string key) + Returns the contents of the string identified by key in the ResourceBundle */ +static PHP_METHOD(ResourceBundle, getStringByKey) +{ + UErrorCode status = U_ZERO_ERROR; + const UChar *str_buf; + int32_t str_len; + char *key_str; + int key_len; + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key_str, &key_len)) { + IF_RB_INIT(rb) { + str_buf = ures_getStringByKey(rb->ures, key_str, &str_len, &status); + IF_RB_SUCCESS(status) { + RETURN_UNICODEL(str_buf, str_len, ZSTR_DUPLICATE); + } + } + } +} +/* }}} */ + +/* {{{ proto binary ResourceBundle::getBinary(void) + Get the binary contents of the ResourceBundle of type BINARY */ +static PHP_METHOD(ResourceBundle, getBinary) +{ + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ""); + + IF_RB_INIT(rb) { + IF_RB_TYPE(rb, URES_BINARY) { + _extract_binary(rb->ures, return_value TSRMLS_CC); + } + } +} +/* }}} */ + +/* {{{ proto int ResourceBundle::getInt(void) + Get the integer value of a ResourceBundle of type INT */ +static PHP_METHOD(ResourceBundle, getInt) +{ + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ""); + + IF_RB_INIT(rb) { + IF_RB_TYPE(rb, URES_INT) { + _extract_int(rb->ures, return_value TSRMLS_CC); + } + } +} +/* }}} */ + +/* {{{ proto array ResourceBundle::getArray(void) + Get an array of the contents of the ResourceBundle of type ARRAY, TABLE or INT_VECTOR*/ +static PHP_METHOD(ResourceBundle, getArray) +{ + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ""); + + IF_RB_INIT(rb) { + _extract(rb->ures, return_value, URES_INT_VECTOR|URES_ARRAY|URES_TABLE TSRMLS_CC); + } +} +/* }}} */ + +/* {{{ proto ResourceBundle ResourceBundle::getByIndex(int index) + Get a child ResourceBundle by its index */ +static PHP_METHOD(ResourceBundle, getByIndex) +{ + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *ures; + long index; + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + php_set_error_handling(EH_THROW, NULL TSRMLS_CC); + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index)) { + IF_RB_INIT(rb) { + ures = ures_getByIndex(rb->ures, index, NULL, &status); + IF_RB_SUCCESS(status) { + Z_TYPE_P(return_value) = IS_OBJECT; + Z_OBJVAL_P(return_value) = unicode_resourcebundle_create_object_ex(Z_OBJCE_P(getThis()), NULL, ures TSRMLS_CC); + } + } + } + php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); +} +/* }}} */ + +/* {{{ proto ResourceBundle ResourceBundle::getByKey(string key) + Get a child ResourceBundle by its key */ +static PHP_METHOD(ResourceBundle, getByKey) +{ + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *ures; + char *key_str; + int key_len; + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + php_set_error_handling(EH_THROW, NULL TSRMLS_CC); + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key_str, &key_len)) { + IF_RB_INIT(rb) { + ures = ures_getByKey(rb->ures, key_str, NULL, &status); + IF_RB_SUCCESS(status) { + Z_TYPE_P(return_value) = IS_OBJECT; + Z_OBJVAL_P(return_value) = unicode_resourcebundle_create_object_ex(Z_OBJCE_P(getThis()), NULL, ures TSRMLS_CC); + } + } + } + php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); +} +/* }}} */ + +/* {{{ proto mixed ResourceBundle::get() + Get ResourceBundles contents dependent on its type */ +static PHP_METHOD(ResourceBundle, get) +{ + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ""); + + IF_RB_INIT(rb) { + _extract(rb->ures, return_value, _EXTRACT_ALL TSRMLS_CC); + } +} +/* }}} */ + +/* {{{ proto int ResourceBundle::count(void) */ +static PHP_METHOD(ResourceBundle, count) +{ + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ""); + + IF_RB_INIT(rb) { + RETVAL_LONG(ures_getSize(rb->ures)); + } +} +/* }}} */ + +/* {{{ proto string ResourceBundle::getCat(int section, int message[, string default]) + Get a string of a message catalog located in a ResourceBundle */ +static PHP_METHOD(ResourceBundle, getCat) +{ + UErrorCode status = U_ZERO_ERROR; + const UChar *real_str; + int32_t real_len; + UChar *default_str = (UChar *) "\0\0"; + int default_len = 0; + long sect_id, msg_id; + php_resourcebundle *rb = zend_object_store_get_object(getThis() TSRMLS_CC); + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll|u", §_id, &msg_id, &default_str, &default_len)) { + RETURN_FALSE; + } + + IF_RB_INIT(rb) { + real_len = default_len; + real_str = u_catgets(rb->ures, sect_id, msg_id, default_str, &real_len, &status); + IF_RB_SUCCESS(status) { + if (real_str) { + RETURN_UNICODEL(real_str, real_len, ZSTR_DUPLICATE); + } + } + } + + if (default_str) { + RETURN_UNICODEL(default_str, default_len, ZSTR_DUPLICATE); + } else { + RETURN_EMPTY_UNICODE(); + } +} +/* }}} */ + +/* # */ + +/* {{{ php_init_resourcebundle */ +void php_init_resourcebundle(TSRMLS_D) +{ + zend_class_entry ce; + + memset(&ce, 0, sizeof(ce)); + INIT_CLASS_ENTRY(ce, "ResourceBundle", unicode_resourcebundle_fe); + ce.create_object = unicode_resourcebundle_create_object; + ce.get_iterator = unicode_resourcebundle_get_iterator; + + unicode_resourcebundle_ce = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC); + /* TODO: implements Countable */ + memcpy(&unicode_resourcebundle_oh, zend_get_std_object_handlers(), sizeof(unicode_resourcebundle_oh)); + unicode_resourcebundle_oh.clone_obj = NULL; + unicode_resourcebundle_oh.unset_dimension = NULL; + unicode_resourcebundle_oh.write_dimension = NULL; + unicode_resourcebundle_oh.read_dimension = unicode_resourcebundle_read_dimension; + unicode_resourcebundle_oh.has_dimension = unicode_resourcebundle_has_dimension; + unicode_resourcebundle_oh.cast_object = unicode_resourcebundle_cast_object; + unicode_resourcebundle_oh.get_properties = unicode_resourcebundle_get_properties; + + /* any warning code of ures_open() */ + zend_declare_property_long(unicode_resourcebundle_ce, ZEND_STRL("warning"), U_ZERO_ERROR, ZEND_ACC_PUBLIC TSRMLS_CC); + + /* type constants are in constants.c*/ +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ Index: ext/unicode/unicode.c =================================================================== RCS file: /repository/php-src/ext/unicode/unicode.c,v retrieving revision 1.42 diff -u -p -d -r1.42 unicode.c --- ext/unicode/unicode.c 21 Sep 2006 19:30:33 -0000 1.42 +++ ext/unicode/unicode.c 14 Dec 2006 13:15:52 -0000 @@ -399,6 +399,7 @@ PHP_MINIT_FUNCTION(unicode) { php_register_unicode_iterators(TSRMLS_C); php_init_collation(TSRMLS_C); + php_init_resourcebundle(TSRMLS_C); php_register_unicode_constants(TSRMLS_C); return SUCCESS; Index: ext/unicode/tests/resourcebundle_001.phpt =================================================================== RCS file: ext/unicode/tests/resourcebundle_001.phpt diff -N ext/unicode/tests/resourcebundle_001.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ext/unicode/tests/resourcebundle_001.phpt 14 Dec 2006 13:15:52 -0000 @@ -0,0 +1,65 @@ +--TEST-- +Unicode: ResourceBundle +--FILE-- +<?php +$path = dirname(__FILE__)."/test"; +$rb = new ResourceBundle(dirname(__FILE__)."/test"); +var_dump($rb->getByIndex(0)->getString()); +var_dump($rb->getStringByIndex(0)); +var_dump($rb->getByKey("serial")->getArray()); +echo "--\n"; +foreach (new ResourceBundle($path) as $k => $r) var_dump($k, $r->getKey(), $r->get()); +?> +--EXPECT-- +unicode(5) "value" +unicode(5) "value" +array(3) { + [0]=> + int(1) + [1]=> + int(3) + [2]=> + int(5) +} +-- +string(4) "data" +string(4) "data" +unicode(5) "value" +string(5) "greet" +string(5) "greet" +array(7) { + ["1%4"]=> + unicode(13) "Good morning." + ["1%5"]=> + unicode(15) "Good afternoon." + ["1%7"]=> + unicode(13) "Good evening." + ["1%8"]=> + unicode(11) "Good night." + ["4%14"]=> + unicode(7) "Please " + ["4%19"]=> + unicode(10) "Thank you." + ["4%20"]=> + unicode(10) "Sincerely," +} +string(4) "list" +string(4) "list" +array(3) { + ["one"]=> + int(1) + ["three"]=> + string(1) "4" + ["two"]=> + unicode(1) "2" +} +string(6) "serial" +string(6) "serial" +array(3) { + [0]=> + int(1) + [1]=> + int(3) + [2]=> + int(5) +} Index: ext/unicode/tests/test_root.res =================================================================== RCS file: ext/unicode/tests/test_root.res diff -N ext/unicode/tests/test_root.res Binary files /dev/null and test_root.res differ Index: ext/unicode/tests/test_root.txt =================================================================== RCS file: ext/unicode/tests/test_root.txt diff -N ext/unicode/tests/test_root.txt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ext/unicode/tests/test_root.txt 14 Dec 2006 13:15:52 -0000 @@ -0,0 +1,18 @@ +root { + data:string { "value" } + serial:intvector { 1,3,5 } + list { + one:int { 1 } + two { 2 } + three:binary { 34 } + } + greet { + 1%4 { "Good morning." } + 1%5 { "Good afternoon." } + 1%7 { "Good evening." } + 1%8 { "Good night." } + 4%14 { "Please " } + 4%19 { "Thank you." } + 4%20 { "Sincerely," } + } +}
-- PHP Unicode & I18N Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php