123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #ifndef CRYINCLUDE_CRYSYSTEM_HUFFMAN_H
- #define CRYINCLUDE_CRYSYSTEM_HUFFMAN_H
- #pragma once
- class HuffmanCoder
- {
- private:
- struct HuffmanTreeNode
- {
- uint32 count;
- uint32 savedCount;
- int child0;
- int child1;
- };
- struct HuffmanSymbolCode
- {
- uint32 value;
- uint32 numBits;
- };
- struct BitStreamBuilder
- {
- enum EModes
- {
- eM_WRITE,
- eM_READ
- };
- union buf_ptr
- {
- uint8* ptr;
- const uint8* const_ptr;
- };
- EModes m_mode;
- uint8 m_mask;
- buf_ptr m_pBufferStart;
- buf_ptr m_pBufferCursor;
- buf_ptr m_pBufferEnd; //Pointer to the last byte in the buffer
- BitStreamBuilder(uint8* pBufferStart, uint8* pBufferEnd)
- : m_mode(eM_WRITE)
- , m_mask(0x80)
- {
- m_pBufferStart.ptr = pBufferStart;
- m_pBufferCursor.ptr = pBufferStart;
- m_pBufferEnd.ptr = pBufferEnd;
- }
- BitStreamBuilder(const uint8* pBufferStart, const uint8* pBufferEnd)
- : m_mode(eM_READ)
- , m_mask(0x80)
- {
- m_pBufferStart.const_ptr = pBufferStart;
- m_pBufferCursor.const_ptr = pBufferStart;
- m_pBufferEnd.const_ptr = pBufferEnd;
- }
- void AddBits(uint32 value, uint32 numBits);
- void AddBits(uint8 value, uint32 numBits);
- //Returns 1 or 0 for valid values. Returns 2 if the buffer has run out or is the wrong type of builder.
- uint8 GetBit();
- };
- const static int MAX_SYMBOL_VALUE = (255);
- const static int MAX_NUM_SYMBOLS = (MAX_SYMBOL_VALUE + 1);
- const static int END_OF_STREAM = (MAX_NUM_SYMBOLS);
- const static int MAX_NUM_CODES = (MAX_NUM_SYMBOLS + 1);
- const static int MAX_NUM_NODES = (MAX_NUM_CODES * 2);
- const static int MAX_NODE = (MAX_NUM_NODES - 1);
- enum EHuffmanCoderState
- {
- eHCS_NEW, //Has been created, Init not called
- eHCS_OPEN, //Init has been called, tree not yet constructed. Can accept new data.
- eHCS_FINAL //Finalize has been called. Can no longer accept data, but can encode/decode.
- };
- HuffmanTreeNode* m_TreeNodes;
- HuffmanSymbolCode* m_Codes;
- uint32* m_Counts;
- int m_RootNode;
- uint32 m_RefCount;
- EHuffmanCoderState m_State;
- public:
- HuffmanCoder()
- : m_TreeNodes(NULL)
- , m_Codes(NULL)
- , m_Counts(NULL)
- , m_State(eHCS_NEW)
- , m_RootNode(0)
- , m_RefCount(0) {}
- ~HuffmanCoder()
- {
- SAFE_DELETE_ARRAY(m_TreeNodes);
- SAFE_DELETE_ARRAY(m_Codes);
- SAFE_DELETE_ARRAY(m_Counts);
- }
- //A bit like an MD5 generator, has three phases.
- //Clears the existing data
- void Init();
- //Adds the values of an array of chars to the counts
- void Update(const uint8* const pSource, const size_t numBytes);
- //Construct the coding tree using the counts
- void Finalize();
- //We typically create a Huffman Coder per localized string table loaded. Since we can and do unload strings at runtime, it's useful to keep a ref count of each coder.
- inline void AddRef() { m_RefCount++; }
- inline void DecRef() { m_RefCount = m_RefCount > 0 ? m_RefCount - 1 : 0; }
- inline uint32 RefCount() { return m_RefCount; }
- void CompressInput(const uint8* const pInput, const size_t numBytes, uint8* const pOutput, size_t* const outputSize);
- size_t UncompressInput(const uint8* const pInput, const size_t numBytes, uint8* const pOutput, const size_t maxOutputSize);
- private:
- void ScaleCountsAndUpdateNodes();
- int BuildTree();
- void ConvertTreeToCode(const HuffmanTreeNode* const pNodes, HuffmanSymbolCode* const pCodes, const unsigned int value, const unsigned int numBits, const int node);
- };
- #endif // CRYINCLUDE_CRYSYSTEM_HUFFMAN_H
|