From c427c045227973c78ab8937e73e15c65f6212368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 5 Mar 2022 10:41:37 +0100 Subject: [PATCH 1/6] Clear members explicitly instead of zeroing entire object --- src/engine/shared/huffman.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/engine/shared/huffman.cpp b/src/engine/shared/huffman.cpp index 1f29b31cd..125755031 100644 --- a/src/engine/shared/huffman.cpp +++ b/src/engine/shared/huffman.cpp @@ -98,7 +98,10 @@ void CHuffman::Init(const unsigned *pFrequencies) int i; // make sure to cleanout every thing - mem_zero(this, sizeof(*this)); + mem_zero(m_aNodes, sizeof(m_aNodes)); + mem_zero(m_apDecodeLut, sizeof(m_apDecodeLut)); + m_pStartNode = 0x0; + m_NumNodes = 0; // construct the tree ConstructTree(pFrequencies); From f4ade69b5e6a1b4df1d51947f919b3cc6e531c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 5 Mar 2022 10:42:19 +0100 Subject: [PATCH 2/6] Fix comments --- src/engine/shared/huffman.h | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/engine/shared/huffman.h b/src/engine/shared/huffman.h index 2c31da5d6..cf25641a7 100644 --- a/src/engine/shared/huffman.h +++ b/src/engine/shared/huffman.h @@ -40,29 +40,27 @@ class CHuffman public: /* - Function: huffman_init + Function: Init Inits the compressor/decompressor. Parameters: - huff - Pointer to the state to init - frequencies - A pointer to an array of 256 entries of the frequencies of the bytes + pFrequencies - A pointer to an array of 256 entries of the frequencies of the bytes Remarks: - - Does no allocation what so ever. - - You don't have to call any cleanup functions when you are done with it + - Does no allocation whatsoever. + - You don't have to call any cleanup functions when you are done with it. */ void Init(const unsigned *pFrequencies); /* - Function: huffman_compress + Function: Compress Compresses a buffer and outputs a compressed buffer. Parameters: - huff - Pointer to the huffman state - input - Buffer to compress - input_size - Size of the buffer to compress - output - Buffer to put the compressed data into - output_size - Size of the output buffer + pInput - Buffer to compress + InputSize - Size of the buffer to compress + pOutput - Buffer to put the compressed data into + OutputSize - Size of the output buffer Returns: Returns the size of the compressed data. Negative value on failure. @@ -70,19 +68,18 @@ public: int Compress(const void *pInput, int InputSize, void *pOutput, int OutputSize); /* - Function: huffman_decompress + Function: Decompress Decompresses a buffer Parameters: - huff - Pointer to the huffman state - input - Buffer to decompress - input_size - Size of the buffer to decompress - output - Buffer to put the uncompressed data into - output_size - Size of the output buffer + pInput - Buffer to decompress + InputSize - Size of the buffer to decompress + pOutput - Buffer to put the uncompressed data into + OutputSize - Size of the output buffer Returns: Returns the size of the uncompressed data. Negative value on failure. */ int Decompress(const void *pInput, int InputSize, void *pOutput, int OutputSize); }; -#endif // __HUFFMAN_HEADER__ +#endif // ENGINE_SHARED_HUFFMAN_H From 8020934a2649935f5d8ea0cfaf3db5bf85f3ff53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 5 Mar 2022 10:50:48 +0100 Subject: [PATCH 3/6] Make frequency table a static member of CHuffman, use constant --- src/engine/shared/huffman.cpp | 15 +++++++++++++++ src/engine/shared/huffman.h | 4 +++- src/engine/shared/network.cpp | 17 +---------------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/engine/shared/huffman.cpp b/src/engine/shared/huffman.cpp index 125755031..82a212f33 100644 --- a/src/engine/shared/huffman.cpp +++ b/src/engine/shared/huffman.cpp @@ -3,6 +3,21 @@ #include "huffman.h" #include +const unsigned CHuffman::ms_aFreqTable[HUFFMAN_MAX_SYMBOLS] = { + 1 << 30, 4545, 2657, 431, 1950, 919, 444, 482, 2244, 617, 838, 542, 715, 1814, 304, 240, 754, 212, 647, 186, + 283, 131, 146, 166, 543, 164, 167, 136, 179, 859, 363, 113, 157, 154, 204, 108, 137, 180, 202, 176, + 872, 404, 168, 134, 151, 111, 113, 109, 120, 126, 129, 100, 41, 20, 16, 22, 18, 18, 17, 19, + 16, 37, 13, 21, 362, 166, 99, 78, 95, 88, 81, 70, 83, 284, 91, 187, 77, 68, 52, 68, + 59, 66, 61, 638, 71, 157, 50, 46, 69, 43, 11, 24, 13, 19, 10, 12, 12, 20, 14, 9, + 20, 20, 10, 10, 15, 15, 12, 12, 7, 19, 15, 14, 13, 18, 35, 19, 17, 14, 8, 5, + 15, 17, 9, 15, 14, 18, 8, 10, 2173, 134, 157, 68, 188, 60, 170, 60, 194, 62, 175, 71, + 148, 67, 167, 78, 211, 67, 156, 69, 1674, 90, 174, 53, 147, 89, 181, 51, 174, 63, 163, 80, + 167, 94, 128, 122, 223, 153, 218, 77, 200, 110, 190, 73, 174, 69, 145, 66, 277, 143, 141, 60, + 136, 53, 180, 57, 142, 57, 158, 61, 166, 112, 152, 92, 26, 22, 21, 28, 20, 26, 30, 21, + 32, 27, 20, 17, 23, 21, 30, 22, 22, 21, 27, 25, 17, 27, 23, 18, 39, 26, 15, 21, + 12, 18, 18, 27, 20, 18, 15, 19, 11, 17, 33, 12, 18, 15, 19, 18, 16, 26, 17, 18, + 9, 10, 25, 22, 22, 17, 20, 16, 6, 16, 15, 20, 14, 18, 24, 335, 1517}; + struct CHuffmanConstructNode { unsigned short m_NodeId; diff --git a/src/engine/shared/huffman.h b/src/engine/shared/huffman.h index cf25641a7..e7d871451 100644 --- a/src/engine/shared/huffman.h +++ b/src/engine/shared/huffman.h @@ -30,6 +30,8 @@ class CHuffman unsigned char m_Symbol; }; + static const unsigned ms_aFreqTable[HUFFMAN_MAX_SYMBOLS]; + CNode m_aNodes[HUFFMAN_MAX_NODES]; CNode *m_apDecodeLut[HUFFMAN_LUTSIZE]; CNode *m_pStartNode; @@ -50,7 +52,7 @@ public: - Does no allocation whatsoever. - You don't have to call any cleanup functions when you are done with it. */ - void Init(const unsigned *pFrequencies); + void Init(const unsigned *pFrequencies = ms_aFreqTable); /* Function: Compress diff --git a/src/engine/shared/network.cpp b/src/engine/shared/network.cpp index 7cadabb09..e3914e571 100644 --- a/src/engine/shared/network.cpp +++ b/src/engine/shared/network.cpp @@ -412,22 +412,7 @@ int CNetBase::Decompress(const void *pData, int DataSize, void *pOutput, int Out return ms_Huffman.Decompress(pData, DataSize, pOutput, OutputSize); } -static const unsigned s_aFreqTable[256 + 1] = { - 1 << 30, 4545, 2657, 431, 1950, 919, 444, 482, 2244, 617, 838, 542, 715, 1814, 304, 240, 754, 212, 647, 186, - 283, 131, 146, 166, 543, 164, 167, 136, 179, 859, 363, 113, 157, 154, 204, 108, 137, 180, 202, 176, - 872, 404, 168, 134, 151, 111, 113, 109, 120, 126, 129, 100, 41, 20, 16, 22, 18, 18, 17, 19, - 16, 37, 13, 21, 362, 166, 99, 78, 95, 88, 81, 70, 83, 284, 91, 187, 77, 68, 52, 68, - 59, 66, 61, 638, 71, 157, 50, 46, 69, 43, 11, 24, 13, 19, 10, 12, 12, 20, 14, 9, - 20, 20, 10, 10, 15, 15, 12, 12, 7, 19, 15, 14, 13, 18, 35, 19, 17, 14, 8, 5, - 15, 17, 9, 15, 14, 18, 8, 10, 2173, 134, 157, 68, 188, 60, 170, 60, 194, 62, 175, 71, - 148, 67, 167, 78, 211, 67, 156, 69, 1674, 90, 174, 53, 147, 89, 181, 51, 174, 63, 163, 80, - 167, 94, 128, 122, 223, 153, 218, 77, 200, 110, 190, 73, 174, 69, 145, 66, 277, 143, 141, 60, - 136, 53, 180, 57, 142, 57, 158, 61, 166, 112, 152, 92, 26, 22, 21, 28, 20, 26, 30, 21, - 32, 27, 20, 17, 23, 21, 30, 22, 22, 21, 27, 25, 17, 27, 23, 18, 39, 26, 15, 21, - 12, 18, 18, 27, 20, 18, 15, 19, 11, 17, 33, 12, 18, 15, 19, 18, 16, 26, 17, 18, - 9, 10, 25, 22, 22, 17, 20, 16, 6, 16, 15, 20, 14, 18, 24, 335, 1517}; - void CNetBase::Init() { - ms_Huffman.Init(s_aFreqTable); + ms_Huffman.Init(); } From a30991ddd744c3d4cafbe3f3f715083a82673417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 12 Mar 2022 13:01:05 +0100 Subject: [PATCH 4/6] Mark CHuffman::Compress and ::Decompress as const --- src/engine/shared/huffman.cpp | 8 ++++---- src/engine/shared/huffman.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/engine/shared/huffman.cpp b/src/engine/shared/huffman.cpp index 82a212f33..b0767edd2 100644 --- a/src/engine/shared/huffman.cpp +++ b/src/engine/shared/huffman.cpp @@ -148,7 +148,7 @@ void CHuffman::Init(const unsigned *pFrequencies) } //*************************************************************** -int CHuffman::Compress(const void *pInput, int InputSize, void *pOutput, int OutputSize) +int CHuffman::Compress(const void *pInput, int InputSize, void *pOutput, int OutputSize) const { // this macro loads a symbol for a byte into bits and bitcount #define HUFFMAN_MACRO_LOADSYMBOL(Sym) \ @@ -215,7 +215,7 @@ int CHuffman::Compress(const void *pInput, int InputSize, void *pOutput, int Out } //*************************************************************** -int CHuffman::Decompress(const void *pInput, int InputSize, void *pOutput, int OutputSize) +int CHuffman::Decompress(const void *pInput, int InputSize, void *pOutput, int OutputSize) const { // setup buffer pointers unsigned char *pDst = (unsigned char *)pOutput; @@ -226,8 +226,8 @@ int CHuffman::Decompress(const void *pInput, int InputSize, void *pOutput, int O unsigned Bits = 0; unsigned Bitcount = 0; - CNode *pEof = &m_aNodes[HUFFMAN_EOF_SYMBOL]; - CNode *pNode = 0; + const CNode *pEof = &m_aNodes[HUFFMAN_EOF_SYMBOL]; + const CNode *pNode = 0; while(true) { diff --git a/src/engine/shared/huffman.h b/src/engine/shared/huffman.h index e7d871451..e0bc87cea 100644 --- a/src/engine/shared/huffman.h +++ b/src/engine/shared/huffman.h @@ -67,7 +67,7 @@ public: Returns: Returns the size of the compressed data. Negative value on failure. */ - int Compress(const void *pInput, int InputSize, void *pOutput, int OutputSize); + int Compress(const void *pInput, int InputSize, void *pOutput, int OutputSize) const; /* Function: Decompress @@ -82,6 +82,6 @@ public: Returns: Returns the size of the uncompressed data. Negative value on failure. */ - int Decompress(const void *pInput, int InputSize, void *pOutput, int OutputSize); + int Decompress(const void *pInput, int InputSize, void *pOutput, int OutputSize) const; }; #endif // ENGINE_SHARED_HUFFMAN_H From ebb35a8a6f97cce8f3dc851d3de26ce982cb632f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 5 Mar 2022 10:31:32 +0100 Subject: [PATCH 5/6] Replace BubbleSort with std::stable_sort --- src/engine/shared/huffman.cpp | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/src/engine/shared/huffman.cpp b/src/engine/shared/huffman.cpp index b0767edd2..099756656 100644 --- a/src/engine/shared/huffman.cpp +++ b/src/engine/shared/huffman.cpp @@ -1,6 +1,7 @@ /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include "huffman.h" +#include #include const unsigned CHuffman::ms_aFreqTable[HUFFMAN_MAX_SYMBOLS] = { @@ -24,6 +25,11 @@ struct CHuffmanConstructNode int m_Frequency; }; +bool CompareNodesByFrequencyDesc(const CHuffmanConstructNode *pNode1, const CHuffmanConstructNode *pNode2) +{ + return pNode2->m_Frequency < pNode1->m_Frequency; +} + void CHuffman::Setbits_r(CNode *pNode, int Bits, unsigned Depth) { if(pNode->m_aLeafs[1] != 0xffff) @@ -38,29 +44,6 @@ void CHuffman::Setbits_r(CNode *pNode, int Bits, unsigned Depth) } } -// TODO: this should be something faster, but it's enough for now -static void BubbleSort(CHuffmanConstructNode **ppList, int Size) -{ - int Changed = 1; - CHuffmanConstructNode *pTemp; - - while(Changed) - { - Changed = 0; - for(int i = 0; i < Size - 1; i++) - { - if(ppList[i]->m_Frequency < ppList[i + 1]->m_Frequency) - { - pTemp = ppList[i]; - ppList[i] = ppList[i + 1]; - ppList[i + 1] = pTemp; - Changed = 1; - } - } - Size--; - } -} - void CHuffman::ConstructTree(const unsigned *pFrequencies) { CHuffmanConstructNode aNodesLeftStorage[HUFFMAN_MAX_SYMBOLS]; @@ -88,8 +71,7 @@ void CHuffman::ConstructTree(const unsigned *pFrequencies) // construct the table while(NumNodesLeft > 1) { - // we can't rely on stdlib's qsort for this, it can generate different results on different implementations - BubbleSort(apNodesLeft, NumNodesLeft); + std::stable_sort(apNodesLeft, apNodesLeft + NumNodesLeft, CompareNodesByFrequencyDesc); m_aNodes[m_NumNodes].m_NumBits = 0; m_aNodes[m_NumNodes].m_aLeafs[0] = apNodesLeft[NumNodesLeft - 1]->m_NodeId; From 36d9802c8c86599b5d3af098c446346dac2e7c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 2 Apr 2022 00:14:12 +0200 Subject: [PATCH 6/6] Move declaration of loop variable --- src/engine/shared/huffman.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/engine/shared/huffman.cpp b/src/engine/shared/huffman.cpp index 099756656..47d9c3f6a 100644 --- a/src/engine/shared/huffman.cpp +++ b/src/engine/shared/huffman.cpp @@ -92,8 +92,6 @@ void CHuffman::ConstructTree(const unsigned *pFrequencies) void CHuffman::Init(const unsigned *pFrequencies) { - int i; - // make sure to cleanout every thing mem_zero(m_aNodes, sizeof(m_aNodes)); mem_zero(m_apDecodeLut, sizeof(m_apDecodeLut)); @@ -104,7 +102,7 @@ void CHuffman::Init(const unsigned *pFrequencies) ConstructTree(pFrequencies); // build decode LUT - for(i = 0; i < HUFFMAN_LUTSIZE; i++) + for(int i = 0; i < HUFFMAN_LUTSIZE; i++) { unsigned Bits = i; int k;