⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 overload.c

📁 php-4.4.7学习linux时下载的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*   +----------------------------------------------------------------------+   | PHP Version 4                                                        |   +----------------------------------------------------------------------+   | Copyright (c) 1997-2007 The PHP Group                                |   +----------------------------------------------------------------------+   | This source file is subject to version 3.01 of the PHP license,      |   | that is bundled with this package in the file LICENSE, and is        |   | available through the world-wide-web at the following url:           |   | http://www.php.net/license/3_01.txt                                  |   | If you did not receive a copy of the PHP license and are unable to   |   | obtain it through the world-wide-web, please send a note to          |   | license@php.net so we can mail you a copy immediately.               |   +----------------------------------------------------------------------+   | Author: Andrei Zmievski <andrei@php.net>                             |   +----------------------------------------------------------------------+ *//*  * TODO: * + provide a way for user to enable/disabling overloading of get/set/call *   individually  * - call original overloaded handlers if necessary * + use local copy of CE with NULL'ed out handler when calling object's *   overloaded function * - handle both OE_IS_OBJECT and OE_IS_ARRAY in the whole chain * + see how to fix the issue of object trying to set its own property inside *   the handler * + check if function exists in function table, then call it, otherwise *   call handler (aka AUTOLOAD in Perl) * + should it check for existing properties first before calling __get/__set: *   yes * + turn off all overloading handlers on a call to a handler * - pass array overloading info on to handlers? * - add unoverload() function */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "php.h"#include "php_ini.h"#include "ext/standard/info.h"#include "php_overload.h"#ifndef ZEND_ENGINE_2#if HAVE_OVERLOAD#define GET_HANDLER  "__get"#define SET_HANDLER  "__set"#define CALL_HANDLER "__call"#define DISABLE_HANDLERS(ce)          \	(ce).handle_property_get  = NULL; \	(ce).handle_property_set  = NULL; \	(ce).handle_function_call = NULL;typedef struct _oo_class_data {	void (*handle_function_call)(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);	zval (*handle_property_get)(zend_property_reference *property_reference);	int (*handle_property_set)(zend_property_reference *property_reference, zval *value);	HashTable getters;	HashTable setters;} oo_class_data;ZEND_DECLARE_MODULE_GLOBALS(overload)function_entry overload_functions[] = {	PHP_FE(overload,	NULL)	{NULL, NULL, NULL}};zend_module_entry overload_module_entry = {	STANDARD_MODULE_HEADER,	"overload",	overload_functions,	PHP_MINIT(overload),	PHP_MSHUTDOWN(overload),	NULL,	PHP_RSHUTDOWN(overload),	PHP_MINFO(overload),	NO_VERSION_YET,	STANDARD_MODULE_PROPERTIES};#ifdef COMPILE_DL_OVERLOADZEND_GET_MODULE(overload)#endifstatic void overloaded_class_dtor(oo_class_data *oo_data){	zend_hash_destroy(&oo_data->getters);	zend_hash_destroy(&oo_data->setters);}/* {{{ php_overload_init_globals */static void php_overload_init_globals(zend_overload_globals *overload_globals TSRMLS_DC){	zend_hash_init(&overload_globals->overloaded_classes, 10, NULL,				   (dtor_func_t)overloaded_class_dtor, 1);}/* }}} *//* {{{ php_overload_destroy_globals */static void php_overload_destroy_globals(zend_overload_globals *overload_globals TSRMLS_DC){	zend_hash_destroy(&overload_globals->overloaded_classes);}/* }}} *//* {{{ PHP_MINIT_FUNCTION(overload) */PHP_MINIT_FUNCTION(overload){	ZEND_INIT_MODULE_GLOBALS(overload, php_overload_init_globals, php_overload_destroy_globals);	/* If you have INI entries, uncomment these lines 	REGISTER_INI_ENTRIES();	*/	return SUCCESS;}/* }}} *//* {{{ PHP_MSHUTDOWN_FUNCTION(overload) */PHP_MSHUTDOWN_FUNCTION(overload){#ifdef ZTS	ts_free_id(overload_globals_id);#else	php_overload_destroy_globals(&overload_globals TSRMLS_CC);#endif	return SUCCESS;}/* }}} *//* {{{ PHP_RSHUTDOWN_FUNCTION(overload) */PHP_RSHUTDOWN_FUNCTION(overload){	zend_hash_clean(&OOG(overloaded_classes));	return SUCCESS;}/* }}} *//* {{{ PHP_MINFO_FUNCTION */PHP_MINFO_FUNCTION(overload){	php_info_print_table_start();	php_info_print_table_row(2, "User-Space Object Overloading Support", "enabled");	php_info_print_table_end();	/* Remove comments if you have entries in php.ini	DISPLAY_INI_ENTRIES();	*/}/* }}} *//* * In all three handlers, we save the original CE of the object, and replace it * with a temporary one that has all handlers turned off. This is to avoid * recursive calls to our handlers. We can't simply set a handler to NULL on the * original CE, as that would disable overloading on other objects of the same * class. After invoking the callback we restore the object's CE. *//* {{{ static int call_get_handler() */static int call_get_handler(zval *object, zval *prop_name, zval **prop_value TSRMLS_DC){	int call_result;	zend_class_entry temp_ce, *orig_ce;	zval result, *result_ptr = &result;	zval get_handler;	zval **args[2];	zval *retval = NULL;	char *lcase_prop_name;	zval **accessor_name;	oo_class_data *oo_data;	if (zend_hash_index_find(&OOG(overloaded_classes), (long)Z_OBJCE_P(object), (void**)&oo_data) == FAILURE) {		php_error(E_WARNING, "internal problem trying to get property");		return 0;	}	temp_ce = *Z_OBJCE_P(object);	DISABLE_HANDLERS(temp_ce);	orig_ce = Z_OBJCE_P(object);	Z_OBJ_P(object)->ce = &temp_ce;	result_ptr->is_ref = 1;	result_ptr->refcount = 1;	ZVAL_NULL(result_ptr);	lcase_prop_name = estrndup(Z_STRVAL_P(prop_name), Z_STRLEN_P(prop_name));	zend_str_tolower(lcase_prop_name, Z_STRLEN_P(prop_name));	if (zend_hash_find(&oo_data->getters, lcase_prop_name,					   Z_STRLEN_P(prop_name)+1, (void **)&accessor_name) == SUCCESS) {		efree(lcase_prop_name);		args[0] = &result_ptr;		call_result = call_user_function_ex(NULL,											&object,											*accessor_name,											&retval,											1, args,											0, NULL TSRMLS_CC);		Z_OBJ_P(object)->ce = orig_ce;		if (call_result == FAILURE || !retval) {			php_error(E_WARNING, "unable to call %s::" GET_HANDLER "_%s() handler", Z_OBJCE_P(object)->name, Z_STRVAL_P(prop_name));			return 0;		}	} else {		efree(lcase_prop_name);		ZVAL_STRINGL(&get_handler, GET_HANDLER, sizeof(GET_HANDLER)-1, 0);		args[0] = &prop_name;		args[1] = &result_ptr;		call_result = call_user_function_ex(NULL,											&object,											&get_handler,											&retval,											2, args,											0, NULL TSRMLS_CC);		Z_OBJ_P(object)->ce = orig_ce;		if (call_result == FAILURE || !retval) {			php_error(E_WARNING, "unable to call %s::" GET_HANDLER "() handler", Z_OBJCE_P(object)->name);			return 0;		}	}	if (zval_is_true(retval)) {		REPLACE_ZVAL_VALUE(prop_value, result_ptr, 0);		zval_ptr_dtor(&retval);		return 1;	}	zval_ptr_dtor(&retval);	zval_dtor(result_ptr);	if (!oo_data->handle_property_get) {		return 0;	}	/* TODO: call original OO handler */	return 0;}/* }}} *//* {{{ static int call_set_handler() */int call_set_handler(zval *object, zval *prop_name, zval *value TSRMLS_DC){	int call_result;	zend_class_entry temp_ce, *orig_ce;	zval set_handler;	zval *value_copy;	zval **args[2];	zval *retval = NULL;	char *lcase_prop_name;	zval **accessor_name;	oo_class_data *oo_data;	if (zend_hash_index_find(&OOG(overloaded_classes), (long)Z_OBJCE_P(object), (void**)&oo_data) == FAILURE) {		php_error(E_WARNING, "internal problem trying to set property");		return 0;	}	temp_ce = *Z_OBJCE_P(object);	DISABLE_HANDLERS(temp_ce);	orig_ce = Z_OBJCE_P(object);	Z_OBJ_P(object)->ce = &temp_ce;	if (value->refcount == 0) {		MAKE_STD_ZVAL(value_copy);		*value_copy = *value;		zval_copy_ctor(value_copy);		value = value_copy;	}	lcase_prop_name = estrndup(Z_STRVAL_P(prop_name), Z_STRLEN_P(prop_name));	zend_str_tolower(lcase_prop_name, Z_STRLEN_P(prop_name));	if (zend_hash_find(&oo_data->setters, lcase_prop_name,					   Z_STRLEN_P(prop_name)+1, (void **)&accessor_name) == SUCCESS) {		efree(lcase_prop_name);		args[0] = &value;		call_result = call_user_function_ex(NULL,											&object,											*accessor_name,											&retval,											1, args,											0, NULL TSRMLS_CC);		Z_OBJ_P(object)->ce = orig_ce;		if (call_result == FAILURE || !retval) {			php_error(E_WARNING, "unable to call %s::" SET_HANDLER "_%s() handler", Z_OBJCE_P(object)->name, Z_STRVAL_P(prop_name));			return 0;		}	} else {		efree(lcase_prop_name);		ZVAL_STRINGL(&set_handler, SET_HANDLER, sizeof(SET_HANDLER)-1, 0);		args[0] = &prop_name;		args[1] = &value;		call_result = call_user_function_ex(NULL,											&object,											&set_handler,											&retval,											2, args,											0, NULL TSRMLS_CC);		Z_OBJ_P(object)->ce = orig_ce;		if (call_result == FAILURE || !retval) {			php_error(E_WARNING, "unable to call %s::" SET_HANDLER "() handler", orig_ce->name);			return 0;		}	}	if (zval_is_true(retval)) {		zval_ptr_dtor(&retval);		return 1;	}	zval_ptr_dtor(&retval);	if (!oo_data->handle_property_set) {		return 0;	}	/* TODO: call original OO handler */	return 0;}/* }}} */#define CLEANUP_OO_CHAIN() { \	for (; element; element=element->next) { \		zval_dtor(&((zend_overloaded_element *)element->data)->element); \	} \} \/* {{{ zval overload_get_property() */static zval overload_get_property(zend_property_reference *property_reference){	zval result;	zval *result_ptr = &result;	zend_overloaded_element *overloaded_property;	zend_llist_element *element;	zval object = *property_reference->object;	zval **real_prop;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -