mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-16 22:46:03 +01:00
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.
176 lines
4.3 KiB
Lua
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
|