📄 aggregation.c
字号:
/* * Case-insensitivity is like that last freaking mutant from horror movies: * irradiated, blown in half, its eyes melting in their sockets, yet still * dragging itself closer and closer to you until it's pulverized into * microscopic pieces via some last-minute contrivance. And even then you * are not sure that it's finally dead. But that's just how I feel. */ class_name_lc = estrndup(class_name, class_name_len); zend_str_tolower(class_name_lc, class_name_len); if (zend_hash_find(EG(class_table), class_name_lc, class_name_len+1, (void **)&ce) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expects the second parameter to be a valid class name, '%s' given", class_name); efree(class_name_lc); return; }#ifdef ZEND_ENGINE_2 ce = *(zend_class_entry**)ce;#endif /* * And God said, Let there be light; and there was light. But only once. */ if (!BG(aggregation_table)) { BG(aggregation_table) = (HashTable *) emalloc(sizeof(HashTable)); zend_hash_init(BG(aggregation_table), 5, NULL, (dtor_func_t) aggregation_info_dtor, 0); } /* * Digging deep in the rabbit hole with a long object.. and coming up * more empty than the imagination of whoever made "Battlefield Earth". */ if (zend_hash_index_find(BG(aggregation_table), (long)obj, (void**)&aggr_info) == FAILURE) { zval *tmp; /* * You are not expected to understand this. */ new_ce = emalloc(sizeof(zend_class_entry)); new_ce->type = ZEND_USER_CLASS; new_ce->name = estrndup(Z_OBJCE_P(obj)->name, Z_OBJCE_P(obj)->name_length); new_ce->name_length = Z_OBJCE_P(obj)->name_length; new_ce->parent = Z_OBJCE_P(obj)->parent;#ifdef ZEND_ENGINE_2 new_ce->refcount = 1;#else new_ce->refcount = (int *) emalloc(sizeof(int)); *new_ce->refcount = 1;#endif new_ce->constants_updated = Z_OBJCE_P(obj)->constants_updated; zend_hash_init(&new_ce->function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0); zend_hash_init(&new_ce->default_properties, 10, NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(&new_ce->function_table, &Z_OBJCE_P(obj)->function_table, (copy_ctor_func_t) function_add_ref, &tmp_zend_function, sizeof(zend_function)); zend_hash_copy(&new_ce->default_properties, &Z_OBJCE_P(obj)->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));#ifdef ZEND_ENGINE_2 ALLOC_HASHTABLE(new_ce->static_members); zend_hash_init(new_ce->static_members, 10, NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(new_ce->static_members, Z_OBJCE_P(obj)->static_members, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); zend_hash_init(&new_ce->constants_table, 10, NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(&new_ce->constants_table, &Z_OBJCE_P(obj)->constants_table, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); zend_hash_init(&new_ce->class_table, 10, NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(&new_ce->class_table, &Z_OBJCE_P(obj)->class_table, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); zend_hash_init(&new_ce->private_properties, 10, NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(&new_ce->private_properties, &Z_OBJCE_P(obj)->private_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); zend_hash_init(&new_ce->protected_properties, 10, NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(&new_ce->protected_properties, &Z_OBJCE_P(obj)->protected_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); new_ce->constructor = Z_OBJCE_P(obj)->constructor; new_ce->destructor = Z_OBJCE_P(obj)->destructor; new_ce->clone = Z_OBJCE_P(obj)->clone;#endif new_ce->builtin_functions = Z_OBJCE_P(obj)->builtin_functions; new_ce->handle_function_call = Z_OBJCE_P(obj)->handle_function_call; new_ce->handle_property_get = Z_OBJCE_P(obj)->handle_property_get; new_ce->handle_property_set = Z_OBJCE_P(obj)->handle_property_set; /* * Okay, that was kind of exhausting. Let's invoke programmer virtue #1 * and stuff this where it belongs so we don't have to work so hard next * time. */ aggr_info_new.new_ce = new_ce; MAKE_STD_ZVAL(aggr_info_new.aggr_members); array_init(aggr_info_new.aggr_members); zend_hash_index_update(BG(aggregation_table), (long)obj, (void *)&aggr_info_new, sizeof(aggregation_info), NULL); } else { /* * Seek and ye shall find. */ new_ce = aggr_info->new_ce; } /* OBJECT FIXME!! won't work with non-standard objects */ (Z_OBJ_P(obj))->ce = new_ce; /* * This should be easy to understand. If not, ask Rasmus about it at his * next tutorial. */ if (zend_hash_find(Z_ARRVAL_P(aggr_info->aggr_members), class_name_lc, class_name_len+1, (void **)&aggr_members) == FAILURE) { zval *tmp; MAKE_STD_ZVAL(tmp); array_init(tmp); MAKE_STD_ZVAL(aggr_methods_new); array_init(aggr_methods_new); MAKE_STD_ZVAL(aggr_props_new); array_init(aggr_props_new); add_assoc_zval_ex(tmp, "methods", sizeof("methods"), aggr_methods_new); add_assoc_zval_ex(tmp, "properties", sizeof("properties"), aggr_props_new); zend_hash_add(Z_ARRVAL_P(aggr_info->aggr_members), class_name_lc, class_name_len+1, &tmp, sizeof(zval *), NULL); } else { zend_hash_find(Z_ARRVAL_PP(aggr_members), "methods", sizeof("methods"), (void**)&aggr_methods); zend_hash_find(Z_ARRVAL_PP(aggr_members), "properties", sizeof("properties"), (void**)&aggr_props); } if (aggr_type == AGGREGATE_BY_LIST) { aggr_filter = aggr_list; } else if (aggr_type == AGGREGATE_BY_REGEXP) { aggr_filter = &z_aggr_regexp; } if (aggr_what == AGGREGATE_METHODS || aggr_what == AGGREGATE_ALL) { aggregate_methods(new_ce, ce, aggr_type, aggr_filter, exclude, *aggr_methods TSRMLS_CC); } if (aggr_what == AGGREGATE_PROPERTIES || aggr_what == AGGREGATE_ALL) { aggregate_properties(obj, ce, aggr_type, aggr_filter, exclude, *aggr_props TSRMLS_CC); } /* * Yes, we have to clean up after monsters. Tsk-tsk. */ efree(class_name_lc);}/* }}} *//* {{{ proto void aggregate(object obj, string class) */PHP_FUNCTION(aggregate){ aggregate(INTERNAL_FUNCTION_PARAM_PASSTHRU, AGGREGATE_ALL, AGGREGATE_ALL);}/* }}} *//* {{{ proto void aggregate_methods(object obj, string class) */PHP_FUNCTION(aggregate_methods){ aggregate(INTERNAL_FUNCTION_PARAM_PASSTHRU, AGGREGATE_METHODS, AGGREGATE_ALL);}/* }}} *//* {{{ proto void aggregate_methods_by_list(object obj, string class, array method_list [, bool exclude]) */PHP_FUNCTION(aggregate_methods_by_list){ aggregate(INTERNAL_FUNCTION_PARAM_PASSTHRU, AGGREGATE_METHODS, AGGREGATE_BY_LIST);}/* }}} *//* {{{ proto void aggregate_properties(object obj, string class) */PHP_FUNCTION(aggregate_properties){ aggregate(INTERNAL_FUNCTION_PARAM_PASSTHRU, AGGREGATE_PROPERTIES, AGGREGATE_ALL);}/* }}} *//* {{{ proto void aggregate_properties_by_list(object obj, string class, array props_list [, bool exclude]) */PHP_FUNCTION(aggregate_properties_by_list){ aggregate(INTERNAL_FUNCTION_PARAM_PASSTHRU, AGGREGATE_PROPERTIES, AGGREGATE_BY_LIST);}/* }}} */#if (HAVE_PCRE || HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE)/* {{{ proto void aggregate_methods_by_regexp(object obj, string class, string regexp [, bool exclude]) */PHP_FUNCTION(aggregate_methods_by_regexp){ aggregate(INTERNAL_FUNCTION_PARAM_PASSTHRU, AGGREGATE_METHODS, AGGREGATE_BY_REGEXP);}/* }}} *//* {{{ proto void aggregate_properties_by_regexp(object obj, string class, string regexp [, bool exclude]) */PHP_FUNCTION(aggregate_properties_by_regexp){ aggregate(INTERNAL_FUNCTION_PARAM_PASSTHRU, AGGREGATE_PROPERTIES, AGGREGATE_BY_REGEXP);}/* }}} */#endif/* {{{ proto array aggregation_info(object obj) */PHP_FUNCTION(aggregation_info){ zval *obj; aggregation_info *aggr_info; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) { return; } if (!BG(aggregation_table) || zend_hash_index_find(BG(aggregation_table), (long)obj, (void**)&aggr_info) == FAILURE) { RETURN_FALSE; } *return_value = *aggr_info->aggr_members; zval_copy_ctor(return_value);}/* }}} *//* {{{ proto void deaggregate(object obj [, string class]) */PHP_FUNCTION(deaggregate){ zval *obj; char *class_name = NULL, *class_name_lc; int class_name_len; aggregation_info *aggr_info; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|s", &obj, &class_name, &class_name_len) == FAILURE) { return; } if (!BG(aggregation_table) || zend_hash_index_find(BG(aggregation_table), (long)obj, (void**)&aggr_info) == FAILURE) { return; } if (class_name) { zval **aggr_members, **aggr_methods, **aggr_props, **method, **prop; class_name_lc = estrndup(class_name, class_name_len); zend_str_tolower(class_name_lc, class_name_len); if (zend_hash_find(Z_ARRVAL_P(aggr_info->aggr_members), class_name_lc, class_name_len+1, (void **)&aggr_members) == FAILURE) { efree(class_name_lc); return; } zend_hash_find(Z_ARRVAL_PP(aggr_members), "methods", sizeof("methods"), (void**)&aggr_methods); for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(aggr_methods)); zend_hash_get_current_data(Z_ARRVAL_PP(aggr_methods), (void**)&method) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_PP(aggr_methods))) { zend_hash_del(&Z_OBJCE_P(obj)->function_table, Z_STRVAL_PP(method), Z_STRLEN_PP(method)+1); } zend_hash_find(Z_ARRVAL_PP(aggr_members), "properties", sizeof("properties"), (void**)&aggr_props); for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(aggr_props)); zend_hash_get_current_data(Z_ARRVAL_PP(aggr_props), (void**)&prop) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_PP(aggr_props))) { zend_hash_del(Z_OBJPROP_P(obj), Z_STRVAL_PP(prop), Z_STRLEN_PP(prop)+1); } zend_hash_del(Z_ARRVAL_P(aggr_info->aggr_members), class_name_lc, class_name_len+1); efree(class_name_lc); } else { zend_class_entry *orig_ce; zval **aggr_members; zval **aggr_props, **prop; if (zend_hash_find(EG(class_table), Z_OBJCE_P(obj)->name, Z_OBJCE_P(obj)->name_length+1, (void **)&orig_ce) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal deaggregation error"); return; } for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(aggr_info->aggr_members)); zend_hash_get_current_data(Z_ARRVAL_P(aggr_info->aggr_members), (void **)&aggr_members) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_P(aggr_info->aggr_members))) { zend_hash_find(Z_ARRVAL_PP(aggr_members), "properties", sizeof("properties"), (void**)&aggr_props); for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(aggr_props)); zend_hash_get_current_data(Z_ARRVAL_PP(aggr_props), (void**)&prop) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_PP(aggr_props))) { zend_hash_del(Z_OBJPROP_P(obj), Z_STRVAL_PP(prop), Z_STRLEN_PP(prop)+1); } } /* OBJECT FIXME!! won't work with non-standard objects */ (Z_OBJ_P(obj))->ce = orig_ce; zend_hash_index_del(BG(aggregation_table), (long)obj); }}/* }}} *//* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: sw=4 ts=4 fdm=marker * vim<600: sw=4 ts=4 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -