1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
// File: lzham_prefix_coding.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
#include "lzham_huffman_codes.h"
namespace lzham
{
namespace prefix_coding
{
const uint cMaxSupportedSyms = 1024;
// This value can be tuned for a specific CPU.
const uint cMaxTableBits = 11;
bool limit_max_code_size(uint num_syms, uint8* pCodesizes, uint max_code_size);
bool generate_codes(uint num_syms, const uint8* pCodesizes, uint16* pCodes);
class decoder_tables
{
public:
inline decoder_tables(lzham_malloc_context malloc_context) :
m_malloc_context(malloc_context),
m_table_shift(0), m_table_max_code(0), m_decode_start_code_size(0), m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL)
{
}
inline decoder_tables(const decoder_tables& other) :
m_malloc_context(other.m_malloc_context),
m_table_shift(0), m_table_max_code(0), m_decode_start_code_size(0), m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL)
{
*this = other;
}
inline decoder_tables& operator= (const decoder_tables& rhs)
{
assign(rhs);
return *this;
}
inline bool assign(const decoder_tables& rhs)
{
if (this == &rhs)
return true;
if (m_malloc_context != rhs.m_malloc_context)
{
clear();
m_malloc_context = rhs.m_malloc_context;
}
uint32* pCur_lookup = m_lookup;
uint16* pCur_sorted_symbol_order = m_sorted_symbol_order;
memcpy(this, &rhs, sizeof(*this));
if ((pCur_lookup) && (pCur_sorted_symbol_order) && (rhs.m_cur_lookup_size == m_cur_lookup_size) && (rhs.m_cur_sorted_symbol_order_size == m_cur_sorted_symbol_order_size))
{
m_lookup = pCur_lookup;
m_sorted_symbol_order = pCur_sorted_symbol_order;
memcpy(m_lookup, rhs.m_lookup, sizeof(m_lookup[0]) * m_cur_lookup_size);
memcpy(m_sorted_symbol_order, rhs.m_sorted_symbol_order, sizeof(m_sorted_symbol_order[0]) * m_cur_sorted_symbol_order_size);
}
else
{
lzham_delete_array(m_malloc_context, pCur_lookup);
m_lookup = NULL;
if (rhs.m_lookup)
{
m_lookup = lzham_new_array<uint32>(m_malloc_context, m_cur_lookup_size);
if (!m_lookup)
return false;
memcpy(m_lookup, rhs.m_lookup, sizeof(m_lookup[0]) * m_cur_lookup_size);
}
lzham_delete_array(m_malloc_context, pCur_sorted_symbol_order);
m_sorted_symbol_order = NULL;
if (rhs.m_sorted_symbol_order)
{
m_sorted_symbol_order = lzham_new_array<uint16>(m_malloc_context, m_cur_sorted_symbol_order_size);
if (!m_sorted_symbol_order)
return false;
memcpy(m_sorted_symbol_order, rhs.m_sorted_symbol_order, sizeof(m_sorted_symbol_order[0]) * m_cur_sorted_symbol_order_size);
}
}
return true;
}
inline void clear()
{
if (m_lookup)
{
lzham_delete_array(m_malloc_context, m_lookup);
m_lookup = 0;
m_cur_lookup_size = 0;
}
if (m_sorted_symbol_order)
{
lzham_delete_array(m_malloc_context, m_sorted_symbol_order);
m_sorted_symbol_order = NULL;
m_cur_sorted_symbol_order_size = 0;
}
}
inline ~decoder_tables()
{
if (m_lookup)
lzham_delete_array(m_malloc_context, m_lookup);
if (m_sorted_symbol_order)
lzham_delete_array(m_malloc_context, m_sorted_symbol_order);
}
// DO NOT use any complex classes here - it is bitwise copied.
lzham_malloc_context m_malloc_context;
uint m_num_syms;
uint m_total_used_syms;
uint m_table_bits;
uint m_table_shift;
uint m_table_max_code;
uint m_decode_start_code_size;
uint8 m_min_code_size;
uint8 m_max_code_size;
uint m_max_codes[cMaxExpectedHuffCodeSize + 1];
int m_val_ptrs[cMaxExpectedHuffCodeSize + 1];
uint m_cur_lookup_size;
uint32* m_lookup;
uint m_cur_sorted_symbol_order_size;
uint16* m_sorted_symbol_order;
inline uint get_unshifted_max_code(uint len) const
{
LZHAM_ASSERT( (len >= 1) && (len <= cMaxExpectedHuffCodeSize) );
uint k = m_max_codes[len - 1];
if (!k)
return UINT_MAX;
return (k - 1) >> (16 - len);
}
};
bool generate_decoder_tables(uint num_syms, const uint8* pCodesizes, decoder_tables* pTables, uint table_bits, const code_size_histogram &code_size_histo, bool sym_freq_all_ones);
} // namespace prefix_coding
} // namespace lzham
|