/* ========================================================================= //
# vi:  set ts=4:
# vim: set ts=4:
#?
#? NAME
#?      crc.js
#?
#? SYNOPSIS
#?      <SCRIPT language="JavaScript1.3" type="text/javascript" src="EnDe.js"></SCRIPT>
#?      <SCRIPT language="JavaScript1.3" type="text/javascript" src="crc.js"></SCRIPT>
#?
#? DESCRIPTION
#?      Functions for CRC checksums.
#?
#?      Defines  EnDe.CRC  object.
# // ToDo: more to be done ...
#?
#? SEE ALSO
#?      EnDeOpts.xml
#?
#? HACKER's INFO
#?      // ToDo: // some INFOs found in EnDe.man.txt
#?
#? VERSION
#?      @(#) crc.js 3.4 11/04/09 21:33:51
#?
#? AUTHOR
#?      12-oct-08 Achim Hoffmann, mailto: EnDe (at) my (dash) stp (dot) net
#?
 * ========================================================================= */

// ========================================================================= //
// Encoding, Decoding functions                                              //
// ========================================================================= //


if ((typeof EnDe)==='undefined' ) { EnDe = new function() {}; } // contribution to runtime raise condition and some stupid browsers

EnDe.CRC     = new function() {
  this.SID      = '3.4';
  this.sid      = function() { return(EnDe.sid() + '.CRC'); };
  this.dbx      = function(src,nl) { return EnDe.dbx(src,nl); };

	// ===================================================================== //
	// global constants                                                      //
	// ===================================================================== //

	// ===================================================================== //
	// global CRC functions                                                  //
	// ===================================================================== //

  this.reflectByte  = function(src) {
  //#? reflect one byte
// ToDO. NOT YET TESTED
	var bux=0;
	var bbb = 0x01;
	for (var j=0x80; j; j>>=1) {
		if (src & bbb) { bux |= j; }
		bbb <<= 1;
	}
	return (bux);
  };

  this.reflect  = function(src,bitnum,startLSB) {
  //#? reflect 'bitnum' bits starting at lowest bit = startLSB
// ToDO. NOT YET TESTED
	var i, j, k, iw, jw, bit;
	for (k=0; k+startLSB<bitnum-1-k; k++) {
		iw=7-((k+startLSB)>>3);
		jw=1<<((k+startLSB)&7);
		i=7-((bitnum-1-k)>>3);
		j=1<<((bitnum-1-k)&7);

		bit = src[iw] & jw;
		if (src[i] & j) src[iw] |= jw;
		else src[iw] &= (0xff-jw);
		if (bit) src[i] |= j;
		else src[i] &= (0xff-j);
	}
	return src;
  };

  this.c8tab      = function(src,iv,mask,polynomial)  {
  //#? compute CRC-8 checksum
	var bux = iv;
	var crc8Map = new Array(  // table for polynomial *unknown*
		0x00, 0x1b, 0x36, 0x2d, 0x6c, 0x77, 0x5a, 0x41,
		0xd8, 0xc3, 0xee, 0xf5, 0xb4, 0xaf, 0x82, 0x99,
		0xd3, 0xc8, 0xe5, 0xfe, 0xbf, 0xa4, 0x89, 0x92,
		0x0b, 0x10, 0x3d, 0x26, 0x67, 0x7c, 0x51, 0x4a,
		0xc5, 0xde, 0xf3, 0xe8, 0xa9, 0xb2, 0x9f, 0x84,
		0x1d, 0x06, 0x2b, 0x30, 0x71, 0x6a, 0x47, 0x5c,
		0x16, 0x0d, 0x20, 0x3b, 0x7a, 0x61, 0x4c, 0x57,
		0xce, 0xd5, 0xf8, 0xe3, 0xa2, 0xb9, 0x94, 0x8f,
		0xe9, 0xf2, 0xdf, 0xc4, 0x85, 0x9e, 0xb3, 0xa8,
		0x31, 0x2a, 0x07, 0x1c, 0x5d, 0x46, 0x6b, 0x70,
		0x3a, 0x21, 0x0c, 0x17, 0x56, 0x4d, 0x60, 0x7b,
		0xe2, 0xf9, 0xd4, 0xcf, 0x8e, 0x95, 0xb8, 0xa3,
		0x2c, 0x37, 0x1a, 0x01, 0x40, 0x5b, 0x76, 0x6d,
		0xf4, 0xef, 0xc2, 0xd9, 0x98, 0x83, 0xae, 0xb5,
		0xff, 0xe4, 0xc9, 0xd2, 0x93, 0x88, 0xa5, 0xbe,
		0x27, 0x3c, 0x11, 0x0a, 0x4b, 0x50, 0x7d, 0x66,
		0xb1, 0xaa, 0x87, 0x9c, 0xdd, 0xc6, 0xeb, 0xf0,
		0x69, 0x72, 0x5f, 0x44, 0x05, 0x1e, 0x33, 0x28,
		0x62, 0x79, 0x54, 0x4f, 0x0e, 0x15, 0x38, 0x23,
		0xba, 0xa1, 0x8c, 0x97, 0xd6, 0xcd, 0xe0, 0xfb,
		0x74, 0x6f, 0x42, 0x59, 0x18, 0x03, 0x2e, 0x35,
		0xac, 0xb7, 0x9a, 0x81, 0xc0, 0xdb, 0xf6, 0xed,
		0xa7, 0xbc, 0x91, 0x8a, 0xcb, 0xd0, 0xfd, 0xe6,
		0x7f, 0x64, 0x49, 0x52, 0x13, 0x08, 0x25, 0x3e,
		0x58, 0x43, 0x6e, 0x75, 0x34, 0x2f, 0x02, 0x19,
		0x80, 0x9b, 0xb6, 0xad, 0xec, 0xf7, 0xda, 0xc1,
		0x8b, 0x90, 0xbd, 0xa6, 0xe7, 0xfc, 0xd1, 0xca,
		0x53, 0x48, 0x65, 0x7e, 0x3f, 0x24, 0x09, 0x12,
		0x9d, 0x86, 0xab, 0xb0, 0xf1, 0xea, 0xc7, 0xdc,
		0x45, 0x5e, 0x73, 0x68, 0x29, 0x32, 0x1f, 0x04,
		0x4e, 0x55, 0x78, 0x63, 0x22, 0x39, 0x14, 0x0f,
		0x96, 0x8d, 0xa0, 0xbb, 0xfa, 0xe1, 0xcc, 0xd7
	);
	for (var i=0; i<src.length; i++) {
		ccc = src.charCodeAt(i);
		bux = crc8Map[(bux^ccc)&0xff];
	}
	if (crc8Map.length) { crc8Map.length = 0; }; crc8Map = null;
	return (bux ^ mask);
  }; // c8tab

/* =================================================================
 * simple CRC-16 CIIT (polynomial 0x1021)
    crc  = (unsigned char)(crc >> 8) | (crc << 8);
    crc ^= ser_data;
    crc ^= (unsigned char)(crc & 0xff) >> 4;
    crc ^= (crc << 8) << 4;
    crc ^= ((crc & 0xff) << 4) << 1;
 * ================================================================= */

  this.crc16     = function(src,iv,mask,polynomial)  {
  //#? compute CRC-16 checksum
	function _crc16(chr, crc16, polynomial) {
	// calculate the CRC-16 byte by byte
	// chr is the next byte and crc16 is the result from the last call
		var xor = false;
		chr <<= 8;
		for(var i=0; i<8; i++) {
			xor = ((crc16 ^ chr) & 0x8000)!=0 ? true : false;
			crc16 <<= 1;
			if (xor==true) { crc16 ^= polynomial; }
			chr <<= 1;
		}
		crc16 &= 0x0000ffff; // zero out the upper two bytes
		return crc16;
	};
	// calculate the CRC-16
	var bux = iv;
	for (var i=0; i<src.length; i++) {
		ccc = src.charCodeAt(i);
		bux = _crc16(ccc, bux, polynomial);
	}
	return (bux ^ mask);
  }; // crc16

  this.c16arc   = function(src,iv,mask)  {
  //#? compute CRC-16 checksum using classic table (ARC)
	var bux = iv;
	var crc16Map = new Array(  // table for polynomial *unknown* (some classic CRC)
		0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
		0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
		0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
		0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
		0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
		0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
		0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
		0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
		0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
		0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
		0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
		0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
		0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
		0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
		0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
		0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
		0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
		0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
		0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
		0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
		0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
		0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
		0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
		0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
		0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
		0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
		0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
		0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
		0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
		0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
		0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
		0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
        );
	for (var i=0; i<src.length; i++) {
		ccc = src.charCodeAt(i);
		bux = crc16Map[(bux^ccc)&0xff] ^ (bux>>8);
//		bux = crc16Map[(bux^ccc)&0xff] ^ (bux>>8)&0xff; // same as above
//		bux = (bux>>8) ^ crc16Map[(bux^ccc)&0xff];      // same as above
	}
	if (crc16Map.length) { crc16Map.length = 0; }; crc16Map = null;
	return (bux ^ mask);
  }; // c16arc

  this.c16ppp   = function(src,iv,mask)  {
  //#? compute CRC-16 checksum using RFC-1662 table (aka PPP, aka FCS-16)
	var bux = iv;
	/*
	 * following table found at: http://www.digsys.se/js_crc.html
	 * (in october 2008)
	 */
	var crc16Map = new Array(  // table for polynomial *unknown*
		0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
		0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
		0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
		0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
		0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
		0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
		0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
		0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
		0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
		0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
		0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
		0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
		0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
		0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
		0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
		0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
		0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
		0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
		0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
		0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
		0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
		0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
		0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
		0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
		0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
		0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
		0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
		0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
		0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
		0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
		0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
		0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
	);
	for (var i=0; i<src.length; i++) {
		ccc = src.charCodeAt(i);
		bux = crc16Map[(bux^ccc)&0xff] ^ (bux>>8);
	}
	if (crc16Map.length) { crc16Map.length = 0; }; crc16Map = null;
	return (bux ^ mask);
  }; // c16ppp

  this.c16zmo   = function(src,iv,mask)  {
  //#? compute CRC-16 checksum using ZModem table
	/*
	 * following table found at: http://www.digsys.se/js_crc.html
	 * (in october 2008) which claims following rights to use:
	 * --
	 * Copyright (c) 1989 AnDan Software. You may use this program, or
	 * code or tables extracted from it, as long as this notice is not
	 * removed or changed.
	 * --
	 */
	var bux = iv;
	var crc16Map = new Array(  // table for polynomial *unknown*
		0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
		0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
		0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
		0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
		0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
		0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
		0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
		0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
		0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
		0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
		0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
		0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
		0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
		0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
		0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
		0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
		0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
		0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
		0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
		0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
		0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
		0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
		0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
		0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
		0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
		0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
		0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
		0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
		0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
		0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
		0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
		0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
	);
	for (var i=0; i<src.length; i++) {
		ccc = src.charCodeAt(i);
		bux = crc16Map[((bux>>8)^ccc)&0xff]^((bux<<8)&0xffff);
//		bux = (bux>>8) ^ crc16Map[(bux^ccc)&0xff];      // same ??
	}
	if (crc16Map.length) { crc16Map.length = 0; }; crc16Map = null;
	return (bux ^ mask);
  }; // c16zmo

  this.c32tab   = function(src,iv,mask)  {
  //#? compute CRC-32 checksum (aka FCS-32)
	// initial vector is 0xffffffff and final result is XOR 0xffffffff
	var bux = 0xffffffff; // ToDo: use iv but does not work with JavaScript 'cause of 2^53 limit
	var ccc;
	var crc32Map = new Array( // table for plynomial 0x04C11DB7
		0x00000000,0x77073096,0xee0e612c,0x990951ba,0x076dc419,0x706af48f,0xe963a535,0x9e6495a3,
		0x0edb8832,0x79dcb8a4,0xe0d5e91e,0x97d2d988,0x09b64c2b,0x7eb17cbd,0xe7b82d07,0x90bf1d91,
		0x1db71064,0x6ab020f2,0xf3b97148,0x84be41de,0x1adad47d,0x6ddde4eb,0xf4d4b551,0x83d385c7,
		0x136c9856,0x646ba8c0,0xfd62f97a,0x8a65c9ec,0x14015c4f,0x63066cd9,0xfa0f3d63,0x8d080df5,
		0x3b6e20c8,0x4c69105e,0xd56041e4,0xa2677172,0x3c03e4d1,0x4b04d447,0xd20d85fd,0xa50ab56b,
		0x35b5a8fa,0x42b2986c,0xdbbbc9d6,0xacbcf940,0x32d86ce3,0x45df5c75,0xdcd60dcf,0xabd13d59,
		0x26d930ac,0x51de003a,0xc8d75180,0xbfd06116,0x21b4f4b5,0x56b3c423,0xcfba9599,0xb8bda50f,
		0x2802b89e,0x5f058808,0xc60cd9b2,0xb10be924,0x2f6f7c87,0x58684c11,0xc1611dab,0xb6662d3d,
		0x76dc4190,0x01db7106,0x98d220bc,0xefd5102a,0x71b18589,0x06b6b51f,0x9fbfe4a5,0xe8b8d433,
		0x7807c9a2,0x0f00f934,0x9609a88e,0xe10e9818,0x7f6a0dbb,0x086d3d2d,0x91646c97,0xe6635c01,
		0x6b6b51f4,0x1c6c6162,0x856530d8,0xf262004e,0x6c0695ed,0x1b01a57b,0x8208f4c1,0xf50fc457,
		0x65b0d9c6,0x12b7e950,0x8bbeb8ea,0xfcb9887c,0x62dd1ddf,0x15da2d49,0x8cd37cf3,0xfbd44c65,
		0x4db26158,0x3ab551ce,0xa3bc0074,0xd4bb30e2,0x4adfa541,0x3dd895d7,0xa4d1c46d,0xd3d6f4fb,
		0x4369e96a,0x346ed9fc,0xad678846,0xda60b8d0,0x44042d73,0x33031de5,0xaa0a4c5f,0xdd0d7cc9,
		0x5005713c,0x270241aa,0xbe0b1010,0xc90c2086,0x5768b525,0x206f85b3,0xb966d409,0xce61e49f,
		0x5edef90e,0x29d9c998,0xb0d09822,0xc7d7a8b4,0x59b33d17,0x2eb40d81,0xb7bd5c3b,0xc0ba6cad,
		0xedb88320,0x9abfb3b6,0x03b6e20c,0x74b1d29a,0xead54739,0x9dd277af,0x04db2615,0x73dc1683,
		0xe3630b12,0x94643b84,0x0d6d6a3e,0x7a6a5aa8,0xe40ecf0b,0x9309ff9d,0x0a00ae27,0x7d079eb1,
		0xf00f9344,0x8708a3d2,0x1e01f268,0x6906c2fe,0xf762575d,0x806567cb,0x196c3671,0x6e6b06e7,
		0xfed41b76,0x89d32be0,0x10da7a5a,0x67dd4acc,0xf9b9df6f,0x8ebeeff9,0x17b7be43,0x60b08ed5,
		0xd6d6a3e8,0xa1d1937e,0x38d8c2c4,0x4fdff252,0xd1bb67f1,0xa6bc5767,0x3fb506dd,0x48b2364b,
		0xd80d2bda,0xaf0a1b4c,0x36034af6,0x41047a60,0xdf60efc3,0xa867df55,0x316e8eef,0x4669be79,
		0xcb61b38c,0xbc66831a,0x256fd2a0,0x5268e236,0xcc0c7795,0xbb0b4703,0x220216b9,0x5505262f,
		0xc5ba3bbe,0xb2bd0b28,0x2bb45a92,0x5cb36a04,0xc2d7ffa7,0xb5d0cf31,0x2cd99e8b,0x5bdeae1d,
		0x9b64c2b0,0xec63f226,0x756aa39c,0x026d930a,0x9c0906a9,0xeb0e363f,0x72076785,0x05005713,
		0x95bf4a82,0xe2b87a14,0x7bb12bae,0x0cb61b38,0x92d28e9b,0xe5d5be0d,0x7cdcefb7,0x0bdbdf21,
		0x86d3d2d4,0xf1d4e242,0x68ddb3f8,0x1fda836e,0x81be16cd,0xf6b9265b,0x6fb077e1,0x18b74777,
		0x88085ae6,0xff0f6a70,0x66063bca,0x11010b5c,0x8f659eff,0xf862ae69,0x616bffd3,0x166ccf45,
		0xa00ae278,0xd70dd2ee,0x4e048354,0x3903b3c2,0xa7672661,0xd06016f7,0x4969474d,0x3e6e77db,
		0xaed16a4a,0xd9d65adc,0x40df0b66,0x37d83bf0,0xa9bcae53,0xdebb9ec5,0x47b2cf7f,0x30b5ffe9,
		0xbdbdf21c,0xcabac28a,0x53b39330,0x24b4a3a6,0xbad03605,0xcdd70693,0x54de5729,0x23d967bf,
		0xb3667a2e,0xc4614ab8,0x5d681b02,0x2a6f2b94,0xb40bbe37,0xc30c8ea1,0x5a05df1b,0x2d02ef8d
	);
	for (var i=0; i<src.length; i++) {
		ccc = src.charCodeAt(i);
		bux = crc32Map[(bux ^ ccc)&0xff] ^ ((bux >> 8) & 0xffffff);
	}
	if (crc32Map.length) { crc32Map.length = 0; }; crc32Map = null;
// ToDo: use mask parameter but does not work with JavaScript 'cause of 2^53 limit
	return (bux ^ 0xffffffff);
  }; // c32tab

  this.dispatch = function(type,src,iv,mask,polynomial) {
  //#? wrapper for CRC functions
	this.dbx('.CRC.dispatch(' + type + ', ' + src + ', ' + iv + ', ' + mask + ', ' + polynomial + ')');
	switch (type) {
	  case 'C8tab':  return this.c8tab( src,iv,mask); break;
	  case 'C32tab': return this.c32tab(src,iv,mask); break;
	  case 'ARCtab': return this.c16arc(src,iv,mask); break;
	  case 'PPPtab': return this.c16ppp(src,iv,mask); break;
	  case 'MODtab': return this.c16zmo(src,iv,mask); break;
	  case 'user':   return this.crc16( src,iv,mask,polynomial); break;
	  case 'test':   return  '' +
// ToDo: move these test cases to EnDeTest.js
			'# iv   mask  : result\n' +
			'------+------+-------'   +
			//                                                        iv     mask      | expected result
			'\n== c16arc:' +
			'\n0x0000 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.c16arc(src,0x0000,0x0000)) ) + // BB3D
			'\n0xffff 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.c16arc(src,0xffff,0x0000)) ) + // 4B37
			'\n0x0000 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.c16arc(src,0x0000,0xffff)) ) + // 44c2
			'\n0xffff 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.c16arc(src,0xffff,0xffff)) ) + // b4c8
			'\n0x1d0f 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.c16arc(src,0x1d0f,0x0000)) ) + // debc
			'\n0x1d0f 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.c16arc(src,0x1d0f,0xffff)) ) + // 2143
			'\n0x0000 0x1d0f: '+EnDe.i2h(2, EnDe.z2n(this.c16arc(src,0x0000,0x1d0f)) ) + // a632
			'\n== c16ppp:' +
			'\n0x0000 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.c16ppp(src,0x0000,0x0000)) ) + // 2189
			'\n0xffff 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.c16ppp(src,0xffff,0x0000)) ) + // 6f91
			'\n0x0000 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.c16ppp(src,0x0000,0xffff)) ) + // de76
			'\n0xffff 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.c16ppp(src,0xffff,0xffff)) ) + // 906e
			'\n0x1d0f 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.c16ppp(src,0x1d0f,0x0000)) ) + // 5604
			'\n0x1d0f 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.c16ppp(src,0x1d0f,0xffff)) ) + // a9fb
			'\n0x0000 0x1d0f: '+EnDe.i2h(2, EnDe.z2n(this.c16ppp(src,0x0000,0x1d0f)) ) + // a45a
			'\n== c16zmo:' +
			'\n0x0000 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.c16zmo(src,0x0000,0x0000)) ) + // b955
			'\n0xffff 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.c16zmo(src,0xffff,0x0000)) ) + // 6eb4
			'\n0x0000 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.c16zmo(src,0x0000,0xffff)) ) + // 46aa
			'\n0xffff 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.c16zmo(src,0xffff,0xffff)) ) + // 914b
			'\n0x1d0f 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.c16zmo(src,0x1d0f,0x0000)) ) + // c53d
			'\n0x1d0f 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.c16zmo(src,0x1d0f,0xffff)) ) + // 3ac2
			'\n0x0000 0x1d0f: '+EnDe.i2h(2, EnDe.z2n(this.c16zmo(src,0x0000,0x1d0f)) ) + // a45a
			//                                                     iv     mask  plynom     | expected result
			'\n== crc16(0x1021):' +
			'\n0x0000 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0x0000,0x0000,0x1021)) ) + // 31C3
			'\n0xffff 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0xffff,0x0000,0x1021)) ) + // 29B1
			'\n0x0000 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0x0000,0xffff,0x1021)) ) + // cec3
//	'\n0x0000 0xFFFF: '+EnDe.i2h(2, EnDe.z2n(this.reflect(this.crc16(src,0x0000,0xffff,0x1021),16,8)) ) + // cec3
//	'\n0x0000 0xFFFF: '+EnDe.i2h(2, EnDe.z2n(this.reflectByte(this.crc16(src,0x0000,0xffff,0x1021))) ) + // cec3
			'\n0xffff 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0xffff,0xffff,0x1021)) ) + // d64e
			'\n== crc16(0x1d0f):' +
			'\n0x0000 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0x0000,0x0000,0x1d0f)) ) + // 73a7
			'\n0xffff 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0xffff,0x0000,0x1d0f)) ) + // 59e9
			'\n0x0000 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0x0000,0xffff,0x1d0f)) ) + // 8c58
			'\n0xffff 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0xffff,0xffff,0x1d0f)) ) + // a616
			'\n== crc16(0x3d65):' +
			'\n0x0000 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0x0000,0x0000,0x3d65)) ) + // 3d48
			'\n0xffff 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0xffff,0x0000,0x3d65)) ) + // bbb6
			'\n0x0000 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0x0000,0xffff,0x3d65)) ) + // c2b7
			'\n0xffff 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0xffff,0xffff,0x3d65)) ) + // 4449
			'\n== crc16(0x8408):' +
			'\n0x0000 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0x0000,0x0000,0x8408)) ) + // 96a8
			'\n0xffff 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0xffff,0x0000,0x8408)) ) + // 520
			'\n0x0000 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0x0000,0xffff,0x8408)) ) + // 6957
			'\n0xffff 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0xffff,0xffff,0x8408)) ) + // fadf
			'\n== crc16(0x8005):' +
			'\n0x0000 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0x0000,0x0000,0x8005)) ) + // 96a8
			'\n0xffff 0x0000: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0xffff,0x0000,0x8005)) ) + // 520
			'\n0x0000 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0x0000,0xffff,0x8005)) ) + // 6957
			'\n0xffff 0xffff: '+EnDe.i2h(2, EnDe.z2n(this.crc16(src,0xffff,0xffff,0x8005)) ) + // fadf
			'';
		break;
/*
 * result of above calls with value 123456789 (0x313233)

===================+ type of CRC
== crc16arc:
0x0000 0x0000: bb3d	CRC-16 (ARC)
0xffff 0x0000: 4b37	CRC-16 (Modbus)
0x0000 0xffff: 44c2
0xffff 0xffff: b4c8
0x1d0f 0x0000: debc
0x1d0f 0xffff: 2143
0x0000 0x1d0f: a632
== crc16ppp:
0xffff 0xffff: b4c8	CRC-16 (FCS-16, PPP)
0x0000 0x0000: 2189
0xffff 0x0000: 6f91
0x0000 0xffff: de76
0xffff 0xffff: 906e
0x1d0f 0x0000: 5604
0x1d0f 0xffff: a9fb
0x0000 0x1d0f: 3c86
== c16zmo:
0x0000 0x0000: 31c3
0xffff 0x0000: 29b1
0x0000 0xffff: ce3c
0xffff 0xffff: d64e
0x1d0f 0x0000: e5cc
0x1d0f 0xffff: 1a33
0x0000 0x1d0f: 2ccc
== crc16(0x1021):
0x0000 0x0000: 31c3	CRC-16 (CCITT XModem, ZModem)
0xffff 0x0000: 29b1	CRC-16 (CCITT)
0x0000 0xffff: ce3c
0xffff 0xffff: d64e
== crc16(0x1d0f):
0x0000 0x0000: 73a7
0xffff 0x0000: 59e9
0x0000 0xffff: 8c58
0xffff 0xffff: a616
== crc16(0x3d65):
0x0000 0x0000: 3d48
0xffff 0x0000: bbb6
0x0000 0xffff: c2b7
0xffff 0xffff: 4449
== crc16(0x8408):
0x0000 0x0000: 96a8
0xffff 0x0000: 520
0x0000 0xffff: 6957
0xffff 0xffff: fadf
== crc16(0x8005):
0x0000 0x0000: fee8
0xffff 0x0000: aee7
0x0000 0xffff: 117
0xffff 0xffff: 5118

#*
	---------------+-------+-------+---------------+--------
	mode		IV	ploynom	XOR result	check
	---------------+-------+-------+---------------+--------
	CRC-8		?	0x07	?		20	?
	CRC-10		?	0x233	?		?	?
	CRC-12		?	0x80f	?		?	?
	CRC-16		0x0000	0x8005	0x0000		BB3D	Magnetband
	CRC-16 ARC	0x0000	0x8005	0x0000		BB3D
	CRC-16 Modbus	0xffff	0x8005	0x0000		4B37
	CRC-16 CIIT	0xffff	0x1021	0x0000		29B1	Disketten
	CRC-16 XMODEM	0x0000	0x8408	0x0000		C73
	?CRC-16 ?	0xffff	0x1021	0x0000		DE76
	?CRC-16/CIIT	0x1d0f	0x1021
	? CRC-DNP	0xffff	0x3d65
	? CRC-DNP	0x1d0f	0x3d65
	? CRC-16	0xffff	0x8005
	? CRC-16	0x1d0f	0x8005
	CRC-32	    0xffffffff	0x04C11DB7 0xffffffff	CBF43926 Ethernet
	---------------+-------+-------+---------------+--------
#*
*/
	}
	return null; // ToDo: internal error
  }; // dispatch

}; // EnDe.CRC

