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
48 #include <netinet/in.h>
55 #define Fprintf(x) fprintf x
61 FILE *infile
, *outfile
;
63 #if defined(ENCODE) || defined(DECODE)
72 static __inline__
void Error(char *message
)
74 Fprintf((stderr
, "\n%s\n", message
));
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
)
82 unsigned long res
= 0;
91 for (i
= 3; i
>= 0; i
--)
92 res
= (res
<< 8) + u
.c
[i
];
96 static unsigned long host_to_i86ul(unsigned long ul
)
105 for (i
= 0; i
< 4; i
++)
117 /* magic file header for compressed files */
118 static const unsigned char magic
[8] =
119 { 0x00, 0xe9, 0x55, 0x43, 0x4c, 0xff, 0x01, 0x1a };
124 /********** NRV2B_99 compression **********/
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.
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
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
146 unsigned int max_offset
;
147 unsigned int max_match
;
159 unsigned int look
; /* bytes in lookahead buffer */
164 unsigned int last_m_len
;
165 unsigned int last_m_off
;
167 const unsigned char *bp
;
168 const unsigned char *ip
;
169 const unsigned char *in
;
170 const unsigned char *in_end
;
175 unsigned bb_c_endian
;
179 unsigned char *bb_op
;
181 struct ucl_compress_config conf
;
182 unsigned int *result
;
184 unsigned int textsize
; /* text size counter */
185 unsigned int codesize
; /* code size counter */
186 unsigned int printcount
; /* counter for reporting progress every 1K
191 unsigned long lit_bytes
;
192 unsigned long match_bytes
;
193 unsigned long rep_bytes
;
199 #define getbyte(c) ((c).ip < (c).in_end ? *((c).ip)++ : (-1))
202 #define UCL_E_INVALID_ARGUMENT 1
203 #define UCL_E_OUT_OF_MEMORY 2
204 #define UCL_E_ERROR 3
206 /***********************************************************************
208 ************************************************************************/
210 #define SWD_HSIZE 16384
211 #define SWD_MAX_CHAIN 2048
212 #define SWD_BEST_OFF 1
215 (((0x9f5f*(((((uint32_t)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & (SWD_HSIZE-1))
217 #define HEAD2(b,p) (b[p] ^ ((unsigned)b[p+1]<<8))
218 #define NIL2 UINT_MAX
222 /* public - "built-in" */
225 unsigned int threshold
;
227 /* public - configuration */
228 unsigned int max_chain
;
229 unsigned int nice_length
;
231 unsigned int lazy_insert
;
233 /* public - output */
238 #if defined(SWD_BEST_OFF)
239 unsigned int best_off
[ SWD_BEST_OFF
];
243 struct ucl_compress
*c
;
245 #if defined(SWD_BEST_OFF)
246 unsigned int best_pos
[ SWD_BEST_OFF
];
251 const uint8_t *dict_end
;
252 unsigned int dict_len
;
255 unsigned int ip
; /* input pointer (lookahead) */
256 unsigned int bp
; /* buffer pointer */
257 unsigned int rp
; /* remove pointer */
260 unsigned char *b_wrap
;
262 unsigned int node_count
;
263 unsigned int first_rp
;
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 ];
273 #define s_head3(s,key) s->head3[key]
276 #if !defined( NDEBUG)
277 static void assert_match(const struct ucl_swd
* swd
, unsigned int m_len
,
281 const struct ucl_compress
*c
= swd
->c
;
285 if (m_off
<= (unsigned int) (c
->bp
- c
->in
))
287 assert(c
->bp
- m_off
+ m_len
< c
->ip
);
288 assert(memcmp(c
->bp
, c
->bp
- m_off
, m_len
) == 0);
292 assert(swd
->dict
!= NULL
);
293 d_off
= m_off
- (unsigned int) (c
->bp
- c
->in
);
294 assert(d_off
<= swd
->dict_len
);
297 assert(memcmp(c
->bp
, swd
->dict_end
- d_off
, d_off
) ==
300 assert(c
->in
+ m_len
- d_off
< c
->ip
);
301 assert(memcmp(c
->bp
+ d_off
, c
->in
, m_len
- d_off
) ==
307 assert(memcmp(c
->bp
, swd
->dict_end
- d_off
, m_len
) ==
314 # define assert_match(a,b,c) ((void)0)
317 /***********************************************************************
319 ************************************************************************/
323 void swd_initdict(struct ucl_swd
*s
, const uint8_t *dict
, unsigned int dict_len
)
326 s
->dict
= s
->dict_end
= NULL
;
329 if (!dict
|| dict_len
<= 0)
333 dict
+= dict_len
- s
->n
;
338 s
->dict_len
= dict_len
;
339 s
->dict_end
= dict
+ dict_len
;
340 memcpy(s
->b
,dict
,dict_len
);
346 void swd_insertdict(struct ucl_swd
*s
, unsigned int node
, unsigned int len
)
350 s
->node_count
= s
->n
- len
;
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);
360 assert(s
->llen3
[key
] <= s
->n
);
362 key
= HEAD2(s
->b
,node
);
363 s
->head2
[key
] = (unsigned int)(node
);
369 /***********************************************************************
371 ************************************************************************/
375 int swd_init(struct ucl_swd
*s
, const uint8_t *dict
, unsigned int dict_len
)
384 s
->threshold
= THRESHOLD
;
385 if (s
->n
> N
|| s
->f
> F
)
386 return UCL_E_INVALID_ARGUMENT
;
389 s
->max_chain
= SWD_MAX_CHAIN
;
390 s
->nice_length
= s
->f
;
394 s
->b_size
= s
->n
+ s
->f
;
395 if (s
->b_size
+ s
->f
>= UINT_MAX
)
397 s
->b_wrap
= s
->b
+ s
->b_size
;
398 s
->node_count
= s
->n
;
400 memset(s
->llen3
, 0, sizeof(s
->llen3
[0]) * SWD_HSIZE
);
401 for (i
= 0; i
< 65536U; i
++)
405 swd_initdict(s
,dict
,dict_len
);
409 assert(s
->ip
+ s
->f
<= s
->b_size
);
411 s
->look
= (unsigned int) (s
->c
->in_end
- s
->c
->ip
);
416 memcpy(&s
->b
[s
->ip
],s
->c
->ip
,s
->look
);
420 if (s
->ip
== s
->b_size
)
423 if (s
->look
>= 2 && s
->dict_len
> 0)
424 swd_insertdict(s
,0,s
->dict_len
);
427 if (s
->rp
>= s
->node_count
)
428 s
->rp
-= s
->node_count
;
430 s
->rp
+= s
->b_size
- s
->node_count
;
439 void swd_exit(struct ucl_swd
*s
)
445 #define swd_pos2off(s,pos) \
446 (s->bp > (pos) ? s->bp - (pos) : s->b_size - ((pos) - s->bp))
448 /***********************************************************************
450 ************************************************************************/
453 void swd_getbyte(struct ucl_swd
*s
)
457 if ((c
= getbyte(*(s
->c
))) < 0)
464 s
->b
[s
->ip
] = (uint8_t)(c
);
466 s
->b_wrap
[s
->ip
] = (uint8_t)(c
);
468 if (++s
->ip
== s
->b_size
)
470 if (++s
->bp
== s
->b_size
)
472 if (++s
->rp
== s
->b_size
)
475 /***********************************************************************
476 // remove node from lists
477 ************************************************************************/
480 void swd_remove_node(struct ucl_swd
*s
, unsigned int node
)
482 if (s
->node_count
== 0)
487 if (s
->first_rp
!= UINT_MAX
)
489 if (node
!= s
->first_rp
)
490 printf("Remove %5d: %5d %5d %5d %5d %6d %6d\n",
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
;
499 key
= HEAD3(s
->b
,node
);
500 assert(s
->llen3
[key
] > 0);
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
;
513 /***********************************************************************
515 ************************************************************************/
519 void swd_accept(struct ucl_swd
*s
, unsigned int n
)
521 assert(n
<= s
->look
);
527 swd_remove_node(s
,s
->rp
);
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);
535 assert(s
->llen3
[key
] <= s
->n
);
537 /* add bp into HEAD2 */
538 key
= HEAD2(s
->b
,s
->bp
);
539 s
->head2
[key
] = (unsigned int)(s
->bp
);
545 /***********************************************************************
547 ************************************************************************/
550 void swd_search(struct ucl_swd
*s
, unsigned int node
, unsigned int cnt
)
552 const unsigned char *p1
;
553 const unsigned char *p2
;
554 const unsigned char *px
;
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
;
562 assert(s
->m_len
> 0);
564 scan_end1
= bp
[m_len
- 1];
565 for ( ; cnt
-- > 0; node
= s
->succ3
[node
])
571 assert(m_len
< s
->look
);
574 p2
[m_len
- 1] == scan_end1
&&
575 p2
[m_len
] == p1
[m_len
] &&
580 assert(memcmp(bp
,&b
[node
],3) == 0);
583 do {} while (++p1
< px
&& *p1
== *++p2
);
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]);
592 assert(memcmp(bp
,&b
[node
],i
) == 0);
594 #if defined(SWD_BEST_OFF)
595 if (i
< SWD_BEST_OFF
)
597 if (s
->best_pos
[i
] == 0)
598 s
->best_pos
[i
] = node
+ 1;
603 s
->m_len
= m_len
= i
;
605 if (m_len
== s
->look
)
607 if (m_len
>= s
->nice_length
)
609 if (m_len
> (unsigned int) s
->best3
[node
])
611 scan_end1
= bp
[m_len
- 1];
617 static int swd_search2(struct ucl_swd
*s
)
621 assert(s
->look
>= 2);
622 assert(s
->m_len
> 0);
624 key
= s
->head2
[ HEAD2(s
->b
,s
->bp
) ];
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]);
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;
646 /***********************************************************************
648 ************************************************************************/
651 void swd_findbest(struct ucl_swd
*s
)
654 unsigned int cnt
, node
;
657 assert(s
->m_len
> 0);
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)
666 s
->head3
[key
] = (unsigned int)(s
->bp
);
668 s
->b_char
= s
->b
[s
->bp
];
670 if (s
->m_len
>= s
->look
)
675 s
->best3
[s
->bp
] = (unsigned int)(s
->f
+ 1);
681 swd_search(s
,node
,cnt
);
683 s
->m_off
= swd_pos2off(s
,s
->m_pos
);
684 s
->best3
[s
->bp
] = (unsigned int)(s
->m_len
);
686 #if defined(SWD_BEST_OFF)
690 for (i
= 2; i
< SWD_BEST_OFF
; i
++)
691 if (s
->best_pos
[i
] > 0)
693 swd_pos2off(s
,s
->best_pos
[i
]-1);
701 swd_remove_node(s
,s
->rp
);
703 /* add bp into HEAD2 */
704 key
= HEAD2(s
->b
,s
->bp
);
705 s
->head2
[key
] = (unsigned int)(s
->bp
);
709 /***********************************************************************
711 ************************************************************************/
714 init_match ( struct ucl_compress
*c
, struct ucl_swd
*s
,
715 const uint8_t *dict
, unsigned int dict_len
,
725 c
->last_m_len
= c
->last_m_off
= 0;
727 c
->textsize
= c
->codesize
= c
->printcount
= 0;
728 c
->lit_bytes
= c
->match_bytes
= c
->rep_bytes
= 0;
731 r
= swd_init(s
,dict
,dict_len
);
738 s
->use_best_off
= (flags
& 1) ? 1 : 0;
743 find_match ( struct ucl_compress
*c
, struct ucl_swd
*s
,
744 unsigned int this_len
, unsigned int skip
)
750 assert(this_len
>= skip
);
751 swd_accept(s
, this_len
- skip
);
752 c
->textsize
+= this_len
- skip
+ 1;
756 assert(this_len
<= 1);
757 c
->textsize
+= this_len
- skip
;
760 s
->m_len
= THRESHOLD
;
763 memset(s
->best_pos
,0,sizeof(s
->best_pos
));
779 c
->look
= s
->look
+ 1;
781 c
->bp
= c
->ip
- c
->look
;
784 /* brute force match search */
785 if (c
->m_len
> THRESHOLD
&& c
->m_len
+ 1 <= c
->look
)
787 const uint8_t *ip
= c
->bp
;
788 const uint8_t *m
= c
->bp
- c
->m_off
;
789 const uint8_t *in
= c
->in
;
800 if (memcmp(in
,ip
,c
->m_len
+1) == 0)
801 printf("%p %p %p %5d\n",in
,ip
,m
,c
->m_len
);
812 static int bbConfig(struct ucl_compress
*c
, int endian
, int bitsize
)
818 c
->bb_c_endian
= endian
;
822 if (bitsize
!= 8 && bitsize
!= 16 && bitsize
!= 32 && bitsize
!= 64)
825 c
->bb_c_s8
= bitsize
/ 8;
827 c
->bb_b
= 0; c
->bb_k
= 0;
833 static void bbWriteBits(struct ucl_compress
*c
)
835 uint8_t *p
= c
->bb_p
;
836 uint64_t b
= c
->bb_b
;
838 p
[0] = (uint8_t)(b
>> 0);
841 p
[1] = (uint8_t)(b
>> 8);
844 p
[2] = (uint8_t)(b
>> 16);
845 p
[3] = (uint8_t)(b
>> 24);
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);
858 static void bbPutBit(struct ucl_compress
*c
, unsigned bit
)
860 assert(bit
== 0 || bit
== 1);
861 assert(c
->bb_k
<= c
->bb_c_s
);
863 if (c
->bb_k
< c
->bb_c_s
)
867 assert(c
->bb_p
== NULL
);
869 c
->bb_op
+= c
->bb_c_s8
;
871 assert(c
->bb_p
!= NULL
);
872 assert(c
->bb_p
+ c
->bb_c_s8
<= c
->bb_op
);
874 c
->bb_b
= (c
->bb_b
<< 1) + bit
;
879 assert(c
->bb_p
!= NULL
);
880 assert(c
->bb_p
+ c
->bb_c_s8
<= c
->bb_op
);
884 c
->bb_op
+= c
->bb_c_s8
;
891 static void bbPutByte(struct ucl_compress
*c
, unsigned b
)
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
);
898 static void bbFlushBits(struct ucl_compress
*c
, unsigned filler_bit
)
902 assert(c
->bb_k
<= c
->bb_c_s
);
903 while (c
->bb_k
!= c
->bb_c_s
)
904 bbPutBit(c
, filler_bit
);
913 /***********************************************************************
915 ************************************************************************/
918 static void code_prefix_ss11(struct ucl_compress
*c
, uint32_t i
)
930 bbPutBit(c
, (i
& t
) ? 1 : 0);
934 bbPutBit(c
, (unsigned)i
& 1);
939 code_match(struct ucl_compress
*c
, unsigned int m_len
, const unsigned int m_off
)
942 while (m_len
> c
->conf
.max_match
)
944 code_match(c
, c
->conf
.max_match
- 3, m_off
);
945 m_len
-= c
->conf
.max_match
- 3;
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
;
956 if (m_off
== c
->last_m_off
)
963 code_prefix_ss11(c
, 1 + ((m_off
- 1) >> 8));
964 bbPutByte(c
, (unsigned)m_off
- 1);
966 m_len
= m_len
- 1 - (m_off
> M2_MAX_OFFSET
);
971 code_prefix_ss11(c
, m_len
- 4);
975 bbPutBit(c
, m_len
> 1);
976 bbPutBit(c
, (unsigned)m_len
& 1);
979 c
->last_m_off
= m_off
;
983 code_run(struct ucl_compress
*c
, const uint8_t *ii
, unsigned int lit
)
988 if (lit
> c
->result
[5])
996 /***********************************************************************
998 ************************************************************************/
1001 len_of_coded_match(struct ucl_compress
*c
, unsigned int m_len
, unsigned int
1006 if (m_len
< 2 || (m_len
== 2 && (m_off
> M2_MAX_OFFSET
))
1007 || m_off
> c
->conf
.max_offset
)
1011 m_len
= m_len
- 2 - (m_off
> M2_MAX_OFFSET
);
1013 if (m_off
== c
->last_m_off
)
1018 m_off
= (m_off
- 1) >> 8;
1034 } while (m_len
> 0);
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
)
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];
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
1060 #define SC_MAX_OFFSET N
1062 memset(c
, 0, sizeof(*c
));
1064 c
->in_end
= in
+ in_len
;
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
;
1070 memset(&c
->conf
, 0xff, sizeof(c
->conf
));
1071 r
= bbConfig(c
, ENDIAN
, BITSIZE
);
1073 r
= bbConfig(c
, c
->conf
.bb_endian
, c
->conf
.bb_size
);
1075 return UCL_E_INVALID_ARGUMENT
;
1078 ii
= c
->ip
; /* point to start of literal run */
1082 swd
= (struct ucl_swd
*) malloc(sizeof(*swd
));
1084 return UCL_E_OUT_OF_MEMORY
;
1088 if (in_len
>= 256 && in_len
< swd
->n
)
1090 if (swd
->f
< 8 || swd
->n
< 256)
1091 return UCL_E_INVALID_ARGUMENT
;
1093 r
= init_match(c
,swd
,NULL
,0, SC_FLAGS
);
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
;
1107 r
= find_match(c
,swd
,0,0);
1113 unsigned int max_ahead
;
1116 c
->codesize
= c
->bb_op
- out
;
1121 assert(c
->bp
== c
->ip
- c
->look
);
1122 assert(c
->bp
>= in
);
1125 assert(ii
+ lit
== c
->bp
);
1126 assert(swd
->b_char
== *(c
->bp
));
1128 if (m_len
< 2 || (m_len
== 2 && (m_off
> M2_MAX_OFFSET
))
1129 || m_off
> c
->conf
.max_offset
)
1133 swd
->max_chain
= SC_MAX_CHAIN
;
1134 r
= find_match(c
,swd
,1,0);
1140 assert_match(swd
,m_len
,m_off
);
1142 /* shall we try a lazy match ? */
1144 if (SC_TRY_LAZY
<= 0 || m_len
>= SC_MAX_LAZY
|| m_off
==
1154 /* yes, try a lazy match */
1155 l1
= len_of_coded_match(c
,m_len
,m_off
);
1157 max_ahead
= SC_TRY_LAZY
;
1158 if ((m_len
- 1) < max_ahead
) {
1159 max_ahead
= m_len
-1;
1163 while (ahead
< max_ahead
&& c
->look
> m_len
)
1165 if (m_len
>= SC_GOOD_LENGTH
)
1166 swd
->max_chain
= SC_MAX_CHAIN
>> 2;
1168 swd
->max_chain
= SC_MAX_CHAIN
;
1169 r
= find_match(c
,swd
,1,0);
1173 assert(c
->look
> 0);
1174 assert(ii
+ lit
+ ahead
== c
->bp
);
1178 l2
= len_of_coded_match(c
,c
->m_len
,c
->m_off
);
1181 if (l1
+ (int)(ahead
+ c
->m_len
- m_len
) * 5 > l2
+
1185 assert_match(swd
,c
->m_len
,c
->m_off
);
1187 assert(ii
+ lit
== c
->bp
);
1188 goto lazy_match_done
;
1192 assert(ii
+ lit
+ ahead
== c
->bp
);
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
);
1207 /* store final run */
1212 code_prefix_ss11(c
, 0x1000000U
);
1217 assert(c
->textsize
== in_len
);
1218 c
->codesize
= c
->bb_op
- out
;
1219 *out_len
= c
->bb_op
- out
;
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]);
1227 assert(c
->lit_bytes
+ c
->match_bytes
== in_len
);
1236 void Encode(void) /* compression */
1239 unsigned long in_len
, out_len
;
1242 fseek(infile
, 0, SEEK_END
);
1243 in_len
= ftell(infile
);
1245 if ((signed long)in_len
< 0)
1246 Fprintf((stderr
, "Errno: %d", errno
));
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.");
1266 if (fwrite(&tw
, sizeof(tw
), 1, outfile
) != 1)
1267 Error("Can't write."); /* output size of text */
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 */
1278 in
= malloc(in_len
);
1279 out_len
= in_len
+ (in_len
/8) + 256;
1280 out
= malloc(out_len
);
1282 Error("Can't malloc");
1284 if (fread(in
, in_len
, 1, infile
) != 1) {
1285 Error("Can't read");
1287 r
= ucl_nrv2b_99_compress(in
, in_len
, out
, &out_len
, 0 );
1289 Error("Compression failure\n");
1291 tw
= htonl(out_len
);
1292 if (fwrite(&tw
, sizeof(tw
), 1, outfile
) != 1)
1293 Error("Can't write."); /* file size of text */
1296 if (fwrite(out
, out_len
, 1, outfile
) != 1) {
1297 Error("Write error\n");
1300 tw
= htonl(0); /* EOF marker */
1301 if (fwrite(&tw
, sizeof(tw
), 1, outfile
) != 1)
1302 Error("Can't write.");
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
));
1311 Fprintf((stdout
, "input/output = %ld/%ld = %.3f\n", in_len
, out_len
,
1312 (double)in_len
/ out_len
));
1321 #define GETBIT_8(bb, src, ilen) \
1322 (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1)
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))
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))
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))
1335 #if ENDIAN == 0 && BITSIZE == 8
1336 #define GETBIT(bb, src, ilen) GETBIT_8(bb, src, ilen)
1338 #if ENDIAN == 0 && BITSIZE == 16
1339 #define GETBIT(bb, src, ilen) GETBIT_LE16(bb, src, ilen)
1341 #if ENDIAN == 0 && BITSIZE == 32
1342 #define GETBIT(bb, src, ilen) GETBIT_LE32(bb, src, ilen)
1344 #if ENDIAN == 0 && BITSIZE == 64
1345 #define GETBIT(bb, src, ilen) GETBIT_LE64(bb, src, ilen)
1348 #error "Bad Combination of ENDIAN and BITSIZE values specified"
1354 #define FAIL(x,r) if (x) { Error(r); }
1359 void Decode(void) /* recover */
1363 unsigned long max_src_len
, src_len
, dst_len
;
1364 unsigned long ilen
= 0, olen
= 0, last_m_off
= 1;
1372 if (fseek(infile
, sizeof(magic
) + sizeof(tw
) + 1 + 1 + sizeof(tw
),
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
);
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;
1390 dst
= malloc(dst_len
);
1392 Error("Can't malloc");
1393 src
= malloc(max_src_len
);
1395 Error("Can't malloc");
1396 src_len
= fread(src
, 1, max_src_len
, infile
);
1398 Error("Can't read");
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
++];
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
));
1419 FAIL(ilen
>= src_len
, "input overrun");
1420 m_off
= (m_off
- 3)*256 + src
[ilen
++];
1421 if (m_off
== 0xffffffffU
)
1423 last_m_off
= ++m_off
;
1425 m_len
= GETBIT(bb
, src
, ilen
);
1426 m_len
= m_len
*2 + GETBIT(bb
, src
, ilen
);
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
));
1437 m_len
+= (m_off
> 0xd00);
1438 FAIL(olen
+ m_len
> dst_len
, "output overrun");
1439 FAIL(m_off
> olen
, "lookbeind overrun");
1441 const uint8_t *m_pos
;
1442 m_pos
= dst
+ olen
- m_off
;
1443 dst
[olen
++] = *m_pos
++;
1445 dst
[olen
++] = *m_pos
++;
1446 } while(--m_len
> 0);
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");
1456 if (fwrite(dst
, olen
, 1, outfile
) != 1)
1457 Error("Write error\n");
1464 int main(int argc
, char *argv
[])
1472 if ((f
= tmpfile()) == NULL
) {
1474 return EXIT_FAILURE
;
1476 while ((c
= getchar()) != EOF
)
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
;
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
;
1493 if (toupper(*argv
[1]) == 'E')
1499 return EXIT_SUCCESS
;