]> granicus.if.org Git - php/commitdiff
- Pretty much finish _clone() support
authorAndi Gutmans <andi@php.net>
Wed, 26 Dec 2001 19:54:20 +0000 (19:54 +0000)
committerAndi Gutmans <andi@php.net>
Wed, 26 Dec 2001 19:54:20 +0000 (19:54 +0000)
Zend/zend.c
Zend/zend.h
Zend/zend_API.h
Zend/zend_compile.c
Zend/zend_objects.c

index 1e945fc9daec6a448846f524cdd7a885d3844cd0..8ab5351967747cd4fbe5eb17260f412377cba2cc 100644 (file)
@@ -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;
index 69d33f32918c6a01c4aaf04bce0b94ea829846dc..88c92142991cd77cbb8beaac9116b9dabeb84fe6 100644 (file)
@@ -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);
index 47cac6466e236d56777a1c47ff96b6e405c3d214..8b16c26586994cbbb5589602909e20eabba74f0c 100644 (file)
@@ -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;                                     \
                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;   \
index e1a7e853af1fd6630b5faf6cd2145141b6561996..d9aeb00c17cc672dc65162e6f44b5b4267f5364b 100644 (file)
@@ -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;
index 581e150bf9f5517fe4da2f1009cc2bf86ada7682..f86148158d19df1183d87e2aade74e82470e4896 100644 (file)
@@ -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;
 }