#define PERL_NO_GET_CONTEXT #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #ifndef NVTYPE # if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) # define NVTYPE long double # else # define NVTYPE double # endif typedef NVTYPE NV; #endif #ifndef newSVuv # define newSVuv(uv) (uv > ((~((UV)0))>>1) ? newSVnv((NV)uv) : newSViv((IV)uv)) #endif #ifndef aTHX_ # define aTHX_ #endif #ifndef SvGETMAGIC # define SvGETMAGIC(x) STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END #endif #define TABSIZE 256 static UV reflect(UV in, int width) { int i; UV out = 0; for (i = width; in && i; i--, in >>= 1) out = (out << 1) | (in & 1); return out << i; } MODULE = Digest::CRC PACKAGE = Digest::CRC PROTOTYPES: ENABLE UV _reflect(in, width) UV in IV width CODE: RETVAL = reflect(in, width); OUTPUT: RETVAL SV * _tabinit(width, poly, ref) IV width UV poly IV ref PREINIT: UV *tab; UV mask, t, r, i; int j, wm8; CODE: if (ref) poly = reflect(poly, width); mask = ((UV)1)<<(width-1); mask = mask + (mask-1); i = TABSIZE*sizeof(UV); RETVAL = newSV(i); SvPOK_only(RETVAL); SvCUR_set(RETVAL, i); tab = (UV *) SvPVX(RETVAL); if (!ref) { t = ((UV)1) << (width - 1); wm8 = width - 8; } for (i = 0; i < TABSIZE; i++) { if (ref) { r = i; for (j = 0; j < 8; j++) if (r & 1) r = (r >> 1) ^ poly; else r >>= 1; } else { r = i << (width - 8); for (j = 0; j < 8; j++) if (r & t) r = (r << 1) ^ poly; else r <<= 1; } tab[i] = r & mask; } OUTPUT: RETVAL SV * _crc(message, width, init, xorout, refin, refout, cont, table) SV *message IV width UV init UV xorout IV refin IV refout IV cont SV *table PREINIT: UV crc, mask, *tab; STRLEN len; const char *msg, *end; CODE: SvGETMAGIC(message); msg = SvPV(message, len); end = msg + len; mask = ((UV)1)<<(width-1); mask = mask + (mask-1); tab = (UV *) SvPVX(table); crc = refin ? reflect(init, width) : init; if (cont) { crc = (init ^ xorout) & mask; if (refout ^ refin) crc = reflect(crc, width); } if (refin) { while (msg < end) crc = (crc >> 8) ^ tab[(crc ^ *msg++) & 0xFF]; } else { int wm8 = width - 8; while (msg < end) crc = (crc << 8) ^ tab[((crc >> wm8) ^ *msg++) & 0xFF]; } if (refout ^ refin) crc = reflect(crc, width); crc = (crc ^ xorout) & mask; RETVAL = newSVuv(crc); OUTPUT: RETVAL SV * _crc64(message, crc=0) SV * message UV crc PREINIT: unsigned long long poly64rev = 0xd800000000000000ULL; unsigned long long part; int i, j; static int init = 0; static unsigned long long CRCTable[256]; STRLEN len; const char *msg, *end; CODE: SvGETMAGIC(message); msg = SvPV(message, len); end = msg + len; if (!init) { init = 1; for (i = 0; i < 256; i++) { part = i; for (j = 0; j < 8; j++) { if (part & 1) part = (part >> 1) ^ poly64rev; else part >>= 1; } CRCTable[i] = part; } } while (msg < end) crc = CRCTable[(crc ^ *msg++) & 0xff] ^ (crc >> 8); RETVAL = newSVuv(crc); OUTPUT: RETVAL