PageRenderTime 44ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/release/src/router/php/ext/intl/resourcebundle/resourcebundle_class.c

https://gitlab.com/envieidoc/tomato
C | 455 lines | 290 code | 76 blank | 89 comment | 46 complexity | df8ba45f9448d8c1fb1cbb17c0db2aa2 MD5 | raw file
  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. #include <stdlib.h>
  17. #include <unicode/ures.h>
  18. #include <unicode/uenum.h>
  19. #include <zend.h>
  20. #include <Zend/zend_exceptions.h>
  21. #include <Zend/zend_interfaces.h>
  22. #include <php.h>
  23. #include "php_intl.h"
  24. #include "intl_data.h"
  25. #include "resourcebundle/resourcebundle.h"
  26. #include "resourcebundle/resourcebundle_iterator.h"
  27. #include "resourcebundle/resourcebundle_class.h"
  28. zend_class_entry *ResourceBundle_ce_ptr = NULL;
  29. static zend_object_handlers ResourceBundle_object_handlers;
  30. /* {{{ ResourceBundle_object_dtor */
  31. static void ResourceBundle_object_destroy( void *object, zend_object_handle handle TSRMLS_DC )
  32. {
  33. ResourceBundle_object *rb = (ResourceBundle_object *) object;
  34. // only free local errors
  35. intl_error_reset( INTL_DATA_ERROR_P(rb) TSRMLS_CC );
  36. if (rb->me) {
  37. ures_close( rb->me );
  38. }
  39. if (rb->child) {
  40. ures_close( rb->child );
  41. }
  42. zend_object_std_dtor( object TSRMLS_CC );
  43. efree(object);
  44. }
  45. /* }}} */
  46. /* {{{ ResourceBundle_object_create */
  47. static zend_object_value ResourceBundle_object_create( zend_class_entry *ce TSRMLS_DC )
  48. {
  49. zend_object_value retval;
  50. ResourceBundle_object *rb;
  51. rb = ecalloc( 1, sizeof(ResourceBundle_object) );
  52. zend_object_std_init( (zend_object *) rb, ce TSRMLS_CC );
  53. object_properties_init((zend_object *) rb, ce);
  54. intl_error_init( INTL_DATA_ERROR_P(rb) TSRMLS_CC );
  55. rb->me = NULL;
  56. rb->child = NULL;
  57. retval.handlers = &ResourceBundle_object_handlers;
  58. retval.handle = zend_objects_store_put( rb, ResourceBundle_object_destroy, NULL, NULL TSRMLS_CC );
  59. return retval;
  60. }
  61. /* }}} */
  62. /* {{{ ResourceBundle_ctor */
  63. static void resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS)
  64. {
  65. const char *bundlename;
  66. int bundlename_len = 0;
  67. const char *locale;
  68. int locale_len = 0;
  69. zend_bool fallback = 1;
  70. zval *object = return_value;
  71. ResourceBundle_object *rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC);
  72. intl_error_reset( NULL TSRMLS_CC );
  73. if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s!s!|b",
  74. &locale, &locale_len, &bundlename, &bundlename_len, &fallback ) == FAILURE )
  75. {
  76. intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
  77. "resourcebundle_ctor: unable to parse input parameters", 0 TSRMLS_CC );
  78. zval_dtor( return_value );
  79. RETURN_NULL();
  80. }
  81. INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value);
  82. if (locale == NULL) {
  83. locale = intl_locale_get_default(TSRMLS_C);
  84. }
  85. if (fallback) {
  86. rb->me = ures_open(bundlename, locale, &INTL_DATA_ERROR_CODE(rb));
  87. } else {
  88. rb->me = ures_openDirect(bundlename, locale, &INTL_DATA_ERROR_CODE(rb));
  89. }
  90. INTL_CTOR_CHECK_STATUS(rb, "resourcebundle_ctor: Cannot load libICU resource bundle");
  91. if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING ||
  92. INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) {
  93. char *pbuf;
  94. intl_errors_set_code(NULL, INTL_DATA_ERROR_CODE(rb) TSRMLS_CC);
  95. spprintf(&pbuf, 0, "resourcebundle_ctor: Cannot load libICU resource "
  96. "'%s' without fallback from %s to %s",
  97. bundlename ? bundlename : "(default data)", locale,
  98. ures_getLocaleByType(
  99. rb->me, ULOC_ACTUAL_LOCALE, &INTL_DATA_ERROR_CODE(rb)));
  100. intl_errors_set_custom_msg(INTL_DATA_ERROR_P(rb), pbuf, 1 TSRMLS_CC);
  101. efree(pbuf);
  102. zval_dtor(return_value);
  103. RETURN_NULL();
  104. }
  105. }
  106. /* }}} */
  107. /* {{{ arginfo_resourcebundle__construct */
  108. ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle___construct, 0, 0, 2 )
  109. ZEND_ARG_INFO( 0, locale )
  110. ZEND_ARG_INFO( 0, bundlename )
  111. ZEND_ARG_INFO( 0, fallback )
  112. ZEND_END_ARG_INFO()
  113. /* }}} */
  114. /* {{{ proto void ResourceBundle::__construct( string $locale [, string $bundlename [, bool $fallback = true ]] )
  115. * ResourceBundle object constructor
  116. */
  117. PHP_METHOD( ResourceBundle, __construct )
  118. {
  119. return_value = getThis();
  120. resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  121. }
  122. /* }}} */
  123. /* {{{ proto ResourceBundle ResourceBundle::create( string $locale [, string $bundlename [, bool $fallback = true ]] )
  124. proto ResourceBundle resourcebundle_create( string $locale [, string $bundlename [, bool $fallback = true ]] )
  125. */
  126. PHP_FUNCTION( resourcebundle_create )
  127. {
  128. object_init_ex( return_value, ResourceBundle_ce_ptr );
  129. resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  130. }
  131. /* }}} */
  132. /* {{{ resourcebundle_array_fetch */
  133. static void resourcebundle_array_fetch(zval *object, zval *offset, zval *return_value, int fallback TSRMLS_DC)
  134. {
  135. int32_t meindex = 0;
  136. char * mekey = NULL;
  137. zend_bool is_numeric = 0;
  138. char *pbuf;
  139. ResourceBundle_object *rb;
  140. intl_error_reset( NULL TSRMLS_CC );
  141. RESOURCEBUNDLE_METHOD_FETCH_OBJECT;
  142. if(Z_TYPE_P(offset) == IS_LONG) {
  143. is_numeric = 1;
  144. meindex = Z_LVAL_P(offset);
  145. rb->child = ures_getByIndex( rb->me, meindex, rb->child, &INTL_DATA_ERROR_CODE(rb) );
  146. } else if(Z_TYPE_P(offset) == IS_STRING) {
  147. mekey = Z_STRVAL_P(offset);
  148. rb->child = ures_getByKey(rb->me, mekey, rb->child, &INTL_DATA_ERROR_CODE(rb) );
  149. } else {
  150. intl_errors_set(INTL_DATA_ERROR_P(rb), U_ILLEGAL_ARGUMENT_ERROR,
  151. "resourcebundle_get: index should be integer or string", 0 TSRMLS_CC);
  152. RETURN_NULL();
  153. }
  154. intl_error_set_code( NULL, INTL_DATA_ERROR_CODE(rb) TSRMLS_CC );
  155. if (U_FAILURE(INTL_DATA_ERROR_CODE(rb))) {
  156. if (is_numeric) {
  157. spprintf( &pbuf, 0, "Cannot load resource element %d", meindex );
  158. } else {
  159. spprintf( &pbuf, 0, "Cannot load resource element '%s'", mekey );
  160. }
  161. intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 TSRMLS_CC );
  162. efree(pbuf);
  163. RETURN_NULL();
  164. }
  165. if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING || INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) {
  166. UErrorCode icuerror;
  167. const char * locale = ures_getLocaleByType( rb->me, ULOC_ACTUAL_LOCALE, &icuerror );
  168. if (is_numeric) {
  169. spprintf( &pbuf, 0, "Cannot load element %d without fallback from to %s", meindex, locale );
  170. } else {
  171. spprintf( &pbuf, 0, "Cannot load element '%s' without fallback from to %s", mekey, locale );
  172. }
  173. intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 TSRMLS_CC );
  174. efree(pbuf);
  175. RETURN_NULL();
  176. }
  177. resourcebundle_extract_value( return_value, rb TSRMLS_CC );
  178. }
  179. /* }}} */
  180. /* {{{ resourcebundle_array_get */
  181. zval *resourcebundle_array_get(zval *object, zval *offset, int type TSRMLS_DC)
  182. {
  183. zval *retval;
  184. if(offset == NULL) {
  185. php_error( E_ERROR, "Cannot apply [] to ResourceBundle object" );
  186. }
  187. MAKE_STD_ZVAL(retval);
  188. resourcebundle_array_fetch(object, offset, retval, 1 TSRMLS_CC);
  189. Z_DELREF_P(retval);
  190. return retval;
  191. }
  192. /* }}} */
  193. /* {{{ arginfo_resourcebundle_get */
  194. ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_get, 0, 0, 1 )
  195. ZEND_ARG_INFO( 0, index )
  196. ZEND_ARG_INFO( 0, fallback )
  197. ZEND_END_ARG_INFO()
  198. /* }}} */
  199. /* {{{ proto mixed ResourceBundle::get( integer|string $resindex [, bool $fallback = true ] )
  200. * proto mixed resourcebundle_get( ResourceBundle $rb, integer|string $resindex [, bool $fallback = true ] )
  201. * Get resource identified by numerical index or key name.
  202. */
  203. PHP_FUNCTION( resourcebundle_get )
  204. {
  205. zend_bool fallback = 1;
  206. zval * offset;
  207. zval * object;
  208. if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz|b", &object, ResourceBundle_ce_ptr, &offset, &fallback ) == FAILURE) {
  209. intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
  210. "resourcebundle_get: unable to parse input params", 0 TSRMLS_CC);
  211. RETURN_FALSE;
  212. }
  213. resourcebundle_array_fetch(object, offset, return_value, fallback TSRMLS_CC);
  214. }
  215. /* }}} */
  216. /* {{{ resourcebundle_array_count */
  217. int resourcebundle_array_count(zval *object, long *count TSRMLS_DC)
  218. {
  219. ResourceBundle_object *rb;
  220. RESOURCEBUNDLE_METHOD_FETCH_OBJECT_NO_CHECK;
  221. if (rb->me == NULL) {
  222. intl_errors_set(&rb->error, U_ILLEGAL_ARGUMENT_ERROR,
  223. "Found unconstructed ResourceBundle", 0 TSRMLS_CC);
  224. return 0;
  225. }
  226. *count = ures_getSize( rb->me );
  227. return SUCCESS;
  228. }
  229. /* }}} */
  230. /* {{{ arginfo_resourcebundle_count */
  231. ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_count, 0, 0, 0 )
  232. ZEND_END_ARG_INFO()
  233. /* }}} */
  234. /* {{{ proto int ResourceBundle::count()
  235. * proto int resourcebundle_count( ResourceBundle $bundle )
  236. * Get resources count
  237. */
  238. PHP_FUNCTION( resourcebundle_count )
  239. {
  240. int32_t len;
  241. RESOURCEBUNDLE_METHOD_INIT_VARS;
  242. if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, ResourceBundle_ce_ptr ) == FAILURE ) {
  243. intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
  244. "resourcebundle_count: unable to parse input params", 0 TSRMLS_CC);
  245. RETURN_FALSE;
  246. }
  247. RESOURCEBUNDLE_METHOD_FETCH_OBJECT;
  248. len = ures_getSize( rb->me );
  249. RETURN_LONG( len );
  250. }
  251. /* {{{ arginfo_resourcebundle_getlocales */
  252. ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_getlocales, 0, 0, 1 )
  253. ZEND_ARG_INFO( 0, bundlename )
  254. ZEND_END_ARG_INFO()
  255. /* }}} */
  256. /* {{{ proto array ResourceBundle::getLocales( string $bundlename )
  257. * proto array resourcebundle_locales( string $bundlename )
  258. * Get available locales from ResourceBundle name
  259. */
  260. PHP_FUNCTION( resourcebundle_locales )
  261. {
  262. char * bundlename;
  263. int bundlename_len = 0;
  264. const char * entry;
  265. int entry_len;
  266. UEnumeration *icuenum;
  267. UErrorCode icuerror = U_ZERO_ERROR;
  268. intl_errors_reset( NULL TSRMLS_CC );
  269. if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &bundlename, &bundlename_len ) == FAILURE )
  270. {
  271. intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
  272. "resourcebundle_locales: unable to parse input params", 0 TSRMLS_CC);
  273. RETURN_FALSE;
  274. }
  275. if(bundlename_len == 0) {
  276. // fetch default locales list
  277. bundlename = NULL;
  278. }
  279. icuenum = ures_openAvailableLocales( bundlename, &icuerror );
  280. INTL_CHECK_STATUS(icuerror, "Cannot fetch locales list");
  281. uenum_reset( icuenum, &icuerror );
  282. INTL_CHECK_STATUS(icuerror, "Cannot iterate locales list");
  283. array_init( return_value );
  284. while ((entry = uenum_next( icuenum, &entry_len, &icuerror ))) {
  285. add_next_index_stringl( return_value, (char *) entry, entry_len, 1 );
  286. }
  287. uenum_close( icuenum );
  288. }
  289. /* }}} */
  290. /* {{{ arginfo_resourcebundle_get_error_code */
  291. ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_get_error_code, 0, 0, 0 )
  292. ZEND_END_ARG_INFO()
  293. /* }}} */
  294. /* {{{ proto string ResourceBundle::getErrorCode( )
  295. * proto string resourcebundle_get_error_code( ResourceBundle $bundle )
  296. * Get text description for ResourceBundle's last error code.
  297. */
  298. PHP_FUNCTION( resourcebundle_get_error_code )
  299. {
  300. RESOURCEBUNDLE_METHOD_INIT_VARS;
  301. if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
  302. &object, ResourceBundle_ce_ptr ) == FAILURE )
  303. {
  304. intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
  305. "resourcebundle_get_error_code: unable to parse input params", 0 TSRMLS_CC );
  306. RETURN_FALSE;
  307. }
  308. rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC );
  309. RETURN_LONG(INTL_DATA_ERROR_CODE(rb));
  310. }
  311. /* }}} */
  312. /* {{{ arginfo_resourcebundle_get_error_message */
  313. ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_get_error_message, 0, 0, 0 )
  314. ZEND_END_ARG_INFO()
  315. /* }}} */
  316. /* {{{ proto string ResourceBundle::getErrorMessage( )
  317. * proto string resourcebundle_get_error_message( ResourceBundle $bundle )
  318. * Get text description for ResourceBundle's last error.
  319. */
  320. PHP_FUNCTION( resourcebundle_get_error_message )
  321. {
  322. char* message = NULL;
  323. RESOURCEBUNDLE_METHOD_INIT_VARS;
  324. if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
  325. &object, ResourceBundle_ce_ptr ) == FAILURE )
  326. {
  327. intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
  328. "resourcebundle_get_error_message: unable to parse input params", 0 TSRMLS_CC );
  329. RETURN_FALSE;
  330. }
  331. rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC );
  332. message = (char *)intl_error_get_message(INTL_DATA_ERROR_P(rb) TSRMLS_CC);
  333. RETURN_STRING(message, 0);
  334. }
  335. /* }}} */
  336. /* {{{ ResourceBundle_class_functions
  337. * Every 'ResourceBundle' class method has an entry in this table
  338. */
  339. static zend_function_entry ResourceBundle_class_functions[] = {
  340. PHP_ME( ResourceBundle, __construct, arginfo_resourcebundle___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR )
  341. ZEND_NAMED_ME( create, ZEND_FN( resourcebundle_create ), arginfo_resourcebundle___construct, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
  342. ZEND_NAMED_ME( get, ZEND_FN(resourcebundle_get), arginfo_resourcebundle_get, ZEND_ACC_PUBLIC )
  343. ZEND_NAMED_ME( count, ZEND_FN(resourcebundle_count), arginfo_resourcebundle_count, ZEND_ACC_PUBLIC )
  344. ZEND_NAMED_ME( getLocales, ZEND_FN(resourcebundle_locales), arginfo_resourcebundle_getlocales, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC )
  345. ZEND_NAMED_ME( getErrorCode, ZEND_FN(resourcebundle_get_error_code), arginfo_resourcebundle_get_error_code, ZEND_ACC_PUBLIC )
  346. ZEND_NAMED_ME( getErrorMessage, ZEND_FN(resourcebundle_get_error_message), arginfo_resourcebundle_get_error_message, ZEND_ACC_PUBLIC )
  347. PHP_FE_END
  348. };
  349. /* }}} */
  350. /* {{{ resourcebundle_register_class
  351. * Initialize 'ResourceBundle' class
  352. */
  353. void resourcebundle_register_class( TSRMLS_D )
  354. {
  355. zend_class_entry ce;
  356. INIT_CLASS_ENTRY( ce, "ResourceBundle", ResourceBundle_class_functions );
  357. ce.create_object = ResourceBundle_object_create;
  358. ce.get_iterator = resourcebundle_get_iterator;
  359. ResourceBundle_ce_ptr = zend_register_internal_class( &ce TSRMLS_CC );
  360. if( !ResourceBundle_ce_ptr )
  361. {
  362. zend_error(E_ERROR, "Failed to register ResourceBundle class");
  363. return;
  364. }
  365. ResourceBundle_object_handlers = std_object_handlers;
  366. ResourceBundle_object_handlers.clone_obj = NULL; /* ICU ResourceBundle has no clone implementation */
  367. ResourceBundle_object_handlers.read_dimension = resourcebundle_array_get;
  368. ResourceBundle_object_handlers.count_elements = resourcebundle_array_count;
  369. zend_class_implements(ResourceBundle_ce_ptr TSRMLS_CC, 1, zend_ce_traversable);
  370. }
  371. /* }}} */
  372. /*
  373. * Local variables:
  374. * tab-width: 4
  375. * c-basic-offset: 4
  376. * End:
  377. * vim600: noet sw=4 ts=4 fdm=marker
  378. * vim<600: noet sw=4 ts=4
  379. */