##// END OF EJS Templates
files: add support for log-like template keywords and functions...
files: add support for log-like template keywords and functions Note that the ctx does not point to the revision where the file was last changed, but the revision specified by -rREV option.

File last commit:

r37513:b1fb341d default
r38560:7ae0ea73 default
Show More
huf_compress.c
788 lines | 31.6 KiB | text/x-c | CLexer
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 /* ******************************************************************
Huffman encoder, part of New Generation Entropy library
Copyright (C) 2013-2016, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
- Public forum : https://groups.google.com/forum/#!forum/lz4c
****************************************************************** */
/* **************************************************************
* Compiler specifics
****************************************************************/
#ifdef _MSC_VER /* Visual Studio */
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
#endif
/* **************************************************************
* Includes
****************************************************************/
#include <string.h> /* memcpy, memset */
#include <stdio.h> /* printf (debug) */
#include "bitstream.h"
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 #include "compiler.h"
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 #define FSE_STATIC_LINKING_ONLY /* FSE_optimalTableLog_internal */
#include "fse.h" /* header compression */
#define HUF_STATIC_LINKING_ONLY
#include "huf.h"
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 #include "error_private.h"
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434
/* **************************************************************
* Error Management
****************************************************************/
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 #define HUF_isError ERR_isError
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 #define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 #define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 #define CHECK_F(f) { CHECK_V_F(_var_err__, f); }
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434
/* **************************************************************
* Utils
****************************************************************/
unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue)
{
return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 1);
}
/* *******************************************************
* HUF : Huffman block compression
*********************************************************/
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 /* HUF_compressWeights() :
* Same as FSE_compress(), but dedicated to huff0's weights compression.
* The use case needs much less stack memory.
* Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX.
*/
#define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6
size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weightTable, size_t wtSize)
{
BYTE* const ostart = (BYTE*) dst;
BYTE* op = ostart;
BYTE* const oend = ostart + dstSize;
U32 maxSymbolValue = HUF_TABLELOG_MAX;
U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER;
FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)];
BYTE scratchBuffer[1<<MAX_FSE_TABLELOG_FOR_HUFF_HEADER];
U32 count[HUF_TABLELOG_MAX+1];
S16 norm[HUF_TABLELOG_MAX+1];
/* init conditions */
if (wtSize <= 1) return 0; /* Not compressible */
/* Scan input and build symbol stats */
{ CHECK_V_F(maxCount, FSE_count_simple(count, &maxSymbolValue, weightTable, wtSize) );
if (maxCount == wtSize) return 1; /* only a single symbol in src : rle */
if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */
}
tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue);
CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue) );
/* Write table description header */
{ CHECK_V_F(hSize, FSE_writeNCount(op, oend-op, norm, maxSymbolValue, tableLog) );
op += hSize;
}
/* Compress */
CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer)) );
{ CHECK_V_F(cSize, FSE_compress_usingCTable(op, oend - op, weightTable, wtSize, CTable) );
if (cSize == 0) return 0; /* not enough space for compressed data */
op += cSize;
}
return op-ostart;
}
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 struct HUF_CElt_s {
U16 val;
BYTE nbBits;
}; /* typedef'd to HUF_CElt within "huf.h" */
/*! HUF_writeCTable() :
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 `CTable` : Huffman tree to save, using huf representation.
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 @return : size of saved CTable */
size_t HUF_writeCTable (void* dst, size_t maxDstSize,
const HUF_CElt* CTable, U32 maxSymbolValue, U32 huffLog)
{
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; /* precomputed conversion table */
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 BYTE huffWeight[HUF_SYMBOLVALUE_MAX];
BYTE* op = (BYTE*)dst;
U32 n;
/* check conditions */
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434
/* convert to weight */
bitsToWeight[0] = 0;
for (n=1; n<huffLog+1; n++)
bitsToWeight[n] = (BYTE)(huffLog + 1 - n);
for (n=0; n<maxSymbolValue; n++)
huffWeight[n] = bitsToWeight[CTable[n].nbBits];
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 /* attempt weights compression by FSE */
{ CHECK_V_F(hSize, HUF_compressWeights(op+1, maxDstSize-1, huffWeight, maxSymbolValue) );
if ((hSize>1) & (hSize < maxSymbolValue/2)) { /* FSE compressed */
op[0] = (BYTE)hSize;
return hSize+1;
} }
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 /* write raw values as 4-bits (max : 15) */
if (maxSymbolValue > (256-128)) return ERROR(GENERIC); /* should not happen : likely means source cannot be compressed */
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */
op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1));
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause msan issue in final combination */
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 for (n=0; n<maxSymbolValue; n+=2)
op[(n/2)+1] = (BYTE)((huffWeight[n] << 4) + huffWeight[n+1]);
return ((maxSymbolValue+1)/2) + 1;
}
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 size_t HUF_readCTable (HUF_CElt* CTable, U32* maxSymbolValuePtr, const void* src, size_t srcSize)
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 {
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; /* init not required, even though some static analyzer may complain */
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */
U32 tableLog = 0;
U32 nbSymbols = 0;
/* get symbol weights */
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 CHECK_V_F(readSize, HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX+1, rankVal, &nbSymbols, &tableLog, src, srcSize));
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434
/* check result */
if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 if (nbSymbols > *maxSymbolValuePtr+1) return ERROR(maxSymbolValue_tooSmall);
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434
/* Prepare base value per rank */
{ U32 n, nextRankStart = 0;
for (n=1; n<=tableLog; n++) {
U32 current = nextRankStart;
nextRankStart += (rankVal[n] << (n-1));
rankVal[n] = current;
} }
/* fill nbBits */
{ U32 n; for (n=0; n<nbSymbols; n++) {
const U32 w = huffWeight[n];
CTable[n].nbBits = (BYTE)(tableLog + 1 - w);
} }
/* fill val */
{ U16 nbPerRank[HUF_TABLELOG_MAX+2] = {0}; /* support w=0=>n=tableLog+1 */
U16 valPerRank[HUF_TABLELOG_MAX+2] = {0};
{ U32 n; for (n=0; n<nbSymbols; n++) nbPerRank[CTable[n].nbBits]++; }
/* determine stating value per rank */
valPerRank[tableLog+1] = 0; /* for w==0 */
{ U16 min = 0;
U32 n; for (n=tableLog; n>0; n--) { /* start at n=tablelog <-> w=1 */
valPerRank[n] = min; /* get starting value within each rank */
min += nbPerRank[n];
min >>= 1;
} }
/* assign value within rank, symbol order */
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 { U32 n; for (n=0; n<nbSymbols; n++) CTable[n].val = valPerRank[CTable[n].nbBits]++; }
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 }
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 *maxSymbolValuePtr = nbSymbols - 1;
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 return readSize;
}
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 typedef struct nodeElt_s {
U32 count;
U16 parent;
BYTE byte;
BYTE nbBits;
} nodeElt;
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits)
{
const U32 largestBits = huffNode[lastNonNull].nbBits;
if (largestBits <= maxNbBits) return largestBits; /* early exit : no elt > maxNbBits */
/* there are several too large elements (at least >= 2) */
{ int totalCost = 0;
const U32 baseCost = 1 << (largestBits - maxNbBits);
U32 n = lastNonNull;
while (huffNode[n].nbBits > maxNbBits) {
totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits));
huffNode[n].nbBits = (BYTE)maxNbBits;
n --;
} /* n stops at huffNode[n].nbBits <= maxNbBits */
while (huffNode[n].nbBits == maxNbBits) n--; /* n end at index of smallest symbol using < maxNbBits */
/* renorm totalCost */
totalCost >>= (largestBits - maxNbBits); /* note : totalCost is necessarily a multiple of baseCost */
/* repay normalized cost */
{ U32 const noSymbol = 0xF0F0F0F0;
U32 rankLast[HUF_TABLELOG_MAX+2];
int pos;
/* Get pos of last (smallest) symbol per rank */
memset(rankLast, 0xF0, sizeof(rankLast));
{ U32 currentNbBits = maxNbBits;
for (pos=n ; pos >= 0; pos--) {
if (huffNode[pos].nbBits >= currentNbBits) continue;
currentNbBits = huffNode[pos].nbBits; /* < maxNbBits */
rankLast[maxNbBits-currentNbBits] = pos;
} }
while (totalCost > 0) {
U32 nBitsToDecrease = BIT_highbit32(totalCost) + 1;
for ( ; nBitsToDecrease > 1; nBitsToDecrease--) {
U32 highPos = rankLast[nBitsToDecrease];
U32 lowPos = rankLast[nBitsToDecrease-1];
if (highPos == noSymbol) continue;
if (lowPos == noSymbol) break;
{ U32 const highTotal = huffNode[highPos].count;
U32 const lowTotal = 2 * huffNode[lowPos].count;
if (highTotal <= lowTotal) break;
} }
/* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 /* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */
while ((nBitsToDecrease<=HUF_TABLELOG_MAX) && (rankLast[nBitsToDecrease] == noSymbol))
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 nBitsToDecrease ++;
totalCost -= 1 << (nBitsToDecrease-1);
if (rankLast[nBitsToDecrease-1] == noSymbol)
rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease]; /* this rank is no longer empty */
huffNode[rankLast[nBitsToDecrease]].nbBits ++;
if (rankLast[nBitsToDecrease] == 0) /* special case, reached largest symbol */
rankLast[nBitsToDecrease] = noSymbol;
else {
rankLast[nBitsToDecrease]--;
if (huffNode[rankLast[nBitsToDecrease]].nbBits != maxNbBits-nBitsToDecrease)
rankLast[nBitsToDecrease] = noSymbol; /* this rank is now empty */
} } /* while (totalCost > 0) */
while (totalCost < 0) { /* Sometimes, cost correction overshoot */
if (rankLast[1] == noSymbol) { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */
while (huffNode[n].nbBits == maxNbBits) n--;
huffNode[n+1].nbBits--;
rankLast[1] = n+1;
totalCost++;
continue;
}
huffNode[ rankLast[1] + 1 ].nbBits--;
rankLast[1]++;
totalCost ++;
} } } /* there are several too large elements (at least >= 2) */
return maxNbBits;
}
typedef struct {
U32 base;
U32 current;
} rankPos;
static void HUF_sort(nodeElt* huffNode, const U32* count, U32 maxSymbolValue)
{
rankPos rank[32];
U32 n;
memset(rank, 0, sizeof(rank));
for (n=0; n<=maxSymbolValue; n++) {
U32 r = BIT_highbit32(count[n] + 1);
rank[r].base ++;
}
for (n=30; n>0; n--) rank[n-1].base += rank[n].base;
for (n=0; n<32; n++) rank[n].current = rank[n].base;
for (n=0; n<=maxSymbolValue; n++) {
U32 const c = count[n];
U32 const r = BIT_highbit32(c+1) + 1;
U32 pos = rank[r].current++;
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 while ((pos > rank[r].base) && (c > huffNode[pos-1].count)) {
huffNode[pos] = huffNode[pos-1];
pos--;
}
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 huffNode[pos].count = c;
huffNode[pos].byte = (BYTE)n;
}
}
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 /** HUF_buildCTable_wksp() :
* Same as HUF_buildCTable(), but using externally allocated scratch buffer.
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of HUF_CTABLE_WORKSPACE_SIZE_U32 unsigned.
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 */
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 #define STARTNODE (HUF_SYMBOLVALUE_MAX+1)
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32];
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize)
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 {
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 nodeElt* const huffNode0 = (nodeElt*)workSpace;
nodeElt* const huffNode = huffNode0+1;
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 U32 n, nonNullRank;
int lowS, lowN;
U16 nodeNb = STARTNODE;
U32 nodeRoot;
/* safety checks */
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
if (wkspSize < sizeof(huffNodeTable)) return ERROR(workSpace_tooSmall);
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT;
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 memset(huffNode0, 0, sizeof(huffNodeTable));
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434
/* sort, decreasing order */
HUF_sort(huffNode, count, maxSymbolValue);
/* init for parents */
nonNullRank = maxSymbolValue;
while(huffNode[nonNullRank].count == 0) nonNullRank--;
lowS = nonNullRank; nodeRoot = nodeNb + lowS - 1; lowN = nodeNb;
huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count;
huffNode[lowS].parent = huffNode[lowS-1].parent = nodeNb;
nodeNb++; lowS-=2;
for (n=nodeNb; n<=nodeRoot; n++) huffNode[n].count = (U32)(1U<<30);
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 huffNode0[0].count = (U32)(1U<<31); /* fake entry, strong barrier */
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434
/* create parents */
while (nodeNb <= nodeRoot) {
U32 n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++;
U32 n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++;
huffNode[nodeNb].count = huffNode[n1].count + huffNode[n2].count;
huffNode[n1].parent = huffNode[n2].parent = nodeNb;
nodeNb++;
}
/* distribute weights (unlimited tree height) */
huffNode[nodeRoot].nbBits = 0;
for (n=nodeRoot-1; n>=STARTNODE; n--)
huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1;
for (n=0; n<=nonNullRank; n++)
huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1;
/* enforce maxTableLog */
maxNbBits = HUF_setMaxHeight(huffNode, nonNullRank, maxNbBits);
/* fill result into tree (val, nbBits) */
{ U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0};
U16 valPerRank[HUF_TABLELOG_MAX+1] = {0};
if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */
for (n=0; n<=nonNullRank; n++)
nbPerRank[huffNode[n].nbBits]++;
/* determine stating value per rank */
{ U16 min = 0;
for (n=maxNbBits; n>0; n--) {
valPerRank[n] = min; /* get starting value within each rank */
min += nbPerRank[n];
min >>= 1;
} }
for (n=0; n<=maxSymbolValue; n++)
tree[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */
for (n=0; n<=maxSymbolValue; n++)
tree[n].val = valPerRank[tree[n].nbBits]++; /* assign value within rank, symbol order */
}
return maxNbBits;
}
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 /** HUF_buildCTable() :
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 * @return : maxNbBits
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 * Note : count is used before tree is written, so they can safely overlap
*/
size_t HUF_buildCTable (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits)
{
huffNodeTable nodeTable;
return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, nodeTable, sizeof(nodeTable));
}
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 static size_t HUF_estimateCompressedSize(HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue)
{
size_t nbBits = 0;
int s;
for (s = 0; s <= (int)maxSymbolValue; ++s) {
nbBits += CTable[s].nbBits * count[s];
}
return nbBits >> 3;
}
static int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) {
int bad = 0;
int s;
for (s = 0; s <= (int)maxSymbolValue; ++s) {
bad |= (count[s] != 0) & (CTable[s].nbBits == 0);
}
return !bad;
}
size_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); }
FORCE_INLINE_TEMPLATE void
HUF_encodeSymbol(BIT_CStream_t* bitCPtr, U32 symbol, const HUF_CElt* CTable)
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 {
BIT_addBitsFast(bitCPtr, CTable[symbol].val, CTable[symbol].nbBits);
}
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 #define HUF_FLUSHBITS(s) BIT_flushBits(s)
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434
#define HUF_FLUSHBITS_1(stream) \
if (sizeof((stream)->bitContainer)*8 < HUF_TABLELOG_MAX*2+7) HUF_FLUSHBITS(stream)
#define HUF_FLUSHBITS_2(stream) \
if (sizeof((stream)->bitContainer)*8 < HUF_TABLELOG_MAX*4+7) HUF_FLUSHBITS(stream)
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 FORCE_INLINE_TEMPLATE size_t
HUF_compress1X_usingCTable_internal_body(void* dst, size_t dstSize,
const void* src, size_t srcSize,
const HUF_CElt* CTable)
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 {
const BYTE* ip = (const BYTE*) src;
BYTE* const ostart = (BYTE*)dst;
BYTE* const oend = ostart + dstSize;
BYTE* op = ostart;
size_t n;
BIT_CStream_t bitC;
/* init */
if (dstSize < 8) return 0; /* not enough space to compress */
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 { size_t const initErr = BIT_initCStream(&bitC, op, oend-op);
if (HUF_isError(initErr)) return 0; }
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434
n = srcSize & ~3; /* join to mod 4 */
switch (srcSize & 3)
{
case 3 : HUF_encodeSymbol(&bitC, ip[n+ 2], CTable);
HUF_FLUSHBITS_2(&bitC);
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 /* fall-through */
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 case 2 : HUF_encodeSymbol(&bitC, ip[n+ 1], CTable);
HUF_FLUSHBITS_1(&bitC);
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 /* fall-through */
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 case 1 : HUF_encodeSymbol(&bitC, ip[n+ 0], CTable);
HUF_FLUSHBITS(&bitC);
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 /* fall-through */
case 0 : /* fall-through */
default: break;
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 }
for (; n>0; n-=4) { /* note : n&3==0 at this stage */
HUF_encodeSymbol(&bitC, ip[n- 1], CTable);
HUF_FLUSHBITS_1(&bitC);
HUF_encodeSymbol(&bitC, ip[n- 2], CTable);
HUF_FLUSHBITS_2(&bitC);
HUF_encodeSymbol(&bitC, ip[n- 3], CTable);
HUF_FLUSHBITS_1(&bitC);
HUF_encodeSymbol(&bitC, ip[n- 4], CTable);
HUF_FLUSHBITS(&bitC);
}
return BIT_closeCStream(&bitC);
}
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 #if DYNAMIC_BMI2
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 static TARGET_ATTRIBUTE("bmi2") size_t
HUF_compress1X_usingCTable_internal_bmi2(void* dst, size_t dstSize,
const void* src, size_t srcSize,
const HUF_CElt* CTable)
{
return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);
}
static size_t
HUF_compress1X_usingCTable_internal_default(void* dst, size_t dstSize,
const void* src, size_t srcSize,
const HUF_CElt* CTable)
{
return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);
}
static size_t
HUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,
const void* src, size_t srcSize,
const HUF_CElt* CTable, const int bmi2)
{
if (bmi2) {
return HUF_compress1X_usingCTable_internal_bmi2(dst, dstSize, src, srcSize, CTable);
}
return HUF_compress1X_usingCTable_internal_default(dst, dstSize, src, srcSize, CTable);
}
#else
static size_t
HUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,
const void* src, size_t srcSize,
const HUF_CElt* CTable, const int bmi2)
{
(void)bmi2;
return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);
}
#endif
size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)
{
return HUF_compress1X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0);
}
static size_t
HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
const void* src, size_t srcSize,
const HUF_CElt* CTable, int bmi2)
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 {
size_t const segmentSize = (srcSize+3)/4; /* first 3 segments */
const BYTE* ip = (const BYTE*) src;
const BYTE* const iend = ip + srcSize;
BYTE* const ostart = (BYTE*) dst;
BYTE* const oend = ostart + dstSize;
BYTE* op = ostart;
if (dstSize < 6 + 1 + 1 + 1 + 8) return 0; /* minimum space to compress successfully */
if (srcSize < 12) return 0; /* no saving possible : too small input */
op += 6; /* jumpTable */
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, segmentSize, CTable, bmi2) );
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 if (cSize==0) return 0;
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 assert(cSize <= 65535);
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 MEM_writeLE16(ostart, (U16)cSize);
op += cSize;
}
ip += segmentSize;
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, segmentSize, CTable, bmi2) );
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 if (cSize==0) return 0;
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 assert(cSize <= 65535);
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 MEM_writeLE16(ostart+2, (U16)cSize);
op += cSize;
}
ip += segmentSize;
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, segmentSize, CTable, bmi2) );
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 if (cSize==0) return 0;
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 assert(cSize <= 65535);
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 MEM_writeLE16(ostart+4, (U16)cSize);
op += cSize;
}
ip += segmentSize;
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, iend-ip, CTable, bmi2) );
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 if (cSize==0) return 0;
op += cSize;
}
return op-ostart;
}
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)
{
return HUF_compress4X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0);
}
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513
static size_t HUF_compressCTable_internal(
BYTE* const ostart, BYTE* op, BYTE* const oend,
const void* src, size_t srcSize,
unsigned singleStream, const HUF_CElt* CTable, const int bmi2)
{
size_t const cSize = singleStream ?
HUF_compress1X_usingCTable_internal(op, oend - op, src, srcSize, CTable, bmi2) :
HUF_compress4X_usingCTable_internal(op, oend - op, src, srcSize, CTable, bmi2);
if (HUF_isError(cSize)) { return cSize; }
if (cSize==0) { return 0; } /* uncompressible */
op += cSize;
/* check compressibility */
if ((size_t)(op-ostart) >= srcSize-1) { return 0; }
return op-ostart;
}
typedef struct {
U32 count[HUF_SYMBOLVALUE_MAX + 1];
HUF_CElt CTable[HUF_SYMBOLVALUE_MAX + 1];
huffNodeTable nodeTable;
} HUF_compress_tables_t;
/* HUF_compress_internal() :
* `workSpace` must a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 static size_t HUF_compress_internal (
void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog,
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 unsigned singleStream,
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 void* workSpace, size_t wkspSize,
HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat,
const int bmi2)
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 {
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 HUF_compress_tables_t* const table = (HUF_compress_tables_t*)workSpace;
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 BYTE* const ostart = (BYTE*)dst;
BYTE* const oend = ostart + dstSize;
BYTE* op = ostart;
/* checks & inits */
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
if (wkspSize < sizeof(*table)) return ERROR(workSpace_tooSmall);
if (!srcSize) return 0; /* Uncompressed */
if (!dstSize) return 0; /* cannot fit anything within dst budget */
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 if (srcSize > HUF_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); /* current block size limit */
if (huffLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 if (!maxSymbolValue) maxSymbolValue = HUF_SYMBOLVALUE_MAX;
if (!huffLog) huffLog = HUF_TABLELOG_DEFAULT;
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 /* Heuristic : If old table is valid, use it for small inputs */
if (preferRepeat && repeat && *repeat == HUF_repeat_valid) {
return HUF_compressCTable_internal(ostart, op, oend,
src, srcSize,
singleStream, oldHufTable, bmi2);
}
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 /* Scan input and build symbol stats */
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 { CHECK_V_F(largest, FSE_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, table->count) );
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 if (largest <= (srcSize >> 7)+1) return 0; /* heuristic : probably not compressible enough */
}
/* Check validity of previous table */
if ( repeat
&& *repeat == HUF_repeat_check
&& !HUF_validateCTable(oldHufTable, table->count, maxSymbolValue)) {
*repeat = HUF_repeat_none;
}
/* Heuristic : use existing table for small inputs */
if (preferRepeat && repeat && *repeat != HUF_repeat_none) {
return HUF_compressCTable_internal(ostart, op, oend,
src, srcSize,
singleStream, oldHufTable, bmi2);
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 }
/* Build Huffman Tree */
huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 { CHECK_V_F(maxBits, HUF_buildCTable_wksp(table->CTable, table->count,
maxSymbolValue, huffLog,
table->nodeTable, sizeof(table->nodeTable)) );
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 huffLog = (U32)maxBits;
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 /* Zero unused symbols in CTable, so we can check it for validity */
memset(table->CTable + (maxSymbolValue + 1), 0,
sizeof(table->CTable) - ((maxSymbolValue + 1) * sizeof(HUF_CElt)));
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 }
/* Write table description header */
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 { CHECK_V_F(hSize, HUF_writeCTable (op, dstSize, table->CTable, maxSymbolValue, huffLog) );
/* Check if using previous huffman table is beneficial */
if (repeat && *repeat != HUF_repeat_none) {
size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, table->count, maxSymbolValue);
size_t const newSize = HUF_estimateCompressedSize(table->CTable, table->count, maxSymbolValue);
if (oldSize <= hSize + newSize || hSize + 12 >= srcSize) {
return HUF_compressCTable_internal(ostart, op, oend,
src, srcSize,
singleStream, oldHufTable, bmi2);
} }
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 /* Use the new huffman table */
if (hSize + 12ul >= srcSize) { return 0; }
op += hSize;
if (repeat) { *repeat = HUF_repeat_none; }
if (oldHufTable)
memcpy(oldHufTable, table->CTable, sizeof(table->CTable)); /* Save new table */
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 }
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 return HUF_compressCTable_internal(ostart, op, oend,
src, srcSize,
singleStream, table->CTable, bmi2);
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 }
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 size_t HUF_compress1X_wksp (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog,
void* workSpace, size_t wkspSize)
{
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 return HUF_compress_internal(dst, dstSize, src, srcSize,
maxSymbolValue, huffLog, 1 /*single stream*/,
workSpace, wkspSize,
NULL, NULL, 0, 0 /*bmi2*/);
}
size_t HUF_compress1X_repeat (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog,
void* workSpace, size_t wkspSize,
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2)
{
return HUF_compress_internal(dst, dstSize, src, srcSize,
maxSymbolValue, huffLog, 1 /*single stream*/,
workSpace, wkspSize, hufTable,
repeat, preferRepeat, bmi2);
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 }
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 size_t HUF_compress1X (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog)
{
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 unsigned workSpace[HUF_WORKSPACE_SIZE_U32];
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
}
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 /* HUF_compress4X_repeat():
* compress input using 4 streams.
* provide workspace to generate compression tables */
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 size_t HUF_compress4X_wksp (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog,
void* workSpace, size_t wkspSize)
{
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 return HUF_compress_internal(dst, dstSize, src, srcSize,
maxSymbolValue, huffLog, 0 /*4 streams*/,
workSpace, wkspSize,
NULL, NULL, 0, 0 /*bmi2*/);
}
/* HUF_compress4X_repeat():
* compress input using 4 streams.
* re-use an existing huffman compression table */
size_t HUF_compress4X_repeat (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog,
void* workSpace, size_t wkspSize,
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2)
{
return HUF_compress_internal(dst, dstSize, src, srcSize,
maxSymbolValue, huffLog, 0 /* 4 streams */,
workSpace, wkspSize,
hufTable, repeat, preferRepeat, bmi2);
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 }
size_t HUF_compress2 (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog)
{
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 unsigned workSpace[HUF_WORKSPACE_SIZE_U32];
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 return HUF_compress4X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 }
size_t HUF_compress (void* dst, size_t maxDstSize, const void* src, size_t srcSize)
{
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 return HUF_compress2(dst, maxDstSize, src, srcSize, 255, HUF_TABLELOG_DEFAULT);
Gregory Szorc
zstd: vendor zstd 1.1.1...
r30434 }