-- CRC object
-- Cyclic Redundancy Check
----------------------------------------------
-- Provided by Robert Ramsden (05 November 2002)
-- rob@digitaljunction.co.za
----------------------------------------------
-- Usage:
-- Instantiate a copy of this object.
-- Use the mSetup method to set all the default object variables.
-- Should you require a different seed other than the CRC-32 standard,
-- seed the algorithm using the mSeedCRC method.
--
-- To add data to the crc algorithim use mAppendToCRC and supply
-- the sting to append to the crc.
-- Once completed request mReturnCRC to return the value
-- of the calculated CRC.
-- The reason for breaking the algorithm into an append
-- and a return, is that the data is significantly changed
-- on output.
-- This method therefore allows data to be read in chuncks
-- without affecting the outcome of the CRC.
----------------------------------------------
-- Globals
----------------------------------------------
-- Properties
property pCRCTable
property pCrc
property pSeedCRC
property pBitShiftList
property pUpperMasksList
----------------------------------------------
on new(me)
-- return the object with a new memory reference
return me
end new
----------------------------------------------
on mInit(me)
-- return the object with the same memory reference
return me
end mInit
----------------------------------------------
on mSetup me, lSeed
-- Setup the CRC object.
-- Create lookup tables for BitShifting and BitMasks
-- Seed the CRC algorithm with the supplied seed parameter.
-- Initiate the CRC lookup table
pBitShiftList = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, -2147483648]
pUpperMasksList = [2147483647, 1073741823, 536870911, 268435455, 134217727, 67108863, 33554431, 16777215, 8388607, 4194303, 2097151, 1048575, 524287, 262143, 131071, 65535, 32767, 16383, 8191, 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0]
pSeedCRC = lSeed
mSeedCRC me, pSeedCRC
mInitCRCTable me
end mSetup
----------------------------------------------
on mSeedCRC me, lSeed
-- Seed the CRC with a seed value of use the
-- default hex value : 0xffffffff
-- integer value : -1 or 4294967295
if voidP(pSeedCRC) then
pCrc = -1 -- 0xffffffff
end if
end mSeedCRC
----------------------------------------------
on mReturnCRC(me)
-- Returns the current CRC
-- Resets the CRC Seed to the initial value for next CRC opperation.
lCrc = bitXOR(pCrc, -1)
mSeedCRC me, pSeedCRC
return lCrc
end mReturnCRC
----------------------------------------------
on mAppendToCRC me, lString
--// This function uses the crc32_table lookup table
--// to generate a CRC for csData
--int CCRCfileDlg::Get_CRC(CString &csData, DWORD dwSize)
--{
-- // Be sure to use unsigned variables,
-- // because negative values introduce high bits
-- // where zero bits are required.
-- ULONG crc(0xffffffff);
-- int len;
-- unsigned char* buffer;
--
-- len = dwSize;
-- // Save the text in the buffer.
-- buffer = (unsigned char*)(LPCTSTR)csData;
-- // Perform the algorithm on each character
-- // in the string, using the lookup table values.
-- while(len--)
-- crc = (crc >> 8) ^ crc32_table[(crc & 0xFF) ^ *buffer++];
-- // Exclusive OR the result with the beginning value.
-- return crc^0xffffffff;
--}
repeat with i = 1 to lString.length
pCrc = bitXOR(bitShift(me, pCrc, 8), pCRCTable[bitXOR(bitAND(pCrc, 255), charToNum(lString.char[i])) + 1])
end repeat
end mAppendToCRC
----------------------------------------------
on mInitCRCTable me
-- // Call this function only once to initialize the CRC table.
--void CCRCfileDlg::Init_CRC32_Table()
--{// Called by OnInitDialog()
--
-- // This is the official polynomial used by CRC-32
-- // in PKZip, WinZip and Ethernet.
-- ULONG ulPolynomial = 0x04c11db7;
--
-- // 256 values representing ASCII character codes.
-- for(int i = 0; i <= 0xFF; i++)
-- {
-- crc32_table[i]=Reflect(i, 8) << 24;
-- for (int j = 0; j < 8; j++)
-- crc32_table[i] = (crc32_table[i] << 1) ^ (crc32_table[i] & (1 << 31) ? ulPolynomial : 0);
-- crc32_table[i] = Reflect(crc32_table[i], 32);
-- }
--}
lPolynomial = 79764919 -- 0x04c11db7
pCRCTable = []
repeat with i = 1 to 256 -- for(int i = 0; i <= 0xFF; i++)
pCRCTable[i] = bitShift(me, mReflectInt(me, (i - 1), 8), -24) -- crc32_table[i] = Reflect(i, 8) << 24
repeat with j = 0 to 7 -- for (int j = 0; j < 8; j++)
if bitAND(pCRCTable[i], bitShift(me, 1, -31)) then -- if (crc32_table[i] & (1 << 31))
lTmp = lPolynomial -- tmp = ulPolynomial;
else
lTmp = 0 -- tmp = 0
end if
pCRCTable[i] = bitXOR(bitShift(me, pCRCTable[i], -1), lTmp) -- crc32_table[i] = (crc32_table[i] << 1) ^ tmp
end repeat
pCRCTable[i] = mReflectInt(me, pCRCTable[i], 32) -- crc32_table[i] = Reflect(crc32_table[i], 32)
end repeat
end mInitCRCTable
----------------------------------------------
on mReflectInt(me, lValue, lLen)
-- Reflection is a requirement for the official CRC-32 standard.
-- You can create CRCs without it, but they won't conform to the standard.
-- Base reflection lingo supplied by Robert Tweed
-- Reflect a byte
--255 = 1 1 1 1 1 1 1 1 => 1 1 1 1 1 1 1 1 = 255
--254 = 1 1 1 1 1 1 1 0 => 0 1 1 1 1 1 1 1 = 127
--126 = 0 1 1 1 1 1 1 0 => 0 1 1 1 1 1 1 0 = 126
--125 = 0 1 1 1 1 1 0 1 => 1 0 1 1 1 1 1 0 = 190
-- 4 = 0 0 0 0 0 1 0 0 => 0 0 1 0 0 0 0 0 = 32
lTmp = []
pBitShiftList = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, -2147483648]
repeat with i = 1 to lLen
lTmp[i] = bitAnd(lValue , pBitShiftList[i])
end repeat
lReflectValue = 0
lHLen = lLen / 2
repeat with i = 1 to lHLen
lReflectValue = integer(lReflectValue + lTmp[i] * pBitShiftList[lLen - ((i - 1) * 2)])
end repeat
repeat with i = (lHLen + 1) to lLen
lReflectValue = integer(lReflectValue + lTmp[i] / pBitShiftList[((i - lHLen) * 2)])
end repeat
return lReflectValue
end mReflectInt
----------------------------------------------
on bitShift(me, argVal, argAmount)
-- positive = right
-- Base bitShift lingo supplied by Jonas Beckeman
if (argAmount > 0) then
if (argVal > 0) then argVal = argVal / pBitShiftList[argAmount+1]
else --means highest bit is set - remove it!
argVal = bitAnd(argVal, 2147483647)
argVal = argVal / pBitShiftList[argAmount+1]
argVal = argVal + pBitShiftList[32-argAmount]
end if
else
--remove upper bits
argVal = bitAnd(pUpperMasksList[-argAmount], argVal)
--then multiply
argVal = argVal * pBitShiftList[-argAmount+1]
end if
return argVal
end bitShift
----------------------------------------------
on mDispose me
-- Disposal function
pCRCTable = void
pCrc = void
pSeedCRC = void
pBitShiftList = void
pUpperMasksList = void
end mDispose
----------------------------------------------