Never been to TextSnippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

Ocaml CRC-CCITT

Implementation of CRC-CCITT (CRC-16 variant) in Objective Caml. Uses a bit vector implementation but is not table driven.

 open Bitv
 open List
 open Printf

 (* convenience functions *)
 let bits initf = Bitv.init 16 initf 
 let zeros = Bitv.create 16 false
 let ones = Bitv.create 16 true
 let from_str s = function n -> (String.get s n) == '1'

 (* CC-ITT CRC polynomials: big endian and little endian *)
 let poly8048 =   from_str "1000010000001000" 
 let poly1021 =   from_str "0001000000100001" 

 (* bit twiddling functions. I hate that OCaml doesn't have a bit vector type *)
 (* and unsigned ints are 30 bits, and signed ints are 31 bits if that isn't wierd enough *)
 (* and no, there is no 16 bit type that can be used as an integer. Sigh. *)
 let bit n bits = Bitv.get bits n
 let shl n bitv = Bitv.shiftl bitv n
 let bxor bitv1 bitv2 = Bitv.bw_xor bitv1 bitv2
 let byte_bits c = Bitv.sub (Bitv.of_int_us(int_of_char c)) 0 8
 let pad n bits = Bitv.append bits (Bitv.create n false)

 (* calculate the CRC for a given byte value. can use this to create a table *)
 (* lookup version that should be faster, should you find yourself in a big hurry *)
 let chksum poly remainder byte = 
   let rem = bxor (shl 8 (pad 8 byte)) remainder in
   let sum remnant = 
     let shifted = shl 1 remnant in 
     if bit 15 remnant then bxor shifted poly else shifted
   in let rec bits at max remnant byte =
     if at < max then bits (at + 1) max (sum remnant) byte else remnant
   in bits 0 8 rem byte

 (* fold the list, collecting and applying the checksum to each byte *)
 let crc init bytes =
   List.fold_left (chksum (bits poly8048)) init bytes

 (* test to see if we get the proper output corresponding to a correct implementation *)
 (* should be 0x29B1, ocaml ints have 30 bits, accounting for strange pad value used *)
 let result = 
   let bits = List.map byte_bits ['1';'2';'3';'4';'5';'6';'7';'8';'9';] in
   printf "0x%X\n" (Bitv.to_int_us(pad 14 (crc ones bits)))

You need to create an account or log in to post comments to this site.