Advertisement
killer64

serialize/unserialize

Dec 3rd, 2013
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.97 KB | None | 0 0
  1. local _tob64={
  2.     [0]="A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
  3.     "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",
  4.     "0","1","2","3","4","5","6","7","8","9","+","/"
  5. }
  6. function tob64(stxt)
  7.     local txt=tostring(stxt)
  8.     if not txt then
  9.         error("string expected, got "..type(stxt),2)
  10.     end
  11.     local d,o,d1,d2,d3={string.byte(txt,1,#txt)},""
  12.     for l1=1,#txt-2,3 do
  13.         d1,d2,d3=d[l1],d[l1+1],d[l1+2]
  14.         o=o.._tob64[math.floor(d1/4)].._tob64[((d1%4)*16)+math.floor(d2/16)].._tob64[((d2%16)*4)+math.floor(d3/64)].._tob64[d3%64]
  15.     end
  16.     local m=#txt%3
  17.     if m==1 then
  18.         o=o.._tob64[math.floor(d[#txt]/4)].._tob64[((d[#txt]%4)*16)].."=="
  19.     elseif m==2 then
  20.         o=o.._tob64[math.floor(d[#txt-1]/4)].._tob64[((d[#txt-1]%4)*16)+math.floor(d[#txt]/16)].._tob64[(d[#txt]%16)*4].."="
  21.     end
  22.     return o
  23. end
  24. local _unb64={
  25.     ["A"]=0,["B"]=1,["C"]=2,["D"]=3,["E"]=4,["F"]=5,["G"]=6,["H"]=7,["I"]=8,["J"]=9,["K"]=10,["L"]=11,["M"]=12,["N"]=13,
  26.     ["O"]=14,["P"]=15,["Q"]=16,["R"]=17,["S"]=18,["T"]=19,["U"]=20,["V"]=21,["W"]=22,["X"]=23,["Y"]=24,["Z"]=25,
  27.     ["a"]=26,["b"]=27,["c"]=28,["d"]=29,["e"]=30,["f"]=31,["g"]=32,["h"]=33,["i"]=34,["j"]=35,["k"]=36,["l"]=37,["m"]=38,
  28.     ["n"]=39,["o"]=40,["p"]=41,["q"]=42,["r"]=43,["s"]=44,["t"]=45,["u"]=46,["v"]=47,["w"]=48,["x"]=49,["y"]=50,["z"]=51,
  29.     ["0"]=52,["1"]=53,["2"]=54,["3"]=55,["4"]=56,["5"]=57,["6"]=58,["7"]=59,["8"]=60,["9"]=61,["+"]=62,["/"]=63,
  30. }
  31. function unb64(stxt)
  32.     local txt=tostring(stxt)
  33.     if not txt then
  34.         error("string expected, got "..type(stxt),2)
  35.     end
  36.     txt=txt:gsub("[^%a%d/%+]","")
  37.     local m=#txt%4
  38.     if m==1 then
  39.         error("invalid b64",2)
  40.     end
  41.     local o,d1,d2=""
  42.     for l1=1,#txt-3,4 do
  43.         d1,d2=_unb64[txt:sub(l1+1,l1+1)],_unb64[txt:sub(l1+2,l1+2)]
  44.         o=o..string.char((_unb64[txt:sub(l1,l1)]*4)+math.floor(d1/16),((d1%16)*16)+math.floor(d2/4),((d2%4)*64)+_unb64[txt:sub(l1+3,l1+3)])
  45.     end
  46.     if m==2 then
  47.         o=o..string.char((_unb64[txt:sub(-2,-2)]*4)+math.floor(_unb64[txt:sub(-1,-1)]/16))
  48.     elseif m==3 then
  49.         d1=_unb64[txt:sub(-2,-2)]
  50.         o=o..string.char((_unb64[txt:sub(-3,-3)]*4)+math.floor(d1/16),((d1%16)*16)+math.floor(_unb64[txt:sub(-1,-1)]/4))
  51.     end
  52.     return o
  53. end
  54. function serialize(dat,options)
  55.     options=options or {}
  56.     local out=""
  57.     local queue={{dat}}
  58.     local cv=0
  59.     local keydat
  60.     local ptbl={}
  61.     while queue[1] do
  62.         local cu=queue[1]
  63.         table.remove(queue,1)
  64.         local typ=type(cu[1])
  65.         local ot
  66.         if typ=="string" then
  67.             ot=string.gsub(string.format("%q",cu[1]),"\\\n","\\n")
  68.         elseif typ=="number" or typ=="boolean" or typ=="nil" then
  69.             ot=tostring(cu[1])
  70.         elseif typ=="table" then
  71.             local empty=true
  72.             ot="{"
  73.             local st=0
  74.             ptbl[#ptbl+1]=cu[1]
  75.             for k,v in pairs(cu[1]) do
  76.                 empty=false
  77.                 st=st+1
  78.                 table.insert(queue,st,{k,"key"})
  79.                 st=st+1
  80.                 local val=v
  81.                 if type(v)=="table" then
  82.                     for n,l in pairs(ptbl) do
  83.                         if l==v then
  84.                             if options.nofalse then
  85.                                 val="recursive"
  86.                             elseif options.noerror then
  87.                                 return false
  88.                             else
  89.                                 error("Cannot handle recursive tables.",2)
  90.                             end
  91.                         end
  92.                     end
  93.                 end
  94.                 table.insert(queue,st,{val,"value",nil,st/2})
  95.             end
  96.             if empty then
  97.                 ot=ot.."}"
  98.                 ptbl[#ptbl]=nil
  99.                 typ="emptytable"
  100.             else
  101.                 cv=cv+1
  102.                 if cu[3] then
  103.                     queue[st][3]=cu[3]
  104.                     cu[3]=nil
  105.                 end
  106.                 queue[st][3]=(queue[st][3] or 0)+1
  107.             end
  108.         elseif typ=="function" then
  109.             if options.nofunc then
  110.                 ot="function"
  111.             else
  112.                 local e,r,er=pcall(string.dump,cu[1])
  113.                 if e and r then
  114.                     ot="f(\""..tob64(r).."\")"
  115.                 else
  116.                     if options.nofalse then
  117.                         ot="invalid function"
  118.                     elseif options.noerror then
  119.                         return false
  120.                     else
  121.                         error(r or er,2)
  122.                     end
  123.                 end
  124.             end
  125.         end
  126.         if cu[2]=="key" then
  127.             if type(ot)=="string" then
  128.                 local nt=ot:sub(2,-2)
  129.                 local e,r=loadstring("return {"..nt.."=true}")
  130.                 if options.noshortkey or not e then
  131.                     ot="["..ot.."]="
  132.                 else
  133.                     ot=nt.."="
  134.                 end
  135.             else
  136.                 ot=ot.."="
  137.             end
  138.             keydat={cu[1],ot}
  139.             ot=""
  140.         elseif cu[2]=="value" then
  141.             if keydat[1]~=cu[4] then
  142.                 ot=keydat[2]..ot
  143.             end
  144.             if cu[3] then
  145.                 ot=ot..("}"):rep(cu[3])
  146.                 for l1=1,cu[3] do
  147.                     ptbl[#ptbl]=nil
  148.                 end
  149.                 cv=cv-cu[3]
  150.                 if cv~=0 then
  151.                     ot=ot..","
  152.                 end
  153.             elseif typ~="table" then
  154.                 ot=ot..","
  155.             end
  156.         end
  157.         out=out..ot
  158.     end
  159.     return out
  160. end
  161. function serializeRecursive(dat,nofunc,rc)
  162.     local tpe=type(dat)
  163.     if tpe=="table" then
  164.         local result="{"
  165.         local aset=1
  166.         local comma=false
  167.         for k,v in pairs(dat) do
  168.             comma=true
  169.             if k==aset then
  170.                 result=result..serializeRecursive(v,nofunc)..","
  171.                 aset=aset+1
  172.             else
  173.                 local tmp=serializeImpl(k,nofunc)
  174.                 local tmp2=serializeImpl(v,nofunc)
  175.                 if type(k)=="string" then
  176.                     local r=loadstring("return {"..k.."="..(nofunc and "true" or tmp2).."}")
  177.                     if r and not string.find(k,",") then
  178.                         result=result..k.."="..tmp2..","
  179.                     else
  180.                         result=result.."["..tmp.."]="..tmp2..","
  181.                     end
  182.                 else
  183.                     result=result.."["..tmp.."]="..tmp2..","
  184.                 end
  185.             end
  186.         end
  187.         if comma then
  188.             result=string.sub(result,1,-2)
  189.         end
  190.         result=result.."}"
  191.         return result
  192.     elseif sType == "string" then
  193.         local s=string.gsub(string.format("%q",dat),"\\\n","\\n")
  194.         return s
  195.     elseif sType == "number" or sType == "boolean" or sType == "nil" then
  196.         return tostring(dat)
  197.     elseif sType == "function" then -- function i added
  198.         if nofunc then
  199.             return "function"
  200.         else
  201.             local status,data=pcall(string.dump,dat) -- convert the function into a string
  202.             if status then
  203.                 return "f("..tob64(data)..")" -- format it so it dosent screw up syntax
  204.             else
  205.                 return "badfunc"
  206.             end
  207.         end
  208.     else
  209.         error("unknown type: "..tpe)
  210.     end
  211. end
  212. function unserialize(s,tf) -- converts a string back into its original form
  213.     do -- check to make sure it isnt attempting to call anything
  214.         local strtype=0
  215.         local esc=false
  216.         local bc=false
  217.         for c in s:gmatch(".") do
  218.             if strtype>0 then
  219.                 if esc then
  220.                     esc=false
  221.                 elseif c=="\\" then
  222.                     esc=true
  223.                 elseif (strtype==1 and c=="\"") or (strtype==2 and c=="'") then
  224.                     strtype=0
  225.                 end
  226.             elseif c=="\"" then
  227.                 strtype=1
  228.             elseif c=="'" then
  229.                 strtype=2
  230.             end
  231.             if bc then
  232.                 if c==")" then
  233.                     error("Function call detected.",2)
  234.                 else
  235.                     bc=false
  236.                 end
  237.             elseif c=="(" and strtype==0 then
  238.                 bc=true
  239.             end
  240.         end
  241.     end
  242.     if type(s)~="string" then
  243.         error("String exepcted. got "..type(s),2)
  244.     end
  245.     local func,e=loadstring("return "..s,"unserialize")
  246.     if not func then
  247.         error("Invalid string.",2)
  248.     end
  249.     return setfenv(func,{f=function(s) return loadstring(unb64(s)) end})()
  250. end
  251. function c(...)
  252.     local r=serialize({...},{noerror=true})
  253.     if r then
  254.         r=r:sub(2,-2)
  255.     end
  256.     return r
  257. end
  258. function d(S)
  259.     if not S then
  260.         return false,"nil"
  261.     end
  262.     local E,D,C=pcall(unserialize,"{"..S.."}")
  263.     if C or not E then
  264.         return false,D
  265.     else
  266.         return type(D)=="table" and D
  267.     end
  268. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement