Darking560

myJsonAPI

Nov 1st, 2016
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.13 KB | None | 0 0
  1. ------------------------------------------------------------------ utils
  2. local controls = {["\/"]="\\/",["\u"]="\\u",["\n"]="\\n", ["\r"]="\\r", ["\t"]="\\t", ["\b"]="\\b", ["\f"]="\\f", ["\""]="\\\"", ["\\"]="\\\\"}
  3.  
  4. local escapes = {["00e7"]="c",["00e8"]="e",["00e9"]="e",["00ea"]="e",["00e0"]="a",["00f9"]="u"}
  5.  
  6. local function isArray(t)
  7.     local max = 0
  8.     for k,v in pairs(t) do
  9.         if type(k) ~= "number" then
  10.             return false
  11.         elseif k > max then
  12.             max = k
  13.         end
  14.     end
  15.     return max == #t
  16. end
  17.  
  18. local whites = {['\n']=true; ['\r']=true; ['\t']=true; [' ']=true; [',']=true; [':']=true}
  19. function removeWhite(str)
  20.     while whites[str:sub(1, 1)] do
  21.         str = str:sub(2)
  22.     end
  23.     return str
  24. end
  25.  
  26. ------------------------------------------------------------------ encoding
  27.  
  28. local function encodeCommon(val, pretty, tabLevel, tTracking)
  29.     local str = ""
  30.  
  31.     -- Tabbing util
  32.     local function tab(s)
  33.         str = str .. ("\t"):rep(tabLevel) .. s
  34.     end
  35.  
  36.     local function arrEncoding(val, bracket, closeBracket, iterator, loopFunc)
  37.         str = str .. bracket
  38.         if pretty then
  39.             str = str .. "\n"
  40.             tabLevel = tabLevel + 1
  41.         end
  42.         for k,v in iterator(val) do
  43.             tab("")
  44.             loopFunc(k,v)
  45.             str = str .. ","
  46.             if pretty then str = str .. "\n" end
  47.         end
  48.         if pretty then
  49.             tabLevel = tabLevel - 1
  50.         end
  51.         if str:sub(-2) == ",\n" then
  52.             str = str:sub(1, -3) .. "\n"
  53.         elseif str:sub(-1) == "," then
  54.             str = str:sub(1, -2)
  55.         end
  56.         tab(closeBracket)
  57.     end
  58.  
  59.     -- Table encoding
  60.     if type(val) == "table" then
  61.         assert(not tTracking[val], "Cannot encode a table holding itself recursively")
  62.         tTracking[val] = true
  63.         if isArray(val) then
  64.             arrEncoding(val, "[", "]", ipairs, function(k,v)
  65.                 str = str .. encodeCommon(v, pretty, tabLevel, tTracking)
  66.             end)
  67.         else
  68.             arrEncoding(val, "{", "}", pairs, function(k,v)
  69.                 assert(type(k) == "string", "JSON object keys must be strings", 2)
  70.                 str = str .. encodeCommon(k, pretty, tabLevel, tTracking)
  71.                 str = str .. (pretty and ": " or ":") .. encodeCommon(v, pretty, tabLevel, tTracking)
  72.             end)
  73.         end
  74.     -- String encoding
  75.     elseif type(val) == "string" then
  76.         str = '"' .. val:gsub("[%c\"\\]", controls) .. '"'
  77.     -- Number encoding
  78.     elseif type(val) == "number" or type(val) == "boolean" then
  79.         str = tostring(val)
  80.     else
  81.         error("JSON only supports arrays, objects, numbers, booleans, and strings", 2)
  82.     end
  83.     return str
  84. end
  85.  
  86. function encode(val)
  87.     return encodeCommon(val, false, 0, {})
  88. end
  89.  
  90. function encodePretty(val)
  91.     return encodeCommon(val, true, 0, {})
  92. end
  93.  
  94. ------------------------------------------------------------------ decoding
  95.  
  96. local decodeControls = {}
  97. for k,v in pairs(controls) do
  98.     decodeControls[v] = k
  99. end
  100.  
  101. function parseBoolean(str)
  102.     if str:sub(1, 4) == "true" then
  103.         return true, removeWhite(str:sub(5))
  104.     else
  105.         return false, removeWhite(str:sub(6))
  106.     end
  107. end
  108.  
  109. function parseNull(str)
  110.     return nil, removeWhite(str:sub(5))
  111. end
  112.  
  113. local numChars = {['e']=true; ['E']=true; ['+']=true; ['-']=true; ['.']=true}
  114. function parseNumber(str)
  115.     local i = 1
  116.     while numChars[str:sub(i, i)] or tonumber(str:sub(i, i)) do
  117.         i = i + 1
  118.     end
  119.     local val = tonumber(str:sub(1, i - 1))
  120.     str = removeWhite(str:sub(i))
  121.     return val, str
  122. end
  123.  
  124. function parseString(str)
  125.     str = str:sub(2)
  126.     local s = ""
  127.     while str:sub(1,1) ~= "\"" do
  128.         local next = str:sub(1,1)
  129.         str = str:sub(2)
  130.         assert(next ~= "\n", "Unclosed string")
  131.  
  132.         if next == "\\" then
  133.             local escape = str:sub(1,1)
  134.             if escape == "u" then
  135.                 code = str:sub(2,5)
  136.                 str=str:sub(6)
  137.                 next=escapes[code]
  138.                 if next==nil then
  139.                     next="?"
  140.                 end
  141.             else
  142.                 str = str:sub(2)
  143.                 next = assert(decodeControls[next..escape], "Invalid escape character")
  144.             end
  145.         end
  146.  
  147.         s = s .. next
  148.     end
  149.     return s, removeWhite(str:sub(2))
  150. end
  151.  
  152. function parseArray(str)
  153.     str = removeWhite(str:sub(2))
  154.  
  155.     local val = {}
  156.     local i = 1
  157.     while str:sub(1, 1) ~= "]" do
  158.         local v = nil
  159.         v, str = parseValue(str)
  160.         val[i] = v
  161.         i = i + 1
  162.         str = removeWhite(str)
  163.     end
  164.     str = removeWhite(str:sub(2))
  165.     return val, str
  166. end
  167.  
  168. function parseObject(str)
  169.     str = removeWhite(str:sub(2))
  170.  
  171.     local val = {}
  172.     while str:sub(1, 1) ~= "}" do
  173.         local k, v = nil, nil
  174.         k, v, str = parseMember(str)
  175.         val[k] = v
  176.         str = removeWhite(str)
  177.     end
  178.     str = removeWhite(str:sub(2))
  179.     return val, str
  180. end
  181.  
  182. function parseMember(str)
  183.     local k = nil
  184.     k, str = parseValue(str)
  185.     local val = nil
  186.     val, str = parseValue(str)
  187.     return k, val, str
  188. end
  189.  
  190. function parseValue(str)
  191.     local fchar = str:sub(1, 1)
  192.     if fchar == "{" then
  193.         return parseObject(str)
  194.     elseif fchar == "[" then
  195.         return parseArray(str)
  196.     elseif tonumber(fchar) ~= nil or numChars[fchar] then
  197.         return parseNumber(str)
  198.     elseif str:sub(1, 4) == "true" or str:sub(1, 5) == "false" then
  199.         return parseBoolean(str)
  200.     elseif fchar == "\"" then
  201.         return parseString(str)
  202.     elseif str:sub(1, 4) == "null" then
  203.         return parseNull(str)
  204.     end
  205.     return nil
  206. end
  207.  
  208. function decode(str)
  209.     str = removeWhite(str)
  210.     t = parseValue(str)
  211.     return t
  212. end
  213.  
  214. function decodeFromFile(path)
  215.     local file = assert(fs.open(path, "r"))
  216.     local decoded = decode(file.readAll())
  217.     file.close()
  218.     return decoded
  219. end
Add Comment
Please, Sign In to add comment