inline unsigned int HuffmanDecoder::Decode(code_t code, /* out */ value_t &value) const { assert(m_codeToValue.size() > 0); LookupEntry &entry = m_cache[code & m_cacheMask]; code_t normalizedCode; if (entry.type != 1) normalizedCode = BitReverse(code); if (entry.type == 0) FillCacheEntry(entry, normalizedCode); if (entry.type == 1) { value = entry.value; return entry.len; } else { const CodeInfo &codeInfo = (entry.type == 2) ? entry.begin[(normalizedCode << m_cacheBits) >> (MAX_CODE_BITS - (entry.len - m_cacheBits))] : *(std::upper_bound(entry.begin, entry.end, normalizedCode, CodeLessThan())-1); value = codeInfo.value; return codeInfo.len; } }
void HuffmanDecoder::FillCacheEntry(LookupEntry &entry, code_t normalizedCode) const { normalizedCode &= m_normalizedCacheMask; const CodeInfo &codeInfo = *(std::upper_bound(m_codeToValue.begin(), m_codeToValue.end(), normalizedCode, CodeLessThan())-1); if (codeInfo.len <= m_cacheBits) { entry.type = 1; entry.value = codeInfo.value; entry.len = codeInfo.len; } else { entry.begin = &codeInfo; const CodeInfo *last = & *(std::upper_bound(m_codeToValue.begin(), m_codeToValue.end(), normalizedCode + ~m_normalizedCacheMask, CodeLessThan())-1); if (codeInfo.len == last->len) { entry.type = 2; entry.len = codeInfo.len; } else { entry.type = 3; entry.end = last+1; } } }