author | Matthew Wild <mwild1@gmail.com> |
Fri, 19 Apr 2013 13:30:37 +0100 | |
changeset 5497 | b42781a96174 |
parent 5214 | 1430c6f36621 |
child 6780 | 5de6b93d0190 |
permissions | -rw-r--r-- |
3545
c85f9a4ae1c4
util.template: Initial commit. A template library for XML stanzas.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
1 |
|
5214
1430c6f36621
util.template: Use util.xml.
Waqas Hussain <waqas20@gmail.com>
parents:
4495
diff
changeset
|
2 |
local stanza_mt = require "util.stanza".stanza_mt; |
3545
c85f9a4ae1c4
util.template: Initial commit. A template library for XML stanzas.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
3 |
local setmetatable = setmetatable; |
c85f9a4ae1c4
util.template: Initial commit. A template library for XML stanzas.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
4 |
local pairs = pairs; |
3637
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
5 |
local ipairs = ipairs; |
3545
c85f9a4ae1c4
util.template: Initial commit. A template library for XML stanzas.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
6 |
local error = error; |
3637
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
7 |
local loadstring = loadstring; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
8 |
local debug = debug; |
4495
c0f5c78cb817
util.template: Refactoring to make the string->stanza conversion code more generic.
Waqas Hussain <waqas20@gmail.com>
parents:
3640
diff
changeset
|
9 |
local t_remove = table.remove; |
5214
1430c6f36621
util.template: Use util.xml.
Waqas Hussain <waqas20@gmail.com>
parents:
4495
diff
changeset
|
10 |
local parse_xml = require "util.xml".parse; |
3545
c85f9a4ae1c4
util.template: Initial commit. A template library for XML stanzas.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
11 |
|
c85f9a4ae1c4
util.template: Initial commit. A template library for XML stanzas.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
12 |
module("template") |
c85f9a4ae1c4
util.template: Initial commit. A template library for XML stanzas.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
13 |
|
4495
c0f5c78cb817
util.template: Refactoring to make the string->stanza conversion code more generic.
Waqas Hussain <waqas20@gmail.com>
parents:
3640
diff
changeset
|
14 |
local function trim_xml(stanza) |
c0f5c78cb817
util.template: Refactoring to make the string->stanza conversion code more generic.
Waqas Hussain <waqas20@gmail.com>
parents:
3640
diff
changeset
|
15 |
for i=#stanza,1,-1 do |
c0f5c78cb817
util.template: Refactoring to make the string->stanza conversion code more generic.
Waqas Hussain <waqas20@gmail.com>
parents:
3640
diff
changeset
|
16 |
local child = stanza[i]; |
c0f5c78cb817
util.template: Refactoring to make the string->stanza conversion code more generic.
Waqas Hussain <waqas20@gmail.com>
parents:
3640
diff
changeset
|
17 |
if child.name then |
c0f5c78cb817
util.template: Refactoring to make the string->stanza conversion code more generic.
Waqas Hussain <waqas20@gmail.com>
parents:
3640
diff
changeset
|
18 |
trim_xml(child); |
c0f5c78cb817
util.template: Refactoring to make the string->stanza conversion code more generic.
Waqas Hussain <waqas20@gmail.com>
parents:
3640
diff
changeset
|
19 |
else |
c0f5c78cb817
util.template: Refactoring to make the string->stanza conversion code more generic.
Waqas Hussain <waqas20@gmail.com>
parents:
3640
diff
changeset
|
20 |
child = child:gsub("^%s*", ""):gsub("%s*$", ""); |
c0f5c78cb817
util.template: Refactoring to make the string->stanza conversion code more generic.
Waqas Hussain <waqas20@gmail.com>
parents:
3640
diff
changeset
|
21 |
stanza[i] = child; |
c0f5c78cb817
util.template: Refactoring to make the string->stanza conversion code more generic.
Waqas Hussain <waqas20@gmail.com>
parents:
3640
diff
changeset
|
22 |
if child == "" then t_remove(stanza, i); end |
c0f5c78cb817
util.template: Refactoring to make the string->stanza conversion code more generic.
Waqas Hussain <waqas20@gmail.com>
parents:
3640
diff
changeset
|
23 |
end |
c0f5c78cb817
util.template: Refactoring to make the string->stanza conversion code more generic.
Waqas Hussain <waqas20@gmail.com>
parents:
3640
diff
changeset
|
24 |
end |
c0f5c78cb817
util.template: Refactoring to make the string->stanza conversion code more generic.
Waqas Hussain <waqas20@gmail.com>
parents:
3640
diff
changeset
|
25 |
end |
c0f5c78cb817
util.template: Refactoring to make the string->stanza conversion code more generic.
Waqas Hussain <waqas20@gmail.com>
parents:
3640
diff
changeset
|
26 |
|
3637
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
27 |
local function create_string_string(str) |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
28 |
str = ("%q"):format(str); |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
29 |
str = str:gsub("{([^}]*)}", function(s) |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
30 |
return '"..(data["'..s..'"]or"").."'; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
31 |
end); |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
32 |
return str; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
33 |
end |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
34 |
local function create_attr_string(attr, xmlns) |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
35 |
local str = '{'; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
36 |
for name,value in pairs(attr) do |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
37 |
if name ~= "xmlns" or value ~= xmlns then |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
38 |
str = str..("[%q]=%s;"):format(name, create_string_string(value)); |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
39 |
end |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
40 |
end |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
41 |
return str..'}'; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
42 |
end |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
43 |
local function create_clone_string(stanza, lookup, xmlns) |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
44 |
if not lookup[stanza] then |
3640
4bc88bb748d1
util.template: Don't add stanza.last_add. 20% faster.
Waqas Hussain <waqas20@gmail.com>
parents:
3637
diff
changeset
|
45 |
local s = ('setmetatable({name=%q,attr=%s,tags={'):format(stanza.name, create_attr_string(stanza.attr, xmlns)); |
3637
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
46 |
-- add tags |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
47 |
for i,tag in ipairs(stanza.tags) do |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
48 |
s = s..create_clone_string(tag, lookup, stanza.attr.xmlns)..";"; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
49 |
end |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
50 |
s = s..'};'; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
51 |
-- add children |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
52 |
for i,child in ipairs(stanza) do |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
53 |
if child.name then |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
54 |
s = s..create_clone_string(child, lookup, stanza.attr.xmlns)..";"; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
55 |
else |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
56 |
s = s..create_string_string(child)..";" |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
57 |
end |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
58 |
end |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
59 |
s = s..'}, stanza_mt)'; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
60 |
s = s:gsub('%.%.""', ""):gsub('([=;])""%.%.', "%1"):gsub(';"";', ";"); -- strip empty strings |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
61 |
local n = #lookup + 1; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
62 |
lookup[n] = s; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
63 |
lookup[stanza] = "_"..n; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
64 |
end |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
65 |
return lookup[stanza]; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
66 |
end |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
67 |
local function create_cloner(stanza, chunkname) |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
68 |
local lookup = {}; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
69 |
local name = create_clone_string(stanza, lookup, ""); |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
70 |
local f = "local setmetatable,stanza_mt=...;return function(data)"; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
71 |
for i=1,#lookup do |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
72 |
f = f.."local _"..i.."="..lookup[i]..";"; |
3546
cb1600dea3ad
util.template: Optimized to be almost as fast as manual stanza building.
Waqas Hussain <waqas20@gmail.com>
parents:
3545
diff
changeset
|
73 |
end |
3637
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
74 |
f = f.."return "..name..";end"; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
75 |
local f,err = loadstring(f, chunkname); |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
76 |
if not f then error(err); end |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
77 |
return f(setmetatable, stanza_mt); |
3546
cb1600dea3ad
util.template: Optimized to be almost as fast as manual stanza building.
Waqas Hussain <waqas20@gmail.com>
parents:
3545
diff
changeset
|
78 |
end |
cb1600dea3ad
util.template: Optimized to be almost as fast as manual stanza building.
Waqas Hussain <waqas20@gmail.com>
parents:
3545
diff
changeset
|
79 |
|
3637
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
80 |
local template_mt = { __tostring = function(t) return t.name end }; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
81 |
local function create_template(templates, text) |
3545
c85f9a4ae1c4
util.template: Initial commit. A template library for XML stanzas.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
82 |
local stanza, err = parse_xml(text); |
c85f9a4ae1c4
util.template: Initial commit. A template library for XML stanzas.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
83 |
if not stanza then error(err); end |
4495
c0f5c78cb817
util.template: Refactoring to make the string->stanza conversion code more generic.
Waqas Hussain <waqas20@gmail.com>
parents:
3640
diff
changeset
|
84 |
trim_xml(stanza); |
3637
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
85 |
|
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
86 |
local info = debug.getinfo(3, "Sl"); |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
87 |
info = info and ("template(%s:%d)"):format(info.short_src:match("[^\\/]*$"), info.currentline) or "template(unknown)"; |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
88 |
|
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
89 |
local template = setmetatable({ apply = create_cloner(stanza, info), name = info, text = text }, template_mt); |
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
90 |
templates[text] = template; |
3545
c85f9a4ae1c4
util.template: Initial commit. A template library for XML stanzas.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
91 |
return template; |
c85f9a4ae1c4
util.template: Initial commit. A template library for XML stanzas.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
92 |
end |
c85f9a4ae1c4
util.template: Initial commit. A template library for XML stanzas.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
93 |
|
3637
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
94 |
local templates = setmetatable({}, { __mode = 'k', __index = create_template }); |
3545
c85f9a4ae1c4
util.template: Initial commit. A template library for XML stanzas.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
95 |
return function(text) |
3637
bd491def3efb
util.template: Rewritten to be much faster than the util.stanza stanza building API.
Waqas Hussain <waqas20@gmail.com>
parents:
3546
diff
changeset
|
96 |
return templates[text]; |
3545
c85f9a4ae1c4
util.template: Initial commit. A template library for XML stanzas.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
97 |
end; |