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
7 minor beautifications and adjustments for compiling under Linux
8 by Markus Gutschke <gutschk@math.uni-muenster.de>
11 Modifications to allow use as a filter by Ken Yap
12 <ken_yap@users.sourceforge.net>.
16 Small mod to cope with running on big-endian machines
17 by Jim Hague <jim.hague@acm.org)
20 Make compression statistics report shorter
21 by Ken Yap <ken_yap@users.sourceforge.net>.
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 <ebiederman@lnxi.com>.
32 **************************************************************/
33 #define UCLPACK_COMPAT 0
43 #include <netinet/in.h>
50 #define Fprintf(x) fprintf x
56 FILE *infile, *outfile;
58 #if defined(ENCODE) || defined(DECODE)
67 static __inline__ void Error(char *message)
69 Fprintf((stderr, "\n%s\n", message));
73 /* These will be a complete waste of time on a lo-endian */
74 /* system, but it only gets done once so WTF. */
75 static unsigned long i86ul_to_host(unsigned long ul)
77 unsigned long res = 0;
86 for (i = 3; i >= 0; i--)
87 res = (res << 8) + u.c[i];
91 static unsigned long host_to_i86ul(unsigned long ul)
100 for (i = 0; i < 4; i++)
112 /* magic file header for compressed files */
113 static const unsigned char magic[8] =
114 { 0x00, 0xe9, 0x55, 0x43, 0x4c, 0xff, 0x01, 0x1a };
119 /********** NRV2B_99 compression **********/
121 #define N (1024*1024ul) /* size of ring buffer */
122 #define THRESHOLD 1 /* lower limit for match length */
123 #define F 2048 /* upper limit for match length */
124 #define M2_MAX_OFFSET 0xd00
126 /* note: to use default values pass -1, i.e. initialize
127 * this struct by a memset(x,0xff,sizeof(x)) */
128 struct ucl_compress_config
132 unsigned int max_offset;
133 unsigned int max_match;
145 unsigned int look; /* bytes in lookahead buffer */
150 unsigned int last_m_len;
151 unsigned int last_m_off;
153 const unsigned char *bp;
154 const unsigned char *ip;
155 const unsigned char *in;
156 const unsigned char *in_end;
161 unsigned bb_c_endian;
165 unsigned char *bb_op;
167 struct ucl_compress_config conf;
168 unsigned int *result;
170 unsigned int textsize; /* text size counter */
171 unsigned int codesize; /* code size counter */
172 unsigned int printcount; /* counter for reporting progress every 1K
177 unsigned long lit_bytes;
178 unsigned long match_bytes;
179 unsigned long rep_bytes;
185 #define getbyte(c) ((c).ip < (c).in_end ? *((c).ip)++ : (-1))
188 #define UCL_E_INVALID_ARGUMENT 1
189 #define UCL_E_OUT_OF_MEMORY 2
190 #define UCL_E_ERROR 3
192 /***********************************************************************
194 ************************************************************************/
196 #define SWD_HSIZE 16384
197 #define SWD_MAX_CHAIN 2048
200 (((0x9f5f*(((((uint32_t)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & (SWD_HSIZE-1))
202 #define HEAD2(b,p) (b[p] ^ ((unsigned)b[p+1]<<8))
203 #define NIL2 UINT_MAX
207 /* public - "built-in" */
210 unsigned int threshold;
212 /* public - configuration */
213 unsigned int max_chain;
214 unsigned int nice_length;
216 unsigned int lazy_insert;
218 /* public - output */
223 #if defined(SWD_BEST_OFF)
224 unsigned int best_off[ SWD_BEST_OFF ];
228 struct ucl_compress *c;
230 #if defined(SWD_BEST_OFF)
231 unsigned int best_pos[ SWD_BEST_OFF ];
236 const uint8_t *dict_end;
237 unsigned int dict_len;
240 unsigned int ip; /* input pointer (lookahead) */
241 unsigned int bp; /* buffer pointer */
242 unsigned int rp; /* remove pointer */
245 unsigned char *b_wrap;
247 unsigned int node_count;
248 unsigned int first_rp;
250 unsigned char b [ N + F + F ];
251 unsigned int head3 [ SWD_HSIZE ];
252 unsigned int succ3 [ N + F ];
253 unsigned int best3 [ N + F ];
254 unsigned int llen3 [ SWD_HSIZE ];
255 unsigned int head2 [ 65536U ];
258 #define s_head3(s,key) s->head3[key]
261 #if !defined( NDEBUG)
262 static void assert_match(const struct ucl_swd * swd, unsigned int m_len,
266 const struct ucl_compress *c = swd->c;
270 if (m_off <= (unsigned int) (c->bp - c->in))
272 assert(c->bp - m_off + m_len < c->ip);
273 assert(memcmp(c->bp, c->bp - m_off, m_len) == 0);
277 assert(swd->dict != NULL);
278 d_off = m_off - (unsigned int) (c->bp - c->in);
279 assert(d_off <= swd->dict_len);
282 assert(memcmp(c->bp, swd->dict_end - d_off, d_off) ==
285 assert(c->in + m_len - d_off < c->ip);
286 assert(memcmp(c->bp + d_off, c->in, m_len - d_off) ==
292 assert(memcmp(c->bp, swd->dict_end - d_off, m_len) ==
299 # define assert_match(a,b,c) ((void)0)
302 /***********************************************************************
304 ************************************************************************/
308 void swd_initdict(struct ucl_swd *s, const uint8_t *dict, unsigned int dict_len)
311 s->dict = s->dict_end = NULL;
314 if (!dict || dict_len <= 0)
318 dict += dict_len - s->n;
323 s->dict_len = dict_len;
324 s->dict_end = dict + dict_len;
325 memcpy(s->b,dict,dict_len);
331 void swd_insertdict(struct ucl_swd *s, unsigned int node, unsigned int len)
335 s->node_count = s->n - len;
340 key = HEAD3(s->b,node);
341 s->succ3[node] = s_head3(s,key);
342 s->head3[key] = (unsigned int)(node);
343 s->best3[node] = (unsigned int)(s->f + 1);
345 assert(s->llen3[key] <= s->n);
347 key = HEAD2(s->b,node);
348 s->head2[key] = (unsigned int)(node);
354 /***********************************************************************
356 ************************************************************************/
360 int swd_init(struct ucl_swd *s, const uint8_t *dict, unsigned int dict_len)
369 s->threshold = THRESHOLD;
370 if (s->n > N || s->f > F)
371 return UCL_E_INVALID_ARGUMENT;
374 s->max_chain = SWD_MAX_CHAIN;
375 s->nice_length = s->f;
379 s->b_size = s->n + s->f;
380 if (s->b_size + s->f >= UINT_MAX)
382 s->b_wrap = s->b + s->b_size;
383 s->node_count = s->n;
385 memset(s->llen3, 0, sizeof(s->llen3[0]) * SWD_HSIZE);
386 for (i = 0; i < 65536U; i++)
390 swd_initdict(s,dict,dict_len);
394 assert(s->ip + s->f <= s->b_size);
396 s->look = (unsigned int) (s->c->in_end - s->c->ip);
401 memcpy(&s->b[s->ip],s->c->ip,s->look);
405 if (s->ip == s->b_size)
408 if (s->look >= 2 && s->dict_len > 0)
409 swd_insertdict(s,0,s->dict_len);
412 if (s->rp >= s->node_count)
413 s->rp -= s->node_count;
415 s->rp += s->b_size - s->node_count;
424 void swd_exit(struct ucl_swd *s)
430 #define swd_pos2off(s,pos) \
431 (s->bp > (pos) ? s->bp - (pos) : s->b_size - ((pos) - s->bp))
433 /***********************************************************************
435 ************************************************************************/
438 void swd_getbyte(struct ucl_swd *s)
442 if ((c = getbyte(*(s->c))) < 0)
449 s->b[s->ip] = (uint8_t)(c);
451 s->b_wrap[s->ip] = (uint8_t)(c);
453 if (++s->ip == s->b_size)
455 if (++s->bp == s->b_size)
457 if (++s->rp == s->b_size)
460 /***********************************************************************
461 // remove node from lists
462 ************************************************************************/
465 void swd_remove_node(struct ucl_swd *s, unsigned int node)
467 if (s->node_count == 0)
472 if (s->first_rp != UINT_MAX)
474 if (node != s->first_rp)
475 printf("Remove %5d: %5d %5d %5d %5d %6d %6d\n",
477 node, s->rp, s->ip, s->bp, s->first_rp,
478 s->ip - node, s->ip - s->bp);
479 assert(node == s->first_rp);
480 s->first_rp = UINT_MAX;
484 key = HEAD3(s->b,node);
485 assert(s->llen3[key] > 0);
488 key = HEAD2(s->b,node);
489 assert(s->head2[key] != NIL2);
490 if ((unsigned int) s->head2[key] == node)
491 s->head2[key] = NIL2;
498 /***********************************************************************
500 ************************************************************************/
504 void swd_accept(struct ucl_swd *s, unsigned int n)
506 assert(n <= s->look);
512 swd_remove_node(s,s->rp);
514 /* add bp into HEAD3 */
515 key = HEAD3(s->b,s->bp);
516 s->succ3[s->bp] = s_head3(s,key);
517 s->head3[key] = (unsigned int)(s->bp);
518 s->best3[s->bp] = (unsigned int)(s->f + 1);
520 assert(s->llen3[key] <= s->n);
522 /* add bp into HEAD2 */
523 key = HEAD2(s->b,s->bp);
524 s->head2[key] = (unsigned int)(s->bp);
530 /***********************************************************************
532 ************************************************************************/
535 void swd_search(struct ucl_swd *s, unsigned int node, unsigned int cnt)
537 const unsigned char *p1;
538 const unsigned char *p2;
539 const unsigned char *px;
541 unsigned int m_len = s->m_len;
542 const unsigned char * b = s->b;
543 const unsigned char * bp = s->b + s->bp;
544 const unsigned char * bx = s->b + s->bp + s->look;
545 unsigned char scan_end1;
547 assert(s->m_len > 0);
549 scan_end1 = bp[m_len - 1];
550 for ( ; cnt-- > 0; node = s->succ3[node])
556 assert(m_len < s->look);
559 p2[m_len - 1] == scan_end1 &&
560 p2[m_len] == p1[m_len] &&
565 assert(memcmp(bp,&b[node],3) == 0);
568 do {} while (++p1 < px && *p1 == *++p2);
572 if (memcmp(bp,&b[node],i) != 0)
573 printf("%5ld %5ld %02x%02x %02x%02x\n",
574 (long)s->bp, (long) node,
575 bp[0], bp[1], b[node], b[node+1]);
577 assert(memcmp(bp,&b[node],i) == 0);
579 #if defined(SWD_BEST_OFF)
580 if (i < SWD_BEST_OFF)
582 if (s->best_pos[i] == 0)
583 s->best_pos[i] = node + 1;
588 s->m_len = m_len = i;
590 if (m_len == s->look)
592 if (m_len >= s->nice_length)
594 if (m_len > (unsigned int) s->best3[node])
596 scan_end1 = bp[m_len - 1];
602 static int swd_search2(struct ucl_swd *s)
606 assert(s->look >= 2);
607 assert(s->m_len > 0);
609 key = s->head2[ HEAD2(s->b,s->bp) ];
613 if (memcmp(&s->b[s->bp],&s->b[key],2) != 0)
614 printf("%5ld %5ld %02x%02x %02x%02x\n", (long)s->bp, (long)key,
615 s->b[s->bp], s->b[s->bp+1], s->b[key], s->b[key+1]);
617 assert(memcmp(&s->b[s->bp],&s->b[key],2) == 0);
618 #if defined(SWD_BEST_OFF)
619 if (s->best_pos[2] == 0)
620 s->best_pos[2] = key + 1;
631 /***********************************************************************
633 ************************************************************************/
636 void swd_findbest(struct ucl_swd *s)
639 unsigned int cnt, node;
642 assert(s->m_len > 0);
644 /* get current head, add bp into HEAD3 */
645 key = HEAD3(s->b,s->bp);
646 node = s->succ3[s->bp] = s_head3(s,key);
647 cnt = s->llen3[key]++;
648 assert(s->llen3[key] <= s->n + s->f);
649 if (cnt > s->max_chain && s->max_chain > 0)
651 s->head3[key] = (unsigned int)(s->bp);
653 s->b_char = s->b[s->bp];
655 if (s->m_len >= s->look)
660 s->best3[s->bp] = (unsigned int)(s->f + 1);
666 swd_search(s,node,cnt);
668 s->m_off = swd_pos2off(s,s->m_pos);
669 s->best3[s->bp] = (unsigned int)(s->m_len);
671 #if defined(SWD_BEST_OFF)
675 for (i = 2; i < SWD_BEST_OFF; i++)
676 if (s->best_pos[i] > 0)
678 swd_pos2off(s,s->best_pos[i]-1);
686 swd_remove_node(s,s->rp);
688 /* add bp into HEAD2 */
689 key = HEAD2(s->b,s->bp);
690 s->head2[key] = (unsigned int)(s->bp);
694 /***********************************************************************
696 ************************************************************************/
699 init_match ( struct ucl_compress *c, struct ucl_swd *s,
700 const uint8_t *dict, unsigned int dict_len,
710 c->last_m_len = c->last_m_off = 0;
712 c->textsize = c->codesize = c->printcount = 0;
713 c->lit_bytes = c->match_bytes = c->rep_bytes = 0;
716 r = swd_init(s,dict,dict_len);
723 s->use_best_off = (flags & 1) ? 1 : 0;
728 find_match ( struct ucl_compress *c, struct ucl_swd *s,
729 unsigned int this_len, unsigned int skip )
735 assert(this_len >= skip);
736 swd_accept(s, this_len - skip);
737 c->textsize += this_len - skip + 1;
741 assert(this_len <= 1);
742 c->textsize += this_len - skip;
745 s->m_len = THRESHOLD;
748 memset(s->best_pos,0,sizeof(s->best_pos));
764 c->look = s->look + 1;
766 c->bp = c->ip - c->look;
769 /* brute force match search */
770 if (c->m_len > THRESHOLD && c->m_len + 1 <= c->look)
772 const uint8_t *ip = c->bp;
773 const uint8_t *m = c->bp - c->m_off;
774 const uint8_t *in = c->in;
785 if (memcmp(in,ip,c->m_len+1) == 0)
786 printf("%p %p %p %5d\n",
787 in, ip, m, c->m_len);
798 static int bbConfig(struct ucl_compress *c, int endian, int bitsize)
804 c->bb_c_endian = endian;
808 if (bitsize != 8 && bitsize != 16 && bitsize != 32)
811 c->bb_c_s8 = bitsize / 8;
813 c->bb_b = 0; c->bb_k = 0;
819 static void bbWriteBits(struct ucl_compress *c)
821 uint8_t *p = c->bb_p;
822 uint32_t b = c->bb_b;
824 p[0] = (uint8_t)(b >> 0);
827 p[1] = (uint8_t)(b >> 8);
830 p[2] = (uint8_t)(b >> 16);
831 p[3] = (uint8_t)(b >> 24);
837 static void bbPutBit(struct ucl_compress *c, unsigned bit)
839 assert(bit == 0 || bit == 1);
840 assert(c->bb_k <= c->bb_c_s);
842 if (c->bb_k < c->bb_c_s)
846 assert(c->bb_p == NULL);
848 c->bb_op += c->bb_c_s8;
850 assert(c->bb_p != NULL);
851 assert(c->bb_p + c->bb_c_s8 <= c->bb_op);
853 c->bb_b = (c->bb_b << 1) + bit;
858 assert(c->bb_p != NULL);
859 assert(c->bb_p + c->bb_c_s8 <= c->bb_op);
863 c->bb_op += c->bb_c_s8;
870 static void bbPutByte(struct ucl_compress *c, unsigned b)
872 /**printf("putbyte %p %p %x (%d)\n", op, bb_p, x, bb_k);*/
873 assert(c->bb_p == NULL || c->bb_p + c->bb_c_s8 <= c->bb_op);
874 *c->bb_op++ = (uint8_t)(b);
877 static void bbFlushBits(struct ucl_compress *c, unsigned filler_bit)
881 assert(c->bb_k <= c->bb_c_s);
882 while (c->bb_k != c->bb_c_s)
883 bbPutBit(c, filler_bit);
892 /***********************************************************************
894 ************************************************************************/
897 static void code_prefix_ss11(struct ucl_compress *c, uint32_t i)
909 bbPutBit(c, (i & t) ? 1 : 0);
913 bbPutBit(c, (unsigned)i & 1);
918 code_match(struct ucl_compress *c, unsigned int m_len, const unsigned int m_off)
921 while (m_len > c->conf.max_match)
923 code_match(c, c->conf.max_match - 3, m_off);
924 m_len -= c->conf.max_match - 3;
927 c->match_bytes += m_len;
928 if (m_len > c->result[3])
929 c->result[3] = m_len;
930 if (m_off > c->result[1])
931 c->result[1] = m_off;
935 if (m_off == c->last_m_off)
942 code_prefix_ss11(c, 1 + ((m_off - 1) >> 8));
943 bbPutByte(c, (unsigned)m_off - 1);
945 m_len = m_len - 1 - (m_off > M2_MAX_OFFSET);
950 code_prefix_ss11(c, m_len - 4);
954 bbPutBit(c, m_len > 1);
955 bbPutBit(c, (unsigned)m_len & 1);
958 c->last_m_off = m_off;
962 code_run(struct ucl_compress *c, const uint8_t *ii, unsigned int lit)
967 if (lit > c->result[5])
975 /***********************************************************************
977 ************************************************************************/
980 len_of_coded_match(struct ucl_compress *c, unsigned int m_len, unsigned int
985 if (m_len < 2 || (m_len == 2 && (m_off > M2_MAX_OFFSET))
986 || m_off > c->conf.max_offset)
990 m_len = m_len - 2 - (m_off > M2_MAX_OFFSET);
992 if (m_off == c->last_m_off)
997 m_off = (m_off - 1) >> 8;
1013 } while (m_len > 0);
1018 int ucl_nrv2b_99_compress(
1019 const uint8_t *in, unsigned long in_len,
1020 uint8_t *out, unsigned long *out_len,
1021 unsigned int *result)
1025 unsigned int m_len, m_off;
1026 struct ucl_compress c_buffer;
1027 struct ucl_compress * const c = &c_buffer;
1028 struct ucl_swd *swd;
1029 unsigned int result_buffer[16];
1032 /* max compression */
1033 #define SC_TRY_LAZY 2
1034 #define SC_GOOD_LENGTH F
1035 #define SC_MAX_LAZY F
1036 #define SC_NICE_LENGTH F
1037 #define SC_MAX_CHAIN 4096
1039 #define SC_MAX_OFFSET N
1041 memset(c, 0, sizeof(*c));
1043 c->in_end = in + in_len;
1045 c->result = result ? result : result_buffer;
1046 memset(c->result, 0, 16*sizeof(*c->result));
1047 c->result[0] = c->result[2] = c->result[4] = UINT_MAX;
1049 memset(&c->conf, 0xff, sizeof(c->conf));
1050 r = bbConfig(c, ENDIAN, BITSIZE);
1052 r = bbConfig(c, c->conf.bb_endian, c->conf.bb_size);
1054 return UCL_E_INVALID_ARGUMENT;
1057 ii = c->ip; /* point to start of literal run */
1061 swd = (struct ucl_swd *) malloc(sizeof(*swd));
1063 return UCL_E_OUT_OF_MEMORY;
1067 if (in_len >= 256 && in_len < swd->n)
1069 if (swd->f < 8 || swd->n < 256)
1070 return UCL_E_INVALID_ARGUMENT;
1072 r = init_match(c,swd,NULL,0, SC_FLAGS);
1078 if (SC_MAX_CHAIN > 0)
1079 swd->max_chain = SC_MAX_CHAIN;
1080 if (SC_NICE_LENGTH > 0)
1081 swd->nice_length = SC_NICE_LENGTH;
1082 if (c->conf.max_match < swd->nice_length)
1083 swd->nice_length = c->conf.max_match;
1086 r = find_match(c,swd,0,0);
1092 unsigned int max_ahead;
1095 c->codesize = c->bb_op - out;
1100 assert(c->bp == c->ip - c->look);
1101 assert(c->bp >= in);
1104 assert(ii + lit == c->bp);
1105 assert(swd->b_char == *(c->bp));
1107 if (m_len < 2 || (m_len == 2 && (m_off > M2_MAX_OFFSET))
1108 || m_off > c->conf.max_offset)
1112 swd->max_chain = SC_MAX_CHAIN;
1113 r = find_match(c,swd,1,0);
1119 assert_match(swd,m_len,m_off);
1121 /* shall we try a lazy match ? */
1123 if (SC_TRY_LAZY <= 0 || m_len >= SC_MAX_LAZY || m_off ==
1133 /* yes, try a lazy match */
1134 l1 = len_of_coded_match(c,m_len,m_off);
1136 max_ahead = SC_TRY_LAZY;
1137 if ((m_len - 1) < max_ahead) {
1138 max_ahead = m_len -1;
1142 while (ahead < max_ahead && c->look > m_len)
1144 if (m_len >= SC_GOOD_LENGTH)
1145 swd->max_chain = SC_MAX_CHAIN >> 2;
1147 swd->max_chain = SC_MAX_CHAIN;
1148 r = find_match(c,swd,1,0);
1152 assert(c->look > 0);
1153 assert(ii + lit + ahead == c->bp);
1157 l2 = len_of_coded_match(c,c->m_len,c->m_off);
1160 if (l1 + (int)(ahead + c->m_len - m_len) * 5 > l2 +
1164 assert_match(swd,c->m_len,c->m_off);
1166 assert(ii + lit == c->bp);
1167 goto lazy_match_done;
1171 assert(ii + lit + ahead == c->bp);
1177 /* 2 - code match */
1178 code_match(c,m_len,m_off);
1179 swd->max_chain = SC_MAX_CHAIN;
1180 r = find_match(c,swd,m_len,1+ahead);
1186 /* store final run */
1191 code_prefix_ss11(c, 0x1000000U);
1196 assert(c->textsize == in_len);
1197 c->codesize = c->bb_op - out;
1198 *out_len = c->bb_op - out;
1201 printf("%7ld %7ld -> %7ld %7ld %7ld %ld (max: %d %d %d)\n",
1202 (long) c->textsize, (long) in_len, (long) c->codesize,
1203 c->match_bytes, c->lit_bytes, c->lazy,
1204 c->result[1], c->result[3], c->result[5]);
1206 assert(c->lit_bytes + c->match_bytes == in_len);
1215 void Encode(void) /* compression */
1218 unsigned long in_len, out_len;
1221 fseek(infile, 0, SEEK_END);
1222 in_len = ftell(infile);
1224 if ((signed long)in_len < 0)
1225 Fprintf((stderr, "Errno: %d", errno));
1230 if (fwrite(magic, sizeof(magic), 1, outfile) != 1)
1231 Error("Can't write.");
1232 tw = htonl(0); /* flags */
1233 if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
1234 Error("Can't write.");
1235 byte = 0x2b; /* method */
1236 if (fwrite(&byte, sizeof(byte), 1, outfile) != 1)
1237 Error("Can't write.");
1238 byte = 10; /* level */
1239 if (fwrite(&byte, sizeof(byte), 1, outfile) != 1)
1240 Error("Can't write.");
1241 tw = htonl(256*1024); /* block_size */
1242 if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
1243 Error("Can't write.");
1245 if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
1246 Error("Can't write."); /* output size of text */
1249 tw = host_to_i86ul(in_len);
1250 if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
1251 Error("Can't write."); /* output size of text */
1257 in = malloc(in_len);
1258 out_len = in_len + (in_len/8) + 256;
1259 out = malloc(out_len);
1261 Error("Can't malloc");
1263 if (fread(in, in_len, 1, infile) != 1) {
1264 Error("Can't read");
1266 r = ucl_nrv2b_99_compress(in, in_len, out, &out_len, 0 );
1268 tw = htonl(out_len);
1269 if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
1270 Error("Can't write."); /* file size of text */
1273 if (fwrite(out, out_len, 1, outfile) != 1) {
1274 Error("Write error\n");
1277 tw = htonl(0); /* EOF marker */
1278 if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
1279 Error("Can't write.");
1284 Fprintf((stderr, "input size %ld bytes\n", in_len));
1285 Fprintf((stderr, "output size %ld bytes\n", out_len));
1286 Fprintf((stderr, "input/output %.3f\n", (double)in_len / out_len));
1288 Fprintf((stderr, "input/output = %ld/%ld = %.3f\n", in_len, out_len,
1289 (double)in_len / out_len));
1298 #define GETBIT_8(bb, src, ilen) \
1299 (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1)
1301 #define GETBIT_LE16(bb, src, ilen) \
1302 (bb*=2,bb&0xffff ? (bb>>16)&1 : (ilen+=2,((bb=(src[ilen-2]+src[ilen-1]*256u)*2+1)>>16)&1))
1304 #define GETBIT_LE32(bb, src, ilen) \
1305 (bc > 0 ? ((bb>>--bc)&1) : (bc=31,\
1306 bb=*(const uint32_t *)((src)+ilen),ilen+=4,(bb>>31)&1))
1308 #if ENDIAN == 0 && BITSIZE == 8
1309 #define GETBIT(bb, src, ilen) GETBIT_8(bb, src, ilen)
1311 #if ENDIAN == 0 && BITSIZE == 16
1312 #define GETBIT(bb, src, ilen) GETBIT_LE16(bb, src, ilen)
1314 #if ENDIAN == 0 && BITSIZE == 32
1315 #define GETBIT(bb, src, ilen) GETBIT_LE32(bb, src, ilen)
1319 #error "Bad Combination of ENDIAN and BITSIZE values specified"
1325 #define FAIL(x,r) if (x) { Error(r); }
1330 void Decode(void) /* recover */
1334 unsigned long max_src_len, src_len, dst_len;
1335 unsigned long ilen = 0, olen = 0, last_m_off = 1;
1339 if (fseek(infile, sizeof(magic) + sizeof(tw) + 1 + 1 + sizeof(tw),
1342 Error("Seek Error");
1343 if (fread(&tw, sizeof(tw), 1, infile) < 1)
1344 Error("Can't read"); /* read size of text */
1345 dst_len = ntohl(tw);
1346 if (fread(&tw, sizeof(tw), 1, infile) < 1)
1347 Error("Can't read"); /* read size of file */
1348 max_src_len = ntohl(tw);
1350 if (fread(&tw, sizeof(tw), 1, infile) < 1)
1351 Error("Can't read"); /* read size of text */
1352 dst_len = i86ul_to_host(tw);
1353 max_src_len = dst_len + (dst_len/8) + 256;
1357 dst = malloc(dst_len);
1359 Error("Can't malloc");
1360 src = malloc(max_src_len);
1362 Error("Can't malloc");
1363 src_len = fread(src, 1, max_src_len, infile);
1365 Error("Can't read");
1368 unsigned int m_off, m_len;
1369 while(GETBIT(bb, src, ilen)) {
1370 FAIL(ilen >= src_len, "input overrun");
1371 FAIL(olen >= dst_len, "output overrun");
1372 dst[olen++] = src[ilen++];
1376 m_off = m_off*2 + GETBIT(bb, src, ilen);
1377 FAIL(ilen >= src_len, "input overrun");
1378 FAIL(m_off > 0xffffffU +3, "lookbehind overrun");
1379 } while (!GETBIT(bb, src, ilen));
1386 FAIL(ilen >= src_len, "input overrun");
1387 m_off = (m_off - 3)*256 + src[ilen++];
1388 if(m_off == 0xffffffffU)
1390 last_m_off = ++m_off;
1392 m_len = GETBIT(bb, src, ilen);
1393 m_len = m_len*2 + GETBIT(bb, src, ilen);
1398 m_len = m_len*2 + GETBIT(bb, src, ilen);
1399 FAIL(ilen >= src_len, "input overrun");
1400 FAIL(m_len >= dst_len, "output overrun");
1401 } while(!GETBIT(bb, src, ilen));
1404 m_len += (m_off > 0xd00);
1405 FAIL(olen + m_len > dst_len, "output overrun");
1406 FAIL(m_off > olen, "lookbeind overrun");
1408 const uint8_t *m_pos;
1409 m_pos = dst + olen - m_off;
1410 dst[olen++] = *m_pos++;
1412 dst[olen++] = *m_pos++;
1413 } while(--m_len > 0);
1416 FAIL(ilen < src_len, "input not consumed");
1417 FAIL(ilen > src_len, "input overrun");
1418 assert(ilen == src_len);
1419 Fprintf((stderr, "%12ld\n", olen));
1420 if (dst_len != olen) {
1421 fprintf(stderr, "length != expected length\n");
1423 if (fwrite(dst, olen, 1, outfile) != 1)
1424 Error("Write error\n");
1431 int main(int argc, char *argv[])
1439 if ((f = tmpfile()) == NULL) {
1441 return EXIT_FAILURE;
1443 while ((c = getchar()) != EOF)
1447 else if (argc != 4) {
1448 Fprintf((stderr, "'nrv2b e file1 file2' encodes file1 into file2.\n"
1449 "'nrv2b d file2 file1' decodes file2 into file1.\n"));
1451 return EXIT_FAILURE;
1454 if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL)
1455 || (s = argv[2], (infile = fopen(s, "rb")) == NULL)
1456 || (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
1457 Fprintf((stderr, "??? %s\n", s));
1458 return EXIT_FAILURE;
1461 if (toupper(*argv[1]) == 'E')
1467 return EXIT_SUCCESS;