]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/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
31 * Transcribe binary value (for debugging)
34 * @v bits Length of value (in bits)
35 * @ret string Transcribed value
37 const char * huffman_bin ( unsigned long value
, unsigned int bits
) {
38 static char buf
[ ( 8 * sizeof ( value
) ) + 1 /* NUL */ ];
42 assert ( bits
< sizeof ( buf
) );
44 /* Transcribe value */
46 *(out
++) = ( ( value
& ( 1 << bits
) ) ? '1' : '0' );
53 * Dump Huffman alphabet (for debugging)
55 * @v alphabet Huffman alphabet
57 static void __attribute__ (( unused
))
58 huffman_dump_alphabet ( struct huffman_alphabet
*alphabet
) {
59 struct huffman_symbols
*sym
;
66 /* Dump symbol table for each utilised length */
67 for ( bits
= 1 ; bits
<= ( sizeof ( alphabet
->huf
) /
68 sizeof ( alphabet
->huf
[0] ) ) ; bits
++ ) {
69 sym
= &alphabet
->huf
[ bits
- 1 ];
72 huf
= ( sym
->start
>> sym
->shift
);
73 DBG ( "Huffman length %d start \"%s\" freq %d:", bits
,
74 huffman_bin ( huf
, sym
->bits
), sym
->freq
);
75 for ( i
= 0 ; i
< sym
->freq
; i
++ ) {
76 DBG ( " %03x", sym
->raw
[ huf
+ i
] );
81 /* Dump quick lookup table */
82 DBG ( "Huffman quick lookup:" );
83 for ( i
= 0 ; i
< ( sizeof ( alphabet
->lookup
) /
84 sizeof ( alphabet
->lookup
[0] ) ) ; i
++ ) {
85 DBG ( " %d", ( alphabet
->lookup
[i
] + 1 ) );
91 * Construct Huffman alphabet
93 * @v alphabet Huffman alphabet
94 * @v lengths Symbol length table
95 * @v count Number of symbols
96 * @ret rc Return status code
98 int huffman_alphabet ( struct huffman_alphabet
*alphabet
,
99 uint8_t *lengths
, unsigned int count
) {
100 struct huffman_symbols
*sym
;
102 unsigned int cum_freq
;
105 unsigned int adjustment
;
110 /* Clear symbol table */
111 memset ( alphabet
->huf
, 0, sizeof ( alphabet
->huf
) );
113 /* Count number of symbols with each Huffman-coded length */
115 for ( raw
= 0 ; raw
< count
; raw
++ ) {
118 alphabet
->huf
[ bits
- 1 ].freq
++;
123 /* In the degenerate case of having no symbols (i.e. an unused
124 * alphabet), generate a trivial alphabet with exactly two
125 * single-bit codes. This allows callers to avoid having to
126 * check for this special case.
129 alphabet
->huf
[0].freq
= 2;
131 /* Populate Huffman-coded symbol table */
134 for ( bits
= 1 ; bits
<= ( sizeof ( alphabet
->huf
) /
135 sizeof ( alphabet
->huf
[0] ) ) ; bits
++ ) {
136 sym
= &alphabet
->huf
[ bits
- 1 ];
138 sym
->shift
= ( HUFFMAN_BITS
- bits
);
139 sym
->start
= ( huf
<< sym
->shift
);
140 sym
->raw
= &alphabet
->raw
[cum_freq
];
142 if ( huf
> ( 1U << bits
) ) {
143 DBG ( "Huffman alphabet has too many symbols with "
144 "lengths <=%d\n", bits
);
148 cum_freq
+= sym
->freq
;
150 complete
= ( huf
== ( 1U << bits
) );
152 /* Populate raw symbol table */
153 for ( raw
= 0 ; raw
< count
; raw
++ ) {
156 sym
= &alphabet
->huf
[ bits
- 1 ];
161 /* Adjust Huffman-coded symbol table raw pointers and populate
162 * quick lookup table.
164 for ( bits
= 1 ; bits
<= ( sizeof ( alphabet
->huf
) /
165 sizeof ( alphabet
->huf
[0] ) ) ; bits
++ ) {
166 sym
= &alphabet
->huf
[ bits
- 1 ];
168 /* Adjust raw pointer */
169 sym
->raw
-= sym
->freq
; /* Reset to first symbol */
170 adjustment
= ( sym
->start
>> sym
->shift
);
171 sym
->raw
-= adjustment
; /* Adjust for quick indexing */
173 /* Populate quick lookup table */
174 for ( prefix
= ( sym
->start
>> HUFFMAN_QL_SHIFT
) ;
175 prefix
< ( 1 << HUFFMAN_QL_BITS
) ; prefix
++ ) {
176 alphabet
->lookup
[prefix
] = ( bits
- 1 );
180 /* Check that there are no invalid codes */
182 DBG ( "Huffman alphabet is incomplete\n" );
190 * Get Huffman symbol set
192 * @v alphabet Huffman alphabet
193 * @v huf Raw input value (normalised to HUFFMAN_BITS bits)
194 * @ret sym Huffman symbol set
196 struct huffman_symbols
* huffman_sym ( struct huffman_alphabet
*alphabet
,
198 struct huffman_symbols
*sym
;
199 unsigned int lookup_index
;
201 /* Find symbol set for this length */
202 lookup_index
= ( huf
>> HUFFMAN_QL_SHIFT
);
203 sym
= &alphabet
->huf
[ alphabet
->lookup
[ lookup_index
] ];
204 while ( huf
< sym
->start
)