Blob Blame History Raw
#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