DEv0on

json

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