/* simple.c -- the annotated simple example program for the UCL library This file is part of the UCL real-time data compression library. Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer The UCL library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The UCL library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the UCL library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Markus F.X.J. Oberhumer markus.oberhumer@jk.uni-linz.ac.at */ /************************************************************************* This program shows the basic usage of the UCL library. We will compress a block of data and decompress again. **************************************************************************/ #include #include #include "../src/ucl_conf.h" #include "../src/getbit.h" int gs(int i) { static int v0=0, v1=0; if (i==-1) fprintf(stderr, "\nSTATS: (0,1)=(%d,%d)=(%f,%f) (jr:%d/i%d, jp:%d)\n", v0, v1, (double)v0/(double)(v0+v1), (double)v1/(double)(v0+v1), v0*7+v1*12, v1*7+v0*12, (v0+v1)*10); else { if (i==0) v0++; else v1++; } return i; } void adam_decompress(ucl_byte *src, ucl_uint src_len, ucl_byte *dst /*, ucl_uint *dst_len*/ ) { /* #define getbit(bb) \ (bb*=2,bb&0xff ? (bb>>8)&1 : ((bb=(src[ilen++]*2)|1)>>8)&1) */ /* #define getbit(bb) \ (bb&0x7f ? \ ((bb*=2)>>8)&1 : \ ((bb=(src[ilen++]*2)|1)>>8)&1) */ #define getbit(bb) \ ( ( ((bb) = (bb)&0x7f ? (bb)*2 : (src[ilen++]*2)|1) >> 8) & 1) ucl_uint bb = 0; ucl_uint ilen = 0, olen = 0, last_m_off = 1; for (;;) { ucl_uint m_off; ucl_uint m_len; while (/*gs*/(getbit(bb)) != 0) { /* note: short runs, ~0-9 bytes */ dst[olen] = src[ilen]; ilen += 1; olen += 1; } m_off = 1; do { m_off *= 2; if (m_off > 0xFFFF) /* if the shift just carried over 16 bits...! */ { fprintf(stderr, "TERM%x ", m_off); goto done; } m_off |= (getbit(bb)); } while ((getbit(bb)) == 0); if ((m_off == 2)) { m_off = last_m_off; } else { m_off -= 3; m_off *= 256; m_off |= src[ilen]; /* if (m_off == 0xffffffff) { fprintf(stderr, "TERMINATOR "); break; } */ ilen += 1; m_off += 1; last_m_off = m_off; } m_len = (getbit(bb)); m_len *= 2; m_len |= (getbit(bb)); if ((m_len == 0)) { m_len = 1; do { m_len *= 2; m_len |= (getbit(bb)); } while (!(getbit(bb))); m_len += 2; } if ((m_off > 0x0d00)) { m_len += 1; } { ucl_byte *m_pos; m_pos = dst; m_pos += olen; m_pos -= m_off; dst[olen] = *m_pos; m_pos += 1; olen += 1; /*fprintf(stderr, "%d'", m_len); */ /*gs(m_len == 1);*/ do { dst[olen] = *m_pos; m_pos += 1; olen += 1; m_len -= 1; } while (m_len > 0); } } /* *dst_len = olen; */ done: /* gs(-1); */ } /* We want to compress the data block at `in' with length `IN_LEN' to * the block at `out'. Because the input block may be incompressible, * we must provide a little more output space in case that compression * is not possible. */ #if 0 #ifndef IN_LEN /*#define IN_LEN (49920L) */ #define IN_LEN (6912L) /*#define IN_LEN (128*1024L) */ #endif #define OUT_LEN (IN_LEN + IN_LEN / 8 + 256) #endif /************************************************************************* **************************************************************************/ #include "lutil.h" int main(int argc, char *argv[]) { int r; ucl_byte *in; ucl_byte *out; ucl_uint in_len; ucl_uint out_len; ucl_uint IN_LEN; ucl_uint OUT_LEN; ucl_uint new_len; int level = 10; /* compression level (1-10) */ #if defined(__EMX__) _response(&argc,&argv); _wildcard(&argc,&argv); #endif if (argc < 0 && argv == NULL) /* avoid warning about unused args */ return 0; printf("\nUCL real-time data compression library (v%s, %s).\n", ucl_version_string(), ucl_version_date()); printf("Copyright (C) 1996,1997,1998,1999,2000 Markus Franz Xaver Johannes Oberhumer\n\n"); /* * Step 1: initialize the UCL library */ if (ucl_init() != UCL_E_OK) { printf("ucl_init() failed !!!\n"); return 4; } if (argc != 2) { printf("need single filename parameter.\n"); return 7; } /* * Step 2: allocate blocks */ { struct stat stat_buf; if (stat(argv[1], &stat_buf)) { printf("file not found: %s\n", argv[1]); return 8; } IN_LEN = stat_buf.st_size; OUT_LEN = (IN_LEN + IN_LEN / 8 + 256); } #define MAXSLOP 8192 in = ucl_malloc(IN_LEN+MAXSLOP); out = ucl_malloc(OUT_LEN+MAXSLOP); if (in == NULL || out == NULL) { printf("out of memory\n"); return 3; } /* * Step 3: prepare the input block that will get compressed. * We just fill it with zeros in this example program, * but you would use your real-world data here. */ in_len = IN_LEN; ucl_memset(in,'!',in_len); { FILE *fp; fp = fopen(argv[1], "rb"); fread(in, 1, in_len, fp); fclose(fp); } /* * Step 4: compress from `in' to `out' with UCL NRV2B */ r = ucl_nrv2b_99_compress(in,in_len,out,&out_len,NULL,level,NULL,NULL); if (r == UCL_E_OK) printf("compressed %lu bytes into %lu bytes\n", (long) in_len, (long) out_len); else { /* this should NEVER happen */ printf("internal error - compression failed: %d\n", r); return 2; } /* check for an incompressible block */ if (out_len >= in_len) { printf("This block contains uncompressible data. (may crash now)\n"); /* return 0; */ } { FILE *fp; fp = fopen("COMPR", "wb"); fwrite(out, 1, out_len, fp); fclose(fp); } /* * Step 5: decompress again, now going from `out' to `in' */ { int slop; ucl_memset(in,'?',in_len); for (slop = 0; slop <= MAXSLOP; slop++) { int offset = slop+(in_len - out_len); memcpy(&in[offset], out, out_len); new_len = in_len; r = ucl_nrv2b_test_overlap_8(in,offset,out_len,&new_len,NULL); /* fprintf(stderr, "(%d,%c,%d/%d/%d)", in[offset], in[0], offset, out_len, new_len); */ if (r == UCL_E_OK && new_len == in_len) { printf("decompressed %lu bytes back into %lu bytes,\n" "minimal nonoverlap slop is %d\n", (long) out_len, (long) in_len, slop); #if 0 ucl_nrv2b_decompress_8(&in[offset],out_len,in,&new_len,NULL); #else adam_decompress(out,out_len,in); #endif break; } if (slop == MAXSLOP) { printf("no luck with in-place decompression at any slop-value\n" " up to %d (error %d)\n", MAXSLOP, r); return 1; } } } { FILE *fp; char *val = malloc(in_len); ucl_memset(val,'!',in_len); fp = fopen(argv[1], "rb"); fread(val, 1, in_len, fp); fclose(fp); if (memcmp(val, in, in_len)) printf("UGH, bad verification.\n\007"); } { FILE *fp; fp = fopen("CYC", "wb"); fwrite(in, 1, in_len, fp); fclose(fp); } ucl_free(out); ucl_free(in); printf("Simple compression test passed.\n"); return 0; } /* vi:ts=4:et */