diff --git a/Makefile b/Makefile index 56af208..a5218e5 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ PROGRAM = crc32 .PHONY: all clean install -FILES = main.c args.c +FILES = main.c args.c crc32.c CFLAGS += -Wall -Werror -ansi -pedantic LDFLAGS += diff --git a/crc32.c b/crc32.c new file mode 100644 index 0000000..de2e66d --- /dev/null +++ b/crc32.c @@ -0,0 +1,98 @@ +/* Copyright (C) 2012 Connor Olding + * + * This program is licensed under the terms of the MIT License, and + * is distributed without any warranty. You should have received a + * copy of the license along with this program; see the file LICENSE. + */ + +#include + +typedef unsigned long ulong; + +#include "crc32.h" + +int crc_big_endian = 0; +ulong crc_polynomial = 0x04C11DB7; + +enum { + TABLE_SIZE = 0x100 +}; +static ulong crc_be_table[TABLE_SIZE]; /* big endian */ +static ulong crc_le_table[TABLE_SIZE]; /* little endian */ + +ulong crc_reflect(ulong input) +{ + ulong reflected = 0; + int i; + for (i = 0; i < 4 * 8; i++) { + reflected <<= 1; + reflected |= input & 1; + input >>= 1; + } + return reflected; +} + +static void crc_fill_big_endian_table() +{ + const ulong lsb = 1 << 31; /* least significant bit */ + ulong c; + int i; + + for (c = 0; c < TABLE_SIZE; c++) { + crc_be_table[c] = c << 24; + for (i = 0; i < 8; i++) { + if (crc_be_table[c] & lsb) { + crc_be_table[c] <<= 1; + crc_be_table[c] ^= crc_polynomial; + } else { + crc_be_table[c] <<= 1; + } + crc_be_table[c] &= 0xFFFFFFFF; + } + } +} + +static void crc_fill_little_endian_table() +{ + const ulong lsb = 1; /* least significant bit */ + const ulong reflected = crc_reflect(crc_polynomial); + ulong c; + int i; + + for (c = 0; c < TABLE_SIZE; c++) { + crc_le_table[c] = c; + for (i = 0; i < 8; i++) { + if (crc_le_table[c] & lsb) { + crc_le_table[c] >>= 1; + crc_le_table[c] ^= reflected; + } else { + crc_le_table[c] >>= 1; + } + } + } +} + +static void crc_fill_tables_once() +{ + static char filled = 0; + if (crc_big_endian && !(filled & 1)) { + crc_fill_big_endian_table(); + filled |= 1; + } else if (!crc_big_endian && !(filled & 2)) { + crc_fill_little_endian_table(); + filled |= 2; + } +} + +void crc_cycle(ulong *remainder, char c) +{ + crc_fill_tables_once(); + if (crc_big_endian) { + const ulong byte = crc_be_table[((*remainder) >> 24) ^ c]; + *remainder = ((*remainder) << 8) ^ byte; + *remainder &= 0xFFFFFFFF; + } else { + const ulong byte = crc_le_table[((*remainder) ^ c) & 0xFF]; + *remainder = ((*remainder) >> 8) ^ byte; + } +} diff --git a/crc32.h b/crc32.h index db97b01..b939d95 100644 --- a/crc32.h +++ b/crc32.h @@ -5,149 +5,9 @@ * copy of the license along with this program; see the file LICENSE. */ -#ifndef CRC32_H_ -#define CRC32_H_ - -#include - -/* interface */ - -typedef unsigned long ulong; +int crc_big_endian; +ulong crc_polynomial; void crc_cycle(ulong *remainder, char c); ulong crc_reflect(ulong input); -void crc_set_big_endian(); -void crc_set_little_endian(); -void crc_set_polynomial(ulong p); - -/* implementation */ - -static char crc_big_endian = 0; -static const int crc_table_size = 0x100; -static ulong *crc_be_table = NULL; /* big endian */ -static ulong *crc_le_table = NULL; /* little endian */ -static ulong crc_polynomial = 0x04C11DB7; - -ulong crc_reflect(ulong input) -{ - ulong reflected = 0; - int i; - for (i = 0; i < 4 * 8; i++) { - reflected <<= 1; - reflected |= input & 1; - input >>= 1; - } - return reflected; -} - -static ulong *crc_alloc(size_t size) -{ - ulong *p = (ulong*) malloc(size * sizeof(ulong)); - if (p == NULL) - exit(1); - return p; -} - -static void crc_allocate_tables_once() -{ - static char allocated = 0; - if (crc_big_endian && !(allocated & 1)) { - crc_be_table = crc_alloc(crc_table_size); - allocated |= 1; - } else if (!crc_big_endian && !(allocated & 2)) { - crc_le_table = crc_alloc(crc_table_size); - allocated |= 2; - } -} - -static void crc_fill_big_endian_table() -{ - const ulong least_significant_bit = 1 << 31; - ulong c; - int i; - - crc_allocate_tables_once(); - - for (c = 0; c < crc_table_size; c++) { - crc_be_table[c] = c << 24; - for (i = 0; i < 8; i++) { - if (crc_be_table[c] & least_significant_bit) { - crc_be_table[c] <<= 1; - crc_be_table[c] ^= crc_polynomial; - } else { - crc_be_table[c] <<= 1; - } - crc_be_table[c] &= 0xFFFFFFFF; - } - } -} - -static void crc_fill_little_endian_table() -{ - const ulong least_significant_bit = 1; - const ulong reflected_polynomial = crc_reflect(crc_polynomial); - ulong c; - int i; - - crc_allocate_tables_once(); - /* printf("p: %08X\n", (int)reflected_polynomial); */ - - for (c = 0; c < crc_table_size; c++) { - crc_le_table[c] = c; - for (i = 0; i < 8; i++) { - if (crc_le_table[c] & least_significant_bit) { - crc_le_table[c] >>= 1; - crc_le_table[c] ^= reflected_polynomial; - } else { - crc_le_table[c] >>= 1; - } - } - } -} - -static void crc_fill_tables_once() -{ - static char filled = 0; - if (crc_big_endian && !(filled & 1)) { - crc_fill_big_endian_table(); - filled |= 1; - } else if (!crc_big_endian && !(filled & 2)) { - crc_fill_little_endian_table(); - filled |= 2; - } -} - -void crc_set_big_endian() -{ - crc_big_endian = 1; -} - -void crc_set_little_endian() -{ - crc_big_endian = 0; -} - -void crc_set_polynomial(ulong p) -{ - crc_polynomial = p; -} - -void crc_cycle(ulong *remainder, char c) -{ - crc_fill_tables_once(); - if (crc_big_endian) { - const ulong newByte = crc_be_table[((*remainder) >> 24) ^ c]; - /* printf("%08X00 ^ %08X =\n", - (int)(*remainder), (int)newByte); */ - *remainder = ((*remainder) << 8) ^ newByte; - *remainder &= 0xFFFFFFFF; - } else { - const ulong newByte = crc_le_table[((*remainder) ^ c) & 0xFF]; - /* printf(" %08X ^ %08X =\n", - (int)((*remainder) >> 8), (int)newByte); */ - *remainder = ((*remainder) >> 8) ^ newByte; - } -} - -#endif diff --git a/main.c b/main.c index 669dae8..5f46cc2 100644 --- a/main.c +++ b/main.c @@ -9,6 +9,8 @@ #include #include +typedef unsigned long ulong; + #include "crc32.h" #include "args.h" @@ -65,7 +67,7 @@ static void handle_flag(char flag, char *(*nextarg)()) printf(help2); exit(0); case 'e': - crc_set_big_endian(); + crc_big_endian = 1; return; case 'b': print_binary = 1; @@ -85,7 +87,7 @@ static void handle_flag(char flag, char *(*nextarg)()) break; case 'p': next = check_next(flag, nextarg()); - crc_set_polynomial(strtoul(next, NULL, 0)); + crc_polynomial = strtoul(next, NULL, 0); break; default: fprintf(stderr, "Unknown flag: -%c\n", flag); @@ -147,7 +149,6 @@ static void print_crc(ulong remainder) int main(int argc, char **argv) { string_node *n; - crc_set_little_endian(); args_parse(argc, argv, handle_flag, add_input); if (!input_node) {