#ifndef TBDECODE #define TBDECODE #include #include #include #include #ifndef CLOCKS_PER_SEC #define CLOCKS_PER_SEC CLK_TCK #endif /* ---------------------------- Error codes --------------------------- */ /* ----------- */ #define COMP_ERR_NONE 0 /* everything is OK */ #define COMP_ERR_READ 2 /* input file read error */ #define COMP_ERR_NOMEM 5 /* no enough memory */ #define COMP_ERR_BROKEN 6 /* damaged compressed data */ #define COMP_ERR_PARAM 7 /* incorrect function parameter */ #define COMP_ERR_INTERNAL 9 /* everything else is internal error */ /* hopefully it should never happen */ /* Almost all functions listed further return one as its result on of */ /* codes given above: if no error occured then COMP_ERR_NONE (i.e. 0) */ /* is returned, otherwise functions return error code plus number of */ /* line in "comp.c" where the error was detected multiplied by 256; */ /* line number may be used for exact specification of a place where */ /* error was detected thus making debugging slightly simpler. */ /* */ /* Thus, "(code & 0xff)" gives proper error code, and "(code >> 8)" */ /* gives number of line where the error was raised. */ /* -------------------------------------------------------------------- */ /* */ /* Compress/decompress some chess tables */ /* */ /* Copyright (c) 1991--1998 Andrew Kadatch */ /* */ /* The Limited-Reference variant of Lempel-Ziv algorithm implemented */ /* here was first described in my B.Sc. thesis "Efficient algorithms */ /* for image compression", Novosibirsk State University, 1992, and */ /* cannot be used in any product distributed in Russia or CIS without */ /* written permission from the author. */ /* */ /* Most of the code listed below is significantly simplified code from */ /* the PRS data compression library and therefore it should not be used */ /* in any product (software or hardware, commercial or not, and so on) */ /* without written permission from the author. */ /* */ /* -------------------------------------------------------------------- */ /* ---------------------------- Debugging ----------------------------- */ /* --------- */ #ifndef DEBUG #define DEBUG 0 #endif #if DEBUG #define assert(cond) ((cond) ? (void) 0 : _local_assert (__LINE__)) static void _local_assert(int lineno) { fprintf(stderr, "assertion at line %u failed\n", lineno); exit(33); } #define debug(x) x #define dprintf(x) printf x #else #if !defined (assert) #define assert(cond) ((void) 0) #endif #define debug(x) ((void) 0) #define dprintf(x) ((void) 0) #endif /* mob_pach */ #ifndef __cplusplus int cbEGTBCompBytes = 0; #else extern "C" { int cbEGTBCompBytes = 0; } #endif /* --------------------- Constants, types, etc. ----------------------- */ /* ---------------------- */ #define MIN_BLOCK_BITS 8 /* LOG2 (min size of block to compress) */ #define MAX_BLOCK_BITS 16 /* LOG2 (max size of block to compress) */ /* max. integer we can take LOG2 by table */ #define MAX_BITS_HALF ((MAX_BLOCK_BITS + 1) >> 1) #define MAX_BITS (MAX_BITS_HALF * 2) /* assume that integer is at least 32 bits wide */ #ifndef uint #define uint unsigned #endif #ifndef uchar #define uchar unsigned char #endif #define HEADER_SIZE 80 /* number of reserved bytes */ #define STOP_SEARCH_LENGTH 256 /* terminate search if match */ /* length exceeds that value */ #define MAX_LENGTH_BITS 5 #define MAX_LENGTH (1 << MAX_LENGTH_BITS) #define LONG_BITS 1 #define LONG_LENGTH (MAX_BLOCK_BITS - LONG_BITS) #define LONG_QUICK (MAX_LENGTH - LONG_LENGTH) #if LONG_LENGTH > (MAX_BLOCK_BITS - LONG_BITS) # undef LONG_LENGTH # define LONG_LENGTH (MAX_BLOCK_BITS - LONG_BITS) #endif #if LONG_LENGTH >= MAX_LENGTH || LONG_LENGTH <= 0 #error LONG_LENGTH is out of range #endif #if LONG_BITS <= 0 #error LONG_BITS must be positive #endif #define DELTA (LONG_BITS + LONG_QUICK - 1) #if (MAX_LENGTH - 1) - (LONG_LENGTH - LONG_BITS) != DELTA #error Hmmm #endif #define MAX_DISTANCES 24 #define LOG_MAX_DISTANCES 6 /* see check below */ #if MAX_DISTANCES > (1 << LOG_MAX_DISTANCES) #error MAX_DISTANCES should not exceed (1 << LOG_MAX_DISTANCES) #endif #define ALPHABET_SIZE (256 + (MAX_DISTANCES << MAX_LENGTH_BITS)) #define MAX_ALPHABET ALPHABET_SIZE /* max. alphabet handled by */ /* Huffman coding routines */ #define USE_CRC32 1 /* 0 - use Fletcher's checksum, != 0 - use proper CRC32 */ static uchar header_title[64] = "Compressed by DATACOMP v 1.0 (c) 1991--1998 Andrew Kadatch\r\n\0"; #define RET(n) ((n) + __LINE__ * 256) /* ------------------------- CRC32 routines --------------------------- */ /* -------------- */ #if USE_CRC32 static unsigned CRC32_table[256]; static int CRC32_initialized = 0; static void CRC32_init(void) { int i, j; unsigned k, m = (unsigned) 0xedb88320L; if (CRC32_initialized) return; for (i = 0; i < 256; ++i) { k = i; j = 8; do { if ((k & 1) != 0) k >>= 1; else { k >>= 1; k ^= m; }; } while (--j); CRC32_table[i] = k; } CRC32_initialized = 1; } static unsigned CRC32(uchar * p, int n, unsigned k) { unsigned *table = CRC32_table; uchar *e = p + n; while (p + 16 < e) { # define X(i) k = table[((uchar) k) ^ p[i]] ^ (k >> 8) X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); X(10); X(11); X(12); X(13); X(14); X(15); # undef X p += 16; } while (p < e) k = table[((uchar) k) ^ *p++] ^ (k >> 8); return (k); } #else #define CRC32_init() static unsigned CRC32(uchar * p, int n, unsigned k1) { unsigned k0 = k1 & 0xffff; uchar *e = p + n; k1 = (k1 >> 16) & 0xffff; while (p + 16 < e) { # define X(i) k0 += p[i]; k1 += k0; X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); X(10); X(11); X(12); X(13); X(14); X(15); # undef X k0 = (k0 & 0xffff) + (k0 >> 16); k1 = (k1 & 0xffff) + (k1 >> 16); p += 16; } while (p < e) { k0 += *p++; k1 += k0; } k0 = (k0 & 0xffff) + (k0 >> 16); k1 = (k1 & 0xffff) + (k1 >> 16); k0 = (k0 & 0xffff) + (k0 >> 16); k1 = (k1 & 0xffff) + (k1 >> 16); assert(((k0 | k1) >> 16) == 0); return (k0 + (k1 << 16)); } #endif /* USE_CRC32 */ /* ------------------------ Bit IO interface -------------------------- */ /* ---------------- */ #define BITIO_LOCALS \ uint _mask; \ int _bits; \ uchar *_ptr typedef struct { BITIO_LOCALS; } bitio_t; #define BITIO_ENTER(p) do { \ _mask = (p)._mask; \ _bits = (p)._bits; \ _ptr = (p)._ptr; \ } while (0) #define BITIO_LEAVE(p) do { \ (p)._mask = _mask; \ (p)._bits = _bits; \ (p)._ptr = _ptr; \ } while (0) #define BIORD_START(from) do { \ _ptr = (uchar *) (from); \ _bits = sizeof (_mask); \ _mask = 0; \ do \ _mask = (_mask << 8) | *_ptr++; \ while (--_bits != 0); \ _bits = 16; \ } while (0) /* read [1, 17] bits at once */ #define BIORD(bits) \ (_mask >> (8 * sizeof (_mask) - (bits))) #define BIORD_MORE(bits) do { \ _mask <<= (bits); \ if ((_bits -= (bits)) <= 0) \ { \ _mask |= ((_ptr[0] << 8) + _ptr[1]) << (-_bits); \ _ptr += 2; _bits += 16; \ } \ } while (0) /* ------------------------ Huffman coding ---------------------------- */ /* -------------- */ #if MAX_ALPHABET <= 0xffff # if MAX_ALPHABET <= 1024 /* positive value takes 15 bits => symbol number occupies <= 10 bits */ # define huffman_decode_t short # else # define huffman_decode_t int # endif #else # define huffman_decode_t int #endif #define HUFFMAN_DECODE(ch,table,start_bits) do { \ (ch) = table[BIORD (start_bits)]; \ if (((int) (ch)) >= 0) \ { \ BIORD_MORE ((ch) & 31); \ (ch) >>= 5; \ break; \ } \ BIORD_MORE (start_bits); \ do \ { \ (ch) = table[BIORD (1) - (ch)]; \ BIORD_MORE (1); \ } \ while (((int) (ch)) < 0); \ } while (0) #define HUFFMAN_TABLE_SIZE(n,start_bits) \ ((1 << (start_bits)) + ((n) << 1)) static int huffman_decode_create(huffman_decode_t * table, uchar * length, int n, int start_bits) { int i, j, k, last, freq[32], sum[32]; /* calculate number of codewords */ memset(freq, 0, sizeof(freq)); for (i = 0; i < n; ++i) { if ((k = length[i]) > 31) return RET(COMP_ERR_BROKEN); ++freq[k]; } /* handle special case(s) -- 0 and 1 symbols in alphabet */ if (freq[0] == n) { memset(table, 0, sizeof(table[0]) << start_bits); return (0); } if (freq[0] == n - 1) { if (freq[1] != 1) return RET(COMP_ERR_BROKEN); for (i = 0; length[i] == 0;) ++i; i <<= 5; for (k = 1 << start_bits; --k >= 0;) *table++ = (huffman_decode_t) i; return (0); } /* save frequences */ memcpy(sum, freq, sizeof(sum)); /* check code correctness */ k = 0; for (i = 32; --i != 0;) { if ((k += freq[i]) & 1) return RET(COMP_ERR_BROKEN); k >>= 1; } if (k != 1) return RET(COMP_ERR_BROKEN); /* sort symbols */ k = 0; for (i = 1; i < 32; ++i) freq[i] = (k += freq[i]); last = freq[31]; /* preserve number of symbols in alphabet */ for (i = n; --i >= 0;) { if ((k = length[i]) != 0) table[--freq[k]] = (huffman_decode_t) i; } /* now create decoding table */ k = i = (1 << start_bits) + (n << 1); for (n = 32; --n > start_bits;) { j = i; while (k > j) table[--i] = (huffman_decode_t) - (k -= 2); for (k = sum[n]; --k >= 0;) table[--i] = table[--last]; k = j; } j = i; i = 1 << start_bits; while (k > j) table[--i] = (huffman_decode_t) - (k -= 2); for (; n > 0; --n) { for (k = sum[n]; --k >= 0;) { assert(last <= i && last > 0); j = i - (1 << (start_bits - n)); n |= table[--last] << 5; do table[--i] = (huffman_decode_t) n; while (i != j); n &= 31; } } assert((i | last) == 0); return (0); } /* -------------------- Read/write Huffman code ----------------------- */ /* ----------------------- */ #define MIN_REPT 2 #if MIN_REPT <= 1 #error MIN_REPT must exceed 1 #endif #define TEMP_TABLE_BITS 8 static int huffman_read_length(bitio_t * bitio, uchar * length, int n) { BITIO_LOCALS; huffman_decode_t table[2][HUFFMAN_TABLE_SIZE(64, TEMP_TABLE_BITS)]; uchar bits[128]; int i, j, k; BITIO_ENTER(*bitio); k = BIORD(1); BIORD_MORE(1); if (k != 0) { memset(length, 0, n); goto ret; } if (n <= 128) { k = BIORD(5); BIORD_MORE(5); for (i = 0; i < n;) { length[i] = (uchar) BIORD(k); BIORD_MORE(k); if (length[i++] == 0) { j = i + BIORD(4); BIORD_MORE(4); if (j > n) return RET(COMP_ERR_BROKEN); while (i != j) length[i++] = 0; } } goto ret; } BITIO_LEAVE(*bitio); i = huffman_read_length(bitio, bits, 128); if (i != 0) return (i); i = huffman_decode_create(table[0], bits, 64, TEMP_TABLE_BITS); if (i != 0) return (i); i = huffman_decode_create(table[1], bits + 64, 64, TEMP_TABLE_BITS); if (i != 0) return (i); BITIO_ENTER(*bitio); for (i = 0; i < n;) { HUFFMAN_DECODE(k, table[0], TEMP_TABLE_BITS); if (k <= 31) { length[i++] = (uchar) k; continue; } k &= 31; HUFFMAN_DECODE(j, table[1], TEMP_TABLE_BITS); if (j > 31) { int jj = j - 32; j = 1 << jj; if (jj != 0) { if (jj > 16) { j += BIORD(16) << (jj - 16); BIORD_MORE(16); } j += BIORD(jj); BIORD_MORE(jj); } j += 31; } j += MIN_REPT + i; if (j > n) return RET(COMP_ERR_BROKEN); do length[i] = (uchar) k; while (++i != j); } ret: BITIO_LEAVE(*bitio); return (0); } /* ----------------------- Proper compression ------------------------- */ /* ------------------ */ #if MIN_BLOCK_BITS > MAX_BLOCK_BITS || MAX_BLOCK_BITS > MAX_BITS_HALF*2 #error condition MIN_BLOCK_BITS <= MAX_BLOCK_BITS <= MAX_BITS_HALF*2 failed #endif #define DECODE_MAGIC ((int) 0x5abc947fL) #define BLOCK_MAGIC ((int) 0x79a3f29dL) #define START_BITS 13 #define SHORT_INDEX 8u typedef struct { huffman_decode_t table[HUFFMAN_TABLE_SIZE(ALPHABET_SIZE, START_BITS)]; int distance[MAX_DISTANCES]; unsigned *crc, *blk_u; unsigned short *blk_s; int block_size_log, /* block_size is integral power of 2 */ block_size, /* 1 << block_size_log */ last_block_size, /* [original] size of last block */ n_blk, /* total number of blocks */ comp_block_size, /* size of largest compressed block+32 */ check_crc; /* check CRC32? */ uchar *comp; int magic; } decode_info; typedef struct { unsigned char *ptr; /* pointer to the first decoded byte */ int decoded; /* number of bytes decoded so far */ int total; /* total number of bytes in block */ int number; /* number of this block */ } COMP_BLOCK_T; /* Pointer to compressed data block */ typedef struct { COMP_BLOCK_T b; struct { uchar *first; int size; } orig , comp; struct { uchar *ptr, *src; int rept; } emit; bitio_t bitio; int n; int magic; } decode_block; static int calculate_offset(decode_info * info, unsigned n) { unsigned i; i = n / (2 * SHORT_INDEX); if (n & SHORT_INDEX) return info->blk_u[i + 1] - info->blk_s[n]; else return info->blk_u[i] + info->blk_s[n]; } static void do_decode(decode_info * info, decode_block * block, uchar * e) { BITIO_LOCALS; uchar *p, *s = 0; int ch; if ((p = block->emit.ptr) >= e) return; if (p == block->orig.first) { BIORD_START(block->comp.first); block->emit.rept = 0; } else { BITIO_ENTER(block->bitio); if ((ch = block->emit.rept) != 0) { block->emit.rept = 0; s = block->emit.src; goto copy; } } #define OVER if (p < e) goto over; break do { over: HUFFMAN_DECODE(ch, info->table, START_BITS); if ((ch -= 256) < 0) { *p++ = (uchar) ch; OVER; } s = p + info->distance[ch >> MAX_LENGTH_BITS]; ch &= MAX_LENGTH - 1; if (ch <= 3) { p[0] = s[0]; p[1] = s[1]; p[2] = s[2]; p[3] = s[3]; p += ch + 1; OVER; } else if (ch >= LONG_LENGTH) { ch -= LONG_LENGTH - LONG_BITS; #if (MAX_BLOCK_BITS - 1) + (LONG_LENGTH - LONG_BITS) >= MAX_LENGTH if (ch == DELTA) { ch = BIORD(5); BIORD_MORE(5); ch += DELTA; } #endif { int n = 1 << ch; if (ch > 16) { n += BIORD(16) << (ch -= 16); BIORD_MORE(16); } n += BIORD(ch); BIORD_MORE(ch); ch = n; } ch += LONG_LENGTH - (1 << LONG_BITS); } ++ch; copy: if (ch > 16) { if (p + ch > e) { block->emit.rept = ch - (int) (e - p); ch = (int) (e - p); goto copy; } do { # define X(i) p[i] = s[i] X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); X(10); X(11); X(12); X(13); X(14); X(15); # undef X p += 16; s += 16; } while ((ch -= 16) > 16); } p += ch; s += ch; switch (ch) { # define X(i) case i: p[-i] = s[-i] X(16); X(15); X(14); X(13); X(12); X(11); X(10); X(9); X(8); X(7); X(6); X(5); X(4); X(3); X(2); # undef X } p[-1] = s[-1]; } while (p < e); #undef OVER block->emit.ptr = p; block->emit.src = s; BITIO_LEAVE(block->bitio); } /* pretty ugly */ static int comp_open_file(decode_info ** res, FILE * fd, int check_crc) { BITIO_LOCALS; bitio_t Bitio; uchar temp[ALPHABET_SIZE >= HEADER_SIZE ? ALPHABET_SIZE : HEADER_SIZE]; uchar *ptr; int header_size, block_size, block_size_log, n_blk, i, n, n_s, n_u; unsigned *blk_u, *blk; unsigned short *blk_s; decode_info *info; if (res == 0) return RET(COMP_ERR_PARAM); CRC32_init(); *res = 0; if (fread(temp, 1, HEADER_SIZE, fd) != HEADER_SIZE) return RET(COMP_ERR_READ); if (memcmp(temp, header_title, 64) != 0) return RET(COMP_ERR_READ); ptr = temp; #define R4(i) \ ((ptr[i] << 24) + (ptr[(i) + 1] << 16) + (ptr[(i) + 2] << 8) + (ptr[(i) + 3])) header_size = R4(64); block_size_log = ptr[70]; if (block_size_log > MAX_BITS || header_size < 84) return RET(COMP_ERR_BROKEN); block_size = 1 << block_size_log; if (ptr[71] != MAX_DISTANCES) return RET(COMP_ERR_BROKEN); n_blk = R4(72); if (R4(76) != (ALPHABET_SIZE << 12) + (LONG_BITS << 8) + (LONG_LENGTH << 4) + MAX_LENGTH_BITS) return RET(COMP_ERR_BROKEN); if ((ptr = (uchar *) malloc(header_size)) == 0) return RET(COMP_ERR_NOMEM); if (fread(ptr + HEADER_SIZE, 1, header_size - HEADER_SIZE, fd) != (size_t) (header_size - HEADER_SIZE)) { free(ptr); return RET(COMP_ERR_NOMEM); } memcpy(ptr, temp, HEADER_SIZE); header_size -= 4; if (CRC32(ptr, header_size, 0) != (unsigned) R4(header_size)) { free(ptr); return RET(COMP_ERR_BROKEN); } header_size += 4; /* blk = (unsigned *) malloc (sizeof (unsigned) * (1 + n_blk)); */ n = sizeof(unsigned) * (1 + n_blk); if (n < 4 * 1024 * 1024) n = 4 * 1024 * 1024; blk = (unsigned *) malloc(n); if (blk == 0) { free(ptr); return RET(COMP_ERR_NOMEM); } n = sizeof(info->crc[0]) * (1 + (check_crc ? (2 * n_blk) : 0)); n_u = sizeof(unsigned) * (2 + n_blk / (2 * SHORT_INDEX)); n_s = sizeof(unsigned short) * (1 + n_blk); if ((info = (decode_info *) malloc(sizeof(*info) + n + n_u + n_s)) == 0) { free(ptr); free(blk); return RET(COMP_ERR_NOMEM); } cbEGTBCompBytes += sizeof(*info) + n + n_s + n_u; info->crc = (unsigned *) (info + 1); if (check_crc) blk_u = info->blk_u = info->crc + 2 * n_blk; else blk_u = info->blk_u = info->crc; blk_s = info->blk_s = (unsigned short *) (blk_u + 2 + n_blk / (2 * SHORT_INDEX)); info->check_crc = check_crc; info->block_size_log = block_size_log; info->block_size = block_size; info->n_blk = n_blk; if (check_crc) { n_blk <<= 1; i = HEADER_SIZE; for (n = 0; n < n_blk; ++n) { info->crc[n] = R4(i); i += 4; } n_blk >>= 1; } i = HEADER_SIZE + (n_blk << 3); BIORD_START(ptr + i); info->comp_block_size = 0; for (n = 0; n <= n_blk; ++n) { if ((blk[n] = BIORD(block_size_log)) == 0) blk[n] = block_size; if (info->comp_block_size < (int) (blk[n])) info->comp_block_size = (int) (blk[n]); BIORD_MORE(block_size_log); } info->comp_block_size += 32; for (n = 0; n < MAX_DISTANCES; ++n) { info->distance[n] = -((int) BIORD(block_size_log)); BIORD_MORE(block_size_log); } i += ((n_blk + 1 + MAX_DISTANCES) * block_size_log + 7) >> 3; BIORD_START(ptr + i); BITIO_LEAVE(Bitio); if (huffman_read_length(&Bitio, temp, ALPHABET_SIZE) != 0) { free(blk); free(info); free(ptr); return RET(COMP_ERR_BROKEN); } if (huffman_decode_create(info->table, temp, ALPHABET_SIZE, START_BITS) != 0) { free(blk); free(info); free(ptr); return RET(COMP_ERR_BROKEN); } info->last_block_size = blk[n_blk]; blk[n_blk] = 0; for (n = 0; n <= n_blk; ++n) { i = blk[n]; blk[n] = header_size; header_size += i; if (0 == n % (2 * SHORT_INDEX)) blk_u[n / (2 * SHORT_INDEX)] = blk[n]; } blk_u[n_blk / (2 * SHORT_INDEX) + 1] = blk[n_blk]; for (n = 0; n <= n_blk; ++n) { i = n / (2 * SHORT_INDEX); if (n & SHORT_INDEX) blk_s[n] = blk_u[i + 1] - blk[n]; else blk_s[n] = blk[n] - blk_u[i]; } free(blk); free(ptr); info->comp = 0; info->magic = DECODE_MAGIC; *res = info; return (COMP_ERR_NONE); } static int comp_tell_blocks(decode_info * info) { if (info == 0 || info->magic != DECODE_MAGIC) return (-1); return (info->n_blk); } static int comp_init_block(decode_block * block, int block_size, uchar * orig) { if (block == 0) return RET(COMP_ERR_PARAM); block->orig.first = orig; block->comp.first = (uchar *) (block + 1); block->b.ptr = 0; block->b.decoded = -1; block->b.total = -1; block->b.number = -1; block->n = -1; block->magic = BLOCK_MAGIC; return (COMP_ERR_NONE); } static int comp_alloc_block(decode_block ** ret_block, int block_size) { decode_block *block; if (ret_block == 0) return RET(COMP_ERR_PARAM); *ret_block = 0; if ((block = (decode_block *) malloc(sizeof(*block) + block_size)) == 0) return RET(COMP_ERR_NOMEM); cbEGTBCompBytes += sizeof(*block) + block_size; if (0 != comp_init_block(block, block_size, NULL)) return RET(COMP_ERR_PARAM); *ret_block = block; return (COMP_ERR_NONE); } #define RETURN(n) \ return ((n) == COMP_ERR_NONE ? COMP_ERR_NONE : RET (n)); static int comp_read_block(decode_block * block, decode_info * info, FILE * fd, int n) { int comp_size, orig_size, comp_start; uchar *comp, *orig; if (block == 0 || block->magic != BLOCK_MAGIC) return RET(COMP_ERR_PARAM); assert(info->magic == DECODE_MAGIC); if ((unsigned) n >= (unsigned) info->n_blk) RETURN(COMP_ERR_PARAM); comp = block->comp.first; block->n = n; orig = block->orig.first; orig_size = info->block_size; if (n == info->n_blk - 1) orig_size = info->last_block_size; block->orig.size = orig_size; comp_start = calculate_offset(info, n); block->comp.size = comp_size = calculate_offset(info, n + 1) - comp_start; if (fseek(fd, comp_start, SEEK_SET) != 0) RETURN(COMP_ERR_READ); if (fread(comp, 1, comp_size, fd) != (size_t) comp_size) RETURN(COMP_ERR_READ); if (info->check_crc && info->crc[(n << 1) + 1] != CRC32(block->comp.first, comp_size, 0)) RETURN(COMP_ERR_BROKEN); block->emit.rept = 0; if (comp_size == orig_size) { memcpy(orig, comp, comp_size); block->emit.ptr = orig + comp_size; block->b.decoded = comp_size; } else { block->emit.ptr = orig; block->b.decoded = 0; } block->b.number = n; block->b.ptr = orig; block->b.total = orig_size; RETURN(COMP_ERR_NONE); } static int comp_decode_and_check_crc(decode_block * block, decode_info * info, int n, int check_crc) { if (block == 0 || block->magic != BLOCK_MAGIC) return RET(COMP_ERR_PARAM); assert(info->magic == DECODE_MAGIC); if ((unsigned) (n - 1) > (unsigned) (block->orig.size - 1)) RETURN(COMP_ERR_PARAM); if (check_crc) n = block->orig.size; do_decode(info, block, block->orig.first + n); block->b.ptr = block->orig.first; block->b.total = block->orig.size; if (block->b.decoded >= block->b.total) { if (block->b.decoded > block->b.total) RETURN(COMP_ERR_BROKEN); if (block->emit.rept != 0) RETURN(COMP_ERR_BROKEN); } if (check_crc && info->check_crc && info->crc[block->n << 1] != CRC32(block->orig.first, block->orig.size, 0)) RETURN(COMP_ERR_BROKEN); RETURN(COMP_ERR_NONE); } #if !defined (COLOR_DECLARED) /* Test driver */ #define CRC_CHECK 1 int main(int argc, char *argv[]) { int i; int size; int result; FILE *fp; decode_info *comp_info; decode_block *comp_block; clock_t tStart, tEnd; double dSeconds; uchar rgbBuf[8192 + 32]; if (2 != argc) { printf("Invalid arguments\n"); exit(1); } fp = fopen(argv[1], "rb"); if (0 == fp) { printf("Unable to open file\n"); exit(1); } result = comp_open_file(&comp_info, fp, CRC_CHECK); if (0 != result) { printf("Unable to read file (1): %d\n", result); exit(1); } if (8192 != comp_info->block_size) { printf("Invalid block size: %d\n", comp_info->block_size); exit(1); } result = comp_alloc_block(&comp_block, comp_info->block_size); if (0 != result) { printf("Unable to allocate block: %d\n", result); exit(1); } size = 0; tStart = clock(); for (i = 0; i < comp_info->n_blk; i++) { if (0 != (result = comp_init_block(comp_block, comp_info->block_size, rgbBuf))) { printf("Unable to init block: %d\n", result); exit(1); } if (0 != (result = comp_read_block(comp_block, comp_info, fp, i))) { printf("Unable to read block: %d\n", result); exit(1); } size += comp_block->orig.size; if (0 != (result = comp_decode_and_check_crc(comp_block, comp_info, comp_block->orig.size, CRC_CHECK))) { printf("Unable to decode block: %d\n", result); exit(1); } } tEnd = clock(); dSeconds = (double) (tEnd - tStart) / CLOCKS_PER_SEC; printf("Total memory allocated: %dKb\n", (cbEGTBCompBytes + 1023) / 1024); printf("%g seconds, %dMb, %gMb/sec)\n", dSeconds, size / (1024 * 1024), size / (1024 * 1024) / dSeconds); return 0; } #endif #endif