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()