Esempio n. 1
0
        /// <summary>
        /// Decompressed (inflates) a compressed byte array using the Inflate algorithm.
        /// </summary>
        /// <param name="compressedData">The deflate-compressed data</param>
        /// <param name="dictionary">The dictionary originally used to compress the data, or null if no dictionary was used.</param>
        /// <returns>The uncompressed data</returns>
        internal static byte[] ZlibDecompressWithDictionary(byte[] compressedData, byte[] dictionary)
        {
            using (var ms = new MemoryStream())
            {
                const int bufferSize = 256;
                var       buffer     = new byte[bufferSize];

                var codec = new ZlibCodec
                {
                    InputBuffer      = compressedData,
                    NextIn           = 0,
                    AvailableBytesIn = compressedData.Length
                };

                codec.AssertOk("InitializeInflate", codec.InitializeInflate(false));
                if (dictionary != null)
                {
                    codec.AssertOk("SetDictionary", codec.SetDictionaryUnconditionally(dictionary));
                }

                codec.OutputBuffer = buffer;

                while (true)
                {
                    codec.NextOut           = 0;
                    codec.AvailableBytesOut = bufferSize;
                    var inflateReturnCode = codec.Inflate(FlushType.None);
                    var bytesToWrite      = bufferSize - codec.AvailableBytesOut;
                    ms.Write(buffer, 0, bytesToWrite);

                    if (inflateReturnCode == ZlibConstants.Z_STREAM_END)
                    {
                        break;
                    }
                    else if (inflateReturnCode == ZlibConstants.Z_NEED_DICT && dictionary != null)
                    {
                        //implies bytesToWrite was 0
                        var dictionaryAdler32 = ((int)Adler.Adler32(1u, dictionary, 0, dictionary.Length));
                        if (codec.Adler32 != dictionaryAdler32)
                        {
                            throw new InvalidOperationException("Compressed data is requesting a dictionary with adler32 " + codec.Adler32 + ", but the dictionary is actually " + dictionaryAdler32);
                        }

                        codec.AssertOk("SetDictionary", codec.SetDictionary(dictionary));
                    }
                    else
                    {
                        codec.AssertOk("Inflate", inflateReturnCode);
                    }
                }

                codec.AssertOk("EndInflate", codec.EndInflate());
                return(ms.ToArray());
            }
        }