/* $Id: crc16_arc.cs $
* Last updated:
* $Date: 2019-11-23 07:07Z $
* $Version: 1.1 $
*/
/******************************* LICENSE ***********************************
* Copyright (C) 2019 David Ireland, DI Management Services Pty Limited.
* All rights reserved. <www.di-mgt.com.au> <www.cryptosys.net>
* The code in this module is licensed under the terms of the MIT license.
* For a copy, see <http://opensource.org/licenses/MIT>
****************************************************************************
*/
using System;
using System.Text;
using System.Diagnostics;
namespace crc16
{
/* Compute CRC-16 checksum over input string.
Ref: Catalogue of parametrised CRC algorithms with 16 bits
http://reveng.sourceforge.net/crc-catalogue/16.htm
CRC-16/ARC
Alias: ARC, CRC-16, CRC-16/LHA, CRC-IBM
width=16 poly=0x8005 init=0x0000 refin=true refout=true xorout=0x0000 check=0xbb3d residue=0x0000 name="CRC-16/ARC"
CRC('123456789')=bb3d
*/
class crc16_arc
{
static void Main(string[] args)
{
// Standard check
CheckTest("123456789", 0xbb3d);
// Other tests
CheckTest("hello world", 0x39c1);
CheckTest("a", 0xe8c1);
CheckTest(" ", 0xd801);
CheckTest("", 0x0000);
}
static bool CheckTest(string msg, UInt16 check)
{
UInt16 crc;
crc = crc16(msg);
Console.WriteLine("CRC-16('{0}')={1:X4}, CHECK={2:X4}", msg, crc, check);
Debug.Assert(crc == check, "CRC check failed");
return (crc == check);
}
/// <summary>
/// Compute CRC-16/ARC checksum over input string.
/// </summary>
/// <param name="Str">Input string</param>
/// <returns>CRC value as 16-bit unsigned integer</returns>
static UInt16 crc16(string Str)
{
const UInt16 INIT = 0x0000;
const UInt16 POLY = 0xA001; // 0x8005 with bits reversed
const UInt16 XOUT = 0x0000;
// Convert string to byte array
byte[] b = System.Text.Encoding.Default.GetBytes(Str);
int len = b.Length;
UInt16 temp;
int i, j;
UInt16 crc = INIT;
for (i = 0; i < len; i++) {
temp = (UInt16)((crc & 0xFF) ^ b[i]);
for (j = 0; j < 8; j++) {
if ((temp & 0x1) > 0)
temp = (UInt16)((temp >> 1) ^ POLY);
else
temp >>= 1;
}
crc = (UInt16)((crc >> 8) ^ temp);
}
return (UInt16)(crc ^ XOUT);
}
}
}