xref: /freebsd/sys/tools/syscalls/tools/util.lua (revision 9ded074e875c29cb92d5f643801990d7bb23cca4)
1--
2-- SPDX-License-Identifier: BSD-2-Clause
3--
4-- Copyright (c) 2024 Tyler Baxter <agge@FreeBSD.org>
5-- Copyright (c) 2023 Warner Losh <imp@bsdimp.com>
6-- Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
7--
8
9local util = {}
10
11--
12-- Returns a trimmed string. Default is to trim whitespace.
13--
14-- PARAM: String s, the string to trim.
15--
16-- PARAM: char, nil or optional character to trim.
17--
18function util.trim(s, char)
19	if s == nil then
20		return nil
21	end
22	if char == nil then
23		char = "%s"
24	end
25	return s:gsub("^" .. char .. "+", ""):gsub(char .. "+$", "")
26end
27
28-- Returns a table (list) of strings.
29function util.split(s, re)
30	local t = { }
31
32	for v in s:gmatch(re) do
33		table.insert(t, v)
34	end
35	return t
36end
37
38-- Aborts with a message and does a clean exit procedure.
39function util.abort(status, msg)
40	assert(io.stderr:write(msg .. "\n"))
41	-- cleanup
42	os.exit(status)
43end
44
45--
46-- Returns a set.
47--
48-- PARAM: t, a list.
49--
50-- EXAMPLE: param: {"foo", "bar"}, return: {foo = true, bar = true}
51--
52function util.set(t)
53	local s = { }
54
55	for _,v in pairs(t) do
56		s[v] = true
57	end
58	return s
59end
60
61--
62-- Returns a set.
63--
64-- PARAM: str, a string.
65-- PARAM: re, the pattern to construct keys from.
66--
67function util.setFromString(str, re)
68	local s = { }
69
70	for v in str:gmatch(re) do
71		s[v] = true
72	end
73	return s
74end
75
76function util.isEmpty(tbl)
77	if tbl ~= nil then
78		if next(tbl) == nil then
79			return true
80		end
81		return false
82	end
83	return true
84end
85
86--
87--  Iterator that traverses a table following the order of its keys.
88--  An optional parameter f allows the specification of an alternative order.
89--
90--  CREDIT: https://www.lua.org/pil/19.3.html
91--  LICENSE: MIT
92--
93function util.pairsByKeys(t, f)
94	local a = {}
95	for n in pairs(t) do table.insert(a, n) end
96	table.sort(a, f)
97	local i = 0	  -- iterator variable
98	local iter = function ()   -- iterator function
99		i = i + 1
100		if a[i] == nil then
101			return nil
102		else
103			return a[i], t[a[i]]
104		end
105	end
106	return iter
107end
108
109--
110-- Checks for pointer types: '*', caddr_t, or intptr_t.
111--
112-- PARAM: type, the type to check.
113--
114-- PARAM: abi, nil or optional ABI-specified intptr_t.
115--
116function util.isPtrType(type, abi)
117	local default = abi or "intptr_t"
118	return type:find("*") or type:find("caddr_t") or type:find(default)
119end
120
121function util.isPtrArrayType(type)
122	return type:find("[*][*]") or type:find("[*][ ]*const[ ]*[*]")
123end
124
125-- Find types that are always 64-bits wide.
126function util.is64bitType(type)
127	return type:find("^dev_t[ ]*$") or type:find("^id_t[ ]*$") or
128	    type:find("^off_t[ ]*$")
129end
130
131--
132-- Returns the name of the struct pointed to by the argument or nil.
133--
134-- PARAM: type, the type to check.
135--
136function util.structName(type)
137	if util.isPtrType(type) then
138		local is_struct = false
139		for word in type:gmatch("[^ *]+") do
140			if is_struct then
141				return word
142			end
143			if word == "struct" then
144				-- next word is the struct name
145				is_struct = true
146			end
147		end
148	end
149	return nil
150end
151
152-- Strip the ABI function prefix if it exists (e.g., "freebsd32_"). Returns the
153-- function name with the ABI prefix stripped, or the original function name if
154-- there was no ABI function prefix.
155function util.stripAbiPrefix(funcname, abiprefix)
156	local stripped_name
157	if funcname == nil then
158		return nil
159	end
160	if abiprefix ~= "" and funcname:find("^" .. abiprefix) then
161		stripped_name = funcname:gsub("^" .. abiprefix, "")
162	else
163		stripped_name = funcname
164	end
165
166	return stripped_name
167end
168
169-- ipairs for a sparse array.
170-- CREDIT: Lua Game Development Cookbook, Mario Kasuba
171function util.ipairsSparse(t)
172	-- tmp_index will hold sorted indices, otherwise
173	-- this iterator would be no different from pairs iterator
174	local tmp_index = {}
175	local index, _ = next(t)
176	while index do
177		tmp_index[#tmp_index + 1] = index
178		index, _ = next(t, index)
179	end
180	-- sort table indices
181	table.sort(tmp_index)
182	local j = 1
183
184	return function()
185		-- get index value
186		local i = tmp_index[j]
187		j = j + 1
188		if i then
189			return i, t[i]
190		end
191	end
192end
193
194return util
195