AuctioneerSuite/Auc-Advanced/Support/LibGroupStore.lua
2026-04-13 17:48:13 -04:00

194 lines
5.9 KiB
Lua

--[[
-- LibGroupStorage.lua
-- Group data storage
-- A storage array for variable sized groups of data
-- Written by Ken Allan <ken@norganna.org>
-- This code is hereby released into the Public Domain without warranty.
--
-- Basic Usage:
-- local GroupStore = LibStub("LibGroupStore")
-- local storage = GroupStore()
--
-- local id = storage:InsertGroup(122, 233, 344, 411)
-- local a, b, c, d = storage:GetGroup(id)
--
-- Advanced Usage:
-- storage:Clear() -- Remove all groups from the storage
-- storage:RemoveGroup(7) -- Removes group 7 from the array, shifting later groups down.
-- base = storage:GetBase() -- Returns the base array (so you can save it, etc)
-- storage = GroupStore(base) -- Resurrect a saved storage array
--
-- Shortcuts:
-- storage(nil, 1,2,3) = storage:InsertGroup(1,2,3)
-- storage - 3 = storage:RemoveGroup(3)
-- storage(1) = storage:GetGroup(1)
-- #storage = storage:GetNumGroups()
--]]
local LIBRARY_VERSION_MAJOR = "LibGroupStore"
local LIBRARY_VERSION_MINOR = 1
--[[-----------------------------------------------------------------
LibStub is a simple versioning stub meant for use in Libraries.
See <http://www.wowwiki.com/LibStub> for more info.
LibStub is hereby placed in the Public Domain.
Credits:
Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
--]]-----------------------------------------------------------------
do
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2
local LibStub = _G[LIBSTUB_MAJOR]
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
function LibStub:NewLibrary(major, minor)
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
local oldminor = self.minors[major]
if oldminor and oldminor >= minor then return nil end
self.minors[major], self.libs[major] = minor, self.libs[major] or {}
return self.libs[major], oldminor
end
function LibStub:GetLibrary(major, silent)
if not self.libs[major] and not silent then
error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
end
return self.libs[major], self.minors[major]
end
function LibStub:IterateLibraries() return pairs(self.libs) end
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end
end
--[End of LibStub]---------------------------------------------------
local lib = LibStub:NewLibrary(LIBRARY_VERSION_MAJOR, LIBRARY_VERSION_MINOR)
if not lib then return end
local kit={}
lib.data = {}
local function findFunction(self, index)
return kit[index]
end
-- Create a new storage instance
function lib:New(base)
-- Init it's variables
if base then
assert(base.index or #base == 0, "Cannot specify a non-group base")
else
base = {}
base.index = {}
end
local proxy = newproxy(true)
local mt = getmetatable(proxy)
mt.__len = kit.GetNumGroups
mt.__sub = kit.RemoveGroup
mt.__call = kit.GetGroup
mt.__index = findFunction
lib.data[proxy] = base
-- Return the data
return proxy
end
setmetatable(lib, { __call = lib.New })
-- Insert the items on the stack as a group into the storage
function kit:InsertGroup(...)
local base = lib.data[self]
local pos = #base
local len = select('#', ...)
table.insert(base.index, pos)
table.insert(base.index, len)
for i = 1, len do
base[pos+i] = select(i, ...)
end
-- Return the group id
return (#base.index / 2)
end
-- Remove specified group from the storage, shifting all higher groups down
function kit:RemoveGroup(group)
local base = lib.data[self]
local max = #base.index / 2
group = tonumber(group)
assert(group, "Must specify a group number")
assert(group > 0, "Attempt to get group range <= 0")
assert(group <= max, "Attempt to get group range > max")
local index = group * 2 - 1
local pos = table.remove(base.index, index)
local len = table.remove(base.index, index)
for i = 1, len do
table.remove(base, pos+1)
end
for i = group, max-1 do
index = i * 2 - 1
base.index[index] = base.index[index]-len
end
return self
end
-- Fetch the start, end and length of a specified group (for direct access)
function kit:GetGroupRange(group)
local base = lib.data[self]
local max = #base.index / 2
group = tonumber(group)
assert(group, "Must specify a group number")
assert(group > 0, "Attempt to get group range <= 0")
assert(group <= max, "Attempt to get group range > max")
local index = group * 2 - 1
local pos = base.index[index]
local len = base.index[index]
-- Return start, end, length
return pos+1, pos+len, len
end
-- Return the specified group on the stack
function kit:GetGroup(group, ...)
if not group or group <= 0 then return kit.InsertGroup(self, ...) end
local base = lib.data[self]
local max = #base.index / 2
group = tonumber(group)
assert(group, "Must specify a group number")
assert(group > 0, "Attempt to get group range <= 0")
assert(group <= max, "Attempt to get group range > max")
local index = group * 2 - 1
local pos = base.index[index]
local len = base.index[index+1]
return unpack(base, pos+1, pos+len)
end
-- Return the number of groups
function kit:GetNumGroups()
local base = lib.data[self]
return #base.index / 2
end
-- Return a reference to the base object (for saves)
function kit:GetBase()
return lib.data[self]
end
-- Clear all groups from the entire storage array
function kit:Clear()
local base = lib.data[self]
while #base.index > 0 do table.remove(base.index) end
while #base > 0 do table.remove(base) end
return self
end