Guest User

tsig

a guest
Jun 30th, 2013
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.07 KB | None | 0 0
  1.  
  2. -----------------------------------------------------------------------------
  3. -- JSON4Lua: JSON encoding / decoding support for the Lua language.
  4. -- json Module.
  5. -- Author: Craig Mason-Jones
  6. -- Homepage: http://json.luaforge.net/
  7. -- Version: 0.9.40
  8. -- This module is released under the MIT License (MIT).
  9.  
  10. -- edited for brevity
  11.  
  12. local base = _G
  13. local decode_scanArray
  14. local decode_scanComment
  15. local decode_scanConstant
  16. local decode_scanNumber
  17. local decode_scanObject
  18. local decode_scanString
  19. local decode_scanWhitespace
  20. local encodeString
  21. local isArray
  22. local isEncodable
  23.  
  24. local function encode (v)
  25.   -- Handle nil values
  26.   if v==nil then
  27.     return "null"
  28.   end
  29.  
  30.   local vtype = base.type(v)  
  31.  
  32.   -- Handle strings
  33.   if vtype=='string' then    
  34.     return '"' .. encodeString(v) .. '"'        -- Need to handle encoding in string
  35.   end
  36.  
  37.   -- Handle booleans
  38.   if vtype=='number' or vtype=='boolean' then
  39.     return base.tostring(v)
  40.   end
  41.  
  42.   -- Handle tables
  43.   if vtype=='table' then
  44.     local rval = {}
  45.     -- Consider arrays separately
  46.     local bArray, maxCount = isArray(v)
  47.     if bArray then
  48.       for i = 1,maxCount do
  49.         table.insert(rval, encode(v[i]))
  50.       end
  51.     else    -- An object, not an array
  52.       for i,j in base.pairs(v) do
  53.         if isEncodable(i) and isEncodable(j) then
  54.           table.insert(rval, '"' .. encodeString(i) .. '":' .. encode(j))
  55.         end
  56.       end
  57.     end
  58.     if bArray then
  59.       return '[' .. table.concat(rval,',') ..']'
  60.     else
  61.       return '{' .. table.concat(rval,',') .. '}'
  62.     end
  63.   end
  64.  
  65.   -- Handle null values
  66.   if vtype=='function' and v==null then
  67.     return 'null'
  68.   end
  69.  
  70.   base.assert(false,'encode attempt to encode unsupported type ' .. vtype .. ':' .. base.tostring(v))
  71. end
  72.  
  73. local function decode(s, startPos)
  74.   startPos = startPos and startPos or 1
  75.   startPos = decode_scanWhitespace(s,startPos)
  76.   base.assert(startPos<=string.len(s), 'Unterminated JSON encoded object found at position in [' .. s .. ']')
  77.   local curChar = string.sub(s,startPos,startPos)
  78.   -- Object
  79.   if curChar=='{' then
  80.     return decode_scanObject(s,startPos)
  81.   end
  82.   -- Array
  83.   if curChar=='[' then
  84.     return decode_scanArray(s,startPos)
  85.   end
  86.   -- Number
  87.   if string.find("+-0123456789.e", curChar, 1, true) then
  88.     return decode_scanNumber(s,startPos)
  89.   end
  90.   -- String
  91.   if curChar==[["]] or curChar==[[']] then
  92.    return decode_scanString(s,startPos)
  93.  end
  94.  if string.sub(s,startPos,startPos+1)=='/*' then
  95.    return decode(s, decode_scanComment(s,startPos))
  96.  end
  97.  -- Otherwise, it must be a constant
  98.  return decode_scanConstant(s,startPos)
  99. end
  100.  
  101. local function null()
  102.  return null -- so json.null() will also return null ;-)
  103. end
  104.  
  105.  
  106. function decode_scanArray(s,startPos)
  107.   local array = {}  -- The return value
  108.  local stringLen = string.len(s)
  109.  base.assert(string.sub(s,startPos,startPos)=='[','decode_scanArray called but array does not start at position ' .. startPos .. ' in string:\n'..s )
  110.  startPos = startPos + 1
  111.  -- Infinite loop for array elements
  112.  repeat
  113.    startPos = decode_scanWhitespace(s,startPos)
  114.    base.assert(startPos<=stringLen,'JSON String ended unexpectedly scanning array.')
  115.    local curChar = string.sub(s,startPos,startPos)
  116.    if (curChar==']') then
  117.      return array, startPos+1
  118.    end
  119.    if (curChar==',') then
  120.      startPos = decode_scanWhitespace(s,startPos+1)
  121.    end
  122.    base.assert(startPos<=stringLen, 'JSON String ended unexpectedly scanning array.')
  123.    object, startPos = decode(s,startPos)
  124.    table.insert(array,object)
  125.  until false
  126. end
  127.  
  128. function decode_scanComment(s, startPos)
  129.  base.assert( string.sub(s,startPos,startPos+1)=='/*', "decode_scanComment called but comment does not start at position " .. startPos)
  130.  local endPos = string.find(s,'*/',startPos+2)
  131.  base.assert(endPos~=nil, "Unterminated comment in string at " .. startPos)
  132.  return endPos+2  
  133. end
  134.  
  135. function decode_scanConstant(s, startPos)
  136.  local consts = { ["true"] = true, ["false"] = false, ["null"] = nil }
  137.  local constNames = {"true","false","null"}
  138.  
  139.  for i,k in base.pairs(constNames) do
  140.    --print ("[" .. string.sub(s,startPos, startPos + string.len(k) -1) .."]", k)
  141.    if string.sub(s,startPos, startPos + string.len(k) -1 )==k then
  142.      return consts[k], startPos + string.len(k)
  143.    end
  144.  end
  145.  base.assert(nil, 'Failed to scan constant from string ' .. s .. ' at starting position ' .. startPos)
  146. end
  147.  
  148. function decode_scanNumber(s,startPos)
  149.  local endPos = startPos+1
  150.  local stringLen = string.len(s)
  151.  local acceptableChars = "+-0123456789.e"
  152.  while (string.find(acceptableChars, string.sub(s,endPos,endPos), 1, true)
  153.     and endPos<=stringLen
  154.     ) do
  155.    endPos = endPos + 1
  156.  end
  157.  local stringValue = 'return ' .. string.sub(s,startPos, endPos-1)
  158.  local stringEval = base.loadstring(stringValue)
  159.  base.assert(stringEval, 'Failed to scan number [ ' .. stringValue .. '] in JSON string at position ' .. startPos .. ' : ' .. endPos)
  160.  return stringEval(), endPos
  161. end
  162.  
  163. function decode_scanObject(s,startPos)
  164.  local object = {}
  165.  local stringLen = string.len(s)
  166.  local key, value
  167.  base.assert(string.sub(s,startPos,startPos)=='{','decode_scanObject called but object does not start at position ' .. startPos .. ' in string:\n' .. s)
  168.  startPos = startPos + 1
  169.  repeat
  170.    startPos = decode_scanWhitespace(s,startPos)
  171.    base.assert(startPos<=stringLen, 'JSON string ended unexpectedly while scanning object.')
  172.    local curChar = string.sub(s,startPos,startPos)
  173.    if (curChar=='}') then
  174.      return object,startPos+1
  175.    end
  176.    if (curChar==',') then
  177.      startPos = decode_scanWhitespace(s,startPos+1)
  178.    end
  179.    base.assert(startPos<=stringLen, 'JSON string ended unexpectedly scanning object.')
  180.    -- Scan the key
  181.    key, startPos = decode(s,startPos)
  182.    base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)
  183.    startPos = decode_scanWhitespace(s,startPos)
  184.    base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)
  185.    base.assert(string.sub(s,startPos,startPos)==':','JSON object key-value assignment mal-formed at ' .. startPos)
  186.    startPos = decode_scanWhitespace(s,startPos+1)
  187.    base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)
  188.    value, startPos = decode(s,startPos)
  189.    object[key]=value
  190.   until false   -- infinite loop while key-value pairs are found
  191. end
  192.  
  193. function decode_scanString(s,startPos)
  194.  base.assert(startPos, 'decode_scanString(..) called without start position')
  195.  local startChar = string.sub(s,startPos,startPos)
  196.  base.assert(startChar==[[']] or startChar==[["]],'decode_scanString called for a non-string')
  197.   local escaped = false
  198.   local endPos = startPos + 1
  199.   local bEnded = false
  200.   local stringLen = string.len(s)
  201.   repeat
  202.     local curChar = string.sub(s,endPos,endPos)
  203.     -- Character escaping is only used to escape the string delimiters
  204.     if not escaped then
  205.       if curChar==[[\]] then
  206.         escaped = true
  207.       else
  208.         bEnded = curChar==startChar
  209.       end
  210.     else
  211.       -- If we're escaped, we accept the current character come what may
  212.       escaped = false
  213.     end
  214.     endPos = endPos + 1
  215.     base.assert(endPos <= stringLen+1, "String decoding failed: unterminated string at position " .. endPos)
  216.   until bEnded
  217.   local stringValue = 'return ' .. string.sub(s, startPos, endPos-1)
  218.   local stringEval = base.loadstring(stringValue)
  219.   base.assert(stringEval, 'Failed to load string [ ' .. stringValue .. '] in JSON4Lua.decode_scanString at position ' .. startPos .. ' : ' .. endPos)
  220.   return stringEval(), endPos  
  221. end
  222.  
  223. function decode_scanWhitespace(s,startPos)
  224.   local whitespace=" \n\r\t"
  225.   local stringLen = string.len(s)
  226.   while ( string.find(whitespace, string.sub(s,startPos,startPos), 1, true)  and startPos <= stringLen) do
  227.     startPos = startPos + 1
  228.   end
  229.   return startPos
  230. end
  231.  
  232. function encodeString(s)
  233.   s = string.gsub(s,'\\','\\\\')
  234.   s = string.gsub(s,'"','\\"')
  235.   s = string.gsub(s,"'",'\\"')
  236.   s = string.gsub(s,'\n','\\n')
  237.   s = string.gsub(s,'\t','\\t')
  238.   return s
  239. end
  240.  
  241. function isArray(t)
  242.   -- Next we count all the elements, ensuring that any non-indexed elements are not-encodable
  243.   -- (with the possible exception of 'n')
  244.   local maxIndex = 0
  245.   for k,v in base.pairs(t) do
  246.     if (base.type(k)=='number' and math.floor(k)==k and 1<=k) then  -- k,v is an indexed pair
  247.       if (not isEncodable(v)) then return false end -- All array elements must be encodable
  248.       maxIndex = math.max(maxIndex,k)
  249.     else
  250.       if (k=='n') then
  251.         if v ~= table.getn(t) then return false end  -- False if n does not hold the number of elements
  252.       else -- Else of (k=='n')
  253.         if isEncodable(v) then return false end
  254.       end  -- End of (k~='n')
  255.     end -- End of k,v not an indexed pair
  256.   end  -- End of loop across all pairs
  257.   return true, maxIndex
  258. end
  259.  
  260. function isEncodable(o)
  261.   local t = base.type(o)
  262.   return (t=='string' or t=='boolean' or t=='number' or t=='nil' or t=='table') or (t=='function' and o==null)
  263. end
  264.  
  265.  
  266.  
  267.  
  268. -- Gist Client
  269. -- 2013 Matti Vapa
  270. -- License: MIT
  271.  
  272. local url = "https://api.github.com/gists"
  273.  
  274. -- default parameters for POST
  275. local putvars = {}
  276. putvars["description"] = ""
  277. putvars["public"] = true
  278. putvars["files"] = {}
  279.  
  280.  
  281. local printUsage = function()
  282.     print("Usage:")
  283.     print("gist get <id>")
  284.     print("gist put <filename1> <filename2> ...")
  285. end
  286.  
  287. local args = {...}
  288. local mode
  289.  
  290. if not http then
  291.     print( "gist requires http API" )
  292.     print( "Set enableAPI_http to 1 in mod_ComputerCraft.cfg" )
  293.     return
  294. end
  295.  
  296. if #args == 2 and args[1] == "get"then
  297.     mode = "get"
  298. elseif args[1] == "put" and #args >= 2 then
  299.     mode = "put"
  300. else
  301.     printUsage()
  302.     return
  303. end
  304.  
  305. if mode == "get" then
  306.    
  307.     local id = args[2]
  308.  
  309.     local resp = http.get(url.."/"..id)
  310.  
  311.     if resp ~= nil then
  312.         --print("Success with code "..tostring(resp.getResponseCode()).."!")
  313.         local sresp = resp.readAll()
  314.         resp.close()
  315.         local data = decode(sresp)
  316.         --iterate over the files (there can be several in one gist)
  317.         for key, value in pairs(data["files"]) do
  318.             local file = value["filename"]
  319.             local localFile = file
  320.             local path = shell.resolve(localFile)
  321.             local confirm = true
  322.             while fs.exists(path) do
  323.                 term.write("Local file "..localFile.." already exists. Overwrite? [y/n] ")
  324.                 local inp = io.read():lower()
  325.                 if inp ~= "y" then
  326.                     term.write("Download to a new local file? [y/n] ")
  327.                     local inp = io.read():lower()
  328.                     if inp ~= "y" then
  329.                         print("Skipping remote file: "..file)
  330.                         confirm = false
  331.                         break
  332.                     else
  333.                         term.write("Give a new file name: ")
  334.                         localFile = io.read()
  335.                         path = shell.resolve(localFile)
  336.                     end
  337.                 else
  338.                     print("Overwriting local file: "..localFile)
  339.                     break
  340.                 end
  341.             end
  342.             if confirm then
  343.                 local raw = http.get(value["raw_url"])
  344.                 if raw == nil then print("Unable to download contents of "..file.."!") return end
  345.                 local f = fs.open(path,"w")
  346.                 f.write(raw.readAll())
  347.                 f.close()
  348.                 raw.close()
  349.                 print("Remote file "..file.." downloaded!")
  350.             end
  351.         end
  352.  
  353.     else
  354.         print("Failed to download gist with id "..id.."!")
  355.         return
  356.     end
  357.  
  358. elseif mode == "put" then
  359.     local files = {}
  360.     for i = 2,#args do
  361.         local file = args[i]
  362.         local path = shell.resolve(file)
  363.         if not fs.exists(path) then
  364.             print("No such file: "..file)
  365.             return
  366.         end
  367.         local f = fs.open(path,"r")
  368.         files[file] = {}
  369.         files[file]["content"] = f.readAll()
  370.         f.close()
  371.     end
  372.  
  373.     putvars["files"] = files
  374.  
  375.     print("Give a description for the gist. (Can be blank)")
  376.     putvars["description"] = io.read()
  377.  
  378.     term.write("Uploading to gist... ")
  379.     local resp = http.post(url,encode(putvars))
  380.  
  381.     if resp ~= nil then
  382.         print("Success!")
  383.         --print("Success with code "..tostring(resp.getResponseCode()).."!")
  384.         local data = decode(resp.readAll())
  385.         resp.close()
  386.         print("Gist id: "..tostring(data["id"])..".")
  387.         print("Available for viewing at https://gist.github.com/"..tostring(data["id"]))
  388.     else
  389.         print("Failed.")
  390.     end
  391. end
Advertisement
Add Comment
Please, Sign In to add comment