PHP_METHOD(air_view, assign) { AIR_INIT_THIS; int argc = ZEND_NUM_ARGS(); zval *data = zend_read_property(air_view_ce, self, ZEND_STRL("_data"), 0 TSRMLS_CC); if(argc == 1){ zval *arr; if( zend_parse_parameters(argc TSRMLS_CC, "a", &arr) == FAILURE ){ AIR_NEW_EXCEPTION(1, "param 1 must be an array when only 1 param passed in"); } if(Z_TYPE_P(arr) == IS_ARRAY){ zend_hash_copy(Z_ARRVAL_P(data), Z_ARRVAL_P(arr), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); } }else{ char *key; int key_len = 0; zval *val; if( zend_parse_parameters(argc TSRMLS_CC, "sz", &key, &key_len, &val) == FAILURE ){ AIR_NEW_EXCEPTION(1, "invalid params"); } Z_ADDREF_P(val); zend_hash_update(Z_ARRVAL_P(data), key, key_len+1, &val, sizeof(zval *), NULL); } AIR_RET_THIS; }
PHP_METHOD(air_router, set_url) { AIR_INIT_THIS; char *url; uint len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &url, &len) == FAILURE) { AIR_NEW_EXCEPTION(1, "invalid set_url param"); }else{ zend_update_property_stringl(air_router_ce, self, ZEND_STRL("_url"), url, len TSRMLS_CC); } AIR_RET_THIS; }
PHP_METHOD(air_async_waiter, serve) { AIR_INIT_THIS; zval *request = NULL; if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &request) == FAILURE){ AIR_NEW_EXCEPTION(1, "invalid serve param"); } zval *service = NULL; MAKE_STD_ZVAL(service); object_init_ex(service, air_async_service_ce); zend_call_method_with_2_params(&service, air_async_service_ce, NULL, "__construct", NULL, self, request); zval *services = zend_read_property(Z_OBJCE_P(self), self, ZEND_STRL("_services"), 0 TSRMLS_CC); zval *service_id = zend_read_property(Z_OBJCE_P(service), service, ZEND_STRL("_id"), 1 TSRMLS_CC); add_index_zval(services, Z_LVAL_P(service_id), service); RETURN_ZVAL(service, 1, 0); }
/* {{{ PHP METHODS */ PHP_METHOD(air_async_service, __construct) { AIR_INIT_THIS; zval *waiter = NULL; zval *request = NULL; if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &waiter, &request) == FAILURE){ AIR_NEW_EXCEPTION(1, "invalid __construct params"); } //check if waiter is instance of air\waiter if(Z_TYPE_P(waiter) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(waiter), air_async_waiter_ce TSRMLS_CC)) { air_throw_exception(1, "param waiter must be a instance of air\\waiter"); } zend_update_property(air_async_service_ce, self, ZEND_STRL("_waiter"), waiter TSRMLS_CC); zend_update_property(air_async_service_ce, self, ZEND_STRL("request"), request TSRMLS_CC); zval *__id = zend_read_static_property(air_async_service_ce, ZEND_STRL("__id"), 0 TSRMLS_CC); (*__id).value.lval++; zend_update_property_long(air_async_service_ce, self, ZEND_STRL("_id"), Z_LVAL_P(__id) TSRMLS_CC); }
PHP_METHOD(air_async_waiter, response) { long id = 0; if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &id) == FAILURE){ AIR_NEW_EXCEPTION(1, "invalid response param"); } AIR_INIT_THIS; zval *responses = zend_read_property(air_async_waiter_ce, self, ZEND_STRL("_responses"), 0 TSRMLS_CC); zval *data = air_arr_idx_find(responses, id); if(!data){ zval *services = zend_read_property(air_async_waiter_ce, self, ZEND_STRL("_services"), 0 TSRMLS_CC); zval *service = air_arr_idx_find(services, id); if(service){ air_call_static_method(air_async_scheduler_ce, "loop", NULL, 0, NULL); data = air_arr_idx_find(responses, id); } } if(data){ RETURN_ZVAL(data, 1, 0); } RETURN_NULL(); }
PHP_METHOD(air_view, render){ AIR_INIT_THIS; char *tpl_str; int tpl_len = 0; zend_bool ret_res = 0; if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sb", &tpl_str, &tpl_len, &ret_res) == FAILURE) { RETURN_FALSE; } smart_str ss_path = {0}; if(tpl_str[0] != '/'){ zval *root_path = NULL; MAKE_STD_ZVAL(root_path); if(zend_get_constant(ZEND_STRL("ROOT_PATH"), root_path) == FAILURE){ php_error_docref(NULL TSRMLS_CC, E_ERROR, "ROOT_PATH not defined"); } smart_str_appendl(&ss_path, Z_STRVAL_P(root_path), Z_STRLEN_P(root_path)); smart_str_appendc(&ss_path, '/'); if(root_path != NULL){ zval_ptr_dtor(&root_path); } zval *tmp = NULL; zval **tmp_pp; zval *config = zend_read_property(air_view_ce, getThis(), ZEND_STRL("_config"), 0 TSRMLS_CC); if(config != NULL && Z_TYPE_P(config) == IS_ARRAY && zend_hash_find(Z_ARRVAL_P(config), ZEND_STRL("path"), (void **)&tmp_pp) == SUCCESS){ smart_str_appendl(&ss_path, Z_STRVAL_PP(tmp_pp), Z_STRLEN_PP(tmp_pp)); }else{ zval *app_conf; zval *view_conf; if(air_config_get(NULL, ZEND_STRS("app"), &app_conf TSRMLS_CC) == FAILURE){ AIR_NEW_EXCEPTION(1, "@error config: app"); } zval *app_path = NULL; if(air_config_get(app_conf, ZEND_STRS("path"), &app_path) == FAILURE){ AIR_NEW_EXCEPTION(1, "@error config: app.path"); } zval *view_path = NULL; if(air_config_get_path(app_conf, ZEND_STRS("view.path"), &view_path) == FAILURE){ AIR_NEW_EXCEPTION(1, "@view config not found"); } smart_str_appendl(&ss_path, Z_STRVAL_P(app_path), Z_STRLEN_P(app_path)); smart_str_appendc(&ss_path, '/'); smart_str_appendl(&ss_path, Z_STRVAL_P(view_path), Z_STRLEN_P(view_path)); } smart_str_appendc(&ss_path, '/'); } smart_str_appendl(&ss_path, tpl_str, tpl_len); smart_str_0(&ss_path); //php_printf("full view path: %s\n", ss_path.c); //构造运行时所需基本变量 HashTable *origin_symbol_table = NULL; zval *output_handler = NULL; long chunk_size = 0; long flags = PHP_OUTPUT_HANDLER_STDFLAGS; zval *view_ret = NULL; //尝试缓存当前符号表 if(EG(active_symbol_table)){ origin_symbol_table = EG(active_symbol_table); } if (ret_res) { MAKE_STD_ZVAL(view_ret); if(php_output_start_user(output_handler, chunk_size, flags TSRMLS_CC) == FAILURE) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to create buffer"); RETURN_FALSE; } } ALLOC_HASHTABLE(EG(active_symbol_table)); zval *data = zend_read_property(air_view_ce, getThis(), ZEND_STRL("_data"), 0 TSRMLS_CC); zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0); //将当前的模板变量放到符号表去 ZEND_SET_SYMBOL_WITH_LENGTH(EG(active_symbol_table), "var", 4, data, Z_REFCOUNT_P(data) + 1, PZVAL_IS_REF(data)); if(air_loader_include_file(ss_path.c TSRMLS_CC) == FAILURE){ air_throw_exception_ex(1, "tpl %s render failed!\n", ss_path.c); return ; } if(ret_res){ php_output_get_contents(view_ret TSRMLS_CC); php_output_discard(TSRMLS_C); RETVAL_ZVAL(view_ret, 1, 0); zval_ptr_dtor(&view_ret); } zend_hash_destroy(EG(active_symbol_table)); FREE_HASHTABLE(EG(active_symbol_table)); EG(active_symbol_table) = origin_symbol_table; smart_str_free(&ss_path); }