// File: lzham_prefix_coding.h // LZHAM is in the Public Domain. Please see the Public Domain declaration at the end of include/lzham.h #pragma once namespace lzham { namespace prefix_coding { const uint cMaxExpectedCodeSize = 16; 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() : 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_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; 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(pCur_lookup); m_lookup = NULL; if (rhs.m_lookup) { m_lookup = lzham_new_array(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(pCur_sorted_symbol_order); m_sorted_symbol_order = NULL; if (rhs.m_sorted_symbol_order) { m_sorted_symbol_order = lzham_new_array(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_lookup); m_lookup = 0; m_cur_lookup_size = 0; } if (m_sorted_symbol_order) { lzham_delete_array(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_lookup); if (m_sorted_symbol_order) lzham_delete_array(m_sorted_symbol_order); } // DO NOT use any complex classes here - it is bitwise copied. 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[cMaxExpectedCodeSize + 1]; int m_val_ptrs[cMaxExpectedCodeSize + 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 <= cMaxExpectedCodeSize) ); 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); } // namespace prefix_coding } // namespace lzham