map.to_list = function(shallow = false)
list = []
for i in self.indexes
if typeof(self[i]) == "map" then
if shallow == true then
list.push([i, self[i]])
else
list.push([i, self[i].to_list])
end if
else
list.push([i, self[i]])
end if
end for
return list
end function
list.to_map = function()
l = self[0:]
map = {}
for i in indexes(l)
if typeof(l[i][1]) == "list" and l[i][1].len == 2 and typeof(l[i][1][0]) == "string" then
map[l[i][0]] = l[i][1].to_map
else
map[l[i][0]] = l[i][1]
end if
end for
return map
end function
list.each = function(func)
result = self[0:] //list copy.
for i in indexes(self)
func(result[i])
end for
end function
map.each = function(func)
list = self.to_list(true)
result = list[0:] //list copy.
for i in indexes(list)
func(result[i][0], result[i][1])
end for
end function
list.map = function(func)
result = self[0:] //list copy.
for i in indexes(self)
result[i] = func(result[i])
end for
return result
end function
list.reject = function(func)
result = self[0:] //list copy.
i = 0
while i < result.len
if func(result[i]) == true then
result.remove(i)
continue
end if
i = i + 1
end while
return result
end function
list.select = function(func)
f = function(o)
return not func(o)
end function
return self.reject(@f)
end function
// do not rename funcc to to func it will infinite loop
list.lsort = function(funcc)
f = function(i)
return {"sort_key": funcc(i), "obj": i}
end function
result = self.map(@f)
result = result.sort("sort_key")
f = function(i)
return i["obj"]
end function
return result.map(@f)
end function
list.flat = function()
result = []
for i in self
if typeof(i) == "list" then
result = result + i.flat
else
result.push(i)
end if
end for
return result
end function
list.uniq = function()
result = []
for i in self
if result.indexOf(i) == null then result.push(i)
end for
return result
end function
list.has_any = function(value)
for i in self
if i == value then return true
end for
return false
end function
list.min = function()
min = self[0]
for item in self
if item < min then
min = item
end if
end for
return min
end function
list.max = function()
max = self[0]
for item in self
if item > max then
max = item
end if
end for
return max
end function
SafeMap = {}
SafeMap.methods = ["hasIndex", "indexOf", "indexes", "len", "pop", "push", "remove", "shuffle", "sum", "values", "__isa"]
SafeMap.escaped = []
for i in SafeMap.methods.indexes
SafeMap.escaped.push(char(2000 + i))
end for
SafeMap.escape = function(index)
if self.methods.indexOf(index) != null then
index = self.escaped[self.methods.indexOf(index)]
end if
return index
end function
SafeMap.unescape = function(index)
if self.escaped.indexOf(index) != null then
index = self.methods[self.escaped.indexOf(index)]
end if
return index
end function
SafeMap.set = function(dict, index, value)
index = self.escape(index)
dict[index] = value
return dict
end function
SafeMap.get = function(dict, index)
index = self.escape(index)
return dict[index]
end function
SafeMap.hasIndex = function(dict, index)
index = self.escape(index)
return dict.hasIndex(index)
end function
SafeMap.indexOf = function(dict, value)
index = dict.indexOf(value)
index = self.unescape(index)
return index
end function
SafeMap.indexes = function(dict)
indexes = dict.indexes
for i in indexes.indexes
indexes[i] = self.unescape(indexes[i])
end for
return indexes
end function
SafeMap.len = function(dict)
return dict.len
end function
SafeMap.pop = function(dict)
return dict.pop
end function
SafeMap.push = function(dict, index)
index = self.escape(index)
return dict.push(index)
end function
SafeMap.remove = function(dict, index)
index = self.escape(index)
return dict.remove(index)
end function
SafeMap.shuffle = function(dict)
return dict.shuffle
end function
SafeMap.sum = function(dict)
return dict.sum
end function
SafeMap.values = function(dict)
return dict.values
end function
// require lst
// require SafeMap
Lzw = {}
Lzw.generate_dict = function(length)
result = {}
for i in range(length - 1).sort
result[char(i)] = char(i)
end for
return result
end function
Lzw.compress = function(uncompressed)
dict_size = 256
dictionary = self.generate_dict(dict_size)
w = ""
result = []
for c in uncompressed.values
wc = w + c
//if dictionary.hasIndex(wc) then
if SafeMap.hasIndex(dictionary, wc) then
w = wc
else
//result.push(dictionary[w])
result.push(SafeMap.get(dictionary, w))
//dictionary[wc] = dict_size
SafeMap.set(dictionary, wc, dict_size)
dict_size = dict_size + 1
w = c
end if
end for
//if w != "" then result.push(dictionary[w])
if w != "" then result.push(SafeMap.get(dictionary, w))
return result
end function
Lzw.decompress = function(compressed)
dict_size = 256
dictionary = self.generate_dict(dict_size)
w = compressed[0]
result = compressed[0]
compressed = compressed[1:]
for k in compressed
//if dictionary.hasIndex(k) then
if SafeMap.hasIndex(dictionary, k) then
//entry = dictionary[k]
entry = SafeMap.get(dictionary, k)
else if k == dict_size then
entry = w + w[0]
else
exit("Bad compressed k: " + k)
end if
result = result + entry
//dictionary[dict_size] = w + entry[0]
SafeMap.set(dictionary, dict_size, w + entry[0])
dict_size = dict_size + 1
w = entry
end for
return result
end function
// require lst
Encoder = {}
Encoder.CELL_LEN = 14
char_set = []
char_set.push(range(48, 57)) // numbers
char_set.push(range(65, 90)) // capital_letters
char_set.push(range(97, 122)) // letters
char_set.push(range(128, 193)) // extended
char_set = char_set.flat // <- 7 bit char set
Encoder.CHAR_SET = char_set
// UTILS ------------------------------------------------------
Encoder.Utils = {}
Encoder.Utils.to_bin = function(n)
if n == 0 then return "0"
if n == 1 then return "1"
return self.to_bin(floor(n / 2)) + str(n % 2)
end function
Encoder.Utils.to_int = function(n)
n = n.values
n.reverse
r = 0
for i in n.indexes
if n[i] == "1" then
r = r + 2 ^ i
end if
end for
return r
end function
Encoder.Utils.divide = function(s, n)
offset = 0
r = []
while true
r.push(s[0:n])
s = s[n:]
if s.len == 0 then break
end while
return r
end function
// -------------------------------------------------------------
Encoder.encode = function(lzw)
l = lzw[0:]
CELL_SIZE = 0
for i in l.indexes
if l[i] isa string then l[i] = l[i].code
l[i] = self.Utils.to_bin(l[i])
if l[i].len > CELL_SIZE then CELL_SIZE = l[i].len
end for
for i in l.indexes
l[i] = "0" * (CELL_SIZE - l[i].len) + l[i]
end for
l = l.join("")
FAT_ADDED = l.len % 7
if FAT_ADDED > 0 then FAT_ADDED = 7 - FAT_ADDED
l = l + "0" * FAT_ADDED
l = self.Utils.divide(l, 7)
fat_bin = self.Utils.to_bin(FAT_ADDED)
l.insert(0, "0" * (7 - fat_bin.len) + fat_bin)
cell_bin = self.Utils.to_bin(CELL_SIZE)
l.insert(0, "0" * (7 - cell_bin.len) + cell_bin)
l = self.Utils.divide(l.join(""), 7)
//print l
for i in l.indexes
l[i] = char(self.CHAR_SET[self.Utils.to_int(l[i])])
end for
return l.join("")
end function
Encoder.decode = function(string)
l = string.values
for i in l.indexes
l[i] = self.Utils.to_bin(self.CHAR_SET.indexOf(l[i].code))
l[i] = "0" * (7 - l[i].len) + l[i]
end for
//l[-1] = l[-1][2:]
l = l.join("")
CELL_SIZE = self.Utils.to_int(l[0:7])
FAT_ADDED = self.Utils.to_int(l[7: 14])
l = self.Utils.divide(l[14:], 7)
//print l
if FAT_ADDED > 0 then l[-1] = l[-1][0:FAT_ADDED * -1]
//print l
l = self.Utils.divide(l.join(""), CELL_SIZE)
for i in l.indexes
l[i] = self.Utils.to_int(l[i])
if l[i] < 256 then l[i] = char(l[i])
end for
return l
end function
//This implementation deviates from RFC 7159 - The JavaScript Object Notation (JSON) Data Interchange Format <https://tools.ietf.org/html/rfc7159> in the following ways:
//Section 6 (Numbers):
// Leading zeros are allowed
// Infinity, -Infinity, NaN are considered valid numbers
//Section 7 (Strings):
// Escaping characters is not implemented
// Literal double quote is represented as "" in a string
//usage:
//json = new JSON
//string = json.to_string(object)
//object = json.to_object(string)
JSON = {}
JSON.JSON_QUOTE = """"
JSON.JSON_WHITESPACE = [char(9), char(10), char(13), char(32)] //[TAB, LF, CR, Space]
JSON.JSON_SYNTAX = [",",":","[","]","{","}"]
JSON.NUMBER_SYNTAX = ["-","+","E","e","."]
JSON.NULL = null
JSON.sLexString=function(string)
if string[0] == self.JSON_QUOTE then
string = string[1:]
else
return [self.NULL, string]
end if
json_string = ""
strlen = string.len
if strlen > 0 then
i = 0
while i < strlen
if string[i] == "\" and string[i+1] == self.JSON_QUOTE then
i = i + 2
json_string = json_string + self.JSON_QUOTE
continue
end if
if string[i] == self.JSON_QUOTE then
i = i + 1
return [json_string, string[i:]]
end if
json_string = json_string + string[i]
i = i + 1
end while
end if
exit("<color=#ff0000>JSON string lexer error: Expected end-of-string quote")
end function
JSON.sLexNumber=function(string)
strlen = string.len
if strlen > 8 and string[:9] == "-Infinity" then
return ["-Infinity".val, string[9:]]
else if strlen > 7 and string[:8] == "Infinity" then
return ["Infinity".val, string[8:]]
else if strlen > 2 and string[:3] == "NaN" then
return ["NaN".val, string[3:]]
end if
json_number = ""
for c in string
if (c.code > 47 and c.code < 58) or self.NUMBER_SYNTAX.indexOf(c) != null then
json_number = json_number + c
else
break
end if
end for
number = json_number.val
if number == 0 and json_number != "0" then return [self.NULL, string]
return [number, string[json_number.len:]]
end function
JSON.sLexBool=function(string)
strlen=string.len
if strlen > 3 and string[:4] == "true" then return [true, string[4:]]
if strlen > 4 and string[:5] == "false" then return [false, string[5:]]
return [self.NULL, string]
end function
JSON.sLexNull=function(string)
if string.len > 3 and string[:4] == "null" then return [true, string[4:]]
return [false, string]
end function
JSON.sLexWhitespace=function(string)
if self.JSON_WHITESPACE.indexOf(string[0]) != null then
return [string[0], string[1:]]
end if
return [self.NULL, string]
end function
JSON.sLexSyntax=function(string)
if self.JSON_SYNTAX.indexOf(string[0]) != null then
return [string[0], string[1:]]
end if
return [self.NULL, string]
end function
JSON.sLex=function(string)
tokens = []
while string
res = self.sLexString(string)
if res[0] != null then
tokens.push({"token":"string","value":res[0]})
string=res[1]
continue
end if
res = self.sLexNumber(string)
if res[0] != null then
tokens.push({"token":"number","value":res[0]})
string=res[1]
continue
end if
res = self.sLexBool(string)
if res[0] != null then
tokens.push({"token":"bool","value":res[0]})
string=res[1]
continue
end if
res = self.sLexNull(string)
if res[0] == true then
tokens.push({"token":"null","value":self.NULL})
string=res[1]
continue
end if
res = self.sLexSyntax(string)
if res[0] != null then
tokens.push({"token":"syntax","value":res[0]})
string=res[1]
continue
end if
res = self.sLexWhitespace(string)
if res[0] != null then
string=res[1]
continue
end if
exit("<color=#ff0000>JSON lexer error: Unexpected character: "+string[0])
end while
return tokens
end function
JSON.sParseList=function(tokens)
if tokens[0] == {"token":"syntax","value":"]"} then return [[], tokens[1:]]
json_list = []
while tokens
res = self.sParse(tokens)
json_list.push(res[0])
tokens = res[1]
if tokens[0] == {"token":"syntax","value":"]"} then
return [json_list, tokens[1:]]
else if tokens[0] != {"token":"syntax","value":","} then
exit("<color=#ff0000>JSON parser error: Expected comma after object in list")
end if
tokens = tokens[1:]
end while
exit("<color=#ff0000>JSON list parser error: Expected end-of-list bracket")
end function
JSON.sParseMap=function(tokens)
if tokens[0] == {"token":"syntax","value":"}"} then return [{}, tokens[1:]]
json_map = {}
while tokens
if tokens[0].token == "string" or tokens[0].token == "number" then
json_key = tokens[0].value
tokens = tokens[1:]
else
exit("<color=#ff0000>JSON map parser error: Expected string or number key, got: "+tokens[0])
end if
if tokens[0] != {"token":"syntax","value":":"} then
exit("<color=#ff0000>JSON map parser error: Expected "":"" after key in map, got: "+tokens[0])
end if
res = self.sParse(tokens[1:])
json_map[json_key]=res[0]
tokens=res[1]
if tokens[0] == {"token":"syntax","value":"}"} then
return [json_map, tokens[1:]]
else if tokens[0] != {"token":"syntax","value":","} then
exit("<color=#ff0000>JSON map parser error: Expected "","" after pair in map, got: "+tokens[0])
end if
tokens = tokens[1:]
end while
exit("<color=#ff0000>JSON map parser error: Expected end-of-map brace")
end function
JSON.sParse=function(tokens)
if tokens then
if tokens[0] == {"token":"syntax","value":"["} then
return self.sParseList(tokens[1:])
else if tokens[0] == {"token":"syntax","value":"{"} then
return self.sParseMap(tokens[1:])
end if
return [tokens[0].value, tokens[1:]]
end if
return null
end function
JSON.oParseList=function(list)
list_string = "["
listlen = list.len
if listlen then
if listlen > 1 then
for i in range(0,listlen-2)
list_string = list_string + self.to_string(list[i]) + ","
end for
end if
list_string = list_string + self.to_string(list[-1])
end if
return list_string + "]"
end function
JSON.oParseMap=function(map)
map_string = "{"
mapkeys = map.indexes
maplen = mapkeys.len
if maplen then
if maplen > 1 then
for i in range(0,maplen-2)
if typeof(mapkeys[i]) == "string" then
map_string = map_string + """" + mapkeys[i] + """" + ":" + self.to_string(map[mapkeys[i]]) + ","
else
map_string = map_string + mapkeys[i] + ":" + self.to_string(map[mapkeys[i]]) + ","
end if
end for
end if
if typeof(mapkeys[-1]) == "string" then
map_string = map_string + """" + mapkeys[-1] + """" + ":" + self.to_string(map[mapkeys[-1]])
else
map_string = map_string + mapkeys[-1] + ":" + self.to_string(map[mapkeys[-1]])
end if
end if
return map_string + "}"
end function
JSON.to_object=function(string)
return self.sParse(self.sLex(string))[0]
end function
JSON.to_string=function(object)
if typeof(object) == "string" then
return """" + object.replace("""", "\""") + """"
else if typeof(object) == "number" then
return str(object)
else if object == null then
return null
else if typeof(object) == "list" then
return self.oParseList(object)
else
return self.oParseMap(object)
end if
end function
// --------------------------------------
get_folder_table = function(folder, table=null, parent="")
if table == null then table = {}
index = table.len
obj = {"parent": parent, "type": "folder", "name": folder.name}
table[str(index)] = obj
parent = str(index)
index = index + 1
scripts = folder.get_files
folders = folder.get_folders
for script in scripts
print "compressing " + script.name
compressed_content = Encoder.encode(Lzw.compress(script.get_content))
obj = {"parent": parent, "type": "script", "name": script.name, "content": compressed_content}
table[str(index)] = obj
index = index + 1
end for
for folder in folders
get_folder_table(folder, table, parent)
end for
return table
end function
computer = get_shell.host_computer
root_path = current_path
root_folder = computer.File(root_path)
import_folder = function()
json = new JSON
root_folder_name = user_input("(optional, you can press enter to skip and use the root folder name provided in the import string)\nroot folder name: \n")
export_string = user_input("export string: \n").replace(char(10), "")
print char(10) * 50
table = json.to_object(export_string)
file_table = {}
for value in table.values
key = table.indexOf(value)
file_name = value["name"].replace(" ", "_")
if value["parent"] == "" then
parent_folder = root_folder
if root_folder_name != "" then file_name = root_folder_name
file_path = parent_folder.path + "/" + file_name
if computer.File(file_path) then computer.File(file_path).delete //clear
else
parent_folder = file_table[value["parent"]]["file"]
file_path = parent_folder.path + "/" + file_name
end if
if value["type"] == "folder" then
f_out = computer.create_folder(parent_folder.path, file_name)
if f_out != 1 then
print(file_path)
exit(f_out)
end if
file = computer.File(file_path)
else if value["type"] == "script" then
f_out = computer.touch(parent_folder.path, file_name)
if f_out != 1 then
print(file_path)
exit(f_out)
end if
file = computer.File(file_path)
print "decompressing " + value["name"]
decompressed_content = Lzw.decompress(Encoder.decode(value["content"]))
file.set_content(decompressed_content)
end if
file_table[key] = {"parent": value["parent"], "file": file}
print(file_path + " " + value["type"] +" created")
end for
end function
export_folder = function()
full_path = user_input("full path of the folder:\n")
folder = computer.File(full_path)
if not folder then exit("ERROR: path is invalid")
export_obj = get_folder_table(folder)
print("\n\nthis is your export string:\n\n")
json = new JSON
export_string = json.to_string(export_obj)
print char(10) * 50
print(export_string)
print char(10) * 10
end function
print("<b>grey repo parser (www.greyrepo.xyz/posts/folder-parser)</b>\nactions:\n[1] import project\n[2] export a local folder")
input = user_input("select action:\n")
if input == "1" then import_folder()
if input == "2" then export_folder()