2021-06-11 20:47:29 +02:00
|
|
|
-- Localize globals
|
|
|
|
local math, modlib, pairs, setmetatable, string, table = math, modlib, pairs, setmetatable, string, table
|
|
|
|
|
2021-06-17 19:45:08 +02:00
|
|
|
-- Set environment
|
|
|
|
local _ENV = {}
|
|
|
|
setfenv(1, _ENV)
|
|
|
|
|
2020-12-18 12:27:19 +01:00
|
|
|
function upper_first(text) return text:sub(1, 1):upper() .. text:sub(2) end
|
|
|
|
|
|
|
|
function lower_first(text) return text:sub(1, 1):lower() .. text:sub(2) end
|
|
|
|
|
|
|
|
function starts_with(text, start) return text:sub(1, start:len()) == start end
|
|
|
|
|
|
|
|
function ends_with(text, suffix) return text:sub(text:len() - suffix:len() + 1) == suffix end
|
|
|
|
|
|
|
|
function trim(text, to_remove)
|
|
|
|
local j = 1
|
|
|
|
for i = 1, string.len(text) do
|
|
|
|
if text:sub(i, i) ~= to_remove then
|
|
|
|
j = i
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
local k = 1
|
|
|
|
for i = string.len(text), j, -1 do
|
|
|
|
if text:sub(i, i) ~= to_remove then
|
|
|
|
k = i
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return text:sub(j, k)
|
2020-02-09 01:39:54 +01:00
|
|
|
end
|
|
|
|
|
2020-12-18 12:27:19 +01:00
|
|
|
function trim_begin(text, to_remove)
|
|
|
|
local j = 1
|
|
|
|
for i = 1, string.len(text) do
|
|
|
|
if text:sub(i, i) ~= to_remove then
|
|
|
|
j = i
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return text:sub(j)
|
2020-02-09 01:39:54 +01:00
|
|
|
end
|
|
|
|
|
2020-06-02 23:07:33 +02:00
|
|
|
trim_left = trim_begin
|
|
|
|
|
2020-12-18 12:27:19 +01:00
|
|
|
function trim_end(text, to_remove)
|
|
|
|
local k = 1
|
|
|
|
for i = string.len(text), 1, -1 do
|
|
|
|
if text:sub(i, i) ~= to_remove then
|
|
|
|
k = i
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return text:sub(1, k)
|
2020-06-02 23:07:33 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
trim_right = trim_end
|
|
|
|
|
2021-08-29 15:41:51 +02:00
|
|
|
function trim_spacing(text)
|
2021-09-18 14:08:09 +02:00
|
|
|
return text:match"^%s*(.-)%s*$"
|
2021-08-29 15:41:51 +02:00
|
|
|
end
|
|
|
|
|
2021-03-04 19:45:34 +01:00
|
|
|
local inputstream_metatable = {
|
|
|
|
__index = {read = function(self, count)
|
|
|
|
local cursor = self.cursor + 1
|
|
|
|
self.cursor = self.cursor + count
|
|
|
|
local text = self.text:sub(cursor, self.cursor)
|
|
|
|
return text ~= "" and text or nil
|
|
|
|
end}
|
|
|
|
}
|
|
|
|
function inputstream(text)
|
|
|
|
return setmetatable({text = text, cursor = 0}, inputstream_metatable)
|
|
|
|
end
|
|
|
|
|
2021-03-05 11:05:47 +01:00
|
|
|
function hexdump(text)
|
|
|
|
local dump = {}
|
|
|
|
for index = 1, text:len() do
|
|
|
|
dump[index] = ("%02X"):format(text:byte(index))
|
|
|
|
end
|
|
|
|
return table.concat(dump)
|
|
|
|
end
|
2021-03-04 19:45:34 +01:00
|
|
|
|
2020-12-18 12:27:19 +01:00
|
|
|
function split(text, delimiter, limit, is_regex)
|
|
|
|
limit = limit or math.huge
|
|
|
|
local no_regex = not is_regex
|
|
|
|
local parts = {}
|
|
|
|
local occurences = 1
|
|
|
|
local last_index = 1
|
|
|
|
local index = string.find(text, delimiter, 1, no_regex)
|
|
|
|
while index and occurences < limit do
|
|
|
|
table.insert(parts, string.sub(text, last_index, index - 1))
|
|
|
|
last_index = index + string.len(delimiter)
|
|
|
|
index = string.find(text, delimiter, index + string.len(delimiter), no_regex)
|
|
|
|
occurences = occurences + 1
|
|
|
|
end
|
|
|
|
table.insert(parts, string.sub(text, last_index))
|
|
|
|
return parts
|
2020-02-09 01:39:54 +01:00
|
|
|
end
|
|
|
|
|
2020-12-18 12:27:19 +01:00
|
|
|
function split_without_limit(text, delimiter, is_regex) return split(text, delimiter, nil, is_regex) end
|
2020-02-09 01:39:54 +01:00
|
|
|
|
2020-06-02 23:07:33 +02:00
|
|
|
split_unlimited = split_without_limit
|
|
|
|
|
2020-12-18 12:27:19 +01:00
|
|
|
function split_lines(text, limit) return modlib.text.split(text, "\r?\n", limit, true) end
|
|
|
|
|
|
|
|
function lines(text) return text:gmatch"[^\r\n]*" end
|
2020-06-02 23:07:33 +02:00
|
|
|
|
2020-12-18 12:27:19 +01:00
|
|
|
local zero = string.byte"0"
|
|
|
|
local nine = string.byte"9"
|
|
|
|
local letter_a = string.byte"A"
|
|
|
|
local letter_f = string.byte"F"
|
2020-02-09 01:39:54 +01:00
|
|
|
|
|
|
|
function is_hexadecimal(byte)
|
2020-12-18 12:27:19 +01:00
|
|
|
return byte >= zero and byte <= nine or byte >= letter_a and byte <= letter_f
|
2020-02-09 01:39:54 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
magic_chars = {
|
2020-12-18 12:27:19 +01:00
|
|
|
"%",
|
|
|
|
"(",
|
|
|
|
")",
|
|
|
|
".",
|
|
|
|
"+",
|
|
|
|
"-",
|
|
|
|
"*",
|
|
|
|
"?",
|
|
|
|
"[",
|
|
|
|
"^",
|
|
|
|
"$"
|
2020-02-09 01:39:54 +01:00
|
|
|
}
|
2020-12-18 12:27:19 +01:00
|
|
|
local magic_charset = {}
|
|
|
|
for _, magic_char in pairs(magic_chars) do table.insert(magic_charset, "%" .. magic_char) end
|
|
|
|
magic_charset = "[" .. table.concat(magic_charset) .. "]"
|
2020-02-09 01:39:54 +01:00
|
|
|
|
2020-12-18 12:27:19 +01:00
|
|
|
function escape_magic_chars(text) return text:gsub("(" .. magic_charset .. ")", "%%%1") end
|
2020-02-09 01:39:54 +01:00
|
|
|
|
|
|
|
function utf8(number)
|
2021-08-14 00:15:48 +02:00
|
|
|
if number <= 0x007F then
|
2020-12-18 12:27:19 +01:00
|
|
|
-- Single byte
|
|
|
|
return string.char(number)
|
|
|
|
end
|
|
|
|
if number < 0x00A0 or number > 0x10FFFF then
|
|
|
|
-- Out of range
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local result = ""
|
|
|
|
local i = 0
|
|
|
|
while true do
|
|
|
|
local remainder = number % 64
|
|
|
|
result = string.char(128 + remainder) .. result
|
|
|
|
number = (number - remainder) / 64
|
|
|
|
i = i + 1
|
2020-12-19 15:31:37 +01:00
|
|
|
if number <= 2 ^ (8 - i - 2) then break end
|
2020-12-18 12:27:19 +01:00
|
|
|
end
|
2020-12-19 15:31:37 +01:00
|
|
|
return string.char(256 - 2 ^ (8 - i - 1) + number) .. result
|
2020-02-09 01:39:54 +01:00
|
|
|
end
|
|
|
|
|
2020-12-18 12:27:19 +01:00
|
|
|
--+ deprecated
|
2020-08-23 22:37:17 +02:00
|
|
|
function handle_ifdefs(code, vars)
|
2020-12-18 12:27:19 +01:00
|
|
|
local finalcode = {}
|
|
|
|
local endif
|
|
|
|
local after_endif = -1
|
|
|
|
local ifdef_pos, after_ifdef = string.find(code, "--IFDEF", 1, true)
|
|
|
|
while ifdef_pos do
|
|
|
|
table.insert(finalcode, string.sub(code, after_endif + 2, ifdef_pos - 1))
|
|
|
|
local linebreak = string.find(code, "\n", after_ifdef + 1, true)
|
|
|
|
local varname = string.sub(code, after_ifdef + 2, linebreak - 1)
|
|
|
|
endif, after_endif = string.find(code, "--ENDIF", linebreak + 1, true)
|
|
|
|
if not endif then break end
|
|
|
|
if vars[varname] then
|
|
|
|
table.insert(finalcode, string.sub(code, linebreak + 1, endif - 1))
|
|
|
|
end
|
|
|
|
ifdef_pos, after_ifdef = string.find(code, "--IFDEF", after_endif + 1, true)
|
|
|
|
end
|
|
|
|
table.insert(finalcode, string.sub(code, after_endif + 2))
|
|
|
|
return table.concat(finalcode, "")
|
2021-06-17 19:45:08 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
-- Export environment
|
|
|
|
return _ENV
|