putbits(wp, c - 1, p & (0xFFFFU >> (17 - c)));
}
+/*
+ output format for a block.
+
+ +-----------+
+ | blocksize |
+ +-----------+
+ 16bit
+
+ +-----+--------------------+
+ | len | pt_len | Huffman tree for c_len[]
+ +-----+--------------------+
+ 5bit ?? bit
+ TBIT
+
+ +-------+------------------+
+ | len | c_len | Huffman tree for characters and length
+ +-------+------------------+
+ 9bit ?? bit
+ CBIT
+
+ +---------+--------------------+
+ | len | pt_len | Huffman tree for offset
+ +---------+--------------------+
+ pbit ?? bit
+ (pbit=4bit(lh4,5) or 5bit(lh6,7))
+
+ +---------------------+
+ | encoding text |
+ +---------------------+
+
+
+ In special case, only one kind characters in a block.
+
+ TBIT: 5 bits
+ CBIT: 9 bits
+
+ +-----------+
+ | blocksize |
+ +-----------+
+ 16bit
+
+ +-----+-----+
+ | 0 | 0 | Huffman tree for c_len[]
+ +-----+-----+
+ TBIT TBIT
+
+ +-------+-------+
+ | 0 | 0 | Huffman tree for characters and length
+ +-------+-------+
+ CBIT CBIT
+
+ +---------+--------------+
+ | 0 | offset value | Huffman tree for offset
+ +---------+--------------+
+ pbit pbit
+ (pbit=4bit(lh4,5) or 5bit(lh6,7))
+
+ +---------------------+
+ | encoding text |
+ +---------------------+
+ */
static void
send_block(struct lzh_ostream *wp)
{
uint i, k, flags, root, pos, size;
+ /* make Huffman tree for characters and length */
root = make_tree(NC, c_freq, c_len, c_code);
size = c_freq[root];
putbits(wp, 16, size);
if (root >= NC) {
+ /* make Huffman tree for c_len */
count_t_freq();
root = make_tree(NT, t_freq, pt_len, pt_code);
if (root >= NT) {
write_pt_len(wp, NT, TBIT, 3);
}
else {
+ /* only one kind */
putbits(wp, TBIT, 0);
putbits(wp, TBIT, root);
}
write_c_len(wp);
}
else {
+ /* only one kind */
putbits(wp, TBIT, 0);
putbits(wp, TBIT, 0);
putbits(wp, CBIT, 0);
putbits(wp, CBIT, root);
}
+
+ /* make Huffman tree for offset */
root = make_tree(np, p_freq, pt_len, pt_code);
if (root >= np) {
write_pt_len(wp, np, pbit, -1);
putbits(wp, pbit, 0);
putbits(wp, pbit, root);
}
+
+ /* write Huffman encoding */
pos = 0;
for (i = 0; i < size; i++) {
if (i % CHAR_BIT == 0)
else
flags <<= 1;
if (flags & (1U << (CHAR_BIT - 1))) {
+ /* write length */
encode_c(wp, wp->buf[pos++] + (1U << CHAR_BIT));
+ /* write offset */
k = wp->buf[pos++] << CHAR_BIT;
k += wp->buf[pos++];
encode_p(wp, k);
}
- else
+ else {
+ /* write character */
encode_c(wp, wp->buf[pos++]);
+ }
if (wp->unpackable)
return;
}
+
+ /* clear frequency table */
for (i = 0; i < NC; i++)
c_freq[i] = 0;
for (i = 0; i < np; i++)
cpos /
/
output_pos
-
+c_freq[] has frequency of cN and len.
+p_freq[] has frequency of length of off bits.
*/
void
output(struct lzh_ostream *wp, uint c, uint p)