diff --git a/php_phongo.c b/php_phongo.c index 6c9bd29fc..595eb1352 100644 --- a/php_phongo.c +++ b/php_phongo.c @@ -155,13 +155,6 @@ static zend_class_entry* php_phongo_fetch_internal_class(const char* class_name, return NULL; } -static HashTable* php_phongo_std_get_gc(zend_object* object, zval** table, int* n) -{ - *table = NULL; - *n = 0; - return zend_std_get_properties(object); -} - PHP_MINIT_FUNCTION(mongodb) /* {{{ */ { bson_mem_vtable_t bson_mem_vtable = { @@ -197,9 +190,6 @@ PHP_MINIT_FUNCTION(mongodb) /* {{{ */ /* Disable cloning by default. Individual classes can opt in if they need to * support this (e.g. BSON objects). */ phongo_std_object_handlers.clone_obj = NULL; - /* Ensure that get_gc delegates to zend_std_get_properties directly in case - * our class defines a get_properties handler for debugging purposes. */ - phongo_std_object_handlers.get_gc = php_phongo_std_get_gc; /* Initialize zend_class_entry dependencies. * diff --git a/php_phongo.h b/php_phongo.h index d0655f911..9292d7e3d 100644 --- a/php_phongo.h +++ b/php_phongo.h @@ -77,11 +77,97 @@ zend_object_handlers* phongo_get_std_object_handlers(void); #define PHONGO_GET_PROPERTY_HASH_FREE_PROPS(is_temp, props) \ do { \ if (is_temp) { \ - zend_hash_destroy((props)); \ - FREE_HASHTABLE(props); \ + zend_hash_release((props)); \ } \ } while (0) +#define PHONGO_GET_PROPERTY_HANDLERS(_name, _intern_extractor) \ + PHONGO_GET_PROPERTY_HANDLERS_NO_GC(_name, _intern_extractor) \ + \ + static HashTable* php_phongo_##_name##_get_gc(zend_object* zobj, zval** table, int* n) \ + { \ + *table = NULL; \ + *n = 0; \ + return _intern_extractor(zobj)->php_properties; \ + } + +#define PHONGO_GET_PROPERTY_HANDLERS_NO_GC(_name, _intern_extractor) \ + static zval* php_phongo_##_name##_read_property(zend_object* zobj, zend_string* member, int type, void** cache_slot, zval* rv) \ + { \ + HashTable* props = _intern_extractor(zobj)->php_properties; \ + if (!props) { \ + ALLOC_HASHTABLE(props); \ + zend_hash_init(props, 0, NULL, ZVAL_PTR_DTOR, 0); \ + _intern_extractor(zobj)->php_properties = props; \ + } \ + zval* ret = zend_hash_find(props, member); \ + if (ret) { \ + return ret; \ + } \ + return &EG(uninitialized_zval); \ + } \ + \ + static zval* php_phongo_##_name##_write_property(zend_object* zobj, zend_string* name, zval* value, void** cache_slot) \ + { \ + Z_TRY_ADDREF_P(value); \ + HashTable* props = _intern_extractor(zobj)->php_properties; \ + if (!props) { \ + ALLOC_HASHTABLE(props); \ + zend_hash_init(props, 0, NULL, ZVAL_PTR_DTOR, 0); \ + _intern_extractor(zobj)->php_properties = props; \ + } \ + return zend_hash_add_new(props, name, value); \ + } \ + static int php_phongo_##_name##_has_property(zend_object* zobj, zend_string* name, int has_set_exists, void** cache_slot) \ + { \ + HashTable* props = _intern_extractor(zobj)->php_properties; \ + if (!props) { \ + ALLOC_HASHTABLE(props); \ + zend_hash_init(props, 0, NULL, ZVAL_PTR_DTOR, 0); \ + _intern_extractor(zobj)->php_properties = props; \ + } \ + zval* value = zend_hash_find(props, name); \ + if (value) { \ + if (has_set_exists == ZEND_PROPERTY_NOT_EMPTY) { \ + return zend_is_true(value); \ + } \ + if (has_set_exists < ZEND_PROPERTY_NOT_EMPTY) { \ + ZEND_ASSERT(has_set_exists == ZEND_PROPERTY_ISSET); \ + ZVAL_DEREF(value); \ + return (Z_TYPE_P(value) != IS_NULL); \ + } \ + ZEND_ASSERT(has_set_exists == ZEND_PROPERTY_EXISTS); \ + return true; \ + } \ + return false; \ + } \ + static void php_phongo_##_name##_unset_property(zend_object* zobj, zend_string* name, void** cache_slot) \ + { \ + HashTable* props = _intern_extractor(zobj)->php_properties; \ + if (!props) { \ + ALLOC_HASHTABLE(props); \ + zend_hash_init(props, 0, NULL, ZVAL_PTR_DTOR, 0); \ + _intern_extractor(zobj)->php_properties = props; \ + } \ + zend_hash_del(props, name); \ + } \ + \ + static zval* php_phongo_##_name##_get_property_ptr_ptr(zend_object* zobj, zend_string* name, int type, void** cache_slot) \ + { \ + HashTable* props = _intern_extractor(zobj)->php_properties; \ + if (!props) { \ + ALLOC_HASHTABLE(props); \ + zend_hash_init(props, 0, NULL, ZVAL_PTR_DTOR, 0); \ + _intern_extractor(zobj)->php_properties = props; \ + } \ + \ + zval* value = zend_hash_find(props, name); \ + if (value) { \ + return value; \ + } \ + return zend_hash_add(props, name, &EG(uninitialized_zval)); \ + } + #define PHONGO_ZVAL_EXCEPTION_NAME(e) (ZSTR_VAL(e->ce->name)) #define PHONGO_SET_CREATED_BY_PID(intern) \ diff --git a/src/BSON/Binary.c b/src/BSON/Binary.c index 4583ac8ab..a7c6d53ea 100644 --- a/src/BSON/Binary.c +++ b/src/BSON/Binary.c @@ -214,8 +214,14 @@ static void php_phongo_binary_free_object(zend_object* object) } if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } } @@ -281,18 +287,26 @@ static HashTable* php_phongo_binary_get_properties(zend_object* object) return php_phongo_binary_get_properties_hash(object, false); } +PHONGO_GET_PROPERTY_HANDLERS(binary, Z_OBJ_BINARY); + void php_phongo_binary_init_ce(INIT_FUNC_ARGS) { php_phongo_binary_ce = register_class_MongoDB_BSON_Binary(php_phongo_binary_interface_ce, php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); php_phongo_binary_ce->create_object = php_phongo_binary_create_object; memcpy(&php_phongo_handler_binary, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_binary.compare = php_phongo_binary_compare_objects; - php_phongo_handler_binary.clone_obj = php_phongo_binary_clone_object; - php_phongo_handler_binary.get_debug_info = php_phongo_binary_get_debug_info; - php_phongo_handler_binary.get_properties = php_phongo_binary_get_properties; - php_phongo_handler_binary.free_obj = php_phongo_binary_free_object; - php_phongo_handler_binary.offset = XtOffsetOf(php_phongo_binary_t, std); + php_phongo_handler_binary.compare = php_phongo_binary_compare_objects; + php_phongo_handler_binary.clone_obj = php_phongo_binary_clone_object; + php_phongo_handler_binary.get_debug_info = php_phongo_binary_get_debug_info; + php_phongo_handler_binary.get_properties = php_phongo_binary_get_properties; + php_phongo_handler_binary.read_property = php_phongo_binary_read_property; + php_phongo_handler_binary.write_property = php_phongo_binary_write_property; + php_phongo_handler_binary.has_property = php_phongo_binary_has_property; + php_phongo_handler_binary.unset_property = php_phongo_binary_unset_property; + php_phongo_handler_binary.get_property_ptr_ptr = php_phongo_binary_get_property_ptr_ptr; + php_phongo_handler_binary.get_gc = php_phongo_binary_get_gc; + php_phongo_handler_binary.free_obj = php_phongo_binary_free_object; + php_phongo_handler_binary.offset = XtOffsetOf(php_phongo_binary_t, std); } bool phongo_binary_new(zval* object, const char* data, size_t data_len, bson_subtype_t type) diff --git a/src/BSON/DBPointer.c b/src/BSON/DBPointer.c index b0285732e..fb955d96f 100644 --- a/src/BSON/DBPointer.c +++ b/src/BSON/DBPointer.c @@ -177,8 +177,14 @@ static void php_phongo_dbpointer_free_object(zend_object* object) } if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } } @@ -241,18 +247,26 @@ static HashTable* php_phongo_dbpointer_get_properties(zend_object* object) return php_phongo_dbpointer_get_properties_hash(object, false); } +PHONGO_GET_PROPERTY_HANDLERS(dbpointer, Z_OBJ_DBPOINTER); + void php_phongo_dbpointer_init_ce(INIT_FUNC_ARGS) { php_phongo_dbpointer_ce = register_class_MongoDB_BSON_DBPointer(php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); php_phongo_dbpointer_ce->create_object = php_phongo_dbpointer_create_object; memcpy(&php_phongo_handler_dbpointer, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_dbpointer.compare = php_phongo_dbpointer_compare_objects; - php_phongo_handler_dbpointer.clone_obj = php_phongo_dbpointer_clone_object; - php_phongo_handler_dbpointer.get_debug_info = php_phongo_dbpointer_get_debug_info; - php_phongo_handler_dbpointer.get_properties = php_phongo_dbpointer_get_properties; - php_phongo_handler_dbpointer.free_obj = php_phongo_dbpointer_free_object; - php_phongo_handler_dbpointer.offset = XtOffsetOf(php_phongo_dbpointer_t, std); + php_phongo_handler_dbpointer.compare = php_phongo_dbpointer_compare_objects; + php_phongo_handler_dbpointer.clone_obj = php_phongo_dbpointer_clone_object; + php_phongo_handler_dbpointer.get_debug_info = php_phongo_dbpointer_get_debug_info; + php_phongo_handler_dbpointer.get_properties = php_phongo_dbpointer_get_properties; + php_phongo_handler_dbpointer.read_property = php_phongo_dbpointer_read_property; + php_phongo_handler_dbpointer.write_property = php_phongo_dbpointer_write_property; + php_phongo_handler_dbpointer.has_property = php_phongo_dbpointer_has_property; + php_phongo_handler_dbpointer.unset_property = php_phongo_dbpointer_unset_property; + php_phongo_handler_dbpointer.get_property_ptr_ptr = php_phongo_dbpointer_get_property_ptr_ptr; + php_phongo_handler_dbpointer.get_gc = php_phongo_dbpointer_get_gc; + php_phongo_handler_dbpointer.free_obj = php_phongo_dbpointer_free_object; + php_phongo_handler_dbpointer.offset = XtOffsetOf(php_phongo_dbpointer_t, std); } bool phongo_dbpointer_new(zval* object, const char* ref, size_t ref_len, const bson_oid_t* oid) diff --git a/src/BSON/Decimal128.c b/src/BSON/Decimal128.c index 970ee00e7..9619a06fc 100644 --- a/src/BSON/Decimal128.c +++ b/src/BSON/Decimal128.c @@ -169,8 +169,14 @@ static void php_phongo_decimal128_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } } @@ -216,17 +222,25 @@ static HashTable* php_phongo_decimal128_get_properties(zend_object* object) return php_phongo_decimal128_get_properties_hash(object, false); } +PHONGO_GET_PROPERTY_HANDLERS(decimal128, Z_OBJ_DECIMAL128); + void php_phongo_decimal128_init_ce(INIT_FUNC_ARGS) { php_phongo_decimal128_ce = register_class_MongoDB_BSON_Decimal128(php_phongo_decimal128_interface_ce, php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); php_phongo_decimal128_ce->create_object = php_phongo_decimal128_create_object; memcpy(&php_phongo_handler_decimal128, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_decimal128.clone_obj = php_phongo_decimal128_clone_object; - php_phongo_handler_decimal128.get_debug_info = php_phongo_decimal128_get_debug_info; - php_phongo_handler_decimal128.get_properties = php_phongo_decimal128_get_properties; - php_phongo_handler_decimal128.free_obj = php_phongo_decimal128_free_object; - php_phongo_handler_decimal128.offset = XtOffsetOf(php_phongo_decimal128_t, std); + php_phongo_handler_decimal128.clone_obj = php_phongo_decimal128_clone_object; + php_phongo_handler_decimal128.get_debug_info = php_phongo_decimal128_get_debug_info; + php_phongo_handler_decimal128.get_properties = php_phongo_decimal128_get_properties; + php_phongo_handler_decimal128.read_property = php_phongo_decimal128_read_property; + php_phongo_handler_decimal128.write_property = php_phongo_decimal128_write_property; + php_phongo_handler_decimal128.has_property = php_phongo_decimal128_has_property; + php_phongo_handler_decimal128.unset_property = php_phongo_decimal128_unset_property; + php_phongo_handler_decimal128.get_property_ptr_ptr = php_phongo_decimal128_get_property_ptr_ptr; + php_phongo_handler_decimal128.get_gc = php_phongo_decimal128_get_gc; + php_phongo_handler_decimal128.free_obj = php_phongo_decimal128_free_object; + php_phongo_handler_decimal128.offset = XtOffsetOf(php_phongo_decimal128_t, std); } bool phongo_decimal128_new(zval* object, const bson_decimal128_t* decimal) diff --git a/src/BSON/Document.c b/src/BSON/Document.c index b0886b369..83ed55e27 100644 --- a/src/BSON/Document.c +++ b/src/BSON/Document.c @@ -447,8 +447,14 @@ static void php_phongo_document_free_object(zend_object* object) } if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } } diff --git a/src/BSON/Int64.c b/src/BSON/Int64.c index d350f2b7b..7737db156 100644 --- a/src/BSON/Int64.c +++ b/src/BSON/Int64.c @@ -176,8 +176,14 @@ static void php_phongo_int64_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } } @@ -554,20 +560,28 @@ static HashTable* php_phongo_int64_get_properties(zend_object* object) return php_phongo_int64_get_properties_hash(object, false); } +PHONGO_GET_PROPERTY_HANDLERS(int64, Z_OBJ_INT64); + void php_phongo_int64_init_ce(INIT_FUNC_ARGS) { php_phongo_int64_ce = register_class_MongoDB_BSON_Int64(php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); php_phongo_int64_ce->create_object = php_phongo_int64_create_object; memcpy(&php_phongo_handler_int64, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_int64.compare = php_phongo_int64_compare_objects; - php_phongo_handler_int64.clone_obj = php_phongo_int64_clone_object; - php_phongo_handler_int64.get_debug_info = php_phongo_int64_get_debug_info; - php_phongo_handler_int64.get_properties = php_phongo_int64_get_properties; - php_phongo_handler_int64.free_obj = php_phongo_int64_free_object; - php_phongo_handler_int64.offset = XtOffsetOf(php_phongo_int64_t, std); - php_phongo_handler_int64.cast_object = php_phongo_int64_cast_object; - php_phongo_handler_int64.do_operation = php_phongo_int64_do_operation; + php_phongo_handler_int64.compare = php_phongo_int64_compare_objects; + php_phongo_handler_int64.clone_obj = php_phongo_int64_clone_object; + php_phongo_handler_int64.get_debug_info = php_phongo_int64_get_debug_info; + php_phongo_handler_int64.get_properties = php_phongo_int64_get_properties; + php_phongo_handler_int64.read_property = php_phongo_int64_read_property; + php_phongo_handler_int64.write_property = php_phongo_int64_write_property; + php_phongo_handler_int64.has_property = php_phongo_int64_has_property; + php_phongo_handler_int64.unset_property = php_phongo_int64_unset_property; + php_phongo_handler_int64.get_property_ptr_ptr = php_phongo_int64_get_property_ptr_ptr; + php_phongo_handler_int64.get_gc = php_phongo_int64_get_gc; + php_phongo_handler_int64.free_obj = php_phongo_int64_free_object; + php_phongo_handler_int64.offset = XtOffsetOf(php_phongo_int64_t, std); + php_phongo_handler_int64.cast_object = php_phongo_int64_cast_object; + php_phongo_handler_int64.do_operation = php_phongo_int64_do_operation; } bool phongo_int64_new(zval* object, int64_t integer) diff --git a/src/BSON/Iterator.c b/src/BSON/Iterator.c index 1306dbc7d..de0a80bfe 100644 --- a/src/BSON/Iterator.c +++ b/src/BSON/Iterator.c @@ -249,8 +249,14 @@ static void php_phongo_iterator_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } php_phongo_iterator_free_current(intern); @@ -377,6 +383,7 @@ static zend_object_iterator* php_phongo_iterator_get_iterator(zend_class_entry* return iterator; } +PHONGO_GET_PROPERTY_HANDLERS(iterator, Z_OBJ_ITERATOR); void php_phongo_iterator_init_ce(INIT_FUNC_ARGS) { @@ -385,9 +392,15 @@ void php_phongo_iterator_init_ce(INIT_FUNC_ARGS) php_phongo_iterator_ce->get_iterator = php_phongo_iterator_get_iterator; memcpy(&php_phongo_handler_iterator, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_iterator.clone_obj = php_phongo_iterator_clone_object; - php_phongo_handler_iterator.get_debug_info = php_phongo_iterator_get_debug_info; - php_phongo_handler_iterator.get_properties = php_phongo_iterator_get_properties; - php_phongo_handler_iterator.free_obj = php_phongo_iterator_free_object; - php_phongo_handler_iterator.offset = XtOffsetOf(php_phongo_iterator_t, std); + php_phongo_handler_iterator.clone_obj = php_phongo_iterator_clone_object; + php_phongo_handler_iterator.get_debug_info = php_phongo_iterator_get_debug_info; + php_phongo_handler_iterator.get_properties = php_phongo_iterator_get_properties; + php_phongo_handler_iterator.read_property = php_phongo_iterator_read_property; + php_phongo_handler_iterator.write_property = php_phongo_iterator_write_property; + php_phongo_handler_iterator.has_property = php_phongo_iterator_has_property; + php_phongo_handler_iterator.unset_property = php_phongo_iterator_unset_property; + php_phongo_handler_iterator.get_property_ptr_ptr = php_phongo_iterator_get_property_ptr_ptr; + php_phongo_handler_iterator.get_gc = php_phongo_iterator_get_gc; + php_phongo_handler_iterator.free_obj = php_phongo_iterator_free_object; + php_phongo_handler_iterator.offset = XtOffsetOf(php_phongo_iterator_t, std); } diff --git a/src/BSON/Javascript.c b/src/BSON/Javascript.c index 38312dc2d..676239f94 100644 --- a/src/BSON/Javascript.c +++ b/src/BSON/Javascript.c @@ -263,8 +263,14 @@ static void php_phongo_javascript_free_object(zend_object* object) } if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } } @@ -322,18 +328,26 @@ static HashTable* php_phongo_javascript_get_properties(zend_object* object) return php_phongo_javascript_get_properties_hash(object, false); } +PHONGO_GET_PROPERTY_HANDLERS(javascript, Z_OBJ_JAVASCRIPT); + void php_phongo_javascript_init_ce(INIT_FUNC_ARGS) { php_phongo_javascript_ce = register_class_MongoDB_BSON_Javascript(php_phongo_javascript_interface_ce, php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); php_phongo_javascript_ce->create_object = php_phongo_javascript_create_object; memcpy(&php_phongo_handler_javascript, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_javascript.compare = php_phongo_javascript_compare_objects; - php_phongo_handler_javascript.clone_obj = php_phongo_javascript_clone_object; - php_phongo_handler_javascript.get_debug_info = php_phongo_javascript_get_debug_info; - php_phongo_handler_javascript.get_properties = php_phongo_javascript_get_properties; - php_phongo_handler_javascript.free_obj = php_phongo_javascript_free_object; - php_phongo_handler_javascript.offset = XtOffsetOf(php_phongo_javascript_t, std); + php_phongo_handler_javascript.compare = php_phongo_javascript_compare_objects; + php_phongo_handler_javascript.clone_obj = php_phongo_javascript_clone_object; + php_phongo_handler_javascript.get_debug_info = php_phongo_javascript_get_debug_info; + php_phongo_handler_javascript.get_properties = php_phongo_javascript_get_properties; + php_phongo_handler_javascript.read_property = php_phongo_javascript_read_property; + php_phongo_handler_javascript.write_property = php_phongo_javascript_write_property; + php_phongo_handler_javascript.has_property = php_phongo_javascript_has_property; + php_phongo_handler_javascript.unset_property = php_phongo_javascript_unset_property; + php_phongo_handler_javascript.get_property_ptr_ptr = php_phongo_javascript_get_property_ptr_ptr; + php_phongo_handler_javascript.get_gc = php_phongo_javascript_get_gc; + php_phongo_handler_javascript.free_obj = php_phongo_javascript_free_object; + php_phongo_handler_javascript.offset = XtOffsetOf(php_phongo_javascript_t, std); } bool phongo_javascript_new(zval* object, const char* code, size_t code_len, const bson_t* scope) diff --git a/src/BSON/ObjectId.c b/src/BSON/ObjectId.c index 240441ac4..7d15aca21 100644 --- a/src/BSON/ObjectId.c +++ b/src/BSON/ObjectId.c @@ -203,8 +203,14 @@ static void php_phongo_objectid_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } } @@ -263,18 +269,26 @@ static HashTable* php_phongo_objectid_get_properties(zend_object* object) return php_phongo_objectid_get_properties_hash(object, false); } +PHONGO_GET_PROPERTY_HANDLERS(objectid, Z_OBJ_OBJECTID); + void php_phongo_objectid_init_ce(INIT_FUNC_ARGS) { php_phongo_objectid_ce = register_class_MongoDB_BSON_ObjectId(php_phongo_objectid_interface_ce, php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); php_phongo_objectid_ce->create_object = php_phongo_objectid_create_object; memcpy(&php_phongo_handler_objectid, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_objectid.compare = php_phongo_objectid_compare_objects; - php_phongo_handler_objectid.clone_obj = php_phongo_objectid_clone_object; - php_phongo_handler_objectid.get_debug_info = php_phongo_objectid_get_debug_info; - php_phongo_handler_objectid.get_properties = php_phongo_objectid_get_properties; - php_phongo_handler_objectid.free_obj = php_phongo_objectid_free_object; - php_phongo_handler_objectid.offset = XtOffsetOf(php_phongo_objectid_t, std); + php_phongo_handler_objectid.compare = php_phongo_objectid_compare_objects; + php_phongo_handler_objectid.clone_obj = php_phongo_objectid_clone_object; + php_phongo_handler_objectid.get_debug_info = php_phongo_objectid_get_debug_info; + php_phongo_handler_objectid.get_properties = php_phongo_objectid_get_properties; + php_phongo_handler_objectid.read_property = php_phongo_objectid_read_property; + php_phongo_handler_objectid.write_property = php_phongo_objectid_write_property; + php_phongo_handler_objectid.has_property = php_phongo_objectid_has_property; + php_phongo_handler_objectid.unset_property = php_phongo_objectid_unset_property; + php_phongo_handler_objectid.get_property_ptr_ptr = php_phongo_objectid_get_property_ptr_ptr; + php_phongo_handler_objectid.get_gc = php_phongo_objectid_get_gc; + php_phongo_handler_objectid.free_obj = php_phongo_objectid_free_object; + php_phongo_handler_objectid.offset = XtOffsetOf(php_phongo_objectid_t, std); } bool phongo_objectid_new(zval* return_value, const bson_oid_t* oid) diff --git a/src/BSON/PackedArray.c b/src/BSON/PackedArray.c index 6fdbcf575..321a09a05 100644 --- a/src/BSON/PackedArray.c +++ b/src/BSON/PackedArray.c @@ -431,8 +431,14 @@ static void php_phongo_packedarray_free_object(zend_object* object) } if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } } @@ -564,22 +570,30 @@ void php_phongo_packedarray_unset_dimension(zend_object* object, zval* offset) phongo_throw_exception(PHONGO_ERROR_LOGIC, "Cannot unset %s offset", ZSTR_VAL(php_phongo_packedarray_ce->name)); } +PHONGO_GET_PROPERTY_HANDLERS(packedarray, Z_OBJ_PACKEDARRAY); + void php_phongo_packedarray_init_ce(INIT_FUNC_ARGS) { php_phongo_packedarray_ce = register_class_MongoDB_BSON_PackedArray(zend_ce_aggregate, zend_ce_arrayaccess, php_phongo_type_ce, zend_ce_stringable); php_phongo_packedarray_ce->create_object = php_phongo_packedarray_create_object; memcpy(&php_phongo_handler_packedarray, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_packedarray.compare = php_phongo_packedarray_compare_objects; - php_phongo_handler_packedarray.clone_obj = php_phongo_packedarray_clone_object; - php_phongo_handler_packedarray.get_debug_info = php_phongo_packedarray_get_debug_info; - php_phongo_handler_packedarray.get_properties = php_phongo_packedarray_get_properties; - php_phongo_handler_packedarray.free_obj = php_phongo_packedarray_free_object; - php_phongo_handler_packedarray.read_dimension = php_phongo_packedarray_read_dimension; - php_phongo_handler_packedarray.write_dimension = php_phongo_packedarray_write_dimension; - php_phongo_handler_packedarray.has_dimension = php_phongo_packedarray_has_dimension; - php_phongo_handler_packedarray.unset_dimension = php_phongo_packedarray_unset_dimension; - php_phongo_handler_packedarray.offset = XtOffsetOf(php_phongo_packedarray_t, std); + php_phongo_handler_packedarray.compare = php_phongo_packedarray_compare_objects; + php_phongo_handler_packedarray.clone_obj = php_phongo_packedarray_clone_object; + php_phongo_handler_packedarray.get_debug_info = php_phongo_packedarray_get_debug_info; + php_phongo_handler_packedarray.get_properties = php_phongo_packedarray_get_properties; + php_phongo_handler_packedarray.read_property = php_phongo_packedarray_read_property; + php_phongo_handler_packedarray.write_property = php_phongo_packedarray_write_property; + php_phongo_handler_packedarray.has_property = php_phongo_packedarray_has_property; + php_phongo_handler_packedarray.unset_property = php_phongo_packedarray_unset_property; + php_phongo_handler_packedarray.get_property_ptr_ptr = php_phongo_packedarray_get_property_ptr_ptr; + php_phongo_handler_packedarray.get_gc = php_phongo_packedarray_get_gc; + php_phongo_handler_packedarray.free_obj = php_phongo_packedarray_free_object; + php_phongo_handler_packedarray.read_dimension = php_phongo_packedarray_read_dimension; + php_phongo_handler_packedarray.write_dimension = php_phongo_packedarray_write_dimension; + php_phongo_handler_packedarray.has_dimension = php_phongo_packedarray_has_dimension; + php_phongo_handler_packedarray.unset_dimension = php_phongo_packedarray_unset_dimension; + php_phongo_handler_packedarray.offset = XtOffsetOf(php_phongo_packedarray_t, std); } bool phongo_packedarray_new(zval* object, bson_t* bson, bool copy) diff --git a/src/BSON/Regex.c b/src/BSON/Regex.c index a75b75e39..61c498d5e 100644 --- a/src/BSON/Regex.c +++ b/src/BSON/Regex.c @@ -229,8 +229,14 @@ static void php_phongo_regex_free_object(zend_object* object) } if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } } @@ -294,18 +300,26 @@ static HashTable* php_phongo_regex_get_properties(zend_object* object) return php_phongo_regex_get_properties_hash(object, false); } +PHONGO_GET_PROPERTY_HANDLERS(regex, Z_OBJ_REGEX); + void php_phongo_regex_init_ce(INIT_FUNC_ARGS) { php_phongo_regex_ce = register_class_MongoDB_BSON_Regex(php_phongo_regex_interface_ce, php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); php_phongo_regex_ce->create_object = php_phongo_regex_create_object; memcpy(&php_phongo_handler_regex, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_regex.compare = php_phongo_regex_compare_objects; - php_phongo_handler_regex.clone_obj = php_phongo_regex_clone_object; - php_phongo_handler_regex.get_debug_info = php_phongo_regex_get_debug_info; - php_phongo_handler_regex.get_properties = php_phongo_regex_get_properties; - php_phongo_handler_regex.free_obj = php_phongo_regex_free_object; - php_phongo_handler_regex.offset = XtOffsetOf(php_phongo_regex_t, std); + php_phongo_handler_regex.compare = php_phongo_regex_compare_objects; + php_phongo_handler_regex.clone_obj = php_phongo_regex_clone_object; + php_phongo_handler_regex.get_debug_info = php_phongo_regex_get_debug_info; + php_phongo_handler_regex.get_properties = php_phongo_regex_get_properties; + php_phongo_handler_regex.read_property = php_phongo_regex_read_property; + php_phongo_handler_regex.write_property = php_phongo_regex_write_property; + php_phongo_handler_regex.has_property = php_phongo_regex_has_property; + php_phongo_handler_regex.unset_property = php_phongo_regex_unset_property; + php_phongo_handler_regex.get_property_ptr_ptr = php_phongo_regex_get_property_ptr_ptr; + php_phongo_handler_regex.get_gc = php_phongo_regex_get_gc; + php_phongo_handler_regex.free_obj = php_phongo_regex_free_object; + php_phongo_handler_regex.offset = XtOffsetOf(php_phongo_regex_t, std); } bool phongo_regex_new(zval* object, const char* pattern, const char* flags) diff --git a/src/BSON/Symbol.c b/src/BSON/Symbol.c index a47b6c2fe..20c636124 100644 --- a/src/BSON/Symbol.c +++ b/src/BSON/Symbol.c @@ -151,8 +151,14 @@ static void php_phongo_symbol_free_object(zend_object* object) } if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } } @@ -208,18 +214,26 @@ static HashTable* php_phongo_symbol_get_properties(zend_object* object) return php_phongo_symbol_get_properties_hash(object, false); } +PHONGO_GET_PROPERTY_HANDLERS(symbol, Z_OBJ_SYMBOL); + void php_phongo_symbol_init_ce(INIT_FUNC_ARGS) { php_phongo_symbol_ce = register_class_MongoDB_BSON_Symbol(php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); php_phongo_symbol_ce->create_object = php_phongo_symbol_create_object; memcpy(&php_phongo_handler_symbol, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_symbol.compare = php_phongo_symbol_compare_objects; - php_phongo_handler_symbol.clone_obj = php_phongo_symbol_clone_object; - php_phongo_handler_symbol.get_debug_info = php_phongo_symbol_get_debug_info; - php_phongo_handler_symbol.get_properties = php_phongo_symbol_get_properties; - php_phongo_handler_symbol.free_obj = php_phongo_symbol_free_object; - php_phongo_handler_symbol.offset = XtOffsetOf(php_phongo_symbol_t, std); + php_phongo_handler_symbol.compare = php_phongo_symbol_compare_objects; + php_phongo_handler_symbol.clone_obj = php_phongo_symbol_clone_object; + php_phongo_handler_symbol.get_debug_info = php_phongo_symbol_get_debug_info; + php_phongo_handler_symbol.get_properties = php_phongo_symbol_get_properties; + php_phongo_handler_symbol.read_property = php_phongo_symbol_read_property; + php_phongo_handler_symbol.write_property = php_phongo_symbol_write_property; + php_phongo_handler_symbol.has_property = php_phongo_symbol_has_property; + php_phongo_handler_symbol.unset_property = php_phongo_symbol_unset_property; + php_phongo_handler_symbol.get_property_ptr_ptr = php_phongo_symbol_get_property_ptr_ptr; + php_phongo_handler_symbol.get_gc = php_phongo_symbol_get_gc; + php_phongo_handler_symbol.free_obj = php_phongo_symbol_free_object; + php_phongo_handler_symbol.offset = XtOffsetOf(php_phongo_symbol_t, std); } bool phongo_symbol_new(zval* object, const char* symbol, size_t symbol_len) diff --git a/src/BSON/Timestamp.c b/src/BSON/Timestamp.c index 82cd6f537..232bd38a4 100644 --- a/src/BSON/Timestamp.c +++ b/src/BSON/Timestamp.c @@ -262,8 +262,14 @@ static void php_phongo_timestamp_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } } @@ -328,18 +334,26 @@ static HashTable* php_phongo_timestamp_get_properties(zend_object* object) return php_phongo_timestamp_get_properties_hash(object, false); } +PHONGO_GET_PROPERTY_HANDLERS(timestamp, Z_OBJ_TIMESTAMP); + void php_phongo_timestamp_init_ce(INIT_FUNC_ARGS) { php_phongo_timestamp_ce = register_class_MongoDB_BSON_Timestamp(php_phongo_timestamp_interface_ce, php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); php_phongo_timestamp_ce->create_object = php_phongo_timestamp_create_object; memcpy(&php_phongo_handler_timestamp, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_timestamp.compare = php_phongo_timestamp_compare_objects; - php_phongo_handler_timestamp.clone_obj = php_phongo_timestamp_clone_object; - php_phongo_handler_timestamp.get_debug_info = php_phongo_timestamp_get_debug_info; - php_phongo_handler_timestamp.get_properties = php_phongo_timestamp_get_properties; - php_phongo_handler_timestamp.free_obj = php_phongo_timestamp_free_object; - php_phongo_handler_timestamp.offset = XtOffsetOf(php_phongo_timestamp_t, std); + php_phongo_handler_timestamp.compare = php_phongo_timestamp_compare_objects; + php_phongo_handler_timestamp.clone_obj = php_phongo_timestamp_clone_object; + php_phongo_handler_timestamp.get_debug_info = php_phongo_timestamp_get_debug_info; + php_phongo_handler_timestamp.get_properties = php_phongo_timestamp_get_properties; + php_phongo_handler_timestamp.read_property = php_phongo_timestamp_read_property; + php_phongo_handler_timestamp.write_property = php_phongo_timestamp_write_property; + php_phongo_handler_timestamp.has_property = php_phongo_timestamp_has_property; + php_phongo_handler_timestamp.unset_property = php_phongo_timestamp_unset_property; + php_phongo_handler_timestamp.get_property_ptr_ptr = php_phongo_timestamp_get_property_ptr_ptr; + php_phongo_handler_timestamp.get_gc = php_phongo_timestamp_get_gc; + php_phongo_handler_timestamp.free_obj = php_phongo_timestamp_free_object; + php_phongo_handler_timestamp.offset = XtOffsetOf(php_phongo_timestamp_t, std); } bool phongo_timestamp_new(zval* object, uint32_t increment, uint32_t timestamp) diff --git a/src/BSON/UTCDateTime.c b/src/BSON/UTCDateTime.c index d0f169858..e6293db97 100644 --- a/src/BSON/UTCDateTime.c +++ b/src/BSON/UTCDateTime.c @@ -302,8 +302,14 @@ static void php_phongo_utcdatetime_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } } @@ -363,18 +369,26 @@ static HashTable* php_phongo_utcdatetime_get_properties(zend_object* object) return php_phongo_utcdatetime_get_properties_hash(object, false); } +PHONGO_GET_PROPERTY_HANDLERS(utcdatetime, Z_OBJ_UTCDATETIME); + void php_phongo_utcdatetime_init_ce(INIT_FUNC_ARGS) { php_phongo_utcdatetime_ce = register_class_MongoDB_BSON_UTCDateTime(php_phongo_utcdatetime_interface_ce, php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); php_phongo_utcdatetime_ce->create_object = php_phongo_utcdatetime_create_object; memcpy(&php_phongo_handler_utcdatetime, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_utcdatetime.compare = php_phongo_utcdatetime_compare_objects; - php_phongo_handler_utcdatetime.clone_obj = php_phongo_utcdatetime_clone_object; - php_phongo_handler_utcdatetime.get_debug_info = php_phongo_utcdatetime_get_debug_info; - php_phongo_handler_utcdatetime.get_properties = php_phongo_utcdatetime_get_properties; - php_phongo_handler_utcdatetime.free_obj = php_phongo_utcdatetime_free_object; - php_phongo_handler_utcdatetime.offset = XtOffsetOf(php_phongo_utcdatetime_t, std); + php_phongo_handler_utcdatetime.compare = php_phongo_utcdatetime_compare_objects; + php_phongo_handler_utcdatetime.clone_obj = php_phongo_utcdatetime_clone_object; + php_phongo_handler_utcdatetime.get_debug_info = php_phongo_utcdatetime_get_debug_info; + php_phongo_handler_utcdatetime.get_properties = php_phongo_utcdatetime_get_properties; + php_phongo_handler_utcdatetime.read_property = php_phongo_utcdatetime_read_property; + php_phongo_handler_utcdatetime.write_property = php_phongo_utcdatetime_write_property; + php_phongo_handler_utcdatetime.has_property = php_phongo_utcdatetime_has_property; + php_phongo_handler_utcdatetime.unset_property = php_phongo_utcdatetime_unset_property; + php_phongo_handler_utcdatetime.get_property_ptr_ptr = php_phongo_utcdatetime_get_property_ptr_ptr; + php_phongo_handler_utcdatetime.get_gc = php_phongo_utcdatetime_get_gc; + php_phongo_handler_utcdatetime.free_obj = php_phongo_utcdatetime_free_object; + php_phongo_handler_utcdatetime.offset = XtOffsetOf(php_phongo_utcdatetime_t, std); } bool phongo_utcdatetime_new(zval* object, int64_t msec_since_epoch) diff --git a/src/MongoDB/Manager.c b/src/MongoDB/Manager.c index 2bf02fbdf..b3846bba0 100644 --- a/src/MongoDB/Manager.c +++ b/src/MongoDB/Manager.c @@ -798,8 +798,7 @@ static void php_phongo_manager_free_object(zend_object* object) } if (intern->subscribers) { - zend_hash_destroy(intern->subscribers); - FREE_HASHTABLE(intern->subscribers); + zend_hash_release(intern->subscribers); } } diff --git a/src/MongoDB/ReadConcern.c b/src/MongoDB/ReadConcern.c index 54ed384db..38a2693af 100644 --- a/src/MongoDB/ReadConcern.c +++ b/src/MongoDB/ReadConcern.c @@ -184,8 +184,14 @@ static void php_phongo_readconcern_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } if (intern->read_concern) { @@ -216,16 +222,24 @@ static HashTable* php_phongo_readconcern_get_properties(zend_object* object) return php_phongo_readconcern_get_properties_hash(object, false); } +PHONGO_GET_PROPERTY_HANDLERS(readconcern, Z_OBJ_READCONCERN); + void php_phongo_readconcern_init_ce(INIT_FUNC_ARGS) { php_phongo_readconcern_ce = register_class_MongoDB_Driver_ReadConcern(php_phongo_serializable_ce); php_phongo_readconcern_ce->create_object = php_phongo_readconcern_create_object; memcpy(&php_phongo_handler_readconcern, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_readconcern.get_debug_info = php_phongo_readconcern_get_debug_info; - php_phongo_handler_readconcern.get_properties = php_phongo_readconcern_get_properties; - php_phongo_handler_readconcern.free_obj = php_phongo_readconcern_free_object; - php_phongo_handler_readconcern.offset = XtOffsetOf(php_phongo_readconcern_t, std); + php_phongo_handler_readconcern.get_debug_info = php_phongo_readconcern_get_debug_info; + php_phongo_handler_readconcern.get_properties = php_phongo_readconcern_get_properties; + php_phongo_handler_readconcern.read_property = php_phongo_readconcern_read_property; + php_phongo_handler_readconcern.write_property = php_phongo_readconcern_write_property; + php_phongo_handler_readconcern.has_property = php_phongo_readconcern_has_property; + php_phongo_handler_readconcern.unset_property = php_phongo_readconcern_unset_property; + php_phongo_handler_readconcern.get_property_ptr_ptr = php_phongo_readconcern_get_property_ptr_ptr; + php_phongo_handler_readconcern.get_gc = php_phongo_readconcern_get_gc; + php_phongo_handler_readconcern.free_obj = php_phongo_readconcern_free_object; + php_phongo_handler_readconcern.offset = XtOffsetOf(php_phongo_readconcern_t, std); } void phongo_readconcern_init(zval* return_value, const mongoc_read_concern_t* read_concern) diff --git a/src/MongoDB/ReadPreference.c b/src/MongoDB/ReadPreference.c index cd7fed69b..100ba4a79 100644 --- a/src/MongoDB/ReadPreference.c +++ b/src/MongoDB/ReadPreference.c @@ -484,8 +484,14 @@ static void php_phongo_readpreference_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } if (intern->read_preference) { @@ -516,16 +522,24 @@ static HashTable* php_phongo_readpreference_get_properties(zend_object* object) return php_phongo_readpreference_get_properties_hash(object, false); } +PHONGO_GET_PROPERTY_HANDLERS(readpreference, Z_OBJ_READPREFERENCE); + void php_phongo_readpreference_init_ce(INIT_FUNC_ARGS) { php_phongo_readpreference_ce = register_class_MongoDB_Driver_ReadPreference(php_phongo_serializable_ce); php_phongo_readpreference_ce->create_object = php_phongo_readpreference_create_object; memcpy(&php_phongo_handler_readpreference, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_readpreference.get_debug_info = php_phongo_readpreference_get_debug_info; - php_phongo_handler_readpreference.get_properties = php_phongo_readpreference_get_properties; - php_phongo_handler_readpreference.free_obj = php_phongo_readpreference_free_object; - php_phongo_handler_readpreference.offset = XtOffsetOf(php_phongo_readpreference_t, std); + php_phongo_handler_readpreference.get_debug_info = php_phongo_readpreference_get_debug_info; + php_phongo_handler_readpreference.get_properties = php_phongo_readpreference_get_properties; + php_phongo_handler_readpreference.read_property = php_phongo_readpreference_read_property; + php_phongo_handler_readpreference.write_property = php_phongo_readpreference_write_property; + php_phongo_handler_readpreference.has_property = php_phongo_readpreference_has_property; + php_phongo_handler_readpreference.unset_property = php_phongo_readpreference_unset_property; + php_phongo_handler_readpreference.get_property_ptr_ptr = php_phongo_readpreference_get_property_ptr_ptr; + php_phongo_handler_readpreference.get_gc = php_phongo_readpreference_get_gc; + php_phongo_handler_readpreference.free_obj = php_phongo_readpreference_free_object; + php_phongo_handler_readpreference.offset = XtOffsetOf(php_phongo_readpreference_t, std); } void phongo_readpreference_init(zval* return_value, const mongoc_read_prefs_t* read_prefs) diff --git a/src/MongoDB/ServerApi.c b/src/MongoDB/ServerApi.c index 3dd6f6264..ebec9f5cc 100644 --- a/src/MongoDB/ServerApi.c +++ b/src/MongoDB/ServerApi.c @@ -212,8 +212,14 @@ static void php_phongo_serverapi_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } if (intern->server_api) { @@ -244,14 +250,22 @@ static HashTable* php_phongo_serverapi_get_properties(zend_object* object) return php_phongo_serverapi_get_properties_hash(object, false, true); } +PHONGO_GET_PROPERTY_HANDLERS(serverapi, Z_OBJ_SERVERAPI); + void php_phongo_serverapi_init_ce(INIT_FUNC_ARGS) { php_phongo_serverapi_ce = register_class_MongoDB_Driver_ServerApi(php_phongo_serializable_ce); php_phongo_serverapi_ce->create_object = php_phongo_serverapi_create_object; memcpy(&php_phongo_handler_serverapi, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_serverapi.get_debug_info = php_phongo_serverapi_get_debug_info; - php_phongo_handler_serverapi.get_properties = php_phongo_serverapi_get_properties; - php_phongo_handler_serverapi.free_obj = php_phongo_serverapi_free_object; - php_phongo_handler_serverapi.offset = XtOffsetOf(php_phongo_serverapi_t, std); + php_phongo_handler_serverapi.get_debug_info = php_phongo_serverapi_get_debug_info; + php_phongo_handler_serverapi.get_properties = php_phongo_serverapi_get_properties; + php_phongo_handler_serverapi.read_property = php_phongo_serverapi_read_property; + php_phongo_handler_serverapi.write_property = php_phongo_serverapi_write_property; + php_phongo_handler_serverapi.has_property = php_phongo_serverapi_has_property; + php_phongo_handler_serverapi.unset_property = php_phongo_serverapi_unset_property; + php_phongo_handler_serverapi.get_property_ptr_ptr = php_phongo_serverapi_get_property_ptr_ptr; + php_phongo_handler_serverapi.get_gc = php_phongo_serverapi_get_gc; + php_phongo_handler_serverapi.free_obj = php_phongo_serverapi_free_object; + php_phongo_handler_serverapi.offset = XtOffsetOf(php_phongo_serverapi_t, std); } diff --git a/src/MongoDB/ServerDescription.c b/src/MongoDB/ServerDescription.c index 7a21e9e07..360020c2c 100644 --- a/src/MongoDB/ServerDescription.c +++ b/src/MongoDB/ServerDescription.c @@ -159,8 +159,14 @@ static void php_phongo_serverdescription_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } if (intern->server_description) { @@ -267,16 +273,24 @@ static HashTable* php_phongo_serverdescription_get_properties(zend_object* objec return php_phongo_serverdescription_get_properties_hash(object, false); } +PHONGO_GET_PROPERTY_HANDLERS(serverdescription, Z_OBJ_SERVERDESCRIPTION); + void php_phongo_serverdescription_init_ce(INIT_FUNC_ARGS) { php_phongo_serverdescription_ce = register_class_MongoDB_Driver_ServerDescription(); php_phongo_serverdescription_ce->create_object = php_phongo_serverdescription_create_object; memcpy(&php_phongo_handler_serverdescription, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_serverdescription.get_debug_info = php_phongo_serverdescription_get_debug_info; - php_phongo_handler_serverdescription.get_properties = php_phongo_serverdescription_get_properties; - php_phongo_handler_serverdescription.free_obj = php_phongo_serverdescription_free_object; - php_phongo_handler_serverdescription.offset = XtOffsetOf(php_phongo_serverdescription_t, std); + php_phongo_handler_serverdescription.get_debug_info = php_phongo_serverdescription_get_debug_info; + php_phongo_handler_serverdescription.get_properties = php_phongo_serverdescription_get_properties; + php_phongo_handler_serverdescription.read_property = php_phongo_serverdescription_read_property; + php_phongo_handler_serverdescription.write_property = php_phongo_serverdescription_write_property; + php_phongo_handler_serverdescription.has_property = php_phongo_serverdescription_has_property; + php_phongo_handler_serverdescription.unset_property = php_phongo_serverdescription_unset_property; + php_phongo_handler_serverdescription.get_property_ptr_ptr = php_phongo_serverdescription_get_property_ptr_ptr; + php_phongo_handler_serverdescription.get_gc = php_phongo_serverdescription_get_gc; + php_phongo_handler_serverdescription.free_obj = php_phongo_serverdescription_free_object; + php_phongo_handler_serverdescription.offset = XtOffsetOf(php_phongo_serverdescription_t, std); } void phongo_serverdescription_init_ex(zval* return_value, mongoc_server_description_t* server_description, bool copy) diff --git a/src/MongoDB/TopologyDescription.c b/src/MongoDB/TopologyDescription.c index ab625dff0..dca234aab 100644 --- a/src/MongoDB/TopologyDescription.c +++ b/src/MongoDB/TopologyDescription.c @@ -108,8 +108,14 @@ static void php_phongo_topologydescription_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } if (intern->topology_description) { @@ -180,16 +186,24 @@ static HashTable* php_phongo_topologydescription_get_properties(zend_object* obj return php_phongo_topologydescription_get_properties_hash(object, false); } +PHONGO_GET_PROPERTY_HANDLERS(topologydescription, Z_OBJ_TOPOLOGYDESCRIPTION); + void php_phongo_topologydescription_init_ce(INIT_FUNC_ARGS) { php_phongo_topologydescription_ce = register_class_MongoDB_Driver_TopologyDescription(); php_phongo_topologydescription_ce->create_object = php_phongo_topologydescription_create_object; memcpy(&php_phongo_handler_topologydescription, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_topologydescription.get_debug_info = php_phongo_topologydescription_get_debug_info; - php_phongo_handler_topologydescription.get_properties = php_phongo_topologydescription_get_properties; - php_phongo_handler_topologydescription.free_obj = php_phongo_topologydescription_free_object; - php_phongo_handler_topologydescription.offset = XtOffsetOf(php_phongo_topologydescription_t, std); + php_phongo_handler_topologydescription.get_debug_info = php_phongo_topologydescription_get_debug_info; + php_phongo_handler_topologydescription.get_properties = php_phongo_topologydescription_get_properties; + php_phongo_handler_topologydescription.read_property = php_phongo_topologydescription_read_property; + php_phongo_handler_topologydescription.write_property = php_phongo_topologydescription_write_property; + php_phongo_handler_topologydescription.has_property = php_phongo_topologydescription_has_property; + php_phongo_handler_topologydescription.unset_property = php_phongo_topologydescription_unset_property; + php_phongo_handler_topologydescription.get_property_ptr_ptr = php_phongo_topologydescription_get_property_ptr_ptr; + php_phongo_handler_topologydescription.get_gc = php_phongo_topologydescription_get_gc; + php_phongo_handler_topologydescription.free_obj = php_phongo_topologydescription_free_object; + php_phongo_handler_topologydescription.offset = XtOffsetOf(php_phongo_topologydescription_t, std); } void phongo_topologydescription_init(zval* return_value, mongoc_topology_description_t* topology_description) diff --git a/src/MongoDB/WriteConcern.c b/src/MongoDB/WriteConcern.c index c0edb5a05..619cc9506 100644 --- a/src/MongoDB/WriteConcern.c +++ b/src/MongoDB/WriteConcern.c @@ -369,8 +369,14 @@ static void php_phongo_writeconcern_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + HashTable* props = intern->properties; + intern->properties = NULL; + zend_hash_release(props); + } + if (intern->php_properties) { + HashTable* props = intern->php_properties; + intern->php_properties = NULL; + zend_hash_release(props); } if (intern->write_concern) { @@ -401,16 +407,24 @@ static HashTable* php_phongo_writeconcern_get_properties(zend_object* object) return php_phongo_writeconcern_get_properties_hash(object, false, false, false); } +PHONGO_GET_PROPERTY_HANDLERS(writeconcern, Z_OBJ_WRITECONCERN); + void php_phongo_writeconcern_init_ce(INIT_FUNC_ARGS) { php_phongo_writeconcern_ce = register_class_MongoDB_Driver_WriteConcern(php_phongo_serializable_ce); php_phongo_writeconcern_ce->create_object = php_phongo_writeconcern_create_object; memcpy(&php_phongo_handler_writeconcern, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); - php_phongo_handler_writeconcern.get_debug_info = php_phongo_writeconcern_get_debug_info; - php_phongo_handler_writeconcern.get_properties = php_phongo_writeconcern_get_properties; - php_phongo_handler_writeconcern.free_obj = php_phongo_writeconcern_free_object; - php_phongo_handler_writeconcern.offset = XtOffsetOf(php_phongo_writeconcern_t, std); + php_phongo_handler_writeconcern.get_debug_info = php_phongo_writeconcern_get_debug_info; + php_phongo_handler_writeconcern.get_properties = php_phongo_writeconcern_get_properties; + php_phongo_handler_writeconcern.read_property = php_phongo_writeconcern_read_property; + php_phongo_handler_writeconcern.write_property = php_phongo_writeconcern_write_property; + php_phongo_handler_writeconcern.has_property = php_phongo_writeconcern_has_property; + php_phongo_handler_writeconcern.unset_property = php_phongo_writeconcern_unset_property; + php_phongo_handler_writeconcern.get_property_ptr_ptr = php_phongo_writeconcern_get_property_ptr_ptr; + php_phongo_handler_writeconcern.get_gc = php_phongo_writeconcern_get_gc; + php_phongo_handler_writeconcern.free_obj = php_phongo_writeconcern_free_object; + php_phongo_handler_writeconcern.offset = XtOffsetOf(php_phongo_writeconcern_t, std); } void phongo_writeconcern_init(zval* return_value, const mongoc_write_concern_t* write_concern) diff --git a/src/phongo_structs.h b/src/phongo_structs.h index 7b083e612..5d0f9fc86 100644 --- a/src/phongo_structs.h +++ b/src/phongo_structs.h @@ -122,12 +122,14 @@ typedef struct { typedef struct { mongoc_read_concern_t* read_concern; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_readconcern_t; typedef struct { mongoc_read_prefs_t* read_preference; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_readpreference_t; @@ -141,12 +143,14 @@ typedef struct { typedef struct { mongoc_server_api_t* server_api; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_serverapi_t; typedef struct { mongoc_server_description_t* server_description; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_serverdescription_t; @@ -160,11 +164,13 @@ typedef struct { typedef struct { mongoc_topology_description_t* topology_description; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_topologydescription_t; typedef struct { HashTable* properties; + HashTable* php_properties; mongoc_write_concern_t* write_concern; zend_object std; } php_phongo_writeconcern_t; @@ -197,18 +203,21 @@ typedef struct { int data_len; uint8_t type; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_binary_t; typedef struct { bson_t* bson; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_packedarray_t; typedef struct { bson_t* bson; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_document_t; @@ -220,6 +229,7 @@ typedef struct { size_t key; zval current; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_iterator_t; @@ -228,6 +238,7 @@ typedef struct { size_t ref_len; char id[25]; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_dbpointer_t; @@ -235,6 +246,7 @@ typedef struct { bool initialized; bson_decimal128_t decimal; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_decimal128_t; @@ -242,6 +254,7 @@ typedef struct { bool initialized; int64_t integer; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_int64_t; @@ -250,6 +263,7 @@ typedef struct { size_t code_len; bson_t* scope; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_javascript_t; @@ -265,6 +279,7 @@ typedef struct { bool initialized; char oid[25]; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_objectid_t; @@ -274,6 +289,7 @@ typedef struct { char* flags; int flags_len; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_regex_t; @@ -281,6 +297,7 @@ typedef struct { char* symbol; size_t symbol_len; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_symbol_t; @@ -289,6 +306,7 @@ typedef struct { uint32_t increment; uint32_t timestamp; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_timestamp_t; @@ -300,6 +318,7 @@ typedef struct { bool initialized; int64_t milliseconds; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_utcdatetime_t; diff --git a/tests/bson/bug1598-002.phpt b/tests/bson/bug1598-002.phpt index de32da9a8..4a55de7e6 100644 --- a/tests/bson/bug1598-002.phpt +++ b/tests/bson/bug1598-002.phpt @@ -1,12 +1,9 @@ --TEST-- PHPC-1598: BSON type get_gc should delegate to zend_std_get_properties ---SKIPIF-- - -=', '8.1.99'); ?> --FILE-- new MongoDB\BSON\Binary('foo', MongoDB\BSON\Binary::TYPE_GENERIC) ], [ 'dbpointer' => createDBPointer(), ], diff --git a/tests/bson/bug2505.phpt b/tests/bson/bug2505.phpt new file mode 100644 index 000000000..fa96d9e1d --- /dev/null +++ b/tests/bson/bug2505.phpt @@ -0,0 +1,71 @@ +--TEST-- +PHPC-2505: gc_collect_cycles() may interfere with using foreach to iterate objects +--FILE-- + new MongoDB\BSON\Binary('foo', MongoDB\BSON\Binary::TYPE_GENERIC) ], + [ 'dbpointer' => createDBPointer() ], + [ 'decimal128' => new MongoDB\BSON\Decimal128('1234.5678') ], + [ 'int64' => new MongoDB\BSON\Int64('9223372036854775807') ], + // JavaScript w/ scope may not be necessary (same code path as w/o scope), but we'll test it anyway + [ 'javascript' => new MongoDB\BSON\Javascript('function() { return 1; }') ], + + // The context is recreated every time with a different object ID + //[ 'javascript_ws' => new MongoDB\BSON\Javascript('function() { return a; }', ['a' => 1]) ], + + // MaxKey and MinKey don't have get_properties or get_gc handlers, but we'll test them anyway + [ 'maxkey' => new MongoDB\BSON\MaxKey ], + [ 'minkey' => new MongoDB\BSON\MinKey ], + [ 'objectid' => new MongoDB\BSON\ObjectId ], + [ 'regex' => new MongoDB\BSON\Regex('pattern', 'i') ], + [ 'symbol' => createSymbol() ], + [ 'timestamp' => new MongoDB\BSON\Timestamp(1234, 5678) ], + [ 'utcdatetime' => new MongoDB\BSON\UTCDateTime ], +]; + +ob_start(); +foreach ($tests as $test) { + echo key($test), "\n"; + $test = reset($test); + + foreach ($test as $k => $v) { + var_dump($k, $v); + } +} +$buf1 = ob_get_clean(); +if ($buf1 === false) { + throw new \AssertionError("Could not flush buffer"); +} + +gc_enable(); +gc_collect_cycles(); + +ob_start(); +foreach ($tests as $test) { + echo key($test), "\n"; + $test = reset($test); + + foreach ($test as $k => $v) { + var_dump($k, $v); + } +} +$buf2 = ob_get_clean(); +if ($buf2 === false) { + throw new \AssertionError("Could not flush buffer"); +} + +if ($buf1 === $buf2) { + echo "OK!\n"; + exit(0); +} else { + echo("buf1 != buf2: $buf1\n\n IS NOT EQUAL TO \n\n$buf2\n"); + exit(1); +} + +?> +--EXPECT-- +OK! \ No newline at end of file diff --git a/tests/bson/bug2505_2.phpt b/tests/bson/bug2505_2.phpt new file mode 100644 index 000000000..78aaa7467 --- /dev/null +++ b/tests/bson/bug2505_2.phpt @@ -0,0 +1,71 @@ +--TEST-- +PHPC-2505: Setting and unsetting a property may interfere with using foreach to iterate objects +--FILE-- + new MongoDB\BSON\Binary('foo', MongoDB\BSON\Binary::TYPE_GENERIC) ], + [ 'dbpointer' => createDBPointer() ], + [ 'decimal128' => new MongoDB\BSON\Decimal128('1234.5678') ], + [ 'int64' => new MongoDB\BSON\Int64('9223372036854775807') ], + // JavaScript w/ scope may not be necessary (same code path as w/o scope), but we'll test it anyway + [ 'javascript' => new MongoDB\BSON\Javascript('function() { return 1; }') ], + // The context is recreated every time with a different object ID + //[ 'javascript_ws' => new MongoDB\BSON\Javascript('function() { return a; }', ['a' => 1]) ], + // MaxKey and MinKey don't have get_properties or get_gc handlers, but we'll test them anyway + [ 'maxkey' => new MongoDB\BSON\MaxKey ], + [ 'minkey' => new MongoDB\BSON\MinKey ], + [ 'objectid' => new MongoDB\BSON\ObjectId ], + [ 'regex' => new MongoDB\BSON\Regex('pattern', 'i') ], + [ 'symbol' => createSymbol() ], + [ 'timestamp' => new MongoDB\BSON\Timestamp(1234, 5678) ], + [ 'utcdatetime' => new MongoDB\BSON\UTCDateTime ], +]; + +ob_start(); +foreach ($tests as $test) { + echo key($test), "\n"; + $test = reset($test); + + foreach ($test as $k => $v) { + var_dump($k, $v); + } +} +$buf1 = ob_get_clean(); +if ($buf1 === false) { + throw new \AssertionError("Could not flush buffer"); +} + +foreach ($tests as $test) { + $test = reset($test); + $test->a = 'test'; + unset($test->a); +} + +ob_start(); +foreach ($tests as $test) { + echo key($test), "\n"; + $test = reset($test); + + foreach ($test as $k => $v) { + var_dump($k, $v); + } +} +$buf2 = ob_get_clean(); +if ($buf2 === false) { + throw new \AssertionError("Could not flush buffer"); +} + +if ($buf1 === $buf2) { + echo "OK!\n"; + exit(0); +} else { + echo("buf1 != buf2: $buf1\n!=\n$buf2\n"); +} + +?> +--EXPECT-- +OK! \ No newline at end of file diff --git a/tests/bson/bug2505_3.phpt b/tests/bson/bug2505_3.phpt new file mode 100644 index 000000000..9327f1e7d --- /dev/null +++ b/tests/bson/bug2505_3.phpt @@ -0,0 +1,72 @@ +--TEST-- +PHPC-2505: Setting and unsetting a property may interfere with using foreach to iterate objects +--FILE-- + new MongoDB\BSON\Binary('foo', MongoDB\BSON\Binary::TYPE_GENERIC) ], + [ 'dbpointer' => createDBPointer() ], + [ 'decimal128' => new MongoDB\BSON\Decimal128('1234.5678') ], + [ 'int64' => new MongoDB\BSON\Int64('9223372036854775807') ], + // JavaScript w/ scope may not be necessary (same code path as w/o scope), but we'll test it anyway + [ 'javascript' => new MongoDB\BSON\Javascript('function() { return 1; }') ], + // The context is recreated every time with a different object ID + //[ 'javascript_ws' => new MongoDB\BSON\Javascript('function() { return a; }', ['a' => 1]) ], + // MaxKey and MinKey don't have get_properties or get_gc handlers, but we'll test them anyway + [ 'maxkey' => new MongoDB\BSON\MaxKey ], + [ 'minkey' => new MongoDB\BSON\MinKey ], + [ 'objectid' => new MongoDB\BSON\ObjectId ], + [ 'regex' => new MongoDB\BSON\Regex('pattern', 'i') ], + [ 'symbol' => createSymbol() ], + [ 'timestamp' => new MongoDB\BSON\Timestamp(1234, 5678) ], + [ 'utcdatetime' => new MongoDB\BSON\UTCDateTime ], +]; + +ob_start(); +foreach ($tests as $test) { + echo key($test), "\n"; + $test = reset($test); + + foreach ($test as $k => $v) { + var_dump($k, $v); + } +} +$buf1 = ob_get_clean(); +if ($buf1 === false) { + throw new \AssertionError("Could not flush buffer"); +} + +foreach ($tests as $test) { + $test = reset($test); + $t = &$test->a; + $t = 'test'; + unset($test->a, $t); +} + +ob_start(); +foreach ($tests as $test) { + echo key($test), "\n"; + $test = reset($test); + + foreach ($test as $k => $v) { + var_dump($k, $v); + } +} +$buf2 = ob_get_clean(); +if ($buf2 === false) { + throw new \AssertionError("Could not flush buffer"); +} + +if ($buf1 === $buf2) { + echo "OK!\n"; + exit(0); +} else { + echo("buf1 != buf2: $buf1\n!=\n$buf2\n"); +} + +?> +--EXPECT-- +OK! \ No newline at end of file diff --git a/tests/readConcern/bug1598-002.phpt b/tests/readConcern/bug1598-002.phpt index fb7450f7c..a343f81de 100644 --- a/tests/readConcern/bug1598-002.phpt +++ b/tests/readConcern/bug1598-002.phpt @@ -1,8 +1,5 @@ --TEST-- PHPC-1598: ReadConcern get_gc should delegate to zend_std_get_properties ---SKIPIF-- - -=', '8.1.99'); ?> --FILE-- -=', '8.1.99'); ?> --FILE-- -=', '8.1.99'); ?> --FILE--