mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-09-22 23:05:03 +00:00
Split last MSB/LSB
This commit is contained in:
@@ -61,7 +61,6 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
#endregion
|
||||
|
||||
// TODO: These should be in a separate file
|
||||
#region ReadBits Methods
|
||||
|
||||
/* This header defines macros that read data streams by
|
||||
@@ -369,182 +368,10 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
#endregion
|
||||
|
||||
// TODO: These should be in a separate file
|
||||
#region ReadHuff Methods
|
||||
|
||||
#region Common
|
||||
|
||||
/// <summary>
|
||||
/// This function was originally coded by David Tritscher.
|
||||
///
|
||||
/// It builds a fast huffman decoding table from
|
||||
/// a canonical huffman code lengths table.
|
||||
/// </summary>
|
||||
/// <param name="nsyms">total number of symbols in this huffman tree.</param>
|
||||
/// <param name="nbits">any symbols with a code length of nbits or less can be decoded in one lookup of the table.</param>
|
||||
/// <param name="length">A table to get code lengths from [0 to nsyms-1]</param>
|
||||
/// <param name="table">
|
||||
/// The table to fill up with decoded symbols and pointers.
|
||||
/// Should be ((1<<nbits) + (nsyms*2)) in length.
|
||||
/// </param>
|
||||
/// <returns>true for OK or false for error</returns>
|
||||
/// <remarks>TODO: Split into MSB and LSB variants</remarks>
|
||||
public static bool MakeDecodeTable(int nsyms, int nbits, byte[] length, ushort[] table, bool msb)
|
||||
{
|
||||
ushort sym, next_symbol;
|
||||
uint leaf, fill;
|
||||
uint reverse; // Only used when !msb
|
||||
byte bit_num;
|
||||
uint pos = 0; // The current position in the decode table
|
||||
uint table_mask = (uint)1 << nbits;
|
||||
uint bit_mask = table_mask >> 1; // Don't do 0 length codes
|
||||
|
||||
// Fill entries for codes short enough for a direct mapping
|
||||
for (bit_num = 1; bit_num <= nbits; bit_num++)
|
||||
{
|
||||
for (sym = 0; sym < nsyms; sym++)
|
||||
{
|
||||
if (length[sym] != bit_num)
|
||||
continue;
|
||||
|
||||
if (msb)
|
||||
{
|
||||
leaf = pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reverse the significant bits
|
||||
fill = length[sym];
|
||||
reverse = pos >> (nbits - (byte)fill);
|
||||
leaf = 0;
|
||||
|
||||
do
|
||||
{
|
||||
leaf <<= 1;
|
||||
leaf |= reverse & 1;
|
||||
reverse >>= 1;
|
||||
} while (--fill != 0);
|
||||
}
|
||||
|
||||
if ((pos += bit_mask) > table_mask)
|
||||
return false; // Table overrun
|
||||
|
||||
// Fill all possible lookups of this symbol with the symbol itself
|
||||
if (msb)
|
||||
{
|
||||
for (fill = bit_mask; fill-- > 0;)
|
||||
{
|
||||
table[leaf++] = sym;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fill = bit_mask;
|
||||
next_symbol = (ushort)(1 << bit_num);
|
||||
|
||||
do
|
||||
{
|
||||
table[leaf] = sym;
|
||||
leaf += next_symbol;
|
||||
} while (--fill != 0);
|
||||
}
|
||||
}
|
||||
|
||||
bit_mask >>= 1;
|
||||
}
|
||||
|
||||
// Exit with success if table is now complete
|
||||
if (pos == table_mask)
|
||||
return true;
|
||||
|
||||
// Mark all remaining table entries as unused
|
||||
for (sym = (ushort)pos; sym < table_mask; sym++)
|
||||
{
|
||||
if (msb)
|
||||
{
|
||||
table[sym] = 0xFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
reverse = sym;
|
||||
leaf = 0;
|
||||
fill = (uint)nbits;
|
||||
|
||||
do
|
||||
{
|
||||
leaf <<= 1;
|
||||
leaf |= reverse & 1;
|
||||
reverse >>= 1;
|
||||
} while (--fill != 0);
|
||||
|
||||
table[leaf] = 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
// next_symbol = base of allocation for long codes
|
||||
next_symbol = ((table_mask >> 1) < nsyms) ? (ushort)nsyms : (ushort)(table_mask >> 1);
|
||||
|
||||
// Give ourselves room for codes to grow by up to 16 more bits.
|
||||
// codes now start at bit nbits+16 and end at (nbits+16-codelength)
|
||||
pos <<= 16;
|
||||
table_mask <<= 16;
|
||||
bit_mask = 1 << 15;
|
||||
|
||||
for (bit_num = (byte)(nbits + 1); bit_num <= HUFF_MAXBITS; bit_num++)
|
||||
{
|
||||
for (sym = 0; sym < nsyms; sym++)
|
||||
{
|
||||
if (length[sym] != bit_num)
|
||||
continue;
|
||||
if (pos >= table_mask)
|
||||
return false; // Table overflow
|
||||
|
||||
if (msb)
|
||||
{
|
||||
leaf = pos >> 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
// leaf = the first nbits of the code, reversed
|
||||
reverse = pos >> 16;
|
||||
leaf = 0;
|
||||
fill = (uint)nbits;
|
||||
|
||||
do
|
||||
{
|
||||
leaf <<= 1;
|
||||
leaf |= reverse & 1;
|
||||
reverse >>= 1;
|
||||
} while (--fill != 0);
|
||||
}
|
||||
|
||||
for (fill = 0; fill < (bit_num - nbits); fill++)
|
||||
{
|
||||
// If this path hasn't been taken yet, 'allocate' two entries
|
||||
if (table[leaf] == 0xFFFF)
|
||||
{
|
||||
table[(next_symbol << 1)] = 0xFFFF;
|
||||
table[(next_symbol << 1) + 1] = 0xFFFF;
|
||||
table[leaf] = (ushort)next_symbol++;
|
||||
}
|
||||
|
||||
// Follow the path and select either left or right for next bit
|
||||
leaf = (uint)(table[leaf] << 1);
|
||||
if (((pos >> (15 - (int)fill)) & 1) != 0)
|
||||
leaf++;
|
||||
}
|
||||
|
||||
table[leaf] = sym;
|
||||
pos += bit_mask;
|
||||
}
|
||||
|
||||
bit_mask >>= 1;
|
||||
}
|
||||
|
||||
// Full table?
|
||||
return pos == table_mask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Per compression error code for decoding failure
|
||||
/// </summary>
|
||||
@@ -587,6 +414,107 @@ namespace LibMSPackSharp.Compression
|
||||
} while (sym >= maxsymbols);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function was originally coded by David Tritscher.
|
||||
///
|
||||
/// It builds a fast huffman decoding table from
|
||||
/// a canonical huffman code lengths table.
|
||||
/// </summary>
|
||||
/// <param name="nsyms">total number of symbols in this huffman tree.</param>
|
||||
/// <param name="nbits">any symbols with a code length of nbits or less can be decoded in one lookup of the table.</param>
|
||||
/// <param name="length">A table to get code lengths from [0 to nsyms-1]</param>
|
||||
/// <param name="table">
|
||||
/// The table to fill up with decoded symbols and pointers.
|
||||
/// Should be ((1<<nbits) + (nsyms*2)) in length.
|
||||
/// </param>
|
||||
/// <returns>True for OK or false for error</returns>
|
||||
public static bool MakeDecodeTableMSB(int nsyms, int nbits, byte[] length, ushort[] table)
|
||||
{
|
||||
ushort sym, next_symbol;
|
||||
uint leaf, fill;
|
||||
byte bit_num;
|
||||
uint pos = 0; // The current position in the decode table
|
||||
uint table_mask = (uint)1 << nbits;
|
||||
uint bit_mask = table_mask >> 1; // Don't do 0 length codes
|
||||
|
||||
// Fill entries for codes short enough for a direct mapping
|
||||
for (bit_num = 1; bit_num <= nbits; bit_num++)
|
||||
{
|
||||
for (sym = 0; sym < nsyms; sym++)
|
||||
{
|
||||
if (length[sym] != bit_num)
|
||||
continue;
|
||||
|
||||
leaf = pos;
|
||||
if ((pos += bit_mask) > table_mask)
|
||||
return false; // Table overrun
|
||||
|
||||
// Fill all possible lookups of this symbol with the symbol itself
|
||||
for (fill = bit_mask; fill-- > 0;)
|
||||
{
|
||||
table[leaf++] = sym;
|
||||
}
|
||||
}
|
||||
|
||||
bit_mask >>= 1;
|
||||
}
|
||||
|
||||
// Exit with success if table is now complete
|
||||
if (pos == table_mask)
|
||||
return true;
|
||||
|
||||
// Mark all remaining table entries as unused
|
||||
for (sym = (ushort)pos; sym < table_mask; sym++)
|
||||
{
|
||||
table[sym] = 0xFFFF;
|
||||
}
|
||||
|
||||
// next_symbol = base of allocation for long codes
|
||||
next_symbol = ((table_mask >> 1) < nsyms) ? (ushort)nsyms : (ushort)(table_mask >> 1);
|
||||
|
||||
// Give ourselves room for codes to grow by up to 16 more bits.
|
||||
// codes now start at bit nbits+16 and end at (nbits+16-codelength)
|
||||
pos <<= 16;
|
||||
table_mask <<= 16;
|
||||
bit_mask = 1 << 15;
|
||||
|
||||
for (bit_num = (byte)(nbits + 1); bit_num <= HUFF_MAXBITS; bit_num++)
|
||||
{
|
||||
for (sym = 0; sym < nsyms; sym++)
|
||||
{
|
||||
if (length[sym] != bit_num)
|
||||
continue;
|
||||
if (pos >= table_mask)
|
||||
return false; // Table overflow
|
||||
|
||||
leaf = pos >> 16;
|
||||
for (fill = 0; fill < (bit_num - nbits); fill++)
|
||||
{
|
||||
// If this path hasn't been taken yet, 'allocate' two entries
|
||||
if (table[leaf] == 0xFFFF)
|
||||
{
|
||||
table[(next_symbol << 1)] = 0xFFFF;
|
||||
table[(next_symbol << 1) + 1] = 0xFFFF;
|
||||
table[leaf] = next_symbol++;
|
||||
}
|
||||
|
||||
// Follow the path and select either left or right for next bit
|
||||
leaf = (uint)(table[leaf] << 1);
|
||||
if (((pos >> (15 - (int)fill)) & 1) != 0)
|
||||
leaf++;
|
||||
}
|
||||
|
||||
table[leaf] = sym;
|
||||
pos += bit_mask;
|
||||
}
|
||||
|
||||
bit_mask >>= 1;
|
||||
}
|
||||
|
||||
// Full table?
|
||||
return pos == table_mask;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region LSB
|
||||
@@ -624,6 +552,145 @@ namespace LibMSPackSharp.Compression
|
||||
} while (sym >= maxsymbols);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function was originally coded by David Tritscher.
|
||||
///
|
||||
/// It builds a fast huffman decoding table from
|
||||
/// a canonical huffman code lengths table.
|
||||
/// </summary>
|
||||
/// <param name="nsyms">total number of symbols in this huffman tree.</param>
|
||||
/// <param name="nbits">any symbols with a code length of nbits or less can be decoded in one lookup of the table.</param>
|
||||
/// <param name="length">A table to get code lengths from [0 to nsyms-1]</param>
|
||||
/// <param name="table">
|
||||
/// The table to fill up with decoded symbols and pointers.
|
||||
/// Should be ((1<<nbits) + (nsyms*2)) in length.
|
||||
/// </param>
|
||||
/// <returns>True for OK or false for error</returns>
|
||||
public static bool MakeDecodeTableLSB(int nsyms, int nbits, byte[] length, ushort[] table)
|
||||
{
|
||||
ushort sym, next_symbol;
|
||||
uint leaf, fill;
|
||||
uint reverse;
|
||||
byte bit_num;
|
||||
uint pos = 0; // The current position in the decode table
|
||||
uint table_mask = (uint)1 << nbits;
|
||||
uint bit_mask = table_mask >> 1; // Don't do 0 length codes
|
||||
|
||||
// Fill entries for codes short enough for a direct mapping
|
||||
for (bit_num = 1; bit_num <= nbits; bit_num++)
|
||||
{
|
||||
for (sym = 0; sym < nsyms; sym++)
|
||||
{
|
||||
if (length[sym] != bit_num)
|
||||
continue;
|
||||
|
||||
// Reverse the significant bits
|
||||
fill = length[sym];
|
||||
reverse = pos >> (int)(nbits - fill);
|
||||
leaf = 0;
|
||||
|
||||
do
|
||||
{
|
||||
leaf <<= 1;
|
||||
leaf |= reverse & 1;
|
||||
reverse >>= 1;
|
||||
} while (--fill != 0);
|
||||
|
||||
if ((pos += bit_mask) > table_mask)
|
||||
return false; // Table overrun
|
||||
|
||||
// Fill all possible lookups of this symbol with the symbol itself
|
||||
fill = bit_mask;
|
||||
next_symbol = (ushort)(1 << bit_num);
|
||||
|
||||
do
|
||||
{
|
||||
table[leaf] = sym;
|
||||
leaf += next_symbol;
|
||||
} while (--fill != 0);
|
||||
}
|
||||
|
||||
bit_mask >>= 1;
|
||||
}
|
||||
|
||||
// Exit with success if table is now complete
|
||||
if (pos == table_mask)
|
||||
return true;
|
||||
|
||||
// Mark all remaining table entries as unused
|
||||
for (sym = (ushort)pos; sym < table_mask; sym++)
|
||||
{
|
||||
reverse = sym;
|
||||
leaf = 0;
|
||||
fill = (uint)nbits;
|
||||
|
||||
do
|
||||
{
|
||||
leaf <<= 1;
|
||||
leaf |= reverse & 1;
|
||||
reverse >>= 1;
|
||||
} while (--fill != 0);
|
||||
|
||||
table[leaf] = 0xFFFF;
|
||||
}
|
||||
|
||||
// next_symbol = base of allocation for long codes
|
||||
next_symbol = ((table_mask >> 1) < nsyms) ? (ushort)nsyms : (ushort)(table_mask >> 1);
|
||||
|
||||
// Give ourselves room for codes to grow by up to 16 more bits.
|
||||
// codes now start at bit nbits+16 and end at (nbits+16-codelength)
|
||||
pos <<= 16;
|
||||
table_mask <<= 16;
|
||||
bit_mask = 1 << 15;
|
||||
|
||||
for (bit_num = (byte)(nbits + 1); bit_num <= HUFF_MAXBITS; bit_num++)
|
||||
{
|
||||
for (sym = 0; sym < nsyms; sym++)
|
||||
{
|
||||
if (length[sym] != bit_num)
|
||||
continue;
|
||||
if (pos >= table_mask)
|
||||
return false; // Table overflow
|
||||
|
||||
// leaf = the first nbits of the code, reversed
|
||||
reverse = pos >> 16;
|
||||
leaf = 0;
|
||||
fill = (uint)nbits;
|
||||
|
||||
do
|
||||
{
|
||||
leaf <<= 1;
|
||||
leaf |= reverse & 1;
|
||||
reverse >>= 1;
|
||||
} while (--fill != 0);
|
||||
|
||||
for (fill = 0; fill < (bit_num - nbits); fill++)
|
||||
{
|
||||
// If this path hasn't been taken yet, 'allocate' two entries
|
||||
if (table[leaf] == 0xFFFF)
|
||||
{
|
||||
table[(next_symbol << 1)] = 0xFFFF;
|
||||
table[(next_symbol << 1) + 1] = 0xFFFF;
|
||||
table[leaf] = (ushort)next_symbol++;
|
||||
}
|
||||
|
||||
// Follow the path and select either left or right for next bit
|
||||
leaf = (uint)(table[leaf] << 1);
|
||||
if (((pos >> (15 - (int)fill)) & 1) != 0)
|
||||
leaf++;
|
||||
}
|
||||
|
||||
table[leaf] = sym;
|
||||
pos += bit_mask;
|
||||
}
|
||||
|
||||
bit_mask >>= 1;
|
||||
}
|
||||
|
||||
// Full table?
|
||||
return pos == table_mask;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -152,7 +152,7 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
lzh.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
|
||||
|
||||
if (!CompressionStream.MakeDecodeTable(maxsymbols, tablebits, lengths, table, msb: true))
|
||||
if (!CompressionStream.MakeDecodeTableMSB(maxsymbols, tablebits, lengths, table))
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
@@ -1039,7 +1039,7 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
private static Error BUILD_TABLE(LZXDStream lzx, ushort[] table, byte[] lengths, int tablebits, int maxsymbols)
|
||||
{
|
||||
if (!CompressionStream.MakeDecodeTable(maxsymbols, tablebits, lengths, table, msb: true))
|
||||
if (!CompressionStream.MakeDecodeTableMSB(maxsymbols, tablebits, lengths, table))
|
||||
{
|
||||
Console.WriteLine($"Failed to build table");
|
||||
return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
@@ -1051,7 +1051,7 @@ namespace LibMSPackSharp.Compression
|
||||
private static Error BUILD_TABLE_MAYBE_EMPTY(LZXDStream lzx)
|
||||
{
|
||||
lzx.LENGTH_empty = 0;
|
||||
if (!CompressionStream.MakeDecodeTable(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, lzx.LENGTH_len, lzx.LENGTH_table, msb: true))
|
||||
if (!CompressionStream.MakeDecodeTableMSB(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, lzx.LENGTH_len, lzx.LENGTH_table))
|
||||
{
|
||||
for (int i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
|
||||
{
|
||||
|
||||
@@ -360,7 +360,7 @@ namespace LibMSPackSharp.Compression
|
||||
}
|
||||
|
||||
// Create decoding table with an immediate lookup
|
||||
if (!CompressionStream.MakeDecodeTable(19, 7, bl_len, bl_table, msb: false))
|
||||
if (!CompressionStream.MakeDecodeTableLSB(19, 7, bl_len, bl_table))
|
||||
return Error.INF_ERR_BITLENTBL;
|
||||
|
||||
// Read literal / distance code lengths
|
||||
@@ -565,10 +565,10 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
// Now huffman lengths are read for either kind of block,
|
||||
// create huffman decoding tables
|
||||
if (!CompressionStream.MakeDecodeTable(MSZIP_LITERAL_MAXSYMBOLS, MSZIP_LITERAL_TABLEBITS, zip.LITERAL_len, zip.LITERAL_table, msb: false))
|
||||
if (!CompressionStream.MakeDecodeTableLSB(MSZIP_LITERAL_MAXSYMBOLS, MSZIP_LITERAL_TABLEBITS, zip.LITERAL_len, zip.LITERAL_table))
|
||||
return Error.INF_ERR_LITERALTBL;
|
||||
|
||||
if (!CompressionStream.MakeDecodeTable(MSZIP_DISTANCE_MAXSYMBOLS, MSZIP_DISTANCE_TABLEBITS, zip.DISTANCE_len, zip.DISTANCE_table, msb: false))
|
||||
if (!CompressionStream.MakeDecodeTableLSB(MSZIP_DISTANCE_MAXSYMBOLS, MSZIP_DISTANCE_TABLEBITS, zip.DISTANCE_len, zip.DISTANCE_table))
|
||||
return Error.INF_ERR_DISTANCETBL;
|
||||
|
||||
// Decode forever until end of block code
|
||||
|
||||
Reference in New Issue
Block a user