static size_t ZSTD_getFrameHeader_advanced()

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;
		}