libs/web: drop the Lua template parser, the C implementation is faster in almost every case, even without caching

This commit is contained in:
Jo-Philipp Wich 2009-09-10 08:05:56 +00:00
parent d32f3dca5c
commit aa93e16092
2 changed files with 12 additions and 146 deletions

View file

@ -30,7 +30,6 @@ local util = require "luci.util"
local table = require "table"
local string = require "string"
local config = require "luci.config"
local coroutine = require "coroutine"
local nixio = require "nixio", require "nixio.util"
local tparser = require "luci.template.parser"
@ -43,84 +42,12 @@ local assert, type, error = assert, type, error
module "luci.template"
config.template = config.template or {}
viewdir = config.template.viewdir or util.libpath() .. "/view"
compiledir = config.template.compiledir or util.libpath() .. "/view"
-- Compile modes:
-- memory: Always compile, do not save compiled files, ignore precompiled
-- file: Compile on demand, save compiled files, update precompiled
compiler_mode = config.template.compiler_mode or "memory"
viewdir = config.template.viewdir or util.libpath() .. "/view"
-- Define the namespace for template modules
context = util.threadlocal()
--- Manually compile a given template into an executable Lua function
-- @param template LuCI template
-- @return Lua template function
function compile(template)
local expr = {}
-- Search all <% %> expressions
local function expr_add(ws1, skip1, command, skip2, ws2)
expr[#expr+1] = command
return ( #skip1 > 0 and "" or ws1 ) ..
"<%" .. tostring(#expr) .. "%>" ..
( #skip2 > 0 and "" or ws2 )
end
-- Save all expressiosn to table "expr"
template = template:gsub("(%s*)<%%(%-?)(.-)(%-?)%%>(%s*)", expr_add)
local function sanitize(s)
s = "%q" % s
return s:sub(2, #s-1)
end
-- Escape and sanitize all the template (all non-expressions)
template = sanitize(template)
-- Template module header/footer declaration
local header = 'write("'
local footer = '")'
template = header .. template .. footer
-- Replacements
local r_include = '")\ninclude("%s")\nwrite("'
local r_i18n = '")\nwrite(translate("%1","%2"))\nwrite("'
local r_i18n2 = '")\nwrite(translate("%1", ""))\nwrite("'
local r_pexec = '")\nwrite(tostring(%s or ""))\nwrite("'
local r_exec = '")\n%s\nwrite("'
-- Parse the expressions
for k,v in pairs(expr) do
local p = v:sub(1, 1)
v = v:gsub("%%", "%%%%")
local re = nil
if p == "+" then
re = r_include:format(sanitize(string.sub(v, 2)))
elseif p == ":" then
if v:find(" ") then
re = sanitize(v):gsub(":(.-) (.*)", r_i18n)
else
re = sanitize(v):gsub(":(.+)", r_i18n2)
end
elseif p == "=" then
re = r_pexec:format(v:sub(2))
elseif p == "#" then
re = ""
else
re = r_exec:format(v)
end
template = template:gsub("<%%"..tostring(k).."%%>", re)
end
return loadstring(template)
end
--- Render a certain template.
-- @param name Template name
-- @param scope Scope to assign to template (optional)
@ -138,21 +65,6 @@ Template.cache = setmetatable({}, {__mode = "v"})
-- Constructor - Reads and compiles the template on-demand
function Template.__init__(self, name)
local function _encode_filename(str)
local function __chrenc( chr )
return "%%%02x" % string.byte( chr )
end
if type(str) == "string" then
str = str:gsub(
"([^a-zA-Z0-9$_%-%.%+!*'(),])",
__chrenc
)
end
return str
end
self.template = self.cache[name]
self.name = name
@ -161,60 +73,18 @@ function Template.__init__(self, name)
self.viewns = context.viewns
-- If we have a cached template, skip compiling and loading
if self.template then
return
end
-- Enforce cache security
local cdir = compiledir .. "/" .. sys.process.info("uid")
-- Compile and build
local sourcefile = viewdir .. "/" .. name
local compiledfile = cdir .. "/" .. _encode_filename(name) .. ".lua"
local err
if compiler_mode == "file" then
local tplmt = fs.stat(sourcefile, "mtime") or fs.stat(sourcefile .. ".htm", "mtime")
local commt = fs.stat(compiledfile, "mtime")
if not fs.stat(cdir, "mtime") then
fs.mkdirr(cdir)
fs.chmod(fs.dirname(cdir), 777)
end
assert(tplmt or commt, "No such template: " .. name)
-- Build if there is no compiled file or if compiled file is outdated
if not commt or (commt and tplmt and commt < tplmt) then
local source
source, err = fs.readfile(sourcefile) or fs.readfile(sourcefile .. ".htm")
if source then
local compiled, err = compile(source)
local f = nixio.open(compiledfile, "w", 600)
f:writeall(util.get_bytecode(compiled))
f:close()
self.template = compiled
end
else
assert(
sys.process.info("uid") == fs.stat(compiledfile, "uid")
and fs.stat(compiledfile, "modestr") == "rw-------",
"Fatal: Cachefile is not sane!"
)
self.template, err = loadfile(compiledfile)
end
elseif compiler_mode == "memory" then
self.template, _, err = tparser.parse(sourcefile .. ".htm")
end
-- If we have no valid template throw error, otherwise cache the template
if not self.template then
error(err)
else
self.cache[name] = self.template
-- Compile template
local sourcefile = viewdir .. "/" .. name .. ".htm"
self.template, _, err = tparser.parse(sourcefile)
-- If we have no valid template throw error, otherwise cache the template
if not self.template then
error(err)
else
self.cache[name] = self.template
end
end
end

View file

@ -20,9 +20,5 @@ config internal sauth
config internal ccache
option enable 1
config internal template
option compiler_mode memory
option compiledir "/tmp/luci-templatecache"
config internal themes