root/Zend/zend_objects.c

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

DEFINITIONS

This source file includes following definitions.
  1. zend_object_std_init
  2. zend_object_std_dtor
  3. zend_objects_destroy_object
  4. zend_objects_free_object_storage
  5. zend_objects_new
  6. zend_objects_get_address
  7. zend_objects_clone_members
  8. zend_objects_clone_obj

   1 /*
   2    +----------------------------------------------------------------------+
   3    | Zend Engine                                                          |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 2.00 of the Zend license,     |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.zend.com/license/2_00.txt.                                |
  11    | If you did not receive a copy of the Zend license and are unable to  |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@zend.com so we can mail you a copy immediately.              |
  14    +----------------------------------------------------------------------+
  15    | Authors: Andi Gutmans <andi@zend.com>                                |
  16    |          Zeev Suraski <zeev@zend.com>                                |
  17    +----------------------------------------------------------------------+
  18 */
  19 
  20 /* $Id$ */
  21 
  22 #include "zend.h"
  23 #include "zend_globals.h"
  24 #include "zend_variables.h"
  25 #include "zend_API.h"
  26 #include "zend_interfaces.h"
  27 #include "zend_exceptions.h"
  28 
  29 ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce TSRMLS_DC)
  30 {
  31         object->ce = ce;
  32         object->properties = NULL;
  33         object->properties_table = NULL;
  34         object->guards = NULL;
  35 }
  36 
  37 ZEND_API void zend_object_std_dtor(zend_object *object TSRMLS_DC)
  38 {
  39         if (object->guards) {
  40                 zend_hash_destroy(object->guards);
  41                 FREE_HASHTABLE(object->guards);
  42         }
  43         if (object->properties) {
  44                 zend_hash_destroy(object->properties);
  45                 FREE_HASHTABLE(object->properties);
  46                 if (object->properties_table) {
  47                         efree(object->properties_table);
  48                 }
  49         } else if (object->properties_table) {
  50                 int i;
  51 
  52                 for (i = 0; i < object->ce->default_properties_count; i++) {
  53                         if (object->properties_table[i]) {
  54                                 zval_ptr_dtor(&object->properties_table[i]);
  55                         }
  56                 }
  57                 efree(object->properties_table);
  58         }
  59 }
  60 
  61 ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handle handle TSRMLS_DC)
  62 {
  63         zend_function *destructor = object ? object->ce->destructor : NULL;
  64 
  65         if (destructor) {
  66                 zval *old_exception;
  67                 zval *obj;
  68                 zend_object_store_bucket *obj_bucket;
  69 
  70                 if (destructor->op_array.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) {
  71                         if (destructor->op_array.fn_flags & ZEND_ACC_PRIVATE) {
  72                                 /* Ensure that if we're calling a private function, we're allowed to do so.
  73                                  */
  74                                 if (object->ce != EG(scope)) {
  75                                         zend_class_entry *ce = object->ce;
  76 
  77                                         zend_error(EG(in_execution) ? E_ERROR : E_WARNING,
  78                                                 "Call to private %s::__destruct() from context '%s'%s",
  79                                                 ce->name,
  80                                                 EG(scope) ? EG(scope)->name : "",
  81                                                 EG(in_execution) ? "" : " during shutdown ignored");
  82                                         return;
  83                                 }
  84                         } else {
  85                                 /* Ensure that if we're calling a protected function, we're allowed to do so.
  86                                  */
  87                                 if (!zend_check_protected(zend_get_function_root_class(destructor), EG(scope))) {
  88                                         zend_class_entry *ce = object->ce;
  89 
  90                                         zend_error(EG(in_execution) ? E_ERROR : E_WARNING,
  91                                                 "Call to protected %s::__destruct() from context '%s'%s",
  92                                                 ce->name,
  93                                                 EG(scope) ? EG(scope)->name : "",
  94                                                 EG(in_execution) ? "" : " during shutdown ignored");
  95                                         return;
  96                                 }
  97                         }
  98                 }
  99 
 100                 MAKE_STD_ZVAL(obj);
 101                 Z_TYPE_P(obj) = IS_OBJECT;
 102                 Z_OBJ_HANDLE_P(obj) = handle;
 103                 obj_bucket = &EG(objects_store).object_buckets[handle];
 104                 if (!obj_bucket->bucket.obj.handlers) {
 105                         obj_bucket->bucket.obj.handlers = &std_object_handlers;
 106                 }
 107                 Z_OBJ_HT_P(obj) = obj_bucket->bucket.obj.handlers;
 108                 zval_copy_ctor(obj);
 109 
 110                 /* Make sure that destructors are protected from previously thrown exceptions.
 111                  * For example, if an exception was thrown in a function and when the function's
 112                  * local variable destruction results in a destructor being called.
 113                  */
 114                 old_exception = NULL;
 115                 if (EG(exception)) {
 116                         if (Z_OBJ_HANDLE_P(EG(exception)) == handle) {
 117                                 zend_error(E_ERROR, "Attempt to destruct pending exception");
 118                         } else {
 119                                 old_exception = EG(exception);
 120                                 EG(exception) = NULL;
 121                         }
 122                 }
 123                 zend_call_method_with_0_params(&obj, object->ce, &destructor, ZEND_DESTRUCTOR_FUNC_NAME, NULL);
 124                 if (old_exception) {
 125                         if (EG(exception)) {
 126                                 zend_exception_set_previous(EG(exception), old_exception TSRMLS_CC);
 127                         } else {
 128                                 EG(exception) = old_exception;
 129                         }
 130                 }
 131                 zval_ptr_dtor(&obj);
 132         }
 133 }
 134 
 135 ZEND_API void zend_objects_free_object_storage(zend_object *object TSRMLS_DC)
 136 {
 137         zend_object_std_dtor(object TSRMLS_CC);
 138         efree(object);
 139 }
 140 
 141 ZEND_API zend_object_value zend_objects_new(zend_object **object, zend_class_entry *class_type TSRMLS_DC)
 142 {
 143         zend_object_value retval;
 144 
 145         *object = emalloc(sizeof(zend_object));
 146         (*object)->ce = class_type;
 147         (*object)->properties = NULL;
 148         (*object)->properties_table = NULL;
 149         (*object)->guards = NULL;
 150         retval.handle = zend_objects_store_put(*object, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) zend_objects_free_object_storage, NULL TSRMLS_CC);
 151         retval.handlers = &std_object_handlers;
 152         return retval;
 153 }
 154 
 155 ZEND_API zend_object *zend_objects_get_address(const zval *zobject TSRMLS_DC)
 156 {
 157         return (zend_object *)zend_object_store_get_object(zobject TSRMLS_CC);
 158 }
 159 
 160 ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object_value new_obj_val, zend_object *old_object, zend_object_handle handle TSRMLS_DC)
 161 {
 162         int i;
 163 
 164         if (old_object->properties_table) {
 165                 if (!new_object->properties_table) {
 166                         new_object->properties_table = emalloc(sizeof(zval*) * old_object->ce->default_properties_count);
 167                         memset(new_object->properties_table, 0, sizeof(zval*) * old_object->ce->default_properties_count);
 168                 }
 169                 for (i = 0; i < old_object->ce->default_properties_count; i++) {
 170                         if (!new_object->properties) {
 171                                 if (new_object->properties_table[i]) {
 172                                         zval_ptr_dtor(&new_object->properties_table[i]);
 173                                 }
 174                         }
 175                         if (!old_object->properties) {
 176                                 new_object->properties_table[i] = old_object->properties_table[i];
 177                                 if (new_object->properties_table[i]) {
 178                                         Z_ADDREF_P(new_object->properties_table[i]);
 179                                 }
 180                         }
 181                 }
 182         }
 183         if (old_object->properties) {
 184                 if (!new_object->properties) {
 185                         ALLOC_HASHTABLE(new_object->properties);
 186                         zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
 187                 }
 188                 zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *));
 189                 if (old_object->properties_table) {
 190                         HashPosition pos;
 191                         zend_property_info *prop_info;
 192                         for (zend_hash_internal_pointer_reset_ex(&old_object->ce->properties_info, &pos);
 193                              zend_hash_get_current_data_ex(&old_object->ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
 194                              zend_hash_move_forward_ex(&old_object->ce->properties_info, &pos)) {
 195                                 if ((prop_info->flags & ZEND_ACC_STATIC) == 0) {
 196                                         if (zend_hash_quick_find(new_object->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&new_object->properties_table[prop_info->offset]) == FAILURE) {
 197                                                 new_object->properties_table[prop_info->offset] = NULL;
 198                                         }
 199                                 }
 200                         }
 201                 }
 202         }
 203 
 204         if (old_object->ce->clone) {
 205                 zval *new_obj;
 206 
 207                 MAKE_STD_ZVAL(new_obj);
 208                 new_obj->type = IS_OBJECT;
 209                 new_obj->value.obj = new_obj_val;
 210                 zval_copy_ctor(new_obj);
 211 
 212                 zend_call_method_with_0_params(&new_obj, old_object->ce, &old_object->ce->clone, ZEND_CLONE_FUNC_NAME, NULL);
 213 
 214                 zval_ptr_dtor(&new_obj);
 215         }
 216 }
 217 
 218 ZEND_API zend_object_value zend_objects_clone_obj(zval *zobject TSRMLS_DC)
 219 {
 220         zend_object_value new_obj_val;
 221         zend_object *old_object;
 222         zend_object *new_object;
 223         zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
 224 
 225         /* assume that create isn't overwritten, so when clone depends on the
 226          * overwritten one then it must itself be overwritten */
 227         old_object = zend_objects_get_address(zobject TSRMLS_CC);
 228         new_obj_val = zend_objects_new(&new_object, old_object->ce TSRMLS_CC);
 229 
 230         zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
 231 
 232         return new_obj_val;
 233 }
 234 
 235 /*
 236  * Local variables:
 237  * tab-width: 4
 238  * c-basic-offset: 4
 239  * indent-tabs-mode: t
 240  * End:
 241  */

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