]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - wimboot/wimboot-2.7.3/src/huffman.c
2 * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
35 * Transcribe binary value (for debugging)
38 * @v bits Length of value (in bits)
39 * @ret string Transcribed value
41 static const char * huffman_bin ( unsigned long value
, unsigned int bits
) {
42 static char buf
[ ( 8 * sizeof ( value
) ) + 1 /* NUL */ ];
46 assert ( bits
< sizeof ( buf
) );
48 /* Transcribe value */
50 *(out
++) = ( ( value
& ( 1 << bits
) ) ? '1' : '0' );
57 * Dump Huffman alphabet (for debugging)
59 * @v alphabet Huffman alphabet
61 static void __attribute__ (( unused
))
62 huffman_dump_alphabet ( struct huffman_alphabet
*alphabet
) {
63 struct huffman_symbols
*sym
;
68 /* Dump symbol table for each utilised length */
69 for ( bits
= 1 ; bits
<= ( sizeof ( alphabet
->huf
) /
70 sizeof ( alphabet
->huf
[0] ) ) ; bits
++ ) {
71 sym
= &alphabet
->huf
[ bits
- 1 ];
74 huf
= ( sym
->start
>> sym
->shift
);
75 DBG ( "Huffman length %d start \"%s\" freq %d:", bits
,
76 huffman_bin ( huf
, sym
->bits
), sym
->freq
);
77 for ( i
= 0 ; i
< sym
->freq
; i
++ ) {
78 DBG ( " %03x", sym
->raw
[ huf
+ i
] );
83 /* Dump quick lookup table */
84 DBG ( "Huffman quick lookup:" );
85 for ( i
= 0 ; i
< ( sizeof ( alphabet
->lookup
) /
86 sizeof ( alphabet
->lookup
[0] ) ) ; i
++ ) {
87 DBG ( " %d", ( alphabet
->lookup
[i
] + 1 ) );
93 * Construct Huffman alphabet
95 * @v alphabet Huffman alphabet
96 * @v lengths Symbol length table
97 * @v count Number of symbols
98 * @ret rc Return status code
100 int huffman_alphabet ( struct huffman_alphabet
*alphabet
,
101 uint8_t *lengths
, unsigned int count
) {
102 struct huffman_symbols
*sym
;
104 unsigned int cum_freq
;
107 unsigned int adjustment
;
112 /* Clear symbol table */
113 memset ( alphabet
->huf
, 0, sizeof ( alphabet
->huf
) );
115 /* Count number of symbols with each Huffman-coded length */
117 for ( raw
= 0 ; raw
< count
; raw
++ ) {
120 alphabet
->huf
[ bits
- 1 ].freq
++;
125 /* In the degenerate case of having no symbols (i.e. an unused
126 * alphabet), generate a trivial alphabet with exactly two
127 * single-bit codes. This allows callers to avoid having to
128 * check for this special case.
131 alphabet
->huf
[0].freq
= 2;
133 /* Populate Huffman-coded symbol table */
136 for ( bits
= 1 ; bits
<= ( sizeof ( alphabet
->huf
) /
137 sizeof ( alphabet
->huf
[0] ) ) ; bits
++ ) {
138 sym
= &alphabet
->huf
[ bits
- 1 ];
140 sym
->shift
= ( HUFFMAN_BITS
- bits
);
141 sym
->start
= ( huf
<< sym
->shift
);
142 sym
->raw
= &alphabet
->raw
[cum_freq
];
144 if ( huf
> ( 1U << bits
) ) {
145 DBG ( "Huffman alphabet has too many symbols with "
146 "lengths <=%d\n", bits
);
150 cum_freq
+= sym
->freq
;
152 complete
= ( huf
== ( 1U << bits
) );
154 /* Populate raw symbol table */
155 for ( raw
= 0 ; raw
< count
; raw
++ ) {
158 sym
= &alphabet
->huf
[ bits
- 1 ];
163 /* Adjust Huffman-coded symbol table raw pointers and populate
164 * quick lookup table.
166 for ( bits
= 1 ; bits
<= ( sizeof ( alphabet
->huf
) /
167 sizeof ( alphabet
->huf
[0] ) ) ; bits
++ ) {
168 sym
= &alphabet
->huf
[ bits
- 1 ];
170 /* Adjust raw pointer */
171 sym
->raw
-= sym
->freq
; /* Reset to first symbol */
172 adjustment
= ( sym
->start
>> sym
->shift
);
173 sym
->raw
-= adjustment
; /* Adjust for quick indexing */
175 /* Populate quick lookup table */
176 for ( prefix
= ( sym
->start
>> HUFFMAN_QL_SHIFT
) ;
177 prefix
< ( 1 << HUFFMAN_QL_BITS
) ; prefix
++ ) {
178 alphabet
->lookup
[prefix
] = ( bits
- 1 );
182 /* Check that there are no invalid codes */
184 DBG ( "Huffman alphabet is incomplete\n" );
192 * Get Huffman symbol set
194 * @v alphabet Huffman alphabet
195 * @v huf Raw input value (normalised to HUFFMAN_BITS bits)
196 * @ret sym Huffman symbol set
198 struct huffman_symbols
* huffman_sym ( struct huffman_alphabet
*alphabet
,
200 struct huffman_symbols
*sym
;
201 unsigned int lookup_index
;
203 /* Find symbol set for this length */
204 lookup_index
= ( huf
>> HUFFMAN_QL_SHIFT
);
205 sym
= &alphabet
->huf
[ alphabet
->lookup
[ lookup_index
] ];
206 while ( huf
< sym
->start
)