in csharp/src/HufDecompress.cs [813:925]
public static size_t HUF_readDTableX4_wksp(HUF_DTable* DTable, void* src, size_t srcSize, U32* workSpace, size_t wkspSize)
{
U32 tableLog, maxW, sizeOfSort, nbSymbols;
DTableDesc dtd = GetDTableDesc(DTable);
U32 maxTableLog = dtd.maxTableLog;
size_t iSize;
void* dtPtr = DTable + 1; /* force compiler to avoid strict-aliasing */
HUF_DEltX4* dt = (HUF_DEltX4*)dtPtr;
U32* rankStart;
U32* rankVal;
U32* rankStats;
U32* rankStart0;
sortedSymbol_t* sortedSymbol;
BYTE* weightList;
size_t spaceUsed32 = 0;
rankVal = (U32*)((U32*)workSpace + spaceUsed32);
spaceUsed32 += (sizeofRankValCol_t * HUF_TABLELOG_MAX) >> 2;
rankStats = (U32*)workSpace + spaceUsed32;
spaceUsed32 += HUF_TABLELOG_MAX + 1;
rankStart0 = (U32*)workSpace + spaceUsed32;
spaceUsed32 += HUF_TABLELOG_MAX + 2;
sortedSymbol = (sortedSymbol_t*)workSpace + (spaceUsed32 * sizeof(U32)) / sizeof(sortedSymbol_t);
spaceUsed32 += HUF_ALIGN((size_t)sizeof(sortedSymbol_t) * (HUF_SYMBOLVALUE_MAX + 1), sizeof(U32)) >> 2;
weightList = (BYTE*)((U32*)workSpace + spaceUsed32);
spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
if ((spaceUsed32 << 2) > wkspSize) return ERROR(Error.tableLog_tooLarge);
rankStart = rankStart0 + 1;
memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1));
//HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */
if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(Error.tableLog_tooLarge);
/* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
iSize = ReadStats(weightList, HUF_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);
if (IsError(iSize)) return iSize;
/* check result */
if (tableLog > maxTableLog) return ERROR(Error.tableLog_tooLarge); /* DTable can't fit code depth */
/* find maxWeight */
for (maxW = tableLog; rankStats[maxW] == 0; maxW--)
{
} /* necessarily finds a solution before 0 */
/* Get start index of each weight */
{
U32 w, nextRankStart = 0;
for (w = 1; w < maxW + 1; w++)
{
U32 current = nextRankStart;
nextRankStart += rankStats[w];
rankStart[w] = current;
}
rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/
sizeOfSort = nextRankStart;
}
/* sort symbols by weight */
{
U32 s;
for (s = 0; s < nbSymbols; s++)
{
U32 w = weightList[s];
U32 r = rankStart[w]++;
sortedSymbol[r].symbol = (BYTE)s;
sortedSymbol[r].weight = (BYTE)w;
}
rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
}
/* Build rankVal */
{
U32* rankVal0 = &rankVal[0];
{
int rescale = (int)(maxTableLog - tableLog) - 1; /* tableLog <= maxTableLog */
U32 nextRankVal = 0;
U32 w;
for (w = 1; w < maxW + 1; w++)
{
U32 current = nextRankVal;
nextRankVal += rankStats[w] << (int)(w + rescale);
rankVal0[w] = current;
}
}
{
U32 minBits = tableLog + 1 - maxW;
U32 consumed;
for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++)
{
U32* rankValPtr = &rankVal[consumed * (HUF_TABLELOG_MAX + 1)];
U32 w;
for (w = 1; w < maxW + 1; w++)
{
rankValPtr[w] = rankVal0[w] >> (int)consumed;
}
}
}
}
HUF_fillDTableX4(dt, maxTableLog,
sortedSymbol, sizeOfSort,
rankStart0, rankVal, maxW,
tableLog + 1);
dtd.tableLog = (BYTE)maxTableLog;
dtd.tableType = 1;
*(DTableDesc*)DTable = dtd; // memcpy(DTable, &dtd, sizeof(dtd));
return iSize;
}