Comparison

util/template.lua @ 3546:cb1600dea3ad

util.template: Optimized to be almost as fast as manual stanza building.
author Waqas Hussain <waqas20@gmail.com>
date Sun, 24 Oct 2010 15:08:22 +0500
parent 3545:c85f9a4ae1c4
child 3637:bd491def3efb
comparison
equal deleted inserted replaced
3545:c85f9a4ae1c4 3546:cb1600dea3ad
22 local i = 1; 22 local i = 1;
23 while i <= #stanza do 23 while i <= #stanza do
24 local child = stanza[i]; 24 local child = stanza[i];
25 if child.name then 25 if child.name then
26 process_stanza(child, ops); 26 process_stanza(child, ops);
27 elseif child:match("^{[^}]*}$") then -- text
28 t_insert(ops, {stanza, i, child:match("^{([^}]*)}$"), true});
27 elseif child:match("{[^}]*}") then -- text 29 elseif child:match("{[^}]*}") then -- text
28 t_insert(ops, {stanza, i, child}); 30 t_insert(ops, {stanza, i, child});
29 end 31 end
30 i = i + 1; 32 i = i + 1;
31 end 33 end
79 return ok, err.." (line "..line..", col "..col..")"; 81 return ok, err.." (line "..line..", col "..col..")";
80 end 82 end
81 end; 83 end;
82 end)(); 84 end)();
83 85
86 local stanza_mt = st.stanza_mt;
87 local function fast_st_clone(stanza, lookup)
88 local stanza_attr = stanza.attr;
89 local stanza_tags = stanza.tags;
90 local tags, attr = {}, {};
91 local clone = { name = stanza.name, attr = attr, tags = tags, last_add = {} };
92 for k,v in pairs(stanza_attr) do attr[k] = v; end
93 lookup[stanza_attr] = attr;
94 for i=1,#stanza_tags do
95 local child = stanza_tags[i];
96 local new = fast_st_clone(child, lookup);
97 tags[i] = new;
98 lookup[child] = new;
99 end
100 for i=1,#stanza do
101 local child = stanza[i];
102 clone[i] = lookup[child] or child;
103 end
104 return setmetatable(clone, stanza_mt);
105 end
106
84 local function create_template(text) 107 local function create_template(text)
85 local stanza, err = parse_xml(text); 108 local stanza, err = parse_xml(text);
86 if not stanza then error(err); end 109 if not stanza then error(err); end
87 local ops = {}; 110 local ops = {};
88 process_stanza(stanza, ops); 111 process_stanza(stanza, ops);
89 ops.stanza = stanza;
90 112
91 local template = {}; 113 local template = {};
114 local lookup = {};
92 function template.apply(data) 115 function template.apply(data)
93 local newops = st.clone(ops); 116 local newstanza = fast_st_clone(stanza, lookup);
94 for i=1,#newops do 117 for i=1,#ops do
95 local op = newops[i]; 118 local op = ops[i];
96 local t, k, v = op[1], op[2], op[3]; 119 local t, k, v, g = op[1], op[2], op[3], op[4];
97 t[k] = s_gsub(v, "{([^}]*)}", data); 120 if g then
121 lookup[t][k] = data[v];
122 else
123 lookup[t][k] = s_gsub(v, "{([^}]*)}", data);
124 end
98 end 125 end
99 return newops.stanza; 126 return newstanza;
100 end 127 end
101 return template; 128 return template;
102 end 129 end
103 130
104 local templates = setmetatable({}, { __mode = 'k' }); 131 local templates = setmetatable({}, { __mode = 'k' });