Skip to content
Permalink
Browse files

1. Refactor Yaf_Loader for better performance

2. Remove st_compatible which is out of date, it only used in Baidu AP framework
  • Loading branch information
laruence committed Mar 9, 2020
1 parent 2285556 commit 3c6937f5cc831c407913819a5a98e1d76aa2cba8
Showing with 332 additions and 388 deletions.
  1. +0 −3 yaf.c
  2. +2 −2 yaf_application.c
  3. +86 −159 yaf_dispatcher.c
  4. +242 −206 yaf_loader.c
  5. +2 −18 yaf_loader.h
3 yaf.c
@@ -71,9 +71,6 @@ PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("yaf.forward_limit", "5", PHP_INI_ALL, OnUpdateLongGEZero, forward_limit, zend_yaf_globals, yaf_globals) STD_PHP_INI_ENTRY("yaf.forward_limit", "5", PHP_INI_ALL, OnUpdateLongGEZero, forward_limit, zend_yaf_globals, yaf_globals)
STD_PHP_INI_BOOLEAN("yaf.name_suffix", "1", PHP_INI_ALL, OnUpdateBool, name_suffix, zend_yaf_globals, yaf_globals) STD_PHP_INI_BOOLEAN("yaf.name_suffix", "1", PHP_INI_ALL, OnUpdateBool, name_suffix, zend_yaf_globals, yaf_globals)
PHP_INI_ENTRY("yaf.name_separator", "", PHP_INI_ALL, OnUpdateSeparator) PHP_INI_ENTRY("yaf.name_separator", "", PHP_INI_ALL, OnUpdateSeparator)
/* {{{ This only effects internally */
STD_PHP_INI_BOOLEAN("yaf.st_compatible", "0", PHP_INI_ALL, OnUpdateBool, st_compatible, zend_yaf_globals, yaf_globals)
/* }}} */
STD_PHP_INI_ENTRY("yaf.environ", "product", PHP_INI_SYSTEM, OnUpdateString, environ_name, zend_yaf_globals, yaf_globals) STD_PHP_INI_ENTRY("yaf.environ", "product", PHP_INI_SYSTEM, OnUpdateString, environ_name, zend_yaf_globals, yaf_globals)
STD_PHP_INI_BOOLEAN("yaf.use_namespace", "0", PHP_INI_SYSTEM, OnUpdateBool, use_namespace, zend_yaf_globals, yaf_globals) STD_PHP_INI_BOOLEAN("yaf.use_namespace", "0", PHP_INI_SYSTEM, OnUpdateBool, use_namespace, zend_yaf_globals, yaf_globals)
PHP_INI_END(); PHP_INI_END();
@@ -520,20 +520,20 @@ PHP_METHOD(yaf_application, environ) {
/** {{{ proto public Yaf_Application::bootstrap(void) /** {{{ proto public Yaf_Application::bootstrap(void)
*/ */
PHP_METHOD(yaf_application, bootstrap) { PHP_METHOD(yaf_application, bootstrap) {
zend_string *bootstrap_path;
unsigned retval = 1; unsigned retval = 1;
zend_class_entry *ce; zend_class_entry *ce;
yaf_application_t *self = getThis(); yaf_application_t *self = getThis();


if (!(ce = zend_hash_str_find_ptr(EG(class_table), if (!(ce = zend_hash_str_find_ptr(EG(class_table),
YAF_DEFAULT_BOOTSTRAP_LOWER, sizeof(YAF_DEFAULT_BOOTSTRAP_LOWER) - 1))) { YAF_DEFAULT_BOOTSTRAP_LOWER, sizeof(YAF_DEFAULT_BOOTSTRAP_LOWER) - 1))) {
zend_string *bootstrap_path;
if (YAF_G(bootstrap)) { if (YAF_G(bootstrap)) {
bootstrap_path = zend_string_copy(YAF_G(bootstrap)); bootstrap_path = zend_string_copy(YAF_G(bootstrap));
} else { } else {
bootstrap_path = strpprintf(0, "%s%c%s.%s", bootstrap_path = strpprintf(0, "%s%c%s.%s",
ZSTR_VAL(YAF_G(directory)), DEFAULT_SLASH, YAF_DEFAULT_BOOTSTRAP, ZSTR_VAL(YAF_G(ext))); ZSTR_VAL(YAF_G(directory)), DEFAULT_SLASH, YAF_DEFAULT_BOOTSTRAP, ZSTR_VAL(YAF_G(ext)));
} }
if (!yaf_loader_import(bootstrap_path, 0)) { if (!yaf_loader_import(ZSTR_VAL(bootstrap_path), ZSTR_LEN(bootstrap_path))) {
php_error_docref(NULL, E_WARNING, "Couldn't find bootstrap file %s", ZSTR_VAL(bootstrap_path)); php_error_docref(NULL, E_WARNING, "Couldn't find bootstrap file %s", ZSTR_VAL(bootstrap_path));
retval = 0; retval = 0;
} else if (UNEXPECTED((ce = zend_hash_str_find_ptr(EG(class_table), } else if (UNEXPECTED((ce = zend_hash_str_find_ptr(EG(class_table),
@@ -283,223 +283,150 @@ int yaf_dispatcher_set_request(yaf_dispatcher_t *dispatcher, yaf_request_t *requ
/* }}} */ /* }}} */


zend_class_entry *yaf_dispatcher_get_controller(zend_string *app_dir, zend_string *module, zend_string *controller, int def_module) /* {{{ */ { zend_class_entry *yaf_dispatcher_get_controller(zend_string *app_dir, zend_string *module, zend_string *controller, int def_module) /* {{{ */ {
char *directory; char directory[MAXPATHLEN];
size_t directory_len; size_t directory_len;
zend_class_entry *ce;
zend_string *lc_name;


if (def_module) { if (def_module) {
directory_len = spprintf(&directory, 0, directory_len = snprintf(directory, sizeof(directory),
"%s%c%s", ZSTR_VAL(app_dir), DEFAULT_SLASH, YAF_CONTROLLER_DIRECTORY_NAME); "%s%c%s", ZSTR_VAL(app_dir), DEFAULT_SLASH, YAF_CONTROLLER_DIRECTORY_NAME);
} else { } else {
directory_len = spprintf(&directory, 0, directory_len = snprintf(directory, 0,
"%s%c%s%c%s%c%s", ZSTR_VAL(app_dir), DEFAULT_SLASH, YAF_MODULE_DIRECTORY_NAME, "%s%c%s%c%s%c%s", ZSTR_VAL(app_dir), DEFAULT_SLASH, YAF_MODULE_DIRECTORY_NAME,
DEFAULT_SLASH, ZSTR_VAL(module), DEFAULT_SLASH, YAF_CONTROLLER_DIRECTORY_NAME); DEFAULT_SLASH, ZSTR_VAL(module), DEFAULT_SLASH, YAF_CONTROLLER_DIRECTORY_NAME);
} }


if (EXPECTED(directory_len)) { if (directory_len >= sizeof(directory)) {
zend_string *class; yaf_trigger_error(YAF_ERR_AUTOLOAD_FAILED, "path too long %s: %s", directory);
zend_string *class_lowercase; return NULL;
zend_class_entry *ce = NULL; }


if (YAF_G(name_suffix)) { lc_name = zend_string_alloc(ZSTR_LEN(controller) + YAF_G(name_separator_len) + sizeof("Controller") - 1, 0);
class = strpprintf(0, "%s%s%s", ZSTR_VAL(controller), YAF_G(name_separator), "Controller"); if (EXPECTED(YAF_G(name_suffix))) {
} else { char *p = ZSTR_VAL(lc_name);
class = strpprintf(0, "%s%s%s", "Controller", YAF_G(name_separator), ZSTR_VAL(controller)); zend_str_tolower_copy(p, ZSTR_VAL(controller), ZSTR_LEN(controller));
p += ZSTR_LEN(controller);
if (UNEXPECTED(YAF_G(name_separator_len))) {
zend_str_tolower_copy(p, YAF_G(name_separator), YAF_G(name_separator_len));
p += YAF_G(name_separator_len);
} }
memcpy(p, "controller", sizeof("controller"));
} else {
char *p = ZSTR_VAL(lc_name);
memcpy(p, "controller", sizeof("controller") - 1);
p += sizeof("controller") - 1;
if (UNEXPECTED(YAF_G(name_separator_len))) {
zend_str_tolower_copy(p, YAF_G(name_separator), YAF_G(name_separator_len));
p += YAF_G(name_separator_len);
}
zend_str_tolower_copy(p, ZSTR_VAL(controller), ZSTR_LEN(controller) + 1);
}


class_lowercase = zend_string_tolower(class); if ((ce = (zend_class_entry*)zend_hash_find_ptr(EG(class_table), lc_name)) == NULL) {

if (!yaf_loader_load(NULL, ZSTR_VAL(controller), ZSTR_LEN(controller), directory, directory_len)) {
if ((ce = zend_hash_find_ptr(EG(class_table), class_lowercase)) == NULL) { yaf_trigger_error(YAF_ERR_NOTFOUND_CONTROLLER,
if (!yaf_internal_autoload(ZSTR_VAL(controller), ZSTR_LEN(controller), &directory)) { "Failed opening controller script %s: %s", directory, strerror(errno));
yaf_trigger_error(YAF_ERR_NOTFOUND_CONTROLLER, zend_string_release(lc_name);
"Failed opening controller script %s: %s", directory, strerror(errno)); return NULL;
zend_string_release(class); } else if ((ce = zend_hash_find_ptr(EG(class_table), lc_name)) == NULL) {
zend_string_release(class_lowercase); zend_string_release(lc_name);
efree(directory); if (EXPECTED(YAF_G(name_suffix))) {
return NULL;
} else if ((ce = zend_hash_find_ptr(EG(class_table), class_lowercase)) == NULL) {
yaf_trigger_error(YAF_ERR_AUTOLOAD_FAILED, yaf_trigger_error(YAF_ERR_AUTOLOAD_FAILED,
"Could not find class %s in controller script %s", ZSTR_VAL(class), directory); "Could not find class %s%s%s in controller script %s",
zend_string_release(class); ZSTR_VAL(controller), YAF_G(name_separator), "Controller", directory);
zend_string_release(class_lowercase); } else {
efree(directory); yaf_trigger_error(YAF_ERR_AUTOLOAD_FAILED,
return 0; "Could not find class %s%s%s in controller script %s",
} else if (!instanceof_function(ce, yaf_controller_ce)) { "Controller", YAF_G(name_separator), ZSTR_VAL(controller), directory);
yaf_trigger_error(YAF_ERR_TYPE_ERROR,
"Controller must be an instance of %s", ZSTR_VAL(yaf_controller_ce->name));
zend_string_release(class);
zend_string_release(class_lowercase);
efree(directory);
return 0;
} }
return 0;
} else if (!instanceof_function(ce, yaf_controller_ce)) {
yaf_trigger_error(YAF_ERR_TYPE_ERROR,
"Controller must be an instance of %s", ZSTR_VAL(yaf_controller_ce->name));
zend_string_release(lc_name);
return 0;
} }
}


zend_string_release(class); zend_string_release(lc_name);
zend_string_release(class_lowercase);
efree(directory);


return ce; return ce;
}


return NULL;
} }
/* }}} */ /* }}} */


zend_class_entry *yaf_dispatcher_get_action(zend_string *app_dir, yaf_controller_t *controller, char *module, int def_module, zend_string *action) /* {{{ */ { zend_class_entry *yaf_dispatcher_get_action(zend_string *app_dir, yaf_controller_t *controller, char *module, int def_module, zend_string *action) /* {{{ */ {
zval *paction, *actions_map; zval *paction, *actions_map;
actions_map = zend_read_property(Z_OBJCE_P(controller), actions_map = zend_read_property(Z_OBJCE_P(controller), controller, ZEND_STRL(YAF_CONTROLLER_PROPERTY_NAME_ACTIONS), 1, NULL);
controller, ZEND_STRL(YAF_CONTROLLER_PROPERTY_NAME_ACTIONS), 1, NULL);


if (Z_TYPE_P(actions_map) == IS_REFERENCE) { ZVAL_DEREF(actions_map);
actions_map = Z_REFVAL_P(actions_map);
}


if (EXPECTED(IS_ARRAY == Z_TYPE_P(actions_map))) { if (EXPECTED(IS_ARRAY == Z_TYPE_P(actions_map))) {
zend_class_entry *ce; zend_class_entry *ce;
zend_string *class; zend_string *lc_name;
zend_string *class_lowercase;
char *action_upper = estrndup(ZSTR_VAL(action), ZSTR_LEN(action)); lc_name = zend_string_alloc(ZSTR_LEN(action) + YAF_G(name_separator_len) + sizeof("Action") - 1, 0);

if (EXPECTED(YAF_G(name_suffix))) {
*(action_upper) = toupper(*action_upper); char *p = ZSTR_VAL(lc_name);

zend_str_tolower_copy(p, ZSTR_VAL(action), ZSTR_LEN(action));
if (YAF_G(name_suffix)) { p += ZSTR_LEN(action);
class = strpprintf(0, "%s%s%s", action_upper, YAF_G(name_separator), "Action"); if (UNEXPECTED(YAF_G(name_separator_len))) {
zend_str_tolower_copy(p, YAF_G(name_separator), YAF_G(name_separator_len));
p += YAF_G(name_separator_len);
}
memcpy(p, "action", sizeof("action"));
} else { } else {
class = strpprintf(0, "%s%s%s", "Action", YAF_G(name_separator), action_upper); char *p = ZSTR_VAL(lc_name);
memcpy(p, "action", sizeof("action"));
p += sizeof("action") - 1;
if (UNEXPECTED(YAF_G(name_separator_len))) {
zend_str_tolower_copy(p, YAF_G(name_separator), YAF_G(name_separator_len));
p += YAF_G(name_separator_len);
}
zend_str_tolower_copy(p, ZSTR_VAL(action), ZSTR_LEN(action) + 1);
} }


class_lowercase = zend_string_tolower(class); if ((ce = zend_hash_find_ptr(EG(class_table), lc_name)) != NULL) {

zend_string_release(lc_name);
if ((ce = zend_hash_find_ptr(EG(class_table), class_lowercase)) != NULL) {
efree(action_upper);
zend_string_release(class_lowercase);
if (instanceof_function(ce, yaf_action_ce)) { if (instanceof_function(ce, yaf_action_ce)) {
zend_string_release(class);
return ce; return ce;
} else { } else {
yaf_trigger_error(YAF_ERR_TYPE_ERROR, yaf_trigger_error(YAF_ERR_TYPE_ERROR,
"Action %s must extends from %s", ZSTR_VAL(class), ZSTR_VAL(yaf_action_ce->name)); "Action %s must extends from %s", ZSTR_VAL(action), ZSTR_VAL(yaf_action_ce->name));
zend_string_release(class);
return NULL; return NULL;
} }
} }


if ((paction = zend_hash_find(Z_ARRVAL_P(actions_map), action)) != NULL) { if ((paction = zend_hash_find(Z_ARRVAL_P(actions_map), action)) != NULL) {
if (Z_TYPE_P(paction) == IS_REFERENCE) {
paction = Z_REFVAL_P(paction);
}

zend_string *action_path; zend_string *action_path;
ZVAL_DEREF(paction);


action_path = strpprintf(0, "%s%c%s", ZSTR_VAL(app_dir), DEFAULT_SLASH, Z_STRVAL_P(paction)); action_path = strpprintf(0, "%s%c%s", ZSTR_VAL(app_dir), DEFAULT_SLASH, Z_STRVAL_P(paction));
if (yaf_loader_import(action_path, 0)) { if (yaf_loader_import(ZSTR_VAL(action_path), ZSTR_LEN(action_path))) {
if ((ce = zend_hash_find_ptr(EG(class_table), class_lowercase)) != NULL) { if ((ce = zend_hash_find_ptr(EG(class_table), lc_name)) != NULL) {
zend_string_release(action_path);
efree(action_upper);
zend_string_release(class_lowercase);

if (instanceof_function(ce, yaf_action_ce)) { if (instanceof_function(ce, yaf_action_ce)) {
zend_string_release(class); zend_string_release(action_path);
zend_string_release(lc_name);
return ce; return ce;
} else { } else {
yaf_trigger_error(YAF_ERR_TYPE_ERROR, yaf_trigger_error(YAF_ERR_TYPE_ERROR,
"Action %s must extends from %s", ZSTR_VAL(class), ZSTR_VAL(yaf_action_ce->name)); "Action %s must extends from %s", ZSTR_VAL(action), ZSTR_VAL(yaf_action_ce->name));
zend_string_release(class);
} }

} else { } else {
yaf_trigger_error(YAF_ERR_NOTFOUND_ACTION, yaf_trigger_error(YAF_ERR_NOTFOUND_ACTION,
"Could not find action %s in %s", ZSTR_VAL(class), ZSTR_VAL(action_path)); "Could not find action %s in %s", ZSTR_VAL(action), ZSTR_VAL(action_path));
} }

zend_string_release(action_path);
efree(action_upper);
zend_string_release(class);
zend_string_release(class_lowercase);
} else { } else {
yaf_trigger_error(YAF_ERR_NOTFOUND_ACTION, yaf_trigger_error(YAF_ERR_NOTFOUND_ACTION,
"Failed opening action script %s: %s", ZSTR_VAL(action_path), strerror(errno)); "Failed opening action script %s: %s", ZSTR_VAL(action_path), strerror(errno));
zend_string_release(action_path);
} }
zend_string_release(action_path);
} else { } else {
yaf_trigger_error(YAF_ERR_NOTFOUND_ACTION, "There is no method %s%s in %s::$%s", ZSTR_VAL(action), yaf_trigger_error(YAF_ERR_NOTFOUND_ACTION, "There is no method %s%s in %s::$%s", ZSTR_VAL(action),
"Action", ZSTR_VAL(Z_OBJCE_P(controller)->name), YAF_CONTROLLER_PROPERTY_NAME_ACTIONS); "Action", ZSTR_VAL(Z_OBJCE_P(controller)->name), YAF_CONTROLLER_PROPERTY_NAME_ACTIONS);
} }
} else } else {
/* {{{ This only effects internally */
if (YAF_G(st_compatible)) {
char *directory, *class, *class_lowercase, *p;
unsigned class_len;
zend_class_entry *ce;
char *action_upper = estrndup(ZSTR_VAL(action), ZSTR_LEN(action));

/**
* upper Action Name
* eg: Index_sub -> Index_Sub
*/
p = action_upper;
*(p) = toupper(*p);
while (*p != '\0') {
if (*p == '_' || *p == '\\') {
if (*(p+1) != '\0') {
*(p+1) = toupper(*(p+1));
p++;
}
}
p++;
}

if (def_module) {
spprintf(&directory, 0, "%s%c%s", ZSTR_VAL(app_dir), DEFAULT_SLASH, "actions");
} else {
spprintf(&directory, 0, "%s%c%s%c%s%c%s", ZSTR_VAL(app_dir), DEFAULT_SLASH,
"modules", DEFAULT_SLASH, module, DEFAULT_SLASH, "actions");
}

if (YAF_G(name_suffix)) {
class_len = spprintf(&class, 0, "%s%s%s", action_upper, YAF_G(name_separator), "Action");
} else {
class_len = spprintf(&class, 0, "%s%s%s", "Action", YAF_G(name_separator), action_upper);
}

class_lowercase = zend_str_tolower_dup(class, class_len);

if ((ce = zend_hash_str_find_ptr(EG(class_table), class_lowercase, class_len)) == NULL) {
if (!yaf_internal_autoload(action_upper, ZSTR_LEN(action), &directory)) {
yaf_trigger_error(YAF_ERR_NOTFOUND_ACTION, "Failed opening action script %s: %s", directory, strerror(errno));

efree(class);
efree(action_upper);
efree(class_lowercase);
efree(directory);
return NULL;
} else if ((ce = zend_hash_str_find_ptr(EG(class_table), class_lowercase, class_len)) == NULL) {
yaf_trigger_error(YAF_ERR_AUTOLOAD_FAILED, "Could find class %s in action script %s", class, directory);

efree(class);
efree(action_upper);
efree(class_lowercase);
efree(directory);
return NULL;
} else if (!instanceof_function(ce, yaf_action_ce)) {
yaf_trigger_error(YAF_ERR_TYPE_ERROR, "Action must be an instance of %s", ZSTR_VAL(yaf_action_ce->name));

efree(class);
efree(action_upper);
efree(class_lowercase);
efree(directory);
return NULL;
}
}

efree(class);
efree(action_upper);
efree(class_lowercase);
efree(directory);

return ce;
} else
/* }}} */
{
yaf_trigger_error(YAF_ERR_NOTFOUND_ACTION, yaf_trigger_error(YAF_ERR_NOTFOUND_ACTION,
"There is no method %s%s in %s", ZSTR_VAL(action), "Action", ZSTR_VAL(Z_OBJCE_P(controller)->name)); "There is no method %s%s in %s", ZSTR_VAL(action), "Action", ZSTR_VAL(Z_OBJCE_P(controller)->name));
} }

0 comments on commit 3c6937f

Please sign in to comment.
You can’t perform that action at this time.