parsav  Diff

Differences From Artifact [ba911a8ebc]:

To Artifact [682e534236]:


     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]