transliterator_class.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  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: Gustavo Lopes <cataphract@php.net> |
  14. +----------------------------------------------------------------------+
  15. */
  16. #include "transliterator_class.h"
  17. #include "php_intl.h"
  18. #include "transliterator_methods.h"
  19. #include "intl_error.h"
  20. #include "intl_convert.h"
  21. #include "intl_data.h"
  22. #include <unicode/utrans.h>
  23. zend_class_entry *Transliterator_ce_ptr = NULL;
  24. zend_object_handlers Transliterator_handlers;
  25. /* {{{ int transliterator_object_construct( zval *object, UTransliterator *utrans, UErrorCode *status TSRMLS_DC )
  26. * Initialize internals of Transliterator_object.
  27. */
  28. int transliterator_object_construct( zval *object,
  29. UTransliterator *utrans,
  30. UErrorCode *status TSRMLS_DC )
  31. {
  32. const UChar *ustr_id;
  33. int32_t ustr_id_len;
  34. char *str_id;
  35. int str_id_len;
  36. Transliterator_object *to;
  37. TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK;
  38. assert( to->utrans == NULL );
  39. /* this assignment must happen before any return with failure because the
  40. * caller relies on it always being made (so it can just destroy the object
  41. * to close the transliterator) */
  42. to->utrans = utrans;
  43. ustr_id = utrans_getUnicodeID( utrans, &ustr_id_len );
  44. intl_convert_utf16_to_utf8( &str_id, &str_id_len, ustr_id, (int ) ustr_id_len, status );
  45. if( U_FAILURE( *status ) )
  46. {
  47. return FAILURE;
  48. }
  49. zend_update_property_stringl( Transliterator_ce_ptr, object,
  50. "id", sizeof( "id" ) - 1, str_id, str_id_len TSRMLS_CC );
  51. efree( str_id );
  52. return SUCCESS;
  53. }
  54. /* }}} */
  55. /*
  56. * Auxiliary functions needed by objects of 'Transliterator' class
  57. */
  58. /* {{{ void transliterator_object_init( Transliterator_object* to )
  59. * Initialize internals of Transliterator_object.
  60. */
  61. static void transliterator_object_init( Transliterator_object* to TSRMLS_DC )
  62. {
  63. if( !to )
  64. return;
  65. intl_error_init( TRANSLITERATOR_ERROR_P( to ) TSRMLS_CC );
  66. }
  67. /* }}} */
  68. /* {{{ void transliterator_object_destroy( Transliterator_object* to )
  69. * Clean up mem allocted by internals of Transliterator_object
  70. */
  71. static void transliterator_object_destroy( Transliterator_object* to TSRMLS_DC )
  72. {
  73. if( !to )
  74. return;
  75. if( to->utrans )
  76. {
  77. utrans_close( to->utrans );
  78. to->utrans = NULL;
  79. }
  80. intl_error_reset( TRANSLITERATOR_ERROR_P( to ) TSRMLS_CC );
  81. }
  82. /* }}} */
  83. /* {{{ Transliterator_objects_dtor */
  84. static void Transliterator_objects_dtor(
  85. void *object,
  86. zend_object_handle handle TSRMLS_DC )
  87. {
  88. zend_objects_destroy_object( object, handle TSRMLS_CC );
  89. }
  90. /* }}} */
  91. /* {{{ Transliterator_objects_free */
  92. static void Transliterator_objects_free( zend_object *object TSRMLS_DC )
  93. {
  94. Transliterator_object* to = (Transliterator_object*) object;
  95. zend_object_std_dtor( &to->zo TSRMLS_CC );
  96. transliterator_object_destroy( to TSRMLS_CC );
  97. efree( to );
  98. }
  99. /* }}} */
  100. /* {{{ Transliterator_object_create */
  101. static zend_object_value Transliterator_object_create(
  102. zend_class_entry *ce TSRMLS_DC )
  103. {
  104. zend_object_value retval;
  105. Transliterator_object* intern;
  106. intern = ecalloc( 1, sizeof( Transliterator_object ) );
  107. zend_object_std_init( &intern->zo, ce TSRMLS_CC );
  108. #if PHP_VERSION_ID < 50399
  109. zend_hash_copy( intern->zo.properties, &(ce->default_properties ),
  110. (copy_ctor_func_t) zval_add_ref, NULL, sizeof( zval* ) );
  111. #else
  112. object_properties_init( (zend_object*) intern, ce );
  113. #endif
  114. transliterator_object_init( intern TSRMLS_CC );
  115. retval.handle = zend_objects_store_put(
  116. intern,
  117. Transliterator_objects_dtor,
  118. (zend_objects_free_object_storage_t) Transliterator_objects_free,
  119. NULL TSRMLS_CC );
  120. retval.handlers = &Transliterator_handlers;
  121. return retval;
  122. }
  123. /* }}} */
  124. /*
  125. * Object handlers for Transliterator class (and subclasses)
  126. */
  127. /* {{{ clone handler for Transliterator */
  128. static zend_object_value Transliterator_clone_obj( zval *object TSRMLS_DC )
  129. {
  130. Transliterator_object *to_orig,
  131. *to_new;
  132. zend_object_value ret_val;
  133. intl_error_reset( NULL TSRMLS_CC );
  134. to_orig = zend_object_store_get_object( object TSRMLS_CC );
  135. intl_error_reset( INTL_DATA_ERROR_P( to_orig ) TSRMLS_CC );
  136. ret_val = Transliterator_ce_ptr->create_object( Z_OBJCE_P( object ) TSRMLS_CC );
  137. to_new = zend_object_store_get_object_by_handle( ret_val.handle TSRMLS_CC );
  138. zend_objects_clone_members( &to_new->zo, ret_val,
  139. &to_orig->zo, Z_OBJ_HANDLE_P( object ) TSRMLS_CC );
  140. if( to_orig->utrans != NULL )
  141. {
  142. UTransliterator *utrans = NULL;
  143. zval tempz; /* dummy zval to pass to transliterator_object_construct */
  144. /* guaranteed to return NULL if it fails */
  145. utrans = utrans_clone( to_orig->utrans, TRANSLITERATOR_ERROR_CODE_P( to_orig ) );
  146. if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to_orig ) ) )
  147. goto err;
  148. Z_OBJVAL( tempz ) = ret_val;
  149. transliterator_object_construct( &tempz, utrans,
  150. TRANSLITERATOR_ERROR_CODE_P( to_orig ) TSRMLS_CC );
  151. if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to_orig ) ) )
  152. {
  153. char *err_msg;
  154. err:
  155. if( utrans != NULL )
  156. transliterator_object_destroy( to_new TSRMLS_CC );
  157. /* set the error anyway, in case in the future we decide not to
  158. * throw an error. It also helps build the error message */
  159. intl_error_set_code( NULL, INTL_DATA_ERROR_CODE( to_orig ) TSRMLS_CC );
  160. intl_errors_set_custom_msg( TRANSLITERATOR_ERROR_P( to_orig ),
  161. "Could not clone transliterator", 0 TSRMLS_CC );
  162. err_msg = intl_error_get_message( TRANSLITERATOR_ERROR_P( to_orig ) TSRMLS_CC );
  163. php_error_docref( NULL TSRMLS_CC, E_ERROR, "%s", err_msg );
  164. efree( err_msg ); /* if it's changed into a warning */
  165. /* do not destroy tempz; we need to return something */
  166. }
  167. }
  168. else
  169. {
  170. /* We shouldn't have unconstructed objects in the first place */
  171. php_error_docref( NULL TSRMLS_CC, E_WARNING,
  172. "Cloning unconstructed transliterator." );
  173. }
  174. return ret_val;
  175. }
  176. /* }}} */
  177. #if PHP_VERSION_ID >= 50399
  178. # define TRANSLITERATOR_PROPERTY_HANDLER_PROLOG \
  179. zval tmp_member; \
  180. if( Z_TYPE_P( member ) != IS_STRING ) \
  181. { \
  182. tmp_member = *member; \
  183. zval_copy_ctor( &tmp_member ); \
  184. convert_to_string( &tmp_member ); \
  185. member = &tmp_member; \
  186. key = NULL; \
  187. }
  188. #else
  189. # define TRANSLITERATOR_PROPERTY_HANDLER_PROLOG \
  190. zval tmp_member; \
  191. if( Z_TYPE_P( member ) != IS_STRING ) \
  192. { \
  193. tmp_member = *member; \
  194. zval_copy_ctor( &tmp_member ); \
  195. convert_to_string( &tmp_member ); \
  196. member = &tmp_member; \
  197. }
  198. #endif
  199. #define TRANSLITERATOR_PROPERTY_HANDLER_EPILOG \
  200. if( member == &tmp_member ) \
  201. { \
  202. zval_dtor( &tmp_member ); \
  203. }
  204. /* {{{ get_property_ptr_ptr handler */
  205. #if PHP_VERSION_ID < 50399
  206. static zval **Transliterator_get_property_ptr_ptr( zval *object, zval *member TSRMLS_DC )
  207. #else
  208. static zval **Transliterator_get_property_ptr_ptr( zval *object, zval *member, int type,
  209. const struct _zend_literal *key TSRMLS_DC )
  210. #endif
  211. {
  212. zval **retval;
  213. TRANSLITERATOR_PROPERTY_HANDLER_PROLOG;
  214. if(zend_binary_strcmp( "id", sizeof( "id" ) - 1,
  215. Z_STRVAL_P( member ), Z_STRLEN_P( member ) ) == 0 )
  216. {
  217. retval = NULL; /* fallback to read_property */
  218. }
  219. else
  220. {
  221. #if PHP_VERSION_ID < 50399
  222. retval = std_object_handlers.get_property_ptr_ptr( object, member TSRMLS_CC );
  223. #else
  224. retval = std_object_handlers.get_property_ptr_ptr( object, member, type, key TSRMLS_CC );
  225. #endif
  226. }
  227. TRANSLITERATOR_PROPERTY_HANDLER_EPILOG;
  228. return retval;
  229. }
  230. /* }}} */
  231. /* {{{ read_property handler */
  232. #if PHP_VERSION_ID < 50399
  233. static zval *Transliterator_read_property( zval *object, zval *member, int type TSRMLS_DC ) /* {{{ */
  234. #else
  235. static zval *Transliterator_read_property( zval *object, zval *member, int type,
  236. const struct _zend_literal *key TSRMLS_DC ) /* {{{ */
  237. #endif
  238. {
  239. zval *retval;
  240. TRANSLITERATOR_PROPERTY_HANDLER_PROLOG;
  241. if( ( type != BP_VAR_R && type != BP_VAR_IS ) &&
  242. ( zend_binary_strcmp( "id", sizeof( "id" ) - 1,
  243. Z_STRVAL_P( member ), Z_STRLEN_P( member ) ) == 0 ) )
  244. {
  245. php_error_docref0( NULL TSRMLS_CC, E_WARNING, "The property \"id\" is read-only" );
  246. retval = &EG( uninitialized_zval );
  247. }
  248. else
  249. {
  250. #if PHP_VERSION_ID < 50399
  251. retval = std_object_handlers.read_property( object, member, type TSRMLS_CC );
  252. #else
  253. retval = std_object_handlers.read_property( object, member, type, key TSRMLS_CC );
  254. #endif
  255. }
  256. TRANSLITERATOR_PROPERTY_HANDLER_EPILOG;
  257. return retval;
  258. }
  259. /* }}} */
  260. /* {{{ write_property handler */
  261. #if PHP_VERSION_ID < 50399
  262. static void Transliterator_write_property( zval *object, zval *member, zval *value TSRMLS_DC )
  263. #else
  264. static void Transliterator_write_property( zval *object, zval *member, zval *value,
  265. const struct _zend_literal *key TSRMLS_DC )
  266. #endif
  267. {
  268. TRANSLITERATOR_PROPERTY_HANDLER_PROLOG;
  269. if( ( EG( scope ) != Transliterator_ce_ptr ) &&
  270. ( zend_binary_strcmp( "id", sizeof( "id" ) - 1,
  271. Z_STRVAL_P( member ), Z_STRLEN_P( member ) ) == 0 ) )
  272. {
  273. php_error_docref0( NULL TSRMLS_CC, E_WARNING, "The property \"id\" is read-only" );
  274. }
  275. else
  276. {
  277. #if PHP_VERSION_ID < 50399
  278. std_object_handlers.write_property( object, member, value TSRMLS_CC );
  279. #else
  280. std_object_handlers.write_property( object, member, value, key TSRMLS_CC );
  281. #endif
  282. }
  283. TRANSLITERATOR_PROPERTY_HANDLER_EPILOG;
  284. }
  285. /* }}} */
  286. /*
  287. * 'Transliterator' class registration structures & functions
  288. */
  289. /* {{{ Transliterator methods arguments info */
  290. ZEND_BEGIN_ARG_INFO_EX( ainfo_trans_void, 0, 0, 0 )
  291. ZEND_END_ARG_INFO()
  292. ZEND_BEGIN_ARG_INFO_EX( ainfo_trans_create, 0, 0, 1 )
  293. ZEND_ARG_INFO( 0, id )
  294. ZEND_ARG_INFO( 0, direction )
  295. ZEND_END_ARG_INFO()
  296. ZEND_BEGIN_ARG_INFO_EX( ainfo_trans_create_from_rules, 0, 0, 1 )
  297. ZEND_ARG_INFO( 0, rules )
  298. ZEND_ARG_INFO( 0, direction )
  299. ZEND_END_ARG_INFO()
  300. ZEND_BEGIN_ARG_INFO_EX( ainfo_trans_create_inverse, 0, 0, 1 )
  301. ZEND_ARG_OBJ_INFO( 0, orig_trans, Transliterator, 0 )
  302. ZEND_END_ARG_INFO()
  303. ZEND_BEGIN_ARG_INFO_EX( ainfo_trans_me_transliterate, 0, 0, 1 )
  304. ZEND_ARG_INFO( 0, subject )
  305. ZEND_ARG_INFO( 0, start )
  306. ZEND_ARG_INFO( 0, end )
  307. ZEND_END_ARG_INFO()
  308. ZEND_BEGIN_ARG_INFO_EX( ainfo_trans_error, 0, 0, 1 )
  309. ZEND_ARG_OBJ_INFO( 0, trans, Transliterator, 0 )
  310. ZEND_END_ARG_INFO()
  311. /* }}} */
  312. /* {{{ Transliterator_class_functions
  313. * Every 'Transliterator' class method has an entry in this table
  314. */
  315. zend_function_entry Transliterator_class_functions[] = {
  316. PHP_ME( Transliterator, __construct, ainfo_trans_void, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR | ZEND_ACC_FINAL )
  317. PHP_ME_MAPPING( create, transliterator_create, ainfo_trans_create, ZEND_ACC_STATIC |ZEND_ACC_PUBLIC )
  318. PHP_ME_MAPPING( createFromRules,transliterator_create_from_rules, ainfo_trans_create_from_rules, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC )
  319. PHP_ME_MAPPING( createInverse, transliterator_create_inverse, ainfo_trans_void, ZEND_ACC_PUBLIC )
  320. PHP_ME_MAPPING( listIDs, transliterator_list_ids, ainfo_trans_void, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC )
  321. PHP_ME_MAPPING( transliterate, transliterator_transliterate, ainfo_trans_me_transliterate, ZEND_ACC_PUBLIC )
  322. PHP_ME_MAPPING( getErrorCode, transliterator_get_error_code, ainfo_trans_void, ZEND_ACC_PUBLIC )
  323. PHP_ME_MAPPING( getErrorMessage,transliterator_get_error_message, ainfo_trans_void, ZEND_ACC_PUBLIC )
  324. PHP_FE_END
  325. };
  326. /* }}} */
  327. /* {{{ transliterator_register_Transliterator_class
  328. * Initialize 'Transliterator' class
  329. */
  330. void transliterator_register_Transliterator_class( TSRMLS_D )
  331. {
  332. zend_class_entry ce;
  333. /* Create and register 'Transliterator' class. */
  334. INIT_CLASS_ENTRY( ce, "Transliterator", Transliterator_class_functions );
  335. ce.create_object = Transliterator_object_create;
  336. Transliterator_ce_ptr = zend_register_internal_class( &ce TSRMLS_CC );
  337. memcpy( &Transliterator_handlers, zend_get_std_object_handlers(),
  338. sizeof Transliterator_handlers );
  339. Transliterator_handlers.clone_obj = Transliterator_clone_obj;
  340. Transliterator_handlers.get_property_ptr_ptr = Transliterator_get_property_ptr_ptr;
  341. Transliterator_handlers.read_property = Transliterator_read_property;
  342. Transliterator_handlers.write_property = Transliterator_write_property;
  343. /* Declare 'Transliterator' class properties */
  344. if( !Transliterator_ce_ptr )
  345. {
  346. zend_error( E_ERROR,
  347. "Transliterator: attempt to create properties "
  348. "on a non-registered class." );
  349. return;
  350. }
  351. zend_declare_property_null( Transliterator_ce_ptr,
  352. "id", sizeof( "id" ) - 1, ZEND_ACC_PUBLIC TSRMLS_CC );
  353. /* constants are declared in transliterator_register_constants, called from MINIT */
  354. }
  355. /* }}} */
  356. /*
  357. * Local variables:
  358. * tab-width: 4
  359. * c-basic-offset: 4
  360. * End:
  361. * vim600: noet sw=4 ts=4 fdm=marker
  362. * vim<600: noet sw=4 ts=4
  363. */