package com.mindprod.example;

import java.io.UnsupportedEncodingException;

/**
 * 16-bit CRC, cyclic redundancy checks, computed from scratch
 * <p/>
 * composed with IntelliJ IDEA
 *
 * @author Roedy Green, Canadian Mind Products
 * @version 1.0
 */
public final class TestCRC16
    {
    // ------------------------------ FIELDS ------------------------------

    /**
     * generator polynomial
     */
    private static final int poly = 0x1021;/* x16 + x12 + x5 + 1 generator polynomial */
    /* 0x8408 used in European X.25 */

    /**
     * scrambler lookup table for fast computation.
     */
    private static final int[] crcTable = new int[256];

    // -------------------------- STATIC METHODS --------------------------

    static
        {
        // initialise scrambler table
        for ( int i = 0; i < 256; i++ )
            {
            int fcs = 0;
            int d = i << 8;
            for ( int k = 0; k < 8; k++ )
                {
                if ( ( ( fcs ^ d ) & 0x8000 ) != 0 )
                    {
                    fcs = ( fcs << 1 ) ^ poly;
                    }
                else
                    {
                    fcs = ( fcs << 1 );
                    }
                d <<= 1;
                fcs &= 0xffff;
                }
            crcTable[ i ] = fcs;
            }
        }

    /**
     * Calc 16-bit CRC with CCITT method.
     *
     * @param ba byte array to compute CRC on
     * @return 16-bit CRC, unsigned
     */
    private static int crc16( byte[] ba )
        {
        // loop, calculating CRC for each byte of the string
        int work = 0xffff;
        for ( byte b : ba )
            {
            // xor the next data byte with the high byte of what we have so far to
            // look up the scrambler.
            // xor that with the low byte of what we have so far.
            // Mask back to 16 bits.
            work = ( crcTable[ ( b ^ ( work >>> 8 ) ) & 0xff ] ^ ( work << 8 ) ) &
                   0xffff;
            }
        return work;
        }

    // --------------------------- main() method ---------------------------

    /**
     * Test harness
     *
     * @param args not used
     * @throws java.io.UnsupportedEncodingException
     *          in case UTF-8 support missing.
     */
    public static void main( String[] args ) throws UnsupportedEncodingException
        {
        final String s = "The quick brown fox jumped over the lazy dog's back";
        final byte[] ba = s.getBytes( "UTF-8"/* encoding */ );
        System.out.println( crc16( ba ) );
        }
    }