模組:Crc32lua
外观
CRC32的纯Lua实现。
补充:Scribunto提供的标准库中,提供了mw.hash.hashValue()
可以用于生成散列值,其实际上是调用PHP的hash()方法,其中PHP的hash支持算法中,包括三个crc32,分别是crc32、crc32b、crc32c;本lua模块实现的对应就是前面的crc32b,其输出值是前述调用输出字节原值的十进制值(即mw.hash.hashValue()
字节原值的十六进制值)。所以如有性能需要且入参为字符串的话,可以考虑用Scribunto提供的基础库实现代替(标准库提供的只支持字符串入参,不支持字节串入参,尽管PHP的实现是支持的)。
--[[
LUA MODULE
digest.crc32 - CRC-32 checksum implemented entirely in Lua.
SYNOPSIS
local CRC = require 'digest.crc32lua'
print(CRC.crc32 'test') --> 0xD87F7E0C or -662733300
assert(CRC.crc32('st', CRC.crc32('te')) == CRC.crc32 'test')
DESCRIPTION
This can be used to compute CRC-32 checksums on strings.
This is similar to [1-2].
API
Note: in the functions below, checksums are 32-bit integers stored in
numbers. The number format currently depends on the bit
implementation--see DESIGN NOTES below.
CRC.crc32_byte(byte [, crc]) --> rcrc
Returns CRC-32 checksum `rcrc` of byte `byte` (number 0..255) appended to
a string with CRC-32 checksum `crc`. `crc` defaults to 0 (empty string)
if omitted.
CRC.crc32_string(s, crc) --> bcrc
Returns CRC-32 checksum `rcrc` of string `s` appended to
a string with CRC-32 checksum `crc`. `crc` defaults to 0 (empty string)
if omitted.
CRC.crc32(o, crc) --> bcrc
This invokes `crc32_byte` if `o` is a byte or `crc32_string` if `o`
is a string.
CRC.bit
This contains the underlying bit library used by the module. It
should be considered a read-only copy.
DESIGN NOTES
Currently, this module exposes the underlying bit array implementation in CRC
checksums returned. In BitOp, bit arrays are 32-bit signed integer numbers
(may be negative). In Lua 5.2 'bit32' and 'bit.numberlua', bit arrays are
32-bit unsigned integer numbers (non-negative). This is subject to change
in the future but is currently done due to (unconfirmed) performance
implications.
On platforms with 64-bit numbers, one way to normalize CRC
checksums to be unsigned is to do `crcvalue % 2^32`,
The name of this module is inspired by Perl `Digest::CRC*`.
DEPENDENCIES
Requires one of the following bit libraries:
BitOp "bit" -- bitop.luajit.org -- This is included in LuaJIT and also available
for Lua 5.1/5.2. This provides the fastest performance in LuaJIT.
Lua 5.2 "bit32" -- www.lua.org/manual/5.2 -- This is provided in Lua 5.2
and is preferred in 5.2 (unless "bit" also happens to be installed).
"bit.numberlua" (>=000.003) -- https://github.com/davidm/lua-bit-numberlua
This is slowest and used as a last resort.
It is only a few times slower than "bit32" though.
DOWNLOAD/INSTALLATION
If using LuaRocks:
luarocks install lua-digest-crc32lua
Otherwise, download <https://github.com/davidm/lua-digest-crc32lua/zipball/master>.
Alternately, if using git:
git clone git://github.com/davidm/lua-digest-crc32lua.git
cd lua-digest-crc32lua
Optionally unpack:
./util.mk
or unpack and install in LuaRocks:
./util.mk install
REFERENCES
[1] http://www.axlradius.com/freestuff/CRC32.java
[2] http://www.gamedev.net/reference/articles/article1941.asp
[3] http://java.sun.com/j2se/1.5.0/docs/api/java/util/zip/CRC32.html
[4] http://www.dsource.org/projects/tango/docs/current/tango.io.digest.Crc32.html
[5] http://pydoc.org/1.5.2/zlib.html#-crc32
[6] http://www.python.org/doc/2.5.2/lib/module-binascii.html
LICENSE
(c) 2008-2011 David Manura. Licensed under the same terms as Lua (MIT).
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
(end license)
--]]
local M = {_TYPE='module', _NAME='digest.crc32', _VERSION='0.3.20111128'}
local type = type
local require = require
local setmetatable = setmetatable
--[[
Requires the first module listed that exists, else raises like `require`.
If a non-string is encountered, it is returned.
Second return value is module name loaded (or '').
--]]
local function requireany(...)
local errs = {}
for _,name in ipairs{...} do
if type(name) ~= 'string' then return name, '' end
local ok, mod = pcall(require, name)
if ok then return mod, name end
errs[#errs+1] = mod
end
error(table.concat(errs, '\n'), 2)
end
local bit, name_ = requireany('bit32', 'bit', 'bit.numberlua')
local bxor = bit.bxor
local bnot = bit.bnot
local band = bit.band
local rshift = bit.rshift
-- CRC-32-IEEE 802.3 (V.42)
local POLY = 0xEDB88320
-- Memoize function pattern (like http://lua-users.org/wiki/FuncTables ).
local function memoize(f)
local mt = {}
local t = setmetatable({}, mt)
function mt:__index(k)
local v = f(k); t[k] = v
return v
end
return t
end
-- CRC table.
local crc_table = memoize(function(i)
local crc = i
for _=1,8 do
local b = band(crc, 1)
crc = rshift(crc, 1)
if b == 1 then crc = bxor(crc, POLY) end
end
return crc
end)
function M.crc32_byte(byte, crc)
crc = bnot(crc or 0)
local v1 = rshift(crc, 8)
local v2 = crc_table[bxor(crc % 256, byte)]
return bnot(bxor(v1, v2))
end
local M_crc32_byte = M.crc32_byte
function M.crc32_string(s, crc)
crc = crc or 0
for i=1,#s do
crc = M_crc32_byte(s:byte(i), crc)
end
return crc
end
local M_crc32_string = M.crc32_string
function M.crc32(s, crc)
if type(s) == 'string' then
return M_crc32_string(s, crc)
else
return M_crc32_byte(s, crc)
end
end
M.bit = bit -- bit library used
return M