1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501 |
- /**************************************************************
- Form adapted from lzhuf.c
- written by Haruyasu Yoshizaki 11/20/1988
- some minor changes 4/6/1989
- comments translated by Haruhiko Okumura 4/7/1989
-
- minor beautifications and adjustments for compiling under Linux
- by Markus Gutschke <gutschk@math.uni-muenster.de>
- 1997-01-27
-
- Modifications to allow use as a filter by Ken Yap
- <ken_yap@users.sourceforge.net>.
-
- 1997-07-01
-
- Small mod to cope with running on big-endian machines
- by Jim Hague <jim.hague@acm.org)
- 1998-02-06
-
- Make compression statistics report shorter
- by Ken Yap <ken_yap@users.sourceforge.net>.
- 2001-04-25
-
- Replaced algorithm with nrv2b from ucl the compression
- library from upx. That code is:
- Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
- And is distributed under the terms of the GPL.
- The conversion was performed
- by Eric Biederman <ebiederman@lnxi.com>.
- 20 August 2002
-
- **************************************************************/
- #define UCLPACK_COMPAT 0
- #define NDEBUG 1
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <errno.h>
- #ifdef __FreeBSD__
- #include <inttypes.h>
- #else
- #include <stdint.h>
- #endif
- #include <limits.h>
- #include <assert.h>
- #if UCLPACK_COMPAT
- #include <netinet/in.h>
- #endif
-
- #ifndef VERBOSE
- #define Fprintf(x)
- #define wterr 0
- #else
- #define Fprintf(x) fprintf x
- #endif
-
- #ifndef MAIN
- extern
- #endif
- FILE *infile, *outfile;
-
- #if defined(ENCODE) || defined(DECODE)
-
- #ifndef ENDIAN
- #define ENDIAN 0
- #endif
- #ifndef BITSIZE
- #define BITSIZE 32
- #endif
-
- static __inline__ void Error(char *message)
- {
- Fprintf((stderr, "\n%s\n", message));
- exit(EXIT_FAILURE);
- }
-
- /* These will be a complete waste of time on a lo-endian */
- /* system, but it only gets done once so WTF. */
- static unsigned long i86ul_to_host(unsigned long ul)
- {
- unsigned long res = 0;
- int i;
- union
- {
- unsigned char c[4];
- unsigned long ul;
- } u;
-
- u.ul = ul;
- for (i = 3; i >= 0; i--)
- res = (res << 8) + u.c[i];
- return res;
- }
-
- static unsigned long host_to_i86ul(unsigned long ul)
- {
- int i;
- union
- {
- unsigned char c[4];
- unsigned long ul;
- } u;
-
- for (i = 0; i < 4; i++)
- {
- u.c[i] = ul & 0xff;
- ul >>= 8;
- }
- return u.ul;
- }
- #endif
-
-
-
- #if UCLPACK_COMPAT
- /* magic file header for compressed files */
- static const unsigned char magic[8] =
- { 0x00, 0xe9, 0x55, 0x43, 0x4c, 0xff, 0x01, 0x1a };
-
- #endif
-
- #ifdef ENCODE
- /********** NRV2B_99 compression **********/
-
- /* Note by limiting the ring buffer I have limited the maximum
- * offset to 64K. Since etherboot rarely gets that big it
- * is not a problem and it gives me a firm guarantee
- * that I will never get a 3 byte string match that is encodes
- * to more than 9/8 it's original size.
- * That guaranteee is important to for the inplace decompressor.
- * There are better ways to do this if a larger offset and buffer
- * would give better compression.
- */
- #define N (65536ul) /* size of ring buffer */
- #define THRESHOLD 1 /* lower limit for match length */
- #define F 2048 /* upper limit for match length */
- #define M2_MAX_OFFSET 0xd00
-
- /* note: to use default values pass -1, i.e. initialize
- * this struct by a memset(x,0xff,sizeof(x)) */
- struct ucl_compress_config
- {
- int bb_endian;
- int bb_size;
- unsigned int max_offset;
- unsigned int max_match;
- int s_level;
- int h_level;
- int p_level;
- int c_flags;
- unsigned int m_size;
- };
-
- struct ucl_compress
- {
- int init;
-
- unsigned int look; /* bytes in lookahead buffer */
-
- unsigned int m_len;
- unsigned int m_off;
-
- unsigned int last_m_len;
- unsigned int last_m_off;
-
- const unsigned char *bp;
- const unsigned char *ip;
- const unsigned char *in;
- const unsigned char *in_end;
- unsigned char *out;
-
- uint64_t bb_b;
- unsigned bb_k;
- unsigned bb_c_endian;
- unsigned bb_c_s;
- unsigned bb_c_s8;
- unsigned char *bb_p;
- unsigned char *bb_op;
-
- struct ucl_compress_config conf;
- unsigned int *result;
-
- unsigned int textsize; /* text size counter */
- unsigned int codesize; /* code size counter */
- unsigned int printcount; /* counter for reporting progress every 1K
- bytes */
-
-
- /* some stats */
- unsigned long lit_bytes;
- unsigned long match_bytes;
- unsigned long rep_bytes;
- unsigned long lazy;
- };
-
-
-
- #define getbyte(c) ((c).ip < (c).in_end ? *((c).ip)++ : (-1))
-
- #define UCL_E_OK 0
- #define UCL_E_INVALID_ARGUMENT 1
- #define UCL_E_OUT_OF_MEMORY 2
- #define UCL_E_ERROR 3
-
- /***********************************************************************
- //
- ************************************************************************/
-
- #define SWD_HSIZE 16384
- #define SWD_MAX_CHAIN 2048
- #define SWD_BEST_OFF 1
-
- #define HEAD3(b,p) \
- (((0x9f5f*(((((uint32_t)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & (SWD_HSIZE-1))
-
- #define HEAD2(b,p) (b[p] ^ ((unsigned)b[p+1]<<8))
- #define NIL2 UINT_MAX
-
- struct ucl_swd
- {
- /* public - "built-in" */
- unsigned int n;
- unsigned int f;
- unsigned int threshold;
-
- /* public - configuration */
- unsigned int max_chain;
- unsigned int nice_length;
- int use_best_off;
- unsigned int lazy_insert;
-
- /* public - output */
- unsigned int m_len;
- unsigned int m_off;
- unsigned int look;
- int b_char;
- #if defined(SWD_BEST_OFF)
- unsigned int best_off[ SWD_BEST_OFF ];
- #endif
-
- /* semi public */
- struct ucl_compress *c;
- unsigned int m_pos;
- #if defined(SWD_BEST_OFF)
- unsigned int best_pos[ SWD_BEST_OFF ];
- #endif
-
- /* private */
- const uint8_t *dict;
- const uint8_t *dict_end;
- unsigned int dict_len;
-
- /* private */
- unsigned int ip; /* input pointer (lookahead) */
- unsigned int bp; /* buffer pointer */
- unsigned int rp; /* remove pointer */
- unsigned int b_size;
-
- unsigned char *b_wrap;
-
- unsigned int node_count;
- unsigned int first_rp;
-
- unsigned char b [ N + F + F ];
- unsigned int head3 [ SWD_HSIZE ];
- unsigned int succ3 [ N + F ];
- unsigned int best3 [ N + F ];
- unsigned int llen3 [ SWD_HSIZE ];
- unsigned int head2 [ 65536U ];
- };
-
- #define s_head3(s,key) s->head3[key]
-
-
- #if !defined( NDEBUG)
- static void assert_match(const struct ucl_swd * swd, unsigned int m_len,
- unsigned int m_off )
-
- {
- const struct ucl_compress *c = swd->c;
- unsigned int d_off;
-
- assert(m_len >= 2);
- if (m_off <= (unsigned int) (c->bp - c->in))
- {
- assert(c->bp - m_off + m_len < c->ip);
- assert(memcmp(c->bp, c->bp - m_off, m_len) == 0);
- }
- else
- {
- assert(swd->dict != NULL);
- d_off = m_off - (unsigned int) (c->bp - c->in);
- assert(d_off <= swd->dict_len);
- if (m_len > d_off)
- {
- assert(memcmp(c->bp, swd->dict_end - d_off, d_off) ==
- 0);
-
- assert(c->in + m_len - d_off < c->ip);
- assert(memcmp(c->bp + d_off, c->in, m_len - d_off) ==
- 0);
-
- }
- else
- {
- assert(memcmp(c->bp, swd->dict_end - d_off, m_len) ==
- 0);
-
- }
- }
- }
- #else
- # define assert_match(a,b,c) ((void)0)
- #endif
-
- /***********************************************************************
- //
- ************************************************************************/
-
-
- static
- void swd_initdict(struct ucl_swd *s, const uint8_t *dict, unsigned int dict_len)
-
- {
- s->dict = s->dict_end = NULL;
- s->dict_len = 0;
-
- if (!dict || dict_len <= 0)
- return;
- if (dict_len > s->n)
- {
- dict += dict_len - s->n;
- dict_len = s->n;
- }
-
- s->dict = dict;
- s->dict_len = dict_len;
- s->dict_end = dict + dict_len;
- memcpy(s->b,dict,dict_len);
- s->ip = dict_len;
- }
-
-
- static
- void swd_insertdict(struct ucl_swd *s, unsigned int node, unsigned int len)
- {
- unsigned int key;
-
- s->node_count = s->n - len;
- s->first_rp = node;
-
- while (len-- > 0)
- {
- key = HEAD3(s->b,node);
- s->succ3[node] = s_head3(s,key);
- s->head3[key] = (unsigned int)(node);
- s->best3[node] = (unsigned int)(s->f + 1);
- s->llen3[key]++;
- assert(s->llen3[key] <= s->n);
-
- key = HEAD2(s->b,node);
- s->head2[key] = (unsigned int)(node);
-
- node++;
- }
- }
-
- /***********************************************************************
- //
- ************************************************************************/
-
-
- static
- int swd_init(struct ucl_swd *s, const uint8_t *dict, unsigned int dict_len)
- {
- unsigned int i = 0;
- int c = 0;
-
- if (s->n == 0)
- s->n = N;
- if (s->f == 0)
- s->f = F;
- s->threshold = THRESHOLD;
- if (s->n > N || s->f > F)
- return UCL_E_INVALID_ARGUMENT;
-
- /* defaults */
- s->max_chain = SWD_MAX_CHAIN;
- s->nice_length = s->f;
- s->use_best_off = 0;
- s->lazy_insert = 0;
-
- s->b_size = s->n + s->f;
- if (s->b_size + s->f >= UINT_MAX)
- return UCL_E_ERROR;
- s->b_wrap = s->b + s->b_size;
- s->node_count = s->n;
-
- memset(s->llen3, 0, sizeof(s->llen3[0]) * SWD_HSIZE);
- for (i = 0; i < 65536U; i++)
- s->head2[i] = NIL2;
-
- s->ip = 0;
- swd_initdict(s,dict,dict_len);
- s->bp = s->ip;
- s->first_rp = s->ip;
-
- assert(s->ip + s->f <= s->b_size);
-
- s->look = (unsigned int) (s->c->in_end - s->c->ip);
- if (s->look > 0)
- {
- if (s->look > s->f)
- s->look = s->f;
- memcpy(&s->b[s->ip],s->c->ip,s->look);
- s->c->ip += s->look;
- s->ip += s->look;
- }
- if (s->ip == s->b_size)
- s->ip = 0;
-
- if (s->look >= 2 && s->dict_len > 0)
- swd_insertdict(s,0,s->dict_len);
-
- s->rp = s->first_rp;
- if (s->rp >= s->node_count)
- s->rp -= s->node_count;
- else
- s->rp += s->b_size - s->node_count;
-
- /* unused i */
- /* unused c */
- return UCL_E_OK;
- }
-
-
- static
- void swd_exit(struct ucl_swd *s)
- {
- /* unused s */
-
- }
-
- #define swd_pos2off(s,pos) \
- (s->bp > (pos) ? s->bp - (pos) : s->b_size - ((pos) - s->bp))
-
- /***********************************************************************
- //
- ************************************************************************/
-
- static __inline__
- void swd_getbyte(struct ucl_swd *s)
- {
- int c;
-
- if ((c = getbyte(*(s->c))) < 0)
- {
- if (s->look > 0)
- --s->look;
- }
- else
- {
- s->b[s->ip] = (uint8_t)(c);
- if (s->ip < s->f)
- s->b_wrap[s->ip] = (uint8_t)(c);
- }
- if (++s->ip == s->b_size)
- s->ip = 0;
- if (++s->bp == s->b_size)
- s->bp = 0;
- if (++s->rp == s->b_size)
- s->rp = 0;
- }
- /***********************************************************************
- // remove node from lists
- ************************************************************************/
-
- static __inline__
- void swd_remove_node(struct ucl_swd *s, unsigned int node)
- {
- if (s->node_count == 0)
- {
- unsigned int key;
-
- #ifdef UCL_DEBUG
- if (s->first_rp != UINT_MAX)
- {
- if (node != s->first_rp)
- printf("Remove %5d: %5d %5d %5d %5d %6d %6d\n",
-
- node, s->rp, s->ip, s->bp, s->first_rp,
- s->ip - node, s->ip - s->bp);
- assert(node == s->first_rp);
- s->first_rp = UINT_MAX;
- }
- #endif
-
- key = HEAD3(s->b,node);
- assert(s->llen3[key] > 0);
- --s->llen3[key];
-
- key = HEAD2(s->b,node);
- assert(s->head2[key] != NIL2);
- if ((unsigned int) s->head2[key] == node)
- s->head2[key] = NIL2;
- }
- else
- --s->node_count;
- }
-
-
- /***********************************************************************
- //
- ************************************************************************/
-
-
- static
- void swd_accept(struct ucl_swd *s, unsigned int n)
- {
- assert(n <= s->look);
-
- if (n > 0) do
- {
- unsigned int key;
-
- swd_remove_node(s,s->rp);
-
- /* add bp into HEAD3 */
- key = HEAD3(s->b,s->bp);
- s->succ3[s->bp] = s_head3(s,key);
- s->head3[key] = (unsigned int)(s->bp);
- s->best3[s->bp] = (unsigned int)(s->f + 1);
- s->llen3[key]++;
- assert(s->llen3[key] <= s->n);
-
- /* add bp into HEAD2 */
- key = HEAD2(s->b,s->bp);
- s->head2[key] = (unsigned int)(s->bp);
-
- swd_getbyte(s);
- } while (--n > 0);
- }
-
- /***********************************************************************
- //
- ************************************************************************/
-
- static
- void swd_search(struct ucl_swd *s, unsigned int node, unsigned int cnt)
- {
- const unsigned char *p1;
- const unsigned char *p2;
- const unsigned char *px;
-
- unsigned int m_len = s->m_len;
- const unsigned char * b = s->b;
- const unsigned char * bp = s->b + s->bp;
- const unsigned char * bx = s->b + s->bp + s->look;
- unsigned char scan_end1;
-
- assert(s->m_len > 0);
-
- scan_end1 = bp[m_len - 1];
- for ( ; cnt-- > 0; node = s->succ3[node])
- {
- p1 = bp;
- p2 = b + node;
- px = bx;
-
- assert(m_len < s->look);
-
- if (
- p2[m_len - 1] == scan_end1 &&
- p2[m_len] == p1[m_len] &&
- p2[0] == p1[0] &&
- p2[1] == p1[1])
- {
- unsigned int i;
- assert(memcmp(bp,&b[node],3) == 0);
-
- p1 += 2; p2 += 2;
- do {} while (++p1 < px && *p1 == *++p2);
- i = p1 - bp;
-
- #ifdef UCL_DEBUG
- if (memcmp(bp,&b[node],i) != 0)
- printf("%5ld %5ld %02x%02x %02x%02x\n",
- (long)s->bp, (long) node,
- bp[0], bp[1], b[node], b[node+1]);
- #endif
- assert(memcmp(bp,&b[node],i) == 0);
-
- #if defined(SWD_BEST_OFF)
- if (i < SWD_BEST_OFF)
- {
- if (s->best_pos[i] == 0)
- s->best_pos[i] = node + 1;
- }
- #endif
- if (i > m_len)
- {
- s->m_len = m_len = i;
- s->m_pos = node;
- if (m_len == s->look)
- return;
- if (m_len >= s->nice_length)
- return;
- if (m_len > (unsigned int) s->best3[node])
- return;
- scan_end1 = bp[m_len - 1];
- }
- }
- }
- }
-
- static int swd_search2(struct ucl_swd *s)
- {
- unsigned int key;
-
- assert(s->look >= 2);
- assert(s->m_len > 0);
-
- key = s->head2[ HEAD2(s->b,s->bp) ];
- if (key == NIL2)
- return 0;
- #ifdef UCL_DEBUG
- if (memcmp(&s->b[s->bp],&s->b[key],2) != 0)
- printf("%5ld %5ld %02x%02x %02x%02x\n", (long)s->bp, (long)key,
- s->b[s->bp], s->b[s->bp+1], s->b[key], s->b[key+1]);
- #endif
- assert(memcmp(&s->b[s->bp],&s->b[key],2) == 0);
- #if defined(SWD_BEST_OFF)
- if (s->best_pos[2] == 0)
- s->best_pos[2] = key + 1;
- #endif
-
- if (s->m_len < 2)
- {
- s->m_len = 2;
- s->m_pos = key;
- }
- return 1;
- }
-
- /***********************************************************************
- //
- ************************************************************************/
-
- static
- void swd_findbest(struct ucl_swd *s)
- {
- unsigned int key;
- unsigned int cnt, node;
- unsigned int len;
-
- assert(s->m_len > 0);
-
- /* get current head, add bp into HEAD3 */
- key = HEAD3(s->b,s->bp);
- node = s->succ3[s->bp] = s_head3(s,key);
- cnt = s->llen3[key]++;
- assert(s->llen3[key] <= s->n + s->f);
- if (cnt > s->max_chain && s->max_chain > 0)
- cnt = s->max_chain;
- s->head3[key] = (unsigned int)(s->bp);
-
- s->b_char = s->b[s->bp];
- len = s->m_len;
- if (s->m_len >= s->look)
- {
- if (s->look == 0)
- s->b_char = -1;
- s->m_off = 0;
- s->best3[s->bp] = (unsigned int)(s->f + 1);
- }
- else
- {
- if (swd_search2(s))
- if (s->look >= 3)
- swd_search(s,node,cnt);
- if (s->m_len > len)
- s->m_off = swd_pos2off(s,s->m_pos);
- s->best3[s->bp] = (unsigned int)(s->m_len);
-
- #if defined(SWD_BEST_OFF)
- if (s->use_best_off)
- {
- int i;
- for (i = 2; i < SWD_BEST_OFF; i++)
- if (s->best_pos[i] > 0)
- s->best_off[i] =
- swd_pos2off(s,s->best_pos[i]-1);
-
- else
- s->best_off[i] = 0;
- }
- #endif
- }
-
- swd_remove_node(s,s->rp);
-
- /* add bp into HEAD2 */
- key = HEAD2(s->b,s->bp);
- s->head2[key] = (unsigned int)(s->bp);
- }
-
-
- /***********************************************************************
- //
- ************************************************************************/
-
- static int
- init_match ( struct ucl_compress *c, struct ucl_swd *s,
- const uint8_t *dict, unsigned int dict_len,
- uint32_t flags )
- {
- int r;
-
- assert(!c->init);
- c->init = 1;
-
- s->c = c;
-
- c->last_m_len = c->last_m_off = 0;
-
- c->textsize = c->codesize = c->printcount = 0;
- c->lit_bytes = c->match_bytes = c->rep_bytes = 0;
- c->lazy = 0;
-
- r = swd_init(s,dict,dict_len);
- if (r != UCL_E_OK)
- {
- swd_exit(s);
- return r;
- }
-
- s->use_best_off = (flags & 1) ? 1 : 0;
- return UCL_E_OK;
- }
-
- static int
- find_match ( struct ucl_compress *c, struct ucl_swd *s,
- unsigned int this_len, unsigned int skip )
- {
- assert(c->init);
-
- if (skip > 0)
- {
- assert(this_len >= skip);
- swd_accept(s, this_len - skip);
- c->textsize += this_len - skip + 1;
- }
- else
- {
- assert(this_len <= 1);
- c->textsize += this_len - skip;
- }
-
- s->m_len = THRESHOLD;
- #ifdef SWD_BEST_OFF
- if (s->use_best_off)
- memset(s->best_pos,0,sizeof(s->best_pos));
- #endif
- swd_findbest(s);
- c->m_len = s->m_len;
- c->m_off = s->m_off;
-
- swd_getbyte(s);
-
- if (s->b_char < 0)
- {
- c->look = 0;
- c->m_len = 0;
- swd_exit(s);
- }
- else
- {
- c->look = s->look + 1;
- }
- c->bp = c->ip - c->look;
-
- #if 0
- /* brute force match search */
- if (c->m_len > THRESHOLD && c->m_len + 1 <= c->look)
- {
- const uint8_t *ip = c->bp;
- const uint8_t *m = c->bp - c->m_off;
- const uint8_t *in = c->in;
-
- if (ip - in > N)
- in = ip - N;
- for (;;)
- {
- while (*in != *ip)
- in++;
- if (in == ip)
- break;
- if (in != m)
- if (memcmp(in,ip,c->m_len+1) == 0)
- printf("%p %p %p %5d\n",in,ip,m,c->m_len);
-
- in++;
- }
- }
- #endif
-
- return UCL_E_OK;
- }
-
-
- static int bbConfig(struct ucl_compress *c, int endian, int bitsize)
- {
- if (endian != -1)
- {
- if (endian != 0)
- return UCL_E_ERROR;
- c->bb_c_endian = endian;
- }
- if (bitsize != -1)
- {
- if (bitsize != 8 && bitsize != 16 && bitsize != 32 && bitsize != 64)
- return UCL_E_ERROR;
- c->bb_c_s = bitsize;
- c->bb_c_s8 = bitsize / 8;
- }
- c->bb_b = 0; c->bb_k = 0;
- c->bb_p = NULL;
- c->bb_op = NULL;
- return UCL_E_OK;
- }
-
- static void bbWriteBits(struct ucl_compress *c)
- {
- uint8_t *p = c->bb_p;
- uint64_t b = c->bb_b;
-
- p[0] = (uint8_t)(b >> 0);
- if (c->bb_c_s >= 16)
- {
- p[1] = (uint8_t)(b >> 8);
- if (c->bb_c_s >= 32)
- {
- p[2] = (uint8_t)(b >> 16);
- p[3] = (uint8_t)(b >> 24);
- if (c->bb_c_s == 64)
- {
- p[4] = (uint8_t)(b >> 32);
- p[5] = (uint8_t)(b >> 40);
- p[6] = (uint8_t)(b >> 48);
- p[7] = (uint8_t)(b >> 56);
- }
- }
- }
- }
-
-
- static void bbPutBit(struct ucl_compress *c, unsigned bit)
- {
- assert(bit == 0 || bit == 1);
- assert(c->bb_k <= c->bb_c_s);
-
- if (c->bb_k < c->bb_c_s)
- {
- if (c->bb_k == 0)
- {
- assert(c->bb_p == NULL);
- c->bb_p = c->bb_op;
- c->bb_op += c->bb_c_s8;
- }
- assert(c->bb_p != NULL);
- assert(c->bb_p + c->bb_c_s8 <= c->bb_op);
-
- c->bb_b = (c->bb_b << 1) + bit;
- c->bb_k++;
- }
- else
- {
- assert(c->bb_p != NULL);
- assert(c->bb_p + c->bb_c_s8 <= c->bb_op);
-
- bbWriteBits(c);
- c->bb_p = c->bb_op;
- c->bb_op += c->bb_c_s8;
- c->bb_b = bit;
- c->bb_k = 1;
- }
- }
-
-
- static void bbPutByte(struct ucl_compress *c, unsigned b)
- {
- /**printf("putbyte %p %p %x (%d)\n", op, bb_p, x, bb_k);*/
- assert(c->bb_p == NULL || c->bb_p + c->bb_c_s8 <= c->bb_op);
- *c->bb_op++ = (uint8_t)(b);
- }
-
- static void bbFlushBits(struct ucl_compress *c, unsigned filler_bit)
- {
- if (c->bb_k > 0)
- {
- assert(c->bb_k <= c->bb_c_s);
- while (c->bb_k != c->bb_c_s)
- bbPutBit(c, filler_bit);
- bbWriteBits(c);
- c->bb_k = 0;
- }
- c->bb_p = NULL;
- }
-
-
-
- /***********************************************************************
- //
- ************************************************************************/
-
-
- static void code_prefix_ss11(struct ucl_compress *c, uint32_t i)
- {
- if (i >= 2)
- {
- uint32_t t = 4;
- i += 2;
- do {
- t <<= 1;
- } while (i >= t);
- t >>= 1;
- do {
- t >>= 1;
- bbPutBit(c, (i & t) ? 1 : 0);
- bbPutBit(c, 0);
- } while (t > 2);
- }
- bbPutBit(c, (unsigned)i & 1);
- bbPutBit(c, 1);
- }
-
- static void
- code_match(struct ucl_compress *c, unsigned int m_len, const unsigned int m_off)
-
- {
- while (m_len > c->conf.max_match)
- {
- code_match(c, c->conf.max_match - 3, m_off);
- m_len -= c->conf.max_match - 3;
- }
-
- c->match_bytes += m_len;
- if (m_len > c->result[3])
- c->result[3] = m_len;
- if (m_off > c->result[1])
- c->result[1] = m_off;
-
- bbPutBit(c, 0);
-
- if (m_off == c->last_m_off)
- {
- bbPutBit(c, 0);
- bbPutBit(c, 1);
- }
- else
- {
- code_prefix_ss11(c, 1 + ((m_off - 1) >> 8));
- bbPutByte(c, (unsigned)m_off - 1);
- }
- m_len = m_len - 1 - (m_off > M2_MAX_OFFSET);
- if (m_len >= 4)
- {
- bbPutBit(c,0);
- bbPutBit(c,0);
- code_prefix_ss11(c, m_len - 4);
- }
- else
- {
- bbPutBit(c, m_len > 1);
- bbPutBit(c, (unsigned)m_len & 1);
- }
-
- c->last_m_off = m_off;
- }
-
- static void
- code_run(struct ucl_compress *c, const uint8_t *ii, unsigned int lit)
- {
- if (lit == 0)
- return;
- c->lit_bytes += lit;
- if (lit > c->result[5])
- c->result[5] = lit;
- do {
- bbPutBit(c, 1);
- bbPutByte(c, *ii++);
- } while (--lit > 0);
- }
-
- /***********************************************************************
- //
- ************************************************************************/
-
- static int
- len_of_coded_match(struct ucl_compress *c, unsigned int m_len, unsigned int
- m_off)
-
- {
- int b;
- if (m_len < 2 || (m_len == 2 && (m_off > M2_MAX_OFFSET))
- || m_off > c->conf.max_offset)
- return -1;
- assert(m_off > 0);
-
- m_len = m_len - 2 - (m_off > M2_MAX_OFFSET);
-
- if (m_off == c->last_m_off)
- b = 1 + 2;
- else
- {
- b = 1 + 10;
- m_off = (m_off - 1) >> 8;
- while (m_off > 0)
- {
- b += 2;
- m_off >>= 1;
- }
- }
-
- b += 2;
- if (m_len < 3)
- return b;
- m_len -= 3;
-
- do {
- b += 2;
- m_len >>= 1;
- } while (m_len > 0);
-
- return b;
- }
-
- int ucl_nrv2b_99_compress(
- const uint8_t *in, unsigned long in_len,
- uint8_t *out, unsigned long *out_len,
- unsigned int *result)
- {
- const uint8_t *ii;
- unsigned int lit;
- unsigned int m_len, m_off;
- struct ucl_compress c_buffer;
- struct ucl_compress * const c = &c_buffer;
- struct ucl_swd *swd;
- unsigned int result_buffer[16];
- int r;
-
- /* max compression */
- #define SC_TRY_LAZY 2
- #define SC_GOOD_LENGTH F
- #define SC_MAX_LAZY F
- #define SC_NICE_LENGTH F
- #define SC_MAX_CHAIN 4096
- #define SC_FLAGS 1
- #define SC_MAX_OFFSET N
-
- memset(c, 0, sizeof(*c));
- c->ip = c->in = in;
- c->in_end = in + in_len;
- c->out = out;
- c->result = result ? result : result_buffer;
- memset(c->result, 0, 16*sizeof(*c->result));
- c->result[0] = c->result[2] = c->result[4] = UINT_MAX;
- result = NULL;
- memset(&c->conf, 0xff, sizeof(c->conf));
- r = bbConfig(c, ENDIAN, BITSIZE);
- if (r == 0)
- r = bbConfig(c, c->conf.bb_endian, c->conf.bb_size);
- if (r != 0)
- return UCL_E_INVALID_ARGUMENT;
- c->bb_op = out;
-
- ii = c->ip; /* point to start of literal run */
- lit = 0;
-
-
- swd = (struct ucl_swd *) malloc(sizeof(*swd));
- if (!swd)
- return UCL_E_OUT_OF_MEMORY;
-
- swd->f = F;
- swd->n = N;
- if (in_len >= 256 && in_len < swd->n)
- swd->n = in_len;
- if (swd->f < 8 || swd->n < 256)
- return UCL_E_INVALID_ARGUMENT;
-
- r = init_match(c,swd,NULL,0, SC_FLAGS);
- if (r != UCL_E_OK)
- {
- free(swd);
- return r;
- }
- if (SC_MAX_CHAIN > 0)
- swd->max_chain = SC_MAX_CHAIN;
- if (SC_NICE_LENGTH > 0)
- swd->nice_length = SC_NICE_LENGTH;
- if (c->conf.max_match < swd->nice_length)
- swd->nice_length = c->conf.max_match;
-
- c->last_m_off = 1;
- r = find_match(c,swd,0,0);
- if (r != UCL_E_OK)
- return r;
- while (c->look > 0)
- {
- unsigned int ahead;
- unsigned int max_ahead;
- int l1, l2;
-
- c->codesize = c->bb_op - out;
-
- m_len = c->m_len;
- m_off = c->m_off;
-
- assert(c->bp == c->ip - c->look);
- assert(c->bp >= in);
- if (lit == 0)
- ii = c->bp;
- assert(ii + lit == c->bp);
- assert(swd->b_char == *(c->bp));
-
- if (m_len < 2 || (m_len == 2 && (m_off > M2_MAX_OFFSET))
- || m_off > c->conf.max_offset)
- {
- /* a literal */
- lit++;
- swd->max_chain = SC_MAX_CHAIN;
- r = find_match(c,swd,1,0);
- assert(r == 0);
- continue;
- }
-
- /* a match */
- assert_match(swd,m_len,m_off);
-
- /* shall we try a lazy match ? */
- ahead = 0;
- if (SC_TRY_LAZY <= 0 || m_len >= SC_MAX_LAZY || m_off ==
- c->last_m_off)
-
- {
- /* no */
- l1 = 0;
- max_ahead = 0;
- }
- else
- {
- /* yes, try a lazy match */
- l1 = len_of_coded_match(c,m_len,m_off);
- assert(l1 > 0);
- max_ahead = SC_TRY_LAZY;
- if ((m_len - 1) < max_ahead) {
- max_ahead = m_len -1;
- }
- }
-
- while (ahead < max_ahead && c->look > m_len)
- {
- if (m_len >= SC_GOOD_LENGTH)
- swd->max_chain = SC_MAX_CHAIN >> 2;
- else
- swd->max_chain = SC_MAX_CHAIN;
- r = find_match(c,swd,1,0);
- ahead++;
-
- assert(r == 0);
- assert(c->look > 0);
- assert(ii + lit + ahead == c->bp);
-
- if (c->m_len < 2)
- continue;
- l2 = len_of_coded_match(c,c->m_len,c->m_off);
- if (l2 < 0)
- continue;
- if (l1 + (int)(ahead + c->m_len - m_len) * 5 > l2 +
- (int)(ahead) * 9)
- {
- c->lazy++;
- assert_match(swd,c->m_len,c->m_off);
- lit += ahead;
- assert(ii + lit == c->bp);
- goto lazy_match_done;
- }
- }
-
- assert(ii + lit + ahead == c->bp);
-
- /* 1 - code run */
- code_run(c,ii,lit);
- lit = 0;
-
- /* 2 - code match */
- code_match(c,m_len,m_off);
- swd->max_chain = SC_MAX_CHAIN;
- r = find_match(c,swd,m_len,1+ahead);
- assert(r == 0);
-
- lazy_match_done: ;
- }
-
- /* store final run */
- code_run(c,ii,lit);
-
- /* EOF */
- bbPutBit(c, 0);
- code_prefix_ss11(c, 0x1000000U);
- bbPutByte(c, 0xff);
-
- bbFlushBits(c, 0);
-
- assert(c->textsize == in_len);
- c->codesize = c->bb_op - out;
- *out_len = c->bb_op - out;
-
- #if 0
- printf("%7ld %7ld -> %7ld %7ld %7ld %ld (max: %d %d %d)\n",
- (long) c->textsize, (long) in_len, (long) c->codesize,
- c->match_bytes, c->lit_bytes, c->lazy,
- c->result[1], c->result[3], c->result[5]);
- #endif
- assert(c->lit_bytes + c->match_bytes == in_len);
-
- swd_exit(swd);
- free(swd);
-
- return UCL_E_OK;
- }
-
-
- void Encode(void) /* compression */
- {
- uint8_t *in, *out;
- unsigned long in_len, out_len;
- uint32_t tw;
- int r;
- fseek(infile, 0, SEEK_END);
- in_len = ftell(infile);
- #ifdef VERBOSE
- if ((signed long)in_len < 0)
- Fprintf((stderr, "Errno: %d", errno));
- #endif
- #if UCLPACK_COMPAT
- {
- uint8_t byte;
- if (fwrite(magic, sizeof(magic), 1, outfile) != 1)
- Error("Can't write.");
- tw = htonl(0); /* flags */
- if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
- Error("Can't write.");
- byte = 0x2b; /* method */
- if (fwrite(&byte, sizeof(byte), 1, outfile) != 1)
- Error("Can't write.");
- byte = 10; /* level */
- if (fwrite(&byte, sizeof(byte), 1, outfile) != 1)
- Error("Can't write.");
- tw = htonl(256*1024); /* block_size */
- if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
- Error("Can't write.");
- tw = htonl(in_len);
- if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
- Error("Can't write."); /* output size of text */
- }
- #else
- tw = host_to_i86ul(in_len);
- if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
- Error("Can't write."); /* output size of text */
- #endif
- if (in_len == 0)
- return;
- rewind(infile);
-
- in = malloc(in_len);
- out_len = in_len + (in_len/8) + 256;
- out = malloc(out_len);
- if (!in || !out) {
- Error("Can't malloc");
- }
- if (fread(in, in_len, 1, infile) != 1) {
- Error("Can't read");
- }
- r = ucl_nrv2b_99_compress(in, in_len, out, &out_len, 0 );
- if (r != UCL_E_OK)
- Error("Compression failure\n");
- #if UCLPACK_COMPAT
- tw = htonl(out_len);
- if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
- Error("Can't write."); /* file size of text */
-
- #endif
- if (fwrite(out, out_len, 1, outfile) != 1) {
- Error("Write error\n");
- }
- #if UCLPACK_COMPAT
- tw = htonl(0); /* EOF marker */
- if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
- Error("Can't write.");
-
- #endif
-
- #ifdef LONG_REPORT
- Fprintf((stdout, "input size %ld bytes\n", in_len));
- Fprintf((stdout, "output size %ld bytes\n", out_len));
- Fprintf((stdout, "input/output %.3f\n", (double)in_len / out_len));
- #else
- Fprintf((stdout, "input/output = %ld/%ld = %.3f\n", in_len, out_len,
- (double)in_len / out_len));
- #endif
-
- }
-
- #endif
-
- #ifdef DECODE
-
- #define GETBIT_8(bb, src, ilen) \
- (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1)
-
- #define GETBIT_LE16(bb, src, ilen) \
- (bb*=2,bb&0xffff ? (bb>>16)&1 : (ilen+=2,((bb=(src[ilen-2]+src[ilen-1]*256u)*2+1)>>16)&1))
-
- #define GETBIT_LE32(bb, src, ilen) \
- (bc > 0 ? ((bb>>--bc)&1) : (bc=31,\
- bb=*(const uint32_t *)((src)+ilen),ilen+=4,(bb>>31)&1))
-
- #define GETBIT_LE64(bb, src, ilen) \
- (bc > 0 ? ((bb>>--bc)&1) : (bc=63, \
- bb=*(const uint64_t *)((src)+ilen),ilen+=8,(bb>>63)&1))
-
- #if ENDIAN == 0 && BITSIZE == 8
- #define GETBIT(bb, src, ilen) GETBIT_8(bb, src, ilen)
- #endif
- #if ENDIAN == 0 && BITSIZE == 16
- #define GETBIT(bb, src, ilen) GETBIT_LE16(bb, src, ilen)
- #endif
- #if ENDIAN == 0 && BITSIZE == 32
- #define GETBIT(bb, src, ilen) GETBIT_LE32(bb, src, ilen)
- #endif
- #if ENDIAN == 0 && BITSIZE == 64
- #define GETBIT(bb, src, ilen) GETBIT_LE64(bb, src, ilen)
- #endif
- #ifndef GETBIT
- #error "Bad Combination of ENDIAN and BITSIZE values specified"
- #endif
-
- #undef SAFE
-
- #ifdef SAFE
- #define FAIL(x,r) if (x) { Error(r); }
- #else
- #define FAIL(x,r)
- #endif
-
- void Decode(void) /* recover */
- {
- uint32_t tw;
- uint8_t *src, *dst;
- unsigned long max_src_len, src_len, dst_len;
- unsigned long ilen = 0, olen = 0, last_m_off = 1;
- #if BITSIZE <= 32
- uint32_t bb = 0;
- #elif BITSIZE == 64
- uint64_t bb = 0;
- #endif
- unsigned bc = 0;
- #if UCLPACK_COMPAT
- if (fseek(infile, sizeof(magic) + sizeof(tw) + 1 + 1 + sizeof(tw),
- SEEK_SET) != 0)
-
- Error("Seek Error");
- if (fread(&tw, sizeof(tw), 1, infile) < 1)
- Error("Can't read"); /* read size of text */
- dst_len = ntohl(tw);
- if (fread(&tw, sizeof(tw), 1, infile) < 1)
- Error("Can't read"); /* read size of file */
- max_src_len = ntohl(tw);
- #else
- if (fread(&tw, sizeof(tw), 1, infile) < 1)
- Error("Can't read"); /* read size of text */
- dst_len = i86ul_to_host(tw);
- max_src_len = dst_len + (dst_len/8) + 256;
- #endif
- if (dst_len == 0)
- return;
- dst = malloc(dst_len);
- if (!dst)
- Error("Can't malloc");
- src = malloc(max_src_len);
- if (!src)
- Error("Can't malloc");
- src_len = fread(src, 1, max_src_len, infile);
- if (src_len <= 0)
- Error("Can't read");
-
- for(;;) {
- unsigned int m_off, m_len;
- while(GETBIT(bb, src, ilen)) {
- FAIL(ilen >= src_len, "input overrun");
- FAIL(olen >= dst_len, "output overrun");
- dst[olen++] = src[ilen++];
- }
- m_off = 1;
- do {
- m_off = m_off*2 + GETBIT(bb, src, ilen);
- FAIL(ilen >= src_len, "input overrun");
- FAIL(m_off > 0xffffffU +3, "lookbehind overrun");
- } while (!GETBIT(bb, src, ilen));
- if (m_off == 2)
- {
- m_off = last_m_off;
- }
- else
- {
- FAIL(ilen >= src_len, "input overrun");
- m_off = (m_off - 3)*256 + src[ilen++];
- if (m_off == 0xffffffffU)
- break;
- last_m_off = ++m_off;
- }
- m_len = GETBIT(bb, src, ilen);
- m_len = m_len*2 + GETBIT(bb, src, ilen);
- if (m_len == 0)
- {
- m_len++;
- do {
- m_len = m_len*2 + GETBIT(bb, src, ilen);
- FAIL(ilen >= src_len, "input overrun");
- FAIL(m_len >= dst_len, "output overrun");
- } while(!GETBIT(bb, src, ilen));
- m_len += 2;
- }
- m_len += (m_off > 0xd00);
- FAIL(olen + m_len > dst_len, "output overrun");
- FAIL(m_off > olen, "lookbeind overrun");
- {
- const uint8_t *m_pos;
- m_pos = dst + olen - m_off;
- dst[olen++] = *m_pos++;
- do {
- dst[olen++] = *m_pos++;
- } while(--m_len > 0);
- }
- }
- FAIL(ilen < src_len, "input not consumed");
- FAIL(ilen > src_len, "input overrun");
- assert(ilen == src_len);
- Fprintf((stderr, "%12ld\n", olen));
- if (dst_len != olen) {
- fprintf(stderr, "length != expected length\n");
- }
- if (fwrite(dst, olen, 1, outfile) != 1)
- Error("Write error\n");
- free(src);
- free(dst);
- }
- #endif
-
- #ifdef MAIN
- int main(int argc, char *argv[])
- {
- char *s;
- FILE *f;
- int c;
-
- if (argc == 2) {
- outfile = stdout;
- if ((f = tmpfile()) == NULL) {
- perror("tmpfile");
- return EXIT_FAILURE;
- }
- while ((c = getchar()) != EOF)
- fputc(c, f);
- rewind(infile = f);
- }
- else if (argc != 4) {
- Fprintf((stderr, "'nrv2b e file1 file2' encodes file1 into file2.\n"
- "'nrv2b d file2 file1' decodes file2 into file1.\n"));
- return EXIT_FAILURE;
- }
- if (argc == 4) {
- if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL)
- || (s = argv[2], (infile = fopen(s, "rb")) == NULL)
- || (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
- Fprintf((stderr, "??? %s\n", s));
- return EXIT_FAILURE;
- }
- }
- if (toupper(*argv[1]) == 'E')
- Encode();
- else
- Decode();
- fclose(infile);
- fclose(outfile);
- return EXIT_SUCCESS;
- }
- #endif
|