oGoOgO

AdvancedLua.lua

Jun 3rd, 2024
37
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.33 KB | None | 0 0
  1. local filesystem = require("filesystem")
  2. local unicode = require("unicode")
  3. local bit32 = require("bit32")
  4.  
  5. ----------------------------------------------------------------------------------------------------
  6.  
  7. function _G.getCurrentScript()
  8. local info
  9. for runLevel = 0, math.huge do
  10. info = debug.getinfo(runLevel)
  11. if info then
  12. if info.what == "main" then
  13. return info.source:sub(2, -1)
  14. end
  15. else
  16. error("Failed to get debug info for runlevel " .. runLevel)
  17. end
  18. end
  19. end
  20.  
  21. ----------------------------------------------------------------------------------------------------
  22.  
  23. function bit32.merge(number2, number1)
  24. local cutter = math.ceil(math.log(number1 + 1, 256)) * 8
  25. while number2 > 0 do
  26. number1, number2, cutter = bit32.bor(bit32.lshift(bit32.band(number2, 0xFF), cutter), number1), bit32.rshift(number2, 8), cutter + 8
  27. end
  28.  
  29. return number1
  30. end
  31.  
  32. function bit32.numberToByteArray(number)
  33. local byteArray = {}
  34.  
  35. repeat
  36. table.insert(byteArray, 1, bit32.band(number, 0xFF))
  37. number = bit32.rshift(number, 8)
  38. until number <= 0
  39.  
  40. return byteArray
  41. end
  42.  
  43. function bit32.numberToFixedSizeByteArray(number, size)
  44. local byteArray, counter = {}, 0
  45.  
  46. repeat
  47. table.insert(byteArray, 1, bit32.band(number, 0xFF))
  48. number = bit32.rshift(number, 8)
  49. counter = counter + 1
  50. until number <= 0
  51.  
  52. for i = 1, size - counter do
  53. table.insert(byteArray, 1, 0x0)
  54. end
  55.  
  56. return byteArray
  57. end
  58.  
  59. function bit32.byteArrayToNumber(byteArray)
  60. local result = byteArray[1]
  61. for i = 2, #byteArray do
  62. result = bit32.bor(bit32.lshift(result, 8), byteArray[i])
  63. end
  64.  
  65. return result
  66. end
  67.  
  68. function bit32.bitArrayToByte(bitArray)
  69. local result = 0
  70. for i = 1, #bitArray do
  71. result = bit32.bor(bitArray[i], bit32.lshift(result, 1))
  72. end
  73.  
  74. return result
  75. end
  76.  
  77. ----------------------------------------------------------------------------------------------------
  78.  
  79. function math.round(num)
  80. if num >= 0 then
  81. return math.floor(num + 0.5)
  82. else
  83. return math.ceil(num - 0.5)
  84. end
  85. end
  86.  
  87. function math.roundToDecimalPlaces(num, decimalPlaces)
  88. local mult = 10 ^ (decimalPlaces or 0)
  89. return math.round(num * mult) / mult
  90. end
  91.  
  92. function math.getDigitCount(num)
  93. return num == 0 and 1 or math.ceil(math.log(num + 1, 10))
  94. end
  95.  
  96. function math.shorten(number, digitCount)
  97. local shortcuts = {
  98. "K",
  99. "M",
  100. "B",
  101. "T"
  102. }
  103.  
  104. local index = math.floor(math.log(number, 1000))
  105. if number < 1000 then
  106. return number
  107. elseif index > #shortcuts then
  108. index = #shortcuts
  109. end
  110.  
  111. return math.roundToDecimalPlaces(number / 1000 ^ index, digitCount) .. shortcuts[index]
  112. end
  113.  
  114. ----------------------------------------------------------------------------------------------------
  115.  
  116. -- function filesystem.path(path)
  117. -- return path:match("^(.+%/).") or ""
  118. -- end
  119.  
  120. -- function filesystem.name(path)
  121. -- return path:match("%/?([^%/]+)%/?$")
  122. -- end
  123.  
  124. function filesystem.extension(path, lower)
  125. local extension = path:match("[^%/]+(%.[^%/]+)%/?$")
  126. return (lower and extension) and (unicode.lower(extension)) or extension
  127. end
  128.  
  129. function filesystem.hideExtension(path)
  130. return path:match("(.+)%..+") or path
  131. end
  132.  
  133. function filesystem.isFileHidden(path)
  134. if path:match("^%..+$") then
  135. return true
  136. end
  137.  
  138. return false
  139. end
  140.  
  141. function filesystem.sortedList(path, sortingMethod, showHiddenFiles, filenameMatcher, filenameMatcherCaseSensitive)
  142. if not filesystem.exists(path) then
  143. error("Failed to get file list: directory \"" .. tostring(path) .. "\" doesn't exists")
  144. end
  145.  
  146. if not filesystem.isDirectory(path) then
  147. error("Failed to get file list: path \"" .. tostring(path) .. "\" is not a directory")
  148. end
  149.  
  150. local fileList, sortedFileList = {}, {}
  151. for file in filesystem.list(path) do
  152. if not filenameMatcher or string.unicodeFind(filenameMatcherCaseSensitive and file or unicode.lower(file), filenameMatcherCaseSensitive and filenameMatcher or unicode.lower(filenameMatcher)) then
  153. table.insert(fileList, file)
  154. end
  155. end
  156.  
  157. if #fileList > 0 then
  158. if sortingMethod == "type" then
  159. local extension
  160. for i = 1, #fileList do
  161. extension = filesystem.extension(fileList[i]) or "Script"
  162. if filesystem.isDirectory(path .. fileList[i]) and extension ~= ".app" then
  163. extension = ".01_Folder"
  164. end
  165. fileList[i] = {fileList[i], extension}
  166. end
  167.  
  168. table.sort(fileList, function(a, b) return unicode.lower(a[2]) < unicode.lower(b[2]) end)
  169.  
  170. local currentExtensionList, currentExtension = {}, fileList[1][2]
  171. for i = 1, #fileList do
  172. if currentExtension == fileList[i][2] then
  173. table.insert(currentExtensionList, fileList[i][1])
  174. else
  175. table.sort(currentExtensionList, function(a, b) return unicode.lower(a) < unicode.lower(b) end)
  176. for j = 1, #currentExtensionList do
  177. table.insert(sortedFileList, currentExtensionList[j])
  178. end
  179. currentExtensionList, currentExtension = {fileList[i][1]}, fileList[i][2]
  180. end
  181. end
  182.  
  183. table.sort(currentExtensionList, function(a, b) return unicode.lower(a) < unicode.lower(b) end)
  184.  
  185. for j = 1, #currentExtensionList do
  186. table.insert(sortedFileList, currentExtensionList[j])
  187. end
  188. elseif sortingMethod == "name" then
  189. sortedFileList = fileList
  190. table.sort(sortedFileList, function(a, b) return unicode.lower(a) < unicode.lower(b) end)
  191. elseif sortingMethod == "date" then
  192. for i = 1, #fileList do
  193. fileList[i] = {fileList[i], filesystem.lastModified(path .. fileList[i])}
  194. end
  195.  
  196. table.sort(fileList, function(a, b) return unicode.lower(a[2]) > unicode.lower(b[2]) end)
  197.  
  198. for i = 1, #fileList do
  199. table.insert(sortedFileList, fileList[i][1])
  200. end
  201. else
  202. error("Unknown sorting method: " .. tostring(sortingMethod))
  203. end
  204.  
  205. local i = 1
  206. while i <= #sortedFileList do
  207. if not showHiddenFiles and filesystem.isFileHidden(sortedFileList[i]) then
  208. table.remove(sortedFileList, i)
  209. else
  210. i = i + 1
  211. end
  212. end
  213. end
  214.  
  215. return sortedFileList
  216. end
  217.  
  218. function filesystem.directorySize(path)
  219. local size = 0
  220. for file in filesystem.list(path) do
  221. if filesystem.isDirectory(path .. file) then
  222. size = size + filesystem.directorySize(path .. file)
  223. else
  224. size = size + filesystem.size(path .. file)
  225. end
  226. end
  227.  
  228. return size
  229. end
  230.  
  231. function filesystem.readUnicodeChar(file)
  232. local byteArray = {string.byte(file:read(1))}
  233.  
  234. local nullBitPosition = 0
  235. for i = 1, 7 do
  236. if bit32.band(bit32.rshift(byteArray[1], 8 - i), 0x1) == 0x0 then
  237. nullBitPosition = i
  238. break
  239. end
  240. end
  241.  
  242. for i = 1, nullBitPosition - 2 do
  243. table.insert(byteArray, string.byte(file:read(1)))
  244. end
  245.  
  246. return string.char(table.unpack(byteArray))
  247. end
  248.  
  249. ----------------------------------------------------------------------------------------------------
  250.  
  251. function table.serialize(array, prettyLook, indentationWidth, indentUsingTabs, recursionStackLimit)
  252. checkArg(1, array, "table")
  253.  
  254. recursionStackLimit = recursionStackLimit or math.huge
  255. local indentationSymbolAdder = string.rep(indentUsingTabs and " " or " ", indentationWidth or 2)
  256. local equalsSymbol = prettyLook and " = " or "="
  257.  
  258. local function serializeRecursively(array, currentIndentationSymbol, currentRecusrionStack)
  259. local result, nextIndentationSymbol, keyType, valueType, stringValue = {"{"}, currentIndentationSymbol .. indentationSymbolAdder
  260.  
  261. if prettyLook then
  262. table.insert(result, "\n")
  263. end
  264.  
  265. for key, value in pairs(array) do
  266. keyType, valueType, stringValue = type(key), type(value), tostring(value)
  267.  
  268. if prettyLook then
  269. table.insert(result, nextIndentationSymbol)
  270. end
  271.  
  272. if keyType == "number" then
  273. table.insert(result, "[")
  274. table.insert(result, key)
  275. table.insert(result, "]")
  276. table.insert(result, equalsSymbol)
  277. elseif keyType == "string" then
  278. -- Короч, если типа начинается с буковки, а также если это алфавитно-нумерическая поеботня
  279. if prettyLook and key:match("^%a") and key:match("^[%w%_]+$") then
  280. table.insert(result, key)
  281. else
  282. table.insert(result, "[\"")
  283. table.insert(result, key)
  284. table.insert(result, "\"]")
  285. end
  286.  
  287. table.insert(result, equalsSymbol)
  288. end
  289.  
  290. if valueType == "number" or valueType == "boolean" or valueType == "nil" then
  291. table.insert(result, stringValue)
  292. elseif valueType == "string" or valueType == "function" then
  293. table.insert(result, "\"")
  294. table.insert(result, stringValue)
  295. table.insert(result, "\"")
  296. elseif valueType == "table" then
  297. if currentRecusrionStack < recursionStackLimit then
  298. table.insert(
  299. result,
  300. table.concat(
  301. serializeRecursively(
  302. value,
  303. nextIndentationSymbol,
  304. currentRecusrionStack + 1
  305. )
  306. )
  307. )
  308. else
  309. table.insert(result, "\"…\"")
  310. end
  311. end
  312.  
  313. table.insert(result, ",")
  314.  
  315. if prettyLook then
  316. table.insert(result, "\n")
  317. end
  318. end
  319.  
  320. -- Удаляем запятую
  321. if prettyLook then
  322. if #result > 2 then
  323. table.remove(result, #result - 1)
  324. end
  325.  
  326. table.insert(result, currentIndentationSymbol)
  327. else
  328. if #result > 1 then
  329. table.remove(result, #result)
  330. end
  331. end
  332.  
  333. table.insert(result, "}")
  334.  
  335. return result
  336. end
  337.  
  338. return table.concat(serializeRecursively(array, "", 1))
  339. end
  340.  
  341. function table.unserialize(serializedString)
  342. checkArg(1, serializedString, "string")
  343.  
  344. local result, reason = load("return " .. serializedString)
  345. if result then
  346. result, reason = pcall(result)
  347. if result then
  348. return reason
  349. else
  350. return nil, reason
  351. end
  352. else
  353. return nil, reason
  354. end
  355. end
  356.  
  357. table.toString = table.serialize
  358. table.fromString = table.unserialize
  359.  
  360. function table.toFile(path, array, prettyLook, indentationWidth, indentUsingTabs, recursionStackLimit, appendToFile)
  361. checkArg(1, path, "string")
  362. checkArg(2, array, "table")
  363.  
  364. filesystem.makeDirectory(filesystem.path(path) or "")
  365.  
  366. local file, reason = io.open(path, appendToFile and "a" or "w")
  367. if file then
  368. file:write(table.serialize(array, prettyLook, indentationWidth, indentUsingTabs, recursionStackLimit))
  369. file:close()
  370. else
  371. error("Failed to open file for writing: " .. tostring(reason))
  372. end
  373. end
  374.  
  375. function table.fromFile(path)
  376. checkArg(1, path, "string")
  377.  
  378. local file, reason = io.open(path, "r")
  379. if file then
  380. local data, reason = table.unserialize(file:read("*a"))
  381. file:close()
  382.  
  383. if data then
  384. return data
  385. else
  386. error("Failed to unserialize file \"" .. path .. "\": " .. tostring(reason))
  387. end
  388. else
  389. error("Failed to open file \"" .. path .. "\" for reading: " .. tostring(reason))
  390. end
  391. end
  392.  
  393. function table.copy(tableToCopy)
  394. local function copyTableRecursively(source, destination)
  395. for key, value in pairs(source) do
  396. if type(value) == "table" then
  397. destination[key] = {}
  398. doTableCopy(source[key], destination[key])
  399. else
  400. destination[key] = value
  401. end
  402. end
  403. end
  404.  
  405. local result = {}
  406. copyTableRecursively(tableToCopy, result)
  407.  
  408. return result
  409. end
  410.  
  411. function table.size(t)
  412. local size = 0
  413. for key in pairs(t) do size = size + 1 end
  414. return size
  415. end
  416.  
  417. function table.contains(t, object)
  418. for _, value in pairs(t) do
  419. if value == object then
  420. return true
  421. end
  422. end
  423. return false
  424. end
  425.  
  426. function table.indexOf(t, object)
  427. for i = 1, #t do
  428. if t[i] == object then
  429. return i
  430. end
  431. end
  432. end
  433.  
  434. function table.sortAlphabetically(t)
  435. table.sort(t, function(a, b) return a < b end)
  436. end
  437.  
  438. ----------------------------------------------------------------------------------------------------
  439.  
  440. function string.brailleChar(a, b, c, d, e, f, g, h)
  441. return unicode.char(10240 + 128*h + 64*g + 32*f + 16*d + 8*b + 4*e + 2*c + a)
  442. end
  443.  
  444. function string.canonicalPath(str)
  445. return string.gsub("/" .. str, "%/+", "/")
  446. end
  447.  
  448. function string.optimize(str, indentationWidth)
  449. str = string.gsub(str, "\r\n", "\n")
  450. str = string.gsub(str, " ", string.rep(" ", indentationWidth or 2))
  451. return str
  452. end
  453.  
  454. function string.optimizeForURLRequests(code)
  455. if code then
  456. code = string.gsub(code, "([^%w ])", function (c)
  457. return string.format("%%%02X", string.byte(c))
  458. end)
  459. code = string.gsub(code, " ", "+")
  460. end
  461. return code
  462. end
  463.  
  464. function string.unicodeFind(str, pattern, init, plain)
  465. if init then
  466. if init < 0 then
  467. init = -#unicode.sub(str, init)
  468. elseif init > 0 then
  469. init = #unicode.sub(str, 1, init - 1) + 1
  470. end
  471. end
  472.  
  473. a, b = string.find(str, pattern, init, plain)
  474.  
  475. if a then
  476. local ap, bp = str:sub(1, a - 1), str:sub(a,b)
  477. a = unicode.len(ap) + 1
  478. b = a + unicode.len(bp) - 1
  479. return a, b
  480. else
  481. return a
  482. end
  483. end
  484.  
  485. function string.limit(s, limit, mode, noDots)
  486. local length = unicode.len(s)
  487. if length <= limit then return s end
  488.  
  489. if mode == "left" then
  490. if noDots then
  491. return unicode.sub(s, length - limit + 1, -1)
  492. else
  493. return "…" .. unicode.sub(s, length - limit + 2, -1)
  494. end
  495. elseif mode == "center" then
  496. local integer, fractional = math.modf(limit / 2)
  497. if fractional == 0 then
  498. return unicode.sub(s, 1, integer) .. "…" .. unicode.sub(s, -integer + 1, -1)
  499. else
  500. return unicode.sub(s, 1, integer) .. "…" .. unicode.sub(s, -integer, -1)
  501. end
  502. else
  503. if noDots then
  504. return unicode.sub(s, 1, limit)
  505. else
  506. return unicode.sub(s, 1, limit - 1) .. "…"
  507. end
  508. end
  509. end
  510.  
  511. function string.wrap(data, limit)
  512. if type(data) == "string" then data = {data} end
  513.  
  514. local wrappedLines, result, preResult, position = {}
  515.  
  516. -- Дублируем таблицу строк, шоб не перекосоебить ченить переносами
  517. for i = 1, #data do
  518. wrappedLines[i] = data[i]
  519. end
  520.  
  521. -- Отсечение возврата каретки-ебуретки
  522. local i = 1
  523. while i <= #wrappedLines do
  524. local position = string.unicodeFind(wrappedLines[i], "\n")
  525. if position then
  526. table.insert(wrappedLines, i + 1, unicode.sub(wrappedLines[i], position + 1, -1))
  527. wrappedLines[i] = unicode.sub(wrappedLines[i], 1, position - 1)
  528. end
  529.  
  530. i = i + 1
  531. end
  532.  
  533. -- Сам перенос
  534. local i = 1
  535. while i <= #wrappedLines do
  536. result = ""
  537.  
  538. for word in wrappedLines[i]:gmatch("[^%s]+") do
  539. preResult = result .. word
  540.  
  541. if unicode.len(preResult) > limit then
  542. if unicode.len(word) > limit then
  543. table.insert(wrappedLines, i + 1, unicode.sub(wrappedLines[i], limit + 1, -1))
  544. result = unicode.sub(wrappedLines[i], 1, limit)
  545. else
  546. table.insert(wrappedLines, i + 1, unicode.sub(wrappedLines[i], unicode.len(result) + 1, -1))
  547. end
  548.  
  549. break
  550. else
  551. result = preResult .. " "
  552. end
  553. end
  554.  
  555. wrappedLines[i] = result:gsub("%s+$", ""):gsub("^%s+", "")
  556.  
  557. i = i + 1
  558. end
  559.  
  560. return wrappedLines
  561. end
  562.  
  563. ----------------------------------------------------------------------------------------------------
  564.  
  565. return {loaded = true}
Add Comment
Please, Sign In to add comment