GZipDecompressor.cs 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. using System;
  2. using BestHTTP.Extensions;
  3. using BestHTTP.PlatformSupport.Memory;
  4. namespace BestHTTP.Decompression
  5. {
  6. public sealed class GZipDecompressor : IDecompressor
  7. {
  8. private BufferPoolMemoryStream decompressorInputStream;
  9. private BufferPoolMemoryStream decompressorOutputStream;
  10. private Zlib.GZipStream decompressorStream;
  11. private int MinLengthToDecompress = 256;
  12. public GZipDecompressor(int minLengthToDecompress)
  13. {
  14. this.MinLengthToDecompress = minLengthToDecompress;
  15. }
  16. private void CloseDecompressors()
  17. {
  18. if (decompressorStream != null)
  19. decompressorStream.Dispose();
  20. decompressorStream = null;
  21. if (decompressorInputStream != null)
  22. decompressorInputStream.Dispose();
  23. decompressorInputStream = null;
  24. if (decompressorOutputStream != null)
  25. decompressorOutputStream.Dispose();
  26. decompressorOutputStream = null;
  27. }
  28. public DecompressedData Decompress(byte[] data, int offset, int count, bool forceDecompress = false, bool dataCanBeLarger = false)
  29. {
  30. if (decompressorInputStream == null)
  31. decompressorInputStream = new BufferPoolMemoryStream(count);
  32. if (data != null)
  33. decompressorInputStream.Write(data, offset, count);
  34. if (!forceDecompress && decompressorInputStream.Length < MinLengthToDecompress)
  35. return new DecompressedData(null, 0);
  36. decompressorInputStream.Position = 0;
  37. if (decompressorStream == null)
  38. {
  39. decompressorStream = new Zlib.GZipStream(decompressorInputStream,
  40. Zlib.CompressionMode.Decompress,
  41. Zlib.CompressionLevel.Default,
  42. true);
  43. decompressorStream.FlushMode = Zlib.FlushType.Sync;
  44. }
  45. if (decompressorOutputStream == null)
  46. decompressorOutputStream = new BufferPoolMemoryStream();
  47. decompressorOutputStream.SetLength(0);
  48. byte[] copyBuffer = BufferPool.Get(1024, true);
  49. int readCount;
  50. int sumReadCount = 0;
  51. while ((readCount = decompressorStream.Read(copyBuffer, 0, copyBuffer.Length)) != 0)
  52. {
  53. decompressorOutputStream.Write(copyBuffer, 0, readCount);
  54. sumReadCount += readCount;
  55. }
  56. BufferPool.Release(copyBuffer);
  57. // If no read is done (returned with any data) don't zero out the input stream, as it would delete any not yet used data.
  58. if (sumReadCount > 0)
  59. decompressorStream.SetLength(0);
  60. byte[] result = decompressorOutputStream.ToArray(dataCanBeLarger);
  61. return new DecompressedData(result, dataCanBeLarger ? (int)decompressorOutputStream.Length : result.Length);
  62. }
  63. ~GZipDecompressor()
  64. {
  65. Dispose();
  66. }
  67. public void Dispose()
  68. {
  69. CloseDecompressors();
  70. GC.SuppressFinalize(this);
  71. }
  72. }
  73. }