ComputerCraft Archive

Impending Doom

computer utility unknown forum

Description

ElvishJerricco's JSON parser

Installation

Copy one of these commands into your ComputerCraft terminal:

Pastebin:pastebin get RkXibQCz impending_doom
wget:wget https://pastebin.com/raw/RkXibQCz impending_doom
Archive:wget https://cc.shobie.xyz/cc/get/pb-RkXibQCz impending_doom
Quick Install: wget https://cc.shobie.xyz/cc/get/pb-RkXibQCz Impending Doom

Usage

Run the program after downloading

Tags

forumgames

Source

View Original Source

Code Preview

-- ElvishJerricco's JSON parser
-- http://www.computercraft.info/forums2/index.php?/topic/5854-json-api-v201-for-computercraft/
------------------------------------------------------------------ utils
local controls = {["\n"]="\\n", ["\r"]="\\r", ["\t"]="\\t", ["\b"]="\\b", ["\f"]="\\f", ["\""]="\\\"", ["\\"]="\\\\"}
 
local function isArray(t)
    local max = 0
    for k,v in pairs(t) do
        if type(k) ~= "number" then
            return false
        elseif k > max then
            max = k
        end
    end
    return max == #t
end
 
local whites = {['\n']=true; ['\r']=true; ['\t']=true; [' ']=true; [',']=true; [':']=true}
function removeWhite(str)
    while whites[str:sub(1, 1)] do
        str = str:sub(2)
    end
    return str
end
 
------------------------------------------------------------------ encoding
 
local function encodeCommon(val, pretty, tabLevel, tTracking)
    local str = ""
 
    -- Tabbing util
    local function tab(s)
        str = str .. ("\t"):rep(tabLevel) .. s
    end
 
    local function arrEncoding(val, bracket, closeBracket, iterator, loopFunc)
        str = str .. bracket
        if pretty then
            str = str .. "\n"
            tabLevel = tabLevel + 1
        end
        for k,v in iterator(val) do
            tab("")
            loopFunc(k,v)
            str = str .. ","
            if pretty then str = str .. "\n" end
        end
        if pretty then
            tabLevel = tabLevel - 1
        end
        if str:sub(-2) == ",\n" then
            str = str:sub(1, -3) .. "\n"
        elseif str:sub(-1) == "," then
            str = str:sub(1, -2)
        end
        tab(closeBracket)
    end
 
    -- Table encoding
    if type(val) == "table" then
        assert(not tTracking[val], "Cannot encode a table holding itself recursively")
        tTracking[val] = true
        if isArray(val) then
            arrEncoding(val, "[", "]", ipairs, function(k,v)
                str = str .. encodeCommon(v, pretty, tabLevel, tTracking)
            end)
        else
            arrEncoding(val, "{", "}", pairs, function(k,v)
                assert(type(k) == "string", "JSON object keys must be strings", 2)
                str = str .. encodeCommon(k, pretty, tabLevel, tTracking)
                str = str .. (pretty and ": " or ":") .. encodeCommon(v, pretty, tabLevel, tTracking)
            end)
        end
    -- String encoding
    elseif type(val) == "string" then
        str = '"' .. val:gsub("[%c\"\\]", controls) .. '"'
    -- Number encoding
    elseif type(val) == "number" or type(val) == "boolean" then
        str = tostring(val)
    else
        error("JSON only supports arrays, objects, numbers, booleans, and strings", 2)
    end
    return str
end
 
function encode(val)
    return encodeCommon(val, false, 0, {})
end
 
function encodePretty(val)
    return encodeCommon(val, true, 0, {})
end
 
------------------------------------------------------------------ decoding
 
local decodeControls = {}
for k,v in pairs(controls) do
    decodeControls[v] = k
end
 
function parseBoolean(str)
    if str:sub(1, 4) == "true" then
        return true, removeWhite(str:sub(5))
    else
        return false, removeWhite(str:sub(6))
    end
end
 
function parseNull(str)
    return nil, removeWhite(str:sub(5))
end
 
local numChars = {['e']=true; ['E']=true; ['+']=true; ['-']=true; ['.']=true}
function parseNumber(str)
    local i = 1
    while numChars[str:sub(i, i)] or tonumber(str:sub(i, i)) do
        i = i + 1
    end
    local val = tonumber(str:sub(1, i - 1))
    str = removeWhite(str:sub(i))
    return val, str
end
 
function parseString(str)
    str = str:sub(2)
    local s = ""
    while str:sub(1,1) ~= "\"" do
        local next = str:sub(1,1)
        str = str:sub(2)
        assert(next ~= "\n", "Unclosed string")
 
        if next == "\\" then
            local escape = str:sub(1,1)
            str = str:sub(2)
 
            next = assert(decodeControls[next..escape], "Invalid escape character")
        end
 
        s = s .. next
    end
    return s, removeWhite(str:sub(2))
end
 
function parseArray(str)
    str = removeWhite(str:sub(2))
 
    local val = {}
    local i = 1
    while str:sub(1, 1) ~= "]" do
        local v = nil
        v, str = parseValue(str)
        val[i] = v
        i = i + 1
        str = removeWhite(str)
    end
    str = removeWhite(str:sub(2))
    return val, str
