Annotation of embedaddon/php/ext/intl/resourcebundle/resourcebundle_class.c, revision 1.1.1.3
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: {
165: int32_t meindex;
166: char * mekey;
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>