------------------------------------------------------------------------ -- zero-compression zip writer from nullzip.lua ver 0.9.5, by KHMan ------------------------------------------------------------------------ -- Selected Notes: -- * Note: these notes are for the 4-bit per round lookup xor... -- * the output is limited to primitive header blocks (no zip64 records) -- * CRC is disappointingly slow, is there any other way to do it? -- * writes out data at about 100K/sec on an Athlon 2500+ -- (100 calls to nullzip_test() 4.5K sxw writing test in 10 sec) ------------------------------------------------------------------------ ------------------------------------------------------------------------ -- Compute bitwise xor using a 4 bit-at-a-time table lookup. Is there -- any faster xor-calculating algorithm on vanilla Lua? Or a CRC -- algorithm that doesn't use (or use fewer) xor (or bitwise) ops? -- * strings and handling lookups in byte chunks is not faster -- * a 64K lookup table is 40% faster -- * a 64K string byte-lookup is 50% faster -- * building 64K tables is slow, but perhaps can load a binary file... ------------------------------------------------------------------------ CRCLib = {} local xor_lookup = {} local idx = 0 for x = 0, 15 do for y = 0, 15 do local bz = 1 local xx = x; local yy = y xor_lookup[idx] = 0 for z = 1, 4 do if math.mod(xx, 2) ~= math.mod(yy, 2) then xor_lookup[idx] = xor_lookup[idx] + bz end xx = math.floor(xx / 2); yy = math.floor(yy / 2) bz = bz * 2 end idx = idx + 1 end end local function xor(x, y, size) local z = 0 local nz = 1 size = size or 8 for n = 1, size do local nx = math.mod(x, 16); x = (x - nx) / 16 local ny = math.mod(y, 16); y = (y - ny) / 16 z = xor_lookup[nx * 16 + ny] * nz + z nz = nz * 16 end return z end ------------------------------------------------------------------------ -- Straight adaptation of CRC32 code from RFC 1952 (from ISO 3309/ITU-T -- V.42). The crc should be initialized to zero. Pre- and post- -- conditioning (one's complement) is performed within -- nullzip_update_crc so it shouldn't be done by the caller. ------------------------------------------------------------------------ local nullzip_crc_table -- table of CRCs of all 8-bit messages ------------------------------------------------------------------------ -- nullzip_make_crc_table: make the table for a fast CRC. -- Can be replaced by the precomputed table instead. -- Usage: crc = nullzip_crc(data) ------------------------------------------------------------------------ local function nullzip_make_crc_table() local CONST1 = tonumber("EDB88320", 16) nullzip_crc_table = {} for n = 0, 255 do local c = n for k = 0, 7 do if math.mod(c, 2) == 1 then -- c = 0xedb88320L ^ (c >> 1); c = xor(CONST1, math.floor(c / 2)) else c = math.floor(c / 2) end end nullzip_crc_table[n] = c end end ------------------------------------------------------------------------ -- nullzip_update_crc: update a running crc with a specified buffer -- Usage: crc = nullzip_update_crc(original_crc, data) ------------------------------------------------------------------------ local function nullzip_update_crc(original_crc, data) local CONST1 = tonumber("FFFFFFFF", 16) local c = xor(original_crc, CONST1) if not nullzip_crc_table then nullzip_make_crc_table() end for n = 1, string.len(data) do -- c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); c = xor(nullzip_crc_table[xor(c, string.byte(data, n), 2)], math.floor(c / 256)) end return xor(c, CONST1) end function CRCLib.crc(data) return nullzip_update_crc(0, data) end print(string.format("%x", CRCLib.crc("Guild Test"))) print(string.format("%x", CRCLib.crc("Guild Test")))