root/ext/intl/transliterator/transliterator_class.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. transliterator_object_construct
  2. transliterator_object_init
  3. transliterator_object_destroy
  4. Transliterator_objects_dtor
  5. Transliterator_objects_free
  6. Transliterator_object_create
  7. Transliterator_clone_obj
  8. Transliterator_get_property_ptr_ptr
  9. Transliterator_read_property
  10. Transliterator_write_property
  11. transliterator_register_Transliterator_class

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

/* [<][>][^][v][top][bottom][index][help] */