Alakazard12

serialize

Mar 25th, 2014
159
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.55 KB | None | 0 0
  1. local function serializeInt(i)
  2.         local s = ""
  3.         repeat
  4.                 s = s .. string.char((i % 128) + ((i >= 128) and 128 or 0))
  5.                 i = math.floor(i / 128)
  6.         until i == 0
  7.         return s
  8. end
  9. -- returns int, next position
  10. local function deserializeInt(s,pos)
  11.         local k = pos
  12.         local i = 0
  13.         local m = 1
  14.         while true do
  15.                 local b = string.byte(s:sub(k,k))
  16.                 i = i + m * (b % 128)
  17.                 m = m * 128
  18.                 k = k + 1
  19.                 if b < 128 then break end
  20.         end
  21.         return i, k
  22. end
  23.  
  24. local nextid_key = {}
  25. local function serializeInternal(obj, seen)
  26.         if obj ~= nil and seen[obj] then
  27.                 return "06" .. serializeInt(seen[obj])
  28.         end
  29.         if type(obj) == "table" then
  30.                 local id = seen[nextid_key]
  31.                 seen[nextid_key] = id + 1
  32.                 seen[obj] = id
  33.  
  34.                 local s = "05"
  35.                 local ikeys = {}
  36.                 for k,v in ipairs(obj) do
  37.                         ikeys[k] = v
  38.                         s = s .. serializeInternal(v, seen)
  39.                 end
  40.                 s = s .. serializeInternal(nil, seen)
  41.                 for k,v in pairs(obj) do
  42.                         if ikeys[k] == nil then
  43.                                 s = s .. serializeInternal(k, seen) .. serializeInternal(v, seen)
  44.                         end
  45.                 end
  46.                 s = s .. serializeInternal(nil, seen)
  47.                 return s
  48.         elseif type(obj) == "number" then
  49.                 local ns = tostring(obj)
  50.                 return "04" .. serializeInt(ns:len()) .. ns
  51.         elseif type(obj) == "string" then
  52.                 return "03" .. serializeInt(obj:len()) .. obj
  53.         elseif type(obj) == "boolean" then
  54.                 if obj then
  55.                         return "01"
  56.                 else
  57.                         return "02"
  58.                 end
  59.         elseif type(obj) == "nil" then
  60.                 return "00"
  61.         elseif type(obj) == "userdata" then
  62.                 error("cannot serialize userdata")
  63.         elseif type(obj) == "thread" then
  64.                 error("cannot serialize threads")
  65.         elseif type(obj) == "function" then
  66.                 error("cannot serialize functions")
  67.         else
  68.                 error("unknown type: " .. type(obj))
  69.         end
  70. end
  71. function serialize(obj)
  72.         return serializeInternal(obj, {[nextid_key] = 0})
  73. end
  74. function deserialize(s)
  75.         local pos = 1
  76.         local seen = {}
  77.         local nextid = 0
  78.         local function internal()
  79.                 local tch = s:sub(pos,pos)
  80.                 local len
  81.                 pos = pos + 1
  82.                 if tch == "00" then
  83.                         return nil
  84.                 elseif tch == "01" then
  85.                         return true
  86.                 elseif tch == "02" then
  87.                         return false
  88.                 elseif tch == "03" then
  89.                         len, pos = deserializeInt(s, pos)
  90.                         local rv = s:sub(pos, pos+len-1)
  91.                         pos = pos + len
  92.                         return rv
  93.                 elseif tch == "04" then
  94.                         len, pos = deserializeInt(s, pos)
  95.                         local rv = s:sub(pos, pos+len-1)
  96.                         pos = pos + len
  97.                         return tonumber(rv)
  98.                 elseif tch == "05" then
  99.                         local id = nextid
  100.                         nextid = id + 1
  101.                         local t = {}
  102.                         seen[id] = t
  103.  
  104.                         local k = 1
  105.                         while true do
  106.                                 local v = internal()
  107.                                 if v == nil then break end
  108.                                 t[k] = v
  109.                                 k = k + 1
  110.                         end
  111.  
  112.                         while true do
  113.                                 local k = internal()
  114.                                 if k == nil then break end
  115.                                 local v = internal()
  116.                                 if v == nil then break end
  117.                                 t[k] = v
  118.                         end
  119.                         return t
  120.                 elseif tch == "06" then
  121.                         local id
  122.                         id, pos = deserializeInt(s, pos)
  123.                         return seen[id]
  124.                 else
  125.                         return nil
  126.                 end
  127.         end
  128.         return internal()
  129. end
Add Comment
Please, Sign In to add comment