all: sets _ENV to nil using local _ENV = nil to avoid global writing
[luajson.git] / lua / json / encode / output_utility.lua
blobb6607d1ab948bcb1afc056835101a0b6f945432e
1 --[[
2 Licensed according to the included 'LICENSE' document
3 Author: Thomas Harning Jr <harningt@gmail.com>
4 ]]
5 local setmetatable = setmetatable
6 local assert, loadstring = assert, loadstring or load
8 local _ENV = nil
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)
15 local putInner = ""
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)
21 end
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)
28 functionCode = [[
29 return function(composite, ret, encode, state)
30 ]] .. functionCode .. [[
31 end
33 return assert(loadstring(functionCode))()
34 end
36 local function prepareEncoder(cacheKey, nextValues, innerValue, valueWriter, innerWriter)
37 local cache = outputCache[cacheKey]
38 if not cache then
39 cache = {}
40 outputCache[cacheKey] = cache
41 end
42 local fun = cache[nextValues]
43 if not fun then
44 fun = buildFunction(nextValues, innerValue, valueWriter, innerWriter)
45 cache[nextValues] = fun
46 end
47 return fun
48 end
50 local output_utility = {
51 prepareEncoder = prepareEncoder
54 return output_utility