1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
-- Copyright 2025 David Vazgenovich Shakaryan
local mp_utils = require('mp.utils')
local util = {}
function util.copy_table(t)
local u = {}
for k, v in pairs(t) do
u[k] = v
end
return u
end
function util.reverse(t)
for i = 1, #t/2 do
t[i], t[#t-i+1] = t[#t-i+1], t[i]
end
end
function util.strip(str)
return (str:gsub('^%s*(.-)%s*$', '%1'))
end
-- skips over utf8 continuation bytes (10xxxxxx)
-- valid positions range from 1 to #str + 1 (*after* the last byte)
function util.utf8_seek(str, pos, n)
local step = n > 0 and 1 or -1
local test = n > 0
and function() return pos > #str end
or function() return pos <= 1 end
while n ~= 0 and not test() do
repeat
pos = pos + step
until test() or bit.band(str:byte(pos), 0xc0) ~= 0x80
n = n - step
end
return pos
end
-- wraps string into a table of strings. spaces are not removed, resulting in
-- width-1 visible chars; newlines and end of string are handled similarly for
-- consistency. words longer than width are not broken. optional cont_width can
-- be specified to use a different width for continuation lines.
function util.wrap(str, width, cont_width)
local t = {}
local start, stop = 0, 0
while stop < #str do
local i = str:find('[ \n]', stop + 1) or #str + 1
if i - start >= width then
t[#t+1] = str:sub(start, stop)
start = stop + 1
if cont_width then
width = cont_width
end
end
stop = i
if str:byte(stop) == 10 or stop >= #str then
t[#t+1] = str:sub(start, stop - 1) .. ' '
start = stop + 1
end
end
return t
end
function util.read_json_file(path)
local f = io.open(path, 'r')
if not f then
return {}
end
local json = f:read('*all')
f:close()
return mp_utils.parse_json(json)
end
function util.write_json_file(path, data)
local f = io.open(path, 'w')
f:write(mp_utils.format_json(data), '\n')
f:close()
end
return util
|