in csharp/src/ZStdDecompress.cs [421:499]
static size_t ZSTD_getFrameHeader_advanced(ref FrameHeader zfhPtr, void* src, size_t srcSize, ZSTD_format_e format)
{
BYTE* ip = (BYTE*)src;
size_t minInputSize = StartingInputLength(format);
if (srcSize < minInputSize) return minInputSize;
if ((format != ZSTD_format_e.ZSTD_f_zstd1_magicless)
&& (MEM_readLE32(src) != ZSTD_MAGICNUMBER))
{
if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START)
{
/* skippable frame */
if (srcSize < ZSTD_skippableHeaderSize)
return ZSTD_skippableHeaderSize; /* magic number + frame length */
zfhPtr.Reset();
zfhPtr.frameContentSize = MEM_readLE32((sbyte*)src + ZSTD_frameIdSize);
zfhPtr.frameType = ZSTD_frameType_e.ZSTD_skippableFrame;
return 0;
}
return ERROR(Error.prefix_unknown);
}
/* ensure there is enough `srcSize` to fully read/decode frame header */
{
size_t fhsize = ZSTD_frameHeaderSize_internal(src, srcSize, format);
if (srcSize < fhsize) return fhsize;
zfhPtr.headerSize = (U32)fhsize;
}
{
U32 fhdByte = ip[minInputSize - 1];
size_t pos = minInputSize;
U32 dictIDSizeCode = fhdByte & 3;
U32 checksumFlag = (fhdByte >> 2) & 1;
U32 singleSegment = (fhdByte >> 5) & 1;
U32 fcsID = fhdByte >> 6;
U64 windowSize = 0;
U32 dictID = 0;
U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
if ((fhdByte & 0x08) != 0)
return ERROR(Error.frameParameter_unsupported); /* reserved bits, must be zero */
if (singleSegment == 0)
{
U32 wlByte = ip[pos++];
U32 windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
if (windowLog > ZSTD_WINDOWLOG_MAX)
return ERROR(Error.frameParameter_windowTooLarge);
windowSize = ((ulong)1 << (int)windowLog);
windowSize += (windowSize >> 3) * (wlByte & 7);
}
switch (dictIDSizeCode)
{
default: throw new InvalidOperationException(); /* impossible */
case 0: break;
case 1: dictID = ip[pos]; pos++; break;
case 2: dictID = MEM_readLE16(ip + pos); pos += 2; break;
case 3: dictID = MEM_readLE32(ip + pos); pos += 4; break;
}
switch (fcsID)
{
default: throw new InvalidOperationException(); /* impossible */
case 0: if (singleSegment != 0) frameContentSize = ip[pos]; break;
case 1: frameContentSize = MEM_readLE16(ip + pos) + 256; break;
case 2: frameContentSize = MEM_readLE32(ip + pos); break;
case 3: frameContentSize = MEM_readLE64(ip + pos); break;
}
if (singleSegment != 0) windowSize = frameContentSize;
zfhPtr.frameType = ZSTD_frameType_e.ZSTD_frame;
zfhPtr.frameContentSize = frameContentSize;
zfhPtr.windowSize = windowSize;
zfhPtr.blockSizeMax = (uint)Math.Min(windowSize, ZSTD_BLOCKSIZE_MAX);
zfhPtr.dictID = dictID;
zfhPtr.checksumFlag = checksumFlag;
}
return 0;
}