Пример #1
0
        public void UnCompressData()
        {
            uncompressedData = null;
            MemoryStream rawStream;

            if ((header.sectionFlags & SectionFlags.LZ4Compressed) == SectionFlags.LZ4Compressed)
            {
                rawStream = new MemoryStream();

                int outBuffLen = LZ4Decoder.LZ4_COMPRESSBOUND(LZ4_BLOCK_SIZE);
                var outBuffer0 = new byte[outBuffLen];
                var outBuffer1 = new byte[outBuffLen];

                fixed(void *pDiskBase = diskData)
                fixed(void *pOutBuff0 = outBuffer0)
                fixed(void *pOutBuff1 = outBuffer1)
                {
                    byte *pDiskData  = (byte *)pDiskBase;
                    byte *pOutBuffer = (byte *)pOutBuff0;

                    using (LZ4Decoder decoder = new LZ4Decoder())
                    {
                        int loopNo = 0;
                        while (true)
                        {
                            if ((pDiskData - (byte *)pDiskBase) >= diskData.Length)
                            {
                                break;
                            }

                            /*
                             * LZ4 continue 解压会使用上一次解压出的数据的作为下一次解压的字典并且保存数据指针,因此需要不停交换缓冲区
                             */
                            bool useBuff0 = loopNo % 2 == 0;
                            pOutBuffer = (byte *)(useBuff0 ? pOutBuff0 : pOutBuff1);

                            // rdc 文件中的压缩数据按page存储,每个page前4个字节存储长度, 由于对齐原因此长度有可能大于 decodedSize
                            int dataSize = *(int *)pDiskData; pDiskData += 4;
                            Debug.Assert(dataSize > 0 && dataSize < outBuffLen);

                            int decodedSize = decoder.LZ4_decompress_safe_continue(pDiskData, pOutBuffer, dataSize, LZ4_BLOCK_SIZE);
                            Debug.Assert(decodedSize > 0 && decodedSize <= outBuffLen);
                            pDiskData += dataSize;

                            rawStream.Write(useBuff0 ? outBuffer0 : outBuffer1, 0, decodedSize);
                            loopNo++;
                        }
                    }
                }

                uncompressedData = rawStream.ToArray();
                Debug.Assert(uncompressedData.Length == (int)header.sectionUncompressedLength);
            }
            else if ((header.sectionFlags & SectionFlags.ZstdCompressed) == SectionFlags.ZstdCompressed)
            {
                using (var decoder = new Decompressor())
                {
                    uncompressedData = decoder.Unwrap(diskData);
                }
            }
            else // raw data
            {
                uncompressedData = diskData;
            }
        }