diff --git a/project/Aki.Common/Utils/Zlib.cs b/project/Aki.Common/Utils/Zlib.cs
index c48c21d..1f3dcd2 100644
--- a/project/Aki.Common/Utils/Zlib.cs
+++ b/project/Aki.Common/Utils/Zlib.cs
@@ -1,127 +1,86 @@
-using System;
using System.IO;
using ComponentAce.Compression.Libs.zlib;
namespace Aki.Common.Utils
{
- public enum ZlibCompression
- {
- Store = 0,
- Fastest = 1,
- Fast = 3,
- Normal = 5,
- Ultra = 7,
- Maximum = 9
- }
+ public enum ZlibCompression
+ {
+ Store = 0,
+ Fastest = 1,
+ Fast = 3,
+ Normal = 5,
+ Ultra = 7,
+ Maximum = 9
+ }
- public static class Zlib
- {
- // Level | CM/CI FLG
- // ----- | ---------
- // 1 | 78 01
- // 2 | 78 5E
- // 3 | 78 5E
- // 4 | 78 5E
- // 5 | 78 5E
- // 6 | 78 9C
- // 7 | 78 DA
- // 8 | 78 DA
- // 9 | 78 DA
+ public static class Zlib
+ {
+ ///
+ /// Check if the file is ZLib compressed
+ ///
+ /// Data
+ /// If the file is Zlib compressed
+ public static bool IsCompressed(byte[] data)
+ {
+ if (data == null || data.Length < 3)
+ {
+ return false;
+ }
- ///
- /// Check if the file is ZLib compressed
- ///
- /// Data
- /// If the file is Zlib compressed
- public static bool IsCompressed(byte[] Data)
- {
- // We need the first two bytes;
- // First byte: Info (CM/CINFO) Header, should always be 0x78
- // Second byte: Flags (FLG) Header, should define our compression level.
+ // data[0]: Info (CM/CINFO) Header; must be 0x78
+ if (data[0] != 0x78)
+ {
+ return false;
+ }
- if (Data == null || Data.Length < 3 || Data[0] != 0x78)
- {
- return false;
- }
+ // data[1]: Flags (FLG) Header; compression level.
+ switch (data[1])
+ {
+ case 0x01: // [0x78 0x01] level 0-2: fastest
+ case 0x5E: // [0x78 0x5E] level 3-4: low
+ case 0x9C: // [0x78 0x9C] level 5-6: normal
+ case 0xDA: // [0x78 0xDA] level 7-9: max
+ return true;
+ }
- switch (Data[1])
- {
- case 0x01: // fastest
- case 0x5E: // low
- case 0x9C: // normal
- case 0xDA: // max
- return true;
- }
+ return false;
+ }
- return false;
- }
+ private static byte[] Run(byte[] data, ZlibCompression level)
+ {
+ // ZOutputStream.Close() flushes itself.
+ // ZOutputStream.Flush() flushes the target stream.
+ // It's fucking stupid, but whatever.
+ // -- Waffle.Lord, 2022-12-01
- ///
- /// Deflate data.
- ///
- public static byte[] Compress(byte[] data, ZlibCompression level)
- {
- byte[] buffer = new byte[data.Length + 24];
+ using (var ms = new MemoryStream())
+ {
+ using (var zs = (level > ZlibCompression.Store)
+ ? new ZOutputStream(ms, (int)level)
+ : new ZOutputStream(ms))
+ {
+ zs.Write(data, 0, data.Length);
+ }
+ // <-- zs flushes everything here
- ZStream zs = new ZStream()
- {
- avail_in = data.Length,
- next_in = data,
- next_in_index = 0,
- avail_out = buffer.Length,
- next_out = buffer,
- next_out_index = 0
- };
+ return ms.ToArray();
+ }
+ }
- zs.deflateInit((int)level);
- zs.deflate(zlibConst.Z_FINISH);
-
- data = new byte[zs.next_out_index];
- Array.Copy(zs.next_out, 0, data, 0, zs.next_out_index);
-
- return data;
- }
+ ///
+ /// Deflate data.
+ ///
+ public static byte[] Compress(byte[] data, ZlibCompression level)
+ {
+ return Run(data, level);
+ }
///
/// Inflate data.
///
public static byte[] Decompress(byte[] data)
- {
- byte[] buffer = new byte[4096];
-
- ZStream zs = new ZStream()
- {
- avail_in = data.Length,
- next_in = data,
- next_in_index = 0,
- avail_out = buffer.Length,
- next_out = buffer,
- next_out_index = 0
- };
-
- zs.inflateInit();
-
- using (MemoryStream ms = new MemoryStream())
- {
- do
- {
- zs.avail_out = buffer.Length;
- zs.next_out = buffer;
- zs.next_out_index = 0;
-
- int result = zs.inflate(0);
-
- if (result != 0 && result != 1)
- {
- break;
- }
-
- ms.Write(zs.next_out, 0, zs.next_out_index);
- }
- while (zs.avail_in > 0 || zs.avail_out == 0);
-
- return ms.ToArray();
- }
- }
- }
+ {
+ return Run(data, ZlibCompression.Store);
+ }
+ }
}
\ No newline at end of file