2 Licensed according to the included 'LICENSE' document
3 Author: Thomas Harning Jr <harningt@gmail.com>
5 local setmetatable
= setmetatable
6 local assert, loadstring
= assert, loadstring
or load
10 -- Key == weak, if main key goes away, then cache cleared
11 local outputCache
= setmetatable({}, {__mode
= 'k'})
12 -- TODO: inner tables weak?
14 local function buildFunction(nextValues
, innerValue
, valueWriter
, innerWriter
)
16 if innerValue
and innerWriter
then
17 -- Prepare the lua-string representation of the separator to put in between values
18 local formattedInnerValue
= ("%q"):format(innerValue
)
19 -- Fill in the condition %WRITE_INNER% and the %INNER_VALUE% to actually write
20 putInner
= innerWriter
:gsub("%%WRITE_INNER%%", "%%1"):gsub("%%INNER_VALUE%%", formattedInnerValue
)
22 -- Template-in the value writer (if present) and its conditional argument
23 local functionCode
= nextValues
:gsub("PUTINNER(%b())", putInner
)
24 -- %VALUE% is to be filled in by the value-to-write
25 valueWriter
= valueWriter
:gsub("%%VALUE%%", "%%1")
26 -- Template-in the value writer with its argument
27 functionCode
= functionCode
:gsub("PUTVALUE(%b())", valueWriter
)
29 return function(composite, ret, encode, state)
30 ]] .. functionCode
.. [[
33 return assert(loadstring(functionCode
))()
36 local function prepareEncoder(cacheKey
, nextValues
, innerValue
, valueWriter
, innerWriter
)
37 local cache
= outputCache
[cacheKey
]
40 outputCache
[cacheKey
] = cache
42 local fun
= cache
[nextValues
]
44 fun
= buildFunction(nextValues
, innerValue
, valueWriter
, innerWriter
)
45 cache
[nextValues
] = fun
50 local output_utility
= {
51 prepareEncoder
= prepareEncoder