Files
ox_lib/imports/table/shared.lua
Linden fb2225e373 chore: add copyright notices to each file
Some people accidentally, mistakenly, and without any malicious intent forget to attribute code from this resource to its source. This change will hopefully assist people, so that they do not make that mistake again.
2025-03-18 18:46:09 +11:00

176 lines
4.3 KiB
Lua

--[[
https://github.com/overextended/ox_lib
This file is licensed under LGPL-3.0 or higher <https://www.gnu.org/licenses/lgpl-3.0.en.html>
Copyright (c) 2025 Linden <https://github.com/thelindat/fivem>
]]
-- Add additional functions to the standard table library
---@class oxtable : tablelib
lib.table = table
local pairs = pairs
---@param tbl table
---@param value any
---@return boolean
---Checks if tbl contains the given values. Only intended for simple values and unnested tables.
local function contains(tbl, value)
if type(value) ~= 'table' then
for _, v in pairs(tbl) do
if v == value then
return true
end
end
return false
else
local set = {}
for _, v in pairs(tbl) do
set[v] = true
end
for _, v in pairs(value) do
if not set[v] then
return false
end
end
return true
end
end
---@param t1 any
---@param t2 any
---@return boolean
---Compares if two values are equal, iterating over tables and matching both keys and values.
local function table_matches(t1, t2)
local tabletype1 = table.type(t1)
if not tabletype1 then return t1 == t2 end
if tabletype1 ~= table.type(t2) or (tabletype1 == 'array' and #t1 ~= #t2) then
return false
end
for k, v1 in pairs(t1) do
local v2 = t2[k]
if v2 == nil or not table_matches(v1, v2) then
return false
end
end
for k in pairs(t2) do
if t1[k] == nil then
return false
end
end
return true
end
---@generic T
---@param tbl T
---@return T
---Recursively clones a table to ensure no table references.
local function table_deepclone(tbl)
tbl = table.clone(tbl)
for k, v in pairs(tbl) do
if type(v) == 'table' then
tbl[k] = table_deepclone(v)
end
end
return tbl
end
---@param t1 table
---@param t2 table
---@param addDuplicateNumbers boolean? add duplicate number keys together if true, replace if false. Defaults to true.
---@return table
---Merges two tables together. Defaults to adding duplicate keys together if they are numbers, otherwise they are overriden.
local function table_merge(t1, t2, addDuplicateNumbers)
addDuplicateNumbers = addDuplicateNumbers == nil or addDuplicateNumbers
for k, v2 in pairs(t2) do
local v1 = t1[k]
local type1 = type(v1)
local type2 = type(v2)
if type1 == 'table' and type2 == 'table' then
table_merge(v1, v2, addDuplicateNumbers)
elseif addDuplicateNumbers and (type1 == 'number' and type2 == 'number') then
t1[k] = v1 + v2
else
t1[k] = v2
end
end
return t1
end
---@param tbl table
---@return table
---Shuffles the elements of a table randomly using the Fisher-Yates algorithm.
local function shuffle(tbl)
local len = #tbl
for i = len, 2, -1 do
local j = math.random(i)
tbl[i], tbl[j] = tbl[j], tbl[i]
end
return tbl
end
table.contains = contains
table.matches = table_matches
table.deepclone = table_deepclone
table.merge = table_merge
table.shuffle = shuffle
local frozenNewIndex = function(self) error(('cannot set values on a frozen table (%s)'):format(self), 2) end
local _rawset = rawset
---@param tbl table
---@param index any
---@param value any
---@return table
function rawset(tbl, index, value)
if table.isfrozen(tbl) then
frozenNewIndex(tbl)
end
return _rawset(tbl, index, value)
end
---Makes a table read-only, preventing further modification. Unfrozen tables stored within `tbl` are still mutable.
---@generic T : table
---@param tbl T
---@return T
function table.freeze(tbl)
local copy = table.clone(tbl)
local metatbl = getmetatable(tbl)
table.wipe(tbl)
setmetatable(tbl, {
__index = metatbl and setmetatable(copy, metatbl) or copy,
__metatable = 'readonly',
__newindex = frozenNewIndex,
__len = function() return #copy end,
---@diagnostic disable-next-line: redundant-return-value
__pairs = function() return next, copy end,
})
return tbl
end
---Return true if `tbl` is set as read-only.
---@param tbl table
---@return boolean
function table.isfrozen(tbl)
return getmetatable(tbl) == 'readonly'
end
return lib.table