vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:
---------------------------------------------------------------------------
-- Embedded Library Registration Stub
-- Written by Iriel <iriel@vigilance-committee.org>
-- Version 0.1 - 2006-03-05
-- Modified by Tekkub <tekkub@gmail.com>
---------------------------------------------------------------------------
-- YOU DON'T NEED TO TOUCH ANYTHING IN THIS BLOCK OF CODE
---------------------------------------------------------------------------

if not EmbedLibStub then
        EmbedLibStub = {}


        -- Instance replacement method, replace contents of old with that of new
        function EmbedLibStub:ReplaceInstance(old, new)
                 for k,v in pairs(old) do old[k]=nil end
                 for k,v in pairs(new) do old[k]=v end
        end


        -- Get a new copy of the stub
        function EmbedLibStub:NewStub(name)
                local newStub = {}
                self:ReplaceInstance(newStub, self)
                newStub.libName = name
                newStub.lastVersion = ''
                newStub.versions = {}
                return newStub
        end


        -- Get instance version
        function EmbedLibStub:NeedsUpgraded(vmajor, vminor)
                local versionData = self.versions[vmajor]
                if not versionData or versionData.minor < vminor then return true end
        end


        -- Get instance version
        function EmbedLibStub:GetInstance(version)
                if not version then version = self.lastVersion end
                local versionData = self.versions[version]
                if not versionData then print(string.format("<%s> Cannot find library version: %s", self.libName, version or "")) return end
                return versionData.instance
        end


        -- Register new instance
        function EmbedLibStub:Register(newInstance)
                 local version,minor = newInstance:GetLibraryVersion()
                 self.lastVersion = version
                 local versionData = self.versions[version]
                 if not versionData then
                                -- This one is new!
                                versionData = {
                                        instance = newInstance,
                                        minor = minor,
                                        old = {},
                                }
                                self.versions[version] = versionData
                                newInstance:LibActivate(self)
                                return newInstance
                 end
                 -- This is an update
                 local oldInstance = versionData.instance
                 local oldList = versionData.old
                 versionData.instance = newInstance
                 versionData.minor = minor
                 local skipCopy = newInstance:LibActivate(self, oldInstance, oldList)
                 table.insert(oldList, oldInstance)
                 if not skipCopy then
                                for i, old in ipairs(oldList) do self:ReplaceInstance(old, newInstance) end
                 end
                 return newInstance
        end
end



----------------------------------
--      Library Definition      --
----------------------------------

local vmajor, vminor = "compost-1", 1
local libvarname = "CompostLib"
local usedebug = false


---------------------------------------------------------------------------
-- This code is the Library's management code
-- You don't need to change anything here
---------------------------------------------------------------------------

local libobj = getglobal(libvarname)
if not libobj then
        libobj = EmbedLibStub:NewStub(libvarname)
        setglobal(libvarname, libobj)
end


if libobj:NeedsUpgraded(vmajor, vminor) then

        local lib = {}


        -- Return the library's current version
        function lib:GetLibraryVersion() return vmajor, vminor end


        -- Activate a new instance of this library
        function lib:LibActivate(stub, oldLib, oldList)
                local maj, min = self:GetLibraryVersion()
                if usedebug then print(string.format("<%s> Activating version %s - %d", libvarname, maj, min)) end

                if oldLib then
                        local omaj, omin = oldLib:GetLibraryVersion()
                        if usedebug then print(string.format("<%s> Replacing old version %s - %d", libvarname, omaj, omin)) end

                        self.var, self.k = oldLib.var, oldLib.k
                else
                        self.k = {  -- Constants go here
                                maxcache = 10,          -- I think this is a good number, I'll change it later if necessary
                        }
                        self.var = {  -- "Local" variables go here
                                cache = {},
                                secondarycache = {},
                        }

                        -- This makes the secondary cache table a weak table, any values in it will be reclaimed
                        -- during a GC if there are no other references to them
                        setmetatable(self.var.secondarycache, {__mode = "v"})
                end
                -- nil return makes stub do object copy
        end


        -- Removes an empty table from the cache and returns it
        -- or generates a new table if none available
        function lib:Acquire()
                if self.var.disabled then return {} end
                if table.getn(self.var.cache) > 0 then
                        self:IncDec("totn", -1)
                        self:IncDec("numr", 1)
                        local t = self.var.cache[1]
                        table.remove(self.var.cache, 1)
                        return t
                elseif self:ItemsInSecondaryCache() then
                        self:IncDec("totn", -1)
                        self:IncDec("numr", 1)
                        for i in pairs(self.var.secondarycache) do
                                local t = self.var.secondarycache[i]
                                table.remove(self.var.secondarycache, i)
                                return t
                        end
                else
                        self:IncDec("numn", 1)
                        return {}
                end
        end


        -- Returns a table to the cache
        -- All tables referenced inside the passed table will be reclaimed also
        -- If depth is passed any tables referenced in t will also be reclaimed ***USE THIS CAREFULLY***
        function lib:Reclaim(t, depth)
                if type(t) ~= "table" or self.var.disabled then return end

                if not self:ItemsInSecondaryCache() then self.var.totn = table.getn(self.var.cache) end

                if depth and depth > 0 then
                        for i in pairs(t) do
                                if type(t[i]) == "table" then self:Reclaim(t[i], depth - 1) end
                        end
                end
                self:Erase(t)
                if self.var.maxcache and table.getn(self.var.cache) >= self.var.maxcache then
                        table.insert(self.var.secondarycache, t)
                else
                        table.insert(self.var.cache, t)
                end
                self:IncDec("totn", 1)
                self.var.maxn = math.max(self.var.maxn or 0, self.var.totn)
        end


        -- Erases the table passed, nothing more nothing less :)
        -- Tables referenced inside the passed table are NOT erased
        function lib:Erase(t)
                if type(t) ~= "table" then return end
                if self.var.disabled then return {} end
                local mem = gcinfo()
                for i in pairs(t) do
                        t[i] = nil
                end
                t.reset = 1
                t.reset = nil
                table.setn(t, 0)
                self:IncDec("memf", math.abs(gcinfo() - mem))
                self:IncDec("nume", 1)
                return t
        end


        function lib:IncDec(variable, diff)
                self.var[variable] = (self.var[variable] or 0) + diff
        end


        function lib:ItemsInSecondaryCache()
                for i in pairs(self.var.secondarycache) do return true end
        end


        function lib:GetSecondaryCacheSize()
                local n = 0
                for i in pairs(self.var.secondarycache) do n = n + 1 end
                return n
        end


        -- Prints out statistics on table recycling
        -- /script CompostLib:GetInstance("compost-1"):Stats()
        function lib:Stats()
                if self.var.disabled then ChatFrame1:AddMessage("CompostLib is disabled!")
                else ChatFrame1:AddMessage(
                        string.format(
                                "|cff00ff00New: %d|r | |cffffff00Recycled: %d|r | |cff00ffffSaved: %d|r | |cffff0000Secondary: %d|r | |cffff8800Max %d|r | |cff888888Erases: %d|r | |cffff00ffMem Freed: %d KiB",
                                self.var.numn or 0, self.var.numr or 0, table.getn(self.var.cache), self:GetSecondaryCacheSize(), self.var.maxn or 0,
                                (self.var.nume or 0) - (self.var.numr or 0) - table.getn(self.var.cache) - self:GetSecondaryCacheSize(),
                                (self.var.memf or 0) + 32/1024*(self.var.numr or 0)))
                end
        end


        --------------------------------
        --      Load this bitch!      --
        --------------------------------
        libobj:Register(lib)
end