├── rust ├── Cargo.lock ├── Cargo.toml └── src │ └── crc32.rs ├── c ├── Makefile └── crc32.c ├── cpp ├── Makefile └── crc32.cc ├── ruby └── crc32.rb ├── python └── crc32.py ├── node └── crc32.js ├── go └── crc32.go ├── README.md ├── java └── Crc32.java └── lisp └── crc32.l /rust/Cargo.lock: -------------------------------------------------------------------------------- 1 | [root] 2 | name = "crc32" 3 | version = "0.1.0" 4 | 5 | -------------------------------------------------------------------------------- /rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "crc32" 4 | version = "0.1.0" 5 | authors = [ "john" ] 6 | 7 | [[bin]] 8 | 9 | name = "crc32" 10 | -------------------------------------------------------------------------------- /c/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS= -std=c99 -Wall 2 | CC=gcc 3 | 4 | all: crc32-opt crc32-def 5 | 6 | 7 | crc32-opt: crc32.c 8 | gcc crc32.c $(CFLAGS) -O3 -o $@ 9 | 10 | crc32-def: crc32.c 11 | gcc crc32.c $(CFLAGS) -o $@ 12 | 13 | 14 | check-syntax: 15 | $(CC) $(CFLAGS) -fsyntax-only $(CHK_SOURCES) 16 | 17 | clean: 18 | rm -f crc32-opt crc32-def 19 | -------------------------------------------------------------------------------- /cpp/Makefile: -------------------------------------------------------------------------------- 1 | CPPFLAGS= -Wall 2 | CPP=g++ 3 | 4 | all: crc32-opt crc32-def 5 | 6 | 7 | crc32-opt: crc32.cc 8 | $(CPP) crc32.cc $(CPPFLAGS) -O3 -o $@ 9 | 10 | crc32-def: crc32.cc 11 | $(CPP) crc32.cc $(CPPFLAGS) -o $@ 12 | 13 | 14 | check-syntax: 15 | $(CPP) $(CFLAGS) -fsyntax-only $(CHK_SOURCES) 16 | 17 | clean: 18 | rm -f crc32-opt crc32-def 19 | -------------------------------------------------------------------------------- /ruby/crc32.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | class CRC32 4 | SEED = 0xEDB88320 5 | 6 | def initialize 7 | @table = 256.times.map do |i| 8 | 8.times.reduce(i){ |c, _| c & 1 == 1 ? SEED ^ (c >> 1) : c >> 1 } 9 | end 10 | end 11 | 12 | def crc(input) 13 | start 14 | update(input) 15 | finalize 16 | end 17 | 18 | def start 19 | @value = 0xffffffff 20 | end 21 | 22 | def update(input) 23 | @value = input.each_byte.reduce(@value) do |c, ch| 24 | @table[(c ^ ch) & 0xFF] ^ (c >> 8) 25 | end 26 | end 27 | 28 | def finalize 29 | @value ^ 0xffffffff 30 | end 31 | end 32 | 33 | crc32 = CRC32.new 34 | 35 | ARGV.each do |file_name| 36 | File.open(file_name, 'r') do |f| 37 | crc32.start 38 | while buf = f.read(1024 * 1024) 39 | crc32.update(buf) 40 | end 41 | puts "#{file_name}: %08X" % crc32.finalize 42 | end rescue nil 43 | end 44 | -------------------------------------------------------------------------------- /python/crc32.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | 4 | class CRC32: 5 | def __init__(self): 6 | self.table = [] 7 | self.value = None 8 | 9 | for i in range(256): 10 | v = i 11 | for j in range(8): 12 | v = (0xEDB88320 ^ (v >> 1)) if(v & 1) == 1 else (v >> 1) 13 | self.table.append(v) 14 | 15 | def start(self): 16 | self.value = 0xffffffff 17 | 18 | def update(self, buf): 19 | for c in buf: 20 | self.value = self.table[(self.value ^ c) & 0xFF] ^ (self.value >> 8) 21 | 22 | def finalize(self): 23 | return self.value ^ 0xffffffff 24 | 25 | crc32 = CRC32() 26 | 27 | for file_name in sys.argv[1:]: 28 | f = open(file_name, 'rb') 29 | 30 | crc32.start() 31 | while True: 32 | buf = f.read(1024 * 1024) 33 | if buf == b'': 34 | break 35 | crc32.update(buf) 36 | 37 | print("%s: %08X" % (file_name, crc32.finalize())) 38 | 39 | f.close() 40 | -------------------------------------------------------------------------------- /node/crc32.js: -------------------------------------------------------------------------------- 1 | /*jshint undef:true node:true strict:false*/ 2 | var fs = require('fs'); 3 | 4 | var Crc32 = function() { 5 | this.table = []; 6 | this.value = null; 7 | 8 | var v; 9 | 10 | for(var i = 0; i < 256; ++i) { 11 | v = i; 12 | for(var j = 0; j < 8; ++j) { 13 | v = (v & 1) ? (0xedb88320 ^ (v >>> 1)) : (v >>> 1); 14 | } 15 | this.table[i] = v | 0; 16 | } 17 | }; 18 | 19 | Crc32.prototype.start = function() { 20 | this.value = 0xffffffff; 21 | }; 22 | 23 | Crc32.prototype.update = function(text) { 24 | for(var i = 0; i < text.length; ++i) { 25 | var c = text.charCodeAt(i); 26 | this.value = this.table[(this.value ^ c) & 0xFF] ^ (this.value >>> 8); 27 | } 28 | }; 29 | 30 | Crc32.prototype.finalize = function() { 31 | return (this.value ^ 0xffffffff) >>> 0; 32 | }; 33 | 34 | for(var i = 2; i < process.argv.length; ++i) { 35 | 36 | (function(filename) { 37 | var crc = new Crc32(); 38 | var stream = fs.createReadStream(filename, { 39 | encoding: 'binary', 40 | flags: 'r', 41 | bufferSize: 1024 * 1024 42 | }).addListener('data', function(chunk) { 43 | crc.update(chunk); 44 | }).addListener('open', function() { 45 | crc.start(); 46 | }).addListener('close', function() { 47 | console.log(filename, crc.finalize().toString(16)); 48 | }); 49 | })(process.argv[i]); 50 | 51 | } 52 | -------------------------------------------------------------------------------- /go/crc32.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "fmt" 6 | ) 7 | 8 | type Crc32 struct { 9 | value uint32 10 | table[256] uint32 11 | } 12 | 13 | func (self *Crc32) Init() { 14 | var v uint32 15 | 16 | for i := 0; i < 256; i++ { 17 | v = uint32(i) 18 | for j := 0; j < 8; j++ { 19 | if (v & 1 == 1) { 20 | v = (0xedb88320 ^ (v >> 1)) 21 | } else { 22 | v >>= 1 23 | } 24 | } 25 | self.table[i] = v 26 | } 27 | } 28 | 29 | func (self *Crc32) Start() { 30 | self.value = 0xffffffff 31 | } 32 | 33 | func (self *Crc32) Finalize() (uint32) { 34 | return self.value ^ 0xffffffff 35 | } 36 | 37 | func (self *Crc32) Update(data []byte) { 38 | for i := 0; i < len(data); i++ { 39 | self.value = self.table[(self.value ^ uint32(data[i])) & 0xFF] ^ (self.value >> 8) 40 | } 41 | } 42 | 43 | func main() { 44 | var args = os.Args[1:] 45 | var crc = &Crc32{} 46 | 47 | crc.Init() 48 | 49 | for i := 0; i < len(args); i++ { 50 | fp, err := os.Open(args[i]) 51 | if (err == nil) { 52 | crc.Start() 53 | data := make([]byte, 1024 * 1024) 54 | 55 | for { 56 | count, err := fp.Read(data) 57 | if (err != nil || count == 0) { 58 | break 59 | } 60 | crc.Update(data[:count]) 61 | } 62 | fmt.Printf("%s: %08X\n", args[i], crc.Finalize()) 63 | fp.Close() 64 | } 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | crc32 2 | ===== 3 | 4 | crc32 implementation in a myriad of languages. 5 | 6 | Totally Unscientific Results 7 | ============================ 8 | 9 | Run with a 40MB randomly generated file. 10 | 11 | * C++ (optimized) `0.128s` 12 | * C (optimized) `0.136s` 13 | * Java `0.150s` 14 | * Go `0.220s` 15 | * C (no optimizations) `0.244s` 16 | * Node `0.715s` 17 | * C++ (no optimizations) `1.675s` 18 | * Lisp (compiled) `11.788s` 19 | * Ruby `16.289s` 20 | * Python `22.483s` 21 | * Lisp (interpreted) `38.779s` 22 | 23 | 24 | ### C 25 | _i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)_ 26 | 27 | ``` 28 | No optimizations: 0m0.244s 29 | With optimizations (-O3): 0m0.136s 30 | ``` 31 | 32 | ### C++ 33 | _i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)_ 34 | 35 | ``` 36 | No optimizations: 0m1.675s 37 | With optimizations (-O3): 0m0.128s 38 | ``` 39 | 40 | ### Go 41 | _go version go1.0.3_ 42 | 43 | ``` 44 | Go: 0m0.220s 45 | ``` 46 | 47 | ### Java 48 | _java version "1.7.0_15"_ 49 | 50 | ``` 51 | Java: 0m0.150s 52 | ``` 53 | 54 | ### Lisp 55 | _GNU CLISP 2.49 (2010-07-07)_ 56 | 57 | ``` 58 | Interpreted: 0m38.779s 59 | Compiled: 0m11.788s 60 | ``` 61 | 62 | ### Javascript 63 | _node v0.8.8_ 64 | 65 | ``` 66 | Node: 0m0.715s 67 | ``` 68 | 69 | ### Python 70 | _Python 3.3.0_ 71 | 72 | ``` 73 | Python: 0m22.483s 74 | ``` 75 | 76 | ### Ruby 77 | _ruby 1.9.3p327 (2012-11-10 revision 37606) [x86_64-darwin12.2.0]_ 78 | 79 | ``` 80 | Ruby: 0m16.289s 81 | ``` 82 | -------------------------------------------------------------------------------- /c/crc32.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef struct crc32 { 6 | uint32_t table[256]; 7 | uint32_t value; 8 | } crc32_t; 9 | 10 | #define CRC32_INITIAL 0xedb88320 11 | 12 | void crc32_init(crc32_t* crc) { 13 | uint32_t v; 14 | 15 | for(int i = 0; i < 256; ++i) { 16 | v = i; 17 | 18 | for(int j = 0; j < 8; ++j) { 19 | v = (v & 1) ? (CRC32_INITIAL ^ (v >> 1)) : (v >> 1); 20 | } 21 | crc->table[i] = v; 22 | } 23 | } 24 | 25 | void crc32_update(crc32_t* c, uint8_t* buf, size_t len) { 26 | for(size_t i = 0; i < len; ++i) { 27 | c->value = c->table[(c->value ^ buf[i]) & 0xFF] ^ (c->value >> 8); 28 | } 29 | } 30 | 31 | void crc32_start(crc32_t* c) { 32 | c->value = 0xfffffffful; 33 | } 34 | 35 | uint32_t crc32_finalize(crc32_t* c) { 36 | return c->value ^ 0xfffffffful; 37 | } 38 | 39 | uint32_t crc32_crc(crc32_t* c, uint8_t* buf, size_t len) { 40 | crc32_start(c); 41 | crc32_update(c, buf, len); 42 | return crc32_finalize(c); 43 | } 44 | 45 | 46 | int main(int argc, char* argv[]) { 47 | crc32_t c; 48 | size_t buf_size = 1024 * 1024; 49 | uint8_t* buf = malloc(buf_size); 50 | ssize_t len; 51 | 52 | if (!buf) { 53 | perror("error allocating memory"); 54 | exit(1); 55 | } 56 | 57 | crc32_init(&c); 58 | 59 | for(int i = 1; i < argc; ++i) { 60 | FILE* fp = fopen(argv[i], "rb"); 61 | crc32_start(&c); 62 | 63 | while((len = fread(buf, 1, buf_size, fp)) > 0) { 64 | crc32_update(&c, buf, len); 65 | } 66 | printf("%s: %08X\n", argv[i], crc32_finalize(&c)); 67 | 68 | fclose(fp); 69 | } 70 | 71 | free(buf); 72 | 73 | return 0; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /java/Crc32.java: -------------------------------------------------------------------------------- 1 | import java.io.FileInputStream; 2 | import java.io.IOException; 3 | import java.io.FileNotFoundException; 4 | 5 | public class Crc32 { 6 | 7 | private int value; 8 | private int[] table = new int[256]; 9 | 10 | private static final int SEED = 0xEDB88320; 11 | 12 | public Crc32() { 13 | 14 | for(int i = 0; i < 256; ++i) { 15 | int v = i; 16 | for(int j = 0; j < 8; ++j) { 17 | v = (v & 1) == 1 ? (SEED ^ (v >>> 1)) : (v >>> 1); 18 | } 19 | this.table[i] = v; 20 | } 21 | } 22 | 23 | public void start() { 24 | value = 0xFFFFFFFF; 25 | } 26 | 27 | public void update(byte[] bytes, int length) { 28 | for(int i = 0; i < length; ++i) { 29 | this.value = this.table[((this.value ^ bytes[i]) & 0xFF)] ^ (this.value >>> 8); 30 | } 31 | } 32 | 33 | 34 | public int result() { 35 | return (this.value ^ 0xFFFFFFFF); 36 | } 37 | 38 | public static void main(String[] args) throws IOException { 39 | Crc32 crc = new Crc32(); 40 | byte[] buf = new byte[1024 * 1024]; 41 | int len; 42 | 43 | for (String filename : args) { 44 | FileInputStream fs = null; 45 | try { 46 | fs = new FileInputStream(filename); 47 | crc.start(); 48 | while((len = fs.read(buf)) > 0) { 49 | crc.update(buf, len); 50 | } 51 | 52 | System.out.format("%s: %08x\n", filename, crc.result()); 53 | 54 | } catch (FileNotFoundException ex) { 55 | 56 | } finally { 57 | if (fs != null) { 58 | fs.close(); 59 | } 60 | } 61 | } 62 | 63 | } 64 | } 65 | 66 | 67 | -------------------------------------------------------------------------------- /lisp/crc32.l: -------------------------------------------------------------------------------- 1 | ;; build and return the crc32 table 2 | (defun crc-init () 3 | (coerce 4 | (loop for i from 0 below 256 collect 5 | (reduce 6 | (lambda (accum c) 7 | (declare (ignore c)) 8 | (boole boole-and #xFFFFFFFF 9 | (if (eq (boole boole-and accum 1) 1) 10 | (boole boole-xor #xEDB88320 (ash accum -1)) 11 | (ash accum -1)))) 12 | (loop for j from 0 below 8 collect j) ; seq 13 | :initial-value i)) 14 | 'vector)) 15 | 16 | ;; start a new crc32 calculation and return the initial value 17 | (defun crc-start () #xFFFFFFFF) 18 | 19 | ;; update a crc32 and return the new in-progress value 20 | (defun crc-update (table crc bytes) 21 | (reduce 22 | (lambda (accum ch) 23 | (boole boole-xor 24 | (elt 25 | table 26 | (boole boole-and 27 | (boole boole-xor accum ch) 28 | #xFF)) 29 | (ash accum -8))) 30 | bytes 31 | :initial-value crc)) 32 | 33 | ;; finalize a crc32 calculation 34 | (defun crc-finalize (crc) 35 | (boole boole-xor crc #xFFFFFFFF)) 36 | 37 | (let ((table (crc-init))) 38 | (loop for filename in ext:*args* do 39 | (let ((in (open filename 40 | :if-does-not-exist nil 41 | :element-type '(unsigned-byte 8))) 42 | (seq (make-array (* 1024 1024) 43 | :element-type '(unsigned-byte 8) 44 | :adjustable t 45 | :fill-pointer (* 1024 1024))) 46 | (crc (crc-start))) 47 | (when in 48 | ;; read file and update crc value 49 | (progn 50 | (loop 51 | (setf (fill-pointer seq) (read-byte-sequence seq in)) 52 | (when (zerop (fill-pointer seq)) 53 | (return)) 54 | (setq crc (crc-update table crc seq))) 55 | (format t "~A: ~X~%" filename (crc-finalize crc))))))) 56 | -------------------------------------------------------------------------------- /cpp/crc32.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | const static int ONE_MB = 1024 * 1024; 8 | 9 | class Crc32 { 10 | private: 11 | const static uint32_t seed; 12 | std::vector table; 13 | uint32_t value; 14 | public: 15 | Crc32(); 16 | 17 | uint32_t crc(const std::vector& bytes); 18 | void start(); 19 | void update(const std::vector& bytes); 20 | uint32_t finalize(); 21 | }; 22 | 23 | const uint32_t Crc32::seed = 0xEDB88320; 24 | 25 | Crc32::Crc32() : value(0) 26 | { 27 | uint32_t v; 28 | table.resize(256); 29 | 30 | for(size_t i = 0; i < 256; ++i) { 31 | v = i; 32 | for(size_t j = 0; j < 8; ++j) { 33 | v = (v & 1) ? (seed ^ (v >> 1)) : (v >> 1); 34 | } 35 | table[i] = v; 36 | } 37 | } 38 | 39 | uint32_t Crc32::crc(const std::vector& bytes) 40 | { 41 | start(); 42 | update(bytes); 43 | return finalize(); 44 | } 45 | 46 | void Crc32::start() 47 | { 48 | value = 0xFFFFFFFF; 49 | } 50 | 51 | void Crc32::update(const std::vector& bytes) 52 | { 53 | for(std::vector::const_iterator i = bytes.begin(); 54 | i != bytes.end(); 55 | i++) { 56 | value = table[(value ^ *i) & 0xFF] ^ (value >> 8); 57 | } 58 | } 59 | 60 | uint32_t Crc32::finalize() 61 | { 62 | return value ^ 0xFFFFFFFFul; 63 | } 64 | 65 | 66 | int main(int argc, char* argv[]) 67 | { 68 | Crc32 crc; 69 | std::vector buf; 70 | 71 | buf.resize(ONE_MB); 72 | 73 | 74 | for(int i = 1; i < argc; ++i) { 75 | crc.start(); 76 | std::ifstream f(argv[i], std::ios::binary); 77 | 78 | while(f.read((char*)&buf[0], ONE_MB)) { 79 | crc.update(buf); 80 | } 81 | 82 | buf.resize(f.gcount()); 83 | crc.update(buf); 84 | 85 | f.close(); 86 | std::cout << argv[i] << ": " << std::setw(8) << std::setfill('0') << 87 | std::hex << crc.finalize() << std::endl; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /rust/src/crc32.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::path::Path; 3 | use std::env; 4 | use std::thread::{spawn,JoinHandle}; 5 | use std::io::Read; 6 | 7 | pub struct Crc32 { 8 | table: [u32; 256], 9 | value: u32 10 | } 11 | 12 | static CRC32_INITIAL:u32 = 0xedb88320; 13 | 14 | impl Crc32 { 15 | 16 | fn new() -> Crc32 { 17 | let mut c = Crc32 { table: [0; 256], value: 0xffffffff }; 18 | 19 | for i in 0..256 { 20 | let mut v = i as u32; 21 | for _ in 0..8 { 22 | v = if v & 1 != 0 { 23 | CRC32_INITIAL ^ (v >> 1) 24 | } else { 25 | v >> 1 26 | } 27 | } 28 | c.table[i] = v; 29 | } 30 | 31 | c 32 | } 33 | 34 | fn start(&mut self) { 35 | self.value = 0xffffffff; 36 | } 37 | 38 | fn update(&mut self, buf: &[u8]) { 39 | for &i in buf { 40 | self.value = self.table[((self.value ^ (i as u32)) & 0xFF) as usize] ^ (self.value >> 8); 41 | } 42 | } 43 | 44 | fn finalize(&mut self) -> u32 { 45 | self.value ^ 0xffffffffu32 46 | } 47 | 48 | fn crc(&mut self, buf: &[u8]) -> u32 { 49 | self.start(); 50 | self.update(buf); 51 | self.finalize() 52 | } 53 | } 54 | 55 | pub fn main() { 56 | let args = env::args(); 57 | let mut children = vec![]; 58 | 59 | for arg in args.skip(1) { 60 | let mut buf = [0u8 ; 1024]; 61 | let mut crc = Crc32::new(); 62 | let a = arg.clone(); 63 | let r = spawn(move || { 64 | let path = Path::new(&a); 65 | let disp = path.display(); 66 | 67 | let mut file = match File::open(&path) { 68 | Ok(file) => file, 69 | Err(e) => { 70 | println!("{}: {}", disp, e); 71 | return; 72 | } 73 | }; 74 | 75 | crc.start(); 76 | 77 | while match file.read(&mut buf) { 78 | Ok(len) => { 79 | crc.update(&buf[0..len]); 80 | len > 0 81 | }, 82 | Err(_) => false 83 | } { /* do nothing */ }; 84 | 85 | println!("{}: {:X}", disp, crc.finalize()); 86 | }); 87 | children.push(r); 88 | } 89 | 90 | for child in children { 91 | child.join(); 92 | } 93 | 94 | } 95 | --------------------------------------------------------------------------------