Module:Hash

From The Perfect Tower II
Jump to navigation Jump to search

Documentation for this module may be created at Module:Hash/doc

--[[
Simple module for hashing a string.
Generally you won't #invoke this directly, but use templates that do.
]]

-- Disallow global variable read/writes. Copied from Wikipedia's Module:No globals.
local mt = getmetatable(_G) or {}
function mt.__index (t, k)
	if k ~= 'arg' then
		error('Tried to read nil global ' .. tostring(k), 2)
	end
	return nil
end
function mt.__newindex(t, k, v)
	if k ~= 'arg' then
		error('Tried to write global ' .. tostring(k), 2)
	end
	rawset(t, k, v)
end
setmetatable(_G, mt)

local p = {}

local function BitXOR(a,b)
    local p,c=1,0
    while a>0 and b>0 do
        local ra,rb=a%2,b%2
        if ra~=rb then c=c+p end
        a,b,p=(a-ra)/2,(b-rb)/2,p*2
    end
    if a<b then a=b end
    while a>0 do
        local ra=a%2
        if ra>0 then c=c+p end
        a,p=(a-ra)/2,p*2
    end
    return c
end

-- Returns a (stringified) CRC32 of the data
function p.crc_internal(str)
	if not str then
		return "nil"
	end
	local byte = string.byte
	local floor = math.floor
	local crc = 0xFFFFFFFF
	for i = 1, #str do
        local b = byte(str, i)
        crc = BitXOR(crc, b)
        for j = 1, 8 do
            local mask = 0
            if crc % 2 == 1 then
            	crc = BitXOR(floor(crc / 2), 0xEDB88320)
            else
            	crc = floor(crc / 2)
            end
        end
    end
	return string.format("%x", BitXOR(crc, 0xFFFFFFFF))
end

function p.crc(frame)
	return p.crc_internal(frame.args[1])
end

return p