c = buf[i];
switch (state)
{
case tpl_state_normal:
switch(c){
case '{':
state = tpl_state_scode_1;
break;
}
break;
case tpl_state_scode_1:
switch(c){
case '#':
state =tpl_state_code;
append_end_stringfield(mem,sbuf, &buf[i] - sbuf-1);
sbuf = &buf[i+1];
break;
default:
state = tpl_state_normal;
break;
}
break;
case tpl_state_code:
switch(c){
case '#':
state = tpl_state_ecode_1;
break;
}
case tpl_state_ecode_1:
switch(c){
case '}':
automem_append_voidp(mem,sbuf, &buf[i] - sbuf-1);
automem_append_byte(mem,'\n');
sbuf = &buf[i+1];
state = tpl_state_normal;
break;
default:
state=tpl_state_code;
}
default:
break;
}
i++;
}
if(tpl_state_normal == state){
append_end_stringfield(mem,sbuf, &buf[i] - sbuf);
}
}
/* 对模板文件进行编译.*/
static int lua_tpl_compile(lua_State * L)
{
int cache = 0,i = 0, lbuf = 0;
size_t lfile;
const char *cfile = NULL, * file= luaL_checklstring(L, 1,&lfile),* buf;
automem_t mem;
if(lua_isboolean(L, 2))
cache =lua_toboolean(L, 2);
if(0 != cache){
struct stat st1,st2;
cfile=(char *)malloc(lfile+5);
memcpy((char *)cfile,file,lfile);
strcpy((char *)cfile+lfile,".tpl");
if((0 == stat(file,&st1)) && (0 == stat(cfile, &st2)))
{
if(st1.st_mtime <&#61; st2.st_mtime)
{
if(NULL !&#61; (buf &#61; file_get_contents(cfile, &lbuf)))
{
free((void *)cfile);
lua_pushlstring(L,buf, lbuf);
goto lua_tpl_compile_final;
}
}
}
}
if(NULL !&#61; (buf &#61; file_get_contents(file, &lbuf)))
{
automem_init(&mem,lbuf &#43; 1024);
lua_tpl_compile_local(L, &mem, buf, lbuf);
free((void*)buf);
lua_pushlstring(L,(char *)mem.pdata,mem.size);
if(0 !&#61; cache && NULL !&#61;cfile)
file_put_contents(cfile,&mem);
automem_uninit(&mem);
}
if(NULL !&#61; cfile)
free((void *)cfile);
lua_tpl_compile_final:
return 1;
}
static luaL_Reg fmt_tpl_reg[] &#61; {
{"compile",lua_tpl_compile},
{NULL,NULL}
};
int luaopen_cfmt_tpl(lua_State * L)
{
luaL_newlib(L, fmt_tpl_reg);
lua_cfmt_createmetatable(L);
return 1;
}
整个LUA模块扩展就1个函数 compile()。在LUA中的原型如下&#xff1a;
string compile(filePath,cached, write, prefix,suffix,init)
功能: 将html模板编译为lua代码.
参数:
filePath: html源文件的路径.
cached: 是否需要缓存.
writer: 内容输出函数名.
prefix: 文件分界符前缀.
init:初始代码,用于做参数展开之类的工作.
当然,光有C的接口还不够&#xff0c;为了使它变得简单易用&#xff0c;还需要用LUA对其包装一下^_^, 包装代码如下:
function util.tpl(writer)
local t &#61; require "cfmt.tpl"
local tpl &#61; {}
local args &#61; {}
local _prefix&#61;&#39;[&#61;[&#39;
local _suffix&#61;&#39;]&#61;]&#39;
-- 创建的时候指定 writer
if nil ~&#61; writer then args[&#39;_&#39;]&#61;writer end
function tpl:assign(name,value)
args[name]&#61;value
end
function tpl:boundary(prefix, suffix) --修改字符串边界符
if nil ~&#61; prefix then _prefix&#61;prefix end
if nil ~&#61; suffix then _suffix&#61;suffix end
end
function tpl:display(tpl,cache,writer) -- tpl 模板文件位置, cache 是否需要缓存 writer 可选,如果创建对象的时候指定了的话.
local i&#61;1
if nil~&#61;writer then args[&#39;_&#39;]&#61;writer end
local init &#61; {&#39;local args &#61; ...&#39;}
for key,val in pairs(args) do
init[#init&#43;1]&#61;&#39;local &#39;..key..&#39;&#61;args["&#39;..key..&#39;"]&#39;
i&#61;i&#43;1
end
init &#61; table.concat(init,&#39;\n&#39;)
local code &#61;t.compile(tpl,cache,&#39;_(&#39;.._prefix, _suffix,init)
load(code)(args)
end
return tpl;
end
接下来用起来就简单多了,上测试代码.
---外部进来的数据在这里做检测
function login:request(r)
local tpl &#61; (require "util").tpl(r.print)
local users &#61;{
{[&#39;ID&#39;]&#61;1,[&#39;username&#39;]&#61;&#39;bywayboy&#39;,[&#39;age&#39;]&#61;31},
{[&#39;ID&#39;]&#61;1,[&#39;username&#39;]&#61;&#39;liigo&#39;,[&#39;age&#39;]&#61;31},
{[&#39;ID&#39;]&#61;1,[&#39;username&#39;]&#61;&#39;sunwei&#39;,[&#39;age&#39;]&#61;8},
}
local b&#61;{[&#39;a&#39;]&#61;12}
tpl:assign(&#39;users&#39;,users);
tpl:assign(&#39;title&#39;,"测试模板变量.")
tpl:assign(&#39;name&#39;,"某某童鞋")
tpl:display("D:\\VC\\CmdChannel\\win32\\Debug\\test.html",true)
end
再来一个模板文件示例:
{#_(title)#}--方121212法table{border:1px solid #CCC;}
{# for key,val in pairs(users) do#}
{#_(val[&#39;ID&#39;]) #}{#_(val[&#39;username&#39;])#}{#_(val[&#39;age&#39;])#}{#end#}
{#_(name)#}
该文件最终生成的缓存文件为:
local args &#61; ...
local _&#61;args["_"]
local name&#61;args["name"]
local users&#61;args["users"]
local title&#61;args["title"]
_([&#61;[
]&#61;])_(title)
_([&#61;[--方121212法
table{border:1px solid #CCC;}
]&#61;])
for key,val in pairs(users) do
_([&#61;[
]&#61;])_(val[&#39;ID&#39;])
_([&#61;[
]&#61;])_(val[&#39;username&#39;])
_([&#61;[
]&#61;])_(val[&#39;age&#39;])
_([&#61;[
]&#61;])
end
_([&#61;[
]&#61;])
_(name)
_([&#61;[
]&#61;])
输出结果如图:
最终生成的HTML代码如下:
测试模板变量.--方121212法table{border:1px solid #CCC;}
ID | 姓名 | 年龄 |
1 | bywayboy | 31 |
1 | liigo | 31 |
1 | sunwei | 8 |
某某童鞋
目前该项目已经开源:
https://github.com/bywayboy/lua-modules