aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWaqas Hussain <waqas20@gmail.com>2010-10-24 15:08:22 +0500
committerWaqas Hussain <waqas20@gmail.com>2010-10-24 15:08:22 +0500
commit9f58b6013a9b70bcc10dfbb556de93fcda4d3131 (patch)
treeb4f35bf06b0169901dcc2e68473fc83793de6823
parent7115e72cfe1964bb10cc2e4310d114c63e3b9e2f (diff)
downloadprosody-9f58b6013a9b70bcc10dfbb556de93fcda4d3131.tar.gz
prosody-9f58b6013a9b70bcc10dfbb556de93fcda4d3131.zip
util.template: Optimized to be almost as fast as manual stanza building.
-rw-r--r--util/template.lua41
1 files changed, 34 insertions, 7 deletions
diff --git a/util/template.lua b/util/template.lua
index c143a216..10467d4f 100644
--- a/util/template.lua
+++ b/util/template.lua
@@ -24,6 +24,8 @@ local function process_stanza(stanza, ops)
local child = stanza[i];
if child.name then
process_stanza(child, ops);
+ elseif child:match("^{[^}]*}$") then -- text
+ t_insert(ops, {stanza, i, child:match("^{([^}]*)}$"), true});
elseif child:match("{[^}]*}") then -- text
t_insert(ops, {stanza, i, child});
end
@@ -81,22 +83,47 @@ local parse_xml = (function()
end;
end)();
+local stanza_mt = st.stanza_mt;
+local function fast_st_clone(stanza, lookup)
+ local stanza_attr = stanza.attr;
+ local stanza_tags = stanza.tags;
+ local tags, attr = {}, {};
+ local clone = { name = stanza.name, attr = attr, tags = tags, last_add = {} };
+ for k,v in pairs(stanza_attr) do attr[k] = v; end
+ lookup[stanza_attr] = attr;
+ for i=1,#stanza_tags do
+ local child = stanza_tags[i];
+ local new = fast_st_clone(child, lookup);
+ tags[i] = new;
+ lookup[child] = new;
+ end
+ for i=1,#stanza do
+ local child = stanza[i];
+ clone[i] = lookup[child] or child;
+ end
+ return setmetatable(clone, stanza_mt);
+end
+
local function create_template(text)
local stanza, err = parse_xml(text);
if not stanza then error(err); end
local ops = {};
process_stanza(stanza, ops);
- ops.stanza = stanza;
local template = {};
+ local lookup = {};
function template.apply(data)
- local newops = st.clone(ops);
- for i=1,#newops do
- local op = newops[i];
- local t, k, v = op[1], op[2], op[3];
- t[k] = s_gsub(v, "{([^}]*)}", data);
+ local newstanza = fast_st_clone(stanza, lookup);
+ for i=1,#ops do
+ local op = ops[i];
+ local t, k, v, g = op[1], op[2], op[3], op[4];
+ if g then
+ lookup[t][k] = data[v];
+ else
+ lookup[t][k] = s_gsub(v, "{([^}]*)}", data);
+ end
end
- return newops.stanza;
+ return newstanza;
end
return template;
end