first commit
This commit is contained in:
78
lib/knife/serialize.lua
Normal file
78
lib/knife/serialize.lua
Normal file
@@ -0,0 +1,78 @@
|
||||
local tinsert, tconcat, infinity = table.insert, table.concat, math.huge
|
||||
|
||||
return function (value)
|
||||
local intro, outro, ready, known = {}, {}, {}, {}
|
||||
local knownCount = 0
|
||||
local writer = {}
|
||||
|
||||
-- get writer delegate for this value's type
|
||||
local function getWriter (value)
|
||||
return writer[type(value)]
|
||||
end
|
||||
|
||||
-- check if a value has a representation yet
|
||||
local function isReady (value)
|
||||
return type(value) ~= 'table' or ready[value]
|
||||
end
|
||||
|
||||
-- serialize tables
|
||||
function writer.table (value)
|
||||
if known[value] then
|
||||
return known[value]
|
||||
end
|
||||
|
||||
knownCount = knownCount + 1
|
||||
local variable = ('v%i'):format(knownCount)
|
||||
known[value] = variable
|
||||
|
||||
local parts = {}
|
||||
for k, v in pairs(value) do
|
||||
local writeKey, writeValue = getWriter(k), getWriter(v)
|
||||
if writeKey and writeValue then
|
||||
local key, value = writeKey(k), writeValue(v)
|
||||
if isReady(k) and isReady(v) then
|
||||
tinsert(parts, ('[%s]=%s'):format(key, value))
|
||||
else
|
||||
tinsert(outro, ('%s[%s]=%s'):format(variable, key, value))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local fields = tconcat(parts, ',')
|
||||
tinsert(intro, ('local %s={%s}'):format(variable, fields))
|
||||
ready[value] = true
|
||||
|
||||
return variable
|
||||
end
|
||||
|
||||
-- preserve sign bit on NaN, since Lua prints "nan" or "-nan"
|
||||
local function writeNan (n)
|
||||
return tostring(n) == tostring(0/0) and '0/0' or '-(0/0)'
|
||||
end
|
||||
|
||||
-- serialize numbers
|
||||
function writer.number (value)
|
||||
return value == infinity and '1/0'
|
||||
or value == -infinity and '-1/0'
|
||||
or value ~= value and writeNan(value)
|
||||
or ('%.17G'):format(value)
|
||||
end
|
||||
|
||||
-- serialize strings
|
||||
function writer.string (value)
|
||||
return ('%q'):format(value)
|
||||
end
|
||||
|
||||
-- serialize booleans
|
||||
writer.boolean = tostring
|
||||
|
||||
-- concatenate array, joined by and terminated with line break
|
||||
local function lines (t)
|
||||
return #t == 0 and '' or tconcat(t, '\n') .. '\n'
|
||||
end
|
||||
|
||||
-- generate serialized result
|
||||
local write = getWriter(value)
|
||||
local result = write and write(value) or 'nil'
|
||||
return lines(intro) .. lines(outro) .. 'return ' .. result
|
||||
end
|
||||
Reference in New Issue
Block a user