|
|
1.1 root 1: /**************************************************************
2: Form adapted from lzhuf.c
3: written by Haruyasu Yoshizaki 11/20/1988
4: some minor changes 4/6/1989
5: comments translated by Haruhiko Okumura 4/7/1989
6:
7: minor beautifications and adjustments for compiling under Linux
8: by Markus Gutschke <[email protected]>
9: 1997-01-27
10:
11: Modifications to allow use as a filter by Ken Yap
12: <[email protected]>.
13:
14: 1997-07-01
15:
16: Small mod to cope with running on big-endian machines
17: by Jim Hague <[email protected])
18: 1998-02-06
19:
20: Make compression statistics report shorter
21: by Ken Yap <[email protected]>.
22: 2001-04-25
23:
24: Replaced algorithm with nrv2b from ucl the compression
25: library from upx. That code is:
26: Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
27: And is distributed under the terms of the GPL.
28: The conversion was performed
29: by Eric Biederman <[email protected]>.
30: 20 August 2002
31:
32: **************************************************************/
33: #define UCLPACK_COMPAT 0
34: #define NDEBUG 1
35: #include <stdio.h>
36: #include <stdlib.h>
37: #include <string.h>
38: #include <ctype.h>
39: #include <errno.h>
40: #ifdef __FreeBSD__
41: #include <inttypes.h>
42: #else
43: #include <stdint.h>
44: #endif
45: #include <limits.h>
46: #include <assert.h>
47: #if UCLPACK_COMPAT
48: #include <netinet/in.h>
49: #endif
50:
51: #ifndef VERBOSE
52: #define Fprintf(x)
53: #define wterr 0
54: #else
55: #define Fprintf(x) fprintf x
56: #endif
57:
58: #ifndef MAIN
59: extern
60: #endif
61: FILE *infile, *outfile;
62:
63: #if defined(ENCODE) || defined(DECODE)
64:
65: #ifndef ENDIAN
66: #define ENDIAN 0
67: #endif
68: #ifndef BITSIZE
69: #define BITSIZE 32
70: #endif
71:
72: static __inline__ void Error(char *message)
73: {
74: Fprintf((stderr, "\n%s\n", message));
75: exit(EXIT_FAILURE);
76: }
77:
78: /* These will be a complete waste of time on a lo-endian */
79: /* system, but it only gets done once so WTF. */
80: static unsigned long i86ul_to_host(unsigned long ul)
81: {
82: unsigned long res = 0;
83: int i;
84: union
85: {
86: unsigned char c[4];
87: unsigned long ul;
88: } u;
89:
90: u.ul = ul;
91: for (i = 3; i >= 0; i--)
92: res = (res << 8) + u.c[i];
93: return res;
94: }
95:
96: static unsigned long host_to_i86ul(unsigned long ul)
97: {
98: int i;
99: union
100: {
101: unsigned char c[4];
102: unsigned long ul;
103: } u;
104:
105: for (i = 0; i < 4; i++)
106: {
107: u.c[i] = ul & 0xff;
108: ul >>= 8;
109: }
110: return u.ul;
111: }
112: #endif
113:
114:
115:
116: #if UCLPACK_COMPAT
117: /* magic file header for compressed files */
118: static const unsigned char magic[8] =
119: { 0x00, 0xe9, 0x55, 0x43, 0x4c, 0xff, 0x01, 0x1a };
120:
121: #endif
122:
123: #ifdef ENCODE
124: /********** NRV2B_99 compression **********/
125:
126: /* Note by limiting the ring buffer I have limited the maximum
127: * offset to 64K. Since etherboot rarely gets that big it
128: * is not a problem and it gives me a firm guarantee
129: * that I will never get a 3 byte string match that is encodes
130: * to more than 9/8 it's original size.
131: * That guaranteee is important to for the inplace decompressor.
132: * There are better ways to do this if a larger offset and buffer
133: * would give better compression.
134: */
135: #define N (65536ul) /* size of ring buffer */
136: #define THRESHOLD 1 /* lower limit for match length */
137: #define F 2048 /* upper limit for match length */
138: #define M2_MAX_OFFSET 0xd00
139:
140: /* note: to use default values pass -1, i.e. initialize
141: * this struct by a memset(x,0xff,sizeof(x)) */
142: struct ucl_compress_config
143: {
144: int bb_endian;
145: int bb_size;
146: unsigned int max_offset;
147: unsigned int max_match;
148: int s_level;
149: int h_level;
150: int p_level;
151: int c_flags;
152: unsigned int m_size;
153: };
154:
155: struct ucl_compress
156: {
157: int init;
158:
159: unsigned int look; /* bytes in lookahead buffer */
160:
161: unsigned int m_len;
162: unsigned int m_off;
163:
164: unsigned int last_m_len;
165: unsigned int last_m_off;
166:
167: const unsigned char *bp;
168: const unsigned char *ip;
169: const unsigned char *in;
170: const unsigned char *in_end;
171: unsigned char *out;
172:
173: uint64_t bb_b;
174: unsigned bb_k;
175: unsigned bb_c_endian;
176: unsigned bb_c_s;
177: unsigned bb_c_s8;
178: unsigned char *bb_p;
179: unsigned char *bb_op;
180:
181: struct ucl_compress_config conf;
182: unsigned int *result;
183:
184: unsigned int textsize; /* text size counter */
185: unsigned int codesize; /* code size counter */
186: unsigned int printcount; /* counter for reporting progress every 1K
187: bytes */
188:
189:
190: /* some stats */
191: unsigned long lit_bytes;
192: unsigned long match_bytes;
193: unsigned long rep_bytes;
194: unsigned long lazy;
195: };
196:
197:
198:
199: #define getbyte(c) ((c).ip < (c).in_end ? *((c).ip)++ : (-1))
200:
201: #define UCL_E_OK 0
202: #define UCL_E_INVALID_ARGUMENT 1
203: #define UCL_E_OUT_OF_MEMORY 2
204: #define UCL_E_ERROR 3
205:
206: /***********************************************************************
207: //
208: ************************************************************************/
209:
210: #define SWD_HSIZE 16384
211: #define SWD_MAX_CHAIN 2048
212: #define SWD_BEST_OFF 1
213:
214: #define HEAD3(b,p) \
215: (((0x9f5f*(((((uint32_t)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & (SWD_HSIZE-1))
216:
217: #define HEAD2(b,p) (b[p] ^ ((unsigned)b[p+1]<<8))
218: #define NIL2 UINT_MAX
219:
220: struct ucl_swd
221: {
222: /* public - "built-in" */
223: unsigned int n;
224: unsigned int f;
225: unsigned int threshold;
226:
227: /* public - configuration */
228: unsigned int max_chain;
229: unsigned int nice_length;
230: int use_best_off;
231: unsigned int lazy_insert;
232:
233: /* public - output */
234: unsigned int m_len;
235: unsigned int m_off;
236: unsigned int look;
237: int b_char;
238: #if defined(SWD_BEST_OFF)
239: unsigned int best_off[ SWD_BEST_OFF ];
240: #endif
241:
242: /* semi public */
243: struct ucl_compress *c;
244: unsigned int m_pos;
245: #if defined(SWD_BEST_OFF)
246: unsigned int best_pos[ SWD_BEST_OFF ];
247: #endif
248:
249: /* private */
250: const uint8_t *dict;
251: const uint8_t *dict_end;
252: unsigned int dict_len;
253:
254: /* private */
255: unsigned int ip; /* input pointer (lookahead) */
256: unsigned int bp; /* buffer pointer */
257: unsigned int rp; /* remove pointer */
258: unsigned int b_size;
259:
260: unsigned char *b_wrap;
261:
262: unsigned int node_count;
263: unsigned int first_rp;
264:
265: unsigned char b [ N + F + F ];
266: unsigned int head3 [ SWD_HSIZE ];
267: unsigned int succ3 [ N + F ];
268: unsigned int best3 [ N + F ];
269: unsigned int llen3 [ SWD_HSIZE ];
270: unsigned int head2 [ 65536U ];
271: };
272:
273: #define s_head3(s,key) s->head3[key]
274:
275:
276: #if !defined( NDEBUG)
277: static void assert_match(const struct ucl_swd * swd, unsigned int m_len,
278: unsigned int m_off )
279:
280: {
281: const struct ucl_compress *c = swd->c;
282: unsigned int d_off;
283:
284: assert(m_len >= 2);
285: if (m_off <= (unsigned int) (c->bp - c->in))
286: {
287: assert(c->bp - m_off + m_len < c->ip);
288: assert(memcmp(c->bp, c->bp - m_off, m_len) == 0);
289: }
290: else
291: {
292: assert(swd->dict != NULL);
293: d_off = m_off - (unsigned int) (c->bp - c->in);
294: assert(d_off <= swd->dict_len);
295: if (m_len > d_off)
296: {
297: assert(memcmp(c->bp, swd->dict_end - d_off, d_off) ==
298: 0);
299:
300: assert(c->in + m_len - d_off < c->ip);
301: assert(memcmp(c->bp + d_off, c->in, m_len - d_off) ==
302: 0);
303:
304: }
305: else
306: {
307: assert(memcmp(c->bp, swd->dict_end - d_off, m_len) ==
308: 0);
309:
310: }
311: }
312: }
313: #else
314: # define assert_match(a,b,c) ((void)0)
315: #endif
316:
317: /***********************************************************************
318: //
319: ************************************************************************/
320:
321:
322: static
323: void swd_initdict(struct ucl_swd *s, const uint8_t *dict, unsigned int dict_len)
324:
325: {
326: s->dict = s->dict_end = NULL;
327: s->dict_len = 0;
328:
329: if (!dict || dict_len <= 0)
330: return;
331: if (dict_len > s->n)
332: {
333: dict += dict_len - s->n;
334: dict_len = s->n;
335: }
336:
337: s->dict = dict;
338: s->dict_len = dict_len;
339: s->dict_end = dict + dict_len;
340: memcpy(s->b,dict,dict_len);
341: s->ip = dict_len;
342: }
343:
344:
345: static
346: void swd_insertdict(struct ucl_swd *s, unsigned int node, unsigned int len)
347: {
348: unsigned int key;
349:
350: s->node_count = s->n - len;
351: s->first_rp = node;
352:
353: while (len-- > 0)
354: {
355: key = HEAD3(s->b,node);
356: s->succ3[node] = s_head3(s,key);
357: s->head3[key] = (unsigned int)(node);
358: s->best3[node] = (unsigned int)(s->f + 1);
359: s->llen3[key]++;
360: assert(s->llen3[key] <= s->n);
361:
362: key = HEAD2(s->b,node);
363: s->head2[key] = (unsigned int)(node);
364:
365: node++;
366: }
367: }
368:
369: /***********************************************************************
370: //
371: ************************************************************************/
372:
373:
374: static
375: int swd_init(struct ucl_swd *s, const uint8_t *dict, unsigned int dict_len)
376: {
377: unsigned int i = 0;
378: int c = 0;
379:
380: if (s->n == 0)
381: s->n = N;
382: if (s->f == 0)
383: s->f = F;
384: s->threshold = THRESHOLD;
385: if (s->n > N || s->f > F)
386: return UCL_E_INVALID_ARGUMENT;
387:
388: /* defaults */
389: s->max_chain = SWD_MAX_CHAIN;
390: s->nice_length = s->f;
391: s->use_best_off = 0;
392: s->lazy_insert = 0;
393:
394: s->b_size = s->n + s->f;
395: if (s->b_size + s->f >= UINT_MAX)
396: return UCL_E_ERROR;
397: s->b_wrap = s->b + s->b_size;
398: s->node_count = s->n;
399:
400: memset(s->llen3, 0, sizeof(s->llen3[0]) * SWD_HSIZE);
401: for (i = 0; i < 65536U; i++)
402: s->head2[i] = NIL2;
403:
404: s->ip = 0;
405: swd_initdict(s,dict,dict_len);
406: s->bp = s->ip;
407: s->first_rp = s->ip;
408:
409: assert(s->ip + s->f <= s->b_size);
410:
411: s->look = (unsigned int) (s->c->in_end - s->c->ip);
412: if (s->look > 0)
413: {
414: if (s->look > s->f)
415: s->look = s->f;
416: memcpy(&s->b[s->ip],s->c->ip,s->look);
417: s->c->ip += s->look;
418: s->ip += s->look;
419: }
420: if (s->ip == s->b_size)
421: s->ip = 0;
422:
423: if (s->look >= 2 && s->dict_len > 0)
424: swd_insertdict(s,0,s->dict_len);
425:
426: s->rp = s->first_rp;
427: if (s->rp >= s->node_count)
428: s->rp -= s->node_count;
429: else
430: s->rp += s->b_size - s->node_count;
431:
432: /* unused i */
433: /* unused c */
434: return UCL_E_OK;
435: }
436:
437:
438: static
439: void swd_exit(struct ucl_swd *s)
440: {
441: /* unused s */
442:
443: }
444:
445: #define swd_pos2off(s,pos) \
446: (s->bp > (pos) ? s->bp - (pos) : s->b_size - ((pos) - s->bp))
447:
448: /***********************************************************************
449: //
450: ************************************************************************/
451:
452: static __inline__
453: void swd_getbyte(struct ucl_swd *s)
454: {
455: int c;
456:
457: if ((c = getbyte(*(s->c))) < 0)
458: {
459: if (s->look > 0)
460: --s->look;
461: }
462: else
463: {
464: s->b[s->ip] = (uint8_t)(c);
465: if (s->ip < s->f)
466: s->b_wrap[s->ip] = (uint8_t)(c);
467: }
468: if (++s->ip == s->b_size)
469: s->ip = 0;
470: if (++s->bp == s->b_size)
471: s->bp = 0;
472: if (++s->rp == s->b_size)
473: s->rp = 0;
474: }
475: /***********************************************************************
476: // remove node from lists
477: ************************************************************************/
478:
479: static __inline__
480: void swd_remove_node(struct ucl_swd *s, unsigned int node)
481: {
482: if (s->node_count == 0)
483: {
484: unsigned int key;
485:
486: #ifdef UCL_DEBUG
487: if (s->first_rp != UINT_MAX)
488: {
489: if (node != s->first_rp)
490: printf("Remove %5d: %5d %5d %5d %5d %6d %6d\n",
491:
492: node, s->rp, s->ip, s->bp, s->first_rp,
493: s->ip - node, s->ip - s->bp);
494: assert(node == s->first_rp);
495: s->first_rp = UINT_MAX;
496: }
497: #endif
498:
499: key = HEAD3(s->b,node);
500: assert(s->llen3[key] > 0);
501: --s->llen3[key];
502:
503: key = HEAD2(s->b,node);
504: assert(s->head2[key] != NIL2);
505: if ((unsigned int) s->head2[key] == node)
506: s->head2[key] = NIL2;
507: }
508: else
509: --s->node_count;
510: }
511:
512:
513: /***********************************************************************
514: //
515: ************************************************************************/
516:
517:
518: static
519: void swd_accept(struct ucl_swd *s, unsigned int n)
520: {
521: assert(n <= s->look);
522:
523: if (n > 0) do
524: {
525: unsigned int key;
526:
527: swd_remove_node(s,s->rp);
528:
529: /* add bp into HEAD3 */
530: key = HEAD3(s->b,s->bp);
531: s->succ3[s->bp] = s_head3(s,key);
532: s->head3[key] = (unsigned int)(s->bp);
533: s->best3[s->bp] = (unsigned int)(s->f + 1);
534: s->llen3[key]++;
535: assert(s->llen3[key] <= s->n);
536:
537: /* add bp into HEAD2 */
538: key = HEAD2(s->b,s->bp);
539: s->head2[key] = (unsigned int)(s->bp);
540:
541: swd_getbyte(s);
542: } while (--n > 0);
543: }
544:
545: /***********************************************************************
546: //
547: ************************************************************************/
548:
549: static
550: void swd_search(struct ucl_swd *s, unsigned int node, unsigned int cnt)
551: {
552: const unsigned char *p1;
553: const unsigned char *p2;
554: const unsigned char *px;
555:
556: unsigned int m_len = s->m_len;
557: const unsigned char * b = s->b;
558: const unsigned char * bp = s->b + s->bp;
559: const unsigned char * bx = s->b + s->bp + s->look;
560: unsigned char scan_end1;
561:
562: assert(s->m_len > 0);
563:
564: scan_end1 = bp[m_len - 1];
565: for ( ; cnt-- > 0; node = s->succ3[node])
566: {
567: p1 = bp;
568: p2 = b + node;
569: px = bx;
570:
571: assert(m_len < s->look);
572:
573: if (
574: p2[m_len - 1] == scan_end1 &&
575: p2[m_len] == p1[m_len] &&
576: p2[0] == p1[0] &&
577: p2[1] == p1[1])
578: {
579: unsigned int i;
580: assert(memcmp(bp,&b[node],3) == 0);
581:
582: p1 += 2; p2 += 2;
583: do {} while (++p1 < px && *p1 == *++p2);
584: i = p1 - bp;
585:
586: #ifdef UCL_DEBUG
587: if (memcmp(bp,&b[node],i) != 0)
588: printf("%5ld %5ld %02x%02x %02x%02x\n",
589: (long)s->bp, (long) node,
590: bp[0], bp[1], b[node], b[node+1]);
591: #endif
592: assert(memcmp(bp,&b[node],i) == 0);
593:
594: #if defined(SWD_BEST_OFF)
595: if (i < SWD_BEST_OFF)
596: {
597: if (s->best_pos[i] == 0)
598: s->best_pos[i] = node + 1;
599: }
600: #endif
601: if (i > m_len)
602: {
603: s->m_len = m_len = i;
604: s->m_pos = node;
605: if (m_len == s->look)
606: return;
607: if (m_len >= s->nice_length)
608: return;
609: if (m_len > (unsigned int) s->best3[node])
610: return;
611: scan_end1 = bp[m_len - 1];
612: }
613: }
614: }
615: }
616:
617: static int swd_search2(struct ucl_swd *s)
618: {
619: unsigned int key;
620:
621: assert(s->look >= 2);
622: assert(s->m_len > 0);
623:
624: key = s->head2[ HEAD2(s->b,s->bp) ];
625: if (key == NIL2)
626: return 0;
627: #ifdef UCL_DEBUG
628: if (memcmp(&s->b[s->bp],&s->b[key],2) != 0)
629: printf("%5ld %5ld %02x%02x %02x%02x\n", (long)s->bp, (long)key,
630: s->b[s->bp], s->b[s->bp+1], s->b[key], s->b[key+1]);
631: #endif
632: assert(memcmp(&s->b[s->bp],&s->b[key],2) == 0);
633: #if defined(SWD_BEST_OFF)
634: if (s->best_pos[2] == 0)
635: s->best_pos[2] = key + 1;
636: #endif
637:
638: if (s->m_len < 2)
639: {
640: s->m_len = 2;
641: s->m_pos = key;
642: }
643: return 1;
644: }
645:
646: /***********************************************************************
647: //
648: ************************************************************************/
649:
650: static
651: void swd_findbest(struct ucl_swd *s)
652: {
653: unsigned int key;
654: unsigned int cnt, node;
655: unsigned int len;
656:
657: assert(s->m_len > 0);
658:
659: /* get current head, add bp into HEAD3 */
660: key = HEAD3(s->b,s->bp);
661: node = s->succ3[s->bp] = s_head3(s,key);
662: cnt = s->llen3[key]++;
663: assert(s->llen3[key] <= s->n + s->f);
664: if (cnt > s->max_chain && s->max_chain > 0)
665: cnt = s->max_chain;
666: s->head3[key] = (unsigned int)(s->bp);
667:
668: s->b_char = s->b[s->bp];
669: len = s->m_len;
670: if (s->m_len >= s->look)
671: {
672: if (s->look == 0)
673: s->b_char = -1;
674: s->m_off = 0;
675: s->best3[s->bp] = (unsigned int)(s->f + 1);
676: }
677: else
678: {
679: if (swd_search2(s))
680: if (s->look >= 3)
681: swd_search(s,node,cnt);
682: if (s->m_len > len)
683: s->m_off = swd_pos2off(s,s->m_pos);
684: s->best3[s->bp] = (unsigned int)(s->m_len);
685:
686: #if defined(SWD_BEST_OFF)
687: if (s->use_best_off)
688: {
689: int i;
690: for (i = 2; i < SWD_BEST_OFF; i++)
691: if (s->best_pos[i] > 0)
692: s->best_off[i] =
693: swd_pos2off(s,s->best_pos[i]-1);
694:
695: else
696: s->best_off[i] = 0;
697: }
698: #endif
699: }
700:
701: swd_remove_node(s,s->rp);
702:
703: /* add bp into HEAD2 */
704: key = HEAD2(s->b,s->bp);
705: s->head2[key] = (unsigned int)(s->bp);
706: }
707:
708:
709: /***********************************************************************
710: //
711: ************************************************************************/
712:
713: static int
714: init_match ( struct ucl_compress *c, struct ucl_swd *s,
715: const uint8_t *dict, unsigned int dict_len,
716: uint32_t flags )
717: {
718: int r;
719:
720: assert(!c->init);
721: c->init = 1;
722:
723: s->c = c;
724:
725: c->last_m_len = c->last_m_off = 0;
726:
727: c->textsize = c->codesize = c->printcount = 0;
728: c->lit_bytes = c->match_bytes = c->rep_bytes = 0;
729: c->lazy = 0;
730:
731: r = swd_init(s,dict,dict_len);
732: if (r != UCL_E_OK)
733: {
734: swd_exit(s);
735: return r;
736: }
737:
738: s->use_best_off = (flags & 1) ? 1 : 0;
739: return UCL_E_OK;
740: }
741:
742: static int
743: find_match ( struct ucl_compress *c, struct ucl_swd *s,
744: unsigned int this_len, unsigned int skip )
745: {
746: assert(c->init);
747:
748: if (skip > 0)
749: {
750: assert(this_len >= skip);
751: swd_accept(s, this_len - skip);
752: c->textsize += this_len - skip + 1;
753: }
754: else
755: {
756: assert(this_len <= 1);
757: c->textsize += this_len - skip;
758: }
759:
760: s->m_len = THRESHOLD;
761: #ifdef SWD_BEST_OFF
762: if (s->use_best_off)
763: memset(s->best_pos,0,sizeof(s->best_pos));
764: #endif
765: swd_findbest(s);
766: c->m_len = s->m_len;
767: c->m_off = s->m_off;
768:
769: swd_getbyte(s);
770:
771: if (s->b_char < 0)
772: {
773: c->look = 0;
774: c->m_len = 0;
775: swd_exit(s);
776: }
777: else
778: {
779: c->look = s->look + 1;
780: }
781: c->bp = c->ip - c->look;
782:
783: #if 0
784: /* brute force match search */
785: if (c->m_len > THRESHOLD && c->m_len + 1 <= c->look)
786: {
787: const uint8_t *ip = c->bp;
788: const uint8_t *m = c->bp - c->m_off;
789: const uint8_t *in = c->in;
790:
791: if (ip - in > N)
792: in = ip - N;
793: for (;;)
794: {
795: while (*in != *ip)
796: in++;
797: if (in == ip)
798: break;
799: if (in != m)
800: if (memcmp(in,ip,c->m_len+1) == 0)
801: printf("%p %p %p %5d\n",in,ip,m,c->m_len);
802:
803: in++;
804: }
805: }
806: #endif
807:
808: return UCL_E_OK;
809: }
810:
811:
812: static int bbConfig(struct ucl_compress *c, int endian, int bitsize)
813: {
814: if (endian != -1)
815: {
816: if (endian != 0)
817: return UCL_E_ERROR;
818: c->bb_c_endian = endian;
819: }
820: if (bitsize != -1)
821: {
822: if (bitsize != 8 && bitsize != 16 && bitsize != 32 && bitsize != 64)
823: return UCL_E_ERROR;
824: c->bb_c_s = bitsize;
825: c->bb_c_s8 = bitsize / 8;
826: }
827: c->bb_b = 0; c->bb_k = 0;
828: c->bb_p = NULL;
829: c->bb_op = NULL;
830: return UCL_E_OK;
831: }
832:
833: static void bbWriteBits(struct ucl_compress *c)
834: {
835: uint8_t *p = c->bb_p;
836: uint64_t b = c->bb_b;
837:
838: p[0] = (uint8_t)(b >> 0);
839: if (c->bb_c_s >= 16)
840: {
841: p[1] = (uint8_t)(b >> 8);
842: if (c->bb_c_s >= 32)
843: {
844: p[2] = (uint8_t)(b >> 16);
845: p[3] = (uint8_t)(b >> 24);
846: if (c->bb_c_s == 64)
847: {
848: p[4] = (uint8_t)(b >> 32);
849: p[5] = (uint8_t)(b >> 40);
850: p[6] = (uint8_t)(b >> 48);
851: p[7] = (uint8_t)(b >> 56);
852: }
853: }
854: }
855: }
856:
857:
858: static void bbPutBit(struct ucl_compress *c, unsigned bit)
859: {
860: assert(bit == 0 || bit == 1);
861: assert(c->bb_k <= c->bb_c_s);
862:
863: if (c->bb_k < c->bb_c_s)
864: {
865: if (c->bb_k == 0)
866: {
867: assert(c->bb_p == NULL);
868: c->bb_p = c->bb_op;
869: c->bb_op += c->bb_c_s8;
870: }
871: assert(c->bb_p != NULL);
872: assert(c->bb_p + c->bb_c_s8 <= c->bb_op);
873:
874: c->bb_b = (c->bb_b << 1) + bit;
875: c->bb_k++;
876: }
877: else
878: {
879: assert(c->bb_p != NULL);
880: assert(c->bb_p + c->bb_c_s8 <= c->bb_op);
881:
882: bbWriteBits(c);
883: c->bb_p = c->bb_op;
884: c->bb_op += c->bb_c_s8;
885: c->bb_b = bit;
886: c->bb_k = 1;
887: }
888: }
889:
890:
891: static void bbPutByte(struct ucl_compress *c, unsigned b)
892: {
893: /**printf("putbyte %p %p %x (%d)\n", op, bb_p, x, bb_k);*/
894: assert(c->bb_p == NULL || c->bb_p + c->bb_c_s8 <= c->bb_op);
895: *c->bb_op++ = (uint8_t)(b);
896: }
897:
898: static void bbFlushBits(struct ucl_compress *c, unsigned filler_bit)
899: {
900: if (c->bb_k > 0)
901: {
902: assert(c->bb_k <= c->bb_c_s);
903: while (c->bb_k != c->bb_c_s)
904: bbPutBit(c, filler_bit);
905: bbWriteBits(c);
906: c->bb_k = 0;
907: }
908: c->bb_p = NULL;
909: }
910:
911:
912:
913: /***********************************************************************
914: //
915: ************************************************************************/
916:
917:
918: static void code_prefix_ss11(struct ucl_compress *c, uint32_t i)
919: {
920: if (i >= 2)
921: {
922: uint32_t t = 4;
923: i += 2;
924: do {
925: t <<= 1;
926: } while (i >= t);
927: t >>= 1;
928: do {
929: t >>= 1;
930: bbPutBit(c, (i & t) ? 1 : 0);
931: bbPutBit(c, 0);
932: } while (t > 2);
933: }
934: bbPutBit(c, (unsigned)i & 1);
935: bbPutBit(c, 1);
936: }
937:
938: static void
939: code_match(struct ucl_compress *c, unsigned int m_len, const unsigned int m_off)
940:
941: {
942: while (m_len > c->conf.max_match)
943: {
944: code_match(c, c->conf.max_match - 3, m_off);
945: m_len -= c->conf.max_match - 3;
946: }
947:
948: c->match_bytes += m_len;
949: if (m_len > c->result[3])
950: c->result[3] = m_len;
951: if (m_off > c->result[1])
952: c->result[1] = m_off;
953:
954: bbPutBit(c, 0);
955:
956: if (m_off == c->last_m_off)
957: {
958: bbPutBit(c, 0);
959: bbPutBit(c, 1);
960: }
961: else
962: {
963: code_prefix_ss11(c, 1 + ((m_off - 1) >> 8));
964: bbPutByte(c, (unsigned)m_off - 1);
965: }
966: m_len = m_len - 1 - (m_off > M2_MAX_OFFSET);
967: if (m_len >= 4)
968: {
969: bbPutBit(c,0);
970: bbPutBit(c,0);
971: code_prefix_ss11(c, m_len - 4);
972: }
973: else
974: {
975: bbPutBit(c, m_len > 1);
976: bbPutBit(c, (unsigned)m_len & 1);
977: }
978:
979: c->last_m_off = m_off;
980: }
981:
982: static void
983: code_run(struct ucl_compress *c, const uint8_t *ii, unsigned int lit)
984: {
985: if (lit == 0)
986: return;
987: c->lit_bytes += lit;
988: if (lit > c->result[5])
989: c->result[5] = lit;
990: do {
991: bbPutBit(c, 1);
992: bbPutByte(c, *ii++);
993: } while (--lit > 0);
994: }
995:
996: /***********************************************************************
997: //
998: ************************************************************************/
999:
1000: static int
1001: len_of_coded_match(struct ucl_compress *c, unsigned int m_len, unsigned int
1002: m_off)
1003:
1004: {
1005: int b;
1006: if (m_len < 2 || (m_len == 2 && (m_off > M2_MAX_OFFSET))
1007: || m_off > c->conf.max_offset)
1008: return -1;
1009: assert(m_off > 0);
1010:
1011: m_len = m_len - 2 - (m_off > M2_MAX_OFFSET);
1012:
1013: if (m_off == c->last_m_off)
1014: b = 1 + 2;
1015: else
1016: {
1017: b = 1 + 10;
1018: m_off = (m_off - 1) >> 8;
1019: while (m_off > 0)
1020: {
1021: b += 2;
1022: m_off >>= 1;
1023: }
1024: }
1025:
1026: b += 2;
1027: if (m_len < 3)
1028: return b;
1029: m_len -= 3;
1030:
1031: do {
1032: b += 2;
1033: m_len >>= 1;
1034: } while (m_len > 0);
1035:
1036: return b;
1037: }
1038:
1039: int ucl_nrv2b_99_compress(
1040: const uint8_t *in, unsigned long in_len,
1041: uint8_t *out, unsigned long *out_len,
1042: unsigned int *result)
1043: {
1044: const uint8_t *ii;
1045: unsigned int lit;
1046: unsigned int m_len, m_off;
1047: struct ucl_compress c_buffer;
1048: struct ucl_compress * const c = &c_buffer;
1049: struct ucl_swd *swd;
1050: unsigned int result_buffer[16];
1051: int r;
1052:
1053: /* max compression */
1054: #define SC_TRY_LAZY 2
1055: #define SC_GOOD_LENGTH F
1056: #define SC_MAX_LAZY F
1057: #define SC_NICE_LENGTH F
1058: #define SC_MAX_CHAIN 4096
1059: #define SC_FLAGS 1
1060: #define SC_MAX_OFFSET N
1061:
1062: memset(c, 0, sizeof(*c));
1063: c->ip = c->in = in;
1064: c->in_end = in + in_len;
1065: c->out = out;
1066: c->result = result ? result : result_buffer;
1067: memset(c->result, 0, 16*sizeof(*c->result));
1068: c->result[0] = c->result[2] = c->result[4] = UINT_MAX;
1069: result = NULL;
1070: memset(&c->conf, 0xff, sizeof(c->conf));
1071: r = bbConfig(c, ENDIAN, BITSIZE);
1072: if (r == 0)
1073: r = bbConfig(c, c->conf.bb_endian, c->conf.bb_size);
1074: if (r != 0)
1075: return UCL_E_INVALID_ARGUMENT;
1076: c->bb_op = out;
1077:
1078: ii = c->ip; /* point to start of literal run */
1079: lit = 0;
1080:
1081:
1082: swd = (struct ucl_swd *) malloc(sizeof(*swd));
1083: if (!swd)
1084: return UCL_E_OUT_OF_MEMORY;
1085:
1086: swd->f = F;
1087: swd->n = N;
1088: if (in_len >= 256 && in_len < swd->n)
1089: swd->n = in_len;
1090: if (swd->f < 8 || swd->n < 256)
1091: return UCL_E_INVALID_ARGUMENT;
1092:
1093: r = init_match(c,swd,NULL,0, SC_FLAGS);
1094: if (r != UCL_E_OK)
1095: {
1096: free(swd);
1097: return r;
1098: }
1099: if (SC_MAX_CHAIN > 0)
1100: swd->max_chain = SC_MAX_CHAIN;
1101: if (SC_NICE_LENGTH > 0)
1102: swd->nice_length = SC_NICE_LENGTH;
1103: if (c->conf.max_match < swd->nice_length)
1104: swd->nice_length = c->conf.max_match;
1105:
1106: c->last_m_off = 1;
1107: r = find_match(c,swd,0,0);
1108: if (r != UCL_E_OK)
1109: return r;
1110: while (c->look > 0)
1111: {
1112: unsigned int ahead;
1113: unsigned int max_ahead;
1114: int l1, l2;
1115:
1116: c->codesize = c->bb_op - out;
1117:
1118: m_len = c->m_len;
1119: m_off = c->m_off;
1120:
1121: assert(c->bp == c->ip - c->look);
1122: assert(c->bp >= in);
1123: if (lit == 0)
1124: ii = c->bp;
1125: assert(ii + lit == c->bp);
1126: assert(swd->b_char == *(c->bp));
1127:
1128: if (m_len < 2 || (m_len == 2 && (m_off > M2_MAX_OFFSET))
1129: || m_off > c->conf.max_offset)
1130: {
1131: /* a literal */
1132: lit++;
1133: swd->max_chain = SC_MAX_CHAIN;
1134: r = find_match(c,swd,1,0);
1135: assert(r == 0);
1136: continue;
1137: }
1138:
1139: /* a match */
1140: assert_match(swd,m_len,m_off);
1141:
1142: /* shall we try a lazy match ? */
1143: ahead = 0;
1144: if (SC_TRY_LAZY <= 0 || m_len >= SC_MAX_LAZY || m_off ==
1145: c->last_m_off)
1146:
1147: {
1148: /* no */
1149: l1 = 0;
1150: max_ahead = 0;
1151: }
1152: else
1153: {
1154: /* yes, try a lazy match */
1155: l1 = len_of_coded_match(c,m_len,m_off);
1156: assert(l1 > 0);
1157: max_ahead = SC_TRY_LAZY;
1158: if ((m_len - 1) < max_ahead) {
1159: max_ahead = m_len -1;
1160: }
1161: }
1162:
1163: while (ahead < max_ahead && c->look > m_len)
1164: {
1165: if (m_len >= SC_GOOD_LENGTH)
1166: swd->max_chain = SC_MAX_CHAIN >> 2;
1167: else
1168: swd->max_chain = SC_MAX_CHAIN;
1169: r = find_match(c,swd,1,0);
1170: ahead++;
1171:
1172: assert(r == 0);
1173: assert(c->look > 0);
1174: assert(ii + lit + ahead == c->bp);
1175:
1176: if (c->m_len < 2)
1177: continue;
1178: l2 = len_of_coded_match(c,c->m_len,c->m_off);
1179: if (l2 < 0)
1180: continue;
1181: if (l1 + (int)(ahead + c->m_len - m_len) * 5 > l2 +
1182: (int)(ahead) * 9)
1183: {
1184: c->lazy++;
1185: assert_match(swd,c->m_len,c->m_off);
1186: lit += ahead;
1187: assert(ii + lit == c->bp);
1188: goto lazy_match_done;
1189: }
1190: }
1191:
1192: assert(ii + lit + ahead == c->bp);
1193:
1194: /* 1 - code run */
1195: code_run(c,ii,lit);
1196: lit = 0;
1197:
1198: /* 2 - code match */
1199: code_match(c,m_len,m_off);
1200: swd->max_chain = SC_MAX_CHAIN;
1201: r = find_match(c,swd,m_len,1+ahead);
1202: assert(r == 0);
1203:
1204: lazy_match_done: ;
1205: }
1206:
1207: /* store final run */
1208: code_run(c,ii,lit);
1209:
1210: /* EOF */
1211: bbPutBit(c, 0);
1212: code_prefix_ss11(c, 0x1000000U);
1213: bbPutByte(c, 0xff);
1214:
1215: bbFlushBits(c, 0);
1216:
1217: assert(c->textsize == in_len);
1218: c->codesize = c->bb_op - out;
1219: *out_len = c->bb_op - out;
1220:
1221: #if 0
1222: printf("%7ld %7ld -> %7ld %7ld %7ld %ld (max: %d %d %d)\n",
1223: (long) c->textsize, (long) in_len, (long) c->codesize,
1224: c->match_bytes, c->lit_bytes, c->lazy,
1225: c->result[1], c->result[3], c->result[5]);
1226: #endif
1227: assert(c->lit_bytes + c->match_bytes == in_len);
1228:
1229: swd_exit(swd);
1230: free(swd);
1231:
1232: return UCL_E_OK;
1233: }
1234:
1235:
1236: void Encode(void) /* compression */
1237: {
1238: uint8_t *in, *out;
1239: unsigned long in_len, out_len;
1240: uint32_t tw;
1241: int r;
1242: fseek(infile, 0, SEEK_END);
1243: in_len = ftell(infile);
1244: #ifdef VERBOSE
1245: if ((signed long)in_len < 0)
1246: Fprintf((stderr, "Errno: %d", errno));
1247: #endif
1248: #if UCLPACK_COMPAT
1249: {
1250: uint8_t byte;
1251: if (fwrite(magic, sizeof(magic), 1, outfile) != 1)
1252: Error("Can't write.");
1253: tw = htonl(0); /* flags */
1254: if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
1255: Error("Can't write.");
1256: byte = 0x2b; /* method */
1257: if (fwrite(&byte, sizeof(byte), 1, outfile) != 1)
1258: Error("Can't write.");
1259: byte = 10; /* level */
1260: if (fwrite(&byte, sizeof(byte), 1, outfile) != 1)
1261: Error("Can't write.");
1262: tw = htonl(256*1024); /* block_size */
1263: if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
1264: Error("Can't write.");
1265: tw = htonl(in_len);
1266: if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
1267: Error("Can't write."); /* output size of text */
1268: }
1269: #else
1270: tw = host_to_i86ul(in_len);
1271: if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
1272: Error("Can't write."); /* output size of text */
1273: #endif
1274: if (in_len == 0)
1275: return;
1276: rewind(infile);
1277:
1278: in = malloc(in_len);
1279: out_len = in_len + (in_len/8) + 256;
1280: out = malloc(out_len);
1281: if (!in || !out) {
1282: Error("Can't malloc");
1283: }
1284: if (fread(in, in_len, 1, infile) != 1) {
1285: Error("Can't read");
1286: }
1287: r = ucl_nrv2b_99_compress(in, in_len, out, &out_len, 0 );
1288: if (r != UCL_E_OK)
1289: Error("Compression failure\n");
1290: #if UCLPACK_COMPAT
1291: tw = htonl(out_len);
1292: if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
1293: Error("Can't write."); /* file size of text */
1294:
1295: #endif
1296: if (fwrite(out, out_len, 1, outfile) != 1) {
1297: Error("Write error\n");
1298: }
1299: #if UCLPACK_COMPAT
1300: tw = htonl(0); /* EOF marker */
1301: if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
1302: Error("Can't write.");
1303:
1304: #endif
1305:
1306: #ifdef LONG_REPORT
1307: Fprintf((stdout, "input size %ld bytes\n", in_len));
1308: Fprintf((stdout, "output size %ld bytes\n", out_len));
1309: Fprintf((stdout, "input/output %.3f\n", (double)in_len / out_len));
1310: #else
1311: Fprintf((stdout, "input/output = %ld/%ld = %.3f\n", in_len, out_len,
1312: (double)in_len / out_len));
1313: #endif
1314:
1315: }
1316:
1317: #endif
1318:
1319: #ifdef DECODE
1320:
1321: #define GETBIT_8(bb, src, ilen) \
1322: (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1)
1323:
1324: #define GETBIT_LE16(bb, src, ilen) \
1325: (bb*=2,bb&0xffff ? (bb>>16)&1 : (ilen+=2,((bb=(src[ilen-2]+src[ilen-1]*256u)*2+1)>>16)&1))
1326:
1327: #define GETBIT_LE32(bb, src, ilen) \
1328: (bc > 0 ? ((bb>>--bc)&1) : (bc=31,\
1329: bb=*(const uint32_t *)((src)+ilen),ilen+=4,(bb>>31)&1))
1330:
1331: #define GETBIT_LE64(bb, src, ilen) \
1332: (bc > 0 ? ((bb>>--bc)&1) : (bc=63, \
1333: bb=*(const uint64_t *)((src)+ilen),ilen+=8,(bb>>63)&1))
1334:
1335: #if ENDIAN == 0 && BITSIZE == 8
1336: #define GETBIT(bb, src, ilen) GETBIT_8(bb, src, ilen)
1337: #endif
1338: #if ENDIAN == 0 && BITSIZE == 16
1339: #define GETBIT(bb, src, ilen) GETBIT_LE16(bb, src, ilen)
1340: #endif
1341: #if ENDIAN == 0 && BITSIZE == 32
1342: #define GETBIT(bb, src, ilen) GETBIT_LE32(bb, src, ilen)
1343: #endif
1344: #if ENDIAN == 0 && BITSIZE == 64
1345: #define GETBIT(bb, src, ilen) GETBIT_LE64(bb, src, ilen)
1346: #endif
1347: #ifndef GETBIT
1348: #error "Bad Combination of ENDIAN and BITSIZE values specified"
1349: #endif
1350:
1351: #undef SAFE
1352:
1353: #ifdef SAFE
1354: #define FAIL(x,r) if (x) { Error(r); }
1355: #else
1356: #define FAIL(x,r)
1357: #endif
1358:
1359: void Decode(void) /* recover */
1360: {
1361: uint32_t tw;
1362: uint8_t *src, *dst;
1363: unsigned long max_src_len, src_len, dst_len;
1364: unsigned long ilen = 0, olen = 0, last_m_off = 1;
1365: #if BITSIZE <= 32
1366: uint32_t bb = 0;
1367: #elif BITSIZE == 64
1368: uint64_t bb = 0;
1369: #endif
1370: unsigned bc = 0;
1371: #if UCLPACK_COMPAT
1372: if (fseek(infile, sizeof(magic) + sizeof(tw) + 1 + 1 + sizeof(tw),
1373: SEEK_SET) != 0)
1374:
1375: Error("Seek Error");
1376: if (fread(&tw, sizeof(tw), 1, infile) < 1)
1377: Error("Can't read"); /* read size of text */
1378: dst_len = ntohl(tw);
1379: if (fread(&tw, sizeof(tw), 1, infile) < 1)
1380: Error("Can't read"); /* read size of file */
1381: max_src_len = ntohl(tw);
1382: #else
1383: if (fread(&tw, sizeof(tw), 1, infile) < 1)
1384: Error("Can't read"); /* read size of text */
1385: dst_len = i86ul_to_host(tw);
1386: max_src_len = dst_len + (dst_len/8) + 256;
1387: #endif
1388: if (dst_len == 0)
1389: return;
1390: dst = malloc(dst_len);
1391: if (!dst)
1392: Error("Can't malloc");
1393: src = malloc(max_src_len);
1394: if (!src)
1395: Error("Can't malloc");
1396: src_len = fread(src, 1, max_src_len, infile);
1397: if (src_len <= 0)
1398: Error("Can't read");
1399:
1400: for(;;) {
1401: unsigned int m_off, m_len;
1402: while(GETBIT(bb, src, ilen)) {
1403: FAIL(ilen >= src_len, "input overrun");
1404: FAIL(olen >= dst_len, "output overrun");
1405: dst[olen++] = src[ilen++];
1406: }
1407: m_off = 1;
1408: do {
1409: m_off = m_off*2 + GETBIT(bb, src, ilen);
1410: FAIL(ilen >= src_len, "input overrun");
1411: FAIL(m_off > 0xffffffU +3, "lookbehind overrun");
1412: } while (!GETBIT(bb, src, ilen));
1413: if (m_off == 2)
1414: {
1415: m_off = last_m_off;
1416: }
1417: else
1418: {
1419: FAIL(ilen >= src_len, "input overrun");
1420: m_off = (m_off - 3)*256 + src[ilen++];
1421: if (m_off == 0xffffffffU)
1422: break;
1423: last_m_off = ++m_off;
1424: }
1425: m_len = GETBIT(bb, src, ilen);
1426: m_len = m_len*2 + GETBIT(bb, src, ilen);
1427: if (m_len == 0)
1428: {
1429: m_len++;
1430: do {
1431: m_len = m_len*2 + GETBIT(bb, src, ilen);
1432: FAIL(ilen >= src_len, "input overrun");
1433: FAIL(m_len >= dst_len, "output overrun");
1434: } while(!GETBIT(bb, src, ilen));
1435: m_len += 2;
1436: }
1437: m_len += (m_off > 0xd00);
1438: FAIL(olen + m_len > dst_len, "output overrun");
1439: FAIL(m_off > olen, "lookbeind overrun");
1440: {
1441: const uint8_t *m_pos;
1442: m_pos = dst + olen - m_off;
1443: dst[olen++] = *m_pos++;
1444: do {
1445: dst[olen++] = *m_pos++;
1446: } while(--m_len > 0);
1447: }
1448: }
1449: FAIL(ilen < src_len, "input not consumed");
1450: FAIL(ilen > src_len, "input overrun");
1451: assert(ilen == src_len);
1452: Fprintf((stderr, "%12ld\n", olen));
1453: if (dst_len != olen) {
1454: fprintf(stderr, "length != expected length\n");
1455: }
1456: if (fwrite(dst, olen, 1, outfile) != 1)
1457: Error("Write error\n");
1458: free(src);
1459: free(dst);
1460: }
1461: #endif
1462:
1463: #ifdef MAIN
1464: int main(int argc, char *argv[])
1465: {
1466: char *s;
1467: FILE *f;
1468: int c;
1469:
1470: if (argc == 2) {
1471: outfile = stdout;
1472: if ((f = tmpfile()) == NULL) {
1473: perror("tmpfile");
1474: return EXIT_FAILURE;
1475: }
1476: while ((c = getchar()) != EOF)
1477: fputc(c, f);
1478: rewind(infile = f);
1479: }
1480: else if (argc != 4) {
1481: Fprintf((stderr, "'nrv2b e file1 file2' encodes file1 into file2.\n"
1482: "'nrv2b d file2 file1' decodes file2 into file1.\n"));
1483: return EXIT_FAILURE;
1484: }
1485: if (argc == 4) {
1486: if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL)
1487: || (s = argv[2], (infile = fopen(s, "rb")) == NULL)
1488: || (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
1489: Fprintf((stderr, "??? %s\n", s));
1490: return EXIT_FAILURE;
1491: }
1492: }
1493: if (toupper(*argv[1]) == 'E')
1494: Encode();
1495: else
1496: Decode();
1497: fclose(infile);
1498: fclose(outfile);
1499: return EXIT_SUCCESS;
1500: }
1501: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.