Created
June 6, 2021 00:37
-
-
Save TheArmagan/88c25930872f55457f316c1f400fa67a to your computer and use it in GitHub Desktop.
Useful when working with computer craft.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
------------------------------------------------------------------ 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function split(inputString, separateWith) | |
if separateWith == nil then | |
separateWith = ", " | |
end | |
local t={} | |
for str in string.gmatch(inputString, "([^"..separateWith.."]+)") do | |
table.insert(t, str) | |
end | |
return t | |
end | |
function join(inputTable, joinWith) | |
if joinWith == nil then | |
joinWith = ", " | |
end | |
return table.concat(inputTable, joinWith) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment