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-- Prints a warning to stderr 39function util.warn(msg) 40 assert(io.stderr:write("WARNING: " .. msg .. "\n")) 41end 42 43-- Aborts with a message and does a clean exit procedure. 44function util.abort(status, msg) 45 assert(io.stderr:write(msg .. "\n")) 46 -- cleanup 47 os.exit(status) 48end 49 50-- 51-- Returns a set. 52-- 53-- PARAM: t, a list. 54-- 55-- EXAMPLE: param: {"foo", "bar"}, return: {foo = true, bar = true} 56-- 57function util.set(t) 58 local s = { } 59 60 for _,v in pairs(t) do 61 s[v] = true 62 end 63 return s 64end 65 66-- 67-- Returns a set. 68-- 69-- PARAM: str, a string. 70-- PARAM: re, the pattern to construct keys from. 71-- 72function util.setFromString(str, re) 73 local s = { } 74 75 for v in str:gmatch(re) do 76 s[v] = true 77 end 78 return s 79end 80 81function util.isEmpty(tbl) 82 if tbl ~= nil then 83 if next(tbl) == nil then 84 return true 85 end 86 return false 87 end 88 return true 89end 90 91-- 92-- Iterator that traverses a table following the order of its keys. 93-- An optional parameter f allows the specification of an alternative order. 94-- 95-- CREDIT: https://www.lua.org/pil/19.3.html 96-- LICENSE: MIT 97-- 98function util.pairsByKeys(t, f) 99 local a = {} 100 for n in pairs(t) do table.insert(a, n) end 101 table.sort(a, f) 102 local i = 0 -- iterator variable 103 local iter = function () -- iterator function 104 i = i + 1 105 if a[i] == nil then 106 return nil 107 else 108 return a[i], t[a[i]] 109 end 110 end 111 return iter 112end 113 114-- 115-- Checks for pointer types: '*', caddr_t, or intptr_t. 116-- 117-- PARAM: type, the type to check. 118-- 119-- PARAM: abi, nil or optional ABI-specified intptr_t. 120-- 121function util.isPtrType(type, abi) 122 local default = abi or "intptr_t" 123 return type:find("*") or type:find("caddr_t") or type:find(default) 124end 125 126function util.isPtrArrayType(type) 127 return type:find("[*][*]") or type:find("[*][ ]*const[ ]*[*]") 128end 129 130-- Find types that are always 64-bits wide. 131function util.is64bitType(type) 132 return type:find("^dev_t[ ]*$") or type:find("^id_t[ ]*$") or 133 type:find("^off_t[ ]*$") 134end 135 136-- 137-- Returns the name of the struct pointed to by the argument or nil. 138-- 139-- PARAM: type, the type to check. 140-- 141function util.structName(type) 142 if util.isPtrType(type) then 143 local is_struct = false 144 for word in type:gmatch("[^ *]+") do 145 if is_struct then 146 return word 147 end 148 if word == "struct" then 149 -- next word is the struct name 150 is_struct = true 151 end 152 end 153 end 154 return nil 155end 156 157-- Strip the ABI function prefix if it exists (e.g., "freebsd32_"). Returns the 158-- function name with the ABI prefix stripped, or the original function name if 159-- there was no ABI function prefix. 160function util.stripAbiPrefix(funcname, abiprefix) 161 local stripped_name 162 if funcname == nil then 163 return nil 164 end 165 if abiprefix ~= "" and funcname:find("^" .. abiprefix) then 166 stripped_name = funcname:gsub("^" .. abiprefix, "") 167 else 168 stripped_name = funcname 169 end 170 171 return stripped_name 172end 173 174-- ipairs for a sparse array. 175-- CREDIT: Lua Game Development Cookbook, Mario Kasuba 176function util.ipairsSparse(t) 177 -- tmp_index will hold sorted indices, otherwise 178 -- this iterator would be no different from pairs iterator 179 local tmp_index = {} 180 local index, _ = next(t) 181 while index do 182 tmp_index[#tmp_index + 1] = index 183 index, _ = next(t, index) 184 end 185 -- sort table indices 186 table.sort(tmp_index) 187 local j = 1 188 189 return function() 190 -- get index value 191 local i = tmp_index[j] 192 j = j + 1 193 if i then 194 return i, t[i] 195 end 196 end 197end 198 199return util 200