traceObject: function that gets all references to an object

Showcase your libraries, tools and other projects that help your fellow love users.
Post Reply
User avatar
Gunroar:Cannon()
Party member
Posts: 1085
Joined: Thu Dec 10, 2020 1:57 am

traceObject: function that gets all references to an object

Post by Gunroar:Cannon() »

I created this function to help trace any references to an object. It can be useful to
know whether an object is not deleted propally, to find any object tha can be messing with
your code or any other purpose that involves tracing the locations of an object.
Here it is:

Code: Select all

function traceObject(target,ignore,start)
    local isarray = function(x)
        return type(x) == "table" and x[1] ~= nil
    end

    local getiter = function(x)
        if isarray(x) then
            return ipairs
        elseif type(x) == "table" then
            return pairs
        end
        error("expected table", 3)
    end

    local function remove(t, x)
        local iter = getiter(t)
        for i, v in iter(t) do
            if v == x then
                if isarray(t) then
                    table.remove(t, i)
                    return true
                else
                    t[i] = nil
                    return true
                end
            end
        end
        return false
    end

    local done = {}
    local data = ""
    local count = 0
    local refs = {}
    local gotten = {}
    local printed = {}
    if type(ignore)=="string" then
        ignore = {_G, ignore}
    else
        ignore = {}
    end

    local function _traceObject(m,name)
        done[tostring(m)] = true
        local _printed = {}
        
        local function check(x,i)
        
            if i==target and not (x==ignore[2] and m==ignore[1]) then
                if not gotten[tostring(m)..x] then
                    local sp = " "
                    gotten[tostring(m)..x] = 1
                    table.insert(refs,{name or "_G",m})
        
                    if not printed[tostring(m)] then
                        for cc = 1,#refs do
                            local r = refs[cc]
                            local name, value = r[1],r[2]
                            if not _printed[tostring(value)..name] then
                                data = string.format("%s\n%sMoving to index %s: ",data,sp,name)
                                sp = string.format("%s    ",sp)
                                _printed[tostring(value)..name] = 1
                            end
                        end
                        printed[tostring(m)] = sp
                    end
                    sp = printed[tostring(m)]
                    data = string.format("%s\n%sFound target at index `%s`.",data,sp,x)
                    
                    refs[#refs] = nil
                end
            
            elseif type(i)=="table" and not done[tostring(i)] then
                local tt = {name or "_G",m}
                local name = name or "_G"
                
                table.insert(refs,tt)
                _traceObject(i,x)
                remove(refs,tt)
               
            end
        end
        
        for x,i in pairs(m) do
            check(x,i)
        end
        for x,i in ipairs(m) do
            check(x,i)
        end
        return data
    end
    local data = _traceObject(start or _G)
    if data=="" then
        data = "Not Found!"
    end
    return data
end
Use:
traceObject(table object[, table ignore, table start])
table object: object(mostly table, can be other) that should be traced
table ignore: {table parent, string name}, ignore entries of key 'name' in parent
string ignore: ignores global variable put in ignore
table start: where to start tracing, defaults to _G
returns: string representing traces of where the object lies

Code: Select all

--example
t = {"hey"}
gotcha = {["that"]=t}
gotcha.forge = {hey={7,8,9,k={0,["that"]=t,["y"]={"can",t},nu={7,7,t}},t,t}}


--print traces ignoring key "that" at table gotcha
print(traceObject(gotcha.that,{gotcha,"that"}))

--print traces ignoring key "t" at global table
print(traceObject(gotcha.that,"t"))

--print all traces
print(traceObject(gotcha.that))

--print all traces starting from gotcha.forge
print(traceObject(gotcha.that,nil,gotcha.forge))

--print all traces of string "can"
print(traceObject("can,"t"))
If there's any problem in it pls let me know. Use it as you please.
Attachments
trace.lua
(2.8 KiB) Downloaded 329 times
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
Post Reply

Who is online

Users browsing this forum: No registered users and 14 guests