Permalink
Browse files

- Pretty much finish _clone() support

  • Loading branch information...
1 parent 403350e commit 29ea3da2f846ff56669a3ec525bfaad2b295bf42 @andigutmans andigutmans committed Dec 26, 2001
Showing with 53 additions and 3 deletions.
  1. +1 −0 Zend/zend.c
  2. +1 −0 Zend/zend.h
  3. +2 −0 Zend/zend_API.h
  4. +6 −0 Zend/zend_compile.c
  5. +43 −3 Zend/zend_objects.c
View
@@ -252,6 +252,7 @@ static void register_standard_class(void)
zend_hash_init_ex(&zend_standard_class_def.class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
zend_hash_init_ex(&zend_standard_class_def.function_table, 0, NULL, ZEND_FUNCTION_DTOR, 1, 0);
zend_standard_class_def.constructor = NULL;
+ zend_standard_class_def.clone = NULL;
zend_standard_class_def.handle_function_call = NULL;
zend_standard_class_def.handle_property_get = NULL;
zend_standard_class_def.handle_property_set = NULL;
View
@@ -291,6 +291,7 @@ struct _zend_class_entry {
zend_function_entry *builtin_functions;
union _zend_function *constructor;
+ union _zend_function *clone;
/* handlers */
void (*handle_function_call)(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
View
@@ -88,6 +88,7 @@
class_container.name_length = sizeof(class_name)-1; \
class_container.builtin_functions = functions; \
class_container.constructor = NULL; \
+ class_container.clone = NULL; \
class_container.handle_function_call = NULL; \
class_container.handle_property_get = NULL; \
class_container.handle_property_set = NULL; \
@@ -99,6 +100,7 @@
class_container.name_length = sizeof(class_name)-1; \
class_container.builtin_functions = functions; \
class_container.constructor = NULL; \
+ class_container.clone = NULL; \
class_container.handle_function_call = handle_fcall; \
class_container.handle_property_get = handle_propget; \
class_container.handle_property_set = handle_propset; \
View
@@ -761,6 +761,8 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
zend_hash_update(&CG(active_class_entry)->function_table, name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
if ((CG(active_class_entry)->name_length == (uint) name_len) && (!memcmp(CG(active_class_entry)->name, name, name_len))) {
CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
+ } else if ((function_name->u.constant.value.str.len == sizeof("_clone")-1) && (!memcmp(function_name->u.constant.value.str.val, "_clone", sizeof("_clone")))) {
+ CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
}
} else {
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
@@ -1362,6 +1364,7 @@ static void create_class(HashTable *class_table, char *name, int name_length, ze
zend_hash_init(&new_class_entry.constants_table, 10, NULL, ZVAL_PTR_DTOR, 0);
new_class_entry.constructor = NULL;
+ new_class_entry.clone = NULL;
new_class_entry.handle_function_call = NULL;
new_class_entry.handle_property_set = NULL;
@@ -1849,6 +1852,7 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
zend_hash_init(&new_class_entry.constants_table, 10, NULL, ZVAL_PTR_DTOR, 0);
new_class_entry.constructor = NULL;
+ new_class_entry.clone = NULL;
new_class_entry.handle_function_call = NULL;
new_class_entry.handle_property_set = NULL;
@@ -1879,6 +1883,8 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
new_class_entry.constructor = parent_class->constructor;
+ /* FIXME: What do we do with clone? */
+
/* copy overloaded handlers */
new_class_entry.handle_function_call = parent_class->handle_function_call;
new_class_entry.handle_property_get = parent_class->handle_property_get;
View
@@ -1,6 +1,7 @@
#include "zend.h"
#include "zend_globals.h"
#include "zend_variables.h"
+#include "zend_API.h"
#define ZEND_DEBUG_OBJECTS 0
@@ -141,9 +142,48 @@ zend_object_value zend_objects_clone_obj(zend_object_handle handle)
old_object = &EG(objects).object_buckets[handle].bucket.obj.object;
retval = zend_objects_new(&new_object, old_object->ce);
- ALLOC_HASHTABLE(new_object->properties);
- zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *));
+
+ if (old_object->ce->clone) {
+ zval *old_obj;
+ zval *new_obj;
+ zval *clone_func_name;
+ zval *retval_ptr;
+ HashTable symbol_table;
+
+ MAKE_STD_ZVAL(new_obj);
+ new_obj->type = IS_OBJECT;
+ new_obj->value.obj = retval;
+ zval_copy_ctor(new_obj);
+
+ MAKE_STD_ZVAL(old_obj);
+ old_obj->type = IS_OBJECT;
+ old_obj->value.obj.handle = handle;
+ old_obj->value.obj.handlers = &zoh; /* If we reached here than the handlers are zoh */
+ zval_copy_ctor(old_obj);
+
+ /* FIXME: Optimize this so that we use the old_object->ce->clone function pointer instead of the name */
+ MAKE_STD_ZVAL(clone_func_name);
+ clone_func_name->type = IS_STRING;
+ clone_func_name->value.str.val = estrndup("_clone", sizeof("_clone")-1);
+ clone_func_name->value.str.len = sizeof("_clone")-1;
+
+ ALLOC_HASHTABLE(new_object->properties);
+ zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+
+ ZEND_INIT_SYMTABLE(&symbol_table);
+ ZEND_SET_SYMBOL(&symbol_table, "clone", old_obj);
+
+ call_user_function_ex(NULL, &new_obj, clone_func_name, &retval_ptr, 0, NULL, 0, &symbol_table TSRMLS_CC);
+
+ zend_hash_destroy(&symbol_table);
+ zval_ptr_dtor(&new_obj);
+ zval_ptr_dtor(&clone_func_name);
+ zval_ptr_dtor(&retval_ptr);
+ } else {
+ ALLOC_HASHTABLE(new_object->properties);
+ zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *));
+ }
return retval;
}

0 comments on commit 29ea3da

Please sign in to comment.