home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
crcksrc.zip
/
crc24.cpp
next >
Wrap
Text File
|
1995-02-15
|
6KB
|
192 lines
/*
$Header: e:/work2/x/jacquard/src/control/RCS/crc24.cpp 1.2 93/06/23 05:09:50 m3m rel $
**
**
** Copyright M CUBED 1993, ALL RIGHTS DESERVED
** author : Michael McDaniel
**
** This work is derived in part from public domain code, and is contributed
** back to the public domain
**
** ===>>> please keep my credits when you add your own <<<===
**
**
** purpose : calculate 24bit cyclic redundancy check
**
** see also : crc24.h, pgp21, armor.c
**
** reference: 1) "C Programmer's Guide to Serial Communications",
** by Joe Campbell
** These CRC functions are derived from code in chapter 19
** Generalized to any CRC width by Philip Zimmermann; 24 bit
** width used here.
**
** suggested enhancement: read more than one character at a time. This was
** originally linked into a commercial product strictly for an integrity
** check of the executable so as seldom as it was run, reading one character
** at a time was not an issue. Now that this is harnessed with crck.cpp and
** used to check multiple files, fixing the one-char-etc. bottleneck would
** probably be worth it.
*/
# define __CRC24_CPP_
static char rcsid[] = "$Header: e:/work2/x/jacquard/src/control/RCS/crc24.cpp 1.2 93/06/23 05:09:50 m3m rel $";
# include <io.h>
# include <fstream.h>
# include "crc24.h"
const CRCBITS = 24;
const crcword CRCINIT = 0xB704CEUL; // Init value for CRC accumulator
const crcword PRZCRC = 0x864cfbUL; // PRZ's 24-bit CRC generator polynomial
const crcword CRCHIBIT = 1UL << (CRCBITS-1UL); // 0x8000 if CRCBITS is 16
const crcword CRCSHIFTS = CRCBITS - 8 ;
typedef unsigned char byte;
crcword crctable[256]; // Table for speeding up CRC's
inline crcword maskcrc(crcword crc)
{
return (crc & 0xffffffL); // if CRCBITS is 24
}
crc24::crc24( char * file_name )
{ // member vars
accum = CRCINIT;
pvalid = 1;
// local vars
int data = 0;
fstream executable;
if( access(file_name, 04) == 0 )
{
executable.open( file_name, ios::in | ios::binary );
}
else
pvalid = 0;
if( pvalid && !executable.bad() )
{
mk_crctbl(PRZCRC);
while( data != EOF )
{
data = executable.get();
accum = crcupdate( (unsigned char)data, accum);
}
}
executable.close();
}; // end crc24
crc24::~crc24()
{
accum = 0;
}; // end ~crc24()
unsigned long crc24::value()
{
return accum;
};
// m3m; the following are verbatim out of armor.c in pgp21/src
// crc24:: added
/* Notes on making a good 24-bit CRC--
The primitive irreducible polynomial of degree 23 over GF(2),
040435651 (octal), comes from Appendix C of "Error Correcting Codes,
2nd edition" by Peterson and Weldon, page 490. This polynomial was
chosen for its uniform density of ones and zeros, which has better
error detection properties than polynomials with a minimal number of
nonzero terms. Multiplying this primitive degree-23 polynomial by
the polynomial x+1 yields the additional property of detecting any
odd number of bits in error, which means it adds parity. This
approach was recommended by Neal Glover.
To multiply the polynomial 040435651 by x+1, shift it left 1 bit and
bitwise add (xor) the unshifted version back in. Dropping the unused
upper bit (bit 24) produces a CRC-24 generator bitmask of 041446373
octal, or 0x864cfb hex.
You can detect spurious leading zeros or framing errors in the
message by initializing the CRC accumulator to some agreed-upon
nonzero "random-like" value, but this is a bit nonstandard.
*/
crcword crc24::crchware(byte ch, crcword poly, crcword accum)
//
// crchware simulates CRC hardware circuit. Generates true CRC
// directly, without requiring extra NULL bytes to be appended
// to the message.
// Returns new updated CRC accumulator.
//
{ int i;
crcword data;
data = ch;
data <<= CRCSHIFTS; /* shift data to line up with MSB of accum */
i = 8; /* counts 8 bits of data */
do
{ /* if MSB of (data XOR accum) is TRUE, shift and subtract poly */
if ((data ^ accum) & CRCHIBIT)
accum = (accum<<1) ^ poly;
else
accum <<= 1;
data <<= 1;
} while (--i); /* counts 8 bits of data */
return (maskcrc(accum));
} /* crchware */
void crc24::mk_crctbl(crcword poly)
//
// mk_crctbl derives a CRC lookup table from the CRC polynomial.
// The table is used later by crcupdate function given below.
// mk_crctbl only needs to be called once at the dawn of time.
//
{ int i;
for (i=0; i<256; i++)
crctable[i] = crchware((byte) i, poly, 0);
} /* mk_crctbl */
crcword crc24::crcupdate(byte data, register crcword accum)
//
// crcupdate calculates a CRC using the fast table-lookup method.
// Returns new updated CRC accumulator.
//
{ byte combined_value;
/* XOR the MSByte of the accum with the data byte */
combined_value = (accum >> CRCSHIFTS) ^ data;
accum = (accum << 8) ^ crctable[combined_value];
return (maskcrc(accum));
} /* crcupdate */
// end $Source: e:/work2/x/jacquard/src/control/RCS/crc24.cpp $