public static size_t ReadStats()

in csharp/src/EntropyCommon.cs [198:269]


		public static size_t ReadStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr, void* src, size_t srcSize)
		{
			U32 weightTotal;
			BYTE* ip = (BYTE*)src;
			size_t iSize;
			size_t oSize;

			if (srcSize == 0) return ERROR(Error.srcSize_wrong);
			iSize = ip[0];
			/* memset(huffWeight, 0, hwSize);   *//* is not necessary, even though some analyzer complain ... */

			if (iSize >= 128)
			{  /* special header */
				oSize = iSize - 127;
				iSize = ((oSize + 1) / 2);
				if (iSize + 1 > srcSize) return ERROR(Error.srcSize_wrong);
				if (oSize >= hwSize) return ERROR(Error.corruption_detected);
				ip += 1;
				{
					U32 n;
					for (n = 0; n < oSize; n += 2)
					{
						huffWeight[n] = (BYTE)(ip[n / 2] >> 4);
						huffWeight[n + 1] = (BYTE)(ip[n / 2] & 15);
					}
				}
			}
			else
			{   /* header compressed with FSE (normal case) */
				FSE_DTable* fseWorkspace = stackalloc FSE_DTable[Fse.FSE_DTABLE_SIZE_U32(6)];  /* 6 is max possible tableLog for HUF header (maybe even 5, to be tested) */
				if (iSize + 1 > srcSize) return ERROR(Error.srcSize_wrong);
				oSize = FseDecompress.FSE_decompress_wksp(huffWeight, hwSize - 1, ip + 1, iSize, fseWorkspace, 6);   /* max (hwSize-1) values decoded, as last one is implied */
				if (IsError(oSize)) return oSize;
			}

			/* collect weight stats */
			memset(rankStats, 0, (Huf.HUF_TABLELOG_MAX + 1) * sizeof(U32));
			weightTotal = 0;
			{
				U32 n; for (n = 0; n < oSize; n++)
				{
					if (huffWeight[n] >= Huf.HUF_TABLELOG_MAX) return ERROR(Error.corruption_detected);
					rankStats[huffWeight[n]]++;
					weightTotal += ((U32)1 << huffWeight[n]) >> 1;
				}
			}
			if (weightTotal == 0) return ERROR(Error.corruption_detected);

			/* get last non-null symbol weight (implied, total must be 2^n) */
			{
				U32 tableLog = BitStream.BIT_highbit32(weightTotal) + 1;
				if (tableLog > Huf.HUF_TABLELOG_MAX) return ERROR(Error.corruption_detected);
				*tableLogPtr = tableLog;
				/* determine last weight */
				{
					U32 total = (U32)1 << (int)tableLog;
					U32 rest = total - weightTotal;
					U32 verif = (U32)1 << (int)BitStream.BIT_highbit32(rest);
					U32 lastWeight = BitStream.BIT_highbit32(rest) + 1;
					if (verif != rest) return ERROR(Error.corruption_detected);    /* last value must be a clean power of 2 */
					huffWeight[oSize] = (BYTE)lastWeight;
					rankStats[lastWeight]++;
				}
			}

			/* check tree construction validity */
			if ((rankStats[1] < 2) || ((rankStats[1] & 1) != 0)) return ERROR(Error.corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */

			/* results */
			*nbSymbolsPtr = (U32)(oSize + 1);
			return iSize + 1;
		}