batteries/unique_mapping.lua

63 lines
1.4 KiB
Lua

--[[
unique mapping
generate a mapping from unique values to plain numbers
useful for arbitrarily ordering things that don't have
a natural ordering in lua (eg textures for batching)
]]
local unique_mapping = {}
unique_mapping._mt = {
__index = unique_mapping,
__mode = "kv", --weak refs
}
--(used as storage for non-weak data)
local _MAP_VARS = setmetatable({}, {
__mode = "k" --only keys are weak
})
--create a new unique mapping
function unique_mapping:new()
local r = setmetatable({}, self._mt)
--set up the actual vars
_MAP_VARS[r] = {
current_index = 0,
}
return r
end
--private;
--get the next index for this mapping
function unique_mapping:_increment()
local vars = _MAP_VARS[self]
vars.current_index = vars.current_index + 1
return vars.current_index
end
--get or build a mapping for a passed value
function unique_mapping:map(value)
local val = self[value]
if val then
return val
end
local i = self:_increment()
self[value] = i
return i
end
--get a function representing an a < b comparision that can be used
--with table.sort and friends, like `table.sort(values, mapping:compare())`
function unique_mapping:compare()
-- memoised so it doesn't generate garbage, but also doesn't
-- allocate until it's actually used
if not self._compare then
self._compare = function(a, b)
return self:map(a) < self:map(b)
end
end
return self._compare
end
return unique_mapping