end
 
function parseObject(str)
    str = removeWhite(str:sub(2))
 
    local val = {}
    while str:sub(1, 1) ~= "}" do
        local k, v = nil, nil
        k, v, str = parseMember(str)
        val[k] = v
        str = removeWhite(str)
    end
    str = removeWhite(str:sub(2))
    return val, str
end
 
function parseMember(str)
    local k = nil
    k, str = parseValue(str)
    local val = nil
    val, str = parseValue(str)
    return k, val, str
end
 
function parseValue(str)
    local fchar = str:sub(1, 1)
    if fchar == "{" then
        return parseObject(str)
    elseif fchar == "[" then
        return parseArray(str)
    elseif tonumber(fchar) ~= nil or numChars[fchar] then
        return parseNumber(str)
    elseif str:sub(1, 4) == "true" or str:sub(1, 5) == "false" then
        return parseBoolean(str)
    elseif fchar == "\"" then
        return parseString(str)
    elseif str:sub(1, 4) == "null" then
        return parseNull(str)
    end
    return nil
end
 
function decode(str)
    str = removeWhite(str)
    t = parseValue(str)
    return t
end
 
function decodeFromFile(path)
    local file = assert(fs.open(path, "r"))
    local decoded = decode(file.readAll())
    file.close()
    return decoded
end
-- End of JSON parser
 
-- Ramuthra's plane installer
local github = "https://api.github.com/repos/Saldor010/Impending-Doom/contents"
local args = {...}
if args[1] then
    if not type(args[1]) == "string" then
        args[1] = nil
    elseif string.find(args[1],string.len(args[1]),string.len(args[1])) ~= "/" and string.find(args[1],string.len(args[1]),string.len(args[1])) ~= "\\" then
        args[1] = args[1].."/"
    end
end
local pathToInstall = args[1] or "ImpendingDoom/"
 
local function downloadFile(url,filePath)  
    local fileContent = http.get(url)
    if fileContent then fileContent = fileContent.readAll() else return false end
   
    if not fs.exists(filePath) then
        local file = fs.open(filePath,"w")
        file.write(fileContent)
        file.close()
        return true
    else 
		if term.isColor() then term.setTextColor(colors.red) end
		local wD,hT = term.getSize()
		local x,y = term.getCursorPos()
		term.setCursorPos(1,hT)
		term.write("File already exists. Overwrite? (y/n)")
		local overwrite = false
		while true do
			local ev,p1,p2,p3,p4,p5 = os.pullEvent()
			if ev == "char" and string.lower(p1) == "y" then
				overwrite = true
				break
			elseif ev == "char" and string.lower(p1) == "n" then
				overwrite = false
				break
			end
		end
		term.setCursorPos(1,hT)
		term.write(string.rep(" ",wD))
		term.setCursorPos(x,y)
		
		if overwrite then
			local file = fs.open(filePath,"w")
			file.write(fileContent)
			file.close()
			return true
		else return false end
	return false end
end
 
local function readRepository(url)
    local repository = http.get(url)
    if repository then repository = repository.readAll() else return false end
    repository = decode(repository)
   
    for k,v in pairs(repository) do
        if v["download_url"] then 
            local success = nil
            --[[if string.sub(v["url"],1,70) == "https://api.github.com/repos/Saldor010/Ramuthras-Plane/contents/cobalt" or string.sub(v["url"],1,74) == "https://api.github.com/repos/Saldor010/Ramuthras-Plane/contents/cobalt-lib" or string.sub(v["url"],1,73) == "https://api.github.com/repos/Saldor010/Ramuthras-Plane/contents/cobalt-ui" then
                term.setCursorPos(math.floor(51/2)-math.floor(string.len(v["path"])/2),8)
                term.write(pathToInstall..v["path"])
                success = downloadFile(v["download_url"],v["path"])
            else]]--
			if term.isColor() then term.setTextColor(128) end
			write("Downloading "..v["path"]..".. ")
			success = downloadFile(v["download_url"],pathToInstall..v["path"])
			if success then
				if term.isColor() then term.setTextColor(colors.lime) end
				print("Success")
			else
				if term.isColor() then term.setTextColor(colors.red) end
				print("Failed")
			end
            --end
        else
            readRepository(v["url"])
        end
    end
end
if not term.isColor() then
	print("Warning! The program you're about to download cannot be run on this computer. Proceed anyways? (y/n)")
	local proceed = false
	while true do
		local ev,p1,p2,p3,p4,p5 = os.pullEvent()
		if ev == "char" and string.lower(p1) == "y" then
			proceed = true
			break
		elseif ev == "char" and string.lower(p1) == "n" then
			proceed = false
			break
		end
	end
	if proceed == false then print("Download cancelled.") error() end
end
readRepository(github)

if term.isColor() then term.setTextColor(colors.orange) end
print("Download complete! Run "..pathToInstall.."coldwar.lua to start the game!")