2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation, either version 3 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 ////////////////////////////////////////////////////////////////////////////////
24 unsigned int bitbuf
; /* holds between 16 and 32 bits */
25 int bitcount
; /* how many bits does bitbuf hold? */
30 int num
; /* number of nodes in the tree */
39 ////////////////////////////////////////////////////////////////////////////////
41 * Return the big-endian longword at p.
43 static inline unsigned int blong (const unsigned char *p
) {
55 * Return the big-endian word at p.
57 static inline unsigned int bword (const unsigned char *p
) {
67 * Return the little-endian word at p.
69 static inline unsigned int lword (const unsigned char *p
) {
79 * Mirror the bottom n bits of x.
81 static inline unsigned int mirror (unsigned int x
, int n
) {
82 unsigned int top
= 1<<(n
-1), bottom
= 1;
84 while (top
> bottom
) {
85 unsigned int mask
= top
|bottom
;
86 unsigned int masked
= x
&mask
;
88 if (masked
!= 0 && masked
!= mask
) x
^= mask
;
97 * Initialises a bit stream with the first two bytes of the packed
100 static inline void bitread_init (BitStream
*bs
, const unsigned char **p
) {
101 bs
->bitbuf
= lword(*p
);
107 * Fixes up a bit stream after literals have been read out of the
110 static inline void bitread_fix (BitStream
*bs
, const unsigned char **p
) {
112 bs
->bitbuf
&= (1<<bs
->bitcount
)-1; /* remove the top 16 bits */
113 bs
->bitbuf
|= (lword(*p
)<<bs
->bitcount
); /* replace with what's at *p */
121 static inline unsigned int bit_peek (BitStream
*bs
, unsigned int mask
) {
122 return bs
->bitbuf
&mask
;
127 * Advances the bit stream.
129 static inline void bit_advance (BitStream
*bs
, int n
, const unsigned char **p
) {
132 if (bs
->bitcount
< 16) {
134 bs
->bitbuf
|= (lword(*p
)<<bs
->bitcount
);
141 * Reads some bits in one go (ie the above two routines combined).
143 static inline unsigned int bit_read (BitStream
*bs
, unsigned int mask
, int n
, const unsigned char **p
) {
144 unsigned int result
= bit_peek(bs
, mask
);
146 bit_advance(bs
, n
, p
);
152 * Read a Huffman table out of the bit stream and data stream given.
154 static int read_huftable (HuffmanTable
*h
, BitStream
*bs
, const unsigned char **p
) {
158 unsigned int codeb
; /* big-endian form of code */
160 num
= bit_read(bs
, 0x1f, 5, p
);
163 for (int i
= 0; i
< num
; ++i
) {
164 leaflen
[i
] = bit_read(bs
, 0x0F, 4, p
);
165 if (leafmax
< leaflen
[i
]) leafmax
= leaflen
[i
];
169 for (int i
= 1; i
<= leafmax
; ++i
) {
170 for (int j
= 0; j
< num
; ++j
) {
171 if (leaflen
[j
] == i
) {
172 h
->table
[k
].code
= mirror(codeb
, i
);
173 h
->table
[k
].codelen
= i
;
174 h
->table
[k
].value
= j
;
187 * Read a value out of the bit stream using the given Huffman table.
189 static unsigned int huf_read (HuffmanTable
*h
, BitStream
*bs
, const unsigned char **p
) {
193 for (i
= 0; i
< h
->num
; i
++) {
194 unsigned int mask
= (1<<h
->table
[i
].codelen
)-1;
196 if (bit_peek(bs
, mask
) == h
->table
[i
].code
) break;
198 if (i
== h
->num
) return (unsigned int)-1;
199 bit_advance(bs
, h
->table
[i
].codelen
, p
);
200 val
= h
->table
[i
].value
;
203 val
|= bit_read(bs
, val
-1, h
->table
[i
].value
-1, p
);
209 ////////////////////////////////////////////////////////////////////////////////
211 * Decompress a packed data block. Returns the unpacked length if
212 * successful, or negative error codes if not.
214 * If COMPRESSOR is defined, it also returns the leeway number
215 * (which gets stored at offset 16 into the compressed-file header)
216 * in `*leeway', if `leeway' isn't NULL.
218 int rnc_unpack (const void *packed
, void *unpacked
, int *leeway
) {
219 const unsigned char *input
= packed
;
220 const unsigned char *inputend
;
221 unsigned char *output
= unpacked
;
222 unsigned char *outputend
;
224 HuffmanTable raw
, dist
, len
;
225 unsigned int ch_count
;
226 unsigned int ret_len
;
230 if (blong(input
) != RNC_SIGNATURE
) return RNC_FILE_IS_NOT_RNC
;
231 ret_len
= blong(input
+4);
232 outputend
= output
+ret_len
;
233 inputend
= input
+18+blong(input
+8);
234 input
+= 18; /* skip header */
235 // check the packed-data CRC. Also save the unpacked-data CRC for later
236 if (rnc_crc(input
, inputend
-input
) != bword(input
-4)) return RNC_PACKED_CRC_ERROR
;
237 out_crc
= bword(input
-6);
238 bitread_init(&bs
, &input
);
239 bit_advance(&bs
, 2, &input
); /* discard first two bits */
241 while (output
< outputend
) {
244 read_huftable(&raw
, &bs
, &input
);
245 read_huftable(&dist
, &bs
, &input
);
246 read_huftable(&len
, &bs
, &input
);
247 ch_count
= bit_read(&bs
, 0xffff, 16, &input
);
252 length
= huf_read(&raw
, &bs
, &input
);
253 if (length
== -1) return RNC_HUF_DECODE_ERROR
;
255 while (length
--) *output
++ = *input
++;
256 bitread_fix(&bs
, &input
);
258 if (--ch_count
<= 0) break;
259 posn
= huf_read(&dist
, &bs
, &input
);
260 if (posn
== -1) return RNC_HUF_DECODE_ERROR
;
261 length
= huf_read(&len
, &bs
, &input
);
262 if (length
== -1) return RNC_HUF_DECODE_ERROR
;
266 *output
= output
[-posn
];
269 this_lee
= (inputend
-input
)-(outputend
-output
);
270 if (lee
< this_lee
) lee
= this_lee
;
274 if (outputend
!= output
) return RNC_FILE_SIZE_MISMATCH
;
275 if (leeway
) *leeway
= lee
;
276 // check the unpacked-data CRC
277 if (rnc_crc(outputend
-ret_len
, ret_len
) != out_crc
) return RNC_UNPACKED_CRC_ERROR
;
282 ////////////////////////////////////////////////////////////////////////////////
284 * Return the uncompressed length of a packed data block, or a
285 * negative error code.
287 int rnc_ulen (const void *packed
) {
288 const unsigned char *p
= packed
;
290 if (blong(p
) != RNC_SIGNATURE
) return RNC_FILE_IS_NOT_RNC
;
295 ////////////////////////////////////////////////////////////////////////////////
297 * Calculate a CRC, the RNC way.
299 int rnc_crc (const void *data
, int len
) {
300 static int initialized
= 0;
301 static unsigned short crctab
[256];
303 const unsigned char *p
= data
;
306 for (int i
= 0; i
< 256; ++i
) {
308 for (int j
= 0; j
< 8; ++j
) if (val
&1) val
= (val
>>1)^0xA001; else val
= (val
>>1);
316 val
= (val
>>8)^crctab
[val
&0xFF];
323 ////////////////////////////////////////////////////////////////////////////////
325 * Return an error string corresponding to an error return code.
327 const char *rnc_error (int errcode
) {
328 static const char *const errors
[] = {
330 "File is not RNC-1 format",
331 "Huffman decode error",
332 "File size mismatch",
333 "CRC error in packed data",
334 "CRC error in unpacked data",
339 if (errcode
< 0) errcode
= 0;
340 if (errcode
> sizeof(errors
)/sizeof(*errors
)-1) errcode
= sizeof(errors
)/sizeof(*errors
)-1;
341 return errors
[errcode
];
345 ////////////////////////////////////////////////////////////////////////////////
348 #define BLOCKMAX (8192)
349 #define WINMAX (32767)
350 #define MAXTUPLES (4096)
352 #define HASHMAX (509)
353 #define PACKED_DELTA (65536)
361 } PackerHuffmanTable
;
371 static unsigned char blk
[WINMAX
];
372 static int linkp
[WINMAX
];
373 static int hashp
[HASHMAX
];
374 static int blkstart
, bpos
;
377 static Tuple tuples
[MAXTUPLES
];
380 static unsigned char *packed
;
381 static int packedlen
;
382 static int packedpos
, bitpos
, bitcount
, bitbuf
;
385 static inline int hash (const unsigned char *a
) {
386 return ((a
[0]*7+a
[1])*7+a
[2])%HASHMAX
;
390 static inline int pklength (unsigned value
) {
393 while (value
!= 0) { value
>>= 1; ++ret
; }
399 * Write big-endian int.
401 static inline void bwrite (unsigned char *p
, unsigned int val
) {
412 static inline void emit_raw (int n
) {
413 tuples
[ntuple
].rawlen
+= n
;
418 static inline void emit_pair (int pos
, int len
) {
419 tuples
[ntuple
].pos
= bpos
-pos
;
420 tuples
[ntuple
].len
= len
;
421 tuples
[++ntuple
].rawlen
= 0;
426 static inline void check_size (void) {
427 if (packedpos
> packedlen
-16) {
428 packedlen
+= PACKED_DELTA
;
429 packed
= realloc(packed
, packedlen
);
430 if (packed
== NULL
) {
438 static inline void write_literal (unsigned value
) {
439 packed
[packedpos
++] = value
;
444 static inline void write_bits (unsigned value
, int nbits
) {
445 value
&= (1 << nbits
)-1;
446 bitbuf
|= (value
<< bitcount
);
450 packed
[bitpos
] = bitbuf
;
452 packed
[bitpos
+1] = bitbuf
;
462 static void write_hval (PackerHuffmanTable
*h
, unsigned value
) {
463 int len
= pklength(value
);
465 write_bits(h
->table
[len
].code
, h
->table
[len
].codelen
);
466 if (len
>= 2) write_bits(value
, len
-1);
470 static void write_huf (PackerHuffmanTable
*h
) {
473 for (int i
= 0; i
< 32; ++i
) if (h
->table
[i
].codelen
> 0) j
= i
+1;
475 for (int i
= 0; i
< j
; ++i
) write_bits(h
->table
[i
].codelen
, 4);
479 static void build_huf (PackerHuffmanTable
*h
, int *freqs
) {
481 int freq
, parent
, lchild
, rchild
;
487 j
= 0; /* j counts nodes in the pool */
489 for (int i
= 0; i
< 32; ++i
) {
491 pool
[j
].freq
= freqs
[i
];
499 k
= j
; /* k counts _free_ nodes in the pool */
502 int nextmin
= toobig
+1;
503 int minpos
= 0, nextminpos
= 0;
505 /* loop through free nodes */
506 for (int i
= 0; i
< j
; ++i
) {
507 if (pool
[i
].parent
== -1) {
508 if (min
> pool
[i
].freq
) {
513 } else if (nextmin
> pool
[i
].freq
) {
514 nextmin
= pool
[i
].freq
;
519 pool
[j
].freq
= min
+ nextmin
;
521 pool
[j
].lchild
= minpos
;
522 pool
[j
].rchild
= nextminpos
;
523 pool
[minpos
].parent
= j
;
524 pool
[nextminpos
].parent
= j
;
529 for (int i
= 0; i
< 32; ++i
) h
->table
[i
].codelen
= 0;
532 /* loop through original nodes */
533 for (int i
= 0; i
< j
; ++i
) {
534 if (pool
[i
].lchild
== -1) {
537 while (pool
[k
].parent
!= -1) { ++m
; k
= pool
[k
].parent
; }
538 h
->table
[pool
[i
].rchild
].codelen
= m
;
539 if (maxcodelen
< m
) maxcodelen
= m
;
544 for (int i
= 1; i
<= maxcodelen
; ++i
) {
545 for (int j
= 0; j
< 32; ++j
) {
546 if (h
->table
[j
].codelen
== i
) {
547 h
->table
[j
].code
= mirror(codeb
, i
);
556 static void write_block (void) {
558 PackerHuffmanTable raw
, dist
, len
;
561 for (int i
= 0; i
< 32; ++i
) lengths
[i
] = 0;
562 for (int i
= 0; i
<= ntuple
; ++i
) ++(lengths
[pklength(tuples
[i
].rawlen
)]);
563 build_huf(&raw
, lengths
);
566 for (int i
= 0; i
< 32; ++i
) lengths
[i
] = 0;
567 for (int i
= 0; i
< ntuple
; ++i
) ++(lengths
[pklength(tuples
[i
].pos
-1)]);
568 build_huf(&dist
, lengths
);
571 for (int i
= 0; i
< 32; ++i
) lengths
[i
] = 0;
572 for (int i
= 0; i
< ntuple
; ++i
) ++(lengths
[pklength(tuples
[i
].len
-2)]);
573 build_huf(&len
, lengths
);
576 write_bits(ntuple
+1, 16);
579 for (int i
= 0; i
<=ntuple
; ++i
) {
580 write_hval (&raw
, tuples
[i
].rawlen
);
581 for (int j
= 0; j
<tuples
[i
].rawlen
; ++j
) write_literal(blk
[k
++]);
582 if (i
== ntuple
) break;
583 write_hval(&dist
, tuples
[i
].pos
-1);
584 write_hval(&len
, tuples
[i
].len
-2);
590 static void do_block (void) {
591 int lazylen
= 0, lazypos
= 0, lazyraw
= 0;
595 while (bpos
< blkstart
) {
596 hashv
= hash(blk
+bpos
);
603 if (ph
!= -1) linkp
[ph
] = bpos
; else hashp
[hashv
] = bpos
;
608 while (bpos
< blklen
&& ntuple
< MAXTUPLES
-1) {
609 if (blklen
-bpos
< 3) {
610 emit_raw(blklen
-bpos
);
612 int len
, maxlen
, maxlenpos
;
615 hashv
= hash(blk
+bpos
);
622 unsigned char *p
= blk
+bpos
;
623 unsigned char *v
= blk
+h
;
626 while (*p
== *v
&& p
< blk
+blklen
) { ++p
; ++v
; ++len
; }
635 if (ph
!= -1) linkp
[ph
] = bpos
; else hashp
[hashv
] = bpos
;
642 if (maxlen
>= lazylen
+2) {
648 emit_pair(lazypos
, lazylen
);
649 lazyraw
= lazypos
= lazylen
= 0;
651 } else if (maxlen
>= 3) {
660 while (++savebpos
< bpos
) {
661 hashv
= hash(blk
+savebpos
);
668 if (ph
!= -1) linkp
[ph
] = savebpos
; else hashp
[hashv
] = savebpos
;
669 linkp
[savebpos
] = -1;
681 void *rnc_pack (const void *original
, int datalen
, int *packlen
) {
682 const char *data
= original
;
683 int origlen
= datalen
;
685 packed
= malloc(PACKED_DELTA
);
686 if (packed
== NULL
) {
691 fprintf(stderr
, "%3d%%", (int)(((long long)100)*(origlen
-datalen
)/origlen
)); fflush(stderr
);
693 packedlen
= PACKED_DELTA
;
695 bwrite(packed
+4, datalen
);
702 while (datalen
> 0) {
703 blklen
= datalen
> BLOCKMAX
? BLOCKMAX
: datalen
;
704 blkstart
= WINMAX
-BLOCKMAX
;
705 if (blkstart
> origlen
-datalen
) blkstart
= origlen
-datalen
;
706 memcpy (blk
, data
-blkstart
, blkstart
+blklen
);
707 for (int i
= 0; i
< HASHMAX
; ++i
) hashp
[i
] = -1;
709 tuples
[ntuple
].rawlen
= 0;
712 data
+= bpos
-blkstart
;
713 datalen
-= bpos
-blkstart
;
715 fprintf(stderr
, "\x8\x8\x8\x8%3d%%", (int)(((long long)100)*(origlen
-datalen
)/origlen
)); fflush(stderr
);
719 write_bits(0, 17-bitcount
); /* force flush */
720 packedpos
-= 2; /* write_bits will have moved it on */
723 *packlen
= packedpos
;
725 bwrite(packed
, RNC_SIGNATURE
);
726 bwrite(packed
+12, rnc_crc(packed
+18, packedpos
-18));
727 bwrite(packed
+10, rnc_crc(original
, origlen
));
728 bwrite(packed
+8, packedpos
-18);
729 packed
[16] = packed
[17] = 0;
731 fprintf(stderr
, "\x8\x8\x8\x8%3d%%", (int)(((long long)100)*(origlen
-datalen
)/origlen
)); fflush(stderr
);