Differences From
Artifact [ba911a8ebc]:
1 1 -- vim: ft=terra
2 2 -- string template generator:
3 3 -- returns a function that fills out a template
4 4 -- with the strings given
5 5
6 6 local util = lib.util
7 +local pstr = lib.mem.ptr(int8)
7 8 local m = {}
8 9 function m.mk(tplspec)
9 10 local str
10 11 if type(tplspec) == 'string'
11 12 then str = tplspec tplspec = {}
12 13 else str = tplspec.body
13 14 end
................................................................................
33 34 str = str:gsub('%s+[\n$]','')
34 35 str = str:gsub('\n','')
35 36 str = str:gsub('</a><a ','</a> <a ') -- keep nav links from getting smooshed
36 37 str = str:gsub(tplchar .. '%?([-%w]+)', function(file)
37 38 if not docs[file] then docs[file] = data.doc[file] end
38 39 return string.format('<a href="#help-%s" class="help">?</a>', file)
39 40 end)
40 - for start, key, stop in string.gmatch(str,'()'..tplchar..'(%w+)()') do
41 + for start, mode, key, stop in string.gmatch(str,'()'..tplchar..'([:!]?)(%w+)()') do
41 42 if string.sub(str,start-1,start-1) ~= '\\' then
42 43 segs[#segs+1] = string.sub(str,last,start-1)
43 - fields[#segs] = key
44 + fields[#segs] = { key = key, mode = (mode ~= '' and mode or nil) }
44 45 last = stop
45 46 end
46 47 end
47 48 segs[#segs+1] = string.sub(str,last)
48 49
49 50 for i, s in ipairs(segs) do
50 51 segs[i] = string.gsub(s, '\\'..tplchar, tplchar_o)
................................................................................
63 64 local runningtally = symbol(intptr)
64 65 local tallyup = {quote
65 66 var [runningtally] = 1 + constlen
66 67 end}
67 68 local rec = terralib.types.newstruct(string.format('template<%s>',tplspec.id or ''))
68 69 local symself = symbol(&rec)
69 70 do local kfac = {}
70 - for afterseg,key in pairs(fields) do
71 - if not kfac[key] then
71 + local sanmode = {}
72 + for afterseg,fld in ipairs(fields) do
73 + if not kfac[fld.key] then
72 74 rec.entries[#rec.entries + 1] = {
73 - field = key;
75 + field = fld.key;
74 76 type = lib.mem.ptr(int8);
75 77 }
76 78 end
77 - kfac[key] = (kfac[key] or 0) + 1
79 + kfac[fld.key] = (kfac[fld.key] or 0) + 1
80 + sanmode[fld.key] = fld.mode == ':' and 6 or fld.mode == '!' and 5 or 1
78 81 end
79 82 for key, fac in pairs(kfac) do
83 + local sanfac = sanmode[key]
84 +
80 85 tallyup[#tallyup + 1] = quote
81 - [runningtally] = [runningtally] + ([symself].[key].ct)*fac
86 + [runningtally] = [runningtally] + ([symself].[key].ct)*fac*sanfac
82 87 end
83 88 end
84 89 end
85 90
86 91 local copiers = {}
87 92 local senders = {}
88 93 local appenders = {}
................................................................................
90 95 local cpypos = symbol(&opaque)
91 96 local accumulator = symbol(&lib.str.acc)
92 97 local destcon = symbol(&lib.net.mg_connection)
93 98 for idx, seg in ipairs(segs) do
94 99 copiers[#copiers+1] = quote [cpypos] = lib.mem.cpy([cpypos], [&opaque]([seg]), [#seg]) end
95 100 senders[#senders+1] = quote lib.net.mg_send([destcon], [seg], [#seg]) end
96 101 appenders[#appenders+1] = quote [accumulator]:push([seg], [#seg]) end
97 - if fields[idx] then
98 - --local fsz = `lib.str.sz(symself.[fields[idx]])
99 - local fval = `symself.[fields[idx]].ptr
100 - local fsz = `symself.[fields[idx]].ct
101 - copiers[#copiers+1] = quote
102 - [cpypos] = lib.mem.cpy([cpypos], [&opaque]([fval]), [fsz])
102 + if fields[idx] and fields[idx].mode then
103 + local f = fields[idx]
104 + local fp = `symself.[f.key]
105 + copiers[#copiers+1] = quote
106 + if fp.ct > 0 then
107 + var san = lib.html.sanitize(fp, [f.mode == ':'])
108 + [cpypos] = lib.mem.cpy([cpypos], [&opaque](san.ptr), san.ct)
109 + --san:free()
110 + end
111 + end
112 + senders[#senders+1] = quote
113 + if fp.ct > 0 then
114 + var san = lib.html.sanitize(fp, [f.mode == ':'])
115 + lib.net.mg_send([destcon], san.ptr, san.ct)
116 + --san:free()
117 + end
118 + end
119 + appenders[#appenders+1] = quote
120 + if fp.ct > 0 then
121 + var san = lib.html.sanitize(fp, [f.mode == ':'])
122 + [accumulator]:ppush(san)
123 + --san:free()
124 + end
125 + end
126 + elseif fields[idx] then
127 + local f = fields[idx]
128 + local fp = `symself.[f.key]
129 + copiers[#copiers+1] = quote
130 + if fp.ct > 0 then
131 + [cpypos] = lib.mem.cpy([cpypos], [&opaque](fp.ptr), fp.ct)
132 + end
103 133 end
104 134 senders[#senders+1] = quote
105 - lib.net.mg_send([destcon], [fval], [fsz])
135 + if fp.ct > 0 then
136 + lib.net.mg_send([destcon], fp.ptr, fp.ct)
137 + end
106 138 end
107 139 appenders[#appenders+1] = quote
108 - [accumulator]:push([fval], [fsz])
140 + if fp.ct > 0 then [accumulator]:ppush(fp) end
109 141 end
110 142 end
111 143 end
112 144
113 145 local tid = tplspec.id or '<anonymous>'
114 146 rec.methods.tostr = terra([symself])
115 147 lib.dbg(['compiling template ' .. tid])
116 148 [tallyup]
117 149 var [symtxt] = lib.mem.heapa(int8, [runningtally])
118 150 var [cpypos] = [&opaque](symtxt.ptr)
119 151 [copiers]
120 152 @[&int8](cpypos) = 0
153 + symtxt.ct = [&int8](cpypos) - symtxt.ptr
121 154 return symtxt
122 155 end
123 156 rec.methods.append = terra([symself], [accumulator])
124 157 lib.dbg(['appending template ' .. tid])
125 158 [tallyup]
126 159 accumulator:cue([runningtally])
127 160 [appenders]